]> Pileus Git - ~andy/gtk/blob - gtk/gtkimage.c
Merge bgo593793-filechooser-recent-folders-master branch.
[~andy/gtk] / gtk / gtkimage.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include "config.h"
28
29 #include <math.h>
30 #include <string.h>
31
32 #include "gtkcontainer.h"
33 #include "gtkimageprivate.h"
34 #include "gtkiconfactory.h"
35 #include "gtkstock.h"
36 #include "gtkicontheme.h"
37 #include "gtksizerequest.h"
38 #include "gtkintl.h"
39 #include "gtkprivate.h"
40 #include "gtktypebuiltins.h"
41
42 #include "a11y/gtkimageaccessible.h"
43
44 /**
45  * SECTION:gtkimage
46  * @Short_description: A widget displaying an image
47  * @Title: GtkImage
48  * @See_also:#GdkPixbuf
49  *
50  * The #GtkImage widget displays an image. Various kinds of object
51  * can be displayed as an image; most typically, you would load a
52  * #GdkPixbuf ("pixel buffer") from a file, and then display that.
53  * There's a convenience function to do this, gtk_image_new_from_file(),
54  * used as follows:
55  * <informalexample><programlisting>
56  *   GtkWidget *image;
57  *   image = gtk_image_new_from_file ("myfile.png");
58  * </programlisting></informalexample>
59  * If the file isn't loaded successfully, the image will contain a
60  * "broken image" icon similar to that used in many web browsers.
61  * If you want to handle errors in loading the file yourself,
62  * for example by displaying an error message, then load the image with
63  * gdk_pixbuf_new_from_file(), then create the #GtkImage with
64  * gtk_image_new_from_pixbuf().
65  *
66  * The image file may contain an animation, if so the #GtkImage will
67  * display an animation (#GdkPixbufAnimation) instead of a static image.
68  *
69  * #GtkImage is a subclass of #GtkMisc, which implies that you can
70  * align it (center, left, right) and add padding to it, using
71  * #GtkMisc methods.
72  *
73  * #GtkImage is a "no window" widget (has no #GdkWindow of its own),
74  * so by default does not receive events. If you want to receive events
75  * on the image, such as button clicks, place the image inside a
76  * #GtkEventBox, then connect to the event signals on the event box.
77  * <example>
78  * <title>Handling button press events on a
79  * <structname>GtkImage</structname>.</title>
80  * <programlisting>
81  *   static gboolean
82  *   button_press_callback (GtkWidget      *event_box,
83  *                          GdkEventButton *event,
84  *                          gpointer        data)
85  *   {
86  *     g_print ("Event box clicked at coordinates &percnt;f,&percnt;f\n",
87  *              event->x, event->y);
88  *
89  *     /<!---->* Returning TRUE means we handled the event, so the signal
90  *      * emission should be stopped (don't call any further
91  *      * callbacks that may be connected). Return FALSE
92  *      * to continue invoking callbacks.
93  *      *<!---->/
94  *     return TRUE;
95  *   }
96  *
97  *   static GtkWidget*
98  *   create_image (void)
99  *   {
100  *     GtkWidget *image;
101  *     GtkWidget *event_box;
102  *
103  *     image = gtk_image_new_from_file ("myfile.png");
104  *
105  *     event_box = gtk_event_box_new (<!-- -->);
106  *
107  *     gtk_container_add (GTK_CONTAINER (event_box), image);
108  *
109  *     g_signal_connect (G_OBJECT (event_box),
110  *                       "button_press_event",
111  *                       G_CALLBACK (button_press_callback),
112  *                       image);
113  *
114  *     return image;
115  *   }
116  * </programlisting>
117  * </example>
118  *
119  * When handling events on the event box, keep in mind that coordinates
120  * in the image may be different from event box coordinates due to
121  * the alignment and padding settings on the image (see #GtkMisc).
122  * The simplest way to solve this is to set the alignment to 0.0
123  * (left/top), and set the padding to zero. Then the origin of
124  * the image will be the same as the origin of the event box.
125  *
126  * Sometimes an application will want to avoid depending on external data
127  * files, such as image files. GTK+ comes with a program to avoid this,
128  * called <application>gdk-pixbuf-csource</application>. This program
129  * allows you to convert an image into a C variable declaration, which
130  * can then be loaded into a #GdkPixbuf using
131  * gdk_pixbuf_new_from_inline().
132  */
133
134
135 struct _GtkImagePrivate
136 {
137   GtkIconSize           icon_size;      /* Only used with GTK_IMAGE_STOCK, GTK_IMAGE_ICON_SET, GTK_IMAGE_ICON_NAME */
138   GtkImageType          storage_type;
139
140   union
141   {
142     GtkImagePixbufData     pixbuf;
143     GtkImageStockData      stock;
144     GtkImageIconSetData    icon_set;
145     GtkImageAnimationData  anim;
146     GtkImageIconNameData   name;
147     GtkImageGIconData      gicon;
148   } data;
149
150   gchar                *filename;       /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
151   gint                  last_rendered_state;  /* a GtkStateFlags, with -1 meaning an invalid state,
152                                                * only used with GTK_IMAGE_GICON, GTK_IMAGE_ICON_NAME */
153   gint                  pixel_size;
154   gint                  required_width;
155   gint                  required_height;
156   guint                 need_calc_size : 1;
157   guint                 use_fallback   : 1;
158 };
159
160
161 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
162 static gint gtk_image_draw                 (GtkWidget    *widget,
163                                             cairo_t      *cr);
164 static void gtk_image_unmap                (GtkWidget    *widget);
165 static void gtk_image_unrealize            (GtkWidget    *widget);
166 static void gtk_image_get_preferred_width  (GtkWidget    *widget,
167                                             gint         *minimum,
168                                             gint         *natural);
169 static void gtk_image_get_preferred_height (GtkWidget    *widget,
170                                             gint         *minimum,
171                                             gint         *natural);
172
173 static void gtk_image_style_updated        (GtkWidget    *widget);
174 static void gtk_image_screen_changed       (GtkWidget    *widget,
175                                             GdkScreen    *prev_screen);
176 static void gtk_image_destroy              (GtkWidget    *widget);
177 static void gtk_image_reset                (GtkImage     *image);
178 static void gtk_image_calc_size            (GtkImage     *image);
179
180 static void gtk_image_update_size          (GtkImage     *image,
181                                             gint          image_width,
182                                             gint          image_height);
183
184 static void gtk_image_set_property         (GObject      *object,
185                                             guint         prop_id,
186                                             const GValue *value,
187                                             GParamSpec   *pspec);
188 static void gtk_image_get_property         (GObject      *object,
189                                             guint         prop_id,
190                                             GValue       *value,
191                                             GParamSpec   *pspec);
192
193 static void icon_theme_changed             (GtkImage     *image);
194
195 enum
196 {
197   PROP_0,
198   PROP_PIXBUF,
199   PROP_FILE,
200   PROP_STOCK,
201   PROP_ICON_SET,
202   PROP_ICON_SIZE,
203   PROP_PIXEL_SIZE,
204   PROP_PIXBUF_ANIMATION,
205   PROP_ICON_NAME,
206   PROP_STORAGE_TYPE,
207   PROP_GICON,
208   PROP_USE_FALLBACK
209 };
210
211 G_DEFINE_TYPE (GtkImage, gtk_image, GTK_TYPE_MISC)
212
213 static void
214 gtk_image_class_init (GtkImageClass *class)
215 {
216   GObjectClass *gobject_class;
217   GtkWidgetClass *widget_class;
218
219   gobject_class = G_OBJECT_CLASS (class);
220   
221   gobject_class->set_property = gtk_image_set_property;
222   gobject_class->get_property = gtk_image_get_property;
223
224   widget_class = GTK_WIDGET_CLASS (class);
225   widget_class->draw = gtk_image_draw;
226   widget_class->destroy = gtk_image_destroy;
227   widget_class->get_preferred_width = gtk_image_get_preferred_width;
228   widget_class->get_preferred_height = gtk_image_get_preferred_height;
229   widget_class->unmap = gtk_image_unmap;
230   widget_class->unrealize = gtk_image_unrealize;
231   widget_class->style_updated = gtk_image_style_updated;
232   widget_class->screen_changed = gtk_image_screen_changed;
233   
234   g_object_class_install_property (gobject_class,
235                                    PROP_PIXBUF,
236                                    g_param_spec_object ("pixbuf",
237                                                         P_("Pixbuf"),
238                                                         P_("A GdkPixbuf to display"),
239                                                         GDK_TYPE_PIXBUF,
240                                                         GTK_PARAM_READWRITE));
241
242   g_object_class_install_property (gobject_class,
243                                    PROP_FILE,
244                                    g_param_spec_string ("file",
245                                                         P_("Filename"),
246                                                         P_("Filename to load and display"),
247                                                         NULL,
248                                                         GTK_PARAM_READWRITE));
249   
250
251   g_object_class_install_property (gobject_class,
252                                    PROP_STOCK,
253                                    g_param_spec_string ("stock",
254                                                         P_("Stock ID"),
255                                                         P_("Stock ID for a stock image to display"),
256                                                         NULL,
257                                                         GTK_PARAM_READWRITE));
258   
259   g_object_class_install_property (gobject_class,
260                                    PROP_ICON_SET,
261                                    g_param_spec_boxed ("icon-set",
262                                                        P_("Icon set"),
263                                                        P_("Icon set to display"),
264                                                        GTK_TYPE_ICON_SET,
265                                                        GTK_PARAM_READWRITE));
266   
267   g_object_class_install_property (gobject_class,
268                                    PROP_ICON_SIZE,
269                                    g_param_spec_int ("icon-size",
270                                                      P_("Icon size"),
271                                                      P_("Symbolic size to use for stock icon, icon set or named icon"),
272                                                      0, G_MAXINT,
273                                                      DEFAULT_ICON_SIZE,
274                                                      GTK_PARAM_READWRITE));
275   /**
276    * GtkImage:pixel-size:
277    *
278    * The "pixel-size" property can be used to specify a fixed size
279    * overriding the #GtkImage:icon-size property for images of type 
280    * %GTK_IMAGE_ICON_NAME. 
281    *
282    * Since: 2.6
283    */
284   g_object_class_install_property (gobject_class,
285                                    PROP_PIXEL_SIZE,
286                                    g_param_spec_int ("pixel-size",
287                                                      P_("Pixel size"),
288                                                      P_("Pixel size to use for named icon"),
289                                                      -1, G_MAXINT,
290                                                      -1,
291                                                      GTK_PARAM_READWRITE));
292   
293   g_object_class_install_property (gobject_class,
294                                    PROP_PIXBUF_ANIMATION,
295                                    g_param_spec_object ("pixbuf-animation",
296                                                         P_("Animation"),
297                                                         P_("GdkPixbufAnimation to display"),
298                                                         GDK_TYPE_PIXBUF_ANIMATION,
299                                                         GTK_PARAM_READWRITE));
300
301   /**
302    * GtkImage:icon-name:
303    *
304    * The name of the icon in the icon theme. If the icon theme is
305    * changed, the image will be updated automatically.
306    *
307    * Since: 2.6
308    */
309   g_object_class_install_property (gobject_class,
310                                    PROP_ICON_NAME,
311                                    g_param_spec_string ("icon-name",
312                                                         P_("Icon Name"),
313                                                         P_("The name of the icon from the icon theme"),
314                                                         NULL,
315                                                         GTK_PARAM_READWRITE));
316   
317   /**
318    * GtkImage:gicon:
319    *
320    * The GIcon displayed in the GtkImage. For themed icons,
321    * If the icon theme is changed, the image will be updated
322    * automatically.
323    *
324    * Since: 2.14
325    */
326   g_object_class_install_property (gobject_class,
327                                    PROP_GICON,
328                                    g_param_spec_object ("gicon",
329                                                         P_("Icon"),
330                                                         P_("The GIcon being displayed"),
331                                                         G_TYPE_ICON,
332                                                         GTK_PARAM_READWRITE));
333   
334   g_object_class_install_property (gobject_class,
335                                    PROP_STORAGE_TYPE,
336                                    g_param_spec_enum ("storage-type",
337                                                       P_("Storage type"),
338                                                       P_("The representation being used for image data"),
339                                                       GTK_TYPE_IMAGE_TYPE,
340                                                       GTK_IMAGE_EMPTY,
341                                                       GTK_PARAM_READABLE));
342
343   /**
344    * GtkImage:use-fallback:
345    *
346    * Whether the icon displayed in the GtkImage will use
347    * standard icon names fallback. The value of this property
348    * is only relevant for images of type %GTK_IMAGE_ICON_NAME
349    * and %GTK_IMAGE_GICON.
350    *
351    * Since: 3.0
352    */
353   g_object_class_install_property (gobject_class,
354                                    PROP_USE_FALLBACK,
355                                    g_param_spec_boolean ("use-fallback",
356                                                          P_("Use Fallback"),
357                                                          P_("Whether to use icon names fallback"),
358                                                          FALSE,
359                                                          GTK_PARAM_READWRITE));
360
361   g_type_class_add_private (class, sizeof (GtkImagePrivate));
362
363   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_IMAGE_ACCESSIBLE);
364 }
365
366 static void
367 gtk_image_init (GtkImage *image)
368 {
369   GtkImagePrivate *priv;
370
371   image->priv = G_TYPE_INSTANCE_GET_PRIVATE (image,
372                                              GTK_TYPE_IMAGE,
373                                              GtkImagePrivate);
374   priv = image->priv;
375
376   gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
377
378   priv->storage_type = GTK_IMAGE_EMPTY;
379   priv->icon_size = DEFAULT_ICON_SIZE;
380
381   priv->pixel_size = -1;
382
383   priv->filename = NULL;
384 }
385
386 static void
387 gtk_image_destroy (GtkWidget *widget)
388 {
389   GtkImage *image = GTK_IMAGE (widget);
390
391   gtk_image_reset (image);
392
393   GTK_WIDGET_CLASS (gtk_image_parent_class)->destroy (widget);
394 }
395
396 static void 
397 gtk_image_set_property (GObject      *object,
398                         guint         prop_id,
399                         const GValue *value,
400                         GParamSpec   *pspec)
401 {
402   GtkImage *image = GTK_IMAGE (object);
403   GtkImagePrivate *priv = image->priv;
404
405   switch (prop_id)
406     {
407     case PROP_PIXBUF:
408       gtk_image_set_from_pixbuf (image,
409                                  g_value_get_object (value));
410       break;
411     case PROP_FILE:
412       gtk_image_set_from_file (image, g_value_get_string (value));
413       break;
414     case PROP_STOCK:
415       gtk_image_set_from_stock (image, g_value_get_string (value),
416                                 priv->icon_size);
417       break;
418     case PROP_ICON_SET:
419       gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
420                                    priv->icon_size);
421       break;
422     case PROP_ICON_SIZE:
423       if (priv->storage_type == GTK_IMAGE_STOCK)
424         gtk_image_set_from_stock (image,
425                                   priv->data.stock.stock_id,
426                                   g_value_get_int (value));
427       else if (priv->storage_type == GTK_IMAGE_ICON_SET)
428         gtk_image_set_from_icon_set (image,
429                                      priv->data.icon_set.icon_set,
430                                      g_value_get_int (value));
431       else if (priv->storage_type == GTK_IMAGE_ICON_NAME)
432         gtk_image_set_from_icon_name (image,
433                                       priv->data.name.icon_name,
434                                       g_value_get_int (value));
435       else if (priv->storage_type == GTK_IMAGE_GICON)
436         gtk_image_set_from_gicon (image,
437                                   priv->data.gicon.icon,
438                                   g_value_get_int (value));
439       else
440         /* Save to be used when STOCK, ICON_SET, ICON_NAME or GICON property comes in */
441         priv->icon_size = g_value_get_int (value);
442       break;
443     case PROP_PIXEL_SIZE:
444       gtk_image_set_pixel_size (image, g_value_get_int (value));
445       break;
446     case PROP_PIXBUF_ANIMATION:
447       gtk_image_set_from_animation (image,
448                                     g_value_get_object (value));
449       break;
450     case PROP_ICON_NAME:
451       gtk_image_set_from_icon_name (image, g_value_get_string (value),
452                                     priv->icon_size);
453       break;
454     case PROP_GICON:
455       gtk_image_set_from_gicon (image, g_value_get_object (value),
456                                 priv->icon_size);
457       break;
458
459     case PROP_USE_FALLBACK:
460       priv->use_fallback = g_value_get_boolean (value);
461       if (priv->storage_type == GTK_IMAGE_ICON_NAME)
462         gtk_image_set_from_icon_name (image,
463                                       priv->data.name.icon_name,
464                                       priv->icon_size);
465       else if (priv->storage_type == GTK_IMAGE_GICON)
466         gtk_image_set_from_gicon (image,
467                                   priv->data.gicon.icon,
468                                   priv->icon_size);
469       break;
470
471     default:
472       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
473       break;
474     }
475 }
476
477 static void 
478 gtk_image_get_property (GObject     *object,
479                         guint        prop_id,
480                         GValue      *value,
481                         GParamSpec  *pspec)
482 {
483   GtkImage *image = GTK_IMAGE (object);
484   GtkImagePrivate *priv = image->priv;
485
486   /* The "getter" functions whine if you try to get the wrong
487    * storage type. This function is instead robust against that,
488    * so that GUI builders don't have to jump through hoops
489    * to avoid g_warning
490    */
491   
492   switch (prop_id)
493     {
494     case PROP_PIXBUF:
495       if (priv->storage_type != GTK_IMAGE_PIXBUF)
496         g_value_set_object (value, NULL);
497       else
498         g_value_set_object (value,
499                             gtk_image_get_pixbuf (image));
500       break;
501     case PROP_FILE:
502       g_value_set_string (value, priv->filename);
503       break;
504     case PROP_STOCK:
505       if (priv->storage_type != GTK_IMAGE_STOCK)
506         g_value_set_string (value, NULL);
507       else
508         g_value_set_string (value,
509                             priv->data.stock.stock_id);
510       break;
511     case PROP_ICON_SET:
512       if (priv->storage_type != GTK_IMAGE_ICON_SET)
513         g_value_set_boxed (value, NULL);
514       else
515         g_value_set_boxed (value,
516                            priv->data.icon_set.icon_set);
517       break;      
518     case PROP_ICON_SIZE:
519       g_value_set_int (value, priv->icon_size);
520       break;
521     case PROP_PIXEL_SIZE:
522       g_value_set_int (value, priv->pixel_size);
523       break;
524     case PROP_PIXBUF_ANIMATION:
525       if (priv->storage_type != GTK_IMAGE_ANIMATION)
526         g_value_set_object (value, NULL);
527       else
528         g_value_set_object (value,
529                             priv->data.anim.anim);
530       break;
531     case PROP_ICON_NAME:
532       if (priv->storage_type != GTK_IMAGE_ICON_NAME)
533         g_value_set_string (value, NULL);
534       else
535         g_value_set_string (value,
536                             priv->data.name.icon_name);
537       break;
538     case PROP_GICON:
539       if (priv->storage_type != GTK_IMAGE_GICON)
540         g_value_set_object (value, NULL);
541       else
542         g_value_set_object (value,
543                             priv->data.gicon.icon);
544       break;
545     case PROP_STORAGE_TYPE:
546       g_value_set_enum (value, priv->storage_type);
547       break;
548
549     case PROP_USE_FALLBACK:
550       g_value_set_boolean (value, priv->use_fallback);
551       break;
552       
553     default:
554       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
555       break;
556     }
557 }
558
559
560 /**
561  * gtk_image_new_from_file:
562  * @filename: (type filename): a filename
563  * 
564  * Creates a new #GtkImage displaying the file @filename. If the file
565  * isn't found or can't be loaded, the resulting #GtkImage will
566  * display a "broken image" icon. This function never returns %NULL,
567  * it always returns a valid #GtkImage widget.
568  *
569  * If the file contains an animation, the image will contain an
570  * animation.
571  *
572  * If you need to detect failures to load the file, use
573  * gdk_pixbuf_new_from_file() to load the file yourself, then create
574  * the #GtkImage from the pixbuf. (Or for animations, use
575  * gdk_pixbuf_animation_new_from_file()).
576  *
577  * The storage type (gtk_image_get_storage_type()) of the returned
578  * image is not defined, it will be whatever is appropriate for
579  * displaying the file.
580  * 
581  * Return value: a new #GtkImage
582  **/
583 GtkWidget*
584 gtk_image_new_from_file   (const gchar *filename)
585 {
586   GtkImage *image;
587
588   image = g_object_new (GTK_TYPE_IMAGE, NULL);
589
590   gtk_image_set_from_file (image, filename);
591
592   return GTK_WIDGET (image);
593 }
594
595 /**
596  * gtk_image_new_from_pixbuf:
597  * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL
598  *
599  * Creates a new #GtkImage displaying @pixbuf.
600  * The #GtkImage does not assume a reference to the
601  * pixbuf; you still need to unref it if you own references.
602  * #GtkImage will add its own reference rather than adopting yours.
603  * 
604  * Note that this function just creates an #GtkImage from the pixbuf. The
605  * #GtkImage created will not react to state changes. Should you want that, 
606  * you should use gtk_image_new_from_icon_set().
607  * 
608  * Return value: a new #GtkImage
609  **/
610 GtkWidget*
611 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
612 {
613   GtkImage *image;
614
615   image = g_object_new (GTK_TYPE_IMAGE, NULL);
616
617   gtk_image_set_from_pixbuf (image, pixbuf);
618
619   return GTK_WIDGET (image);  
620 }
621
622 /**
623  * gtk_image_new_from_stock:
624  * @stock_id: a stock icon name
625  * @size: (type int): a stock icon size
626  * 
627  * Creates a #GtkImage displaying a stock icon. Sample stock icon
628  * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. Sample stock sizes
629  * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
630  * icon name isn't known, the image will be empty.
631  * You can register your own stock icon names, see
632  * gtk_icon_factory_add_default() and gtk_icon_factory_add().
633  * 
634  * Return value: a new #GtkImage displaying the stock icon
635  **/
636 GtkWidget*
637 gtk_image_new_from_stock (const gchar    *stock_id,
638                           GtkIconSize     size)
639 {
640   GtkImage *image;
641
642   image = g_object_new (GTK_TYPE_IMAGE, NULL);
643
644   gtk_image_set_from_stock (image, stock_id, size);
645
646   return GTK_WIDGET (image);
647 }
648
649 /**
650  * gtk_image_new_from_icon_set:
651  * @icon_set: a #GtkIconSet
652  * @size: (type int): a stock icon size
653  *
654  * Creates a #GtkImage displaying an icon set. Sample stock sizes are
655  * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
656  * this function, usually it's better to create a #GtkIconFactory, put
657  * your icon sets in the icon factory, add the icon factory to the
658  * list of default factories with gtk_icon_factory_add_default(), and
659  * then use gtk_image_new_from_stock(). This will allow themes to
660  * override the icon you ship with your application.
661  *
662  * The #GtkImage does not assume a reference to the
663  * icon set; you still need to unref it if you own references.
664  * #GtkImage will add its own reference rather than adopting yours.
665  * 
666  * Return value: a new #GtkImage
667  **/
668 GtkWidget*
669 gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
670                              GtkIconSize     size)
671 {
672   GtkImage *image;
673
674   image = g_object_new (GTK_TYPE_IMAGE, NULL);
675
676   gtk_image_set_from_icon_set (image, icon_set, size);
677
678   return GTK_WIDGET (image);
679 }
680
681 /**
682  * gtk_image_new_from_animation:
683  * @animation: an animation
684  * 
685  * Creates a #GtkImage displaying the given animation.
686  * The #GtkImage does not assume a reference to the
687  * animation; you still need to unref it if you own references.
688  * #GtkImage will add its own reference rather than adopting yours.
689  *
690  * Note that the animation frames are shown using a timeout with
691  * #G_PRIORITY_DEFAULT. When using animations to indicate busyness,
692  * keep in mind that the animation will only be shown if the main loop
693  * is not busy with something that has a higher priority.
694  *
695  * Return value: a new #GtkImage widget
696  **/
697 GtkWidget*
698 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
699 {
700   GtkImage *image;
701
702   g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
703   
704   image = g_object_new (GTK_TYPE_IMAGE, NULL);
705
706   gtk_image_set_from_animation (image, animation);
707
708   return GTK_WIDGET (image);
709 }
710
711 /**
712  * gtk_image_new_from_icon_name:
713  * @icon_name: an icon name
714  * @size: (type int): a stock icon size
715  * 
716  * Creates a #GtkImage displaying an icon from the current icon theme.
717  * If the icon name isn't known, a "broken image" icon will be
718  * displayed instead.  If the current icon theme is changed, the icon
719  * will be updated appropriately.
720  * 
721  * Return value: a new #GtkImage displaying the themed icon
722  *
723  * Since: 2.6
724  **/
725 GtkWidget*
726 gtk_image_new_from_icon_name (const gchar    *icon_name,
727                               GtkIconSize     size)
728 {
729   GtkImage *image;
730
731   image = g_object_new (GTK_TYPE_IMAGE, NULL);
732
733   gtk_image_set_from_icon_name (image, icon_name, size);
734
735   return GTK_WIDGET (image);
736 }
737
738 /**
739  * gtk_image_new_from_gicon:
740  * @icon: an icon
741  * @size: (type int): a stock icon size
742  * 
743  * Creates a #GtkImage displaying an icon from the current icon theme.
744  * If the icon name isn't known, a "broken image" icon will be
745  * displayed instead.  If the current icon theme is changed, the icon
746  * will be updated appropriately.
747  * 
748  * Return value: a new #GtkImage displaying the themed icon
749  *
750  * Since: 2.14
751  **/
752 GtkWidget*
753 gtk_image_new_from_gicon (GIcon *icon,
754                           GtkIconSize     size)
755 {
756   GtkImage *image;
757
758   image = g_object_new (GTK_TYPE_IMAGE, NULL);
759
760   gtk_image_set_from_gicon (image, icon, size);
761
762   return GTK_WIDGET (image);
763 }
764
765 /**
766  * gtk_image_set_from_file:
767  * @image: a #GtkImage
768  * @filename: (type filename) (allow-none): a filename or %NULL
769  *
770  * See gtk_image_new_from_file() for details.
771  **/
772 void
773 gtk_image_set_from_file   (GtkImage    *image,
774                            const gchar *filename)
775 {
776   GtkImagePrivate *priv;
777   GdkPixbufAnimation *anim;
778   
779   g_return_if_fail (GTK_IS_IMAGE (image));
780
781   priv = image->priv;
782
783   g_object_freeze_notify (G_OBJECT (image));
784   
785   gtk_image_clear (image);
786
787   if (filename == NULL)
788     {
789       priv->filename = NULL;
790       g_object_thaw_notify (G_OBJECT (image));
791       return;
792     }
793
794   anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
795
796   if (anim == NULL)
797     {
798       gtk_image_set_from_stock (image,
799                                 GTK_STOCK_MISSING_IMAGE,
800                                 GTK_ICON_SIZE_BUTTON);
801       g_object_thaw_notify (G_OBJECT (image));
802       return;
803     }
804
805   /* We could just unconditionally set_from_animation,
806    * but it's nicer for memory if we toss the animation
807    * if it's just a single pixbuf
808    */
809
810   if (gdk_pixbuf_animation_is_static_image (anim))
811     gtk_image_set_from_pixbuf (image,
812                                gdk_pixbuf_animation_get_static_image (anim));
813   else
814     gtk_image_set_from_animation (image, anim);
815
816   g_object_unref (anim);
817
818   priv->filename = g_strdup (filename);
819   
820   g_object_thaw_notify (G_OBJECT (image));
821 }
822
823 /**
824  * gtk_image_set_from_pixbuf:
825  * @image: a #GtkImage
826  * @pixbuf: (allow-none): a #GdkPixbuf or %NULL
827  *
828  * See gtk_image_new_from_pixbuf() for details.
829  **/
830 void
831 gtk_image_set_from_pixbuf (GtkImage  *image,
832                            GdkPixbuf *pixbuf)
833 {
834   GtkImagePrivate *priv;
835
836   g_return_if_fail (GTK_IS_IMAGE (image));
837   g_return_if_fail (pixbuf == NULL ||
838                     GDK_IS_PIXBUF (pixbuf));
839
840   priv = image->priv;
841
842   g_object_freeze_notify (G_OBJECT (image));
843   
844   if (pixbuf)
845     g_object_ref (pixbuf);
846
847   gtk_image_clear (image);
848
849   if (pixbuf != NULL)
850     {
851       priv->storage_type = GTK_IMAGE_PIXBUF;
852
853       priv->data.pixbuf.pixbuf = pixbuf;
854
855       gtk_image_update_size (image,
856                              gdk_pixbuf_get_width (pixbuf),
857                              gdk_pixbuf_get_height (pixbuf));
858     }
859
860   g_object_notify (G_OBJECT (image), "pixbuf");
861   
862   g_object_thaw_notify (G_OBJECT (image));
863 }
864
865 /**
866  * gtk_image_set_from_stock:
867  * @image: a #GtkImage
868  * @stock_id: a stock icon name
869  * @size: (type int): a stock icon size
870  *
871  * See gtk_image_new_from_stock() for details.
872  **/
873 void
874 gtk_image_set_from_stock  (GtkImage       *image,
875                            const gchar    *stock_id,
876                            GtkIconSize     size)
877 {
878   GtkImagePrivate *priv;
879   gchar *new_id;
880
881   g_return_if_fail (GTK_IS_IMAGE (image));
882
883   priv = image->priv;
884
885   g_object_freeze_notify (G_OBJECT (image));
886
887   /* in case stock_id == priv->data.stock.stock_id */
888   new_id = g_strdup (stock_id);
889   
890   gtk_image_clear (image);
891
892   if (new_id)
893     {
894       priv->storage_type = GTK_IMAGE_STOCK;
895       
896       priv->data.stock.stock_id = new_id;
897       priv->icon_size = size;
898
899       /* Size is demand-computed in size request method
900        * if we're a stock image, since changing the
901        * style impacts the size request
902        */
903     }
904
905   g_object_notify (G_OBJECT (image), "stock");
906   g_object_notify (G_OBJECT (image), "icon-size");
907   
908   g_object_thaw_notify (G_OBJECT (image));
909 }
910
911 /**
912  * gtk_image_set_from_icon_set:
913  * @image: a #GtkImage
914  * @icon_set: a #GtkIconSet
915  * @size: (type int): a stock icon size
916  *
917  * See gtk_image_new_from_icon_set() for details.
918  **/
919 void
920 gtk_image_set_from_icon_set  (GtkImage       *image,
921                               GtkIconSet     *icon_set,
922                               GtkIconSize     size)
923 {
924   GtkImagePrivate *priv;
925
926   g_return_if_fail (GTK_IS_IMAGE (image));
927
928   priv = image->priv;
929
930   g_object_freeze_notify (G_OBJECT (image));
931   
932   if (icon_set)
933     gtk_icon_set_ref (icon_set);
934   
935   gtk_image_clear (image);
936
937   if (icon_set)
938     {      
939       priv->storage_type = GTK_IMAGE_ICON_SET;
940       
941       priv->data.icon_set.icon_set = icon_set;
942       priv->icon_size = size;
943
944       /* Size is demand-computed in size request method
945        * if we're an icon set
946        */
947     }
948   
949   g_object_notify (G_OBJECT (image), "icon-set");
950   g_object_notify (G_OBJECT (image), "icon-size");
951   
952   g_object_thaw_notify (G_OBJECT (image));
953 }
954
955 /**
956  * gtk_image_set_from_animation:
957  * @image: a #GtkImage
958  * @animation: the #GdkPixbufAnimation
959  * 
960  * Causes the #GtkImage to display the given animation (or display
961  * nothing, if you set the animation to %NULL).
962  **/
963 void
964 gtk_image_set_from_animation (GtkImage           *image,
965                               GdkPixbufAnimation *animation)
966 {
967   GtkImagePrivate *priv;
968
969   g_return_if_fail (GTK_IS_IMAGE (image));
970   g_return_if_fail (animation == NULL ||
971                     GDK_IS_PIXBUF_ANIMATION (animation));
972
973   priv = image->priv;
974
975   g_object_freeze_notify (G_OBJECT (image));
976   
977   if (animation)
978     g_object_ref (animation);
979
980   gtk_image_clear (image);
981
982   if (animation != NULL)
983     {
984       priv->storage_type = GTK_IMAGE_ANIMATION;
985
986       priv->data.anim.anim = animation;
987       priv->data.anim.frame_timeout = 0;
988       priv->data.anim.iter = NULL;
989       
990       gtk_image_update_size (image,
991                              gdk_pixbuf_animation_get_width (animation),
992                              gdk_pixbuf_animation_get_height (animation));
993     }
994
995   g_object_notify (G_OBJECT (image), "pixbuf-animation");
996   
997   g_object_thaw_notify (G_OBJECT (image));
998 }
999
1000 /**
1001  * gtk_image_set_from_icon_name:
1002  * @image: a #GtkImage
1003  * @icon_name: an icon name
1004  * @size: (type int): an icon size
1005  *
1006  * See gtk_image_new_from_icon_name() for details.
1007  * 
1008  * Since: 2.6
1009  **/
1010 void
1011 gtk_image_set_from_icon_name  (GtkImage       *image,
1012                                const gchar    *icon_name,
1013                                GtkIconSize     size)
1014 {
1015   gchar *new_name;
1016   GtkImagePrivate *priv;
1017
1018   g_return_if_fail (GTK_IS_IMAGE (image));
1019
1020   priv = image->priv;
1021
1022   g_object_freeze_notify (G_OBJECT (image));
1023
1024   /* in case icon_name == priv->data.name.icon_name */
1025   new_name = g_strdup (icon_name);
1026   
1027   gtk_image_clear (image);
1028
1029   if (new_name)
1030     {
1031       priv->storage_type = GTK_IMAGE_ICON_NAME;
1032       
1033       priv->data.name.icon_name = new_name;
1034       priv->icon_size = size;
1035
1036       /* Size is demand-computed in size request method
1037        * if we're a icon theme image, since changing the
1038        * style impacts the size request
1039        */
1040     }
1041
1042   g_object_notify (G_OBJECT (image), "icon-name");
1043   g_object_notify (G_OBJECT (image), "icon-size");
1044   
1045   g_object_thaw_notify (G_OBJECT (image));
1046 }
1047
1048 /**
1049  * gtk_image_set_from_gicon:
1050  * @image: a #GtkImage
1051  * @icon: an icon
1052  * @size: (type int): an icon size
1053  *
1054  * See gtk_image_new_from_gicon() for details.
1055  * 
1056  * Since: 2.14
1057  **/
1058 void
1059 gtk_image_set_from_gicon  (GtkImage       *image,
1060                            GIcon          *icon,
1061                            GtkIconSize     size)
1062 {
1063   GtkImagePrivate *priv;
1064
1065   g_return_if_fail (GTK_IS_IMAGE (image));
1066
1067   priv = image->priv;
1068
1069   g_object_freeze_notify (G_OBJECT (image));
1070
1071   /* in case icon == priv->data.gicon.icon */
1072   if (icon)
1073     g_object_ref (icon);
1074   
1075   gtk_image_clear (image);
1076
1077   if (icon)
1078     {
1079       priv->storage_type = GTK_IMAGE_GICON;
1080
1081       priv->data.gicon.icon = icon;
1082       priv->icon_size = size;
1083
1084       /* Size is demand-computed in size request method
1085        * if we're a icon theme image, since changing the
1086        * style impacts the size request
1087        */
1088     }
1089
1090   g_object_notify (G_OBJECT (image), "gicon");
1091   g_object_notify (G_OBJECT (image), "icon-size");
1092   
1093   g_object_thaw_notify (G_OBJECT (image));
1094 }
1095
1096 /**
1097  * gtk_image_get_storage_type:
1098  * @image: a #GtkImage
1099  * 
1100  * Gets the type of representation being used by the #GtkImage
1101  * to store image data. If the #GtkImage has no image data,
1102  * the return value will be %GTK_IMAGE_EMPTY.
1103  * 
1104  * Return value: image representation being used
1105  **/
1106 GtkImageType
1107 gtk_image_get_storage_type (GtkImage *image)
1108 {
1109   g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
1110
1111   return image->priv->storage_type;
1112 }
1113
1114 /**
1115  * gtk_image_get_pixbuf:
1116  * @image: a #GtkImage
1117  *
1118  * Gets the #GdkPixbuf being displayed by the #GtkImage.
1119  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1120  * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1121  * The caller of this function does not own a reference to the
1122  * returned pixbuf.
1123  * 
1124  * Return value: (transfer none): the displayed pixbuf, or %NULL if
1125  * the image is empty
1126  **/
1127 GdkPixbuf*
1128 gtk_image_get_pixbuf (GtkImage *image)
1129 {
1130   GtkImagePrivate *priv;
1131
1132   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1133
1134   priv = image->priv;
1135
1136   g_return_val_if_fail (priv->storage_type == GTK_IMAGE_PIXBUF ||
1137                         priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1138
1139   if (priv->storage_type == GTK_IMAGE_EMPTY)
1140     priv->data.pixbuf.pixbuf = NULL;
1141
1142   return priv->data.pixbuf.pixbuf;
1143 }
1144
1145 /**
1146  * gtk_image_get_stock:
1147  * @image: a #GtkImage
1148  * @stock_id: (out) (transfer none) (allow-none): place to store a
1149  *     stock icon name, or %NULL
1150  * @size: (out) (allow-none) (type int): place to store a stock icon
1151  *     size, or %NULL
1152  *
1153  * Gets the stock icon name and size being displayed by the #GtkImage.
1154  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1155  * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1156  * The returned string is owned by the #GtkImage and should not
1157  * be freed.
1158  **/
1159 void
1160 gtk_image_get_stock  (GtkImage        *image,
1161                       gchar          **stock_id,
1162                       GtkIconSize     *size)
1163 {
1164   GtkImagePrivate *priv;
1165
1166   g_return_if_fail (GTK_IS_IMAGE (image));
1167
1168   priv = image->priv;
1169
1170   g_return_if_fail (priv->storage_type == GTK_IMAGE_STOCK ||
1171                     priv->storage_type == GTK_IMAGE_EMPTY);
1172
1173   if (priv->storage_type == GTK_IMAGE_EMPTY)
1174     priv->data.stock.stock_id = NULL;
1175
1176   if (stock_id)
1177     *stock_id = priv->data.stock.stock_id;
1178
1179   if (size)
1180     *size = priv->icon_size;
1181 }
1182
1183 /**
1184  * gtk_image_get_icon_set:
1185  * @image: a #GtkImage
1186  * @icon_set: (out) (transfer none) (allow-none): location to store a
1187  *     #GtkIconSet, or %NULL
1188  * @size: (out) (allow-none) (type int): location to store a stock
1189  *     icon size, or %NULL
1190  *
1191  * Gets the icon set and size being displayed by the #GtkImage.
1192  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1193  * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1194  **/
1195 void
1196 gtk_image_get_icon_set  (GtkImage        *image,
1197                          GtkIconSet     **icon_set,
1198                          GtkIconSize     *size)
1199 {
1200   GtkImagePrivate *priv;
1201
1202   g_return_if_fail (GTK_IS_IMAGE (image));
1203
1204   priv = image->priv;
1205
1206   g_return_if_fail (priv->storage_type == GTK_IMAGE_ICON_SET ||
1207                     priv->storage_type == GTK_IMAGE_EMPTY);
1208
1209   if (icon_set)
1210     *icon_set = priv->data.icon_set.icon_set;
1211
1212   if (size)
1213     *size = priv->icon_size;
1214 }
1215
1216 /**
1217  * gtk_image_get_animation:
1218  * @image: a #GtkImage
1219  *
1220  * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1221  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1222  * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1223  * The caller of this function does not own a reference to the
1224  * returned animation.
1225  * 
1226  * Return value: (transfer none): the displayed animation, or %NULL if
1227  * the image is empty
1228  **/
1229 GdkPixbufAnimation*
1230 gtk_image_get_animation (GtkImage *image)
1231 {
1232   GtkImagePrivate *priv;
1233
1234   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1235
1236   priv = image->priv;
1237
1238   g_return_val_if_fail (priv->storage_type == GTK_IMAGE_ANIMATION ||
1239                         priv->storage_type == GTK_IMAGE_EMPTY,
1240                         NULL);
1241
1242   if (priv->storage_type == GTK_IMAGE_EMPTY)
1243     priv->data.anim.anim = NULL;
1244
1245   return priv->data.anim.anim;
1246 }
1247
1248 /**
1249  * gtk_image_get_icon_name:
1250  * @image: a #GtkImage
1251  * @icon_name: (out) (transfer none) (allow-none): place to store an
1252  *     icon name, or %NULL
1253  * @size: (out) (allow-none) (type int): place to store an icon size,
1254  *     or %NULL
1255  *
1256  * Gets the icon name and size being displayed by the #GtkImage.
1257  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1258  * %GTK_IMAGE_ICON_NAME (see gtk_image_get_storage_type()).
1259  * The returned string is owned by the #GtkImage and should not
1260  * be freed.
1261  * 
1262  * Since: 2.6
1263  **/
1264 void
1265 gtk_image_get_icon_name  (GtkImage     *image,
1266                           const gchar **icon_name,
1267                           GtkIconSize  *size)
1268 {
1269   GtkImagePrivate *priv;
1270
1271   g_return_if_fail (GTK_IS_IMAGE (image));
1272
1273   priv = image->priv;
1274
1275   g_return_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME ||
1276                     priv->storage_type == GTK_IMAGE_EMPTY);
1277
1278   if (priv->storage_type == GTK_IMAGE_EMPTY)
1279     priv->data.name.icon_name = NULL;
1280
1281   if (icon_name)
1282     *icon_name = priv->data.name.icon_name;
1283
1284   if (size)
1285     *size = priv->icon_size;
1286 }
1287
1288 /**
1289  * gtk_image_get_gicon:
1290  * @image: a #GtkImage
1291  * @gicon: (out) (transfer none) (allow-none): place to store a
1292  *     #GIcon, or %NULL
1293  * @size: (out) (allow-none) (type int): place to store an icon size,
1294  *     or %NULL
1295  *
1296  * Gets the #GIcon and size being displayed by the #GtkImage.
1297  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1298  * %GTK_IMAGE_GICON (see gtk_image_get_storage_type()).
1299  * The caller of this function does not own a reference to the
1300  * returned #GIcon.
1301  * 
1302  * Since: 2.14
1303  **/
1304 void
1305 gtk_image_get_gicon (GtkImage     *image,
1306                      GIcon       **gicon,
1307                      GtkIconSize  *size)
1308 {
1309   GtkImagePrivate *priv;
1310
1311   g_return_if_fail (GTK_IS_IMAGE (image));
1312
1313   priv = image->priv;
1314
1315   g_return_if_fail (priv->storage_type == GTK_IMAGE_GICON ||
1316                     priv->storage_type == GTK_IMAGE_EMPTY);
1317
1318   if (priv->storage_type == GTK_IMAGE_EMPTY)
1319     priv->data.gicon.icon = NULL;
1320
1321   if (gicon)
1322     *gicon = priv->data.gicon.icon;
1323
1324   if (size)
1325     *size = priv->icon_size;
1326 }
1327
1328 /**
1329  * gtk_image_new:
1330  * 
1331  * Creates a new empty #GtkImage widget.
1332  * 
1333  * Return value: a newly created #GtkImage widget. 
1334  **/
1335 GtkWidget*
1336 gtk_image_new (void)
1337 {
1338   return g_object_new (GTK_TYPE_IMAGE, NULL);
1339 }
1340
1341 static void
1342 gtk_image_reset_anim_iter (GtkImage *image)
1343 {
1344   GtkImagePrivate *priv = image->priv;
1345
1346   if (priv->storage_type == GTK_IMAGE_ANIMATION)
1347     {
1348       /* Reset the animation */
1349       
1350       if (priv->data.anim.frame_timeout)
1351         {
1352           g_source_remove (priv->data.anim.frame_timeout);
1353           priv->data.anim.frame_timeout = 0;
1354         }
1355
1356       if (priv->data.anim.iter)
1357         {
1358           g_object_unref (priv->data.anim.iter);
1359           priv->data.anim.iter = NULL;
1360         }
1361     }
1362 }
1363
1364 static void
1365 gtk_image_unmap (GtkWidget *widget)
1366 {
1367   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1368
1369   GTK_WIDGET_CLASS (gtk_image_parent_class)->unmap (widget);
1370 }
1371
1372 static void
1373 gtk_image_unrealize (GtkWidget *widget)
1374 {
1375   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1376
1377   GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize (widget);
1378 }
1379
1380 static gint
1381 animation_timeout (gpointer data)
1382 {
1383   GtkImage *image = GTK_IMAGE (data);
1384   GtkImagePrivate *priv = image->priv;
1385   int delay;
1386
1387   priv->data.anim.frame_timeout = 0;
1388
1389   gdk_pixbuf_animation_iter_advance (priv->data.anim.iter, NULL);
1390
1391   delay = gdk_pixbuf_animation_iter_get_delay_time (priv->data.anim.iter);
1392   if (delay >= 0)
1393     {
1394       GtkWidget *widget = GTK_WIDGET (image);
1395
1396       priv->data.anim.frame_timeout =
1397         gdk_threads_add_timeout (delay, animation_timeout, image);
1398
1399       gtk_widget_queue_draw (widget);
1400
1401       if (gtk_widget_is_drawable (widget))
1402         gdk_window_process_updates (gtk_widget_get_window (widget), TRUE);
1403     }
1404
1405   return FALSE;
1406 }
1407
1408 static void
1409 icon_theme_changed (GtkImage *image)
1410 {
1411   GtkImagePrivate *priv = image->priv;
1412
1413   if (priv->storage_type == GTK_IMAGE_ICON_NAME)
1414     {
1415       if (priv->data.name.pixbuf)
1416         g_object_unref (priv->data.name.pixbuf);
1417       priv->data.name.pixbuf = NULL;
1418
1419       gtk_widget_queue_draw (GTK_WIDGET (image));
1420     }
1421   if (priv->storage_type == GTK_IMAGE_GICON)
1422     {
1423       if (priv->data.gicon.pixbuf)
1424         g_object_unref (priv->data.gicon.pixbuf);
1425       priv->data.gicon.pixbuf = NULL;
1426
1427       gtk_widget_queue_draw (GTK_WIDGET (image));
1428     }
1429 }
1430
1431 static void
1432 ensure_icon_size (GtkImage *image,
1433                   GtkIconLookupFlags *flags,
1434                   gint *width_out,
1435                   gint *height_out)
1436 {
1437   GtkImagePrivate *priv = image->priv;
1438   gint width, height;
1439   GtkSettings *settings;
1440   GdkScreen *screen;
1441   GtkIconTheme *icon_theme;
1442   gint *s, *sizes, dist;
1443
1444   screen = gtk_widget_get_screen (GTK_WIDGET (image));
1445   settings = gtk_settings_get_for_screen (screen);
1446   icon_theme = gtk_icon_theme_get_for_screen (screen);
1447
1448   if (priv->pixel_size != -1)
1449     {
1450       width = height = priv->pixel_size;
1451       *flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
1452     }
1453   else if (!gtk_icon_size_lookup_for_settings (settings,
1454                                                priv->icon_size,
1455                                                &width, &height))
1456     {
1457       if (priv->icon_size == -1)
1458         {
1459           /* Find an available size close to 48 */
1460           sizes = gtk_icon_theme_get_icon_sizes (icon_theme, priv->data.name.icon_name);
1461           dist = 100;
1462           width = height = 48;
1463           for (s = sizes; *s; s++)
1464             {
1465               if (*s == -1)
1466                 {
1467                   width = height = 48;
1468                   break;
1469                 }
1470               if (*s < 48)
1471                 {
1472                   if (48 - *s < dist)
1473                     {
1474                       width = height = *s;
1475                       dist = 48 - *s;
1476                     }
1477                 }
1478               else
1479                 {
1480                   if (*s - 48 < dist)
1481                     {
1482                       width = height = *s;
1483                       dist = *s - 48;
1484                     }
1485                 }
1486             }
1487           g_free (sizes);
1488         }
1489       else
1490         {
1491           g_warning ("Invalid icon size %d\n", priv->icon_size);
1492           width = height = 24;
1493         }
1494     }
1495
1496   *width_out = width;
1497   *height_out = height;
1498 }
1499
1500 static GdkPixbuf *
1501 ensure_stated_icon_from_info (GtkImage *image,
1502                               GtkIconInfo *info)
1503 {
1504   GtkImagePrivate *priv = image->priv;
1505   GtkStyleContext *context;
1506   GdkPixbuf *destination = NULL;
1507   gboolean symbolic;
1508
1509   context = gtk_widget_get_style_context (GTK_WIDGET (image));
1510   symbolic = FALSE;
1511
1512   if (info)
1513     destination =
1514       gtk_icon_info_load_symbolic_for_context (info,
1515                                                context,
1516                                                &symbolic,
1517                                                NULL);
1518
1519   if (destination == NULL)
1520     {
1521       destination =
1522         gtk_widget_render_icon_pixbuf (GTK_WIDGET (image),
1523                                        GTK_STOCK_MISSING_IMAGE,
1524                                        priv->icon_size);
1525     }
1526   else if (!symbolic)
1527     {
1528       GtkIconSource *source;
1529       GdkPixbuf *rendered;
1530
1531       source = gtk_icon_source_new ();
1532       gtk_icon_source_set_pixbuf (source, destination);
1533       /* The size here is arbitrary; since size isn't
1534        * wildcarded in the source, it isn't supposed to be
1535        * scaled by the engine function
1536        */
1537       gtk_icon_source_set_size (source,
1538                                 GTK_ICON_SIZE_SMALL_TOOLBAR);
1539       gtk_icon_source_set_size_wildcarded (source, FALSE);
1540
1541       rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
1542       gtk_icon_source_free (source);
1543
1544       g_object_unref (destination);
1545       destination = rendered;
1546     }
1547
1548   return destination;
1549 }
1550
1551 static void
1552 ensure_pixbuf_for_icon_name (GtkImage        *image,
1553                              GtkStateFlags    state)
1554 {
1555   GtkImagePrivate *priv = image->priv;
1556   GdkScreen *screen;
1557   GtkIconTheme *icon_theme;
1558   gint width, height;
1559   GtkIconInfo *info;
1560   GtkIconLookupFlags flags;
1561
1562   g_return_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME);
1563
1564   screen = gtk_widget_get_screen (GTK_WIDGET (image));
1565   icon_theme = gtk_icon_theme_get_for_screen (screen);
1566
1567   flags = GTK_ICON_LOOKUP_USE_BUILTIN;
1568
1569   if (priv->use_fallback)
1570     flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
1571
1572   if ((priv->data.name.pixbuf == NULL) ||
1573       (priv->last_rendered_state != state))
1574     {
1575       priv->last_rendered_state = state;
1576
1577       if (priv->data.name.pixbuf)
1578         {
1579           g_object_unref (priv->data.name.pixbuf);
1580           priv->data.name.pixbuf = NULL;
1581         }
1582
1583       ensure_icon_size (image, &flags, &width, &height);
1584       info = gtk_icon_theme_lookup_icon (icon_theme,
1585                                          priv->data.name.icon_name,
1586                                          MIN (width, height), flags);
1587
1588       priv->data.name.pixbuf = ensure_stated_icon_from_info (image, info);
1589
1590       if (info)
1591         gtk_icon_info_free (info);
1592     }
1593 }
1594
1595 static void
1596 ensure_pixbuf_for_gicon (GtkImage        *image,
1597                          GtkStateFlags    state)
1598 {
1599   GtkImagePrivate *priv = image->priv;
1600   GdkScreen *screen;
1601   GtkIconTheme *icon_theme;
1602   gint width, height;
1603   GtkIconInfo *info;
1604   GtkIconLookupFlags flags;
1605
1606   g_return_if_fail (priv->storage_type == GTK_IMAGE_GICON);
1607
1608   screen = gtk_widget_get_screen (GTK_WIDGET (image));
1609   icon_theme = gtk_icon_theme_get_for_screen (screen);
1610
1611   flags = GTK_ICON_LOOKUP_USE_BUILTIN;
1612
1613   if (priv->use_fallback)
1614     flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
1615
1616   if ((priv->data.gicon.pixbuf == NULL) ||
1617       (priv->last_rendered_state != state))
1618     {
1619       priv->last_rendered_state = state;
1620
1621       if (priv->data.gicon.pixbuf)
1622         {
1623           g_object_unref (priv->data.gicon.pixbuf);
1624           priv->data.gicon.pixbuf = NULL;
1625         }
1626
1627       ensure_icon_size (image, &flags, &width, &height);
1628       info = gtk_icon_theme_lookup_by_gicon (icon_theme,
1629                                              priv->data.gicon.icon,
1630                                              MIN (width, height), flags);
1631
1632       priv->data.gicon.pixbuf = ensure_stated_icon_from_info (image, info);
1633
1634       if (info)
1635         gtk_icon_info_free (info);
1636     }
1637 }
1638
1639 static gint
1640 gtk_image_draw (GtkWidget *widget,
1641                 cairo_t   *cr)
1642 {
1643   GtkImage *image;
1644   GtkImagePrivate *priv;
1645
1646   g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1647
1648   image = GTK_IMAGE (widget);
1649   priv = image->priv;
1650   
1651   if (priv->storage_type != GTK_IMAGE_EMPTY)
1652     {
1653       GtkMisc *misc;
1654       gint x, y;
1655       gint xpad, ypad;
1656       gfloat xalign, yalign;
1657       GdkPixbuf *pixbuf;
1658       GtkStateFlags state;
1659       GtkStyleContext *context;
1660
1661       misc = GTK_MISC (widget);
1662       context = gtk_widget_get_style_context (widget);
1663
1664       state = gtk_widget_get_state_flags (widget);
1665
1666       gtk_style_context_save (context);
1667       gtk_style_context_set_state (context, state);
1668
1669       /* For stock items and icon sets, we lazily calculate
1670        * the size; we might get here between a queue_resize()
1671        * and size_request() if something explicitely forces
1672        * a redraw.
1673        */
1674       if (priv->need_calc_size)
1675         gtk_image_calc_size (image);
1676
1677       gtk_misc_get_alignment (misc, &xalign, &yalign);
1678       gtk_misc_get_padding (misc, &xpad, &ypad);
1679
1680       if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
1681         xalign = 1.0 - xalign;
1682
1683       x = floor (xpad + ((gtk_widget_get_allocated_width (widget) - priv->required_width) * xalign));
1684       y = floor (ypad + ((gtk_widget_get_allocated_height (widget) - priv->required_height) * yalign));
1685
1686       switch (priv->storage_type)
1687         {
1688
1689         case GTK_IMAGE_PIXBUF:
1690           pixbuf = priv->data.pixbuf.pixbuf;
1691           g_object_ref (pixbuf);
1692           break;
1693
1694         case GTK_IMAGE_STOCK:
1695           pixbuf = gtk_widget_render_icon_pixbuf (widget,
1696                                                   priv->data.stock.stock_id,
1697                                                   priv->icon_size);
1698           break;
1699
1700         case GTK_IMAGE_ICON_SET:
1701           pixbuf =
1702             gtk_icon_set_render_icon_pixbuf (priv->data.icon_set.icon_set,
1703                                              context, priv->icon_size);
1704           break;
1705
1706         case GTK_IMAGE_ANIMATION:
1707           {
1708             if (priv->data.anim.iter == NULL)
1709               {
1710                 priv->data.anim.iter = gdk_pixbuf_animation_get_iter (priv->data.anim.anim, NULL);
1711                 
1712                 if (gdk_pixbuf_animation_iter_get_delay_time (priv->data.anim.iter) >= 0)
1713                   priv->data.anim.frame_timeout =
1714                     gdk_threads_add_timeout (gdk_pixbuf_animation_iter_get_delay_time (priv->data.anim.iter),
1715                                    animation_timeout,
1716                                    image);
1717               }
1718
1719             /* don't advance the anim iter here, or we could get frame changes between two
1720              * exposes of different areas.
1721              */
1722             
1723             pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (priv->data.anim.iter);
1724             g_object_ref (pixbuf);
1725           }
1726           break;
1727
1728         case GTK_IMAGE_ICON_NAME:
1729           ensure_pixbuf_for_icon_name (image, state);
1730           pixbuf = priv->data.name.pixbuf;
1731           if (pixbuf)
1732             {
1733               g_object_ref (pixbuf);
1734             }
1735           break;
1736
1737         case GTK_IMAGE_GICON:
1738           ensure_pixbuf_for_gicon (image, state);
1739           pixbuf = priv->data.gicon.pixbuf;
1740           if (pixbuf)
1741             {
1742               g_object_ref (pixbuf);
1743             }
1744           break;
1745
1746         case GTK_IMAGE_EMPTY:
1747         default:
1748           g_assert_not_reached ();
1749           pixbuf = NULL;
1750           break;
1751         }
1752
1753       if (pixbuf)
1754         {
1755           gtk_render_icon (context, cr,
1756                            pixbuf,
1757                            x, y);
1758
1759           g_object_unref (pixbuf);
1760         }
1761
1762       gtk_style_context_restore (context);
1763     }
1764
1765   return FALSE;
1766 }
1767
1768 static void
1769 gtk_image_reset (GtkImage *image)
1770 {
1771   GtkImagePrivate *priv = image->priv;
1772
1773   g_object_freeze_notify (G_OBJECT (image));
1774   
1775   if (priv->storage_type != GTK_IMAGE_EMPTY)
1776     g_object_notify (G_OBJECT (image), "storage-type");
1777
1778   if (priv->icon_size != DEFAULT_ICON_SIZE)
1779     {
1780       priv->icon_size = DEFAULT_ICON_SIZE;
1781       g_object_notify (G_OBJECT (image), "icon-size");
1782     }
1783   
1784   switch (priv->storage_type)
1785     {
1786
1787     case GTK_IMAGE_PIXBUF:
1788
1789       if (priv->data.pixbuf.pixbuf)
1790         g_object_unref (priv->data.pixbuf.pixbuf);
1791
1792       g_object_notify (G_OBJECT (image), "pixbuf");
1793       
1794       break;
1795
1796     case GTK_IMAGE_STOCK:
1797
1798       g_free (priv->data.stock.stock_id);
1799
1800       priv->data.stock.stock_id = NULL;
1801       
1802       g_object_notify (G_OBJECT (image), "stock");      
1803       break;
1804
1805     case GTK_IMAGE_ICON_SET:
1806       if (priv->data.icon_set.icon_set)
1807         gtk_icon_set_unref (priv->data.icon_set.icon_set);
1808       priv->data.icon_set.icon_set = NULL;
1809       
1810       g_object_notify (G_OBJECT (image), "icon-set");      
1811       break;
1812
1813     case GTK_IMAGE_ANIMATION:
1814       gtk_image_reset_anim_iter (image);
1815       
1816       if (priv->data.anim.anim)
1817         g_object_unref (priv->data.anim.anim);
1818       priv->data.anim.anim = NULL;
1819       
1820       g_object_notify (G_OBJECT (image), "pixbuf-animation");
1821       
1822       break;
1823
1824     case GTK_IMAGE_ICON_NAME:
1825       g_free (priv->data.name.icon_name);
1826       priv->data.name.icon_name = NULL;
1827       if (priv->data.name.pixbuf)
1828         g_object_unref (priv->data.name.pixbuf);
1829       priv->data.name.pixbuf = NULL;
1830
1831       g_object_notify (G_OBJECT (image), "icon-name");
1832
1833       break;
1834       
1835     case GTK_IMAGE_GICON:
1836       if (priv->data.gicon.icon)
1837         g_object_unref (priv->data.gicon.icon);
1838       priv->data.gicon.icon = NULL;
1839       if (priv->data.gicon.pixbuf)
1840         g_object_unref (priv->data.gicon.pixbuf);
1841       priv->data.gicon.pixbuf = NULL;
1842
1843       g_object_notify (G_OBJECT (image), "gicon");
1844
1845       break;
1846       
1847     case GTK_IMAGE_EMPTY:
1848     default:
1849       break;
1850       
1851     }
1852
1853   if (priv->filename)
1854     {
1855       g_free (priv->filename);
1856       priv->filename = NULL;
1857       g_object_notify (G_OBJECT (image), "file");
1858     }
1859
1860   priv->storage_type = GTK_IMAGE_EMPTY;
1861
1862   memset (&priv->data, '\0', sizeof (priv->data));
1863
1864   g_object_thaw_notify (G_OBJECT (image));
1865 }
1866
1867 /**
1868  * gtk_image_clear:
1869  * @image: a #GtkImage
1870  *
1871  * Resets the image to be empty.
1872  *
1873  * Since: 2.8
1874  */
1875 void
1876 gtk_image_clear (GtkImage *image)
1877 {
1878   GtkImagePrivate *priv = image->priv;
1879
1880   priv->need_calc_size = 1;
1881
1882   gtk_image_reset (image);
1883   gtk_image_update_size (image, 0, 0);
1884 }
1885
1886 static void
1887 gtk_image_calc_size (GtkImage *image)
1888 {
1889   GtkWidget *widget = GTK_WIDGET (image);
1890   GtkImagePrivate *priv = image->priv;
1891   GdkPixbuf *pixbuf = NULL;
1892   GtkStyleContext *context;
1893   GtkStateFlags state;
1894
1895   priv->need_calc_size = 0;
1896   context = gtk_widget_get_style_context (widget);
1897
1898   state = gtk_widget_get_state_flags (widget);
1899   gtk_style_context_save (context);
1900   gtk_style_context_set_state (context, state);
1901
1902   /* We update stock/icon set on every size request, because
1903    * the theme could have affected the size; for other kinds of
1904    * image, we just update the required width/height when the image data
1905    * is set.
1906    */
1907   switch (priv->storage_type)
1908     {
1909     case GTK_IMAGE_STOCK:
1910       pixbuf = gtk_widget_render_icon_pixbuf (widget,
1911                                               priv->data.stock.stock_id,
1912                                               priv->icon_size);
1913       break;
1914       
1915     case GTK_IMAGE_ICON_SET:
1916       pixbuf = gtk_icon_set_render_icon_pixbuf (priv->data.icon_set.icon_set,
1917                                                 context, priv->icon_size);
1918       break;
1919     case GTK_IMAGE_ICON_NAME:
1920       ensure_pixbuf_for_icon_name (image, state);
1921       pixbuf = priv->data.name.pixbuf;
1922       if (pixbuf) g_object_ref (pixbuf);
1923       break;
1924     case GTK_IMAGE_GICON:
1925       ensure_pixbuf_for_gicon (image, state);
1926       pixbuf = priv->data.gicon.pixbuf;
1927       if (pixbuf)
1928         g_object_ref (pixbuf);
1929       break;
1930     default:
1931       break;
1932     }
1933
1934   if (pixbuf)
1935     {
1936       gint xpad, ypad;
1937
1938       gtk_misc_get_padding (GTK_MISC (image), &xpad, &ypad);
1939
1940       priv->required_width = gdk_pixbuf_get_width (pixbuf) + xpad * 2;
1941       priv->required_height = gdk_pixbuf_get_height (pixbuf) + ypad * 2;
1942
1943       g_object_unref (pixbuf);
1944     }
1945
1946   gtk_style_context_restore (context);
1947 }
1948
1949 static void
1950 gtk_image_get_preferred_width (GtkWidget *widget,
1951                                gint      *minimum,
1952                                gint      *natural)
1953 {
1954   GtkImage *image;
1955   GtkImagePrivate *priv;
1956
1957   image = GTK_IMAGE (widget);
1958   priv  = image->priv;
1959
1960   gtk_image_calc_size (image);
1961
1962   *minimum = *natural = priv->required_width;
1963 }
1964
1965 static void
1966 gtk_image_get_preferred_height (GtkWidget *widget,
1967                                 gint      *minimum,
1968                                 gint      *natural)
1969 {
1970   GtkImage *image;
1971   GtkImagePrivate *priv;
1972
1973   image = GTK_IMAGE (widget);
1974   priv  = image->priv;
1975
1976   gtk_image_calc_size (image);
1977
1978   *minimum = *natural = priv->required_height;
1979 }
1980
1981 static void
1982 gtk_image_style_updated (GtkWidget *widget)
1983 {
1984   GTK_WIDGET_CLASS (gtk_image_parent_class)->style_updated (widget);
1985
1986   icon_theme_changed (GTK_IMAGE (widget));
1987 }
1988
1989 static void
1990 gtk_image_screen_changed (GtkWidget *widget,
1991                           GdkScreen *prev_screen)
1992 {
1993   GtkImage *image;
1994
1995   image = GTK_IMAGE (widget);
1996
1997   if (GTK_WIDGET_CLASS (gtk_image_parent_class)->screen_changed)
1998     GTK_WIDGET_CLASS (gtk_image_parent_class)->screen_changed (widget, prev_screen);
1999
2000   icon_theme_changed (image);
2001 }
2002
2003
2004 static void
2005 gtk_image_update_size (GtkImage *image,
2006                        gint      image_width,
2007                        gint      image_height)
2008 {
2009   GtkWidget       *widget = GTK_WIDGET (image);
2010   GtkImagePrivate *priv = image->priv;
2011   gint             xpad, ypad;
2012
2013   gtk_misc_get_padding (GTK_MISC (image), &xpad, &ypad);
2014
2015   priv->required_width  = image_width + xpad * 2;
2016   priv->required_height = image_height + ypad * 2;
2017
2018   if (gtk_widget_get_visible (widget))
2019     gtk_widget_queue_resize (widget);
2020 }
2021
2022 void
2023 _gtk_image_gicon_data_clear (GtkImageGIconData *data)
2024 {
2025   if (data->pixbuf)
2026     {
2027       g_object_unref (data->pixbuf);
2028       data->pixbuf = NULL;
2029     }
2030   if (data->icon)
2031     {
2032       g_object_unref (data->icon);
2033       data->icon = NULL;
2034     }
2035 }
2036
2037 /**
2038  * gtk_image_set_pixel_size:
2039  * @image: a #GtkImage
2040  * @pixel_size: the new pixel size
2041  * 
2042  * Sets the pixel size to use for named icons. If the pixel size is set
2043  * to a value != -1, it is used instead of the icon size set by
2044  * gtk_image_set_from_icon_name().
2045  *
2046  * Since: 2.6
2047  */
2048 void 
2049 gtk_image_set_pixel_size (GtkImage *image,
2050                           gint      pixel_size)
2051 {
2052   GtkImagePrivate *priv;
2053
2054   g_return_if_fail (GTK_IS_IMAGE (image));
2055
2056   priv = image->priv;
2057
2058   if (priv->pixel_size != pixel_size)
2059     {
2060       priv->pixel_size = pixel_size;
2061       
2062       if (priv->storage_type == GTK_IMAGE_ICON_NAME)
2063         {
2064           if (priv->data.name.pixbuf)
2065             {
2066               g_object_unref (priv->data.name.pixbuf);
2067               priv->data.name.pixbuf = NULL;
2068             }
2069           
2070           gtk_image_update_size (image, pixel_size, pixel_size);
2071         }
2072       
2073       if (priv->storage_type == GTK_IMAGE_GICON)
2074         {
2075           if (priv->data.gicon.pixbuf)
2076             {
2077               g_object_unref (priv->data.gicon.pixbuf);
2078               priv->data.gicon.pixbuf = NULL;
2079             }
2080           
2081           gtk_image_update_size (image, pixel_size, pixel_size);
2082         }
2083       
2084       g_object_notify (G_OBJECT (image), "pixel-size");
2085     }
2086 }
2087
2088 /**
2089  * gtk_image_get_pixel_size:
2090  * @image: a #GtkImage
2091  * 
2092  * Gets the pixel size used for named icons.
2093  *
2094  * Returns: the pixel size used for named icons.
2095  *
2096  * Since: 2.6
2097  */
2098 gint
2099 gtk_image_get_pixel_size (GtkImage *image)
2100 {
2101   g_return_val_if_fail (GTK_IS_IMAGE (image), -1);
2102
2103   return image->priv->pixel_size;
2104 }