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/.
30 #include "gtkcontainer.h"
32 #include "gtkiconfactory.h"
39 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
41 static void gtk_image_class_init (GtkImageClass *klass);
42 static void gtk_image_init (GtkImage *image);
43 static gint gtk_image_expose (GtkWidget *widget,
44 GdkEventExpose *event);
45 static void gtk_image_unmap (GtkWidget *widget);
46 static void gtk_image_unrealize (GtkWidget *widget);
47 static void gtk_image_size_request (GtkWidget *widget,
48 GtkRequisition *requisition);
49 static void gtk_image_destroy (GtkObject *object);
50 static void gtk_image_clear (GtkImage *image);
51 static void gtk_image_reset (GtkImage *image);
52 static void gtk_image_calc_size (GtkImage *image);
54 static void gtk_image_update_size (GtkImage *image,
58 static void gtk_image_set_property (GObject *object,
62 static void gtk_image_get_property (GObject *object,
67 static gpointer parent_class;
80 PROP_PIXBUF_ANIMATION,
85 gtk_image_get_type (void)
87 static GType image_type = 0;
91 static const GTypeInfo image_info =
93 sizeof (GtkImageClass),
95 NULL, /* base_finalize */
96 (GClassInitFunc) gtk_image_class_init,
97 NULL, /* class_finalize */
98 NULL, /* class_data */
101 (GInstanceInitFunc) gtk_image_init,
104 image_type = g_type_register_static (GTK_TYPE_MISC, "GtkImage",
112 gtk_image_class_init (GtkImageClass *class)
114 GObjectClass *gobject_class;
115 GtkObjectClass *object_class;
116 GtkWidgetClass *widget_class;
118 parent_class = g_type_class_peek_parent (class);
120 gobject_class = G_OBJECT_CLASS (class);
122 gobject_class->set_property = gtk_image_set_property;
123 gobject_class->get_property = gtk_image_get_property;
125 object_class = GTK_OBJECT_CLASS (class);
127 object_class->destroy = gtk_image_destroy;
129 widget_class = GTK_WIDGET_CLASS (class);
131 widget_class->expose_event = gtk_image_expose;
132 widget_class->size_request = gtk_image_size_request;
133 widget_class->unmap = gtk_image_unmap;
134 widget_class->unrealize = gtk_image_unrealize;
136 g_object_class_install_property (gobject_class,
138 g_param_spec_object ("pixbuf",
140 P_("A GdkPixbuf to display"),
144 g_object_class_install_property (gobject_class,
146 g_param_spec_object ("pixmap",
148 P_("A GdkPixmap to display"),
152 g_object_class_install_property (gobject_class,
154 g_param_spec_object ("image",
156 P_("A GdkImage to display"),
160 g_object_class_install_property (gobject_class,
162 g_param_spec_object ("mask",
164 P_("Mask bitmap to use with GdkImage or GdkPixmap"),
168 g_object_class_install_property (gobject_class,
170 g_param_spec_string ("file",
172 P_("Filename to load and display"),
177 g_object_class_install_property (gobject_class,
179 g_param_spec_string ("stock",
181 P_("Stock ID for a stock image to display"),
185 g_object_class_install_property (gobject_class,
187 g_param_spec_boxed ("icon_set",
189 P_("Icon set to display"),
193 g_object_class_install_property (gobject_class,
195 g_param_spec_int ("icon_size",
197 P_("Size to use for stock icon or icon set"),
202 g_object_class_install_property (gobject_class,
203 PROP_PIXBUF_ANIMATION,
204 g_param_spec_object ("pixbuf_animation",
206 P_("GdkPixbufAnimation to display"),
207 GDK_TYPE_PIXBUF_ANIMATION,
210 g_object_class_install_property (gobject_class,
212 g_param_spec_enum ("storage_type",
214 P_("The representation being used for image data"),
221 gtk_image_init (GtkImage *image)
223 GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
225 image->storage_type = GTK_IMAGE_EMPTY;
226 image->icon_size = DEFAULT_ICON_SIZE;
231 gtk_image_destroy (GtkObject *object)
233 GtkImage *image = GTK_IMAGE (object);
235 gtk_image_clear (image);
237 GTK_OBJECT_CLASS (parent_class)->destroy (object);
241 gtk_image_set_property (GObject *object,
248 image = GTK_IMAGE (object);
253 gtk_image_set_from_pixbuf (image,
254 g_value_get_object (value));
257 gtk_image_set_from_pixmap (image,
258 g_value_get_object (value),
262 gtk_image_set_from_image (image,
263 g_value_get_object (value),
267 if (image->storage_type == GTK_IMAGE_PIXMAP)
268 gtk_image_set_from_pixmap (image,
269 image->data.pixmap.pixmap,
270 g_value_get_object (value));
271 else if (image->storage_type == GTK_IMAGE_IMAGE)
272 gtk_image_set_from_image (image,
273 image->data.image.image,
274 g_value_get_object (value));
279 mask = g_value_get_object (value);
284 gtk_image_reset (image);
290 gtk_image_set_from_file (image,
291 g_value_get_string (value));
294 gtk_image_set_from_stock (image, g_value_get_string (value),
298 gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
302 if (image->storage_type == GTK_IMAGE_STOCK)
303 gtk_image_set_from_stock (image,
304 image->data.stock.stock_id,
305 g_value_get_int (value));
306 else if (image->storage_type == GTK_IMAGE_ICON_SET)
307 gtk_image_set_from_icon_set (image,
308 image->data.icon_set.icon_set,
309 g_value_get_int (value));
311 /* Save to be used when STOCK or ICON_SET property comes in */
312 image->icon_size = g_value_get_int (value);
314 case PROP_PIXBUF_ANIMATION:
315 gtk_image_set_from_animation (image,
316 g_value_get_object (value));
320 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
326 gtk_image_get_property (GObject *object,
333 image = GTK_IMAGE (object);
335 /* The "getter" functions whine if you try to get the wrong
336 * storage type. This function is instead robust against that,
337 * so that GUI builders don't have to jump through hoops
344 if (image->storage_type != GTK_IMAGE_PIXBUF)
345 g_value_set_object (value, NULL);
347 g_value_set_object (value,
348 gtk_image_get_pixbuf (image));
351 if (image->storage_type != GTK_IMAGE_PIXMAP)
352 g_value_set_object (value, NULL);
354 g_value_set_object (value,
355 image->data.pixmap.pixmap);
358 g_value_set_object (value, image->mask);
361 if (image->storage_type != GTK_IMAGE_IMAGE)
362 g_value_set_object (value, NULL);
364 g_value_set_object (value,
365 image->data.image.image);
368 if (image->storage_type != GTK_IMAGE_STOCK)
369 g_value_set_string (value, NULL);
371 g_value_set_string (value,
372 image->data.stock.stock_id);
375 if (image->storage_type != GTK_IMAGE_ICON_SET)
376 g_value_set_boxed (value, NULL);
378 g_value_set_boxed (value,
379 image->data.icon_set.icon_set);
382 g_value_set_int (value, image->icon_size);
384 case PROP_PIXBUF_ANIMATION:
385 if (image->storage_type != GTK_IMAGE_ANIMATION)
386 g_value_set_object (value, NULL);
388 g_value_set_object (value,
389 image->data.anim.anim);
391 case PROP_STORAGE_TYPE:
392 g_value_set_enum (value, image->storage_type);
396 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
403 * gtk_image_new_from_pixmap:
404 * @pixmap: a #GdkPixmap, or %NULL
405 * @mask: a #GdkBitmap, or %NULL
407 * Creates a #GtkImage widget displaying @pixmap with a @mask.
408 * A #GdkPixmap is a server-side image buffer in the pixel format of the
409 * current display. The #GtkImage does not assume a reference to the
410 * pixmap or mask; you still need to unref them if you own references.
411 * #GtkImage will add its own reference rather than adopting yours.
413 * Return value: a new #GtkImage
416 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
421 image = g_object_new (GTK_TYPE_IMAGE, NULL);
423 gtk_image_set_from_pixmap (image, pixmap, mask);
425 return GTK_WIDGET (image);
429 * gtk_image_new_from_image:
430 * @image: a #GdkImage, or %NULL
431 * @mask: a #GdkBitmap, or %NULL
433 * Creates a #GtkImage widget displaying a @image with a @mask.
434 * A #GdkImage is a client-side image buffer in the pixel format of the
436 * The #GtkImage does not assume a reference to the
437 * image or mask; you still need to unref them if you own references.
438 * #GtkImage will add its own reference rather than adopting yours.
440 * Return value: a new #GtkImage
443 gtk_image_new_from_image (GdkImage *gdk_image,
448 image = g_object_new (GTK_TYPE_IMAGE, NULL);
450 gtk_image_set_from_image (image, gdk_image, mask);
452 return GTK_WIDGET (image);
456 * gtk_image_new_from_file:
457 * @filename: a filename
459 * Creates a new #GtkImage displaying the file @filename. If the file
460 * isn't found or can't be loaded, the resulting #GtkImage will
461 * display a "broken image" icon. This function never returns %NULL,
462 * it always returns a valid #GtkImage widget.
464 * If the file contains an animation, the image will contain an
467 * If you need to detect failures to load the file, use
468 * gdk_pixbuf_new_from_file() to load the file yourself, then create
469 * the #GtkImage from the pixbuf. (Or for animations, use
470 * gdk_pixbuf_animation_new_from_file()).
472 * The storage type (gtk_image_get_storage_type()) of the returned
473 * image is not defined, it will be whatever is appropriate for
474 * displaying the file.
476 * Return value: a new #GtkImage
479 gtk_image_new_from_file (const gchar *filename)
483 image = g_object_new (GTK_TYPE_IMAGE, NULL);
485 gtk_image_set_from_file (image, filename);
487 return GTK_WIDGET (image);
491 * gtk_image_new_from_pixbuf:
492 * @pixbuf: a #GdkPixbuf, or %NULL
494 * Creates a new #GtkImage displaying @pixbuf.
495 * The #GtkImage does not assume a reference to the
496 * pixbuf; you still need to unref it if you own references.
497 * #GtkImage will add its own reference rather than adopting yours.
499 * Note that this function just creates an #GtkImage from the pixbuf. The
500 * #GtkImage created will not react to state changes. Should you want that, you
501 * should use gtk_image_new_from_icon_set().
503 * Return value: a new #GtkImage
506 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
510 image = g_object_new (GTK_TYPE_IMAGE, NULL);
512 gtk_image_set_from_pixbuf (image, pixbuf);
514 return GTK_WIDGET (image);
518 * gtk_image_new_from_stock:
519 * @stock_id: a stock icon name
520 * @size: a stock icon size
522 * Creates a #GtkImage displaying a stock icon. Sample stock icon
523 * names are #GTK_STOCK_OPEN, #GTK_STOCK_EXIT. Sample stock sizes
524 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
525 * icon name isn't known, a "broken image" icon will be displayed instead.
526 * You can register your own stock icon names, see
527 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
529 * Return value: a new #GtkImage displaying the stock icon
532 gtk_image_new_from_stock (const gchar *stock_id,
537 image = g_object_new (GTK_TYPE_IMAGE, NULL);
539 gtk_image_set_from_stock (image, stock_id, size);
541 return GTK_WIDGET (image);
545 * gtk_image_new_from_icon_set:
546 * @icon_set: a #GtkIconSet
547 * @size: a stock icon size
549 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
550 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
551 * this function, usually it's better to create a #GtkIconFactory, put
552 * your icon sets in the icon factory, add the icon factory to the
553 * list of default factories with gtk_icon_factory_add_default(), and
554 * then use gtk_image_new_from_stock(). This will allow themes to
555 * override the icon you ship with your application.
557 * The #GtkImage does not assume a reference to the
558 * icon set; you still need to unref it if you own references.
559 * #GtkImage will add its own reference rather than adopting yours.
562 * Return value: a new #GtkImage
565 gtk_image_new_from_icon_set (GtkIconSet *icon_set,
570 image = g_object_new (GTK_TYPE_IMAGE, NULL);
572 gtk_image_set_from_icon_set (image, icon_set, size);
574 return GTK_WIDGET (image);
578 * gtk_image_new_from_animation:
579 * @animation: an animation
581 * Creates a #GtkImage displaying the given animation.
582 * The #GtkImage does not assume a reference to the
583 * animation; you still need to unref it if you own references.
584 * #GtkImage will add its own reference rather than adopting yours.
586 * Return value: a new #GtkImage widget
589 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
593 g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
595 image = g_object_new (GTK_TYPE_IMAGE, NULL);
597 gtk_image_set_from_animation (image, animation);
599 return GTK_WIDGET (image);
603 * gtk_image_set_from_pixmap:
604 * @image: a #GtkImage
605 * @pixmap: a #GdkPixmap or %NULL
606 * @mask: a #GdkBitmap or %NULL
608 * See gtk_image_new_from_pixmap() for details.
612 gtk_image_set_from_pixmap (GtkImage *image,
616 g_return_if_fail (GTK_IS_IMAGE (image));
617 g_return_if_fail (pixmap == NULL ||
618 GDK_IS_PIXMAP (pixmap));
619 g_return_if_fail (mask == NULL ||
620 GDK_IS_PIXMAP (mask));
622 g_object_freeze_notify (G_OBJECT (image));
625 g_object_ref (pixmap);
630 gtk_image_reset (image);
639 image->storage_type = GTK_IMAGE_PIXMAP;
641 image->data.pixmap.pixmap = pixmap;
643 gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
645 gtk_image_update_size (image, width, height);
648 g_object_notify (G_OBJECT (image), "pixmap");
649 g_object_notify (G_OBJECT (image), "mask");
651 g_object_thaw_notify (G_OBJECT (image));
655 * gtk_image_set_from_image:
656 * @image: a #GtkImage
657 * @gdk_image: a #GdkImage or %NULL
658 * @mask: a #GdkBitmap or %NULL
660 * See gtk_image_new_from_image() for details.
664 gtk_image_set_from_image (GtkImage *image,
668 g_return_if_fail (GTK_IS_IMAGE (image));
669 g_return_if_fail (gdk_image == NULL ||
670 GDK_IS_IMAGE (gdk_image));
671 g_return_if_fail (mask == NULL ||
672 GDK_IS_PIXMAP (mask));
674 g_object_freeze_notify (G_OBJECT (image));
677 g_object_ref (gdk_image);
682 gtk_image_reset (image);
686 image->storage_type = GTK_IMAGE_IMAGE;
688 image->data.image.image = gdk_image;
691 gtk_image_update_size (image, gdk_image->width, gdk_image->height);
695 /* Clean up the mask if gdk_image was NULL */
697 g_object_unref (mask);
700 g_object_notify (G_OBJECT (image), "image");
701 g_object_notify (G_OBJECT (image), "mask");
703 g_object_thaw_notify (G_OBJECT (image));
707 * gtk_image_set_from_file:
708 * @image: a #GtkImage
709 * @filename: a filename or %NULL
711 * See gtk_image_new_from_file() for details.
715 gtk_image_set_from_file (GtkImage *image,
716 const gchar *filename)
718 GdkPixbufAnimation *anim;
720 g_return_if_fail (GTK_IS_IMAGE (image));
722 g_object_freeze_notify (G_OBJECT (image));
724 gtk_image_reset (image);
726 if (filename == NULL)
728 g_object_thaw_notify (G_OBJECT (image));
732 anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
736 gtk_image_set_from_stock (image,
737 GTK_STOCK_MISSING_IMAGE,
738 GTK_ICON_SIZE_BUTTON);
739 g_object_thaw_notify (G_OBJECT (image));
743 /* We could just unconditionally set_from_animation,
744 * but it's nicer for memory if we toss the animation
745 * if it's just a single pixbuf
748 if (gdk_pixbuf_animation_is_static_image (anim))
750 gtk_image_set_from_pixbuf (image,
751 gdk_pixbuf_animation_get_static_image (anim));
755 gtk_image_set_from_animation (image, anim);
758 g_object_unref (anim);
760 g_object_thaw_notify (G_OBJECT (image));
764 * gtk_image_set_from_pixbuf:
765 * @image: a #GtkImage
766 * @pixbuf: a #GdkPixbuf or %NULL
768 * See gtk_image_new_from_pixbuf() for details.
772 gtk_image_set_from_pixbuf (GtkImage *image,
775 g_return_if_fail (GTK_IS_IMAGE (image));
776 g_return_if_fail (pixbuf == NULL ||
777 GDK_IS_PIXBUF (pixbuf));
779 g_object_freeze_notify (G_OBJECT (image));
782 g_object_ref (pixbuf);
784 gtk_image_reset (image);
788 image->storage_type = GTK_IMAGE_PIXBUF;
790 image->data.pixbuf.pixbuf = pixbuf;
792 gtk_image_update_size (image,
793 gdk_pixbuf_get_width (pixbuf),
794 gdk_pixbuf_get_height (pixbuf));
797 g_object_notify (G_OBJECT (image), "pixbuf");
799 g_object_thaw_notify (G_OBJECT (image));
803 * gtk_image_set_from_stock:
804 * @image: a #GtkImage
805 * @stock_id: a stock icon name
806 * @size: a stock icon size
808 * See gtk_image_new_from_stock() for details.
812 gtk_image_set_from_stock (GtkImage *image,
813 const gchar *stock_id,
818 g_return_if_fail (GTK_IS_IMAGE (image));
820 g_object_freeze_notify (G_OBJECT (image));
822 /* in case stock_id == image->data.stock.stock_id */
823 new_id = g_strdup (stock_id);
825 gtk_image_reset (image);
829 image->storage_type = GTK_IMAGE_STOCK;
831 image->data.stock.stock_id = new_id;
832 image->icon_size = size;
834 /* Size is demand-computed in size request method
835 * if we're a stock image, since changing the
836 * style impacts the size request
840 g_object_notify (G_OBJECT (image), "stock");
841 g_object_notify (G_OBJECT (image), "icon_size");
843 g_object_thaw_notify (G_OBJECT (image));
847 * gtk_image_set_from_icon_set:
848 * @image: a #GtkImage
849 * @icon_set: a #GtkIconSet
850 * @size: a stock icon size
852 * See gtk_image_new_from_icon_set() for details.
856 gtk_image_set_from_icon_set (GtkImage *image,
857 GtkIconSet *icon_set,
860 g_return_if_fail (GTK_IS_IMAGE (image));
862 g_object_freeze_notify (G_OBJECT (image));
865 gtk_icon_set_ref (icon_set);
867 gtk_image_reset (image);
871 image->storage_type = GTK_IMAGE_ICON_SET;
873 image->data.icon_set.icon_set = icon_set;
874 image->icon_size = size;
876 /* Size is demand-computed in size request method
877 * if we're an icon set
881 g_object_notify (G_OBJECT (image), "icon_set");
882 g_object_notify (G_OBJECT (image), "icon_size");
884 g_object_thaw_notify (G_OBJECT (image));
888 * gtk_image_set_from_animation:
889 * @image: a #GtkImage
890 * @animation: the #GdkPixbufAnimation
892 * Causes the #GtkImage to display the given animation (or display
893 * nothing, if you set the animation to %NULL).
896 gtk_image_set_from_animation (GtkImage *image,
897 GdkPixbufAnimation *animation)
899 g_return_if_fail (GTK_IS_IMAGE (image));
900 g_return_if_fail (animation == NULL ||
901 GDK_IS_PIXBUF_ANIMATION (animation));
903 g_object_freeze_notify (G_OBJECT (image));
906 g_object_ref (animation);
908 gtk_image_reset (image);
910 if (animation != NULL)
912 image->storage_type = GTK_IMAGE_ANIMATION;
914 image->data.anim.anim = animation;
915 image->data.anim.frame_timeout = 0;
916 image->data.anim.iter = NULL;
918 gtk_image_update_size (image,
919 gdk_pixbuf_animation_get_width (animation),
920 gdk_pixbuf_animation_get_height (animation));
923 g_object_notify (G_OBJECT (image), "pixbuf_animation");
925 g_object_thaw_notify (G_OBJECT (image));
929 * gtk_image_get_storage_type:
930 * @image: a #GtkImage
932 * Gets the type of representation being used by the #GtkImage
933 * to store image data. If the #GtkImage has no image data,
934 * the return value will be %GTK_IMAGE_EMPTY.
936 * Return value: image representation being used
939 gtk_image_get_storage_type (GtkImage *image)
941 g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
943 return image->storage_type;
947 * gtk_image_get_pixmap:
948 * @image: a #GtkImage
949 * @pixmap: location to store the pixmap, or %NULL
950 * @mask: location to store the mask, or %NULL
952 * Gets the pixmap and mask being displayed by the #GtkImage.
953 * The storage type of the image must be %GTK_IMAGE_EMPTY or
954 * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
955 * The caller of this function does not own a reference to the
956 * returned pixmap and mask.
960 gtk_image_get_pixmap (GtkImage *image,
964 g_return_if_fail (GTK_IS_IMAGE (image));
965 g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
966 image->storage_type == GTK_IMAGE_EMPTY);
969 *pixmap = image->data.pixmap.pixmap;
976 * gtk_image_get_image:
977 * @image: a #GtkImage
978 * @gdk_image: return location for a #GtkImage
979 * @mask: return location for a #GdkBitmap
981 * Gets the #GdkImage and mask being displayed by the #GtkImage.
982 * The storage type of the image must be %GTK_IMAGE_EMPTY or
983 * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
984 * The caller of this function does not own a reference to the
985 * returned image and mask.
988 gtk_image_get_image (GtkImage *image,
989 GdkImage **gdk_image,
992 g_return_if_fail (GTK_IS_IMAGE (image));
993 g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
994 image->storage_type == GTK_IMAGE_EMPTY);
997 *gdk_image = image->data.image.image;
1000 *mask = image->mask;
1004 * gtk_image_get_pixbuf:
1005 * @image: a #GtkImage
1008 * Gets the #GdkPixbuf being displayed by the #GtkImage.
1009 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1010 * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1011 * The caller of this function does not own a reference to the
1014 * Return value: the displayed pixbuf, or %NULL if the image is empty
1017 gtk_image_get_pixbuf (GtkImage *image)
1019 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1020 g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
1021 image->storage_type == GTK_IMAGE_EMPTY, NULL);
1023 if (image->storage_type == GTK_IMAGE_EMPTY)
1024 image->data.pixbuf.pixbuf = NULL;
1026 return image->data.pixbuf.pixbuf;
1030 * gtk_image_get_stock:
1031 * @image: a #GtkImage
1032 * @stock_id: place to store a stock icon name
1033 * @size: place to store a stock icon size
1035 * Gets the stock icon name and size being displayed by the #GtkImage.
1036 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1037 * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1038 * The returned string is owned by the #GtkImage and should not
1043 gtk_image_get_stock (GtkImage *image,
1047 g_return_if_fail (GTK_IS_IMAGE (image));
1048 g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
1049 image->storage_type == GTK_IMAGE_EMPTY);
1051 if (image->storage_type == GTK_IMAGE_EMPTY)
1052 image->data.stock.stock_id = NULL;
1055 *stock_id = image->data.stock.stock_id;
1058 *size = image->icon_size;
1062 * gtk_image_get_icon_set:
1063 * @image: a #GtkImage
1064 * @icon_set: location to store a #GtkIconSet
1065 * @size: location to store a stock icon size
1067 * Gets the icon set and size being displayed by the #GtkImage.
1068 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1069 * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1073 gtk_image_get_icon_set (GtkImage *image,
1074 GtkIconSet **icon_set,
1077 g_return_if_fail (GTK_IS_IMAGE (image));
1078 g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
1079 image->storage_type == GTK_IMAGE_EMPTY);
1082 *icon_set = image->data.icon_set.icon_set;
1085 *size = image->icon_size;
1089 * gtk_image_get_animation:
1090 * @image: a #GtkImage
1093 * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1094 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1095 * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1096 * The caller of this function does not own a reference to the
1097 * returned animation.
1099 * Return value: the displayed animation, or %NULL if the image is empty
1102 gtk_image_get_animation (GtkImage *image)
1104 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1105 g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
1106 image->storage_type == GTK_IMAGE_EMPTY,
1109 if (image->storage_type == GTK_IMAGE_EMPTY)
1110 image->data.anim.anim = NULL;
1112 return image->data.anim.anim;
1118 * Creates a new empty #GtkImage widget.
1120 * Return value: a newly created #GtkImage widget.
1123 gtk_image_new (void)
1125 return g_object_new (GTK_TYPE_IMAGE, NULL);
1129 gtk_image_set (GtkImage *image,
1133 g_return_if_fail (GTK_IS_IMAGE (image));
1135 gtk_image_set_from_image (image, val, mask);
1139 gtk_image_get (GtkImage *image,
1143 g_return_if_fail (GTK_IS_IMAGE (image));
1145 gtk_image_get_image (image, val, mask);
1149 gtk_image_reset_anim_iter (GtkImage *image)
1151 if (image->storage_type == GTK_IMAGE_ANIMATION)
1153 /* Reset the animation */
1155 if (image->data.anim.frame_timeout)
1157 g_source_remove (image->data.anim.frame_timeout);
1158 image->data.anim.frame_timeout = 0;
1161 if (image->data.anim.iter)
1163 g_object_unref (image->data.anim.iter);
1164 image->data.anim.iter = NULL;
1170 gtk_image_unmap (GtkWidget *widget)
1172 gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1174 if (GTK_WIDGET_CLASS (parent_class)->unmap)
1175 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1179 gtk_image_unrealize (GtkWidget *widget)
1181 gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1183 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1184 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
1188 animation_timeout (gpointer data)
1192 GDK_THREADS_ENTER ();
1194 image = GTK_IMAGE (data);
1196 image->data.anim.frame_timeout = 0;
1198 gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);
1200 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1201 image->data.anim.frame_timeout =
1202 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1206 gtk_widget_queue_draw (GTK_WIDGET (image));
1208 GDK_THREADS_LEAVE ();
1214 * Like gdk_rectangle_intersect (dest, src, dest), but make
1215 * sure that the origin of dest is moved by an "even" offset.
1216 * If necessary grow the intersection by one row or column
1219 * This is necessary since we can't pass alignment information
1220 * for the pixelation pattern down to gdk_pixbuf_saturate_and_pixelate(),
1221 * thus we have to makesure that the subimages are properly aligned.
1224 rectangle_intersect_even (GdkRectangle *src,
1232 isect = gdk_rectangle_intersect (dest, src, dest);
1234 if ((dest->x - x + dest->y - y) % 2 != 0)
1252 gtk_image_expose (GtkWidget *widget,
1253 GdkEventExpose *event)
1255 g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1256 g_return_val_if_fail (event != NULL, FALSE);
1258 if (GTK_WIDGET_MAPPED (widget) &&
1259 GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
1263 GdkRectangle area, image_bound;
1265 gint x, y, mask_x, mask_y;
1268 gboolean needs_state_transform;
1270 image = GTK_IMAGE (widget);
1271 misc = GTK_MISC (widget);
1275 /* For stock items and icon sets, we lazily calculate
1276 * the size; we might get here between a queue_resize()
1277 * and size_request() if something explicitely forces
1280 if (widget->requisition.width == 0 && widget->requisition.height == 0)
1281 gtk_image_calc_size (image);
1283 if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
1286 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1287 xalign = misc->xalign;
1289 xalign = 1.0 - misc->xalign;
1291 x = floor (widget->allocation.x + misc->xpad
1292 + ((widget->allocation.width - widget->requisition.width) * xalign)
1294 y = floor (widget->allocation.y + misc->ypad
1295 + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1302 image_bound.width = 0;
1303 image_bound.height = 0;
1307 needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
1309 switch (image->storage_type)
1311 case GTK_IMAGE_PIXMAP:
1313 gdk_drawable_get_size (image->data.pixmap.pixmap,
1315 &image_bound.height);
1316 if (rectangle_intersect_even (&area, &image_bound) &&
1317 needs_state_transform)
1319 pixbuf = gdk_pixbuf_get_from_drawable (NULL,
1320 image->data.pixmap.pixmap,
1321 gtk_widget_get_colormap (widget),
1322 image_bound.x - x, image_bound.y - y,
1325 image_bound.height);
1333 case GTK_IMAGE_IMAGE:
1335 image_bound.width = image->data.image.image->width;
1336 image_bound.height = image->data.image.image->height;
1338 if (rectangle_intersect_even (&area, &image_bound) &&
1339 needs_state_transform)
1341 pixbuf = gdk_pixbuf_get_from_image (NULL,
1342 image->data.image.image,
1343 gtk_widget_get_colormap (widget),
1344 image_bound.x - x, image_bound.y - y,
1347 image_bound.height);
1354 case GTK_IMAGE_PIXBUF:
1355 image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
1356 image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);
1359 if (rectangle_intersect_even (&area, &image_bound) &&
1360 needs_state_transform)
1362 pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf,
1363 image_bound.x - x, image_bound.y - y,
1364 image_bound.width, image_bound.height);
1371 pixbuf = image->data.pixbuf.pixbuf;
1372 g_object_ref (pixbuf);
1376 case GTK_IMAGE_STOCK:
1377 pixbuf = gtk_widget_render_icon (widget,
1378 image->data.stock.stock_id,
1383 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1384 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1388 needs_state_transform = FALSE;
1391 case GTK_IMAGE_ICON_SET:
1393 gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1395 gtk_widget_get_direction (widget),
1396 GTK_WIDGET_STATE (widget),
1403 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1404 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1408 needs_state_transform = FALSE;
1411 case GTK_IMAGE_ANIMATION:
1413 if (image->data.anim.iter == NULL)
1415 image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL);
1417 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1418 image->data.anim.frame_timeout =
1419 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1424 image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim);
1425 image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim);
1427 /* don't advance the anim iter here, or we could get frame changes between two
1428 * exposes of different areas.
1431 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter);
1432 g_object_ref (pixbuf);
1436 case GTK_IMAGE_EMPTY:
1437 g_assert_not_reached ();
1443 gdk_gc_set_clip_mask (widget->style->black_gc, mask);
1444 gdk_gc_set_clip_origin (widget->style->black_gc, mask_x, mask_y);
1447 if (rectangle_intersect_even (&area, &image_bound))
1451 if (needs_state_transform)
1453 GtkIconSource *source;
1454 GdkPixbuf *rendered;
1456 source = gtk_icon_source_new ();
1457 gtk_icon_source_set_pixbuf (source, pixbuf);
1458 /* The size here is arbitrary; since size isn't
1459 * wildcarded in the souce, it isn't supposed to be
1460 * scaled by the engine function
1462 gtk_icon_source_set_size (source,
1463 GTK_ICON_SIZE_SMALL_TOOLBAR);
1464 gtk_icon_source_set_size_wildcarded (source, FALSE);
1466 rendered = gtk_style_render_icon (widget->style,
1468 gtk_widget_get_direction (widget),
1469 GTK_WIDGET_STATE (widget),
1475 gtk_icon_source_free (source);
1477 g_object_unref (pixbuf);
1483 gdk_draw_pixbuf (widget->window,
1484 widget->style->black_gc,
1492 GDK_RGB_DITHER_NORMAL,
1495 g_object_unref (pixbuf);
1501 switch (image->storage_type)
1503 case GTK_IMAGE_PIXMAP:
1504 gdk_draw_drawable (widget->window,
1505 widget->style->black_gc,
1506 image->data.pixmap.pixmap,
1507 image_bound.x - x, image_bound.y - y,
1508 image_bound.x, image_bound.y,
1509 image_bound.width, image_bound.height);
1512 case GTK_IMAGE_IMAGE:
1513 gdk_draw_image (widget->window,
1514 widget->style->black_gc,
1515 image->data.image.image,
1516 image_bound.x - x, image_bound.y - y,
1517 image_bound.x, image_bound.y,
1518 image_bound.width, image_bound.height);
1521 case GTK_IMAGE_PIXBUF:
1522 case GTK_IMAGE_STOCK:
1523 case GTK_IMAGE_ICON_SET:
1524 case GTK_IMAGE_ANIMATION:
1525 case GTK_IMAGE_EMPTY:
1526 g_assert_not_reached ();
1530 } /* if rectangle intersects */
1534 gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
1535 gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
1538 } /* if widget is drawable */
1544 gtk_image_clear (GtkImage *image)
1546 g_object_freeze_notify (G_OBJECT (image));
1548 if (image->storage_type != GTK_IMAGE_EMPTY)
1549 g_object_notify (G_OBJECT (image), "storage_type");
1553 g_object_unref (image->mask);
1555 g_object_notify (G_OBJECT (image), "mask");
1558 if (image->icon_size != DEFAULT_ICON_SIZE)
1560 image->icon_size = DEFAULT_ICON_SIZE;
1561 g_object_notify (G_OBJECT (image), "icon_size");
1564 switch (image->storage_type)
1566 case GTK_IMAGE_PIXMAP:
1568 if (image->data.pixmap.pixmap)
1569 g_object_unref (image->data.pixmap.pixmap);
1570 image->data.pixmap.pixmap = NULL;
1572 g_object_notify (G_OBJECT (image), "pixmap");
1576 case GTK_IMAGE_IMAGE:
1578 if (image->data.image.image)
1579 g_object_unref (image->data.image.image);
1580 image->data.image.image = NULL;
1582 g_object_notify (G_OBJECT (image), "image");
1586 case GTK_IMAGE_PIXBUF:
1588 if (image->data.pixbuf.pixbuf)
1589 g_object_unref (image->data.pixbuf.pixbuf);
1591 g_object_notify (G_OBJECT (image), "pixbuf");
1595 case GTK_IMAGE_STOCK:
1597 g_free (image->data.stock.stock_id);
1599 image->data.stock.stock_id = NULL;
1601 g_object_notify (G_OBJECT (image), "stock");
1604 case GTK_IMAGE_ICON_SET:
1605 if (image->data.icon_set.icon_set)
1606 gtk_icon_set_unref (image->data.icon_set.icon_set);
1607 image->data.icon_set.icon_set = NULL;
1609 g_object_notify (G_OBJECT (image), "icon_set");
1612 case GTK_IMAGE_ANIMATION:
1613 if (image->data.anim.frame_timeout)
1614 g_source_remove (image->data.anim.frame_timeout);
1616 if (image->data.anim.anim)
1617 g_object_unref (image->data.anim.anim);
1619 image->data.anim.frame_timeout = 0;
1620 image->data.anim.anim = NULL;
1622 g_object_notify (G_OBJECT (image), "pixbuf_animation");
1626 case GTK_IMAGE_EMPTY:
1632 image->storage_type = GTK_IMAGE_EMPTY;
1634 memset (&image->data, '\0', sizeof (image->data));
1636 g_object_thaw_notify (G_OBJECT (image));
1640 gtk_image_reset (GtkImage *image)
1642 gtk_image_clear (image);
1644 gtk_image_update_size (image, 0, 0);
1648 gtk_image_calc_size (GtkImage *image)
1650 GtkWidget *widget = GTK_WIDGET (image);
1651 GdkPixbuf *pixbuf = NULL;
1653 /* We update stock/icon set on every size request, because
1654 * the theme could have affected the size; for other kinds of
1655 * image, we just update the requisition when the image data
1658 switch (image->storage_type)
1660 case GTK_IMAGE_STOCK:
1661 pixbuf = gtk_widget_render_icon (widget,
1662 image->data.stock.stock_id,
1667 case GTK_IMAGE_ICON_SET:
1668 pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1670 gtk_widget_get_direction (widget),
1671 GTK_WIDGET_STATE (widget),
1683 widget->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2;
1684 widget->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2;
1686 g_object_unref (pixbuf);
1691 gtk_image_size_request (GtkWidget *widget,
1692 GtkRequisition *requisition)
1696 image = GTK_IMAGE (widget);
1698 gtk_image_calc_size (image);
1700 /* Chain up to default that simply reads current requisition */
1701 GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
1705 gtk_image_update_size (GtkImage *image,
1709 GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
1710 GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
1712 if (GTK_WIDGET_VISIBLE (image))
1713 gtk_widget_queue_resize (GTK_WIDGET (image));