]> Pileus Git - ~andy/gtk/blob - gtk/gtkimage.c
stylecontext: Do invalidation on first resize container
[~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, see <http://www.gnu.org/licenses/>.
16  */
17
18 /*
19  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GTK+ Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
23  */
24
25 #include "config.h"
26
27 #include <math.h>
28 #include <string.h>
29
30 #include "gtkcontainer.h"
31 #include "gtkiconhelperprivate.h"
32 #include "gtkimageprivate.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 #include "gtktypebuiltins.h"
40
41 #include "a11y/gtkimageaccessible.h"
42
43 /**
44  * SECTION:gtkimage
45  * @Short_description: A widget displaying an image
46  * @Title: GtkImage
47  * @See_also:#GdkPixbuf
48  *
49  * The #GtkImage widget displays an image. Various kinds of object
50  * can be displayed as an image; most typically, you would load a
51  * #GdkPixbuf ("pixel buffer") from a file, and then display that.
52  * There's a convenience function to do this, gtk_image_new_from_file(),
53  * used as follows:
54  * <informalexample><programlisting>
55  *   GtkWidget *image;
56  *   image = gtk_image_new_from_file ("myfile.png");
57  * </programlisting></informalexample>
58  * If the file isn't loaded successfully, the image will contain a
59  * "broken image" icon similar to that used in many web browsers.
60  * If you want to handle errors in loading the file yourself,
61  * for example by displaying an error message, then load the image with
62  * gdk_pixbuf_new_from_file(), then create the #GtkImage with
63  * gtk_image_new_from_pixbuf().
64  *
65  * The image file may contain an animation, if so the #GtkImage will
66  * display an animation (#GdkPixbufAnimation) instead of a static image.
67  *
68  * #GtkImage is a subclass of #GtkMisc, which implies that you can
69  * align it (center, left, right) and add padding to it, using
70  * #GtkMisc methods.
71  *
72  * #GtkImage is a "no window" widget (has no #GdkWindow of its own),
73  * so by default does not receive events. If you want to receive events
74  * on the image, such as button clicks, place the image inside a
75  * #GtkEventBox, then connect to the event signals on the event box.
76  * <example>
77  * <title>Handling button press events on a
78  * <structname>GtkImage</structname>.</title>
79  * <programlisting>
80  *   static gboolean
81  *   button_press_callback (GtkWidget      *event_box,
82  *                          GdkEventButton *event,
83  *                          gpointer        data)
84  *   {
85  *     g_print ("Event box clicked at coordinates &percnt;f,&percnt;f\n",
86  *              event->x, event->y);
87  *
88  *     /<!---->* Returning TRUE means we handled the event, so the signal
89  *      * emission should be stopped (don't call any further
90  *      * callbacks that may be connected). Return FALSE
91  *      * to continue invoking callbacks.
92  *      *<!---->/
93  *     return TRUE;
94  *   }
95  *
96  *   static GtkWidget*
97  *   create_image (void)
98  *   {
99  *     GtkWidget *image;
100  *     GtkWidget *event_box;
101  *
102  *     image = gtk_image_new_from_file ("myfile.png");
103  *
104  *     event_box = gtk_event_box_new (<!-- -->);
105  *
106  *     gtk_container_add (GTK_CONTAINER (event_box), image);
107  *
108  *     g_signal_connect (G_OBJECT (event_box),
109  *                       "button_press_event",
110  *                       G_CALLBACK (button_press_callback),
111  *                       image);
112  *
113  *     return image;
114  *   }
115  * </programlisting>
116  * </example>
117  *
118  * When handling events on the event box, keep in mind that coordinates
119  * in the image may be different from event box coordinates due to
120  * the alignment and padding settings on the image (see #GtkMisc).
121  * The simplest way to solve this is to set the alignment to 0.0
122  * (left/top), and set the padding to zero. Then the origin of
123  * the image will be the same as the origin of the event box.
124  *
125  * Sometimes an application will want to avoid depending on external data
126  * files, such as image files. GTK+ comes with a program to avoid this,
127  * called <application>gdk-pixbuf-csource</application>. This library
128  * allows you to convert an image into a C variable declaration, which
129  * can then be loaded into a #GdkPixbuf using
130  * gdk_pixbuf_new_from_inline().
131  */
132
133
134 struct _GtkImagePrivate
135 {
136   GtkIconHelper *icon_helper;
137
138   gint animation_timeout;
139   GdkPixbufAnimationIter *animation_iter;
140
141   gchar                *filename;       /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
142   gchar                *resource_path;  /* Only used with GTK_IMAGE_PIXBUF */
143 };
144
145
146 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
147 static gint gtk_image_draw                 (GtkWidget    *widget,
148                                             cairo_t      *cr);
149 static void gtk_image_unmap                (GtkWidget    *widget);
150 static void gtk_image_unrealize            (GtkWidget    *widget);
151 static void gtk_image_get_preferred_width  (GtkWidget    *widget,
152                                             gint         *minimum,
153                                             gint         *natural);
154 static void gtk_image_get_preferred_height (GtkWidget    *widget,
155                                             gint         *minimum,
156                                             gint         *natural);
157
158 static void gtk_image_style_updated        (GtkWidget    *widget);
159 static void gtk_image_screen_changed       (GtkWidget    *widget,
160                                             GdkScreen    *prev_screen);
161 static void gtk_image_finalize             (GObject      *object);
162 static void gtk_image_reset                (GtkImage     *image);
163
164 static void gtk_image_set_property         (GObject      *object,
165                                             guint         prop_id,
166                                             const GValue *value,
167                                             GParamSpec   *pspec);
168 static void gtk_image_get_property         (GObject      *object,
169                                             guint         prop_id,
170                                             GValue       *value,
171                                             GParamSpec   *pspec);
172
173 static void icon_theme_changed             (GtkImage     *image);
174
175 enum
176 {
177   PROP_0,
178   PROP_PIXBUF,
179   PROP_FILE,
180   PROP_STOCK,
181   PROP_ICON_SET,
182   PROP_ICON_SIZE,
183   PROP_PIXEL_SIZE,
184   PROP_PIXBUF_ANIMATION,
185   PROP_ICON_NAME,
186   PROP_STORAGE_TYPE,
187   PROP_GICON,
188   PROP_RESOURCE,
189   PROP_USE_FALLBACK
190 };
191
192 G_DEFINE_TYPE (GtkImage, gtk_image, GTK_TYPE_MISC)
193
194 static void
195 gtk_image_class_init (GtkImageClass *class)
196 {
197   GObjectClass *gobject_class;
198   GtkWidgetClass *widget_class;
199
200   gobject_class = G_OBJECT_CLASS (class);
201   
202   gobject_class->set_property = gtk_image_set_property;
203   gobject_class->get_property = gtk_image_get_property;
204   gobject_class->finalize = gtk_image_finalize;
205
206   widget_class = GTK_WIDGET_CLASS (class);
207   widget_class->draw = gtk_image_draw;
208   widget_class->get_preferred_width = gtk_image_get_preferred_width;
209   widget_class->get_preferred_height = gtk_image_get_preferred_height;
210   widget_class->unmap = gtk_image_unmap;
211   widget_class->unrealize = gtk_image_unrealize;
212   widget_class->style_updated = gtk_image_style_updated;
213   widget_class->screen_changed = gtk_image_screen_changed;
214   
215   g_object_class_install_property (gobject_class,
216                                    PROP_PIXBUF,
217                                    g_param_spec_object ("pixbuf",
218                                                         P_("Pixbuf"),
219                                                         P_("A GdkPixbuf to display"),
220                                                         GDK_TYPE_PIXBUF,
221                                                         GTK_PARAM_READWRITE));
222
223   g_object_class_install_property (gobject_class,
224                                    PROP_FILE,
225                                    g_param_spec_string ("file",
226                                                         P_("Filename"),
227                                                         P_("Filename to load and display"),
228                                                         NULL,
229                                                         GTK_PARAM_READWRITE));
230   
231
232   g_object_class_install_property (gobject_class,
233                                    PROP_STOCK,
234                                    g_param_spec_string ("stock",
235                                                         P_("Stock ID"),
236                                                         P_("Stock ID for a stock image to display"),
237                                                         NULL,
238                                                         GTK_PARAM_READWRITE));
239   
240   g_object_class_install_property (gobject_class,
241                                    PROP_ICON_SET,
242                                    g_param_spec_boxed ("icon-set",
243                                                        P_("Icon set"),
244                                                        P_("Icon set to display"),
245                                                        GTK_TYPE_ICON_SET,
246                                                        GTK_PARAM_READWRITE));
247   
248   g_object_class_install_property (gobject_class,
249                                    PROP_ICON_SIZE,
250                                    g_param_spec_int ("icon-size",
251                                                      P_("Icon size"),
252                                                      P_("Symbolic size to use for stock icon, icon set or named icon"),
253                                                      0, G_MAXINT,
254                                                      DEFAULT_ICON_SIZE,
255                                                      GTK_PARAM_READWRITE));
256   /**
257    * GtkImage:pixel-size:
258    *
259    * The "pixel-size" property can be used to specify a fixed size
260    * overriding the #GtkImage:icon-size property for images of type 
261    * %GTK_IMAGE_ICON_NAME. 
262    *
263    * Since: 2.6
264    */
265   g_object_class_install_property (gobject_class,
266                                    PROP_PIXEL_SIZE,
267                                    g_param_spec_int ("pixel-size",
268                                                      P_("Pixel size"),
269                                                      P_("Pixel size to use for named icon"),
270                                                      -1, G_MAXINT,
271                                                      -1,
272                                                      GTK_PARAM_READWRITE));
273   
274   g_object_class_install_property (gobject_class,
275                                    PROP_PIXBUF_ANIMATION,
276                                    g_param_spec_object ("pixbuf-animation",
277                                                         P_("Animation"),
278                                                         P_("GdkPixbufAnimation to display"),
279                                                         GDK_TYPE_PIXBUF_ANIMATION,
280                                                         GTK_PARAM_READWRITE));
281
282   /**
283    * GtkImage:icon-name:
284    *
285    * The name of the icon in the icon theme. If the icon theme is
286    * changed, the image will be updated automatically.
287    *
288    * Since: 2.6
289    */
290   g_object_class_install_property (gobject_class,
291                                    PROP_ICON_NAME,
292                                    g_param_spec_string ("icon-name",
293                                                         P_("Icon Name"),
294                                                         P_("The name of the icon from the icon theme"),
295                                                         NULL,
296                                                         GTK_PARAM_READWRITE));
297   
298   /**
299    * GtkImage:gicon:
300    *
301    * The GIcon displayed in the GtkImage. For themed icons,
302    * If the icon theme is changed, the image will be updated
303    * automatically.
304    *
305    * Since: 2.14
306    */
307   g_object_class_install_property (gobject_class,
308                                    PROP_GICON,
309                                    g_param_spec_object ("gicon",
310                                                         P_("Icon"),
311                                                         P_("The GIcon being displayed"),
312                                                         G_TYPE_ICON,
313                                                         GTK_PARAM_READWRITE));
314
315   /**
316    * GtkImage:resource:
317    *
318    * A path to a resource file to display.
319    *
320    * Since: 3.8
321    */
322   g_object_class_install_property (gobject_class,
323                                    PROP_RESOURCE,
324                                    g_param_spec_string ("resource",
325                                                         P_("Resource"),
326                                                         P_("The resource path being displayed"),
327                                                         NULL,
328                                                         GTK_PARAM_READWRITE));
329
330   g_object_class_install_property (gobject_class,
331                                    PROP_STORAGE_TYPE,
332                                    g_param_spec_enum ("storage-type",
333                                                       P_("Storage type"),
334                                                       P_("The representation being used for image data"),
335                                                       GTK_TYPE_IMAGE_TYPE,
336                                                       GTK_IMAGE_EMPTY,
337                                                       GTK_PARAM_READABLE));
338
339   /**
340    * GtkImage:use-fallback:
341    *
342    * Whether the icon displayed in the GtkImage will use
343    * standard icon names fallback. The value of this property
344    * is only relevant for images of type %GTK_IMAGE_ICON_NAME
345    * and %GTK_IMAGE_GICON.
346    *
347    * Since: 3.0
348    */
349   g_object_class_install_property (gobject_class,
350                                    PROP_USE_FALLBACK,
351                                    g_param_spec_boolean ("use-fallback",
352                                                          P_("Use Fallback"),
353                                                          P_("Whether to use icon names fallback"),
354                                                          FALSE,
355                                                          GTK_PARAM_READWRITE));
356
357   g_type_class_add_private (class, sizeof (GtkImagePrivate));
358
359   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_IMAGE_ACCESSIBLE);
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   priv->icon_helper = _gtk_icon_helper_new ();
374
375   priv->filename = NULL;
376 }
377
378 static void
379 gtk_image_finalize (GObject *object)
380 {
381   GtkImage *image = GTK_IMAGE (object);
382
383   g_clear_object (&image->priv->icon_helper);
384   
385   g_free (image->priv->filename);
386
387   G_OBJECT_CLASS (gtk_image_parent_class)->finalize (object);
388 };
389
390 static void 
391 gtk_image_set_property (GObject      *object,
392                         guint         prop_id,
393                         const GValue *value,
394                         GParamSpec   *pspec)
395 {
396   GtkImage *image = GTK_IMAGE (object);
397   GtkImagePrivate *priv = image->priv;
398   GtkIconSize icon_size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
399
400   if (icon_size == GTK_ICON_SIZE_INVALID)
401     icon_size = DEFAULT_ICON_SIZE;
402
403   switch (prop_id)
404     {
405     case PROP_PIXBUF:
406       gtk_image_set_from_pixbuf (image,
407                                  g_value_get_object (value));
408       break;
409     case PROP_FILE:
410       gtk_image_set_from_file (image, g_value_get_string (value));
411       break;
412     case PROP_STOCK:
413       gtk_image_set_from_stock (image, g_value_get_string (value),
414                                 icon_size);
415       break;
416     case PROP_ICON_SET:
417       gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
418                                    icon_size);
419       break;
420     case PROP_ICON_SIZE:
421       _gtk_icon_helper_set_icon_size (priv->icon_helper, g_value_get_int (value));
422       break;
423     case PROP_PIXEL_SIZE:
424       gtk_image_set_pixel_size (image, g_value_get_int (value));
425       break;
426     case PROP_PIXBUF_ANIMATION:
427       gtk_image_set_from_animation (image,
428                                     g_value_get_object (value));
429       break;
430     case PROP_ICON_NAME:
431       gtk_image_set_from_icon_name (image, g_value_get_string (value),
432                                     icon_size);
433       break;
434     case PROP_GICON:
435       gtk_image_set_from_gicon (image, g_value_get_object (value),
436                                 icon_size);
437       break;
438     case PROP_RESOURCE:
439       gtk_image_set_from_resource (image, g_value_get_string (value));
440       break;
441
442     case PROP_USE_FALLBACK:
443       _gtk_icon_helper_set_use_fallback (priv->icon_helper, g_value_get_boolean (value));
444       break;
445
446     default:
447       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
448       break;
449     }
450 }
451
452 static void 
453 gtk_image_get_property (GObject     *object,
454                         guint        prop_id,
455                         GValue      *value,
456                         GParamSpec  *pspec)
457 {
458   GtkImage *image = GTK_IMAGE (object);
459   GtkImagePrivate *priv = image->priv;
460
461   switch (prop_id)
462     {
463     case PROP_PIXBUF:
464       g_value_set_object (value, _gtk_icon_helper_peek_pixbuf (priv->icon_helper));
465       break;
466     case PROP_FILE:
467       g_value_set_string (value, priv->filename);
468       break;
469     case PROP_STOCK:
470       g_value_set_string (value, _gtk_icon_helper_get_stock_id (priv->icon_helper));
471       break;
472     case PROP_ICON_SET:
473       g_value_set_boxed (value, _gtk_icon_helper_peek_icon_set (priv->icon_helper));
474       break;      
475     case PROP_ICON_SIZE:
476       g_value_set_int (value, _gtk_icon_helper_get_icon_size (priv->icon_helper));
477       break;
478     case PROP_PIXEL_SIZE:
479       g_value_set_int (value, _gtk_icon_helper_get_pixel_size (priv->icon_helper));
480       break;
481     case PROP_PIXBUF_ANIMATION:
482       g_value_set_object (value, _gtk_icon_helper_peek_animation (priv->icon_helper));
483       break;
484     case PROP_ICON_NAME:
485       g_value_set_string (value, _gtk_icon_helper_get_icon_name (priv->icon_helper));
486       break;
487     case PROP_GICON:
488       g_value_set_object (value, _gtk_icon_helper_peek_gicon (priv->icon_helper));
489       break;
490     case PROP_RESOURCE:
491       g_value_set_string (value, priv->resource_path);
492       break;
493     case PROP_USE_FALLBACK:
494       g_value_set_boolean (value, _gtk_icon_helper_get_use_fallback (priv->icon_helper));
495       break;
496     case PROP_STORAGE_TYPE:
497       g_value_set_enum (value, _gtk_icon_helper_get_storage_type (priv->icon_helper));
498       break;
499     default:
500       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
501       break;
502     }
503 }
504
505
506 /**
507  * gtk_image_new_from_file:
508  * @filename: (type filename): a filename
509  * 
510  * Creates a new #GtkImage displaying the file @filename. If the file
511  * isn't found or can't be loaded, the resulting #GtkImage will
512  * display a "broken image" icon. This function never returns %NULL,
513  * it always returns a valid #GtkImage widget.
514  *
515  * If the file contains an animation, the image will contain an
516  * animation.
517  *
518  * If you need to detect failures to load the file, use
519  * gdk_pixbuf_new_from_file() to load the file yourself, then create
520  * the #GtkImage from the pixbuf. (Or for animations, use
521  * gdk_pixbuf_animation_new_from_file()).
522  *
523  * The storage type (gtk_image_get_storage_type()) of the returned
524  * image is not defined, it will be whatever is appropriate for
525  * displaying the file.
526  * 
527  * Return value: a new #GtkImage
528  **/
529 GtkWidget*
530 gtk_image_new_from_file   (const gchar *filename)
531 {
532   GtkImage *image;
533
534   image = g_object_new (GTK_TYPE_IMAGE, NULL);
535
536   gtk_image_set_from_file (image, filename);
537
538   return GTK_WIDGET (image);
539 }
540
541 /**
542  * gtk_image_new_from_resource:
543  * @resource_path: a resource path
544  *
545  * Creates a new #GtkImage displaying the resource file @resource_path. If the file
546  * isn't found or can't be loaded, the resulting #GtkImage will
547  * display a "broken image" icon. This function never returns %NULL,
548  * it always returns a valid #GtkImage widget.
549  *
550  * If the file contains an animation, the image will contain an
551  * animation.
552  *
553  * If you need to detect failures to load the file, use
554  * gdk_pixbuf_new_from_file() to load the file yourself, then create
555  * the #GtkImage from the pixbuf. (Or for animations, use
556  * gdk_pixbuf_animation_new_from_file()).
557  *
558  * The storage type (gtk_image_get_storage_type()) of the returned
559  * image is not defined, it will be whatever is appropriate for
560  * displaying the file.
561  *
562  * Return value: a new #GtkImage
563  *
564  * Since: 3.4
565  **/
566 GtkWidget*
567 gtk_image_new_from_resource (const gchar *resource_path)
568 {
569   GtkImage *image;
570
571   image = g_object_new (GTK_TYPE_IMAGE, NULL);
572
573   gtk_image_set_from_resource (image, resource_path);
574
575   return GTK_WIDGET (image);
576 }
577
578 /**
579  * gtk_image_new_from_pixbuf:
580  * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL
581  *
582  * Creates a new #GtkImage displaying @pixbuf.
583  * The #GtkImage does not assume a reference to the
584  * pixbuf; you still need to unref it if you own references.
585  * #GtkImage will add its own reference rather than adopting yours.
586  * 
587  * Note that this function just creates an #GtkImage from the pixbuf. The
588  * #GtkImage created will not react to state changes. Should you want that, 
589  * you should use gtk_image_new_from_icon_set().
590  * 
591  * Return value: a new #GtkImage
592  **/
593 GtkWidget*
594 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
595 {
596   GtkImage *image;
597
598   image = g_object_new (GTK_TYPE_IMAGE, NULL);
599
600   gtk_image_set_from_pixbuf (image, pixbuf);
601
602   return GTK_WIDGET (image);  
603 }
604
605 /**
606  * gtk_image_new_from_stock:
607  * @stock_id: a stock icon name
608  * @size: (type int): a stock icon size
609  * 
610  * Creates a #GtkImage displaying a stock icon. Sample stock icon
611  * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. Sample stock sizes
612  * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
613  * icon name isn't known, the image will be empty.
614  * You can register your own stock icon names, see
615  * gtk_icon_factory_add_default() and gtk_icon_factory_add().
616  * 
617  * Return value: a new #GtkImage displaying the stock icon
618  **/
619 GtkWidget*
620 gtk_image_new_from_stock (const gchar    *stock_id,
621                           GtkIconSize     size)
622 {
623   GtkImage *image;
624
625   image = g_object_new (GTK_TYPE_IMAGE, NULL);
626
627   gtk_image_set_from_stock (image, stock_id, size);
628
629   return GTK_WIDGET (image);
630 }
631
632 /**
633  * gtk_image_new_from_icon_set:
634  * @icon_set: a #GtkIconSet
635  * @size: (type int): a stock icon size
636  *
637  * Creates a #GtkImage displaying an icon set. Sample stock sizes are
638  * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
639  * this function, usually it's better to create a #GtkIconFactory, put
640  * your icon sets in the icon factory, add the icon factory to the
641  * list of default factories with gtk_icon_factory_add_default(), and
642  * then use gtk_image_new_from_stock(). This will allow themes to
643  * override the icon you ship with your application.
644  *
645  * The #GtkImage does not assume a reference to the
646  * icon set; you still need to unref it if you own references.
647  * #GtkImage will add its own reference rather than adopting yours.
648  * 
649  * Return value: a new #GtkImage
650  **/
651 GtkWidget*
652 gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
653                              GtkIconSize     size)
654 {
655   GtkImage *image;
656
657   image = g_object_new (GTK_TYPE_IMAGE, NULL);
658
659   gtk_image_set_from_icon_set (image, icon_set, size);
660
661   return GTK_WIDGET (image);
662 }
663
664 /**
665  * gtk_image_new_from_animation:
666  * @animation: an animation
667  * 
668  * Creates a #GtkImage displaying the given animation.
669  * The #GtkImage does not assume a reference to the
670  * animation; you still need to unref it if you own references.
671  * #GtkImage will add its own reference rather than adopting yours.
672  *
673  * Note that the animation frames are shown using a timeout with
674  * #G_PRIORITY_DEFAULT. When using animations to indicate busyness,
675  * keep in mind that the animation will only be shown if the main loop
676  * is not busy with something that has a higher priority.
677  *
678  * Return value: a new #GtkImage widget
679  **/
680 GtkWidget*
681 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
682 {
683   GtkImage *image;
684
685   g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
686   
687   image = g_object_new (GTK_TYPE_IMAGE, NULL);
688
689   gtk_image_set_from_animation (image, animation);
690
691   return GTK_WIDGET (image);
692 }
693
694 /**
695  * gtk_image_new_from_icon_name:
696  * @icon_name: an icon name
697  * @size: (type int): a stock icon size
698  * 
699  * Creates a #GtkImage displaying an icon from the current icon theme.
700  * If the icon name isn't known, a "broken image" icon will be
701  * displayed instead.  If the current icon theme is changed, the icon
702  * will be updated appropriately.
703  * 
704  * Return value: a new #GtkImage displaying the themed icon
705  *
706  * Since: 2.6
707  **/
708 GtkWidget*
709 gtk_image_new_from_icon_name (const gchar    *icon_name,
710                               GtkIconSize     size)
711 {
712   GtkImage *image;
713
714   image = g_object_new (GTK_TYPE_IMAGE, NULL);
715
716   gtk_image_set_from_icon_name (image, icon_name, size);
717
718   return GTK_WIDGET (image);
719 }
720
721 /**
722  * gtk_image_new_from_gicon:
723  * @icon: an icon
724  * @size: (type int): a stock icon size
725  * 
726  * Creates a #GtkImage displaying an icon from the current icon theme.
727  * If the icon name isn't known, a "broken image" icon will be
728  * displayed instead.  If the current icon theme is changed, the icon
729  * will be updated appropriately.
730  * 
731  * Return value: a new #GtkImage displaying the themed icon
732  *
733  * Since: 2.14
734  **/
735 GtkWidget*
736 gtk_image_new_from_gicon (GIcon *icon,
737                           GtkIconSize     size)
738 {
739   GtkImage *image;
740
741   image = g_object_new (GTK_TYPE_IMAGE, NULL);
742
743   gtk_image_set_from_gicon (image, icon, size);
744
745   return GTK_WIDGET (image);
746 }
747
748 /**
749  * gtk_image_set_from_file:
750  * @image: a #GtkImage
751  * @filename: (type filename) (allow-none): a filename or %NULL
752  *
753  * See gtk_image_new_from_file() for details.
754  **/
755 void
756 gtk_image_set_from_file   (GtkImage    *image,
757                            const gchar *filename)
758 {
759   GtkImagePrivate *priv;
760   GdkPixbufAnimation *anim;
761   
762   g_return_if_fail (GTK_IS_IMAGE (image));
763
764   priv = image->priv;
765
766   g_object_freeze_notify (G_OBJECT (image));
767   
768   gtk_image_clear (image);
769
770   if (filename == NULL)
771     {
772       priv->filename = NULL;
773       g_object_thaw_notify (G_OBJECT (image));
774       return;
775     }
776
777   anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
778
779   if (anim == NULL)
780     {
781       gtk_image_set_from_stock (image,
782                                 GTK_STOCK_MISSING_IMAGE,
783                                 DEFAULT_ICON_SIZE);
784       g_object_thaw_notify (G_OBJECT (image));
785       return;
786     }
787
788   /* We could just unconditionally set_from_animation,
789    * but it's nicer for memory if we toss the animation
790    * if it's just a single pixbuf
791    */
792
793   if (gdk_pixbuf_animation_is_static_image (anim))
794     gtk_image_set_from_pixbuf (image,
795                                gdk_pixbuf_animation_get_static_image (anim));
796   else
797     gtk_image_set_from_animation (image, anim);
798
799   g_object_unref (anim);
800
801   priv->filename = g_strdup (filename);
802   
803   g_object_thaw_notify (G_OBJECT (image));
804 }
805
806 /**
807  * gtk_image_set_from_resource:
808  * @image: a #GtkImage
809  * @resource_path: (allow-none): a resource path or %NULL
810  *
811  * See gtk_image_new_from_resource() for details.
812  **/
813 void
814 gtk_image_set_from_resource (GtkImage    *image,
815                              const gchar *resource_path)
816 {
817   GtkImagePrivate *priv;
818   GdkPixbufAnimation *animation;
819
820   g_return_if_fail (GTK_IS_IMAGE (image));
821
822   priv = image->priv;
823
824   g_object_freeze_notify (G_OBJECT (image));
825
826   gtk_image_clear (image);
827
828   if (resource_path == NULL)
829     {
830       g_object_thaw_notify (G_OBJECT (image));
831       return;
832     }
833
834   animation = gdk_pixbuf_animation_new_from_resource (resource_path, NULL);
835
836   if (animation == NULL)
837     {
838       gtk_image_set_from_stock (image,
839                                 GTK_STOCK_MISSING_IMAGE,
840                                 DEFAULT_ICON_SIZE);
841       g_object_thaw_notify (G_OBJECT (image));
842       return;
843     }
844
845   priv->resource_path = g_strdup (resource_path);
846
847   if (gdk_pixbuf_animation_is_static_image (animation))
848     gtk_image_set_from_pixbuf (image, gdk_pixbuf_animation_get_static_image (animation));
849   else
850     gtk_image_set_from_animation (image, animation);
851
852   g_object_notify (G_OBJECT (image), "resource");
853
854   g_object_unref (animation);
855
856   g_object_thaw_notify (G_OBJECT (image));
857 }
858
859
860 /**
861  * gtk_image_set_from_pixbuf:
862  * @image: a #GtkImage
863  * @pixbuf: (allow-none): a #GdkPixbuf or %NULL
864  *
865  * See gtk_image_new_from_pixbuf() for details.
866  **/
867 void
868 gtk_image_set_from_pixbuf (GtkImage  *image,
869                            GdkPixbuf *pixbuf)
870 {
871   GtkImagePrivate *priv;
872
873   g_return_if_fail (GTK_IS_IMAGE (image));
874   g_return_if_fail (pixbuf == NULL ||
875                     GDK_IS_PIXBUF (pixbuf));
876
877   priv = image->priv;
878
879   g_object_freeze_notify (G_OBJECT (image));
880   
881   gtk_image_clear (image);
882
883   if (pixbuf != NULL)
884     _gtk_icon_helper_set_pixbuf (priv->icon_helper, pixbuf);
885
886   g_object_notify (G_OBJECT (image), "pixbuf");
887   
888   g_object_thaw_notify (G_OBJECT (image));
889 }
890
891 /**
892  * gtk_image_set_from_stock:
893  * @image: a #GtkImage
894  * @stock_id: a stock icon name
895  * @size: (type int): a stock icon size
896  *
897  * See gtk_image_new_from_stock() for details.
898  **/
899 void
900 gtk_image_set_from_stock  (GtkImage       *image,
901                            const gchar    *stock_id,
902                            GtkIconSize     size)
903 {
904   GtkImagePrivate *priv;
905   gchar *new_id;
906
907   g_return_if_fail (GTK_IS_IMAGE (image));
908
909   priv = image->priv;
910
911   g_object_freeze_notify (G_OBJECT (image));
912
913   new_id = g_strdup (stock_id);
914   gtk_image_clear (image);
915
916   if (new_id)
917     {
918       _gtk_icon_helper_set_stock_id (priv->icon_helper, new_id, size);
919       g_free (new_id);
920     }
921
922   g_object_notify (G_OBJECT (image), "stock");
923   g_object_notify (G_OBJECT (image), "icon-size");
924   
925   g_object_thaw_notify (G_OBJECT (image));
926 }
927
928 /**
929  * gtk_image_set_from_icon_set:
930  * @image: a #GtkImage
931  * @icon_set: a #GtkIconSet
932  * @size: (type int): a stock icon size
933  *
934  * See gtk_image_new_from_icon_set() for details.
935  **/
936 void
937 gtk_image_set_from_icon_set  (GtkImage       *image,
938                               GtkIconSet     *icon_set,
939                               GtkIconSize     size)
940 {
941   GtkImagePrivate *priv;
942
943   g_return_if_fail (GTK_IS_IMAGE (image));
944
945   priv = image->priv;
946
947   g_object_freeze_notify (G_OBJECT (image));
948
949   if (icon_set)
950     gtk_icon_set_ref (icon_set);
951   
952   gtk_image_clear (image);
953
954   if (icon_set)
955     {      
956       _gtk_icon_helper_set_icon_set (priv->icon_helper, icon_set, size);
957       gtk_icon_set_unref (icon_set);
958     }
959   
960   g_object_notify (G_OBJECT (image), "icon-set");
961   g_object_notify (G_OBJECT (image), "icon-size");
962   
963   g_object_thaw_notify (G_OBJECT (image));
964 }
965
966 /**
967  * gtk_image_set_from_animation:
968  * @image: a #GtkImage
969  * @animation: the #GdkPixbufAnimation
970  * 
971  * Causes the #GtkImage to display the given animation (or display
972  * nothing, if you set the animation to %NULL).
973  **/
974 void
975 gtk_image_set_from_animation (GtkImage           *image,
976                               GdkPixbufAnimation *animation)
977 {
978   GtkImagePrivate *priv;
979
980   g_return_if_fail (GTK_IS_IMAGE (image));
981   g_return_if_fail (animation == NULL ||
982                     GDK_IS_PIXBUF_ANIMATION (animation));
983
984   priv = image->priv;
985
986   g_object_freeze_notify (G_OBJECT (image));
987   
988   if (animation)
989     g_object_ref (animation);
990
991   gtk_image_clear (image);
992
993   if (animation != NULL)
994     {
995       _gtk_icon_helper_set_animation (priv->icon_helper, animation);
996       g_object_unref (animation);
997     }
998
999   g_object_notify (G_OBJECT (image), "pixbuf-animation");
1000   
1001   g_object_thaw_notify (G_OBJECT (image));
1002 }
1003
1004 /**
1005  * gtk_image_set_from_icon_name:
1006  * @image: a #GtkImage
1007  * @icon_name: an icon name
1008  * @size: (type int): an icon size
1009  *
1010  * See gtk_image_new_from_icon_name() for details.
1011  * 
1012  * Since: 2.6
1013  **/
1014 void
1015 gtk_image_set_from_icon_name  (GtkImage       *image,
1016                                const gchar    *icon_name,
1017                                GtkIconSize     size)
1018 {
1019   GtkImagePrivate *priv;
1020   gchar *new_name;
1021
1022   g_return_if_fail (GTK_IS_IMAGE (image));
1023
1024   priv = image->priv;
1025
1026   g_object_freeze_notify (G_OBJECT (image));
1027
1028   new_name = g_strdup (icon_name);
1029   gtk_image_clear (image);
1030
1031   if (new_name)
1032     {
1033       _gtk_icon_helper_set_icon_name (priv->icon_helper, new_name, size);
1034       g_free (new_name);
1035     }
1036
1037   g_object_notify (G_OBJECT (image), "icon-name");
1038   g_object_notify (G_OBJECT (image), "icon-size");
1039   
1040   g_object_thaw_notify (G_OBJECT (image));
1041 }
1042
1043 /**
1044  * gtk_image_set_from_gicon:
1045  * @image: a #GtkImage
1046  * @icon: an icon
1047  * @size: (type int): an icon size
1048  *
1049  * See gtk_image_new_from_gicon() for details.
1050  * 
1051  * Since: 2.14
1052  **/
1053 void
1054 gtk_image_set_from_gicon  (GtkImage       *image,
1055                            GIcon          *icon,
1056                            GtkIconSize     size)
1057 {
1058   GtkImagePrivate *priv;
1059
1060   g_return_if_fail (GTK_IS_IMAGE (image));
1061
1062   priv = image->priv;
1063
1064   g_object_freeze_notify (G_OBJECT (image));
1065
1066   if (icon)
1067     g_object_ref (icon);
1068
1069   gtk_image_clear (image);
1070
1071   if (icon)
1072     {
1073       _gtk_icon_helper_set_gicon (priv->icon_helper, icon, size);
1074       g_object_unref (icon);
1075     }
1076
1077   g_object_notify (G_OBJECT (image), "gicon");
1078   g_object_notify (G_OBJECT (image), "icon-size");
1079   
1080   g_object_thaw_notify (G_OBJECT (image));
1081 }
1082
1083 /**
1084  * gtk_image_get_storage_type:
1085  * @image: a #GtkImage
1086  * 
1087  * Gets the type of representation being used by the #GtkImage
1088  * to store image data. If the #GtkImage has no image data,
1089  * the return value will be %GTK_IMAGE_EMPTY.
1090  * 
1091  * Return value: image representation being used
1092  **/
1093 GtkImageType
1094 gtk_image_get_storage_type (GtkImage *image)
1095 {
1096   g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
1097
1098   return _gtk_icon_helper_get_storage_type (image->priv->icon_helper);
1099 }
1100
1101 /**
1102  * gtk_image_get_pixbuf:
1103  * @image: a #GtkImage
1104  *
1105  * Gets the #GdkPixbuf being displayed by the #GtkImage.
1106  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1107  * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1108  * The caller of this function does not own a reference to the
1109  * returned pixbuf.
1110  * 
1111  * Return value: (transfer none): the displayed pixbuf, or %NULL if
1112  * the image is empty
1113  **/
1114 GdkPixbuf*
1115 gtk_image_get_pixbuf (GtkImage *image)
1116 {
1117   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1118
1119   return _gtk_icon_helper_peek_pixbuf (image->priv->icon_helper);
1120 }
1121
1122 /**
1123  * gtk_image_get_stock:
1124  * @image: a #GtkImage
1125  * @stock_id: (out) (transfer none) (allow-none): place to store a
1126  *     stock icon name, or %NULL
1127  * @size: (out) (allow-none) (type int): place to store a stock icon
1128  *     size, or %NULL
1129  *
1130  * Gets the stock icon name and size being displayed by the #GtkImage.
1131  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1132  * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1133  * The returned string is owned by the #GtkImage and should not
1134  * be freed.
1135  **/
1136 void
1137 gtk_image_get_stock  (GtkImage        *image,
1138                       gchar          **stock_id,
1139                       GtkIconSize     *size)
1140 {
1141   GtkImagePrivate *priv;
1142
1143   g_return_if_fail (GTK_IS_IMAGE (image));
1144
1145   priv = image->priv;
1146
1147   if (stock_id)
1148     *stock_id = (gchar *) _gtk_icon_helper_get_stock_id (priv->icon_helper);
1149
1150   if (size)
1151     *size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
1152 }
1153
1154 /**
1155  * gtk_image_get_icon_set:
1156  * @image: a #GtkImage
1157  * @icon_set: (out) (transfer none) (allow-none): location to store a
1158  *     #GtkIconSet, or %NULL
1159  * @size: (out) (allow-none) (type int): location to store a stock
1160  *     icon size, or %NULL
1161  *
1162  * Gets the icon set and size being displayed by the #GtkImage.
1163  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1164  * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1165  **/
1166 void
1167 gtk_image_get_icon_set  (GtkImage        *image,
1168                          GtkIconSet     **icon_set,
1169                          GtkIconSize     *size)
1170 {
1171   GtkImagePrivate *priv;
1172
1173   g_return_if_fail (GTK_IS_IMAGE (image));
1174
1175   priv = image->priv;
1176
1177   if (icon_set)
1178     *icon_set = _gtk_icon_helper_peek_icon_set (priv->icon_helper);
1179
1180   if (size)
1181     *size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
1182 }
1183
1184 /**
1185  * gtk_image_get_animation:
1186  * @image: a #GtkImage
1187  *
1188  * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1189  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1190  * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1191  * The caller of this function does not own a reference to the
1192  * returned animation.
1193  * 
1194  * Return value: (transfer none): the displayed animation, or %NULL if
1195  * the image is empty
1196  **/
1197 GdkPixbufAnimation*
1198 gtk_image_get_animation (GtkImage *image)
1199 {
1200   GtkImagePrivate *priv;
1201
1202   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1203
1204   priv = image->priv;
1205
1206   return _gtk_icon_helper_peek_animation (priv->icon_helper);
1207 }
1208
1209 /**
1210  * gtk_image_get_icon_name:
1211  * @image: a #GtkImage
1212  * @icon_name: (out) (transfer none) (allow-none): place to store an
1213  *     icon name, or %NULL
1214  * @size: (out) (allow-none) (type int): place to store an icon size,
1215  *     or %NULL
1216  *
1217  * Gets the icon name and size being displayed by the #GtkImage.
1218  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1219  * %GTK_IMAGE_ICON_NAME (see gtk_image_get_storage_type()).
1220  * The returned string is owned by the #GtkImage and should not
1221  * be freed.
1222  * 
1223  * Since: 2.6
1224  **/
1225 void
1226 gtk_image_get_icon_name  (GtkImage     *image,
1227                           const gchar **icon_name,
1228                           GtkIconSize  *size)
1229 {
1230   GtkImagePrivate *priv;
1231
1232   g_return_if_fail (GTK_IS_IMAGE (image));
1233
1234   priv = image->priv;
1235
1236   if (icon_name)
1237     *icon_name = _gtk_icon_helper_get_icon_name (priv->icon_helper);
1238
1239   if (size)
1240     *size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
1241 }
1242
1243 /**
1244  * gtk_image_get_gicon:
1245  * @image: a #GtkImage
1246  * @gicon: (out) (transfer none) (allow-none): place to store a
1247  *     #GIcon, or %NULL
1248  * @size: (out) (allow-none) (type int): place to store an icon size,
1249  *     or %NULL
1250  *
1251  * Gets the #GIcon and size being displayed by the #GtkImage.
1252  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1253  * %GTK_IMAGE_GICON (see gtk_image_get_storage_type()).
1254  * The caller of this function does not own a reference to the
1255  * returned #GIcon.
1256  * 
1257  * Since: 2.14
1258  **/
1259 void
1260 gtk_image_get_gicon (GtkImage     *image,
1261                      GIcon       **gicon,
1262                      GtkIconSize  *size)
1263 {
1264   GtkImagePrivate *priv;
1265
1266   g_return_if_fail (GTK_IS_IMAGE (image));
1267
1268   priv = image->priv;
1269
1270   if (gicon)
1271     *gicon = _gtk_icon_helper_peek_gicon (priv->icon_helper);
1272
1273   if (size)
1274     *size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
1275 }
1276
1277 /**
1278  * gtk_image_new:
1279  * 
1280  * Creates a new empty #GtkImage widget.
1281  * 
1282  * Return value: a newly created #GtkImage widget. 
1283  **/
1284 GtkWidget*
1285 gtk_image_new (void)
1286 {
1287   return g_object_new (GTK_TYPE_IMAGE, NULL);
1288 }
1289
1290 static void
1291 gtk_image_reset_anim_iter (GtkImage *image)
1292 {
1293   GtkImagePrivate *priv = image->priv;
1294
1295   if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
1296     {
1297       /* Reset the animation */
1298       if (priv->animation_timeout)
1299         {
1300           g_source_remove (priv->animation_timeout);
1301           priv->animation_timeout = 0;
1302         }
1303
1304       g_clear_object (&priv->animation_iter);
1305     }
1306 }
1307
1308 static void
1309 gtk_image_unmap (GtkWidget *widget)
1310 {
1311   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1312
1313   GTK_WIDGET_CLASS (gtk_image_parent_class)->unmap (widget);
1314 }
1315
1316 static void
1317 gtk_image_unrealize (GtkWidget *widget)
1318 {
1319   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1320
1321   GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize (widget);
1322 }
1323
1324 static gint
1325 animation_timeout (gpointer data)
1326 {
1327   GtkImage *image = GTK_IMAGE (data);
1328   GtkImagePrivate *priv = image->priv;
1329   int delay;
1330
1331   priv->animation_timeout = 0;
1332
1333   gdk_pixbuf_animation_iter_advance (priv->animation_iter, NULL);
1334
1335   delay = gdk_pixbuf_animation_iter_get_delay_time (priv->animation_iter);
1336   if (delay >= 0)
1337     {
1338       GtkWidget *widget = GTK_WIDGET (image);
1339
1340       priv->animation_timeout =
1341         gdk_threads_add_timeout (delay, animation_timeout, image);
1342
1343       gtk_widget_queue_draw (widget);
1344     }
1345
1346   return FALSE;
1347 }
1348
1349 static GdkPixbuf *
1350 get_animation_frame (GtkImage *image)
1351 {
1352   GtkImagePrivate *priv = image->priv;
1353
1354   if (priv->animation_iter == NULL)
1355     {
1356       int delay;
1357
1358       priv->animation_iter = 
1359         gdk_pixbuf_animation_get_iter (_gtk_icon_helper_peek_animation (priv->icon_helper), NULL);
1360
1361       delay = gdk_pixbuf_animation_iter_get_delay_time (priv->animation_iter);
1362       if (delay >= 0)
1363         priv->animation_timeout =
1364           gdk_threads_add_timeout (delay, animation_timeout, image);
1365     }
1366
1367   /* don't advance the anim iter here, or we could get frame changes between two
1368    * exposes of different areas.
1369    */
1370   return g_object_ref (gdk_pixbuf_animation_iter_get_pixbuf (priv->animation_iter));
1371 }
1372
1373 static void
1374 gtk_image_get_preferred_size (GtkImage *image,
1375                               gint     *width_out,
1376                               gint     *height_out)
1377 {
1378   GtkImagePrivate *priv = image->priv;
1379   gint width, height;
1380   GtkBorder border;
1381   GtkStyleContext *context;
1382
1383   context = gtk_widget_get_style_context (GTK_WIDGET (image));
1384   _gtk_icon_helper_get_size (priv->icon_helper, context, &width, &height);
1385   _gtk_misc_get_padding_and_border (GTK_MISC (image), &border);
1386
1387   width += border.left + border.right;
1388   height += border.top + border.bottom;
1389
1390   if (width_out)
1391     *width_out = width;
1392   if (height_out)
1393     *height_out = height;
1394 }
1395
1396 static gint
1397 gtk_image_draw (GtkWidget *widget,
1398                 cairo_t   *cr)
1399 {
1400   GtkImage *image;
1401   GtkImagePrivate *priv;
1402   GtkMisc *misc;
1403   GtkStyleContext *context;
1404   gint x, y, width, height;
1405   gfloat xalign, yalign;
1406   GtkBorder border;
1407
1408   g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1409
1410   image = GTK_IMAGE (widget);
1411   misc = GTK_MISC (image);
1412   priv = image->priv;
1413
1414   context = gtk_widget_get_style_context (widget);
1415
1416   gtk_render_background (context, cr,
1417                          0, 0,
1418                          gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget));
1419   gtk_render_frame (context, cr,
1420                     0, 0,
1421                     gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget));
1422
1423   gtk_misc_get_alignment (misc, &xalign, &yalign);
1424   gtk_image_get_preferred_size (image, &width, &height);
1425   _gtk_misc_get_padding_and_border (misc, &border);
1426
1427   if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
1428     xalign = 1.0 - xalign;
1429
1430   x = floor ((gtk_widget_get_allocated_width (widget) - width) * xalign) + border.left;
1431   y = floor ((gtk_widget_get_allocated_height (widget) - height) * yalign) + border.top;
1432
1433   if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
1434     {
1435       GdkPixbuf *pixbuf = get_animation_frame (image);
1436       gtk_render_icon (context, cr,
1437                        pixbuf,
1438                        x, y);
1439       g_object_unref (pixbuf);
1440     }
1441   else
1442     {
1443       _gtk_icon_helper_draw (priv->icon_helper, 
1444                              context, cr,
1445                              x, y);
1446     }
1447
1448   return FALSE;
1449 }
1450
1451 static void
1452 gtk_image_reset (GtkImage *image)
1453 {
1454   GtkImagePrivate *priv = image->priv;
1455   GtkImageType storage_type;
1456
1457   g_object_freeze_notify (G_OBJECT (image));
1458   storage_type = gtk_image_get_storage_type (image);
1459   
1460   if (storage_type != GTK_IMAGE_EMPTY)
1461     g_object_notify (G_OBJECT (image), "storage-type");
1462
1463   g_object_notify (G_OBJECT (image), "icon-size");
1464   
1465   switch (storage_type)
1466     {
1467     case GTK_IMAGE_PIXBUF:
1468       g_object_notify (G_OBJECT (image), "pixbuf");
1469       break;
1470     case GTK_IMAGE_STOCK:
1471       g_object_notify (G_OBJECT (image), "stock");      
1472       break;
1473     case GTK_IMAGE_ICON_SET:
1474       g_object_notify (G_OBJECT (image), "icon-set");      
1475       break;
1476     case GTK_IMAGE_ANIMATION:
1477       gtk_image_reset_anim_iter (image);      
1478       g_object_notify (G_OBJECT (image), "pixbuf-animation");
1479       break;
1480     case GTK_IMAGE_ICON_NAME:
1481       g_object_notify (G_OBJECT (image), "icon-name");
1482       break;
1483     case GTK_IMAGE_GICON:
1484       g_object_notify (G_OBJECT (image), "gicon");
1485       break;
1486     case GTK_IMAGE_EMPTY:
1487     default:
1488       break;
1489     }
1490
1491   if (priv->filename)
1492     {
1493       g_free (priv->filename);
1494       priv->filename = NULL;
1495       g_object_notify (G_OBJECT (image), "file");
1496     }
1497
1498   if (priv->resource_path)
1499     {
1500       g_free (priv->resource_path);
1501       priv->resource_path = NULL;
1502       g_object_notify (G_OBJECT (image), "resource");
1503     }
1504
1505   _gtk_icon_helper_clear (priv->icon_helper);
1506
1507   g_object_thaw_notify (G_OBJECT (image));
1508 }
1509
1510 /**
1511  * gtk_image_clear:
1512  * @image: a #GtkImage
1513  *
1514  * Resets the image to be empty.
1515  *
1516  * Since: 2.8
1517  */
1518 void
1519 gtk_image_clear (GtkImage *image)
1520 {
1521   gtk_image_reset (image);
1522
1523   if (gtk_widget_get_visible (GTK_WIDGET (image)))
1524       gtk_widget_queue_resize (GTK_WIDGET (image));
1525 }
1526
1527 static void
1528 gtk_image_get_preferred_width (GtkWidget *widget,
1529                                gint      *minimum,
1530                                gint      *natural)
1531 {
1532   gint width;
1533
1534   gtk_image_get_preferred_size (GTK_IMAGE (widget), &width, NULL);
1535   *minimum = *natural = width;
1536
1537
1538 static void
1539 gtk_image_get_preferred_height (GtkWidget *widget,
1540                                 gint      *minimum,
1541                                 gint      *natural)
1542 {
1543   gint height;
1544
1545   gtk_image_get_preferred_size (GTK_IMAGE (widget), NULL, &height);
1546   *minimum = *natural = height;
1547 }
1548
1549 static void
1550 icon_theme_changed (GtkImage *image)
1551 {
1552   GtkImagePrivate *priv = image->priv;
1553
1554   _gtk_icon_helper_invalidate (priv->icon_helper);
1555   gtk_widget_queue_draw (GTK_WIDGET (image));
1556 }
1557
1558 static void
1559 gtk_image_style_updated (GtkWidget *widget)
1560 {
1561   GTK_WIDGET_CLASS (gtk_image_parent_class)->style_updated (widget);
1562
1563   icon_theme_changed (GTK_IMAGE (widget));
1564 }
1565
1566 static void
1567 gtk_image_screen_changed (GtkWidget *widget,
1568                           GdkScreen *prev_screen)
1569 {
1570   GtkImage *image;
1571
1572   image = GTK_IMAGE (widget);
1573
1574   if (GTK_WIDGET_CLASS (gtk_image_parent_class)->screen_changed)
1575     GTK_WIDGET_CLASS (gtk_image_parent_class)->screen_changed (widget, prev_screen);
1576
1577   icon_theme_changed (image);
1578 }
1579
1580 void
1581 _gtk_image_gicon_data_clear (GtkImageGIconData *data)
1582 {
1583   if (data->pixbuf)
1584     {
1585       g_object_unref (data->pixbuf);
1586       data->pixbuf = NULL;
1587     }
1588   if (data->icon)
1589     {
1590       g_object_unref (data->icon);
1591       data->icon = NULL;
1592     }
1593 }
1594
1595 /**
1596  * gtk_image_set_pixel_size:
1597  * @image: a #GtkImage
1598  * @pixel_size: the new pixel size
1599  * 
1600  * Sets the pixel size to use for named icons. If the pixel size is set
1601  * to a value != -1, it is used instead of the icon size set by
1602  * gtk_image_set_from_icon_name().
1603  *
1604  * Since: 2.6
1605  */
1606 void 
1607 gtk_image_set_pixel_size (GtkImage *image,
1608                           gint      pixel_size)
1609 {
1610   GtkImagePrivate *priv;
1611   gint old_pixel_size;
1612
1613   g_return_if_fail (GTK_IS_IMAGE (image));
1614
1615   priv = image->priv;
1616   old_pixel_size = gtk_image_get_pixel_size (image);
1617
1618   if (pixel_size != old_pixel_size)
1619     {
1620       _gtk_icon_helper_set_pixel_size (priv->icon_helper, pixel_size);
1621
1622       if (gtk_widget_get_visible (GTK_WIDGET (image)))
1623         gtk_widget_queue_resize (GTK_WIDGET (image));
1624
1625       g_object_notify (G_OBJECT (image), "pixel-size");
1626     }
1627 }
1628
1629 /**
1630  * gtk_image_get_pixel_size:
1631  * @image: a #GtkImage
1632  * 
1633  * Gets the pixel size used for named icons.
1634  *
1635  * Returns: the pixel size used for named icons.
1636  *
1637  * Since: 2.6
1638  */
1639 gint
1640 gtk_image_get_pixel_size (GtkImage *image)
1641 {
1642   g_return_val_if_fail (GTK_IS_IMAGE (image), -1);
1643
1644   return _gtk_icon_helper_get_pixel_size (image->priv->icon_helper);
1645 }