diff options
author | Matthias Clasen <mclasen@redhat.com> | 2008-05-29 14:33:49 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2008-05-29 14:33:49 +0000 |
commit | ee8253f908d2541321d72a0151fcfeb7446f7b8f (patch) | |
tree | aba76516a9370271ff86850367542c38b61a7d7b /gtk/gtkimage.c | |
parent | 24ac36693bebbd22416f91fc78c6fe189f953d94 (diff) | |
download | gtk+-ee8253f908d2541321d72a0151fcfeb7446f7b8f.tar.gz |
Bug 522084 – GIcon support for GtkIconTheme & GtkImage
2008-05-27 Matthias Clasen <mclasen@redhat.com>
Bug 522084 – GIcon support for GtkIconTheme & GtkImage
* gtk/gtkicontheme.[hc]: Add support for GIcon based lookups.
* gtk/gtkimage.[hc]: Allow setting an image from a GIcon.
* gtk/gtk.symbols: Additions
* tests/testimage.c: Add a GIcon test
svn path=/trunk/; revision=20236
Diffstat (limited to 'gtk/gtkimage.c')
-rw-r--r-- | gtk/gtkimage.c | 237 |
1 files changed, 236 insertions, 1 deletions
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 43c442613d..07ce08fb58 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -94,7 +94,8 @@ enum PROP_PIXEL_SIZE, PROP_PIXBUF_ANIMATION, PROP_ICON_NAME, - PROP_STORAGE_TYPE + PROP_STORAGE_TYPE, + PROP_GICON }; G_DEFINE_TYPE (GtkImage, gtk_image, GTK_TYPE_MISC) @@ -231,6 +232,23 @@ gtk_image_class_init (GtkImageClass *class) NULL, GTK_PARAM_READWRITE)); + /** + * GtkImage:gicon: + * + * The GIcon displayed in the GtkImage. For themed icons, + * If the icon theme is changed, the image will be updated + * automatically. + * + * Since: 2.14 + */ + g_object_class_install_property (gobject_class, + PROP_GICON, + g_param_spec_object ("gicon", + P_("Icon"), + P_("The GIcon being displayed"), + G_TYPE_ICON, + GTK_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_STORAGE_TYPE, g_param_spec_enum ("storage-type", @@ -357,6 +375,10 @@ gtk_image_set_property (GObject *object, gtk_image_set_from_icon_name (image, g_value_get_string (value), image->icon_size); break; + case PROP_GICON: + gtk_image_set_from_gicon (image, g_value_get_object (value), + image->icon_size); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -445,6 +467,13 @@ gtk_image_get_property (GObject *object, g_value_set_string (value, image->data.name.icon_name); break; + case PROP_GICON: + if (image->storage_type != GTK_IMAGE_GICON) + g_value_set_object (value, NULL); + else + g_value_set_object (value, + image->data.gicon.icon); + break; case PROP_STORAGE_TYPE: g_value_set_enum (value, image->storage_type); break; @@ -687,6 +716,33 @@ gtk_image_new_from_icon_name (const gchar *icon_name, } /** + * gtk_image_new_from_gicon: + * @icon: an icon + * @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.14 + **/ +GtkWidget* +gtk_image_new_from_gicon (GIcon *icon, + GtkIconSize size) +{ + GtkImage *image; + + image = g_object_new (GTK_TYPE_IMAGE, NULL); + + gtk_image_set_from_gicon (image, icon, size); + + return GTK_WIDGET (image); +} + +/** * gtk_image_set_from_pixmap: * @image: a #GtkImage * @pixmap: a #GdkPixmap or %NULL @@ -1052,6 +1108,50 @@ gtk_image_set_from_icon_name (GtkImage *image, } /** + * gtk_image_set_from_gicon: + * @image: a #GtkImage + * @icon: an icon + * @size: an icon size + * + * See gtk_image_new_from_gicon() for details. + * + * Since: 2.14 + **/ +void +gtk_image_set_from_gicon (GtkImage *image, + GIcon *icon, + GtkIconSize size) +{ + g_return_if_fail (GTK_IS_IMAGE (image)); + + g_object_freeze_notify (G_OBJECT (image)); + + /* in case icon == image->data.gicon.icon */ + if (icon) + g_object_ref (icon); + + gtk_image_clear (image); + + if (icon) + { + image->storage_type = GTK_IMAGE_GICON; + + image->data.gicon.icon = icon; + 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), "gicon"); + g_object_notify (G_OBJECT (image), "icon-size"); + + g_object_thaw_notify (G_OBJECT (image)); +} + +/** * gtk_image_get_storage_type: * @image: a #GtkImage * @@ -1267,6 +1367,39 @@ gtk_image_get_icon_name (GtkImage *image, } /** + * gtk_image_get_gicon: + * @image: a #GtkImage + * @gicon: place to store a #GIcon + * @size: place to store an icon size + * + * Gets the #GIcon and size being displayed by the #GtkImage. + * The storage type of the image must be %GTK_IMAGE_EMPTY or + * %GTK_IMAGE_GICON (see gtk_image_get_storage_type()). + * The caller of this function does not own a reference to the + * returned #GIcon. + * + * Since: 2.14 + **/ +void +gtk_image_get_gicon (GtkImage *image, + GIcon **gicon, + GtkIconSize *size) +{ + 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; + + if (gicon) + *gicon = image->data.gicon.icon; + + if (size) + *size = image->icon_size; +} + +/** * gtk_image_new: * * Creates a new empty #GtkImage widget. @@ -1376,6 +1509,14 @@ icon_theme_changed (GtkImage *image) gtk_widget_queue_draw (GTK_WIDGET (image)); } + if (image->storage_type == GTK_IMAGE_GICON) + { + if (image->data.gicon.pixbuf) + g_object_unref (image->data.gicon.pixbuf); + image->data.gicon.pixbuf = NULL; + + gtk_widget_queue_draw (GTK_WIDGET (image)); + } } static void @@ -1459,6 +1600,59 @@ ensure_pixbuf_for_icon_name (GtkImage *image) } } +static void +ensure_pixbuf_for_gicon (GtkImage *image) +{ + GtkImagePrivate *priv; + GdkScreen *screen; + GtkIconTheme *icon_theme; + GtkSettings *settings; + gint width, height; + GError *error = NULL; + GtkIconInfo *info; + + g_return_if_fail (image->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); + if (image->data.gicon.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) + width = height = 48; + else + { + g_warning ("Invalid icon size %d\n", image->icon_size); + width = height = 24; + } + } + + info = gtk_icon_theme_lookup_by_gicon (icon_theme, + image->data.gicon.icon, + MIN (width, height), 0); + 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. @@ -1690,6 +1884,17 @@ gtk_image_expose (GtkWidget *widget, } break; + case GTK_IMAGE_GICON: + ensure_pixbuf_for_gicon (image); + pixbuf = image->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: g_assert_not_reached (); break; @@ -1778,6 +1983,7 @@ gtk_image_expose (GtkWidget *widget, case GTK_IMAGE_ANIMATION: case GTK_IMAGE_ICON_NAME: case GTK_IMAGE_EMPTY: + case GTK_IMAGE_GICON: g_assert_not_reached (); break; } @@ -1893,6 +2099,18 @@ gtk_image_reset (GtkImage *image) 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; + + g_object_notify (G_OBJECT (image), "gicon"); + + break; + case GTK_IMAGE_EMPTY: default: break; @@ -1963,6 +2181,12 @@ gtk_image_calc_size (GtkImage *image) pixbuf = image->data.name.pixbuf; if (pixbuf) g_object_ref (pixbuf); break; + case GTK_IMAGE_GICON: + ensure_pixbuf_for_gicon (image); + pixbuf = image->data.gicon.pixbuf; + if (pixbuf) + g_object_ref (pixbuf); + break; default: break; } @@ -2068,6 +2292,17 @@ gtk_image_set_pixel_size (GtkImage *image, gtk_image_update_size (image, pixel_size, pixel_size); } + if (image->storage_type == GTK_IMAGE_GICON) + { + if (image->data.gicon.pixbuf) + { + g_object_unref (image->data.gicon.pixbuf); + image->data.gicon.pixbuf = NULL; + } + + gtk_image_update_size (image, pixel_size, pixel_size); + } + g_object_notify (G_OBJECT (image), "pixel-size"); } } |