GtkImage insensitive rendering



Hi,

Patch for:
  http://bugzilla.gnome.org/show_bug.cgi?id=63305

There are two problems in here. 

One is that we drop the mask for pixmap/image GtkImages; this could be
resolved by making gdk_pixbuf_render_to_drawable() render alpha
channel as proposed earlier.

Two is that gtk_style_render_icon() wants an icon size; we sort of
need a magic "do not scale" argument to be passed in instead. 
Would it be too horrible if passing -1 to this resulted in not
scaling? Then we could also remove the logic that decides whether to
scale from default_render_icon and move it to gtkiconfactory.c

The patch is a bit slow, since it doesn't cache anything, but I'm not
sure we _can_ cache anything since we don't know when a pixmap/pixbuf
changes. So people that want caching should maybe use GtkIconSet, or
ideally register all their app's icons with the stock system.

Havoc

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.2857
diff -u -p -u -r1.2857 ChangeLog
--- ChangeLog	2002/01/24 16:54:53	1.2857
+++ ChangeLog	2002/01/24 21:56:55
@@ -1,3 +1,11 @@
+2002-01-24  Havoc Pennington  <hp redhat com>
+
+	* gtk/gtkimage.c (gtk_image_expose): create insensitive version of
+	the image regardless of storage type, #63305
+
+	* demos/gtk-demo/images.c: add toggle button to demonstrate that
+	GtkImage makes its contents insensitive
+
 Thu Jan 24 11:53:19 2002  Owen Taylor  <otaylor redhat com>
 
 	* gtk/gtktreeview.c (gtk_tree_view_destroy): Don't clear
Index: demos/gtk-demo/images.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/images.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 images.c
--- demos/gtk-demo/images.c	2001/11/23 21:46:29	1.7
+++ demos/gtk-demo/images.c	2002/01/24 21:56:55
@@ -41,12 +41,13 @@ progressive_prepared_callback (GdkPixbuf
   gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
 }
 
-static void progressive_updated_callback (GdkPixbufLoader *loader,
-					  gint		   x,
-					  gint		   y,
-					  gint		   width,
-					  gint		   height,
-					  gpointer	   data)
+static void
+progressive_updated_callback (GdkPixbufLoader *loader,
+                              gint		   x,
+                              gint		   y,
+                              gint		   width,
+                              gint		   height,
+                              gpointer	   data)
 {
   GtkWidget *image;
   
@@ -280,6 +281,31 @@ cleanup_callback (GtkObject *object,
   image_stream = NULL;
 }
 
+static void
+toggle_sensitivity_callback (GtkWidget *togglebutton,
+                             gpointer   user_data)
+{
+  GtkContainer *container = user_data;
+  GList *list;
+  GList *tmp;
+  
+  list = gtk_container_get_children (container);
+
+  tmp = list;
+  while (tmp != NULL)
+    {
+      /* don't disable our toggle */
+      if (GTK_WIDGET (tmp->data) != togglebutton)
+        gtk_widget_set_sensitive (GTK_WIDGET (tmp->data),
+                                  !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton)));
+      
+      tmp = tmp->next;
+    }
+
+  g_list_free (list);
+}
+  
+
 GtkWidget *
 do_images (void)
 {
@@ -288,6 +314,7 @@ do_images (void)
   GtkWidget *image;
   GtkWidget *label;
   GtkWidget *align;
+  GtkWidget *button;
   GdkPixbuf *pixbuf;
   GError *error = NULL;
   char *filename;
@@ -410,6 +437,14 @@ do_images (void)
       gtk_container_add (GTK_CONTAINER (frame), image);
 
       start_progressive_loading (image);
+
+      /* Sensitivity control */
+      button = gtk_toggle_button_new_with_mnemonic ("_Insensitive");
+      gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+      g_signal_connect (G_OBJECT (button), "toggled",
+                        G_CALLBACK (toggle_sensitivity_callback),
+                        vbox);
     }
 
   if (!GTK_WIDGET_VISIBLE (window))
