]> Pileus Git - ~andy/gtk/commitdiff
Add a new type GTK_IMAGE_ICON_NAME for named icons, update the size and
authorMatthias Clasen <mclasen@redhat.com>
Mon, 25 Oct 2004 04:36:39 +0000 (04:36 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Mon, 25 Oct 2004 04:36:39 +0000 (04:36 +0000)
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.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/reference/ChangeLog
docs/reference/gtk/gtk-sections.txt
gtk/gtkimage.c
gtk/gtkimage.h
tests/testimage.c [new file with mode: 0644]

index da41277cb455ce7bc51c8a2f5166119c31b57e48..db54756c051896e98a9d5b94a639f09d48404837 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
        
index da41277cb455ce7bc51c8a2f5166119c31b57e48..db54756c051896e98a9d5b94a639f09d48404837 100644 (file)
@@ -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)
        
index da41277cb455ce7bc51c8a2f5166119c31b57e48..db54756c051896e98a9d5b94a639f09d48404837 100644 (file)
@@ -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)
        
index da41277cb455ce7bc51c8a2f5166119c31b57e48..db54756c051896e98a9d5b94a639f09d48404837 100644 (file)
@@ -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)
        
index 4e95e434ccbad3d371788c1d7cbe36218abac0ba..8e059b4b09c1b89aa37e37763595cfd2329c3eef 100644 (file)
@@ -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
index b39ca13279bc5bb2cb5f3c72546997e2e508a6e5..b7d100fa31477932a0efecd6eedf7407ab37b8d0 100644 (file)
@@ -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>
index 8d8b54ad3a104e95be5a81f5ede93ef7ce39ce5f..56bfb59aeac02c6985bcff6cb082ab1d7cc7b999 100644 (file)
 #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;
@@ -599,6 +675,33 @@ gtk_image_new_from_animation (GdkPixbufAnimation *animation)
   return GTK_WIDGET (image);
 }
 
+/**
+ * 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
@@ -925,6 +1028,51 @@ gtk_image_set_from_animation (GtkImage           *image,
   g_object_thaw_notify (G_OBJECT (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
@@ -1112,6 +1260,39 @@ gtk_image_get_animation (GtkImage *image)
   return image->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
+ *
+ * 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:
  * 
@@ -1166,10 +1347,30 @@ 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;
     }
@@ -1698,6 +2033,39 @@ gtk_image_size_request (GtkWidget      *widget,
   GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
 }
 
+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,
@@ -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;
+}
index 2b997ab6d8fe153060f474b9ea031e4fec2eb063..28c6776c642fbe963b1779bdd95a0233d11b5415 100644 (file)
@@ -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 (file)
index 0000000..b9ade1d
--- /dev/null
@@ -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;
+}