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