Index: gtk/gtkimage.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimage.c,v
retrieving revision 1.32
diff -u -p -u -r1.32 gtkimage.c
--- gtk/gtkimage.c	2002/01/10 16:36:24	1.32
+++ gtk/gtkimage.c	2002/01/24 21:56:56
@@ -1205,8 +1205,9 @@ gtk_image_expose (GtkWidget      *widget
       GdkRectangle area, image_bound;
       gfloat xalign;
       gint x, y;
-      GdkBitmap *mask = NULL;
-      GdkPixbuf *stock_pixbuf = NULL;
+      GdkBitmap *mask;
+      GdkPixbuf *pixbuf;
+      gboolean needs_state_transform;
       
       image = GTK_IMAGE (widget);
       misc = GTK_MISC (widget);
@@ -1226,6 +1227,10 @@ gtk_image_expose (GtkWidget      *widget
       image_bound.x = x;
       image_bound.y = y;      
 
+      mask = NULL;
+      pixbuf = NULL;
+      needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
+      
       switch (image->storage_type)
         {
         case GTK_IMAGE_PIXMAP:
@@ -1233,33 +1238,60 @@ gtk_image_expose (GtkWidget      *widget
           gdk_drawable_get_size (image->data.pixmap.pixmap,
                                  &image_bound.width,
                                  &image_bound.height);
+
+          if (needs_state_transform)
+            {
+              pixbuf = gdk_pixbuf_get_from_drawable (NULL,
+                                                     image->data.pixmap.pixmap,
+                                                     gtk_widget_get_colormap (widget),
+                                                     0, 0, 0, 0,
+                                                     image_bound.width,
+                                                     image_bound.height);
+            }
           break;
 
         case GTK_IMAGE_IMAGE:
           mask = image->mask;
           image_bound.width = image->data.image.image->width;
           image_bound.height = image->data.image.image->height;
+
+          if (needs_state_transform)
+            {
+              pixbuf = gdk_pixbuf_get_from_image (NULL,
+                                                  image->data.image.image,
+                                                  gtk_widget_get_colormap (widget),
+                                                  0, 0, 0, 0,
+                                                  image_bound.width,
+                                                  image_bound.height);
+
+            }
           break;
 
         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);
+          image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);          
+
+          pixbuf = image->data.pixbuf.pixbuf;
+          g_object_ref (G_OBJECT (pixbuf));
           break;
 
         case GTK_IMAGE_STOCK:
-          stock_pixbuf = gtk_widget_render_icon (widget,
-                                                 image->data.stock.stock_id,
-                                                 image->icon_size,
-                                                 NULL);
-          if (stock_pixbuf)
+          pixbuf = gtk_widget_render_icon (widget,
+                                           image->data.stock.stock_id,
+                                           image->icon_size,
+                                           NULL);
+          if (pixbuf)
             {              
-              image_bound.width = gdk_pixbuf_get_width (stock_pixbuf);
-              image_bound.height = gdk_pixbuf_get_height (stock_pixbuf);
+              image_bound.width = gdk_pixbuf_get_width (pixbuf);
+              image_bound.height = gdk_pixbuf_get_height (pixbuf);
             }
+
+          /* already done */
+          needs_state_transform = FALSE;
           break;
 
         case GTK_IMAGE_ICON_SET:
-          stock_pixbuf =
+          pixbuf =
             gtk_icon_set_render_icon (image->data.icon_set.icon_set,
                                       widget->style,
                                       gtk_widget_get_direction (widget),
@@ -1268,11 +1300,14 @@ gtk_image_expose (GtkWidget      *widget
                                       widget,
                                       NULL);
 
-          if (stock_pixbuf)
+          if (pixbuf)
             {
-              image_bound.width = gdk_pixbuf_get_width (stock_pixbuf);
-              image_bound.height = gdk_pixbuf_get_height (stock_pixbuf);
+              image_bound.width = gdk_pixbuf_get_width (pixbuf);
+              image_bound.height = gdk_pixbuf_get_height (pixbuf);
             }
+
+          /* already done */
+          needs_state_transform = FALSE;
           break;
 
         case GTK_IMAGE_ANIMATION:
@@ -1290,10 +1325,18 @@ gtk_image_expose (GtkWidget      *widget
 
             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);
+            g_object_ref (G_OBJECT (pixbuf));
           }
           break;
-          
-        default:
+
+        case GTK_IMAGE_EMPTY:
+          g_assert_not_reached ();
           break;
         }
 
@@ -1308,46 +1351,42 @@ gtk_image_expose (GtkWidget      *widget
       if (gdk_rectangle_intersect (&area, &widget->allocation, &area) &&
           gdk_rectangle_intersect (&image_bound, &area, &image_bound))
         {
-          switch (image->storage_type)
+          if (pixbuf)
             {
-            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:
-              gdk_pixbuf_render_to_drawable_alpha (image->data.pixbuf.pixbuf,
-                                                   widget->window,
-                                                   image_bound.x - x,
-                                                   image_bound.y - y,
-                                                   image_bound.x,
-                                                   image_bound.y,
-                                                   image_bound.width,
-                                                   image_bound.height,
-                                                   GDK_PIXBUF_ALPHA_FULL,
-                                                   128,
-                                                   GDK_RGB_DITHER_NORMAL,
-                                                   0, 0);
-              break;
-
-            case GTK_IMAGE_STOCK: /* fall thru */
-            case GTK_IMAGE_ICON_SET:
-              if (stock_pixbuf)
+              if (needs_state_transform)
                 {
-                  gdk_pixbuf_render_to_drawable_alpha (stock_pixbuf,
+                  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 */
+                                                    GTK_ICON_SIZE_SMALL_TOOLBAR,
+                                                    widget,
+                                                    "gtk-image");
+
+                  gtk_icon_source_free (source);
+
+                  g_object_unref (G_OBJECT (pixbuf));
+                  pixbuf = rendered;
+                }
+
+              if (pixbuf)
+                {
+                  /*  FIXME this ignores "mask" */
+                  gdk_pixbuf_render_to_drawable_alpha (pixbuf,
                                                        widget->window,
                                                        image_bound.x - x,
                                                        image_bound.y - y,
@@ -1359,39 +1398,50 @@ gtk_image_expose (GtkWidget      *widget
                                                        128,
                                                        GDK_RGB_DITHER_NORMAL,
                                                        0, 0);
-                  
-                  g_object_unref (G_OBJECT (stock_pixbuf));
-                }
-              break;
 
-            case GTK_IMAGE_ANIMATION:
-              /* don't advance the anim iter here, or we could get frame changes between two
-               * exposes of different areas.
-               */
-              
-              gdk_pixbuf_render_to_drawable_alpha (gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter),
-                                                   widget->window,
-                                                   image_bound.x - x,
-                                                   image_bound.y - y,
-                                                   image_bound.x,
-                                                   image_bound.y,
-                                                   image_bound.width,
-                                                   image_bound.height,
-                                                   GDK_PIXBUF_ALPHA_FULL,
-                                                   128,
-                                                   GDK_RGB_DITHER_NORMAL,
-                                                   0, 0);
-              break;
+                  g_object_unref (G_OBJECT (pixbuf));
+                  pixbuf = NULL;
+                }
+            }
+          else
+            {
+              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;
               
-            default:
-              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_EMPTY:
+                  g_assert_not_reached ();
+                  break;
+                }
             }
         } /* 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);
         }
+      
     } /* if widget is drawable */
 
   return FALSE;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]