GtkImage insensitive rendering
- From: Havoc Pennington <hp redhat com>
- To: gtk-devel-list gnome org
- Subject: GtkImage insensitive rendering
- Date: 24 Jan 2002 17:19:57 -0500
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]