summaryrefslogtreecommitdiff
path: root/gtk/gtkimage.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2010-04-26 11:55:34 +0100
committerBastien Nocera <hadess@hadess.net>2010-04-28 12:02:05 +0100
commit6b939d57c762f58a9f8d529024b7171ff70b6986 (patch)
tree04bf5bcb6aeb62c01c62edb40e9c4036fc8e98e5 /gtk/gtkimage.c
parent3cc9575323b4ca8c6d82572f1bfe3eb23555fdb3 (diff)
downloadgtk+-6b939d57c762f58a9f8d529024b7171ff70b6986.tar.gz
Support 'symbolic' themed icons
Add gtk_icon_info_load_symbolic() to load symbolic icons, and theme their background/foreground colours to match the colours used in the theme. Adds the gtk_icon_info_load_symbolic() function, explicit support in GtkImage and GtkCellRendererPixbuf, and test cases for those 2 widgets. With help from Bastien Nocera <hadess@hadess.net> https://bugzilla.gnome.org/show_bug.cgi?id=614711
Diffstat (limited to 'gtk/gtkimage.c')
-rw-r--r--gtk/gtkimage.c137
1 files changed, 122 insertions, 15 deletions
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c
index 6654f0db62..87e0b08245 100644
--- a/gtk/gtkimage.c
+++ b/gtk/gtkimage.c
@@ -134,6 +134,11 @@ struct _GtkImagePrivate
/* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
gchar *filename;
+ /* a GtkStateType, with -1 meaning an invalid state,
+ * only used with GTK_IMAGE_GICON, GTK_IMAGE_ICON_NAME */
+ gint last_rendered_state;
+ gboolean was_symbolic;
+
gint pixel_size;
guint need_calc_size : 1;
};
@@ -1628,6 +1633,10 @@ animation_timeout (gpointer data)
static void
icon_theme_changed (GtkImage *image)
{
+ GtkImagePrivate *priv;
+
+ priv = GTK_IMAGE_GET_PRIVATE (image);
+
if (image->storage_type == GTK_IMAGE_ICON_NAME)
{
if (image->data.name.pixbuf)
@@ -1647,7 +1656,8 @@ icon_theme_changed (GtkImage *image)
}
static void
-ensure_pixbuf_for_icon_name (GtkImage *image)
+ensure_pixbuf_for_icon_name (GtkImage *image,
+ GtkStateType state)
{
GtkImagePrivate *priv;
GdkScreen *screen;
@@ -1655,8 +1665,8 @@ ensure_pixbuf_for_icon_name (GtkImage *image)
GtkSettings *settings;
gint width, height;
gint *sizes, *s, dist;
+ GtkIconInfo *info;
GtkIconLookupFlags flags;
- GError *error = NULL;
g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME);
@@ -1665,8 +1675,15 @@ ensure_pixbuf_for_icon_name (GtkImage *image)
icon_theme = gtk_icon_theme_get_for_screen (screen);
settings = gtk_settings_get_for_screen (screen);
flags = GTK_ICON_LOOKUP_USE_BUILTIN;
- if (image->data.name.pixbuf == NULL)
+ if (image->data.name.pixbuf == NULL ||
+ (priv->was_symbolic && priv->last_rendered_state != state))
{
+ priv->last_rendered_state = state;
+ if (image->data.name.pixbuf)
+ {
+ g_object_unref (image->data.name.pixbuf);
+ image->data.name.pixbuf = NULL;
+ }
if (priv->pixel_size != -1)
{
width = height = priv->pixel_size;
@@ -1714,24 +1731,57 @@ ensure_pixbuf_for_icon_name (GtkImage *image)
width = height = 24;
}
}
- image->data.name.pixbuf =
- gtk_icon_theme_load_icon (icon_theme,
- image->data.name.icon_name,
- MIN (width, height), flags, &error);
+
+ info = gtk_icon_theme_lookup_icon (icon_theme,
+ image->data.name.icon_name,
+ MIN (width, height), flags);
+ if (info)
+ {
+ GdkColor error_color, warning_color, success_color;
+ GdkColor *error_ptr, *warning_ptr, *success_ptr;
+ GtkStyle *style;
+ gboolean was_symbolic;
+
+ style = gtk_widget_get_style (GTK_WIDGET (image));
+ if (!gtk_style_lookup_color (style, "error_color", &error_color))
+ error_ptr = NULL;
+ else
+ error_ptr = &error_color;
+ if (!gtk_style_lookup_color (style, "warning_color", &warning_color))
+ warning_ptr = NULL;
+ else
+ warning_ptr = &warning_color;
+ if (!gtk_style_lookup_color (style, "success_color", &success_color))
+ success_ptr = NULL;
+ else
+ success_ptr = &success_color;
+
+ image->data.name.pixbuf = gtk_icon_info_load_symbolic (info,
+ &style->fg[state],
+ success_ptr,
+ warning_ptr,
+ error_ptr,
+ &was_symbolic,
+ NULL);
+ priv->was_symbolic = was_symbolic;
+ gtk_icon_info_free (info);
+ }
+
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);
+ priv->was_symbolic = FALSE;
}
}
}
static void
-ensure_pixbuf_for_gicon (GtkImage *image)
+ensure_pixbuf_for_gicon (GtkImage *image,
+ GtkStateType state)
{
GtkImagePrivate *priv;
GdkScreen *screen;
@@ -1748,8 +1798,15 @@ ensure_pixbuf_for_gicon (GtkImage *image)
icon_theme = gtk_icon_theme_get_for_screen (screen);
settings = gtk_settings_get_for_screen (screen);
flags = GTK_ICON_LOOKUP_USE_BUILTIN;
- if (image->data.gicon.pixbuf == NULL)
+ if (image->data.gicon.pixbuf == NULL ||
+ (priv->was_symbolic && priv->last_rendered_state != state))
{
+ priv->last_rendered_state = state;
+ if (image->data.gicon.pixbuf)
+ {
+ g_object_unref (image->data.gicon.pixbuf);
+ image->data.gicon.pixbuf = NULL;
+ }
if (priv->pixel_size != -1)
{
width = height = priv->pixel_size;
@@ -1773,7 +1830,33 @@ ensure_pixbuf_for_gicon (GtkImage *image)
MIN (width, height), flags);
if (info)
{
- image->data.gicon.pixbuf = gtk_icon_info_load_icon (info, NULL);
+ GdkColor error_color, warning_color, success_color;
+ GdkColor *error_ptr, *warning_ptr, *success_ptr;
+ GtkStyle *style;
+ gboolean was_symbolic;
+
+ style = gtk_widget_get_style (GTK_WIDGET (image));
+ if (!gtk_style_lookup_color (style, "error_color", &error_color))
+ error_ptr = NULL;
+ else
+ error_ptr = &error_color;
+ if (!gtk_style_lookup_color (style, "warning_color", &warning_color))
+ warning_ptr = NULL;
+ else
+ warning_ptr = &warning_color;
+ if (!gtk_style_lookup_color (style, "success_color", &success_color))
+ success_ptr = NULL;
+ else
+ success_ptr = &success_color;
+
+ image->data.gicon.pixbuf = gtk_icon_info_load_symbolic (info,
+ &style->fg[state],
+ success_ptr,
+ warning_ptr,
+ error_ptr,
+ &was_symbolic,
+ NULL);
+ priv->was_symbolic = was_symbolic;
gtk_icon_info_free (info);
}
@@ -1784,6 +1867,7 @@ ensure_pixbuf_for_gicon (GtkImage *image)
GTK_STOCK_MISSING_IMAGE,
image->icon_size,
NULL);
+ priv->was_symbolic = FALSE;
}
}
}
@@ -1845,6 +1929,7 @@ gtk_image_expose (GtkWidget *widget,
gint x, y, mask_x, mask_y;
GdkBitmap *mask;
GdkPixbuf *pixbuf;
+ GtkStateType state;
gboolean needs_state_transform;
image = GTK_IMAGE (widget);
@@ -2012,7 +2097,18 @@ gtk_image_expose (GtkWidget *widget,
break;
case GTK_IMAGE_ICON_NAME:
- ensure_pixbuf_for_icon_name (image);
+ state = gtk_widget_get_state (widget);
+ if (state == GTK_STATE_INSENSITIVE)
+ {
+ ensure_pixbuf_for_icon_name (image, GTK_STATE_NORMAL);
+ }
+ else
+ {
+ ensure_pixbuf_for_icon_name (image, state);
+ /* Already done by the loading function? */
+ if (priv->was_symbolic)
+ needs_state_transform = FALSE;
+ }
pixbuf = image->data.name.pixbuf;
if (pixbuf)
{
@@ -2023,7 +2119,18 @@ gtk_image_expose (GtkWidget *widget,
break;
case GTK_IMAGE_GICON:
- ensure_pixbuf_for_gicon (image);
+ state = gtk_widget_get_state (widget);
+ if (state == GTK_STATE_INSENSITIVE)
+ {
+ ensure_pixbuf_for_gicon (image, GTK_STATE_NORMAL);
+ }
+ else
+ {
+ ensure_pixbuf_for_gicon (image, state);
+ /* Already done by the loading function? */
+ if (priv->was_symbolic)
+ needs_state_transform = FALSE;
+ }
pixbuf = image->data.gicon.pixbuf;
if (pixbuf)
{
@@ -2325,12 +2432,12 @@ gtk_image_calc_size (GtkImage *image)
NULL);
break;
case GTK_IMAGE_ICON_NAME:
- ensure_pixbuf_for_icon_name (image);
+ ensure_pixbuf_for_icon_name (image, GTK_STATE_NORMAL);
pixbuf = image->data.name.pixbuf;
if (pixbuf) g_object_ref (pixbuf);
break;
case GTK_IMAGE_GICON:
- ensure_pixbuf_for_gicon (image);
+ ensure_pixbuf_for_gicon (image, GTK_STATE_NORMAL);
pixbuf = image->data.gicon.pixbuf;
if (pixbuf)
g_object_ref (pixbuf);