X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkimage.c;h=473bb3ade90e3c9c19c3d9e24c4416c2537ad226;hb=c770f441ca208e3ce784d109b46e7b1e67663834;hp=56e31711455d11c1a8cc9fddf2ae74c7981ee346;hpb=57223c9a056bfff1635ddd1e67f660cd5a61e9ff;p=~andy%2Fgtk diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 56e317114..473bb3ade 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -25,6 +25,7 @@ */ #include "config.h" + #include #include @@ -33,60 +34,167 @@ #include "gtkiconfactory.h" #include "gtkstock.h" #include "gtkicontheme.h" +#include "gtksizerequest.h" #include "gtkintl.h" #include "gtkprivate.h" -#include "gtkalias.h" +#include "gtktypebuiltins.h" + +/** + * SECTION:gtkimage + * @Short_description: A widget displaying an image + * @Title: GtkImage + * @See_also:#GdkPixbuf + * + * The #GtkImage widget displays an image. Various kinds of object + * can be displayed as an image; most typically, you would load a + * #GdkPixbuf ("pixel buffer") from a file, and then display that. + * There's a convenience function to do this, gtk_image_new_from_file(), + * used as follows: + * + * GtkWidget *image; + * image = gtk_image_new_from_file ("myfile.png"); + * + * If the file isn't loaded successfully, the image will contain a + * "broken image" icon similar to that used in many web browsers. + * If you want to handle errors in loading the file yourself, + * for example by displaying an error message, then load the image with + * gdk_pixbuf_new_from_file(), then create the #GtkImage with + * gtk_image_new_from_pixbuf(). + * + * The image file may contain an animation, if so the #GtkImage will + * display an animation (#GdkPixbufAnimation) instead of a static image. + * + * #GtkImage is a subclass of #GtkMisc, which implies that you can + * align it (center, left, right) and add padding to it, using + * #GtkMisc methods. + * + * #GtkImage is a "no window" widget (has no #GdkWindow of its own), + * so by default does not receive events. If you want to receive events + * on the image, such as button clicks, place the image inside a + * #GtkEventBox, then connect to the event signals on the event box. + * + * Handling button press events on a + * <structname>GtkImage</structname>. + * + * static gboolean + * button_press_callback (GtkWidget *event_box, + * GdkEventButton *event, + * gpointer data) + * { + * g_print ("Event box clicked at coordinates %f,%f\n", + * event->x, event->y); + * + * /* Returning TRUE means we handled the event, so the signal + * * emission should be stopped (don't call any further + * * callbacks that may be connected). Return FALSE + * * to continue invoking callbacks. + * */ + * return TRUE; + * } + * + * static GtkWidget* + * create_image (void) + * { + * GtkWidget *image; + * GtkWidget *event_box; + * + * image = gtk_image_new_from_file ("myfile.png"); + * + * event_box = gtk_event_box_new (); + * + * gtk_container_add (GTK_CONTAINER (event_box), image); + * + * g_signal_connect (G_OBJECT (event_box), + * "button_press_event", + * G_CALLBACK (button_press_callback), + * image); + * + * return image; + * } + * + * + * + * When handling events on the event box, keep in mind that coordinates + * in the image may be different from event box coordinates due to + * the alignment and padding settings on the image (see #GtkMisc). + * The simplest way to solve this is to set the alignment to 0.0 + * (left/top), and set the padding to zero. Then the origin of + * the image will be the same as the origin of the event box. + * + * Sometimes an application will want to avoid depending on external data + * files, such as image files. GTK+ comes with a program to avoid this, + * called gdk-pixbuf-csource. This program + * allows you to convert an image into a C variable declaration, which + * can then be loaded into a #GdkPixbuf using + * gdk_pixbuf_new_from_inline(). + */ -typedef struct _GtkImagePrivate GtkImagePrivate; struct _GtkImagePrivate { - /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */ - gchar *filename; - - gint pixel_size; + GtkIconSize icon_size; /* Only used with GTK_IMAGE_STOCK, GTK_IMAGE_ICON_SET, GTK_IMAGE_ICON_NAME */ + GtkImageType storage_type; + + union + { + GtkImagePixbufData pixbuf; + GtkImageStockData stock; + GtkImageIconSetData icon_set; + GtkImageAnimationData anim; + GtkImageIconNameData name; + GtkImageGIconData gicon; + } data; + + gboolean was_symbolic; + gchar *filename; /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */ + gint last_rendered_state; /* a GtkStateFlags, with -1 meaning an invalid state, + * only used with GTK_IMAGE_GICON, GTK_IMAGE_ICON_NAME */ + gint pixel_size; + gint required_width; + gint required_height; + guint need_calc_size : 1; + guint use_fallback : 1; }; -#define GTK_IMAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_IMAGE, GtkImagePrivate)) - #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON -static gint gtk_image_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_image_unmap (GtkWidget *widget); -static void gtk_image_unrealize (GtkWidget *widget); -static void gtk_image_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_image_style_set (GtkWidget *widget, - GtkStyle *prev_style); -static void gtk_image_screen_changed (GtkWidget *widget, - GdkScreen *prev_screen); -static void gtk_image_destroy (GtkObject *object); -static void gtk_image_reset (GtkImage *image); -static void gtk_image_calc_size (GtkImage *image); - -static void gtk_image_update_size (GtkImage *image, - gint image_width, - gint image_height); - -static void gtk_image_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_image_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void icon_theme_changed (GtkImage *image); +static gint gtk_image_draw (GtkWidget *widget, + cairo_t *cr); +static void gtk_image_unmap (GtkWidget *widget); +static void gtk_image_unrealize (GtkWidget *widget); +static void gtk_image_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural); +static void gtk_image_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural); + +static void gtk_image_style_updated (GtkWidget *widget); +static void gtk_image_screen_changed (GtkWidget *widget, + GdkScreen *prev_screen); +static void gtk_image_destroy (GtkWidget *widget); +static void gtk_image_reset (GtkImage *image); +static void gtk_image_calc_size (GtkImage *image); + +static void gtk_image_update_size (GtkImage *image, + gint image_width, + gint image_height); + +static void gtk_image_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_image_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void icon_theme_changed (GtkImage *image); enum { PROP_0, PROP_PIXBUF, - PROP_PIXMAP, - PROP_IMAGE, - PROP_MASK, PROP_FILE, PROP_STOCK, PROP_ICON_SET, @@ -95,7 +203,8 @@ enum PROP_PIXBUF_ANIMATION, PROP_ICON_NAME, PROP_STORAGE_TYPE, - PROP_GICON + PROP_GICON, + PROP_USE_FALLBACK }; G_DEFINE_TYPE (GtkImage, gtk_image, GTK_TYPE_MISC) @@ -104,25 +213,21 @@ static void gtk_image_class_init (GtkImageClass *class) { GObjectClass *gobject_class; - GtkObjectClass *object_class; GtkWidgetClass *widget_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->set_property = gtk_image_set_property; gobject_class->get_property = gtk_image_get_property; - - object_class = GTK_OBJECT_CLASS (class); - - object_class->destroy = gtk_image_destroy; widget_class = GTK_WIDGET_CLASS (class); - - widget_class->expose_event = gtk_image_expose; - widget_class->size_request = gtk_image_size_request; + widget_class->draw = gtk_image_draw; + widget_class->destroy = gtk_image_destroy; + widget_class->get_preferred_width = gtk_image_get_preferred_width; + widget_class->get_preferred_height = gtk_image_get_preferred_height; widget_class->unmap = gtk_image_unmap; widget_class->unrealize = gtk_image_unrealize; - widget_class->style_set = gtk_image_style_set; + widget_class->style_updated = gtk_image_style_updated; widget_class->screen_changed = gtk_image_screen_changed; g_object_class_install_property (gobject_class, @@ -133,30 +238,6 @@ gtk_image_class_init (GtkImageClass *class) GDK_TYPE_PIXBUF, GTK_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_PIXMAP, - g_param_spec_object ("pixmap", - P_("Pixmap"), - P_("A GdkPixmap to display"), - GDK_TYPE_PIXMAP, - GTK_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_IMAGE, - g_param_spec_object ("image", - P_("Image"), - P_("A GdkImage to display"), - GDK_TYPE_IMAGE, - GTK_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_MASK, - g_param_spec_object ("mask", - P_("Mask"), - P_("Mask bitmap to use with GdkImage or GdkPixmap"), - GDK_TYPE_PIXMAP, - GTK_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_FILE, g_param_spec_string ("file", @@ -258,19 +339,41 @@ gtk_image_class_init (GtkImageClass *class) GTK_IMAGE_EMPTY, GTK_PARAM_READABLE)); - g_type_class_add_private (object_class, sizeof (GtkImagePrivate)); + /** + * GtkImage:use-fallback: + * + * Whether the icon displayed in the GtkImage will use + * standard icon names fallback. The value of this property + * is only relevant for images of type %GTK_IMAGE_ICON_NAME + * and %GTK_IMAGE_GICON. + * + * Since: 3.0 + */ + g_object_class_install_property (gobject_class, + PROP_USE_FALLBACK, + g_param_spec_boolean ("use-fallback", + P_("Use Fallback"), + P_("Whether to use icon names fallback"), + FALSE, + GTK_PARAM_READWRITE)); + + g_type_class_add_private (class, sizeof (GtkImagePrivate)); } static void gtk_image_init (GtkImage *image) { - GtkImagePrivate *priv = GTK_IMAGE_GET_PRIVATE (image); + GtkImagePrivate *priv; + + image->priv = G_TYPE_INSTANCE_GET_PRIVATE (image, + GTK_TYPE_IMAGE, + GtkImagePrivate); + priv = image->priv; - GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW); + gtk_widget_set_has_window (GTK_WIDGET (image), FALSE); - image->storage_type = GTK_IMAGE_EMPTY; - image->icon_size = DEFAULT_ICON_SIZE; - image->mask = NULL; + priv->storage_type = GTK_IMAGE_EMPTY; + priv->icon_size = DEFAULT_ICON_SIZE; priv->pixel_size = -1; @@ -278,13 +381,13 @@ gtk_image_init (GtkImage *image) } static void -gtk_image_destroy (GtkObject *object) +gtk_image_destroy (GtkWidget *widget) { - GtkImage *image = GTK_IMAGE (object); + GtkImage *image = GTK_IMAGE (widget); gtk_image_reset (image); - - GTK_OBJECT_CLASS (gtk_image_parent_class)->destroy (object); + + GTK_WIDGET_CLASS (gtk_image_parent_class)->destroy (widget); } static void @@ -293,76 +396,46 @@ gtk_image_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - GtkImage *image; + GtkImage *image = GTK_IMAGE (object); + GtkImagePrivate *priv = image->priv; - image = GTK_IMAGE (object); - switch (prop_id) { case PROP_PIXBUF: gtk_image_set_from_pixbuf (image, g_value_get_object (value)); break; - case PROP_PIXMAP: - gtk_image_set_from_pixmap (image, - g_value_get_object (value), - image->mask); - break; - case PROP_IMAGE: - gtk_image_set_from_image (image, - g_value_get_object (value), - image->mask); - break; - case PROP_MASK: - if (image->storage_type == GTK_IMAGE_PIXMAP) - gtk_image_set_from_pixmap (image, - image->data.pixmap.pixmap, - g_value_get_object (value)); - else if (image->storage_type == GTK_IMAGE_IMAGE) - gtk_image_set_from_image (image, - image->data.image.image, - g_value_get_object (value)); - else - { - GdkBitmap *mask; - - mask = g_value_get_object (value); - - if (mask) - g_object_ref (mask); - - gtk_image_clear (image); - - image->mask = mask; - } - break; case PROP_FILE: gtk_image_set_from_file (image, g_value_get_string (value)); break; case PROP_STOCK: gtk_image_set_from_stock (image, g_value_get_string (value), - image->icon_size); + priv->icon_size); break; case PROP_ICON_SET: gtk_image_set_from_icon_set (image, g_value_get_boxed (value), - image->icon_size); + priv->icon_size); break; case PROP_ICON_SIZE: - if (image->storage_type == GTK_IMAGE_STOCK) + if (priv->storage_type == GTK_IMAGE_STOCK) gtk_image_set_from_stock (image, - image->data.stock.stock_id, + priv->data.stock.stock_id, g_value_get_int (value)); - else if (image->storage_type == GTK_IMAGE_ICON_SET) + else if (priv->storage_type == GTK_IMAGE_ICON_SET) gtk_image_set_from_icon_set (image, - image->data.icon_set.icon_set, + priv->data.icon_set.icon_set, g_value_get_int (value)); - else if (image->storage_type == GTK_IMAGE_ICON_NAME) + else if (priv->storage_type == GTK_IMAGE_ICON_NAME) gtk_image_set_from_icon_name (image, - image->data.name.icon_name, + priv->data.name.icon_name, g_value_get_int (value)); + else if (priv->storage_type == GTK_IMAGE_GICON) + gtk_image_set_from_gicon (image, + priv->data.gicon.icon, + g_value_get_int (value)); else - /* Save to be used when STOCK or ICON_SET property comes in */ - image->icon_size = g_value_get_int (value); + /* Save to be used when STOCK, ICON_SET, ICON_NAME or GICON property comes in */ + priv->icon_size = g_value_get_int (value); break; case PROP_PIXEL_SIZE: gtk_image_set_pixel_size (image, g_value_get_int (value)); @@ -373,11 +446,23 @@ gtk_image_set_property (GObject *object, break; case PROP_ICON_NAME: gtk_image_set_from_icon_name (image, g_value_get_string (value), - image->icon_size); + priv->icon_size); break; case PROP_GICON: gtk_image_set_from_gicon (image, g_value_get_object (value), - image->icon_size); + priv->icon_size); + break; + + case PROP_USE_FALLBACK: + priv->use_fallback = g_value_get_boolean (value); + if (priv->storage_type == GTK_IMAGE_ICON_NAME) + gtk_image_set_from_icon_name (image, + priv->data.name.icon_name, + priv->icon_size); + else if (priv->storage_type == GTK_IMAGE_GICON) + gtk_image_set_from_gicon (image, + priv->data.gicon.icon, + priv->icon_size); break; default: @@ -392,11 +477,8 @@ gtk_image_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - GtkImage *image; - GtkImagePrivate *priv; - - image = GTK_IMAGE (object); - priv = GTK_IMAGE_GET_PRIVATE (image); + GtkImage *image = GTK_IMAGE (object); + GtkImagePrivate *priv = image->priv; /* The "getter" functions whine if you try to get the wrong * storage type. This function is instead robust against that, @@ -407,75 +489,62 @@ gtk_image_get_property (GObject *object, switch (prop_id) { case PROP_PIXBUF: - if (image->storage_type != GTK_IMAGE_PIXBUF) + if (priv->storage_type != GTK_IMAGE_PIXBUF) g_value_set_object (value, NULL); else g_value_set_object (value, gtk_image_get_pixbuf (image)); break; - case PROP_PIXMAP: - if (image->storage_type != GTK_IMAGE_PIXMAP) - g_value_set_object (value, NULL); - else - g_value_set_object (value, - image->data.pixmap.pixmap); - break; - case PROP_MASK: - g_value_set_object (value, image->mask); - break; - case PROP_IMAGE: - if (image->storage_type != GTK_IMAGE_IMAGE) - g_value_set_object (value, NULL); - else - g_value_set_object (value, - image->data.image.image); - break; case PROP_FILE: g_value_set_string (value, priv->filename); break; case PROP_STOCK: - if (image->storage_type != GTK_IMAGE_STOCK) + if (priv->storage_type != GTK_IMAGE_STOCK) g_value_set_string (value, NULL); else g_value_set_string (value, - image->data.stock.stock_id); + priv->data.stock.stock_id); break; case PROP_ICON_SET: - if (image->storage_type != GTK_IMAGE_ICON_SET) + if (priv->storage_type != GTK_IMAGE_ICON_SET) g_value_set_boxed (value, NULL); else g_value_set_boxed (value, - image->data.icon_set.icon_set); + priv->data.icon_set.icon_set); break; case PROP_ICON_SIZE: - g_value_set_int (value, image->icon_size); + g_value_set_int (value, priv->icon_size); break; case PROP_PIXEL_SIZE: g_value_set_int (value, priv->pixel_size); break; case PROP_PIXBUF_ANIMATION: - if (image->storage_type != GTK_IMAGE_ANIMATION) + if (priv->storage_type != GTK_IMAGE_ANIMATION) g_value_set_object (value, NULL); else g_value_set_object (value, - image->data.anim.anim); + priv->data.anim.anim); break; case PROP_ICON_NAME: - if (image->storage_type != GTK_IMAGE_ICON_NAME) + if (priv->storage_type != GTK_IMAGE_ICON_NAME) g_value_set_string (value, NULL); else g_value_set_string (value, - image->data.name.icon_name); + priv->data.name.icon_name); break; case PROP_GICON: - if (image->storage_type != GTK_IMAGE_GICON) + if (priv->storage_type != GTK_IMAGE_GICON) g_value_set_object (value, NULL); else g_value_set_object (value, - image->data.gicon.icon); + priv->data.gicon.icon); break; case PROP_STORAGE_TYPE: - g_value_set_enum (value, image->storage_type); + g_value_set_enum (value, priv->storage_type); + break; + + case PROP_USE_FALLBACK: + g_value_set_boolean (value, priv->use_fallback); break; default: @@ -485,61 +554,9 @@ gtk_image_get_property (GObject *object, } -/** - * gtk_image_new_from_pixmap: - * @pixmap: a #GdkPixmap, or %NULL - * @mask: a #GdkBitmap, or %NULL - * - * Creates a #GtkImage widget displaying @pixmap with a @mask. - * A #GdkPixmap is a server-side image buffer in the pixel format of the - * current display. The #GtkImage does not assume a reference to the - * pixmap or mask; you still need to unref them if you own references. - * #GtkImage will add its own reference rather than adopting yours. - * - * Return value: a new #GtkImage - **/ -GtkWidget* -gtk_image_new_from_pixmap (GdkPixmap *pixmap, - GdkBitmap *mask) -{ - GtkImage *image; - - image = g_object_new (GTK_TYPE_IMAGE, NULL); - - gtk_image_set_from_pixmap (image, pixmap, mask); - - return GTK_WIDGET (image); -} - -/** - * gtk_image_new_from_image: - * @image: a #GdkImage, or %NULL - * @mask: a #GdkBitmap, or %NULL - * - * Creates a #GtkImage widget displaying a @image with a @mask. - * A #GdkImage is a client-side image buffer in the pixel format of the - * current display. The #GtkImage does not assume a reference to the - * image or mask; you still need to unref them if you own references. - * #GtkImage will add its own reference rather than adopting yours. - * - * Return value: a new #GtkImage - **/ -GtkWidget* -gtk_image_new_from_image (GdkImage *gdk_image, - GdkBitmap *mask) -{ - GtkImage *image; - - image = g_object_new (GTK_TYPE_IMAGE, NULL); - - gtk_image_set_from_image (image, gdk_image, mask); - - return GTK_WIDGET (image); -} - /** * gtk_image_new_from_file: - * @filename: a filename + * @filename: (type filename): a filename * * Creates a new #GtkImage displaying the file @filename. If the file * isn't found or can't be loaded, the resulting #GtkImage will @@ -574,8 +591,8 @@ gtk_image_new_from_file (const gchar *filename) /** * gtk_image_new_from_pixbuf: - * @pixbuf: a #GdkPixbuf, or %NULL - * + * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL + * * Creates a new #GtkImage displaying @pixbuf. * The #GtkImage does not assume a reference to the * pixbuf; you still need to unref it if you own references. @@ -602,7 +619,7 @@ gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf) /** * gtk_image_new_from_stock: * @stock_id: a stock icon name - * @size: a stock icon size + * @size: (type int): a stock icon size * * Creates a #GtkImage displaying a stock icon. Sample stock icon * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. Sample stock sizes @@ -629,7 +646,7 @@ gtk_image_new_from_stock (const gchar *stock_id, /** * gtk_image_new_from_icon_set: * @icon_set: a #GtkIconSet - * @size: a stock icon size + * @size: (type int): a stock icon size * * Creates a #GtkImage displaying an icon set. Sample stock sizes are * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using @@ -691,7 +708,7 @@ gtk_image_new_from_animation (GdkPixbufAnimation *animation) /** * gtk_image_new_from_icon_name: * @icon_name: an icon name - * @size: a stock icon size + * @size: (type int): a stock icon size * * Creates a #GtkImage displaying an icon from the current icon theme. * If the icon name isn't known, a "broken image" icon will be @@ -718,7 +735,7 @@ gtk_image_new_from_icon_name (const gchar *icon_name, /** * gtk_image_new_from_gicon: * @icon: an icon - * @size: a stock icon size + * @size: (type int): a stock icon size * * Creates a #GtkImage displaying an icon from the current icon theme. * If the icon name isn't known, a "broken image" icon will be @@ -742,112 +759,10 @@ gtk_image_new_from_gicon (GIcon *icon, return GTK_WIDGET (image); } -/** - * gtk_image_set_from_pixmap: - * @image: a #GtkImage - * @pixmap: a #GdkPixmap or %NULL - * @mask: a #GdkBitmap or %NULL - * - * See gtk_image_new_from_pixmap() for details. - **/ -void -gtk_image_set_from_pixmap (GtkImage *image, - GdkPixmap *pixmap, - GdkBitmap *mask) -{ - g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (pixmap == NULL || - GDK_IS_PIXMAP (pixmap)); - g_return_if_fail (mask == NULL || - GDK_IS_PIXMAP (mask)); - - g_object_freeze_notify (G_OBJECT (image)); - - if (pixmap) - g_object_ref (pixmap); - - if (mask) - g_object_ref (mask); - - gtk_image_clear (image); - - image->mask = mask; - - if (pixmap) - { - int width; - int height; - - image->storage_type = GTK_IMAGE_PIXMAP; - - image->data.pixmap.pixmap = pixmap; - - gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height); - - gtk_image_update_size (image, width, height); - } - - g_object_notify (G_OBJECT (image), "pixmap"); - g_object_notify (G_OBJECT (image), "mask"); - - g_object_thaw_notify (G_OBJECT (image)); -} - -/** - * gtk_image_set_from_image: - * @image: a #GtkImage - * @gdk_image: a #GdkImage or %NULL - * @mask: a #GdkBitmap or %NULL - * - * See gtk_image_new_from_image() for details. - **/ -void -gtk_image_set_from_image (GtkImage *image, - GdkImage *gdk_image, - GdkBitmap *mask) -{ - g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (gdk_image == NULL || - GDK_IS_IMAGE (gdk_image)); - g_return_if_fail (mask == NULL || - GDK_IS_PIXMAP (mask)); - - g_object_freeze_notify (G_OBJECT (image)); - - if (gdk_image) - g_object_ref (gdk_image); - - if (mask) - g_object_ref (mask); - - gtk_image_clear (image); - - if (gdk_image) - { - image->storage_type = GTK_IMAGE_IMAGE; - - image->data.image.image = gdk_image; - image->mask = mask; - - gtk_image_update_size (image, gdk_image->width, gdk_image->height); - } - else - { - /* Clean up the mask if gdk_image was NULL */ - if (mask) - g_object_unref (mask); - } - - g_object_notify (G_OBJECT (image), "image"); - g_object_notify (G_OBJECT (image), "mask"); - - g_object_thaw_notify (G_OBJECT (image)); -} - /** * gtk_image_set_from_file: * @image: a #GtkImage - * @filename: a filename or %NULL + * @filename: (type filename) (allow-none): a filename or %NULL * * See gtk_image_new_from_file() for details. **/ @@ -855,11 +770,13 @@ void gtk_image_set_from_file (GtkImage *image, const gchar *filename) { - GtkImagePrivate *priv = GTK_IMAGE_GET_PRIVATE (image); + GtkImagePrivate *priv; GdkPixbufAnimation *anim; g_return_if_fail (GTK_IS_IMAGE (image)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); gtk_image_clear (image); @@ -903,18 +820,22 @@ gtk_image_set_from_file (GtkImage *image, /** * gtk_image_set_from_pixbuf: * @image: a #GtkImage - * @pixbuf: a #GdkPixbuf or %NULL + * @pixbuf: (allow-none): a #GdkPixbuf or %NULL * - * See gtk_image_new_from_pixbuf() for details. + * See gtk_image_new_from_pixbuf() for details. **/ void gtk_image_set_from_pixbuf (GtkImage *image, GdkPixbuf *pixbuf) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); if (pixbuf) @@ -924,9 +845,9 @@ gtk_image_set_from_pixbuf (GtkImage *image, if (pixbuf != NULL) { - image->storage_type = GTK_IMAGE_PIXBUF; + priv->storage_type = GTK_IMAGE_PIXBUF; - image->data.pixbuf.pixbuf = pixbuf; + priv->data.pixbuf.pixbuf = pixbuf; gtk_image_update_size (image, gdk_pixbuf_get_width (pixbuf), @@ -942,7 +863,7 @@ gtk_image_set_from_pixbuf (GtkImage *image, * gtk_image_set_from_stock: * @image: a #GtkImage * @stock_id: a stock icon name - * @size: a stock icon size + * @size: (type int): a stock icon size * * See gtk_image_new_from_stock() for details. **/ @@ -951,23 +872,26 @@ gtk_image_set_from_stock (GtkImage *image, const gchar *stock_id, GtkIconSize size) { + GtkImagePrivate *priv; gchar *new_id; - + g_return_if_fail (GTK_IS_IMAGE (image)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); - /* in case stock_id == image->data.stock.stock_id */ + /* in case stock_id == priv->data.stock.stock_id */ new_id = g_strdup (stock_id); gtk_image_clear (image); if (new_id) { - image->storage_type = GTK_IMAGE_STOCK; + priv->storage_type = GTK_IMAGE_STOCK; - image->data.stock.stock_id = new_id; - image->icon_size = size; + priv->data.stock.stock_id = new_id; + priv->icon_size = size; /* Size is demand-computed in size request method * if we're a stock image, since changing the @@ -985,7 +909,7 @@ gtk_image_set_from_stock (GtkImage *image, * gtk_image_set_from_icon_set: * @image: a #GtkImage * @icon_set: a #GtkIconSet - * @size: a stock icon size + * @size: (type int): a stock icon size * * See gtk_image_new_from_icon_set() for details. **/ @@ -994,8 +918,12 @@ gtk_image_set_from_icon_set (GtkImage *image, GtkIconSet *icon_set, GtkIconSize size) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); if (icon_set) @@ -1005,10 +933,10 @@ gtk_image_set_from_icon_set (GtkImage *image, if (icon_set) { - image->storage_type = GTK_IMAGE_ICON_SET; + priv->storage_type = GTK_IMAGE_ICON_SET; - image->data.icon_set.icon_set = icon_set; - image->icon_size = size; + priv->data.icon_set.icon_set = icon_set; + priv->icon_size = size; /* Size is demand-computed in size request method * if we're an icon set @@ -1033,10 +961,14 @@ void gtk_image_set_from_animation (GtkImage *image, GdkPixbufAnimation *animation) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); g_return_if_fail (animation == NULL || GDK_IS_PIXBUF_ANIMATION (animation)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); if (animation) @@ -1046,11 +978,11 @@ gtk_image_set_from_animation (GtkImage *image, if (animation != NULL) { - image->storage_type = GTK_IMAGE_ANIMATION; + priv->storage_type = GTK_IMAGE_ANIMATION; - image->data.anim.anim = animation; - image->data.anim.frame_timeout = 0; - image->data.anim.iter = NULL; + priv->data.anim.anim = animation; + priv->data.anim.frame_timeout = 0; + priv->data.anim.iter = NULL; gtk_image_update_size (image, gdk_pixbuf_animation_get_width (animation), @@ -1066,7 +998,7 @@ gtk_image_set_from_animation (GtkImage *image, * gtk_image_set_from_icon_name: * @image: a #GtkImage * @icon_name: an icon name - * @size: an icon size + * @size: (type int): an icon size * * See gtk_image_new_from_icon_name() for details. * @@ -1078,22 +1010,25 @@ gtk_image_set_from_icon_name (GtkImage *image, GtkIconSize size) { gchar *new_name; - + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); - /* in case icon_name == image->data.name.icon_name */ + /* in case icon_name == priv->data.name.icon_name */ new_name = g_strdup (icon_name); gtk_image_clear (image); if (new_name) { - image->storage_type = GTK_IMAGE_ICON_NAME; + priv->storage_type = GTK_IMAGE_ICON_NAME; - image->data.name.icon_name = new_name; - image->icon_size = size; + priv->data.name.icon_name = new_name; + priv->icon_size = size; /* Size is demand-computed in size request method * if we're a icon theme image, since changing the @@ -1111,7 +1046,7 @@ gtk_image_set_from_icon_name (GtkImage *image, * gtk_image_set_from_gicon: * @image: a #GtkImage * @icon: an icon - * @size: an icon size + * @size: (type int): an icon size * * See gtk_image_new_from_gicon() for details. * @@ -1122,11 +1057,15 @@ gtk_image_set_from_gicon (GtkImage *image, GIcon *icon, GtkIconSize size) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); + priv = image->priv; + g_object_freeze_notify (G_OBJECT (image)); - /* in case icon == image->data.gicon.icon */ + /* in case icon == priv->data.gicon.icon */ if (icon) g_object_ref (icon); @@ -1134,10 +1073,10 @@ gtk_image_set_from_gicon (GtkImage *image, if (icon) { - image->storage_type = GTK_IMAGE_GICON; - - image->data.gicon.icon = icon; - image->icon_size = size; + priv->storage_type = GTK_IMAGE_GICON; + + priv->data.gicon.icon = icon; + priv->icon_size = size; /* Size is demand-computed in size request method * if we're a icon theme image, since changing the @@ -1166,63 +1105,7 @@ gtk_image_get_storage_type (GtkImage *image) { g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY); - return image->storage_type; -} - -/** - * gtk_image_get_pixmap: - * @image: a #GtkImage - * @pixmap: location to store the pixmap, or %NULL - * @mask: location to store the mask, or %NULL - * - * Gets the pixmap and mask being displayed by the #GtkImage. - * The storage type of the image must be %GTK_IMAGE_EMPTY or - * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()). - * The caller of this function does not own a reference to the - * returned pixmap and mask. - **/ -void -gtk_image_get_pixmap (GtkImage *image, - GdkPixmap **pixmap, - GdkBitmap **mask) -{ - g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP || - image->storage_type == GTK_IMAGE_EMPTY); - - if (pixmap) - *pixmap = image->data.pixmap.pixmap; - - if (mask) - *mask = image->mask; -} - -/** - * gtk_image_get_image: - * @image: a #GtkImage - * @gdk_image: return location for a #GtkImage - * @mask: return location for a #GdkBitmap - * - * Gets the #GdkImage and mask being displayed by the #GtkImage. - * The storage type of the image must be %GTK_IMAGE_EMPTY or - * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()). - * The caller of this function does not own a reference to the - * returned image and mask. - **/ -void -gtk_image_get_image (GtkImage *image, - GdkImage **gdk_image, - GdkBitmap **mask) -{ - g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE || - image->storage_type == GTK_IMAGE_EMPTY); - - if (gdk_image) - *gdk_image = image->data.image.image; - - if (mask) - *mask = image->mask; + return image->priv->storage_type; } /** @@ -1235,26 +1118,34 @@ gtk_image_get_image (GtkImage *image, * The caller of this function does not own a reference to the * returned pixbuf. * - * Return value: the displayed pixbuf, or %NULL if the image is empty + * Return value: (transfer none): the displayed pixbuf, or %NULL if + * the image is empty **/ GdkPixbuf* gtk_image_get_pixbuf (GtkImage *image) { + GtkImagePrivate *priv; + g_return_val_if_fail (GTK_IS_IMAGE (image), NULL); - g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF || - image->storage_type == GTK_IMAGE_EMPTY, NULL); - if (image->storage_type == GTK_IMAGE_EMPTY) - image->data.pixbuf.pixbuf = NULL; - - return image->data.pixbuf.pixbuf; + priv = image->priv; + + g_return_val_if_fail (priv->storage_type == GTK_IMAGE_PIXBUF || + priv->storage_type == GTK_IMAGE_EMPTY, NULL); + + if (priv->storage_type == GTK_IMAGE_EMPTY) + priv->data.pixbuf.pixbuf = NULL; + + return priv->data.pixbuf.pixbuf; } /** * gtk_image_get_stock: * @image: a #GtkImage - * @stock_id: place to store a stock icon name - * @size: place to store a stock icon size + * @stock_id: (out) (transfer none) (allow-none): place to store a + * stock icon name, or %NULL + * @size: (out) (allow-none) (type int): place to store a stock icon + * size, or %NULL * * Gets the stock icon name and size being displayed by the #GtkImage. * The storage type of the image must be %GTK_IMAGE_EMPTY or @@ -1267,25 +1158,32 @@ gtk_image_get_stock (GtkImage *image, gchar **stock_id, GtkIconSize *size) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK || - image->storage_type == GTK_IMAGE_EMPTY); - if (image->storage_type == GTK_IMAGE_EMPTY) - image->data.stock.stock_id = NULL; - + priv = image->priv; + + g_return_if_fail (priv->storage_type == GTK_IMAGE_STOCK || + priv->storage_type == GTK_IMAGE_EMPTY); + + if (priv->storage_type == GTK_IMAGE_EMPTY) + priv->data.stock.stock_id = NULL; + if (stock_id) - *stock_id = image->data.stock.stock_id; + *stock_id = priv->data.stock.stock_id; if (size) - *size = image->icon_size; + *size = priv->icon_size; } /** * gtk_image_get_icon_set: * @image: a #GtkImage - * @icon_set: location to store a #GtkIconSet - * @size: location to store a stock icon size + * @icon_set: (out) (transfer none) (allow-none): location to store a + * #GtkIconSet, or %NULL + * @size: (out) (allow-none) (type int): location to store a stock + * icon size, or %NULL * * Gets the icon set and size being displayed by the #GtkImage. * The storage type of the image must be %GTK_IMAGE_EMPTY or @@ -1296,15 +1194,20 @@ gtk_image_get_icon_set (GtkImage *image, GtkIconSet **icon_set, GtkIconSize *size) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET || - image->storage_type == GTK_IMAGE_EMPTY); - - if (icon_set) - *icon_set = image->data.icon_set.icon_set; + + priv = image->priv; + + g_return_if_fail (priv->storage_type == GTK_IMAGE_ICON_SET || + priv->storage_type == GTK_IMAGE_EMPTY); + + if (icon_set) + *icon_set = priv->data.icon_set.icon_set; if (size) - *size = image->icon_size; + *size = priv->icon_size; } /** @@ -1317,27 +1220,35 @@ gtk_image_get_icon_set (GtkImage *image, * The caller of this function does not own a reference to the * returned animation. * - * Return value: the displayed animation, or %NULL if the image is empty + * Return value: (transfer none): the displayed animation, or %NULL if + * the image is empty **/ GdkPixbufAnimation* gtk_image_get_animation (GtkImage *image) { + GtkImagePrivate *priv; + g_return_val_if_fail (GTK_IS_IMAGE (image), NULL); - g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION || - image->storage_type == GTK_IMAGE_EMPTY, + + priv = image->priv; + + g_return_val_if_fail (priv->storage_type == GTK_IMAGE_ANIMATION || + priv->storage_type == GTK_IMAGE_EMPTY, NULL); - if (image->storage_type == GTK_IMAGE_EMPTY) - image->data.anim.anim = NULL; - - return image->data.anim.anim; + if (priv->storage_type == GTK_IMAGE_EMPTY) + priv->data.anim.anim = NULL; + + return priv->data.anim.anim; } /** * gtk_image_get_icon_name: * @image: a #GtkImage - * @icon_name: place to store an icon name - * @size: place to store an icon size + * @icon_name: (out) (transfer none) (allow-none): place to store an + * icon name, or %NULL + * @size: (out) (allow-none) (type int): place to store an icon size, + * or %NULL * * Gets the icon name and size being displayed by the #GtkImage. * The storage type of the image must be %GTK_IMAGE_EMPTY or @@ -1352,25 +1263,32 @@ gtk_image_get_icon_name (GtkImage *image, G_CONST_RETURN gchar **icon_name, GtkIconSize *size) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME || - image->storage_type == GTK_IMAGE_EMPTY); - if (image->storage_type == GTK_IMAGE_EMPTY) - image->data.name.icon_name = NULL; - + priv = image->priv; + + g_return_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME || + priv->storage_type == GTK_IMAGE_EMPTY); + + if (priv->storage_type == GTK_IMAGE_EMPTY) + priv->data.name.icon_name = NULL; + if (icon_name) - *icon_name = image->data.name.icon_name; + *icon_name = priv->data.name.icon_name; if (size) - *size = image->icon_size; + *size = priv->icon_size; } /** * gtk_image_get_gicon: * @image: a #GtkImage - * @gicon: place to store a #GIcon - * @size: place to store an icon size + * @gicon: (out) (transfer none) (allow-none): place to store a + * #GIcon, or %NULL + * @size: (out) (allow-none) (type int): place to store an icon size, + * or %NULL * * Gets the #GIcon and size being displayed by the #GtkImage. * The storage type of the image must be %GTK_IMAGE_EMPTY or @@ -1385,18 +1303,23 @@ gtk_image_get_gicon (GtkImage *image, GIcon **gicon, GtkIconSize *size) { + GtkImagePrivate *priv; + g_return_if_fail (GTK_IS_IMAGE (image)); - g_return_if_fail (image->storage_type == GTK_IMAGE_GICON || - image->storage_type == GTK_IMAGE_EMPTY); - if (image->storage_type == GTK_IMAGE_EMPTY) - image->data.gicon.icon = NULL; - + priv = image->priv; + + g_return_if_fail (priv->storage_type == GTK_IMAGE_GICON || + priv->storage_type == GTK_IMAGE_EMPTY); + + if (priv->storage_type == GTK_IMAGE_EMPTY) + priv->data.gicon.icon = NULL; + if (gicon) - *gicon = image->data.gicon.icon; + *gicon = priv->data.gicon.icon; if (size) - *size = image->icon_size; + *size = priv->icon_size; } /** @@ -1412,43 +1335,25 @@ gtk_image_new (void) return g_object_new (GTK_TYPE_IMAGE, NULL); } -void -gtk_image_set (GtkImage *image, - GdkImage *val, - GdkBitmap *mask) -{ - g_return_if_fail (GTK_IS_IMAGE (image)); - - gtk_image_set_from_image (image, val, mask); -} - -void -gtk_image_get (GtkImage *image, - GdkImage **val, - GdkBitmap **mask) -{ - g_return_if_fail (GTK_IS_IMAGE (image)); - - gtk_image_get_image (image, val, mask); -} - static void gtk_image_reset_anim_iter (GtkImage *image) { - if (image->storage_type == GTK_IMAGE_ANIMATION) + GtkImagePrivate *priv = image->priv; + + if (priv->storage_type == GTK_IMAGE_ANIMATION) { /* Reset the animation */ - if (image->data.anim.frame_timeout) + if (priv->data.anim.frame_timeout) { - g_source_remove (image->data.anim.frame_timeout); - image->data.anim.frame_timeout = 0; + g_source_remove (priv->data.anim.frame_timeout); + priv->data.anim.frame_timeout = 0; } - if (image->data.anim.iter) + if (priv->data.anim.iter) { - g_object_unref (image->data.anim.iter); - image->data.anim.iter = NULL; + g_object_unref (priv->data.anim.iter); + priv->data.anim.iter = NULL; } } } @@ -1458,8 +1363,7 @@ gtk_image_unmap (GtkWidget *widget) { gtk_image_reset_anim_iter (GTK_IMAGE (widget)); - if (GTK_WIDGET_CLASS (gtk_image_parent_class)->unmap) - GTK_WIDGET_CLASS (gtk_image_parent_class)->unmap (widget); + GTK_WIDGET_CLASS (gtk_image_parent_class)->unmap (widget); } static void @@ -1467,32 +1371,32 @@ gtk_image_unrealize (GtkWidget *widget) { gtk_image_reset_anim_iter (GTK_IMAGE (widget)); - if (GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize) - GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize (widget); + GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize (widget); } static gint animation_timeout (gpointer data) { - GtkImage *image; + GtkImage *image = GTK_IMAGE (data); + GtkImagePrivate *priv = image->priv; int delay; - image = GTK_IMAGE (data); - - image->data.anim.frame_timeout = 0; + priv->data.anim.frame_timeout = 0; - gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL); + gdk_pixbuf_animation_iter_advance (priv->data.anim.iter, NULL); - delay = gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter); + delay = gdk_pixbuf_animation_iter_get_delay_time (priv->data.anim.iter); if (delay >= 0) { - image->data.anim.frame_timeout = + GtkWidget *widget = GTK_WIDGET (image); + + priv->data.anim.frame_timeout = gdk_threads_add_timeout (delay, animation_timeout, image); - gtk_widget_queue_draw (GTK_WIDGET (image)); + gtk_widget_queue_draw (widget); - if (GTK_WIDGET_DRAWABLE (image)) - gdk_window_process_updates (GTK_WIDGET (image)->window, TRUE); + if (gtk_widget_is_drawable (widget)) + gdk_window_process_updates (gtk_widget_get_window (widget), TRUE); } return FALSE; @@ -1501,58 +1405,69 @@ animation_timeout (gpointer data) static void icon_theme_changed (GtkImage *image) { - if (image->storage_type == GTK_IMAGE_ICON_NAME) + GtkImagePrivate *priv = image->priv; + + if (priv->storage_type == GTK_IMAGE_ICON_NAME) { - if (image->data.name.pixbuf) - g_object_unref (image->data.name.pixbuf); - image->data.name.pixbuf = NULL; + if (priv->data.name.pixbuf) + g_object_unref (priv->data.name.pixbuf); + priv->data.name.pixbuf = NULL; gtk_widget_queue_draw (GTK_WIDGET (image)); } - if (image->storage_type == GTK_IMAGE_GICON) + if (priv->storage_type == GTK_IMAGE_GICON) { - if (image->data.gicon.pixbuf) - g_object_unref (image->data.gicon.pixbuf); - image->data.gicon.pixbuf = NULL; + if (priv->data.gicon.pixbuf) + g_object_unref (priv->data.gicon.pixbuf); + priv->data.gicon.pixbuf = NULL; gtk_widget_queue_draw (GTK_WIDGET (image)); } } static void -ensure_pixbuf_for_icon_name (GtkImage *image) +ensure_pixbuf_for_icon_name (GtkImage *image, + GtkStateFlags state) { - GtkImagePrivate *priv; + GtkImagePrivate *priv = image->priv; GdkScreen *screen; GtkIconTheme *icon_theme; GtkSettings *settings; gint width, height; gint *sizes, *s, dist; + GtkIconInfo *info; GtkIconLookupFlags flags; - GError *error = NULL; - g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME); + g_return_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME); - priv = GTK_IMAGE_GET_PRIVATE (image); screen = gtk_widget_get_screen (GTK_WIDGET (image)); icon_theme = gtk_icon_theme_get_for_screen (screen); settings = gtk_settings_get_for_screen (screen); flags = GTK_ICON_LOOKUP_USE_BUILTIN; - if (image->data.name.pixbuf == NULL) + if (priv->use_fallback) + flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK; + if (priv->data.name.pixbuf == NULL || + (priv->was_symbolic && priv->last_rendered_state != state)) { + priv->last_rendered_state = state; + if (priv->data.name.pixbuf) + { + g_object_unref (priv->data.name.pixbuf); + priv->data.name.pixbuf = NULL; + } if (priv->pixel_size != -1) { width = height = priv->pixel_size; flags |= GTK_ICON_LOOKUP_FORCE_SIZE; } else if (!gtk_icon_size_lookup_for_settings (settings, - image->icon_size, + priv->icon_size, &width, &height)) { - if (image->icon_size == -1) + if (priv->icon_size == -1) { /* Find an available size close to 48 */ - sizes = gtk_icon_theme_get_icon_sizes (icon_theme, image->data.name.icon_name); + sizes = gtk_icon_theme_get_icon_sizes (icon_theme, priv->data.name.icon_name); dist = 100; width = height = 48; for (s = sizes; *s; s++) @@ -1583,252 +1498,177 @@ ensure_pixbuf_for_icon_name (GtkImage *image) } else { - g_warning ("Invalid icon size %d\n", image->icon_size); + g_warning ("Invalid icon size %d\n", priv->icon_size); width = height = 24; } } - image->data.name.pixbuf = - gtk_icon_theme_load_icon (icon_theme, - image->data.name.icon_name, - MIN (width, height), flags, &error); - if (image->data.name.pixbuf == NULL) + + info = gtk_icon_theme_lookup_icon (icon_theme, + priv->data.name.icon_name, + MIN (width, height), flags); + if (info) + { + GtkStyleContext *context; + gboolean was_symbolic; + + context = gtk_widget_get_style_context (GTK_WIDGET (image)); + priv->data.name.pixbuf = + gtk_icon_info_load_symbolic_for_context (info, + context, + &was_symbolic, + NULL); + priv->was_symbolic = was_symbolic; + gtk_icon_info_free (info); + } + + if (priv->data.name.pixbuf == NULL) { - g_error_free (error); - image->data.name.pixbuf = - gtk_widget_render_icon (GTK_WIDGET (image), - GTK_STOCK_MISSING_IMAGE, - image->icon_size, - NULL); + priv->data.name.pixbuf = + gtk_widget_render_icon_pixbuf (GTK_WIDGET (image), + GTK_STOCK_MISSING_IMAGE, + priv->icon_size); + priv->was_symbolic = FALSE; } } } static void -ensure_pixbuf_for_gicon (GtkImage *image) +ensure_pixbuf_for_gicon (GtkImage *image, + GtkStateFlags state) { - GtkImagePrivate *priv; + GtkImagePrivate *priv = image->priv; GdkScreen *screen; GtkIconTheme *icon_theme; GtkSettings *settings; gint width, height; GtkIconInfo *info; GtkIconLookupFlags flags; - GError *error = NULL; - g_return_if_fail (image->storage_type == GTK_IMAGE_GICON); + g_return_if_fail (priv->storage_type == GTK_IMAGE_GICON); - priv = GTK_IMAGE_GET_PRIVATE (image); screen = gtk_widget_get_screen (GTK_WIDGET (image)); icon_theme = gtk_icon_theme_get_for_screen (screen); settings = gtk_settings_get_for_screen (screen); flags = GTK_ICON_LOOKUP_USE_BUILTIN; - if (image->data.gicon.pixbuf == NULL) + if (priv->use_fallback) + flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK; + if (priv->data.gicon.pixbuf == NULL || + (priv->was_symbolic && priv->last_rendered_state != state)) { + priv->last_rendered_state = state; + if (priv->data.gicon.pixbuf) + { + g_object_unref (priv->data.gicon.pixbuf); + priv->data.gicon.pixbuf = NULL; + } if (priv->pixel_size != -1) { width = height = priv->pixel_size; flags |= GTK_ICON_LOOKUP_FORCE_SIZE; } else if (!gtk_icon_size_lookup_for_settings (settings, - image->icon_size, + priv->icon_size, &width, &height)) { - if (image->icon_size == -1) + if (priv->icon_size == -1) width = height = 48; else { - g_warning ("Invalid icon size %d\n", image->icon_size); + g_warning ("Invalid icon size %d\n", priv->icon_size); width = height = 24; } } info = gtk_icon_theme_lookup_by_gicon (icon_theme, - image->data.gicon.icon, + priv->data.gicon.icon, MIN (width, height), flags); - image->data.gicon.pixbuf = gtk_icon_info_load_icon (info, &error); - if (image->data.gicon.pixbuf == NULL) - { - g_error_free (error); - image->data.gicon.pixbuf = - gtk_widget_render_icon (GTK_WIDGET (image), - GTK_STOCK_MISSING_IMAGE, - image->icon_size, - NULL); - } - } -} - - -/* - * Like gdk_rectangle_intersect (dest, src, dest), but make - * sure that the origin of dest is moved by an "even" offset. - * If necessary grow the intersection by one row or column - * to achieve this. - * - * This is necessary since we can't pass alignment information - * for the pixelation pattern down to gdk_pixbuf_saturate_and_pixelate(), - * thus we have to makesure that the subimages are properly aligned. - */ -static gboolean -rectangle_intersect_even (GdkRectangle *src, - GdkRectangle *dest) -{ - gboolean isect; - gint x, y; - - x = dest->x; - y = dest->y; - isect = gdk_rectangle_intersect (dest, src, dest); + if (info) + { + GtkStyleContext *context; + gboolean was_symbolic; + + context = gtk_widget_get_style_context (GTK_WIDGET (image)); + priv->data.gicon.pixbuf = + gtk_icon_info_load_symbolic_for_context (info, + context, + &was_symbolic, + NULL); + priv->was_symbolic = was_symbolic; + gtk_icon_info_free (info); + } - if ((dest->x - x + dest->y - y) % 2 != 0) - { - if (dest->x > x) - { - dest->x--; - dest->width++; - } - else + if (priv->data.gicon.pixbuf == NULL) { - dest->y--; - dest->height++; + priv->data.gicon.pixbuf = + gtk_widget_render_icon_pixbuf (GTK_WIDGET (image), + GTK_STOCK_MISSING_IMAGE, + priv->icon_size); + priv->was_symbolic = FALSE; } } - - return isect; } static gint -gtk_image_expose (GtkWidget *widget, - GdkEventExpose *event) +gtk_image_draw (GtkWidget *widget, + cairo_t *cr) { + GtkImage *image; + GtkImagePrivate *priv; + g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + + image = GTK_IMAGE (widget); + priv = image->priv; - if (GTK_WIDGET_MAPPED (widget) && - GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY) + if (priv->storage_type != GTK_IMAGE_EMPTY) { - GtkImage *image; GtkMisc *misc; - GdkRectangle area, image_bound; - gfloat xalign; - gint x, y, mask_x, mask_y; - GdkBitmap *mask; + gint x, y; + gint xpad, ypad; + gfloat xalign, yalign; GdkPixbuf *pixbuf; + GtkStateFlags state; gboolean needs_state_transform; + GtkStyleContext *context; - image = GTK_IMAGE (widget); misc = GTK_MISC (widget); + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); - area = event->area; + gtk_style_context_save (context); + gtk_style_context_set_state (context, state); /* For stock items and icon sets, we lazily calculate * the size; we might get here between a queue_resize() * and size_request() if something explicitely forces * a redraw. */ - if (widget->requisition.width == 0 && widget->requisition.height == 0) + if (priv->need_calc_size) gtk_image_calc_size (image); - - if (!gdk_rectangle_intersect (&area, &widget->allocation, &area)) - return FALSE; - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - xalign = misc->xalign; - else - xalign = 1.0 - misc->xalign; - - x = floor (widget->allocation.x + misc->xpad - + ((widget->allocation.width - widget->requisition.width) * xalign)); - y = floor (widget->allocation.y + misc->ypad - + ((widget->allocation.height - widget->requisition.height) * misc->yalign)); - mask_x = x; - mask_y = y; - - image_bound.x = x; - image_bound.y = y; - image_bound.width = 0; - image_bound.height = 0; - - mask = NULL; - pixbuf = NULL; - needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL; - - switch (image->storage_type) - { - case GTK_IMAGE_PIXMAP: - mask = image->mask; - gdk_drawable_get_size (image->data.pixmap.pixmap, - &image_bound.width, - &image_bound.height); - if (rectangle_intersect_even (&area, &image_bound) && - needs_state_transform) - { - pixbuf = gdk_pixbuf_get_from_drawable (NULL, - image->data.pixmap.pixmap, - gtk_widget_get_colormap (widget), - image_bound.x - x, image_bound.y - y, - 0, 0, - image_bound.width, - image_bound.height); - - x = image_bound.x; - y = image_bound.y; - } - - break; + gtk_misc_get_alignment (misc, &xalign, &yalign); + gtk_misc_get_padding (misc, &xpad, &ypad); - case GTK_IMAGE_IMAGE: - mask = image->mask; - image_bound.width = image->data.image.image->width; - image_bound.height = image->data.image.image->height; + if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR) + xalign = 1.0 - xalign; - if (rectangle_intersect_even (&area, &image_bound) && - needs_state_transform) - { - pixbuf = gdk_pixbuf_get_from_image (NULL, - image->data.image.image, - gtk_widget_get_colormap (widget), - image_bound.x - x, image_bound.y - y, - 0, 0, - image_bound.width, - image_bound.height); - - x = image_bound.x; - y = image_bound.y; - } - break; + x = floor (xpad + ((gtk_widget_get_allocated_width (widget) - priv->required_width) * xalign)); + y = floor (ypad + ((gtk_widget_get_allocated_height (widget) - priv->required_height) * yalign)); - case GTK_IMAGE_PIXBUF: - image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf); - image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf); + needs_state_transform = state != 0; - if (rectangle_intersect_even (&area, &image_bound) && - needs_state_transform) - { - pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf, - image_bound.x - x, image_bound.y - y, - image_bound.width, image_bound.height); + switch (priv->storage_type) + { - x = image_bound.x; - y = image_bound.y; - } - else - { - pixbuf = image->data.pixbuf.pixbuf; - g_object_ref (pixbuf); - } + case GTK_IMAGE_PIXBUF: + pixbuf = priv->data.pixbuf.pixbuf; + g_object_ref (pixbuf); break; case GTK_IMAGE_STOCK: - pixbuf = gtk_widget_render_icon (widget, - image->data.stock.stock_id, - image->icon_size, - NULL); - if (pixbuf) - { - image_bound.width = gdk_pixbuf_get_width (pixbuf); - image_bound.height = gdk_pixbuf_get_height (pixbuf); - } + pixbuf = gtk_widget_render_icon_pixbuf (widget, + priv->data.stock.stock_id, + priv->icon_size); /* already done */ needs_state_transform = FALSE; @@ -1836,19 +1676,8 @@ gtk_image_expose (GtkWidget *widget, case GTK_IMAGE_ICON_SET: pixbuf = - gtk_icon_set_render_icon (image->data.icon_set.icon_set, - widget->style, - gtk_widget_get_direction (widget), - GTK_WIDGET_STATE (widget), - image->icon_size, - widget, - NULL); - - if (pixbuf) - { - image_bound.width = gdk_pixbuf_get_width (pixbuf); - image_bound.height = gdk_pixbuf_get_height (pixbuf); - } + gtk_icon_set_render_icon_pixbuf (priv->data.icon_set.icon_set, + context, priv->icon_size); /* already done */ needs_state_transform = FALSE; @@ -1856,156 +1685,103 @@ gtk_image_expose (GtkWidget *widget, case GTK_IMAGE_ANIMATION: { - if (image->data.anim.iter == NULL) + if (priv->data.anim.iter == NULL) { - image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL); + priv->data.anim.iter = gdk_pixbuf_animation_get_iter (priv->data.anim.anim, NULL); - if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0) - image->data.anim.frame_timeout = - gdk_threads_add_timeout (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter), + if (gdk_pixbuf_animation_iter_get_delay_time (priv->data.anim.iter) >= 0) + priv->data.anim.frame_timeout = + gdk_threads_add_timeout (gdk_pixbuf_animation_iter_get_delay_time (priv->data.anim.iter), animation_timeout, image); } - image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim); - image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim); - /* don't advance the anim iter here, or we could get frame changes between two * exposes of different areas. */ - pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter); + pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (priv->data.anim.iter); g_object_ref (pixbuf); } break; case GTK_IMAGE_ICON_NAME: - ensure_pixbuf_for_icon_name (image); - pixbuf = image->data.name.pixbuf; + if (state & GTK_STATE_FLAG_INSENSITIVE) + { + ensure_pixbuf_for_icon_name (image, 0); + } + else + { + ensure_pixbuf_for_icon_name (image, state); + /* Already done by the loading function? */ + if (priv->was_symbolic) + needs_state_transform = FALSE; + } + pixbuf = priv->data.name.pixbuf; if (pixbuf) { g_object_ref (pixbuf); - image_bound.width = gdk_pixbuf_get_width (pixbuf); - image_bound.height = gdk_pixbuf_get_height (pixbuf); } break; case GTK_IMAGE_GICON: - ensure_pixbuf_for_gicon (image); - pixbuf = image->data.gicon.pixbuf; + if (state & GTK_STATE_FLAG_INSENSITIVE) + { + ensure_pixbuf_for_gicon (image, 0); + } + else + { + ensure_pixbuf_for_gicon (image, state); + /* Already done by the loading function? */ + if (priv->was_symbolic) + needs_state_transform = FALSE; + } + pixbuf = priv->data.gicon.pixbuf; if (pixbuf) { g_object_ref (pixbuf); - image_bound.width = gdk_pixbuf_get_width (pixbuf); - image_bound.height = gdk_pixbuf_get_height (pixbuf); } break; case GTK_IMAGE_EMPTY: + default: g_assert_not_reached (); + pixbuf = NULL; break; } - if (mask) - { - gdk_gc_set_clip_mask (widget->style->black_gc, mask); - gdk_gc_set_clip_origin (widget->style->black_gc, mask_x, mask_y); - } - - if (rectangle_intersect_even (&area, &image_bound)) + if (pixbuf) { - if (pixbuf) - { - if (needs_state_transform) - { - GtkIconSource *source; - GdkPixbuf *rendered; - - source = gtk_icon_source_new (); - gtk_icon_source_set_pixbuf (source, pixbuf); - /* The size here is arbitrary; since size isn't - * wildcarded in the souce, it isn't supposed to be - * scaled by the engine function - */ - gtk_icon_source_set_size (source, - GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_icon_source_set_size_wildcarded (source, FALSE); - - rendered = gtk_style_render_icon (widget->style, - source, - gtk_widget_get_direction (widget), - GTK_WIDGET_STATE (widget), - /* arbitrary */ - (GtkIconSize)-1, - widget, - "gtk-image"); - - gtk_icon_source_free (source); - - g_object_unref (pixbuf); - pixbuf = rendered; - } - - if (pixbuf) - { - gdk_draw_pixbuf (widget->window, - widget->style->black_gc, - pixbuf, - image_bound.x - x, - image_bound.y - y, - image_bound.x, - image_bound.y, - image_bound.width, - image_bound.height, - GDK_RGB_DITHER_NORMAL, - 0, 0); - } - } - else + if (needs_state_transform) { - switch (image->storage_type) - { - case GTK_IMAGE_PIXMAP: - gdk_draw_drawable (widget->window, - widget->style->black_gc, - image->data.pixmap.pixmap, - image_bound.x - x, image_bound.y - y, - image_bound.x, image_bound.y, - image_bound.width, image_bound.height); - break; - - case GTK_IMAGE_IMAGE: - gdk_draw_image (widget->window, - widget->style->black_gc, - image->data.image.image, - image_bound.x - x, image_bound.y - y, - image_bound.x, image_bound.y, - image_bound.width, image_bound.height); - break; - - case GTK_IMAGE_PIXBUF: - case GTK_IMAGE_STOCK: - case GTK_IMAGE_ICON_SET: - case GTK_IMAGE_ANIMATION: - case GTK_IMAGE_ICON_NAME: - case GTK_IMAGE_EMPTY: - case GTK_IMAGE_GICON: - g_assert_not_reached (); - break; - } + GtkIconSource *source; + GdkPixbuf *rendered; + + source = gtk_icon_source_new (); + gtk_icon_source_set_pixbuf (source, pixbuf); + /* The size here is arbitrary; since size isn't + * wildcarded in the souce, it isn't supposed to be + * scaled by the engine function + */ + gtk_icon_source_set_size (source, + GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_icon_source_set_size_wildcarded (source, FALSE); + + rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1); + gtk_icon_source_free (source); + + g_object_unref (pixbuf); + pixbuf = rendered; } - } /* if rectangle intersects */ - if (mask) - { - gdk_gc_set_clip_mask (widget->style->black_gc, NULL); - gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0); + gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y); + cairo_paint (cr); + + g_object_unref (pixbuf); } - - if (pixbuf) - g_object_unref (pixbuf); - } /* if widget is drawable */ + gtk_style_context_restore (context); + } return FALSE; } @@ -2013,54 +1789,26 @@ gtk_image_expose (GtkWidget *widget, static void gtk_image_reset (GtkImage *image) { - GtkImagePrivate *priv; - - priv = GTK_IMAGE_GET_PRIVATE (image); + GtkImagePrivate *priv = image->priv; g_object_freeze_notify (G_OBJECT (image)); - if (image->storage_type != GTK_IMAGE_EMPTY) + if (priv->storage_type != GTK_IMAGE_EMPTY) g_object_notify (G_OBJECT (image), "storage-type"); - if (image->mask) - { - g_object_unref (image->mask); - image->mask = NULL; - g_object_notify (G_OBJECT (image), "mask"); - } - - if (image->icon_size != DEFAULT_ICON_SIZE) + if (priv->icon_size != DEFAULT_ICON_SIZE) { - image->icon_size = DEFAULT_ICON_SIZE; + priv->icon_size = DEFAULT_ICON_SIZE; g_object_notify (G_OBJECT (image), "icon-size"); } - switch (image->storage_type) + switch (priv->storage_type) { - case GTK_IMAGE_PIXMAP: - - if (image->data.pixmap.pixmap) - g_object_unref (image->data.pixmap.pixmap); - image->data.pixmap.pixmap = NULL; - - g_object_notify (G_OBJECT (image), "pixmap"); - - break; - - case GTK_IMAGE_IMAGE: - - if (image->data.image.image) - g_object_unref (image->data.image.image); - image->data.image.image = NULL; - - g_object_notify (G_OBJECT (image), "image"); - - break; case GTK_IMAGE_PIXBUF: - if (image->data.pixbuf.pixbuf) - g_object_unref (image->data.pixbuf.pixbuf); + if (priv->data.pixbuf.pixbuf) + g_object_unref (priv->data.pixbuf.pixbuf); g_object_notify (G_OBJECT (image), "pixbuf"); @@ -2068,17 +1816,17 @@ gtk_image_reset (GtkImage *image) case GTK_IMAGE_STOCK: - g_free (image->data.stock.stock_id); + g_free (priv->data.stock.stock_id); - image->data.stock.stock_id = NULL; + priv->data.stock.stock_id = NULL; g_object_notify (G_OBJECT (image), "stock"); break; case GTK_IMAGE_ICON_SET: - if (image->data.icon_set.icon_set) - gtk_icon_set_unref (image->data.icon_set.icon_set); - image->data.icon_set.icon_set = NULL; + if (priv->data.icon_set.icon_set) + gtk_icon_set_unref (priv->data.icon_set.icon_set); + priv->data.icon_set.icon_set = NULL; g_object_notify (G_OBJECT (image), "icon-set"); break; @@ -2086,32 +1834,32 @@ gtk_image_reset (GtkImage *image) case GTK_IMAGE_ANIMATION: gtk_image_reset_anim_iter (image); - if (image->data.anim.anim) - g_object_unref (image->data.anim.anim); - image->data.anim.anim = NULL; + if (priv->data.anim.anim) + g_object_unref (priv->data.anim.anim); + priv->data.anim.anim = NULL; g_object_notify (G_OBJECT (image), "pixbuf-animation"); break; case GTK_IMAGE_ICON_NAME: - g_free (image->data.name.icon_name); - image->data.name.icon_name = NULL; - if (image->data.name.pixbuf) - g_object_unref (image->data.name.pixbuf); - image->data.name.pixbuf = NULL; + g_free (priv->data.name.icon_name); + priv->data.name.icon_name = NULL; + if (priv->data.name.pixbuf) + g_object_unref (priv->data.name.pixbuf); + priv->data.name.pixbuf = NULL; g_object_notify (G_OBJECT (image), "icon-name"); break; case GTK_IMAGE_GICON: - if (image->data.gicon.icon) - g_object_unref (image->data.gicon.icon); - image->data.gicon.icon = NULL; - if (image->data.gicon.pixbuf) - g_object_unref (image->data.gicon.pixbuf); - image->data.gicon.pixbuf = NULL; + if (priv->data.gicon.icon) + g_object_unref (priv->data.gicon.icon); + priv->data.gicon.icon = NULL; + if (priv->data.gicon.pixbuf) + g_object_unref (priv->data.gicon.pixbuf); + priv->data.gicon.pixbuf = NULL; g_object_notify (G_OBJECT (image), "gicon"); @@ -2130,9 +1878,9 @@ gtk_image_reset (GtkImage *image) g_object_notify (G_OBJECT (image), "file"); } - image->storage_type = GTK_IMAGE_EMPTY; + priv->storage_type = GTK_IMAGE_EMPTY; - memset (&image->data, '\0', sizeof (image->data)); + memset (&priv->data, '\0', sizeof (priv->data)); g_object_thaw_notify (G_OBJECT (image)); } @@ -2148,8 +1896,11 @@ gtk_image_reset (GtkImage *image) void gtk_image_clear (GtkImage *image) { - gtk_image_reset (image); + GtkImagePrivate *priv = image->priv; + + priv->need_calc_size = 1; + gtk_image_reset (image); gtk_image_update_size (image, 0, 0); } @@ -2157,39 +1908,43 @@ static void gtk_image_calc_size (GtkImage *image) { GtkWidget *widget = GTK_WIDGET (image); + GtkImagePrivate *priv = image->priv; GdkPixbuf *pixbuf = NULL; - + GtkStyleContext *context; + GtkStateFlags state; + + priv->need_calc_size = 0; + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + + gtk_style_context_save (context); + gtk_style_context_set_state (context, state); + /* We update stock/icon set on every size request, because * the theme could have affected the size; for other kinds of - * image, we just update the requisition when the image data + * image, we just update the required width/height when the image data * is set. */ - switch (image->storage_type) + switch (priv->storage_type) { case GTK_IMAGE_STOCK: - pixbuf = gtk_widget_render_icon (widget, - image->data.stock.stock_id, - image->icon_size, - NULL); + pixbuf = gtk_widget_render_icon_pixbuf (widget, + priv->data.stock.stock_id, + priv->icon_size); break; case GTK_IMAGE_ICON_SET: - pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set, - widget->style, - gtk_widget_get_direction (widget), - GTK_WIDGET_STATE (widget), - image->icon_size, - widget, - NULL); + pixbuf = gtk_icon_set_render_icon_pixbuf (priv->data.icon_set.icon_set, + context, priv->icon_size); break; case GTK_IMAGE_ICON_NAME: - ensure_pixbuf_for_icon_name (image); - pixbuf = image->data.name.pixbuf; + ensure_pixbuf_for_icon_name (image, 0); + pixbuf = priv->data.name.pixbuf; if (pixbuf) g_object_ref (pixbuf); break; case GTK_IMAGE_GICON: - ensure_pixbuf_for_gicon (image); - pixbuf = image->data.gicon.pixbuf; + ensure_pixbuf_for_gicon (image, 0); + pixbuf = priv->data.gicon.pixbuf; if (pixbuf) g_object_ref (pixbuf); break; @@ -2199,38 +1954,60 @@ gtk_image_calc_size (GtkImage *image) if (pixbuf) { - widget->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2; - widget->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2; + gint xpad, ypad; + + gtk_misc_get_padding (GTK_MISC (image), &xpad, &ypad); + + priv->required_width = gdk_pixbuf_get_width (pixbuf) + xpad * 2; + priv->required_height = gdk_pixbuf_get_height (pixbuf) + ypad * 2; g_object_unref (pixbuf); } + + gtk_style_context_restore (context); } static void -gtk_image_size_request (GtkWidget *widget, - GtkRequisition *requisition) +gtk_image_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) { GtkImage *image; - + GtkImagePrivate *priv; + image = GTK_IMAGE (widget); + priv = image->priv; gtk_image_calc_size (image); - /* Chain up to default that simply reads current requisition */ - GTK_WIDGET_CLASS (gtk_image_parent_class)->size_request (widget, requisition); + *minimum = *natural = priv->required_width; } static void -gtk_image_style_set (GtkWidget *widget, - GtkStyle *prev_style) +gtk_image_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) { GtkImage *image; + GtkImagePrivate *priv; image = GTK_IMAGE (widget); + priv = image->priv; + + gtk_image_calc_size (image); + + *minimum = *natural = priv->required_height; +} + +static void +gtk_image_style_updated (GtkWidget *widget) +{ + GtkImage *image; + + image = GTK_IMAGE (widget); + + GTK_WIDGET_CLASS (gtk_image_parent_class)->style_updated (widget); - if (GTK_WIDGET_CLASS (gtk_image_parent_class)->style_set) - GTK_WIDGET_CLASS (gtk_image_parent_class)->style_set (widget, prev_style); - icon_theme_changed (image); } @@ -2254,11 +2031,17 @@ gtk_image_update_size (GtkImage *image, gint image_width, gint image_height) { - GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2; - GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2; + GtkWidget *widget = GTK_WIDGET (image); + GtkImagePrivate *priv = image->priv; + gint xpad, ypad; - if (GTK_WIDGET_VISIBLE (image)) - gtk_widget_queue_resize (GTK_WIDGET (image)); + gtk_misc_get_padding (GTK_MISC (image), &xpad, &ypad); + + priv->required_width = image_width + xpad * 2; + priv->required_height = image_height + ypad * 2; + + if (gtk_widget_get_visible (widget)) + gtk_widget_queue_resize (widget); } @@ -2280,30 +2063,30 @@ gtk_image_set_pixel_size (GtkImage *image, GtkImagePrivate *priv; g_return_if_fail (GTK_IS_IMAGE (image)); - - priv = GTK_IMAGE_GET_PRIVATE (image); + + priv = image->priv; if (priv->pixel_size != pixel_size) { priv->pixel_size = pixel_size; - if (image->storage_type == GTK_IMAGE_ICON_NAME) + if (priv->storage_type == GTK_IMAGE_ICON_NAME) { - if (image->data.name.pixbuf) + if (priv->data.name.pixbuf) { - g_object_unref (image->data.name.pixbuf); - image->data.name.pixbuf = NULL; + g_object_unref (priv->data.name.pixbuf); + priv->data.name.pixbuf = NULL; } gtk_image_update_size (image, pixel_size, pixel_size); } - if (image->storage_type == GTK_IMAGE_GICON) + if (priv->storage_type == GTK_IMAGE_GICON) { - if (image->data.gicon.pixbuf) + if (priv->data.gicon.pixbuf) { - g_object_unref (image->data.gicon.pixbuf); - image->data.gicon.pixbuf = NULL; + g_object_unref (priv->data.gicon.pixbuf); + priv->data.gicon.pixbuf = NULL; } gtk_image_update_size (image, pixel_size, pixel_size); @@ -2326,46 +2109,7 @@ gtk_image_set_pixel_size (GtkImage *image, gint gtk_image_get_pixel_size (GtkImage *image) { - GtkImagePrivate *priv; - g_return_val_if_fail (GTK_IS_IMAGE (image), -1); - - priv = GTK_IMAGE_GET_PRIVATE (image); - return priv->pixel_size; + return image->priv->pixel_size; } - -#ifdef G_OS_WIN32 - -#undef gtk_image_new_from_file - -GtkWidget* -gtk_image_new_from_file (const gchar *filename) -{ - gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL); - GtkWidget *retval; - - retval = gtk_image_new_from_file_utf8 (utf8_filename); - - g_free (utf8_filename); - - return retval; -} - -#undef gtk_image_set_from_file - -void -gtk_image_set_from_file (GtkImage *image, - const gchar *filename) -{ - gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL); - - gtk_image_set_from_file_utf8 (image, utf8_filename); - - g_free (utf8_filename); -} - -#endif - -#define __GTK_IMAGE_C__ -#include "gtkaliasdef.c"