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/.
29 #include "gtkcontainer.h"
31 #include "gtkiconfactory.h"
36 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
38 static void gtk_image_class_init (GtkImageClass *klass);
39 static void gtk_image_init (GtkImage *image);
40 static gint gtk_image_expose (GtkWidget *widget,
41 GdkEventExpose *event);
42 static void gtk_image_unmap (GtkWidget *widget);
43 static void gtk_image_unrealize (GtkWidget *widget);
44 static void gtk_image_size_request (GtkWidget *widget,
45 GtkRequisition *requisition);
46 static void gtk_image_destroy (GtkObject *object);
47 static void gtk_image_clear (GtkImage *image);
48 static void gtk_image_reset (GtkImage *image);
49 static void gtk_image_calc_size (GtkImage *image);
51 static void gtk_image_update_size (GtkImage *image,
55 static void gtk_image_set_property (GObject *object,
59 static void gtk_image_get_property (GObject *object,
64 static gpointer parent_class;
77 PROP_PIXBUF_ANIMATION,
82 gtk_image_get_type (void)
84 static GType image_type = 0;
88 static const GTypeInfo image_info =
90 sizeof (GtkImageClass),
92 NULL, /* base_finalize */
93 (GClassInitFunc) gtk_image_class_init,
94 NULL, /* class_finalize */
95 NULL, /* class_data */
98 (GInstanceInitFunc) gtk_image_init,
101 image_type = g_type_register_static (GTK_TYPE_MISC, "GtkImage",
109 gtk_image_class_init (GtkImageClass *class)
111 GObjectClass *gobject_class;
112 GtkObjectClass *object_class;
113 GtkWidgetClass *widget_class;
115 parent_class = g_type_class_peek_parent (class);
117 gobject_class = G_OBJECT_CLASS (class);
119 gobject_class->set_property = gtk_image_set_property;
120 gobject_class->get_property = gtk_image_get_property;
122 object_class = GTK_OBJECT_CLASS (class);
124 object_class->destroy = gtk_image_destroy;
126 widget_class = GTK_WIDGET_CLASS (class);
128 widget_class->expose_event = gtk_image_expose;
129 widget_class->size_request = gtk_image_size_request;
130 widget_class->unmap = gtk_image_unmap;
131 widget_class->unrealize = gtk_image_unrealize;
133 g_object_class_install_property (gobject_class,
135 g_param_spec_object ("pixbuf",
137 P_("A GdkPixbuf to display"),
141 g_object_class_install_property (gobject_class,
143 g_param_spec_object ("pixmap",
145 P_("A GdkPixmap to display"),
149 g_object_class_install_property (gobject_class,
151 g_param_spec_object ("image",
153 P_("A GdkImage to display"),
157 g_object_class_install_property (gobject_class,
159 g_param_spec_object ("mask",
161 P_("Mask bitmap to use with GdkImage or GdkPixmap"),
165 g_object_class_install_property (gobject_class,
167 g_param_spec_string ("file",
169 P_("Filename to load and display"),
174 g_object_class_install_property (gobject_class,
176 g_param_spec_string ("stock",
178 P_("Stock ID for a stock image to display"),
182 g_object_class_install_property (gobject_class,
184 g_param_spec_boxed ("icon_set",
186 P_("Icon set to display"),
190 g_object_class_install_property (gobject_class,
192 g_param_spec_int ("icon_size",
194 P_("Size to use for stock icon or icon set"),
199 g_object_class_install_property (gobject_class,
200 PROP_PIXBUF_ANIMATION,
201 g_param_spec_object ("pixbuf_animation",
203 P_("GdkPixbufAnimation to display"),
204 GDK_TYPE_PIXBUF_ANIMATION,
207 g_object_class_install_property (gobject_class,
209 g_param_spec_enum ("storage_type",
211 P_("The representation being used for image data"),
218 gtk_image_init (GtkImage *image)
220 GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
222 image->storage_type = GTK_IMAGE_EMPTY;
223 image->icon_size = DEFAULT_ICON_SIZE;
228 gtk_image_destroy (GtkObject *object)
230 GtkImage *image = GTK_IMAGE (object);
232 gtk_image_clear (image);
234 GTK_OBJECT_CLASS (parent_class)->destroy (object);
238 gtk_image_set_property (GObject *object,
245 image = GTK_IMAGE (object);
250 gtk_image_set_from_pixbuf (image,
251 g_value_get_object (value));
254 gtk_image_set_from_pixmap (image,
255 g_value_get_object (value),
259 gtk_image_set_from_image (image,
260 g_value_get_object (value),
264 if (image->storage_type == GTK_IMAGE_PIXMAP)
265 gtk_image_set_from_pixmap (image,
266 image->data.pixmap.pixmap,
267 g_value_get_object (value));
268 else if (image->storage_type == GTK_IMAGE_IMAGE)
269 gtk_image_set_from_image (image,
270 image->data.image.image,
271 g_value_get_object (value));
276 mask = g_value_get_object (value);
281 gtk_image_reset (image);
287 gtk_image_set_from_file (image,
288 g_value_get_string (value));
291 gtk_image_set_from_stock (image, g_value_get_string (value),
295 gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
299 if (image->storage_type == GTK_IMAGE_STOCK)
300 gtk_image_set_from_stock (image,
301 image->data.stock.stock_id,
302 g_value_get_int (value));
303 else if (image->storage_type == GTK_IMAGE_ICON_SET)
304 gtk_image_set_from_icon_set (image,
305 image->data.icon_set.icon_set,
306 g_value_get_int (value));
308 /* Save to be used when STOCK or ICON_SET property comes in */
309 image->icon_size = g_value_get_int (value);
311 case PROP_PIXBUF_ANIMATION:
312 gtk_image_set_from_animation (image,
313 g_value_get_object (value));
317 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
323 gtk_image_get_property (GObject *object,
330 image = GTK_IMAGE (object);
332 /* The "getter" functions whine if you try to get the wrong
333 * storage type. This function is instead robust against that,
334 * so that GUI builders don't have to jump through hoops
341 if (image->storage_type != GTK_IMAGE_PIXBUF)
342 g_value_set_object (value, NULL);
344 g_value_set_object (value,
345 gtk_image_get_pixbuf (image));
348 if (image->storage_type != GTK_IMAGE_PIXMAP)
349 g_value_set_object (value, NULL);
351 g_value_set_object (value,
352 image->data.pixmap.pixmap);
355 g_value_set_object (value, image->mask);
358 if (image->storage_type != GTK_IMAGE_IMAGE)
359 g_value_set_object (value, NULL);
361 g_value_set_object (value,
362 image->data.image.image);
365 if (image->storage_type != GTK_IMAGE_STOCK)
366 g_value_set_string (value, NULL);
368 g_value_set_string (value,
369 image->data.stock.stock_id);
372 if (image->storage_type != GTK_IMAGE_ICON_SET)
373 g_value_set_boxed (value, NULL);
375 g_value_set_boxed (value,
376 image->data.icon_set.icon_set);
379 g_value_set_int (value, image->icon_size);
381 case PROP_PIXBUF_ANIMATION:
382 if (image->storage_type != GTK_IMAGE_ANIMATION)
383 g_value_set_object (value, NULL);
385 g_value_set_object (value,
386 image->data.anim.anim);
388 case PROP_STORAGE_TYPE:
389 g_value_set_enum (value, image->storage_type);
393 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
400 * gtk_image_new_from_pixmap:
401 * @pixmap: a #GdkPixmap, or %NULL
402 * @mask: a #GdkBitmap, or %NULL
404 * Creates a #GtkImage widget displaying @pixmap with a @mask.
405 * A #GdkImage is a server-side image buffer in the pixel format of the
406 * current display. The #GtkImage does not assume a reference to the
407 * pixmap or mask; you still need to unref them if you own references.
408 * #GtkImage will add its own reference rather than adopting yours.
410 * Return value: a new #GtkImage
413 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
418 image = g_object_new (GTK_TYPE_IMAGE, NULL);
420 gtk_image_set_from_pixmap (image, pixmap, mask);
422 return GTK_WIDGET (image);
426 * gtk_image_new_from_image:
427 * @image: a #GdkImage, or %NULL
428 * @mask: a #GdkBitmap, or %NULL
430 * Creates a #GtkImage widget displaying a @image with a @mask.
431 * A #GdkImage is a client-side image buffer in the pixel format of the
433 * The #GtkImage does not assume a reference to the
434 * image or mask; you still need to unref them if you own references.
435 * #GtkImage will add its own reference rather than adopting yours.
437 * Return value: a new #GtkImage
440 gtk_image_new_from_image (GdkImage *gdk_image,
445 image = g_object_new (GTK_TYPE_IMAGE, NULL);
447 gtk_image_set_from_image (image, gdk_image, mask);
449 return GTK_WIDGET (image);
453 * gtk_image_new_from_file:
454 * @filename: a filename
456 * Creates a new #GtkImage displaying the file @filename. If the file
457 * isn't found or can't be loaded, the resulting #GtkImage will
458 * display a "broken image" icon. This function never returns %NULL,
459 * it always returns a valid #GtkImage widget.
461 * If the file contains an animation, the image will contain an
464 * If you need to detect failures to load the file, use
465 * gdk_pixbuf_new_from_file() to load the file yourself, then create
466 * the #GtkImage from the pixbuf. (Or for animations, use
467 * gdk_pixbuf_animation_new_from_file()).
469 * The storage type (gtk_image_get_storage_type()) of the returned
470 * image is not defined, it will be whatever is appropriate for
471 * displaying the file.
473 * Return value: a new #GtkImage
476 gtk_image_new_from_file (const gchar *filename)
480 image = g_object_new (GTK_TYPE_IMAGE, NULL);
482 gtk_image_set_from_file (image, filename);
484 return GTK_WIDGET (image);
488 * gtk_image_new_from_pixbuf:
489 * @pixbuf: a #GdkPixbuf, or %NULL
491 * Creates a new #GtkImage displaying @pixbuf.
492 * The #GtkImage does not assume a reference to the
493 * pixbuf; you still need to unref it if you own references.
494 * #GtkImage will add its own reference rather than adopting yours.
496 * Note that this function just creates an #GtkImage from the pixbuf. The
497 * #GtkImage created will not react to state changes. Should you want that, you
498 * should use gtk_image_new_from_icon_set().
500 * Return value: a new #GtkImage
503 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
507 image = g_object_new (GTK_TYPE_IMAGE, NULL);
509 gtk_image_set_from_pixbuf (image, pixbuf);
511 return GTK_WIDGET (image);
515 * gtk_image_new_from_stock:
516 * @stock_id: a stock icon name
517 * @size: a stock icon size
519 * Creates a #GtkImage displaying a stock icon. Sample stock icon
520 * names are #GTK_STOCK_OPEN, #GTK_STOCK_EXIT. Sample stock sizes
521 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
522 * icon name isn't known, a "broken image" icon will be displayed instead.
523 * You can register your own stock icon names, see
524 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
526 * Return value: a new #GtkImage displaying the stock icon
529 gtk_image_new_from_stock (const gchar *stock_id,
534 image = g_object_new (GTK_TYPE_IMAGE, NULL);
536 gtk_image_set_from_stock (image, stock_id, size);
538 return GTK_WIDGET (image);
542 * gtk_image_new_from_icon_set:
543 * @icon_set: a #GtkIconSet
544 * @size: a stock icon size
546 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
547 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
548 * this function, usually it's better to create a #GtkIconFactory, put
549 * your icon sets in the icon factory, add the icon factory to the
550 * list of default factories with gtk_icon_factory_add_default(), and
551 * then use gtk_image_new_from_stock(). This will allow themes to
552 * override the icon you ship with your application.
554 * The #GtkImage does not assume a reference to the
555 * icon set; you still need to unref it if you own references.
556 * #GtkImage will add its own reference rather than adopting yours.
559 * Return value: a new #GtkImage
562 gtk_image_new_from_icon_set (GtkIconSet *icon_set,
567 image = g_object_new (GTK_TYPE_IMAGE, NULL);
569 gtk_image_set_from_icon_set (image, icon_set, size);
571 return GTK_WIDGET (image);
575 * gtk_image_new_from_animation:
576 * @animation: an animation
578 * Creates a #GtkImage displaying the given animation.
579 * The #GtkImage does not assume a reference to the
580 * animation; you still need to unref it if you own references.
581 * #GtkImage will add its own reference rather than adopting yours.
583 * Return value: a new #GtkImage widget
586 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
590 g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
592 image = g_object_new (GTK_TYPE_IMAGE, NULL);
594 gtk_image_set_from_animation (image, animation);
596 return GTK_WIDGET (image);
600 * gtk_image_set_from_pixmap:
601 * @image: a #GtkImage
602 * @pixmap: a #GdkPixmap or %NULL
603 * @mask: a #GdkBitmap or %NULL
605 * See gtk_image_new_from_pixmap() for details.
609 gtk_image_set_from_pixmap (GtkImage *image,
613 g_return_if_fail (GTK_IS_IMAGE (image));
614 g_return_if_fail (pixmap == NULL ||
615 GDK_IS_PIXMAP (pixmap));
616 g_return_if_fail (mask == NULL ||
617 GDK_IS_PIXMAP (mask));
619 g_object_freeze_notify (G_OBJECT (image));
622 g_object_ref (pixmap);
627 gtk_image_reset (image);
636 image->storage_type = GTK_IMAGE_PIXMAP;
638 image->data.pixmap.pixmap = pixmap;
640 gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
642 gtk_image_update_size (image, width, height);
645 g_object_notify (G_OBJECT (image), "pixmap");
646 g_object_notify (G_OBJECT (image), "mask");
648 g_object_thaw_notify (G_OBJECT (image));
652 * gtk_image_set_from_image:
653 * @image: a #GtkImage
654 * @gdk_image: a #GdkImage or %NULL
655 * @mask: a #GdkBitmap or %NULL
657 * See gtk_image_new_from_image() for details.
661 gtk_image_set_from_image (GtkImage *image,
665 g_return_if_fail (GTK_IS_IMAGE (image));
666 g_return_if_fail (gdk_image == NULL ||
667 GDK_IS_IMAGE (gdk_image));
668 g_return_if_fail (mask == NULL ||
669 GDK_IS_PIXMAP (mask));
671 g_object_freeze_notify (G_OBJECT (image));
674 g_object_ref (gdk_image);
679 gtk_image_reset (image);
683 image->storage_type = GTK_IMAGE_IMAGE;
685 image->data.image.image = gdk_image;
688 gtk_image_update_size (image, gdk_image->width, gdk_image->height);
692 /* Clean up the mask if gdk_image was NULL */
694 g_object_unref (mask);
697 g_object_notify (G_OBJECT (image), "image");
698 g_object_notify (G_OBJECT (image), "mask");
700 g_object_thaw_notify (G_OBJECT (image));
704 * gtk_image_set_from_file:
705 * @image: a #GtkImage
706 * @filename: a filename or %NULL
708 * See gtk_image_new_from_file() for details.
712 gtk_image_set_from_file (GtkImage *image,
713 const gchar *filename)
715 GdkPixbufAnimation *anim;
717 g_return_if_fail (GTK_IS_IMAGE (image));
719 g_object_freeze_notify (G_OBJECT (image));
721 gtk_image_reset (image);
723 if (filename == NULL)
725 g_object_thaw_notify (G_OBJECT (image));
729 anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
733 gtk_image_set_from_stock (image,
734 GTK_STOCK_MISSING_IMAGE,
735 GTK_ICON_SIZE_BUTTON);
736 g_object_thaw_notify (G_OBJECT (image));
740 /* We could just unconditionally set_from_animation,
741 * but it's nicer for memory if we toss the animation
742 * if it's just a single pixbuf
745 if (gdk_pixbuf_animation_is_static_image (anim))
747 gtk_image_set_from_pixbuf (image,
748 gdk_pixbuf_animation_get_static_image (anim));
752 gtk_image_set_from_animation (image, anim);
755 g_object_unref (anim);
757 g_object_thaw_notify (G_OBJECT (image));
761 * gtk_image_set_from_pixbuf:
762 * @image: a #GtkImage
763 * @pixbuf: a #GdkPixbuf or %NULL
765 * See gtk_image_new_from_pixbuf() for details.
769 gtk_image_set_from_pixbuf (GtkImage *image,
772 g_return_if_fail (GTK_IS_IMAGE (image));
773 g_return_if_fail (pixbuf == NULL ||
774 GDK_IS_PIXBUF (pixbuf));
776 g_object_freeze_notify (G_OBJECT (image));
779 g_object_ref (pixbuf);
781 gtk_image_reset (image);
785 image->storage_type = GTK_IMAGE_PIXBUF;
787 image->data.pixbuf.pixbuf = pixbuf;
789 gtk_image_update_size (image,
790 gdk_pixbuf_get_width (pixbuf),
791 gdk_pixbuf_get_height (pixbuf));
794 g_object_notify (G_OBJECT (image), "pixbuf");
796 g_object_thaw_notify (G_OBJECT (image));
800 * gtk_image_set_from_stock:
801 * @image: a #GtkImage
802 * @stock_id: a stock icon name
803 * @size: a stock icon size
805 * See gtk_image_new_from_stock() for details.
809 gtk_image_set_from_stock (GtkImage *image,
810 const gchar *stock_id,
815 g_return_if_fail (GTK_IS_IMAGE (image));
817 g_object_freeze_notify (G_OBJECT (image));
819 /* in case stock_id == image->data.stock.stock_id */
820 new_id = g_strdup (stock_id);
822 gtk_image_reset (image);
826 image->storage_type = GTK_IMAGE_STOCK;
828 image->data.stock.stock_id = new_id;
829 image->icon_size = size;
831 /* Size is demand-computed in size request method
832 * if we're a stock image, since changing the
833 * style impacts the size request
837 g_object_notify (G_OBJECT (image), "stock");
838 g_object_notify (G_OBJECT (image), "icon_size");
840 g_object_thaw_notify (G_OBJECT (image));
844 * gtk_image_set_from_icon_set:
845 * @image: a #GtkImage
846 * @icon_set: a #GtkIconSet
847 * @size: a stock icon size
849 * See gtk_image_new_from_icon_set() for details.
853 gtk_image_set_from_icon_set (GtkImage *image,
854 GtkIconSet *icon_set,
857 g_return_if_fail (GTK_IS_IMAGE (image));
859 g_object_freeze_notify (G_OBJECT (image));
862 gtk_icon_set_ref (icon_set);
864 gtk_image_reset (image);
868 image->storage_type = GTK_IMAGE_ICON_SET;
870 image->data.icon_set.icon_set = icon_set;
871 image->icon_size = size;
873 /* Size is demand-computed in size request method
874 * if we're an icon set
878 g_object_notify (G_OBJECT (image), "icon_set");
879 g_object_notify (G_OBJECT (image), "icon_size");
881 g_object_thaw_notify (G_OBJECT (image));
885 * gtk_image_set_from_animation:
886 * @image: a #GtkImage
887 * @animation: the #GdkPixbufAnimation
889 * Causes the #GtkImage to display the given animation (or display
890 * nothing, if you set the animation to %NULL).
893 gtk_image_set_from_animation (GtkImage *image,
894 GdkPixbufAnimation *animation)
896 g_return_if_fail (GTK_IS_IMAGE (image));
897 g_return_if_fail (animation == NULL ||
898 GDK_IS_PIXBUF_ANIMATION (animation));
900 g_object_freeze_notify (G_OBJECT (image));
903 g_object_ref (animation);
905 gtk_image_reset (image);
907 if (animation != NULL)
909 image->storage_type = GTK_IMAGE_ANIMATION;
911 image->data.anim.anim = animation;
912 image->data.anim.frame_timeout = 0;
913 image->data.anim.iter = NULL;
915 gtk_image_update_size (image,
916 gdk_pixbuf_animation_get_width (animation),
917 gdk_pixbuf_animation_get_height (animation));
920 g_object_notify (G_OBJECT (image), "pixbuf_animation");
922 g_object_thaw_notify (G_OBJECT (image));
926 * gtk_image_get_storage_type:
927 * @image: a #GtkImage
929 * Gets the type of representation being used by the #GtkImage
930 * to store image data. If the #GtkImage has no image data,
931 * the return value will be %GTK_IMAGE_EMPTY.
933 * Return value: image representation being used
936 gtk_image_get_storage_type (GtkImage *image)
938 g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
940 return image->storage_type;
944 * gtk_image_get_pixmap:
945 * @image: a #GtkImage
946 * @pixmap: location to store the pixmap, or %NULL
947 * @mask: location to store the mask, or %NULL
949 * Gets the pixmap and mask being displayed by the #GtkImage.
950 * The storage type of the image must be %GTK_IMAGE_EMPTY or
951 * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
952 * The caller of this function does not own a reference to the
953 * returned pixmap and mask.
957 gtk_image_get_pixmap (GtkImage *image,
961 g_return_if_fail (GTK_IS_IMAGE (image));
962 g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
963 image->storage_type == GTK_IMAGE_EMPTY);
966 *pixmap = image->data.pixmap.pixmap;
973 * gtk_image_get_image:
974 * @image: a #GtkImage
975 * @gdk_image: return location for a #GtkImage
976 * @mask: return location for a #GdkBitmap
978 * Gets the #GdkImage and mask being displayed by the #GtkImage.
979 * The storage type of the image must be %GTK_IMAGE_EMPTY or
980 * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
981 * The caller of this function does not own a reference to the
982 * returned image and mask.
985 gtk_image_get_image (GtkImage *image,
986 GdkImage **gdk_image,
989 g_return_if_fail (GTK_IS_IMAGE (image));
990 g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
991 image->storage_type == GTK_IMAGE_EMPTY);
994 *gdk_image = image->data.image.image;
1001 * gtk_image_get_pixbuf:
1002 * @image: a #GtkImage
1005 * Gets the #GdkPixbuf being displayed by the #GtkImage.
1006 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1007 * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1008 * The caller of this function does not own a reference to the
1011 * Return value: the displayed pixbuf, or %NULL if the image is empty
1014 gtk_image_get_pixbuf (GtkImage *image)
1016 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1017 g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
1018 image->storage_type == GTK_IMAGE_EMPTY, NULL);
1020 if (image->storage_type == GTK_IMAGE_EMPTY)
1021 image->data.pixbuf.pixbuf = NULL;
1023 return image->data.pixbuf.pixbuf;
1027 * gtk_image_get_stock:
1028 * @image: a #GtkImage
1029 * @stock_id: place to store a stock icon name
1030 * @size: place to store a stock icon size
1032 * Gets the stock icon name and size being displayed by the #GtkImage.
1033 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1034 * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1035 * The returned string is owned by the #GtkImage and should not
1040 gtk_image_get_stock (GtkImage *image,
1044 g_return_if_fail (GTK_IS_IMAGE (image));
1045 g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
1046 image->storage_type == GTK_IMAGE_EMPTY);
1048 if (image->storage_type == GTK_IMAGE_EMPTY)
1049 image->data.stock.stock_id = NULL;
1052 *stock_id = image->data.stock.stock_id;
1055 *size = image->icon_size;
1059 * gtk_image_get_icon_set:
1060 * @image: a #GtkImage
1061 * @icon_set: location to store a #GtkIconSet
1062 * @size: location to store a stock icon size
1064 * Gets the icon set and size being displayed by the #GtkImage.
1065 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1066 * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1070 gtk_image_get_icon_set (GtkImage *image,
1071 GtkIconSet **icon_set,
1074 g_return_if_fail (GTK_IS_IMAGE (image));
1075 g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
1076 image->storage_type == GTK_IMAGE_EMPTY);
1079 *icon_set = image->data.icon_set.icon_set;
1082 *size = image->icon_size;
1086 * gtk_image_get_animation:
1087 * @image: a #GtkImage
1090 * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1091 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1092 * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1093 * The caller of this function does not own a reference to the
1094 * returned animation.
1096 * Return value: the displayed animation, or %NULL if the image is empty
1099 gtk_image_get_animation (GtkImage *image)
1101 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1102 g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
1103 image->storage_type == GTK_IMAGE_EMPTY,
1106 if (image->storage_type == GTK_IMAGE_EMPTY)
1107 image->data.anim.anim = NULL;
1109 return image->data.anim.anim;
1115 * Creates a new empty #GtkImage widget.
1117 * Return value: a newly created #GtkImage widget.
1120 gtk_image_new (void)
1122 return g_object_new (GTK_TYPE_IMAGE, NULL);
1126 gtk_image_set (GtkImage *image,
1130 g_return_if_fail (GTK_IS_IMAGE (image));
1132 gtk_image_set_from_image (image, val, mask);
1136 gtk_image_get (GtkImage *image,
1140 g_return_if_fail (GTK_IS_IMAGE (image));
1142 gtk_image_get_image (image, val, mask);
1146 gtk_image_reset_anim_iter (GtkImage *image)
1148 if (image->storage_type == GTK_IMAGE_ANIMATION)
1150 /* Reset the animation */
1152 if (image->data.anim.frame_timeout)
1154 g_source_remove (image->data.anim.frame_timeout);
1155 image->data.anim.frame_timeout = 0;
1158 if (image->data.anim.iter)
1160 g_object_unref (image->data.anim.iter);
1161 image->data.anim.iter = NULL;
1167 gtk_image_unmap (GtkWidget *widget)
1169 gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1171 if (GTK_WIDGET_CLASS (parent_class)->unmap)
1172 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1176 gtk_image_unrealize (GtkWidget *widget)
1178 gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1180 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1181 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
1185 animation_timeout (gpointer data)
1189 GDK_THREADS_ENTER ();
1191 image = GTK_IMAGE (data);
1193 image->data.anim.frame_timeout = 0;
1195 gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);
1197 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1198 image->data.anim.frame_timeout =
1199 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1203 gtk_widget_queue_draw (GTK_WIDGET (image));
1205 GDK_THREADS_LEAVE ();
1211 gtk_image_expose (GtkWidget *widget,
1212 GdkEventExpose *event)
1214 g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1215 g_return_val_if_fail (event != NULL, FALSE);
1217 if (GTK_WIDGET_MAPPED (widget) &&
1218 GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
1222 GdkRectangle area, image_bound;
1227 gboolean needs_state_transform;
1229 image = GTK_IMAGE (widget);
1230 misc = GTK_MISC (widget);
1234 /* For stock items and icon sets, we lazily calculate
1235 * the size; we might get here between a queue_resize()
1236 * and size_request() if something explicitely forces
1239 if (widget->requisition.width == 0 && widget->requisition.height == 0)
1240 gtk_image_calc_size (image);
1242 if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
1245 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1246 xalign = misc->xalign;
1248 xalign = 1.0 - misc->xalign;
1250 x = floor (widget->allocation.x + misc->xpad
1251 + ((widget->allocation.width - widget->requisition.width) * xalign)
1253 y = floor (widget->allocation.y + misc->ypad
1254 + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1259 image_bound.width = 0;
1260 image_bound.height = 0;
1264 needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
1266 switch (image->storage_type)
1268 case GTK_IMAGE_PIXMAP:
1270 gdk_drawable_get_size (image->data.pixmap.pixmap,
1272 &image_bound.height);
1274 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1275 needs_state_transform)
1277 pixbuf = gdk_pixbuf_get_from_drawable (NULL,
1278 image->data.pixmap.pixmap,
1279 gtk_widget_get_colormap (widget),
1280 image_bound.x - x, image_bound.y - y,
1283 image_bound.height);
1291 case GTK_IMAGE_IMAGE:
1293 image_bound.width = image->data.image.image->width;
1294 image_bound.height = image->data.image.image->height;
1296 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1297 needs_state_transform)
1299 pixbuf = gdk_pixbuf_get_from_image (NULL,
1300 image->data.image.image,
1301 gtk_widget_get_colormap (widget),
1302 image_bound.x - x, image_bound.y - y,
1305 image_bound.height);
1312 case GTK_IMAGE_PIXBUF:
1313 image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
1314 image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);
1316 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1317 needs_state_transform)
1319 pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf,
1320 image_bound.x - x, image_bound.y - y,
1321 image_bound.width, image_bound.height);
1328 pixbuf = image->data.pixbuf.pixbuf;
1329 g_object_ref (pixbuf);
1333 case GTK_IMAGE_STOCK:
1334 pixbuf = gtk_widget_render_icon (widget,
1335 image->data.stock.stock_id,
1340 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1341 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1345 needs_state_transform = FALSE;
1348 case GTK_IMAGE_ICON_SET:
1350 gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1352 gtk_widget_get_direction (widget),
1353 GTK_WIDGET_STATE (widget),
1360 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1361 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1365 needs_state_transform = FALSE;
1368 case GTK_IMAGE_ANIMATION:
1370 if (image->data.anim.iter == NULL)
1372 image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL);
1374 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1375 image->data.anim.frame_timeout =
1376 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1381 image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim);
1382 image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim);
1384 /* don't advance the anim iter here, or we could get frame changes between two
1385 * exposes of different areas.
1388 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter);
1389 g_object_ref (pixbuf);
1393 case GTK_IMAGE_EMPTY:
1394 g_assert_not_reached ();
1400 gdk_gc_set_clip_mask (widget->style->black_gc, mask);
1401 gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
1404 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound))
1408 if (needs_state_transform)
1410 GtkIconSource *source;
1411 GdkPixbuf *rendered;
1413 source = gtk_icon_source_new ();
1414 gtk_icon_source_set_pixbuf (source, pixbuf);
1415 /* The size here is arbitrary; since size isn't
1416 * wildcarded in the souce, it isn't supposed to be
1417 * scaled by the engine function
1419 gtk_icon_source_set_size (source,
1420 GTK_ICON_SIZE_SMALL_TOOLBAR);
1421 gtk_icon_source_set_size_wildcarded (source, FALSE);
1423 rendered = gtk_style_render_icon (widget->style,
1425 gtk_widget_get_direction (widget),
1426 GTK_WIDGET_STATE (widget),
1432 gtk_icon_source_free (source);
1434 g_object_unref (pixbuf);
1440 gdk_draw_pixbuf (widget->window,
1441 widget->style->black_gc,
1449 GDK_RGB_DITHER_NORMAL,
1452 g_object_unref (pixbuf);
1458 switch (image->storage_type)
1460 case GTK_IMAGE_PIXMAP:
1461 gdk_draw_drawable (widget->window,
1462 widget->style->black_gc,
1463 image->data.pixmap.pixmap,
1464 image_bound.x - x, image_bound.y - y,
1465 image_bound.x, image_bound.y,
1466 image_bound.width, image_bound.height);
1469 case GTK_IMAGE_IMAGE:
1470 gdk_draw_image (widget->window,
1471 widget->style->black_gc,
1472 image->data.image.image,
1473 image_bound.x - x, image_bound.y - y,
1474 image_bound.x, image_bound.y,
1475 image_bound.width, image_bound.height);
1478 case GTK_IMAGE_PIXBUF:
1479 case GTK_IMAGE_STOCK:
1480 case GTK_IMAGE_ICON_SET:
1481 case GTK_IMAGE_ANIMATION:
1482 case GTK_IMAGE_EMPTY:
1483 g_assert_not_reached ();
1487 } /* if rectangle intersects */
1491 gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
1492 gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
1495 } /* if widget is drawable */
1501 gtk_image_clear (GtkImage *image)
1503 g_object_freeze_notify (G_OBJECT (image));
1505 if (image->storage_type != GTK_IMAGE_EMPTY)
1506 g_object_notify (G_OBJECT (image), "storage_type");
1510 g_object_unref (image->mask);
1512 g_object_notify (G_OBJECT (image), "mask");
1515 if (image->icon_size != DEFAULT_ICON_SIZE)
1517 image->icon_size = DEFAULT_ICON_SIZE;
1518 g_object_notify (G_OBJECT (image), "icon_size");
1521 switch (image->storage_type)
1523 case GTK_IMAGE_PIXMAP:
1525 if (image->data.pixmap.pixmap)
1526 g_object_unref (image->data.pixmap.pixmap);
1527 image->data.pixmap.pixmap = NULL;
1529 g_object_notify (G_OBJECT (image), "pixmap");
1533 case GTK_IMAGE_IMAGE:
1535 if (image->data.image.image)
1536 g_object_unref (image->data.image.image);
1537 image->data.image.image = NULL;
1539 g_object_notify (G_OBJECT (image), "image");
1543 case GTK_IMAGE_PIXBUF:
1545 if (image->data.pixbuf.pixbuf)
1546 g_object_unref (image->data.pixbuf.pixbuf);
1548 g_object_notify (G_OBJECT (image), "pixbuf");
1552 case GTK_IMAGE_STOCK:
1554 g_free (image->data.stock.stock_id);
1556 image->data.stock.stock_id = NULL;
1558 g_object_notify (G_OBJECT (image), "stock");
1561 case GTK_IMAGE_ICON_SET:
1562 if (image->data.icon_set.icon_set)
1563 gtk_icon_set_unref (image->data.icon_set.icon_set);
1564 image->data.icon_set.icon_set = NULL;
1566 g_object_notify (G_OBJECT (image), "icon_set");
1569 case GTK_IMAGE_ANIMATION:
1570 if (image->data.anim.frame_timeout)
1571 g_source_remove (image->data.anim.frame_timeout);
1573 if (image->data.anim.anim)
1574 g_object_unref (image->data.anim.anim);
1576 image->data.anim.frame_timeout = 0;
1577 image->data.anim.anim = NULL;
1579 g_object_notify (G_OBJECT (image), "pixbuf_animation");
1583 case GTK_IMAGE_EMPTY:
1589 image->storage_type = GTK_IMAGE_EMPTY;
1591 memset (&image->data, '\0', sizeof (image->data));
1593 g_object_thaw_notify (G_OBJECT (image));
1597 gtk_image_reset (GtkImage *image)
1599 gtk_image_clear (image);
1601 gtk_image_update_size (image, 0, 0);
1605 gtk_image_calc_size (GtkImage *image)
1607 GtkWidget *widget = GTK_WIDGET (image);
1608 GdkPixbuf *pixbuf = NULL;
1610 /* We update stock/icon set on every size request, because
1611 * the theme could have affected the size; for other kinds of
1612 * image, we just update the requisition when the image data
1615 switch (image->storage_type)
1617 case GTK_IMAGE_STOCK:
1618 pixbuf = gtk_widget_render_icon (widget,
1619 image->data.stock.stock_id,
1624 case GTK_IMAGE_ICON_SET:
1625 pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1627 gtk_widget_get_direction (widget),
1628 GTK_WIDGET_STATE (widget),
1640 widget->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2;
1641 widget->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2;
1643 g_object_unref (pixbuf);
1648 gtk_image_size_request (GtkWidget *widget,
1649 GtkRequisition *requisition)
1653 image = GTK_IMAGE (widget);
1655 gtk_image_calc_size (image);
1657 /* Chain up to default that simply reads current requisition */
1658 GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
1662 gtk_image_update_size (GtkImage *image,
1666 GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
1667 GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
1669 if (GTK_WIDGET_VISIBLE (image))
1670 gtk_widget_queue_resize (GTK_WIDGET (image));