diff options
author | Matthias Clasen <mclasen@redhat.com> | 2004-10-25 04:36:39 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-10-25 04:36:39 +0000 |
commit | b63431c82ade00c522ab2df06ee3476085bd6941 (patch) | |
tree | e37b71b3eb98a0ef9fb0c57e1bcf3e1b197728a9 | |
parent | 2b4ef0648abbc50db56ca367004153f6ce3f10ba (diff) | |
download | gtk+-b63431c82ade00c522ab2df06ee3476085bd6941.tar.gz |
Add a new type GTK_IMAGE_ICON_NAME for named icons, update the size and
2004-10-25 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkimage.h:
* gtk/gtkimage.c (gtk_image_new_from_icon_name)
(gtk_image_set_from_icon_name, gtk_image_get_icon_name)
(gtk_image_set_pixel_size, gtk_image_get_pixel_size): Add a
new type GTK_IMAGE_ICON_NAME for named icons, update the size
and content of stock, icon set and named icon images upon style
changes, and allow to set a fixed pixel size for named icon
images. (#155688, James Henstridge)
* tests/testimage.c: Test application for theming behaviour of
different image types and for image dnd.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 16 | ||||
-rw-r--r-- | docs/reference/ChangeLog | 4 | ||||
-rw-r--r-- | docs/reference/gtk/gtk-sections.txt | 6 | ||||
-rw-r--r-- | gtk/gtkimage.c | 439 | ||||
-rw-r--r-- | gtk/gtkimage.h | 26 | ||||
-rw-r--r-- | tests/testimage.c | 153 |
9 files changed, 681 insertions, 11 deletions
@@ -1,6 +1,20 @@ +2004-10-25 Matthias Clasen <mclasen@redhat.com> + + * gtk/gtkimage.h: + * gtk/gtkimage.c (gtk_image_new_from_icon_name) + (gtk_image_set_from_icon_name, gtk_image_get_icon_name) + (gtk_image_set_pixel_size, gtk_image_get_pixel_size): Add a + new type GTK_IMAGE_ICON_NAME for named icons, update the size + and content of stock, icon set and named icon images upon style + changes, and allow to set a fixed pixel size for named icon + images. (#155688, James Henstridge) + + * tests/testimage.c: Test application for theming behaviour of + different image types and for image dnd. + 2004-10-24 Matthias Clasen <mclasen@redhat.com> - * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, intialize the + * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, initialize the has_entry property, ref the model and add a finalizer. (#156325, Olivier Andrieu) diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index da41277cb4..db54756c05 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,6 +1,20 @@ +2004-10-25 Matthias Clasen <mclasen@redhat.com> + + * gtk/gtkimage.h: + * gtk/gtkimage.c (gtk_image_new_from_icon_name) + (gtk_image_set_from_icon_name, gtk_image_get_icon_name) + (gtk_image_set_pixel_size, gtk_image_get_pixel_size): Add a + new type GTK_IMAGE_ICON_NAME for named icons, update the size + and content of stock, icon set and named icon images upon style + changes, and allow to set a fixed pixel size for named icon + images. (#155688, James Henstridge) + + * tests/testimage.c: Test application for theming behaviour of + different image types and for image dnd. + 2004-10-24 Matthias Clasen <mclasen@redhat.com> - * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, intialize the + * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, initialize the has_entry property, ref the model and add a finalizer. (#156325, Olivier Andrieu) diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index da41277cb4..db54756c05 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,6 +1,20 @@ +2004-10-25 Matthias Clasen <mclasen@redhat.com> + + * gtk/gtkimage.h: + * gtk/gtkimage.c (gtk_image_new_from_icon_name) + (gtk_image_set_from_icon_name, gtk_image_get_icon_name) + (gtk_image_set_pixel_size, gtk_image_get_pixel_size): Add a + new type GTK_IMAGE_ICON_NAME for named icons, update the size + and content of stock, icon set and named icon images upon style + changes, and allow to set a fixed pixel size for named icon + images. (#155688, James Henstridge) + + * tests/testimage.c: Test application for theming behaviour of + different image types and for image dnd. + 2004-10-24 Matthias Clasen <mclasen@redhat.com> - * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, intialize the + * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, initialize the has_entry property, ref the model and add a finalizer. (#156325, Olivier Andrieu) diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index da41277cb4..db54756c05 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,6 +1,20 @@ +2004-10-25 Matthias Clasen <mclasen@redhat.com> + + * gtk/gtkimage.h: + * gtk/gtkimage.c (gtk_image_new_from_icon_name) + (gtk_image_set_from_icon_name, gtk_image_get_icon_name) + (gtk_image_set_pixel_size, gtk_image_get_pixel_size): Add a + new type GTK_IMAGE_ICON_NAME for named icons, update the size + and content of stock, icon set and named icon images upon style + changes, and allow to set a fixed pixel size for named icon + images. (#155688, James Henstridge) + + * tests/testimage.c: Test application for theming behaviour of + different image types and for image dnd. + 2004-10-24 Matthias Clasen <mclasen@redhat.com> - * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, intialize the + * gtk/gtkcellrenderercombo.c: Use G_DEFINE_TYPE, initialize the has_entry property, ref the model and add a finalizer. (#156325, Olivier Andrieu) diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 4e95e434cc..8e059b4b09 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,7 @@ +2004-10-25 Matthias Clasen <mclasen@redhat.com> + + * gtk/gtk-sections.txt: Add new named icon api in GtkImage. + Sun Oct 24 02:54:36 2004 Jonathan Blandford <jrb@redhat.com> * gtk/gtk.types: Add GtkAboutDialog and GtkFileChooserButton diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt index b39ca13279..b7d100fa31 100644 --- a/docs/reference/gtk/gtk-sections.txt +++ b/docs/reference/gtk/gtk-sections.txt @@ -1664,6 +1664,7 @@ gtk_image_get_pixbuf gtk_image_get_pixmap gtk_image_get_stock gtk_image_get_animation +gtk_image_get_icon_name gtk_image_get_storage_type gtk_image_new_from_file gtk_image_new_from_icon_set @@ -1672,6 +1673,7 @@ gtk_image_new_from_pixbuf gtk_image_new_from_pixmap gtk_image_new_from_stock gtk_image_new_from_animation +gtk_image_new_from_icon_name gtk_image_set_from_file gtk_image_set_from_icon_set gtk_image_set_from_image @@ -1679,9 +1681,12 @@ gtk_image_set_from_pixbuf gtk_image_set_from_pixmap gtk_image_set_from_stock gtk_image_set_from_animation +gtk_image_set_from_icon_name gtk_image_new gtk_image_set gtk_image_get +gtk_image_set_pixel_size +gtk_image_get_pixel_size <SUBSECTION Standard> GTK_IMAGE GTK_IS_IMAGE @@ -1697,6 +1702,7 @@ GtkImagePixbufData GtkImagePixmapData GtkImageStockData GtkImageAnimationData +GtkImageIconNameData </SECTION> <SECTION> diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 8d8b54ad3a..56bfb59aea 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -31,9 +31,18 @@ #include "gtkimage.h" #include "gtkiconfactory.h" #include "gtkstock.h" +#include "gtkicontheme.h" #include "gtkintl.h" #include <string.h> +typedef struct _GtkImagePrivate GtkImagePrivate; + +struct _GtkImagePrivate +{ + gint pixel_size; +}; + +#define GTK_IMAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_IMAGE, GtkImagePrivate)) #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON @@ -46,6 +55,8 @@ 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_destroy (GtkObject *object); static void gtk_image_clear (GtkImage *image); static void gtk_image_reset (GtkImage *image); @@ -77,7 +88,9 @@ enum PROP_STOCK, PROP_ICON_SET, PROP_ICON_SIZE, + PROP_PIXEL_SIZE, PROP_PIXBUF_ANIMATION, + PROP_ICON_NAME, PROP_STORAGE_TYPE }; @@ -132,6 +145,7 @@ gtk_image_class_init (GtkImageClass *class) widget_class->size_request = gtk_image_size_request; widget_class->unmap = gtk_image_unmap; widget_class->unrealize = gtk_image_unrealize; + widget_class->style_set = gtk_image_style_set; g_object_class_install_property (gobject_class, PROP_PIXBUF, @@ -194,11 +208,28 @@ gtk_image_class_init (GtkImageClass *class) PROP_ICON_SIZE, g_param_spec_int ("icon_size", P_("Icon size"), - P_("Size to use for stock icon or icon set"), + P_("Symbolic size to use for stock icon, icon set or named icon"), 0, G_MAXINT, DEFAULT_ICON_SIZE, G_PARAM_READWRITE)); - + /** + * GtkImage:pixel-size: + * + * The :pixel-size property can be used to specify a fixed size + * overriding the :icon-size property for images of type + * %GTK_IMAGE_ICON_NAME. + * + * Since: 2.6 + */ + g_object_class_install_property (gobject_class, + PROP_PIXEL_SIZE, + g_param_spec_int ("pixel_size", + P_("Pixel size"), + P_("Pixel size to use for named icon"), + -1, G_MAXINT, + -1, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_PIXBUF_ANIMATION, g_param_spec_object ("pixbuf_animation", @@ -206,6 +237,22 @@ gtk_image_class_init (GtkImageClass *class) P_("GdkPixbufAnimation to display"), GDK_TYPE_PIXBUF_ANIMATION, G_PARAM_READWRITE)); + + /** + * GtkImage:icon-name: + * + * The name of the icon in the icon theme. If the icon theme is + * changed, the image will be updated automatically. + * + * Since: 2.6 + */ + g_object_class_install_property (gobject_class, + PROP_ICON_NAME, + g_param_spec_string ("icon_name", + P_("Icon Name"), + P_("The name of the icon from the icon theme"), + NULL, + G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_STORAGE_TYPE, @@ -215,16 +262,22 @@ gtk_image_class_init (GtkImageClass *class) GTK_TYPE_IMAGE_TYPE, GTK_IMAGE_EMPTY, G_PARAM_READABLE)); + + g_type_class_add_private (object_class, sizeof (GtkImagePrivate)); } static void gtk_image_init (GtkImage *image) { + GtkImagePrivate *priv = GTK_IMAGE_GET_PRIVATE (image); + GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW); image->storage_type = GTK_IMAGE_EMPTY; image->icon_size = DEFAULT_ICON_SIZE; image->mask = NULL; + + priv->pixel_size = -1; } static void @@ -244,8 +297,10 @@ gtk_image_set_property (GObject *object, GParamSpec *pspec) { GtkImage *image; + GtkImagePrivate *priv; image = GTK_IMAGE (object); + priv = GTK_IMAGE_GET_PRIVATE (image); switch (prop_id) { @@ -307,15 +362,24 @@ gtk_image_set_property (GObject *object, gtk_image_set_from_icon_set (image, image->data.icon_set.icon_set, g_value_get_int (value)); + else if (image->storage_type == GTK_IMAGE_ICON_NAME) + gtk_image_set_from_icon_name (image, + image->data.name.icon_name, + 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); break; + case PROP_PIXEL_SIZE: + priv->pixel_size = g_value_get_int (value); + break; case PROP_PIXBUF_ANIMATION: gtk_image_set_from_animation (image, g_value_get_object (value)); break; - + case PROP_ICON_NAME: + gtk_image_set_from_icon_name (image, g_value_get_string (value), + image->icon_size); default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -329,8 +393,10 @@ gtk_image_get_property (GObject *object, GParamSpec *pspec) { GtkImage *image; + GtkImagePrivate *priv; image = GTK_IMAGE (object); + priv = GTK_IMAGE_GET_PRIVATE (image); /* The "getter" functions whine if you try to get the wrong * storage type. This function is instead robust against that, @@ -381,6 +447,9 @@ gtk_image_get_property (GObject *object, case PROP_ICON_SIZE: g_value_set_int (value, image->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) g_value_set_object (value, NULL); @@ -388,6 +457,13 @@ gtk_image_get_property (GObject *object, g_value_set_object (value, image->data.anim.anim); break; + case PROP_ICON_NAME: + if (image->storage_type != GTK_IMAGE_ICON_NAME) + g_value_set_object (value, NULL); + else + g_value_set_string (value, + image->data.name.icon_name); + break; case PROP_STORAGE_TYPE: g_value_set_enum (value, image->storage_type); break; @@ -600,6 +676,33 @@ gtk_image_new_from_animation (GdkPixbufAnimation *animation) } /** + * gtk_image_new_from_icon_name: + * @icon_name: an icon name + * @size: 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 + * displayed instead. If the current icon theme is changed, the icon + * will be updated appropriately. + * + * Return value: a new #GtkImage displaying the themed icon + * + * Since: 2.6 + **/ +GtkWidget* +gtk_image_new_from_icon_name (const gchar *icon_name, + GtkIconSize size) +{ + GtkImage *image; + + image = g_object_new (GTK_TYPE_IMAGE, NULL); + + gtk_image_set_from_icon_name (image, icon_name, size); + + return GTK_WIDGET (image); +} + +/** * gtk_image_set_from_pixmap: * @image: a #GtkImage * @pixmap: a #GdkPixmap or %NULL @@ -926,6 +1029,51 @@ 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 + * + * See gtk_image_new_from_icon_name() for details. + * + * Since: 2.6 + **/ +void +gtk_image_set_from_icon_name (GtkImage *image, + const gchar *icon_name, + GtkIconSize size) +{ + gchar *new_name; + + g_return_if_fail (GTK_IS_IMAGE (image)); + + g_object_freeze_notify (G_OBJECT (image)); + + /* in case stock_id == image->data.stock.stock_id */ + new_name = g_strdup (icon_name); + + gtk_image_reset (image); + + if (new_name) + { + image->storage_type = GTK_IMAGE_ICON_NAME; + + image->data.name.icon_name = new_name; + image->icon_size = size; + + /* Size is demand-computed in size request method + * if we're a icon theme image, since changing the + * style impacts the size request + */ + } + + g_object_notify (G_OBJECT (image), "icon_name"); + g_object_notify (G_OBJECT (image), "icon_size"); + + g_object_thaw_notify (G_OBJECT (image)); +} + +/** * gtk_image_get_storage_type: * @image: a #GtkImage * @@ -1113,6 +1261,39 @@ gtk_image_get_animation (GtkImage *image) } /** + * gtk_image_get_icon_name: + * @image: a #GtkImage + * @icon_name: place to store an icon name + * @size: place to store an icon size + * + * Gets the icon name and size being displayed by the #GtkImage. + * The storage type of the image must be %GTK_IMAGE_EMPTY or + * %GTK_IMAGE_ICON_NAME (see gtk_image_get_storage_type()). + * The returned string is owned by the #GtkImage and should not + * be freed. + * + * Since: 2.6 + **/ +void +gtk_image_get_icon_name (GtkImage *image, + gchar **icon_name, + GtkIconSize *size) +{ + 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; + + if (icon_name) + *icon_name = image->data.name.icon_name; + + if (size) + *size = image->icon_size; +} + +/** * gtk_image_new: * * Creates a new empty #GtkImage widget. @@ -1167,9 +1348,29 @@ gtk_image_reset_anim_iter (GtkImage *image) } static void +gtk_image_reset_icon_theme_change_cb (GtkImage *image) +{ + GdkScreen *screen; + GtkIconTheme *icon_theme; + + if (image->storage_type == GTK_IMAGE_ICON_NAME) + { + if (image->data.name.theme_change_id) + { + screen = gtk_widget_get_screen (GTK_WIDGET (image)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + g_signal_handler_disconnect (icon_theme, + image->data.name.theme_change_id); + } + image->data.name.theme_change_id = 0; + } +} + +static void gtk_image_unmap (GtkWidget *widget) { gtk_image_reset_anim_iter (GTK_IMAGE (widget)); + gtk_image_reset_icon_theme_change_cb (GTK_IMAGE (widget)); if (GTK_WIDGET_CLASS (parent_class)->unmap) GTK_WIDGET_CLASS (parent_class)->unmap (widget); @@ -1179,6 +1380,7 @@ static void gtk_image_unrealize (GtkWidget *widget) { gtk_image_reset_anim_iter (GTK_IMAGE (widget)); + gtk_image_reset_icon_theme_change_cb (GTK_IMAGE (widget)); if (GTK_WIDGET_CLASS (parent_class)->unrealize) GTK_WIDGET_CLASS (parent_class)->unrealize (widget); @@ -1210,6 +1412,98 @@ animation_timeout (gpointer data) return FALSE; } +static void +icon_theme_changed (GtkIconTheme *icon_theme, + GtkImage *image) +{ + if (image->data.name.pixbuf) + g_object_unref (image->data.name.pixbuf); + image->data.name.pixbuf = NULL; + + gtk_widget_queue_draw (GTK_WIDGET (image)); +} + +static void +ensure_pixbuf_for_icon_name (GtkImage *image) +{ + GtkImagePrivate *priv; + GdkScreen *screen; + GtkIconTheme *icon_theme; + GtkSettings *settings; + gint width, height; + gint *sizes, *s, dist; + GError *error = NULL; + + g_return_if_fail (image->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); + if (image->data.name.pixbuf == NULL) + { + if (priv->pixel_size != -1) + { + width = height = priv->pixel_size; + } + else if (!gtk_icon_size_lookup_for_settings (settings, + image->icon_size, + &width, &height)) + { + if (image->icon_size == -1) + { + /* Find an available size close to 48 */ + sizes = gtk_icon_theme_get_icon_sizes (icon_theme, image->data.name.icon_name); + dist = 100; + width = height = 48; + for (s = sizes; *s; s++) + { + if (*s == -1) + { + width = height = 48; + break; + } + if (*s < 48) + { + if (48 - *s < dist) + { + width = height = *s; + dist = 48 - *s; + } + } + else + { + if (*s - 48 < dist) + { + width = height = *s; + dist = *s - 48; + } + } + } + g_free (sizes); + } + else + { + g_warning ("Invalid icon size %d\n", image->icon_size); + width = height = 24; + } + } + image->data.name.pixbuf = + gtk_icon_theme_load_icon (icon_theme, + image->data.name.icon_name, + MIN (width, height), 0, &error); + if (image->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); + } + } +} + /* * Like gdk_rectangle_intersect (dest, src, dest), but make * sure that the origin of dest is moved by an "even" offset. @@ -1266,6 +1560,8 @@ gtk_image_expose (GtkWidget *widget, GdkBitmap *mask; GdkPixbuf *pixbuf; gboolean needs_state_transform; + GdkScreen *screen; + GtkIconTheme *icon_theme; image = GTK_IMAGE (widget); misc = GTK_MISC (widget); @@ -1433,6 +1729,26 @@ gtk_image_expose (GtkWidget *widget, } break; + case GTK_IMAGE_ICON_NAME: + if (image->data.name.theme_change_id == 0) + { + screen = gtk_widget_get_screen (widget); + icon_theme = gtk_icon_theme_get_for_screen (screen); + image->data.name.theme_change_id = + g_signal_connect_object (icon_theme, "changed", + G_CALLBACK (icon_theme_changed), + image, 0); + } + ensure_pixbuf_for_icon_name (image); + pixbuf = image->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_EMPTY: g_assert_not_reached (); break; @@ -1522,6 +1838,7 @@ gtk_image_expose (GtkWidget *widget, case GTK_IMAGE_STOCK: case GTK_IMAGE_ICON_SET: case GTK_IMAGE_ANIMATION: + case GTK_IMAGE_ICON_NAME: case GTK_IMAGE_EMPTY: g_assert_not_reached (); break; @@ -1619,6 +1936,20 @@ gtk_image_clear (GtkImage *image) g_object_notify (G_OBJECT (image), "pixbuf_animation"); break; + + case GTK_IMAGE_ICON_NAME: + gtk_image_reset_icon_theme_change_cb (image); + + if (image->data.name.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_object_notify (G_OBJECT (image), "icon_name"); + + break; case GTK_IMAGE_EMPTY: default: @@ -1670,7 +2001,11 @@ gtk_image_calc_size (GtkImage *image) widget, NULL); break; - + case GTK_IMAGE_ICON_NAME: + ensure_pixbuf_for_icon_name (image); + pixbuf = image->data.name.pixbuf; + if (pixbuf) g_object_ref (pixbuf); + break; default: break; } @@ -1699,6 +2034,39 @@ gtk_image_size_request (GtkWidget *widget, } static void +gtk_image_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GtkImage *image; + + image = GTK_IMAGE (widget); + + /* If the GTK style changes, the pixel values corresponding to + * particular GtkIconSize values can change. So if the image's + * storage type makes use of the icon size, queue a resize. + */ + switch (image->storage_type) + { + case GTK_IMAGE_ICON_NAME: + /* release the cached pixbuf */ + if (image->data.name.pixbuf != NULL) + { + g_object_unref (image->data.name.pixbuf); + image->data.name.pixbuf = NULL; + } + /* fall through */ + case GTK_IMAGE_STOCK: + case GTK_IMAGE_ICON_SET: + gtk_widget_queue_resize (widget); + break; + default: + break; + } + + GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style); +} + +static void gtk_image_update_size (GtkImage *image, gint image_width, gint image_height) @@ -1709,3 +2077,66 @@ gtk_image_update_size (GtkImage *image, if (GTK_WIDGET_VISIBLE (image)) gtk_widget_queue_resize (GTK_WIDGET (image)); } + + +/** + * gtk_image_set_pixel_size: + * @image: a #GtkImage + * @pixel_size: the new pixel size + * + * Sets the pixel size to use for named icons. If the pixel size is set + * to a value != -1, it is used instead of the ::icon-size property for + * images of type %GTK_IMAGE_ICON_NAME. + * + * Since: 2.6 + */ +void +gtk_image_set_pixel_size (GtkImage *image, + gint pixel_size) +{ + GtkImagePrivate *priv; + + g_return_if_fail (GTK_IS_IMAGE (image)); + + priv = GTK_IMAGE_GET_PRIVATE (image); + + if (priv->pixel_size != pixel_size) + { + priv->pixel_size = pixel_size; + + if (image->storage_type == GTK_IMAGE_ICON_NAME) + { + if (image->data.name.pixbuf) + { + g_object_unref (image->data.name.pixbuf); + image->data.name.pixbuf = NULL; + } + + gtk_image_update_size (image, pixel_size, pixel_size); + } + + g_object_notify (G_OBJECT (image), "pixel-size"); + } +} + +/** + * gtk_image_get_pixel_size: + * @image: a #GtkImage + * + * Gets the pixel size used for named icons. + * + * Returns: the value of the :pixel-size property. + * + * Since: 2.6 + */ +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; +} diff --git a/gtk/gtkimage.h b/gtk/gtkimage.h index 2b997ab6d8..28c6776c64 100644 --- a/gtk/gtkimage.h +++ b/gtk/gtkimage.h @@ -53,6 +53,7 @@ typedef struct _GtkImagePixbufData GtkImagePixbufData; typedef struct _GtkImageStockData GtkImageStockData; typedef struct _GtkImageIconSetData GtkImageIconSetData; typedef struct _GtkImageAnimationData GtkImageAnimationData; +typedef struct _GtkImageIconNameData GtkImageIconNameData; struct _GtkImagePixmapData { @@ -86,6 +87,13 @@ struct _GtkImageAnimationData guint frame_timeout; }; +struct _GtkImageIconNameData +{ + gchar *icon_name; + GdkPixbuf *pixbuf; + guint theme_change_id; +}; + typedef enum { GTK_IMAGE_EMPTY, @@ -94,7 +102,8 @@ typedef enum GTK_IMAGE_PIXBUF, GTK_IMAGE_STOCK, GTK_IMAGE_ICON_SET, - GTK_IMAGE_ANIMATION + GTK_IMAGE_ANIMATION, + GTK_IMAGE_ICON_NAME } GtkImageType; struct _GtkImage @@ -111,12 +120,13 @@ struct _GtkImage GtkImageStockData stock; GtkImageIconSetData icon_set; GtkImageAnimationData anim; + GtkImageIconNameData name; } data; /* Only used with GTK_IMAGE_PIXMAP, GTK_IMAGE_IMAGE */ GdkBitmap *mask; - /* Only used with GTK_IMAGE_STOCK, GTK_IMAGE_ICON_SET */ + /* Only used with GTK_IMAGE_STOCK, GTK_IMAGE_ICON_SET, GTK_IMAGE_ICON_NAME */ GtkIconSize icon_size; }; @@ -145,6 +155,8 @@ GtkWidget* gtk_image_new_from_stock (const gchar *stock_id, GtkWidget* gtk_image_new_from_icon_set (GtkIconSet *icon_set, GtkIconSize size); GtkWidget* gtk_image_new_from_animation (GdkPixbufAnimation *animation); +GtkWidget* gtk_image_new_from_icon_name (const gchar *icon_name, + GtkIconSize size); void gtk_image_set_from_pixmap (GtkImage *image, GdkPixmap *pixmap, @@ -164,6 +176,11 @@ void gtk_image_set_from_icon_set (GtkImage *image, GtkIconSize size); void gtk_image_set_from_animation (GtkImage *image, GdkPixbufAnimation *animation); +void gtk_image_set_from_icon_name (GtkImage *image, + const gchar *icon_name, + GtkIconSize size); +void gtk_image_set_pixel_size (GtkImage *image, + gint pixel_size); GtkImageType gtk_image_get_storage_type (GtkImage *image); @@ -181,7 +198,10 @@ void gtk_image_get_icon_set (GtkImage *image, GtkIconSet **icon_set, GtkIconSize *size); GdkPixbufAnimation* gtk_image_get_animation (GtkImage *image); - +void gtk_image_get_icon_name (GtkImage *image, + gchar **icon_name, + GtkIconSize *size); +gint gtk_image_get_pixel_size (GtkImage *image); #ifndef GTK_DISABLE_DEPRECATED /* These three are deprecated */ diff --git a/tests/testimage.c b/tests/testimage.c new file mode 100644 index 0000000000..b9ade1d1f2 --- /dev/null +++ b/tests/testimage.c @@ -0,0 +1,153 @@ +/* testimage.c + * Copyright (C) 2004 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gtk/gtk.h> + +static void +drag_begin (GtkWidget *widget, + GdkDragContext *context, + gpointer data) +{ + GtkWidget *image = GTK_WIDGET (data); + + GdkPixbuf *pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (image)); + + gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2); +} + +void +drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + GtkWidget *image = GTK_WIDGET (data); + + GdkPixbuf *pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (image)); + + gtk_selection_data_set_pixbuf (selection_data, pixbuf); +} + +static void +drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time, + gpointer data) +{ + GtkWidget *image = GTK_WIDGET (data); + + GdkPixbuf *pixbuf; + + if (selection_data->length < 0) + return; + + pixbuf = gtk_selection_data_get_pixbuf (selection_data); + + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *table; + GtkWidget *label, *image, *box; + GtkIconTheme *theme; + GdkPixbuf *pixbuf; + GtkIconSet *iconset; + GtkIconSource *iconsource; + gchar *icon_name = "gnome-terminal"; + + gtk_init (&argc, &argv); + + if (argc > 1) + icon_name = argv[1]; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + table = gtk_table_new (4, 3, FALSE); + gtk_container_add (GTK_CONTAINER (window), table); + + label = gtk_label_new ("symbolic size"); + gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1, + 0, 0, 5, 5); + label = gtk_label_new ("fixed size"); + gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1, + 0, 0, 5, 5); + + label = gtk_label_new ("GTK_IMAGE_PIXBUF"); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2); + + theme = gtk_icon_theme_get_default (); + pixbuf = gtk_icon_theme_load_icon (theme, icon_name, 48, 0, NULL); + image = gtk_image_new_from_pixbuf (pixbuf); + box = gtk_event_box_new (); + gtk_container_add (GTK_CONTAINER (box), image); + gtk_table_attach_defaults (GTK_TABLE (table), box, 2, 3, 1, 2); + + gtk_drag_source_set (box, GDK_BUTTON1_MASK, + NULL, 0, + GDK_ACTION_COPY); + gtk_drag_source_add_image_targets (box); + g_signal_connect (box, "drag_begin", G_CALLBACK (drag_begin), image); + g_signal_connect (box, "drag_data_get", G_CALLBACK (drag_data_get), image); + + gtk_drag_dest_set (box, + GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_HIGHLIGHT | + GTK_DEST_DEFAULT_DROP, + NULL, 0, GDK_ACTION_COPY); + gtk_drag_dest_add_image_targets (box); + g_signal_connect (box, "drag_data_received", + G_CALLBACK (drag_data_received), image); + + label = gtk_label_new ("GTK_IMAGE_STOCK"); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3); + + image = gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_DIALOG); + gtk_table_attach_defaults (GTK_TABLE (table), image, 1, 2, 2, 3); + + label = gtk_label_new ("GTK_IMAGE_ICON_SET"); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4); + + iconsource = gtk_icon_source_new (); + gtk_icon_source_set_icon_name (iconsource, icon_name); + iconset = gtk_icon_set_new (); + gtk_icon_set_add_source (iconset, iconsource); + image = gtk_image_new_from_icon_set (iconset, GTK_ICON_SIZE_DIALOG); + gtk_table_attach_defaults (GTK_TABLE (table), image, 1, 2, 3, 4); + + label = gtk_label_new ("GTK_IMAGE_ICON_NAME"); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5); + image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DIALOG); + gtk_table_attach_defaults (GTK_TABLE (table), image, 1, 2, 4, 5); + image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DIALOG); + gtk_image_set_pixel_size (GTK_IMAGE (image), 30); + gtk_table_attach_defaults (GTK_TABLE (table), image, 2, 3, 4, 5); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} |