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_size_request (GtkWidget *widget,
43 GtkRequisition *requisition);
44 static void gtk_image_destroy (GtkObject *object);
45 static void gtk_image_clear (GtkImage *image);
46 static void gtk_image_reset (GtkImage *image);
47 static void gtk_image_update_size (GtkImage *image,
51 static void gtk_image_set_property (GObject *object,
55 static void gtk_image_get_property (GObject *object,
60 static gpointer parent_class;
73 PROP_PIXBUF_ANIMATION,
78 gtk_image_get_type (void)
80 static GtkType image_type = 0;
84 static const GtkTypeInfo image_info =
88 sizeof (GtkImageClass),
89 (GtkClassInitFunc) gtk_image_class_init,
90 (GtkObjectInitFunc) gtk_image_init,
91 /* reserved_1 */ NULL,
92 /* reserved_2 */ NULL,
93 (GtkClassInitFunc) NULL,
96 image_type = gtk_type_unique (GTK_TYPE_MISC, &image_info);
103 gtk_image_class_init (GtkImageClass *class)
105 GObjectClass *gobject_class;
106 GtkObjectClass *object_class;
107 GtkWidgetClass *widget_class;
109 parent_class = g_type_class_peek_parent (class);
111 gobject_class = G_OBJECT_CLASS (class);
113 gobject_class->set_property = gtk_image_set_property;
114 gobject_class->get_property = gtk_image_get_property;
116 object_class = GTK_OBJECT_CLASS (class);
118 object_class->destroy = gtk_image_destroy;
120 widget_class = GTK_WIDGET_CLASS (class);
122 widget_class->expose_event = gtk_image_expose;
123 widget_class->size_request = gtk_image_size_request;
124 widget_class->unmap = gtk_image_unmap;
126 g_object_class_install_property (gobject_class,
128 g_param_spec_object ("pixbuf",
130 _("A GdkPixbuf to display."),
134 g_object_class_install_property (gobject_class,
136 g_param_spec_object ("pixmap",
138 _("A GdkPixmap to display."),
142 g_object_class_install_property (gobject_class,
144 g_param_spec_object ("image",
146 _("A GdkImage to display."),
150 g_object_class_install_property (gobject_class,
152 g_param_spec_object ("mask",
154 _("Mask bitmap to use with GdkImage or GdkPixmap"),
158 g_object_class_install_property (gobject_class,
160 g_param_spec_string ("file",
162 _("Filename to load and display."),
167 g_object_class_install_property (gobject_class,
169 g_param_spec_string ("stock",
171 _("Stock ID for a stock image to display."),
175 g_object_class_install_property (gobject_class,
177 g_param_spec_boxed ("icon_set",
179 _("Icon set to display."),
183 g_object_class_install_property (gobject_class,
185 g_param_spec_int ("icon_size",
187 _("Size to use for stock icon or icon set."),
192 g_object_class_install_property (gobject_class,
193 PROP_PIXBUF_ANIMATION,
194 g_param_spec_object ("pixbuf_animation",
196 _("GdkPixbufAnimation to display."),
197 GDK_TYPE_PIXBUF_ANIMATION,
200 g_object_class_install_property (gobject_class,
202 g_param_spec_enum ("storage_type",
204 _("The representation being used for image data."),
211 gtk_image_init (GtkImage *image)
213 GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
215 image->storage_type = GTK_IMAGE_EMPTY;
216 image->icon_size = DEFAULT_ICON_SIZE;
221 gtk_image_destroy (GtkObject *object)
223 GtkImage *image = GTK_IMAGE (object);
225 gtk_image_clear (image);
227 GTK_OBJECT_CLASS (parent_class)->destroy (object);
231 gtk_image_set_property (GObject *object,
238 image = GTK_IMAGE (object);
243 gtk_image_set_from_pixbuf (image,
244 g_value_get_object (value));
247 gtk_image_set_from_pixmap (image,
248 g_value_get_object (value),
252 gtk_image_set_from_image (image,
253 g_value_get_object (value),
257 if (image->storage_type == GTK_IMAGE_PIXMAP)
258 gtk_image_set_from_pixmap (image,
259 image->data.pixmap.pixmap,
260 g_value_get_object (value));
261 else if (image->storage_type == GTK_IMAGE_IMAGE)
262 gtk_image_set_from_image (image,
263 image->data.image.image,
264 g_value_get_object (value));
269 mask = g_value_get_object (value);
272 g_object_ref (G_OBJECT (mask));
274 gtk_image_reset (image);
280 gtk_image_set_from_file (image,
281 g_value_get_string (value));
284 gtk_image_set_from_stock (image, g_value_get_string (value),
288 gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
292 if (image->storage_type == GTK_IMAGE_STOCK)
293 gtk_image_set_from_stock (image,
294 image->data.stock.stock_id,
295 g_value_get_int (value));
296 else if (image->storage_type == GTK_IMAGE_ICON_SET)
297 gtk_image_set_from_icon_set (image,
298 image->data.icon_set.icon_set,
299 g_value_get_int (value));
301 /* Save to be used when STOCK or ICON_SET property comes in */
302 image->icon_size = g_value_get_int (value);
304 case PROP_PIXBUF_ANIMATION:
305 gtk_image_set_from_animation (image,
306 g_value_get_object (value));
310 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
316 gtk_image_get_property (GObject *object,
323 image = GTK_IMAGE (object);
325 /* The "getter" functions whine if you try to get the wrong
326 * storage type. This function is instead robust against that,
327 * so that GUI builders don't have to jump through hoops
334 if (image->storage_type != GTK_IMAGE_PIXBUF)
335 g_value_set_object (value, NULL);
337 g_value_set_object (value,
338 gtk_image_get_pixbuf (image));
341 if (image->storage_type != GTK_IMAGE_PIXMAP)
342 g_value_set_object (value, NULL);
344 g_value_set_object (value,
345 image->data.pixmap.pixmap);
348 g_value_set_object (value, image->mask);
351 if (image->storage_type != GTK_IMAGE_IMAGE)
352 g_value_set_object (value, NULL);
354 g_value_set_object (value,
355 image->data.image.image);
358 if (image->storage_type != GTK_IMAGE_STOCK)
359 g_value_set_string (value, NULL);
361 g_value_set_string (value,
362 image->data.stock.stock_id);
365 if (image->storage_type != GTK_IMAGE_ICON_SET)
366 g_value_set_boxed (value, NULL);
368 g_value_set_boxed (value,
369 image->data.icon_set.icon_set);
372 g_value_set_int (value, image->icon_size);
374 case PROP_PIXBUF_ANIMATION:
375 if (image->storage_type != GTK_IMAGE_ANIMATION)
376 g_value_set_object (value, NULL);
378 g_value_set_object (value,
379 image->data.anim.anim);
381 case PROP_STORAGE_TYPE:
382 g_value_set_enum (value, image->storage_type);
386 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
393 * gtk_image_new_from_pixmap:
394 * @pixmap: a #GdkPixmap, or %NULL
395 * @mask: a #GdkBitmap, or %NULL
397 * Creates a #GtkImage widget displaying @pixmap with a @mask.
398 * A #GdkImage is a server-side image buffer in the pixel format of the
399 * current display. The #GtkImage does not assume a reference to the
400 * pixmap or mask; you still need to unref them if you own references.
401 * #GtkImage will add its own reference rather than adopting yours.
403 * Return value: a new #GtkImage
406 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
411 image = gtk_type_new (GTK_TYPE_IMAGE);
413 gtk_image_set_from_pixmap (image, pixmap, mask);
415 return GTK_WIDGET (image);
419 * gtk_image_new_from_image:
420 * @image: a #GdkImage, or %NULL
421 * @mask: a #GdkBitmap, or %NULL
423 * Creates a #GtkImage widget displaying a @image with a @mask.
424 * A #GdkImage is a client-side image buffer in the pixel format of the
426 * The #GtkImage does not assume a reference to the
427 * image or mask; you still need to unref them if you own references.
428 * #GtkImage will add its own reference rather than adopting yours.
430 * Return value: a new #GtkImage
433 gtk_image_new_from_image (GdkImage *gdk_image,
438 image = gtk_type_new (GTK_TYPE_IMAGE);
440 gtk_image_set_from_image (image, gdk_image, mask);
442 return GTK_WIDGET (image);
446 * gtk_image_new_from_file:
447 * @filename: a filename
449 * Creates a new #GtkImage displaying the file @filename. If the file
450 * isn't found or can't be loaded, the resulting #GtkImage will
451 * display a "broken image" icon. This function never returns %NULL,
452 * it always returns a valid #GtkImage widget.
454 * If the file contains an animation, the image will contain an
457 * If you need to detect failures to load the file, use
458 * gdk_pixbuf_new_from_file() to load the file yourself, then create
459 * the #GtkImage from the pixbuf. (Or for animations, use
460 * gdk_pixbuf_animation_new_from_file()).
462 * The storage type (gtk_image_get_storage_type()) of the returned
463 * image is not defined, it will be whatever is appropriate for
464 * displaying the file.
466 * Return value: a new #GtkImage
469 gtk_image_new_from_file (const gchar *filename)
473 image = gtk_type_new (GTK_TYPE_IMAGE);
475 gtk_image_set_from_file (image, filename);
477 return GTK_WIDGET (image);
481 * gtk_image_new_from_pixbuf:
482 * @pixbuf: a #GdkPixbuf, or %NULL
484 * Creates a new #GtkImage displaying @pixbuf.
485 * The #GtkImage does not assume a reference to the
486 * pixbuf; you still need to unref it if you own references.
487 * #GtkImage will add its own reference rather than adopting yours.
489 * Note that this function just creates an #GtkImage from the pixbuf. The
490 * #GtkImage created will not react to state changes. Should you want that, you
491 * should use gtk_image_new_from_icon_set().
493 * Return value: a new #GtkImage
496 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
500 image = gtk_type_new (GTK_TYPE_IMAGE);
502 gtk_image_set_from_pixbuf (image, pixbuf);
504 return GTK_WIDGET (image);
508 * gtk_image_new_from_stock:
509 * @stock_id: a stock icon name
510 * @size: a stock icon size
512 * Creates a #GtkImage displaying a stock icon. Sample stock icon
513 * names are #GTK_STOCK_OPEN, #GTK_STOCK_EXIT. Sample stock sizes
514 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
515 * icon name isn't known, a "broken image" icon will be displayed instead.
516 * You can register your own stock icon names, see
517 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
519 * Return value: a new #GtkImage displaying the stock icon
522 gtk_image_new_from_stock (const gchar *stock_id,
527 image = gtk_type_new (GTK_TYPE_IMAGE);
529 gtk_image_set_from_stock (image, stock_id, size);
531 return GTK_WIDGET (image);
535 * gtk_image_new_from_icon_set:
536 * @icon_set: a #GtkIconSet
537 * @size: a stock icon size
539 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
540 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
541 * this function, usually it's better to create a #GtkIconFactory, put
542 * your icon sets in the icon factory, add the icon factory to the
543 * list of default factories with gtk_icon_factory_add_default(), and
544 * then use gtk_image_new_from_stock(). This will allow themes to
545 * override the icon you ship with your application.
547 * The #GtkImage does not assume a reference to the
548 * icon set; you still need to unref it if you own references.
549 * #GtkImage will add its own reference rather than adopting yours.
552 * Return value: a new #GtkImage
555 gtk_image_new_from_icon_set (GtkIconSet *icon_set,
560 image = gtk_type_new (GTK_TYPE_IMAGE);
562 gtk_image_set_from_icon_set (image, icon_set, size);
564 return GTK_WIDGET (image);
568 * gtk_image_new_from_animation:
569 * @animation: an animation
571 * Creates a #GtkImage displaying the given animation.
572 * The #GtkImage does not assume a reference to the
573 * animation; you still need to unref it if you own references.
574 * #GtkImage will add its own reference rather than adopting yours.
576 * Return value: a new #GtkImage widget
579 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
583 g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
585 image = gtk_type_new (GTK_TYPE_IMAGE);
587 gtk_image_set_from_animation (image, animation);
589 return GTK_WIDGET (image);
593 * gtk_image_set_from_pixmap:
594 * @image: a #GtkImage
595 * @pixmap: a #GdkPixmap or %NULL
596 * @mask: a #GdkBitmap or %NULL
598 * See gtk_image_new_from_pixmap() for details.
602 gtk_image_set_from_pixmap (GtkImage *image,
606 g_return_if_fail (GTK_IS_IMAGE (image));
607 g_return_if_fail (pixmap == NULL ||
608 GDK_IS_PIXMAP (pixmap));
609 g_return_if_fail (mask == NULL ||
610 GDK_IS_PIXMAP (mask));
612 g_object_freeze_notify (G_OBJECT (image));
615 g_object_ref (G_OBJECT (pixmap));
618 g_object_ref (G_OBJECT (mask));
620 gtk_image_reset (image);
629 image->storage_type = GTK_IMAGE_PIXMAP;
631 image->data.pixmap.pixmap = pixmap;
633 gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
635 gtk_image_update_size (image, width, height);
638 g_object_notify (G_OBJECT (image), "pixmap");
639 g_object_notify (G_OBJECT (image), "mask");
641 g_object_thaw_notify (G_OBJECT (image));
645 * gtk_image_set_from_image:
646 * @image: a #GtkImage
647 * @gdk_image: a #GdkImage or %NULL
648 * @mask: a #GdkBitmap or %NULL
650 * See gtk_image_new_from_image() for details.
654 gtk_image_set_from_image (GtkImage *image,
658 g_return_if_fail (GTK_IS_IMAGE (image));
659 g_return_if_fail (gdk_image == NULL ||
660 GDK_IS_IMAGE (gdk_image));
661 g_return_if_fail (mask == NULL ||
662 GDK_IS_PIXMAP (mask));
664 g_object_freeze_notify (G_OBJECT (image));
667 g_object_ref (G_OBJECT (gdk_image));
670 g_object_ref (G_OBJECT (mask));
672 gtk_image_reset (image);
676 image->storage_type = GTK_IMAGE_IMAGE;
678 image->data.image.image = gdk_image;
681 gtk_image_update_size (image, gdk_image->width, gdk_image->height);
685 /* Clean up the mask if gdk_image was NULL */
687 g_object_unref (G_OBJECT (mask));
690 g_object_notify (G_OBJECT (image), "image");
691 g_object_notify (G_OBJECT (image), "mask");
693 g_object_thaw_notify (G_OBJECT (image));
697 * gtk_image_set_from_file:
698 * @image: a #GtkImage
699 * @filename: a filename or %NULL
701 * See gtk_image_new_from_file() for details.
705 gtk_image_set_from_file (GtkImage *image,
706 const gchar *filename)
708 GdkPixbufAnimation *anim;
710 g_return_if_fail (GTK_IS_IMAGE (image));
711 g_return_if_fail (filename != NULL);
713 g_object_freeze_notify (G_OBJECT (image));
715 gtk_image_reset (image);
717 if (filename == NULL)
719 g_object_thaw_notify (G_OBJECT (image));
723 anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
727 gtk_image_set_from_stock (image,
728 GTK_STOCK_MISSING_IMAGE,
729 GTK_ICON_SIZE_BUTTON);
730 g_object_thaw_notify (G_OBJECT (image));
734 /* We could just unconditionally set_from_animation,
735 * but it's nicer for memory if we toss the animation
736 * if it's just a single pixbuf
739 if (gdk_pixbuf_animation_is_static_image (anim))
741 gtk_image_set_from_pixbuf (image,
742 gdk_pixbuf_animation_get_static_image (anim));
746 gtk_image_set_from_animation (image, anim);
749 g_object_unref (G_OBJECT (anim));
751 g_object_thaw_notify (G_OBJECT (image));
755 * gtk_image_set_from_pixbuf:
756 * @image: a #GtkImage
757 * @pixbuf: a #GdkPixbuf or %NULL
759 * See gtk_image_new_from_pixbuf() for details.
763 gtk_image_set_from_pixbuf (GtkImage *image,
766 g_return_if_fail (GTK_IS_IMAGE (image));
767 g_return_if_fail (pixbuf == NULL ||
768 GDK_IS_PIXBUF (pixbuf));
770 g_object_freeze_notify (G_OBJECT (image));
773 g_object_ref (G_OBJECT (pixbuf));
775 gtk_image_reset (image);
779 image->storage_type = GTK_IMAGE_PIXBUF;
781 image->data.pixbuf.pixbuf = pixbuf;
783 gtk_image_update_size (image,
784 gdk_pixbuf_get_width (pixbuf),
785 gdk_pixbuf_get_height (pixbuf));
788 g_object_notify (G_OBJECT (image), "pixbuf");
790 g_object_thaw_notify (G_OBJECT (image));
794 * gtk_image_set_from_stock:
795 * @image: a #GtkImage
796 * @stock_id: a stock icon name
797 * @size: a stock icon size
799 * See gtk_image_new_from_stock() for details.
803 gtk_image_set_from_stock (GtkImage *image,
804 const gchar *stock_id,
809 g_return_if_fail (GTK_IS_IMAGE (image));
811 g_object_freeze_notify (G_OBJECT (image));
813 /* in case stock_id == image->data.stock.stock_id */
814 new_id = g_strdup (stock_id);
816 gtk_image_reset (image);
820 image->storage_type = GTK_IMAGE_STOCK;
822 image->data.stock.stock_id = new_id;
823 image->icon_size = size;
825 /* Size is demand-computed in size request method
826 * if we're a stock image, since changing the
827 * style impacts the size request
831 g_object_notify (G_OBJECT (image), "stock");
832 g_object_notify (G_OBJECT (image), "icon_size");
834 g_object_thaw_notify (G_OBJECT (image));
838 * gtk_image_set_from_icon_set:
839 * @image: a #GtkImage
840 * @icon_set: a #GtkIconSet
841 * @size: a stock icon size
843 * See gtk_image_new_from_icon_set() for details.
847 gtk_image_set_from_icon_set (GtkImage *image,
848 GtkIconSet *icon_set,
851 g_return_if_fail (GTK_IS_IMAGE (image));
853 g_object_freeze_notify (G_OBJECT (image));
856 gtk_icon_set_ref (icon_set);
858 gtk_image_reset (image);
862 image->storage_type = GTK_IMAGE_ICON_SET;
864 image->data.icon_set.icon_set = icon_set;
865 image->icon_size = size;
867 /* Size is demand-computed in size request method
868 * if we're an icon set
872 g_object_notify (G_OBJECT (image), "icon_set");
873 g_object_notify (G_OBJECT (image), "icon_size");
875 g_object_thaw_notify (G_OBJECT (image));
879 * gtk_image_set_from_animation:
880 * @image: a #GtkImage
881 * @animation: the #GdkPixbufAnimation
883 * Causes the #GtkImage to display the given animation (or display
884 * nothing, if you set the animation to %NULL).
887 gtk_image_set_from_animation (GtkImage *image,
888 GdkPixbufAnimation *animation)
890 g_return_if_fail (GTK_IS_IMAGE (image));
891 g_return_if_fail (animation == NULL ||
892 GDK_IS_PIXBUF_ANIMATION (animation));
894 g_object_freeze_notify (G_OBJECT (image));
897 g_object_ref (G_OBJECT (animation));
899 gtk_image_reset (image);
901 if (animation != NULL)
903 image->storage_type = GTK_IMAGE_ANIMATION;
905 image->data.anim.anim = animation;
906 image->data.anim.frame_timeout = 0;
907 image->data.anim.iter = NULL;
909 gtk_image_update_size (image,
910 gdk_pixbuf_animation_get_width (animation),
911 gdk_pixbuf_animation_get_height (animation));
914 g_object_notify (G_OBJECT (image), "pixbuf_animation");
916 g_object_thaw_notify (G_OBJECT (image));
920 * gtk_image_get_storage_type:
921 * @image: a #GtkImage
923 * Gets the type of representation being used by the #GtkImage
924 * to store image data. If the #GtkImage has no image data,
925 * the return value will be %GTK_IMAGE_EMPTY.
927 * Return value: image representation being used
930 gtk_image_get_storage_type (GtkImage *image)
932 g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
934 return image->storage_type;
938 * gtk_image_get_pixmap:
939 * @image: a #GtkImage
940 * @pixmap: location to store the pixmap, or %NULL
941 * @mask: location to store the mask, or %NULL
943 * Gets the pixmap and mask being displayed by the #GtkImage.
944 * The storage type of the image must be %GTK_IMAGE_EMPTY or
945 * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
946 * The caller of this function does not own a reference to the
947 * returned pixmap and mask.
951 gtk_image_get_pixmap (GtkImage *image,
955 g_return_if_fail (GTK_IS_IMAGE (image));
956 g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
957 image->storage_type == GTK_IMAGE_EMPTY);
960 *pixmap = image->data.pixmap.pixmap;
967 * gtk_image_get_image:
968 * @image: a #GtkImage
969 * @gdk_image: return location for a #GtkImage
970 * @mask: return location for a #GdkBitmap
972 * Gets the #GdkImage and mask being displayed by the #GtkImage.
973 * The storage type of the image must be %GTK_IMAGE_EMPTY or
974 * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
975 * The caller of this function does not own a reference to the
976 * returned image and mask.
979 gtk_image_get_image (GtkImage *image,
980 GdkImage **gdk_image,
983 g_return_if_fail (GTK_IS_IMAGE (image));
984 g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
985 image->storage_type == GTK_IMAGE_EMPTY);
988 *gdk_image = image->data.image.image;
995 * gtk_image_get_pixbuf:
996 * @image: a #GtkImage
999 * Gets the #GdkPixbuf being displayed by the #GtkImage.
1000 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1001 * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1002 * The caller of this function does not own a reference to the
1005 * Return value: the displayed pixbuf, or %NULL if the image is empty
1008 gtk_image_get_pixbuf (GtkImage *image)
1010 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1011 g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
1012 image->storage_type == GTK_IMAGE_EMPTY, NULL);
1014 if (image->storage_type == GTK_IMAGE_EMPTY)
1015 image->data.pixbuf.pixbuf = NULL;
1017 return image->data.pixbuf.pixbuf;
1021 * gtk_image_get_stock:
1022 * @image: a #GtkImage
1023 * @stock_id: place to store a stock icon name
1024 * @size: place to store a stock icon size
1026 * Gets the stock icon name and size being displayed by the #GtkImage.
1027 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1028 * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1029 * The returned string is owned by the #GtkImage and should not
1034 gtk_image_get_stock (GtkImage *image,
1038 g_return_if_fail (GTK_IS_IMAGE (image));
1039 g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
1040 image->storage_type == GTK_IMAGE_EMPTY);
1042 if (image->storage_type == GTK_IMAGE_EMPTY)
1043 image->data.stock.stock_id = NULL;
1046 *stock_id = image->data.stock.stock_id;
1049 *size = image->icon_size;
1053 * gtk_image_get_icon_set:
1054 * @image: a #GtkImage
1055 * @icon_set: location to store a #GtkIconSet
1056 * @size: location to store a stock icon size
1058 * Gets the icon set and size being displayed by the #GtkImage.
1059 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1060 * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1064 gtk_image_get_icon_set (GtkImage *image,
1065 GtkIconSet **icon_set,
1068 g_return_if_fail (GTK_IS_IMAGE (image));
1069 g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
1070 image->storage_type == GTK_IMAGE_EMPTY);
1073 *icon_set = image->data.icon_set.icon_set;
1076 *size = image->icon_size;
1080 * gtk_image_get_animation:
1081 * @image: a #GtkImage
1084 * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1085 * The storage type of the image must be %GTK_IMAGE_EMPTY or
1086 * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1087 * The caller of this function does not own a reference to the
1088 * returned animation.
1090 * Return value: the displayed animation, or %NULL if the image is empty
1093 gtk_image_get_animation (GtkImage *image)
1095 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1096 g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
1097 image->storage_type == GTK_IMAGE_EMPTY,
1100 if (image->storage_type == GTK_IMAGE_EMPTY)
1101 image->data.anim.anim = NULL;
1103 return image->data.anim.anim;
1109 * Creates a new empty #GtkImage widget.
1111 * Return value: a newly created #GtkImage widget.
1114 gtk_image_new (void)
1116 return g_object_new (GTK_TYPE_IMAGE, NULL);
1120 gtk_image_set (GtkImage *image,
1124 g_return_if_fail (GTK_IS_IMAGE (image));
1126 gtk_image_set_from_image (image, val, mask);
1130 gtk_image_get (GtkImage *image,
1134 g_return_if_fail (GTK_IS_IMAGE (image));
1136 gtk_image_get_image (image, val, mask);
1140 gtk_image_unmap (GtkWidget *widget)
1144 image = GTK_IMAGE (widget);
1146 if (image->storage_type == GTK_IMAGE_ANIMATION)
1148 /* Reset the animation */
1150 if (image->data.anim.frame_timeout)
1152 g_source_remove (image->data.anim.frame_timeout);
1153 image->data.anim.frame_timeout = 0;
1156 if (image->data.anim.iter)
1158 g_object_unref (G_OBJECT (image->data.anim.iter));
1159 image->data.anim.iter = NULL;
1163 if (GTK_WIDGET_CLASS (parent_class)->unmap)
1164 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1168 animation_timeout (gpointer data)
1172 GDK_THREADS_ENTER ();
1174 image = GTK_IMAGE (data);
1176 image->data.anim.frame_timeout = 0;
1178 gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);
1180 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1181 image->data.anim.frame_timeout =
1182 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1186 gtk_widget_queue_draw (GTK_WIDGET (image));
1188 GDK_THREADS_LEAVE ();
1194 gtk_image_expose (GtkWidget *widget,
1195 GdkEventExpose *event)
1197 g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1198 g_return_val_if_fail (event != NULL, FALSE);
1200 if (GTK_WIDGET_MAPPED (widget) &&
1201 GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
1205 GdkRectangle area, image_bound;
1210 gboolean needs_state_transform;
1212 image = GTK_IMAGE (widget);
1213 misc = GTK_MISC (widget);
1217 if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
1220 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1221 xalign = misc->xalign;
1223 xalign = 1.0 - misc->xalign;
1225 x = floor (widget->allocation.x + misc->xpad
1226 + ((widget->allocation.width - widget->requisition.width) * xalign)
1228 y = floor (widget->allocation.y + misc->ypad
1229 + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1234 image_bound.width = 0;
1235 image_bound.height = 0;
1239 needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
1241 switch (image->storage_type)
1243 case GTK_IMAGE_PIXMAP:
1245 gdk_drawable_get_size (image->data.pixmap.pixmap,
1247 &image_bound.height);
1249 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1250 needs_state_transform)
1252 pixbuf = gdk_pixbuf_get_from_drawable (NULL,
1253 image->data.pixmap.pixmap,
1254 gtk_widget_get_colormap (widget),
1255 image_bound.x - x, image_bound.y - y,
1258 image_bound.height);
1266 case GTK_IMAGE_IMAGE:
1268 image_bound.width = image->data.image.image->width;
1269 image_bound.height = image->data.image.image->height;
1271 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1272 needs_state_transform)
1274 pixbuf = gdk_pixbuf_get_from_image (NULL,
1275 image->data.image.image,
1276 gtk_widget_get_colormap (widget),
1277 image_bound.x - x, image_bound.y - y,
1280 image_bound.height);
1287 case GTK_IMAGE_PIXBUF:
1288 image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
1289 image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);
1291 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1292 needs_state_transform)
1294 pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf,
1295 image_bound.x - x, image_bound.y - y,
1296 image_bound.width, image_bound.height);
1303 pixbuf = image->data.pixbuf.pixbuf;
1304 g_object_ref (G_OBJECT (pixbuf));
1308 case GTK_IMAGE_STOCK:
1309 pixbuf = gtk_widget_render_icon (widget,
1310 image->data.stock.stock_id,
1315 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1316 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1320 needs_state_transform = FALSE;
1323 case GTK_IMAGE_ICON_SET:
1325 gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1327 gtk_widget_get_direction (widget),
1328 GTK_WIDGET_STATE (widget),
1335 image_bound.width = gdk_pixbuf_get_width (pixbuf);
1336 image_bound.height = gdk_pixbuf_get_height (pixbuf);
1340 needs_state_transform = FALSE;
1343 case GTK_IMAGE_ANIMATION:
1345 if (image->data.anim.iter == NULL)
1347 image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL);
1349 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1350 image->data.anim.frame_timeout =
1351 g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1356 image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim);
1357 image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim);
1359 /* don't advance the anim iter here, or we could get frame changes between two
1360 * exposes of different areas.
1363 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter);
1364 g_object_ref (G_OBJECT (pixbuf));
1368 case GTK_IMAGE_EMPTY:
1369 g_assert_not_reached ();
1375 gdk_gc_set_clip_mask (widget->style->black_gc, mask);
1376 gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
1379 if (gdk_rectangle_intersect (&image_bound, &area, &image_bound))
1383 if (needs_state_transform)
1385 GtkIconSource *source;
1386 GdkPixbuf *rendered;
1388 source = gtk_icon_source_new ();
1389 gtk_icon_source_set_pixbuf (source, pixbuf);
1390 /* The size here is arbitrary; since size isn't
1391 * wildcarded in the souce, it isn't supposed to be
1392 * scaled by the engine function
1394 gtk_icon_source_set_size (source,
1395 GTK_ICON_SIZE_SMALL_TOOLBAR);
1396 gtk_icon_source_set_size_wildcarded (source, FALSE);
1398 rendered = gtk_style_render_icon (widget->style,
1400 gtk_widget_get_direction (widget),
1401 GTK_WIDGET_STATE (widget),
1407 gtk_icon_source_free (source);
1409 g_object_unref (G_OBJECT (pixbuf));
1415 gdk_pixbuf_render_to_drawable (pixbuf,
1417 widget->style->black_gc,
1424 GDK_RGB_DITHER_NORMAL,
1427 g_object_unref (G_OBJECT (pixbuf));
1433 switch (image->storage_type)
1435 case GTK_IMAGE_PIXMAP:
1436 gdk_draw_drawable (widget->window,
1437 widget->style->black_gc,
1438 image->data.pixmap.pixmap,
1439 image_bound.x - x, image_bound.y - y,
1440 image_bound.x, image_bound.y,
1441 image_bound.width, image_bound.height);
1444 case GTK_IMAGE_IMAGE:
1445 gdk_draw_image (widget->window,
1446 widget->style->black_gc,
1447 image->data.image.image,
1448 image_bound.x - x, image_bound.y - y,
1449 image_bound.x, image_bound.y,
1450 image_bound.width, image_bound.height);
1453 case GTK_IMAGE_PIXBUF:
1454 case GTK_IMAGE_STOCK:
1455 case GTK_IMAGE_ICON_SET:
1456 case GTK_IMAGE_ANIMATION:
1457 case GTK_IMAGE_EMPTY:
1458 g_assert_not_reached ();
1462 } /* if rectangle intersects */
1466 gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
1467 gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
1470 } /* if widget is drawable */
1476 gtk_image_clear (GtkImage *image)
1478 g_object_freeze_notify (G_OBJECT (image));
1480 if (image->storage_type != GTK_IMAGE_EMPTY)
1481 g_object_notify (G_OBJECT (image), "storage_type");
1485 g_object_unref (G_OBJECT (image->mask));
1487 g_object_notify (G_OBJECT (image), "mask");
1490 if (image->icon_size != DEFAULT_ICON_SIZE)
1492 image->icon_size = DEFAULT_ICON_SIZE;
1493 g_object_notify (G_OBJECT (image), "icon_size");
1496 switch (image->storage_type)
1498 case GTK_IMAGE_PIXMAP:
1500 if (image->data.pixmap.pixmap)
1501 g_object_unref (G_OBJECT (image->data.pixmap.pixmap));
1502 image->data.pixmap.pixmap = NULL;
1504 g_object_notify (G_OBJECT (image), "pixmap");
1508 case GTK_IMAGE_IMAGE:
1510 if (image->data.image.image)
1511 g_object_unref (G_OBJECT (image->data.image.image));
1512 image->data.image.image = NULL;
1514 g_object_notify (G_OBJECT (image), "image");
1518 case GTK_IMAGE_PIXBUF:
1520 if (image->data.pixbuf.pixbuf)
1521 g_object_unref (G_OBJECT (image->data.pixbuf.pixbuf));
1523 g_object_notify (G_OBJECT (image), "pixbuf");
1527 case GTK_IMAGE_STOCK:
1529 g_free (image->data.stock.stock_id);
1531 image->data.stock.stock_id = NULL;
1533 g_object_notify (G_OBJECT (image), "stock");
1536 case GTK_IMAGE_ICON_SET:
1537 if (image->data.icon_set.icon_set)
1538 gtk_icon_set_unref (image->data.icon_set.icon_set);
1539 image->data.icon_set.icon_set = NULL;
1541 g_object_notify (G_OBJECT (image), "icon_set");
1544 case GTK_IMAGE_ANIMATION:
1545 if (image->data.anim.frame_timeout)
1546 g_source_remove (image->data.anim.frame_timeout);
1548 if (image->data.anim.anim)
1549 g_object_unref (G_OBJECT (image->data.anim.anim));
1551 image->data.anim.frame_timeout = 0;
1552 image->data.anim.anim = NULL;
1554 g_object_notify (G_OBJECT (image), "pixbuf_animation");
1558 case GTK_IMAGE_EMPTY:
1564 image->storage_type = GTK_IMAGE_EMPTY;
1566 memset (&image->data, '\0', sizeof (image->data));
1568 g_object_thaw_notify (G_OBJECT (image));
1572 gtk_image_reset (GtkImage *image)
1574 gtk_image_clear (image);
1576 gtk_image_update_size (image, 0, 0);
1580 gtk_image_size_request (GtkWidget *widget,
1581 GtkRequisition *requisition)
1584 GdkPixbuf *pixbuf = NULL;
1586 image = GTK_IMAGE (widget);
1588 /* We update stock/icon set on every size request, because
1589 * the theme could have affected the size; for other kinds of
1590 * image, we just update the requisition when the image data
1594 switch (image->storage_type)
1596 case GTK_IMAGE_STOCK:
1597 pixbuf = gtk_widget_render_icon (GTK_WIDGET (image),
1598 image->data.stock.stock_id,
1603 case GTK_IMAGE_ICON_SET:
1604 pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1606 gtk_widget_get_direction (widget),
1607 GTK_WIDGET_STATE (widget),
1619 GTK_WIDGET (image)->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2;
1620 GTK_WIDGET (image)->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2;
1622 g_object_unref (G_OBJECT (pixbuf));
1625 /* Chain up to default that simply reads current requisition */
1626 GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
1630 gtk_image_update_size (GtkImage *image,
1634 GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
1635 GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
1637 if (GTK_WIDGET_VISIBLE (image))
1638 gtk_widget_queue_resize (GTK_WIDGET (image));