1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gtkcontainer.h"
30 #include "gtkiconfactory.h"
35 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
37 static void gtk_image_class_init (GtkImageClass *klass);
38 static void gtk_image_init (GtkImage *image);
39 static gint gtk_image_expose (GtkWidget *widget,
40 GdkEventExpose *event);
41 static void gtk_image_unmap (GtkWidget *widget);
42 static void gtk_image_unrealize (GtkWidget *widget);
43 static void gtk_image_size_request (GtkWidget *widget,
44 GtkRequisition *requisition);
45 static void gtk_image_destroy (GtkObject *object);
46 static void gtk_image_clear (GtkImage *image);
47 static void gtk_image_reset (GtkImage *image);
48 static void gtk_image_calc_size (GtkImage *image);
50 static void gtk_image_update_size (GtkImage *image,
54 static void gtk_image_set_property (GObject *object,
58 static void gtk_image_get_property (GObject *object,
63 static gpointer parent_class;
76 PROP_PIXBUF_ANIMATION,
81 gtk_image_get_type (void)
83 static GType image_type = 0;
87 static const GTypeInfo image_info =
89 sizeof (GtkImageClass),
91 NULL, /* base_finalize */
92 (GClassInitFunc) gtk_image_class_init,
93 NULL, /* class_finalize */
94 NULL, /* class_data */
97 (GInstanceInitFunc) gtk_image_init,
100 image_type = g_type_register_static (GTK_TYPE_MISC, "GtkImage",
108 gtk_image_class_init (GtkImageClass *class)
110 GObjectClass *gobject_class;
111 GtkObjectClass *object_class;
112 GtkWidgetClass *widget_class;
114 parent_class = g_type_class_peek_parent (class);
116 gobject_class = G_OBJECT_CLASS (class);
118 gobject_class->set_property = gtk_image_set_property;
119 gobject_class->get_property = gtk_image_get_property;
121 object_class = GTK_OBJECT_CLASS (class);
123 object_class->destroy = gtk_image_destroy;
125 widget_class = GTK_WIDGET_CLASS (class);
127 widget_class->expose_event = gtk_image_expose;
128 widget_class->size_request = gtk_image_size_request;
129 widget_class->unmap = gtk_image_unmap;
130 widget_class->unrealize = gtk_image_unrealize;
132 g_object_class_install_property (gobject_class,
134 g_param_spec_object ("pixbuf",
136 _("A GdkPixbuf to display"),
140 g_object_class_install_property (gobject_class,
142 g_param_spec_object ("pixmap",
144 _("A GdkPixmap to display"),
148 g_object_class_install_property (gobject_class,
150 g_param_spec_object ("image",
152 _("A GdkImage to display"),
156 g_object_class_install_property (gobject_class,
158 g_param_spec_object ("mask",
160 _("Mask bitmap to use with GdkImage or GdkPixmap"),
164 g_object_class_install_property (gobject_class,
166 g_param_spec_string ("file",
168 _("Filename to load and display"),
173 g_object_class_install_property (gobject_class,
175 g_param_spec_string ("stock",
177 _("Stock ID for a stock image to display"),
181 g_object_class_install_property (gobject_class,
183 g_param_spec_boxed ("icon_set",
185 _("Icon set to display"),
189 g_object_class_install_property (gobject_class,
191 g_param_spec_int ("icon_size",
193 _("Size to use for stock icon or icon set"),
198 g_object_class_install_property (gobject_class,
199 PROP_PIXBUF_ANIMATION,
200 g_param_spec_object ("pixbuf_animation",
202 _("GdkPixbufAnimation to display"),
203 GDK_TYPE_PIXBUF_ANIMATION,
206 g_object_class_install_property (gobject_class,
208 g_param_spec_enum ("storage_type",
210 _("The representation being used for image data"),
217 gtk_image_init (GtkImage *image)
219 GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
221 image->storage_type = GTK_IMAGE_EMPTY;
222 image->icon_size = DEFAULT_ICON_SIZE;
227 gtk_image_destroy (GtkObject *object)
229 GtkImage *image = GTK_IMAGE (object);
231 gtk_image_clear (image);
233 GTK_OBJECT_CLASS (parent_class)->destroy (object);
237 gtk_image_set_property (GObject *object,
244 image = GTK_IMAGE (object);
249 gtk_image_set_from_pixbuf (image,
250 g_value_get_object (value));
253 gtk_image_set_from_pixmap (image,
254 g_value_get_object (value),
258 gtk_image_set_from_image (image,
259 g_value_get_object (value),
263 if (image->storage_type == GTK_IMAGE_PIXMAP)
264 gtk_image_set_from_pixmap (image,
265 image->data.pixmap.pixmap,
266 g_value_get_object (value));
267 else if (image->storage_type == GTK_IMAGE_IMAGE)
268 gtk_image_set_from_image (image,
269 image->data.image.image,
270 g_value_get_object (value));
275 mask = g_value_get_object (value);
280 gtk_image_reset (image);
286 gtk_image_set_from_file (image,
287 g_value_get_string (value));
290 gtk_image_set_from_stock (image, g_value_get_string (value),
294 gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
298 if (image->storage_type == GTK_IMAGE_STOCK)
299 gtk_image_set_from_stock (image,
300 image->data.stock.stock_id,
301 g_value_get_int (value));
302 else if (image->storage_type == GTK_IMAGE_ICON_SET)
303 gtk_image_set_from_icon_set (image,
304 image->data.icon_set.icon_set,
305 g_value_get_int (value));
307 /* Save to be used when STOCK or ICON_SET property comes in */
308 image->icon_size = g_value_get_int (value);
310 case PROP_PIXBUF_ANIMATION:
311 gtk_image_set_from_animation (image,
312 g_value_get_object (value));
316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
322 gtk_image_get_property (GObject *object,
329 image = GTK_IMAGE (object);
331 /* The "getter" functions whine if you try to get the wrong
332 * storage type. This function is instead robust against that,
333 * so that GUI builders don't have to jump through hoops
340 if (image->storage_type != GTK_IMAGE_PIXBUF)
341 g_value_set_object (value, NULL);
343 g_value_set_object (value,
344 gtk_image_get_pixbuf (image));
347 if (image->storage_type != GTK_IMAGE_PIXMAP)
348 g_value_set_object (value, NULL);
350 g_value_set_object (value,
351 image->data.pixmap.pixmap);
354 g_value_set_object (value, image->mask);
357 if (image->storage_type != GTK_IMAGE_IMAGE)
358 g_value_set_object (value, NULL);
360 g_value_set_object (value,
361 image->data.image.image);
364 if (image->storage_type != GTK_IMAGE_STOCK)
365 g_value_set_string (value, NULL);
367 g_value_set_string (value,
368 image->data.stock.stock_id);
371 if (image->storage_type != GTK_IMAGE_ICON_SET)
372 g_value_set_boxed (value, NULL);
374 g_value_set_boxed (value,
375 image->data.icon_set.icon_set);
378 g_value_set_int (value, image->icon_size);
380 case PROP_PIXBUF_ANIMATION:
381 if (image->storage_type != GTK_IMAGE_ANIMATION)
382 g_value_set_object (value, NULL);
384 g_value_set_object (value,
385 image->data.anim.anim);
387 case PROP_STORAGE_TYPE:
388 g_value_set_enum (value, image->storage_type);
392 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
399 * gtk_image_new_from_pixmap:
400 * @pixmap: a #GdkPixmap, or %NULL
401 * @mask: a #GdkBitmap, or %NULL
403 * Creates a #GtkImage widget displaying @pixmap with a @mask.
404 * A #GdkImage is a server-side image buffer in the pixel format of the
405 * current display. The #GtkImage does not assume a reference to the
406 * pixmap or mask; you still need to unref them if you own references.
407 * #GtkImage will add its own reference rather than adopting yours.
409 * Return value: a new #GtkImage
412 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
417 image = g_object_new (GTK_TYPE_IMAGE, NULL);
419 gtk_image_set_from_pixmap (image, pixmap, mask);
421 return GTK_WIDGET (image);
425 * gtk_image_new_from_image:
426 * @image: a #GdkImage, or %NULL
427 * @mask: a #GdkBitmap, or %NULL
429 * Creates a #GtkImage widget displaying a @image with a @mask.
430 * A #GdkImage is a client-side image buffer in the pixel format of the
432 * The #GtkImage does not assume a reference to the
433 * image or mask; you still need to unref them if you own references.
434 * #GtkImage will add its own reference rather than adopting yours.
436 * Return value: a new #GtkImage
439 gtk_image_new_from_image (GdkImage *gdk_image,
444 image = g_object_new (GTK_TYPE_IMAGE, NULL);
446 gtk_image_set_from_image (image, gdk_image, mask);
448 return GTK_WIDGET (image);
452 * gtk_image_new_from_file:
453 * @filename: a filename
455 * Creates a new #GtkImage displaying the file @filename. If the file
456 * isn't found or can't be loaded, the resulting #GtkImage will
457 * display a "broken image" icon. This function never returns %NULL,
458 * it always returns a valid #GtkImage widget.
460 * If the file contains an animation, the image will contain an
463 * If you need to detect failures to load the file, use
464 * gdk_pixbuf_new_from_file() to load the file yourself, then create
465 * the #GtkImage from the pixbuf. (Or for animations, use
466 * gdk_pixbuf_animation_new_from_file()).
468 * The storage type (gtk_image_get_storage_type()) of the returned
469 * image is not defined, it will be whatever is appropriate for
470 * displaying the file.
472 * Return value: a new #GtkImage
475 gtk_image_new_from_file (const gchar *filename)
479 image = g_object_new (GTK_TYPE_IMAGE, NULL);
481 gtk_image_set_from_file (image, filename);
483 return GTK_WIDGET (image);
487 * gtk_image_new_from_pixbuf:
488 * @pixbuf: a #GdkPixbuf, or %NULL
490 * Creates a new #GtkImage displaying @pixbuf.
491 * The #GtkImage does not assume a reference to the
492 * pixbuf; you still need to unref it if you own references.
493 * #GtkImage will add its own reference rather than adopting yours.
495 * Note that this function just creates an #GtkImage from the pixbuf. The
496 * #GtkImage created will not react to state changes. Should you want that, you
497 * should use gtk_image_new_from_icon_set().
499 * Return value: a new #GtkImage
502 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
506 image = g_object_new (GTK_TYPE_IMAGE, NULL);
508 gtk_image_set_from_pixbuf (image, pixbuf);
510 return GTK_WIDGET (image);
514 * gtk_image_new_from_stock:
515 * @stock_id: a stock icon name
516 * @size: a stock icon size
518 * Creates a #GtkImage displaying a stock icon. Sample stock icon
519 * names are #GTK_STOCK_OPEN, #GTK_STOCK_EXIT. Sample stock sizes
520 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
521 * icon name isn't known, a "broken image" icon will be displayed instead.
522 * You can register your own stock icon names, see
523 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
525 * Return value: a new #GtkImage displaying the stock icon
528 gtk_image_new_from_stock (const gchar *stock_id,
533 image = g_object_new (GTK_TYPE_IMAGE, NULL);
535 gtk_image_set_from_stock (image, stock_id, size);
537 return GTK_WIDGET (image);
541 * gtk_image_new_from_icon_set:
542 * @icon_set: a #GtkIconSet
543 * @size: a stock icon size
545 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
546 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
547 * this function, usually it's better to create a #GtkIconFactory, put
548 * your icon sets in the icon factory, add the icon factory to the
549 * list of default factories with gtk_icon_factory_add_default(), and
550 * then use gtk_image_new_from_stock(). This will allow themes to
551 * override the icon you ship with your application.
553 * The #GtkImage does not assume a reference to the
554 * icon set; you still need to unref it if you own references.
555 * #GtkImage will add its own reference rather than adopting yours.
558 * Return value: a new #GtkImage
561 gtk_image_new_from_icon_set (GtkIconSet *icon_set,
566 image = g_object_new (GTK_TYPE_IMAGE, NULL);
568 gtk_image_set_from_icon_set (image, icon_set, size);
570 return GTK_WIDGET (image);
574 * gtk_image_new_from_animation:
575 * @animation: an animation
577 * Creates a #GtkImage displaying the given animation.
578 * The #GtkImage does not assume a reference to the
579 * animation; you still need to unref it if you own references.
580 * #GtkImage will add its own reference rather than adopting yours.
582 * Return value: a new #GtkImage widget
585 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
589 g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
591 image = g_object_new (GTK_TYPE_IMAGE, NULL);
593 gtk_image_set_from_animation (image, animation);
595 return GTK_WIDGET (image);
599 * gtk_image_set_from_pixmap:
600 * @image: a #GtkImage
601 * @pixmap: a #GdkPixmap or %NULL
602 * @mask: a #GdkBitmap or %NULL
604 * See gtk_image_new_from_pixmap() for details.
608 gtk_image_set_from_pixmap (GtkImage *image,
612 g_return_if_fail (GTK_IS_IMAGE (image));
613 g_return_if_fail (pixmap == NULL ||
614 GDK_IS_PIXMAP (pixmap));
615 g_return_if_fail (mask == NULL ||
616 GDK_IS_PIXMAP (mask));
618 g_object_freeze_notify (G_OBJECT (image));
621 g_object_ref (pixmap);
626 gtk_image_reset (image);
635 image->storage_type = GTK_IMAGE_PIXMAP;
637 image->data.pixmap.pixmap = pixmap;
639 gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
641 gtk_image_update_size (image, width, height);
644 g_object_notify (G_OBJECT (image), "pixmap");
645 g_object_notify (G_OBJECT (image), "mask");
647 g_object_thaw_notify (G_OBJECT (image));
651 * gtk_image_set_from_image:
652 * @image: a #GtkImage
653 * @gdk_image: a #GdkImage or %NULL
654 * @mask: a #GdkBitmap or %NULL
656 * See gtk_image_new_from_image() for details.
660 gtk_image_set_from_image (GtkImage *image,
664 g_return_if_fail (GTK_IS_IMAGE (image));
665 g_return_if_fail (gdk_image == NULL ||
666 GDK_IS_IMAGE (gdk_image));
667 g_return_if_fail (mask == NULL ||
668 GDK_IS_PIXMAP (mask));
670 g_object_freeze_notify (G_OBJECT (image));
673 g_object_ref (gdk_image);
678 gtk_image_reset (image);
682 image->storage_type = GTK_IMAGE_IMAGE;
684 image->data.image.image = gdk_image;
687 gtk_image_update_size (image, gdk_image->width, gdk_image->height);
691 /* Clean up the mask if gdk_image was NULL */
693 g_object_unref (mask);
696 g_object_notify (G_OBJECT (image), "image");
697 g_object_notify (G_OBJECT (image), "mask");
699 g_object_thaw_notify (G_OBJECT (image));
703 * gtk_image_set_from_file:
704 * @image: a #GtkImage
705 * @filename: a filename or %NULL
707 * See gtk_image_new_from_file() for details.
711 gtk_image_set_from_file (GtkImage *image,
712 const gchar *filename)
714 GdkPixbufAnimation *anim;
716 g_return_if_fail (GTK_IS_IMAGE (image));
718 g_object_freeze_notify (G_OBJECT (image));
720 gtk_image_reset (image);
722 if (filename == NULL)
724 g_object_thaw_notify (G_OBJECT (image));
728 anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
732 gtk_image_set_from_stock (image,
733 GTK_STOCK_MISSING_IMAGE,
734 GTK_ICON_SIZE_BUTTON);
735 g_object_thaw_notify (G_OBJECT (image));
739 /* We could just unconditionally set_from_animation,
740 * but it's nicer for memory if we toss the animation
741 * if it's just a single pixbuf
744 if (gdk_pixbuf_animation_is_static_image (anim))
746 gtk_image_set_from_pixbuf (image,
747 gdk_pixbuf_animation_get_static_image (anim));
751 gtk_image_set_from_animation (image, anim);
754 g_object_unref (anim);
756 g_object_thaw_notify (G_OBJECT (image));
760 * gtk_image_set_from_pixbuf:
761 * @image: a #GtkImage
762 * @pixbuf: a #GdkPixbuf or %NULL
764 * See gtk_image_new_from_pixbuf() for details.
768 gtk_image_set_from_pixbuf (GtkImage *image,
771 g_return_if_fail (GTK_IS_IMAGE (image));
772 g_return_if_fail (pixbuf == NULL ||
773 GDK_IS_PIXBUF (pixbuf));
775 g_object_freeze_notify (G_OBJECT (image));
778 g_object_ref (pixbuf);
780 gtk_image_reset (image);
784 image->storage_type = GTK_IMAGE_PIXBUF;
786 image->data.pixbuf.pixbuf = pixbuf;
788 gtk_image_update_size (image,
789 gdk_pixbuf_get_width (pixbuf),
790 gdk_pixbuf_get_height (pixbuf));
793 g_object_notify (G_OBJECT (image), "pixbuf");
795 g_object_thaw_notify (G_OBJECT (image));
799 * gtk_image_set_from_stock:
800 * @image: a #GtkImage
801 * @stock_id: a stock icon name
802 * @size: a stock icon size
804 * See gtk_image_new_from_stock() for details.
808 gtk_image_set_from_stock (GtkImage *image,
809 const gchar *stock_id,
814 g_return_if_fail (GTK_IS_IMAGE (image));
816 g_object_freeze_notify (G_OBJECT (image));
818 /* in case stock_id == image->data.stock.stock_id */
819 new_id = g_strdup (stock_id);
821 gtk_image_reset (image);
825 image->storage_type = GTK_IMAGE_STOCK;
827 image->data.stock.stock_id = new_id;
828 image->icon_size = size;
830 /* Size is demand-computed in size request method
831 * if we're a stock image, since changing the
832 * style impacts the size request
836 g_object_notify (G_OBJECT (image), "stock");
837 g_object_notify (G_OBJECT (image), "icon_size");
839 g_object_thaw_notify (G_OBJECT (image));
843 * gtk_image_set_from_icon_set:
844 * @image: a #GtkImage
845 * @icon_set: a #GtkIconSet
846 * @size: a stock icon size
848 * See gtk_image_new_from_icon_set() for details.
852 gtk_image_set_from_icon_set (GtkImage *image,
853 GtkIconSet *icon_set,
856 g_return_if_fail (GTK_IS_IMAGE (image));
858 g_object_freeze_notify (G_OBJECT (image));
861 gtk_icon_set_ref (icon_set);
863 gtk_image_reset (image);
867 image->storage_type = GTK_IMAGE_ICON_SET;
869 image->data.icon_set.icon_set = icon_set;
870 image->icon_size = size;
872 /* Size is demand-computed in size request method
873 * if we're an icon set
877 g_object_notify (G_OBJECT (image), "icon_set");
878 g_object_notify (G_OBJECT (image), "icon_size");
880 g_object_thaw_notify (G_OBJECT (image));
884 * gtk_image_set_from_animation:
885 * @image: a #GtkImage
886 * @animation: the #GdkPixbufAnimation
888 * Causes the #GtkImage to display the given animation (or display
889 * nothing, if you set the animation to %NULL).
892 gtk_image_set_from_animation (GtkImage *image,
893 GdkPixbufAnimation *animation)
895 g_return_if_fail (GTK_IS_IMAGE (image));
896 g_return_if_fail (animation == NULL ||
897 GDK_IS_PIXBUF_ANIMATION (animation));
899 g_object_freeze_notify (G_OBJECT (image));
902 g_object_ref (animation);
904 gtk_image_reset (image);
906 if (animation != NULL)
908 image->storage_type = GTK_IMAGE_ANIMATION;
910 image->data.anim.anim = animation;
911 image->data.anim.frame_timeout = 0;
912 image->data.anim.iter = NULL;
914 gtk_image_update_size (image,
915 gdk_pixbuf_animation_get_width (animation),
916 gdk_pixbuf_animation_get_height (animation));
919 g_object_notify (G_OBJECT (image), "pixbuf_animation");
921 g_object_thaw_notify (G_OBJECT (image));
925 * gtk_image_get_storage_type:
926 * @image: a #GtkImage
928 * Gets the type of representation being used by the #GtkImage
929 * to store image data. If the #GtkImage has no image data,
930 * the return value will be %GTK_IMAGE_EMPTY.
932 * Return value: image representation being used
935 gtk_image_get_storage_type (GtkImage *image)
937 g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
939 return image->storage_type;
943 * gtk_image_get_pixmap:
944 * @image: a #GtkImage
945 * @pixmap: location to store the pixmap, or %NULL
946 * @mask: location to store the mask, or %NULL
948 * Gets the pixmap and mask being displayed by the #GtkImage.
949 * The storage type of the image must be %GTK_IMAGE_EMPTY or
950 * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
951 * The caller of this function does not own a reference to the
952 * returned pixmap and mask.
956 gtk_image_get_pixmap (GtkImage *image,
960 g_return_if_fail (GTK_IS_IMAGE (image));
961 g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
962 image->storage_type == GTK_IMAGE_EMPTY);
965 *pixmap = image->data.pixmap.pixmap;
972 * gtk_image_get_image:
973 * @image: a #GtkImage
974 * @gdk_image: return location for a #GtkImage
975 * @mask: return location for a #GdkBitmap
977 * Gets the #GdkImage and mask being displayed by the #GtkImage.
978 * The storage type of the image must be %GTK_IMAGE_EMPTY or
979 * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
980 * The caller of this function does not own a reference to the
981 * returned image and mask.
984 gtk_image_get_image (GtkImage *image,
985 GdkImage **gdk_image,
988 g_return_if_fail (GTK_IS_IMAGE (image));
989 g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
990 image->storage_type == GTK_IMAGE_EMPTY);
993 *gdk_image = image->data.image.image;
1000 * gtk_image_get_pixbuf:
1001 * @image: a #GtkImage
1004 * Gets the #GdkPixbuf being displayed by the #GtkImage.
1005 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1006 * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1007 * The caller of this function does not own a reference to the
1010 * Return value: the displayed pixbuf, or %NULL if the image is empty
1013 gtk_image_get_pixbuf (GtkImage *image)
1015 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1016 g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
1017 image->storage_type == GTK_IMAGE_EMPTY, NULL);
1019 if (image->storage_type == GTK_IMAGE_EMPTY)
1020 image->data.pixbuf.pixbuf = NULL;
1022 return image->data.pixbuf.pixbuf;
1026 * gtk_image_get_stock:
1027 * @image: a #GtkImage
1028 * @stock_id: place to store a stock icon name
1029 * @size: place to store a stock icon size
1031 * Gets the stock icon name and size being displayed by the #GtkImage.
1032 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1033 * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1034 * The returned string is owned by the #GtkImage and should not
1039 gtk_image_get_stock (GtkImage *image,
1043 g_return_if_fail (GTK_IS_IMAGE (image));
1044 g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
1045 image->storage_type == GTK_IMAGE_EMPTY);
1047 if (image->storage_type == GTK_IMAGE_EMPTY)
1048 image->data.stock.stock_id = NULL;
1051 *stock_id = image->data.stock.stock_id;
1054 *size = image->icon_size;
1058 * gtk_image_get_icon_set:
1059 * @image: a #GtkImage
1060 * @icon_set: location to store a #GtkIconSet
1061 * @size: location to store a stock icon size
1063 * Gets the icon set and size being displayed by the #GtkImage.
1064 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1065 * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1069 gtk_image_get_icon_set (GtkImage *image,
1070 GtkIconSet **icon_set,
1073 g_return_if_fail (GTK_IS_IMAGE (image));
1074 g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
1075 image->storage_type == GTK_IMAGE_EMPTY);
1078 *icon_set = image->data.icon_set.icon_set;
1081 *size = image->icon_size;
1085 * gtk_image_get_animation:
1086 * @image: a #GtkImage
1089 * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1090 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1091 * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1092 * The caller of this function does not own a reference to the
1093 * returned animation.
1095 * Return value: the displayed animation, or %NULL if the image is empty
1098 gtk_image_get_animation (GtkImage *image)
1100 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1101 g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
1102 image->storage_type == GTK_IMAGE_EMPTY,
1105 if (image->storage_type == GTK_IMAGE_EMPTY)
1106 image->data.anim.anim = NULL;
1108 return image->data.anim.anim;
1114 * Creates a new empty #GtkImage widget.
1116 * Return value: a newly created #GtkImage widget.
1119 gtk_image_new (void)
1121 return g_object_new (GTK_TYPE_IMAGE, NULL);
1125 gtk_image_set (GtkImage *image,
1129 g_return_if_fail (GTK_IS_IMAGE (image));
1131 gtk_image_set_from_image (image, val, mask);
1135 gtk_image_get (GtkImage *image,
1139 g_return_if_fail (GTK_IS_IMAGE (image));
1141 gtk_image_get_image (image, val, mask);
1145 gtk_image_reset_anim_iter (GtkImage *image)
1147 if (image->storage_type == GTK_IMAGE_ANIMATION)
1149 /* Reset the animation */
1151 if (image->data.anim.frame_timeout)
1153 g_source_remove (image->data.anim.frame_timeout);
1154 image->data.anim.frame_timeout = 0;
1157 if (image->data.anim.iter)
1159 g_object_unref (image->data.anim.iter);
1160 image->data.anim.iter = NULL;
1166 gtk_image_unmap (GtkWidget *widget)
1168 gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1170 if (GTK_WIDGET_CLASS (parent_class)->unmap)
1171 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1175 gtk_image_unrealize (GtkWidget *widget)
1177 gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1179 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1180 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
1184 animation_timeout (gpointer data)
1188 GDK_THREADS_ENTER ();
1190 image = GTK_IMAGE (data);
1192 image->data.anim.frame_timeout = 0;
1194 gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);
1196 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1197 image->data.anim.frame_timeout =
1198 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1202 gtk_widget_queue_draw (GTK_WIDGET (image));
1204 GDK_THREADS_LEAVE ();
1210 gtk_image_expose (GtkWidget *widget,
1211 GdkEventExpose *event)
1213 g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1214 g_return_val_if_fail (event != NULL, FALSE);
1216 if (GTK_WIDGET_MAPPED (widget) &&
1217 GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
1221 GdkRectangle area, image_bound;
1226 gboolean needs_state_transform;
1228 image = GTK_IMAGE (widget);
1229 misc = GTK_MISC (widget);
1233 /* For stock items and icon sets, we lazily calculate
1234 * the size; we might get here between a queue_resize()
1235 * and size_request() if something explicitely forces
1238 if (widget->requisition.width == 0 && widget->requisition.height == 0)
1239 gtk_image_calc_size (image);
1241 if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
1244 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1245 xalign = misc->xalign;
1247 xalign = 1.0 - misc->xalign;
1249 x = floor (widget->allocation.x + misc->xpad
1250 + ((widget->allocation.width - widget->requisition.width) * xalign)
1252 y = floor (widget->allocation.y + misc->ypad
1253 + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1258 image_bound.width = 0;
1259 image_bound.height = 0;
1263 needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
1265 switch (image->storage_type)
1267 case GTK_IMAGE_PIXMAP:
1269 gdk_drawable_get_size (image->data.pixmap.pixmap,
1271 &image_bound.height);
1273 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1274 needs_state_transform)
1276 pixbuf = gdk_pixbuf_get_from_drawable (NULL,
1277 image->data.pixmap.pixmap,
1278 gtk_widget_get_colormap (widget),
1279 image_bound.x - x, image_bound.y - y,
1282 image_bound.height);
1290 case GTK_IMAGE_IMAGE:
1292 image_bound.width = image->data.image.image->width;
1293 image_bound.height = image->data.image.image->height;
1295 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1296 needs_state_transform)
1298 pixbuf = gdk_pixbuf_get_from_image (NULL,
1299 image->data.image.image,
1300 gtk_widget_get_colormap (widget),
1301 image_bound.x - x, image_bound.y - y,
1304 image_bound.height);
1311 case GTK_IMAGE_PIXBUF:
1312 image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
1313 image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);
1315 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1316 needs_state_transform)
1318 pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf,
1319 image_bound.x - x, image_bound.y - y,
1320 image_bound.width, image_bound.height);
1327 pixbuf = image->data.pixbuf.pixbuf;
1328 g_object_ref (pixbuf);
1332 case GTK_IMAGE_STOCK:
1333 pixbuf = gtk_widget_render_icon (widget,
1334 image->data.stock.stock_id,
1339 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1340 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1344 needs_state_transform = FALSE;
1347 case GTK_IMAGE_ICON_SET:
1349 gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1351 gtk_widget_get_direction (widget),
1352 GTK_WIDGET_STATE (widget),
1359 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1360 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1364 needs_state_transform = FALSE;
1367 case GTK_IMAGE_ANIMATION:
1369 if (image->data.anim.iter == NULL)
1371 image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL);
1373 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1374 image->data.anim.frame_timeout =
1375 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1380 image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim);
1381 image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim);
1383 /* don't advance the anim iter here, or we could get frame changes between two
1384 * exposes of different areas.
1387 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter);
1388 g_object_ref (pixbuf);
1392 case GTK_IMAGE_EMPTY:
1393 g_assert_not_reached ();
1399 gdk_gc_set_clip_mask (widget->style->black_gc, mask);
1400 gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
1403 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound))
1407 if (needs_state_transform)
1409 GtkIconSource *source;
1410 GdkPixbuf *rendered;
1412 source = gtk_icon_source_new ();
1413 gtk_icon_source_set_pixbuf (source, pixbuf);
1414 /* The size here is arbitrary; since size isn't
1415 * wildcarded in the souce, it isn't supposed to be
1416 * scaled by the engine function
1418 gtk_icon_source_set_size (source,
1419 GTK_ICON_SIZE_SMALL_TOOLBAR);
1420 gtk_icon_source_set_size_wildcarded (source, FALSE);
1422 rendered = gtk_style_render_icon (widget->style,
1424 gtk_widget_get_direction (widget),
1425 GTK_WIDGET_STATE (widget),
1431 gtk_icon_source_free (source);
1433 g_object_unref (pixbuf);
1439 gdk_draw_pixbuf (widget->window,
1440 widget->style->black_gc,
1448 GDK_RGB_DITHER_NORMAL,
1451 g_object_unref (pixbuf);
1457 switch (image->storage_type)
1459 case GTK_IMAGE_PIXMAP:
1460 gdk_draw_drawable (widget->window,
1461 widget->style->black_gc,
1462 image->data.pixmap.pixmap,
1463 image_bound.x - x, image_bound.y - y,
1464 image_bound.x, image_bound.y,
1465 image_bound.width, image_bound.height);
1468 case GTK_IMAGE_IMAGE:
1469 gdk_draw_image (widget->window,
1470 widget->style->black_gc,
1471 image->data.image.image,
1472 image_bound.x - x, image_bound.y - y,
1473 image_bound.x, image_bound.y,
1474 image_bound.width, image_bound.height);
1477 case GTK_IMAGE_PIXBUF:
1478 case GTK_IMAGE_STOCK:
1479 case GTK_IMAGE_ICON_SET:
1480 case GTK_IMAGE_ANIMATION:
1481 case GTK_IMAGE_EMPTY:
1482 g_assert_not_reached ();
1486 } /* if rectangle intersects */
1490 gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
1491 gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
1494 } /* if widget is drawable */
1500 gtk_image_clear (GtkImage *image)
1502 g_object_freeze_notify (G_OBJECT (image));
1504 if (image->storage_type != GTK_IMAGE_EMPTY)
1505 g_object_notify (G_OBJECT (image), "storage_type");
1509 g_object_unref (image->mask);
1511 g_object_notify (G_OBJECT (image), "mask");
1514 if (image->icon_size != DEFAULT_ICON_SIZE)
1516 image->icon_size = DEFAULT_ICON_SIZE;
1517 g_object_notify (G_OBJECT (image), "icon_size");
1520 switch (image->storage_type)
1522 case GTK_IMAGE_PIXMAP:
1524 if (image->data.pixmap.pixmap)
1525 g_object_unref (image->data.pixmap.pixmap);
1526 image->data.pixmap.pixmap = NULL;
1528 g_object_notify (G_OBJECT (image), "pixmap");
1532 case GTK_IMAGE_IMAGE:
1534 if (image->data.image.image)
1535 g_object_unref (image->data.image.image);
1536 image->data.image.image = NULL;
1538 g_object_notify (G_OBJECT (image), "image");
1542 case GTK_IMAGE_PIXBUF:
1544 if (image->data.pixbuf.pixbuf)
1545 g_object_unref (image->data.pixbuf.pixbuf);
1547 g_object_notify (G_OBJECT (image), "pixbuf");
1551 case GTK_IMAGE_STOCK:
1553 g_free (image->data.stock.stock_id);
1555 image->data.stock.stock_id = NULL;
1557 g_object_notify (G_OBJECT (image), "stock");
1560 case GTK_IMAGE_ICON_SET:
1561 if (image->data.icon_set.icon_set)
1562 gtk_icon_set_unref (image->data.icon_set.icon_set);
1563 image->data.icon_set.icon_set = NULL;
1565 g_object_notify (G_OBJECT (image), "icon_set");
1568 case GTK_IMAGE_ANIMATION:
1569 if (image->data.anim.frame_timeout)
1570 g_source_remove (image->data.anim.frame_timeout);
1572 if (image->data.anim.anim)
1573 g_object_unref (image->data.anim.anim);
1575 image->data.anim.frame_timeout = 0;
1576 image->data.anim.anim = NULL;
1578 g_object_notify (G_OBJECT (image), "pixbuf_animation");
1582 case GTK_IMAGE_EMPTY:
1588 image->storage_type = GTK_IMAGE_EMPTY;
1590 memset (&image->data, '\0', sizeof (image->data));
1592 g_object_thaw_notify (G_OBJECT (image));
1596 gtk_image_reset (GtkImage *image)
1598 gtk_image_clear (image);
1600 gtk_image_update_size (image, 0, 0);
1604 gtk_image_calc_size (GtkImage *image)
1606 GtkWidget *widget = GTK_WIDGET (image);
1607 GdkPixbuf *pixbuf = NULL;
1609 /* We update stock/icon set on every size request, because
1610 * the theme could have affected the size; for other kinds of
1611 * image, we just update the requisition when the image data
1614 switch (image->storage_type)
1616 case GTK_IMAGE_STOCK:
1617 pixbuf = gtk_widget_render_icon (widget,
1618 image->data.stock.stock_id,
1623 case GTK_IMAGE_ICON_SET:
1624 pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1626 gtk_widget_get_direction (widget),
1627 GTK_WIDGET_STATE (widget),
1639 widget->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2;
1640 widget->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2;
1642 g_object_unref (pixbuf);
1647 gtk_image_size_request (GtkWidget *widget,
1648 GtkRequisition *requisition)
1652 image = GTK_IMAGE (widget);
1654 gtk_image_calc_size (image);
1656 /* Chain up to default that simply reads current requisition */
1657 GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
1661 gtk_image_update_size (GtkImage *image,
1665 GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
1666 GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
1668 if (GTK_WIDGET_VISIBLE (image))
1669 gtk_widget_queue_resize (GTK_WIDGET (image));