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