1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Red Hat, Inc.
4 * Authors: Cosimo Cecchi <cosimoc@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 #include "gtkiconhelperprivate.h"
26 G_DEFINE_TYPE (GtkIconHelper, _gtk_icon_helper, G_TYPE_OBJECT)
28 struct _GtkIconHelperPrivate {
29 GtkImageType storage_type;
31 GdkPixbuf *orig_pixbuf;
32 GdkPixbufAnimation *animation;
38 GtkIconSize icon_size;
41 gboolean use_fallback;
43 GdkPixbuf *rendered_pixbuf;
44 GtkStateFlags last_rendered_state;
48 _gtk_icon_helper_clear (GtkIconHelper *self)
50 g_clear_object (&self->priv->gicon);
51 g_clear_object (&self->priv->orig_pixbuf);
52 g_clear_object (&self->priv->animation);
53 g_clear_object (&self->priv->rendered_pixbuf);
55 if (self->priv->icon_set != NULL)
57 gtk_icon_set_unref (self->priv->icon_set);
58 self->priv->icon_set = NULL;
61 g_free (self->priv->icon_name);
62 self->priv->icon_name = NULL;
64 g_free (self->priv->stock_id);
65 self->priv->stock_id = NULL;
67 self->priv->storage_type = GTK_IMAGE_EMPTY;
68 self->priv->icon_size = GTK_ICON_SIZE_INVALID;
69 self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
73 _gtk_icon_helper_invalidate (GtkIconHelper *self)
75 g_clear_object (&self->priv->rendered_pixbuf);
79 gtk_icon_helper_finalize (GObject *object)
81 GtkIconHelper *self = GTK_ICON_HELPER (object);
83 _gtk_icon_helper_clear (self);
85 G_OBJECT_CLASS (_gtk_icon_helper_parent_class)->finalize (object);
89 _gtk_icon_helper_class_init (GtkIconHelperClass *klass)
93 oclass = G_OBJECT_CLASS (klass);
94 oclass->finalize = gtk_icon_helper_finalize;
96 g_type_class_add_private (klass, sizeof (GtkIconHelperPrivate));
100 _gtk_icon_helper_init (GtkIconHelper *self)
102 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_ICON_HELPER, GtkIconHelperPrivate);
104 self->priv->storage_type = GTK_IMAGE_EMPTY;
105 self->priv->icon_size = GTK_ICON_SIZE_INVALID;
106 self->priv->pixel_size = -1;
107 self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
111 ensure_icon_size (GtkIconHelper *self,
112 GtkStyleContext *context,
117 GtkSettings *settings;
120 screen = gtk_style_context_get_screen (context);
121 settings = gtk_settings_get_for_screen (screen);
123 if (self->priv->pixel_size != -1)
125 width = height = self->priv->pixel_size;
127 else if (!gtk_icon_size_lookup_for_settings (settings,
128 self->priv->icon_size,
131 if (self->priv->icon_size == GTK_ICON_SIZE_INVALID)
137 g_warning ("Invalid icon size %d\n", self->priv->icon_size);
143 *height_out = height;
147 ensure_stated_icon_from_info (GtkIconHelper *self,
148 GtkStyleContext *context,
151 GdkPixbuf *destination = NULL;
158 gtk_icon_info_load_symbolic_for_context (info,
163 if (destination == NULL)
165 GtkIconSet *icon_set;
166 icon_set = gtk_style_context_lookup_icon_set (context, GTK_STOCK_MISSING_IMAGE);
169 gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
173 GtkIconSource *source;
176 source = gtk_icon_source_new ();
177 gtk_icon_source_set_pixbuf (source, destination);
178 /* The size here is arbitrary; since size isn't
179 * wildcarded in the source, it isn't supposed to be
180 * scaled by the engine function
182 gtk_icon_source_set_size (source,
183 GTK_ICON_SIZE_SMALL_TOOLBAR);
184 gtk_icon_source_set_size_wildcarded (source, FALSE);
186 rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
187 gtk_icon_source_free (source);
189 g_object_unref (destination);
190 destination = rendered;
197 check_invalidate_pixbuf (GtkIconHelper *self,
198 GtkStyleContext *context)
202 state = gtk_style_context_get_state (context);
204 if ((self->priv->rendered_pixbuf != NULL) &&
205 (self->priv->last_rendered_state == state))
208 self->priv->last_rendered_state = state;
209 g_clear_object (&self->priv->rendered_pixbuf);
214 static GtkIconLookupFlags
215 get_icon_lookup_flags (GtkIconHelper *self)
217 GtkIconLookupFlags flags = GTK_ICON_LOOKUP_USE_BUILTIN;
219 if (self->priv->use_fallback)
220 flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
221 if (self->priv->pixel_size != -1)
222 flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
228 ensure_pixbuf_for_icon_name_or_gicon (GtkIconHelper *self,
229 GtkStyleContext *context)
231 GtkIconTheme *icon_theme;
234 GtkIconLookupFlags flags;
236 if (!check_invalidate_pixbuf (self, context))
239 icon_theme = gtk_icon_theme_get_default ();
240 flags = get_icon_lookup_flags (self);
242 ensure_icon_size (self, context, &width, &height);
244 if (self->priv->storage_type == GTK_IMAGE_ICON_NAME &&
245 self->priv->icon_name != NULL)
247 info = gtk_icon_theme_lookup_icon (icon_theme,
248 self->priv->icon_name,
249 MIN (width, height), flags);
251 else if (self->priv->storage_type == GTK_IMAGE_GICON &&
252 self->priv->gicon != NULL)
254 info = gtk_icon_theme_lookup_by_gicon (icon_theme,
256 MIN (width, height), flags);
260 g_assert_not_reached ();
264 self->priv->rendered_pixbuf = ensure_stated_icon_from_info (self, context, info);
267 gtk_icon_info_free (info);
271 ensure_pixbuf_for_icon_set (GtkIconHelper *self,
272 GtkStyleContext *context,
273 GtkIconSet *icon_set)
275 if (!check_invalidate_pixbuf (self, context))
278 self->priv->rendered_pixbuf =
279 gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
283 _gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
284 GtkStyleContext *context)
286 GdkPixbuf *pixbuf = NULL;
287 GtkIconSet *icon_set;
289 switch (self->priv->storage_type)
291 case GTK_IMAGE_PIXBUF:
292 pixbuf = g_object_ref (self->priv->orig_pixbuf);
295 case GTK_IMAGE_STOCK:
296 icon_set = gtk_style_context_lookup_icon_set (context, self->priv->stock_id);
297 ensure_pixbuf_for_icon_set (self, context, icon_set);
300 case GTK_IMAGE_ICON_SET:
301 icon_set = self->priv->icon_set;
302 ensure_pixbuf_for_icon_set (self, context, icon_set);
305 case GTK_IMAGE_ICON_NAME:
306 case GTK_IMAGE_GICON:
307 ensure_pixbuf_for_icon_name_or_gicon (self, context);
310 case GTK_IMAGE_ANIMATION:
311 case GTK_IMAGE_EMPTY:
317 if (pixbuf == NULL &&
318 self->priv->rendered_pixbuf != NULL)
319 pixbuf = g_object_ref (self->priv->rendered_pixbuf);
325 _gtk_icon_helper_get_size (GtkIconHelper *self,
326 GtkStyleContext *context,
334 pix = _gtk_icon_helper_ensure_pixbuf (self, context);
338 width = gdk_pixbuf_get_width (pix);
339 height = gdk_pixbuf_get_height (pix);
341 g_object_unref (pix);
343 else if (self->priv->storage_type == GTK_IMAGE_ANIMATION)
345 width = gdk_pixbuf_animation_get_width (self->priv->animation);
346 height = gdk_pixbuf_animation_get_height (self->priv->animation);
348 else if (self->priv->icon_size != -1)
350 ensure_icon_size (self, context, &width, &height);
356 *height_out = height;
360 _gtk_icon_helper_set_gicon (GtkIconHelper *self,
362 GtkIconSize icon_size)
364 _gtk_icon_helper_clear (self);
368 self->priv->storage_type = GTK_IMAGE_GICON;
369 self->priv->gicon = g_object_ref (gicon);
370 _gtk_icon_helper_set_icon_size (self, icon_size);
375 _gtk_icon_helper_set_icon_name (GtkIconHelper *self,
376 const gchar *icon_name,
377 GtkIconSize icon_size)
379 _gtk_icon_helper_clear (self);
381 if (icon_name != NULL &&
382 g_strcmp0 (icon_name, "") != 0)
384 self->priv->storage_type = GTK_IMAGE_ICON_NAME;
385 self->priv->icon_name = g_strdup (icon_name);
386 _gtk_icon_helper_set_icon_size (self, icon_size);
391 _gtk_icon_helper_set_icon_set (GtkIconHelper *self,
392 GtkIconSet *icon_set,
393 GtkIconSize icon_size)
395 _gtk_icon_helper_clear (self);
397 if (icon_set != NULL)
399 self->priv->storage_type = GTK_IMAGE_ICON_SET;
400 self->priv->icon_set = gtk_icon_set_ref (icon_set);
401 _gtk_icon_helper_set_icon_size (self, icon_size);
406 _gtk_icon_helper_set_pixbuf (GtkIconHelper *self,
409 _gtk_icon_helper_clear (self);
413 self->priv->storage_type = GTK_IMAGE_PIXBUF;
414 self->priv->orig_pixbuf = g_object_ref (pixbuf);
419 _gtk_icon_helper_set_animation (GtkIconHelper *self,
420 GdkPixbufAnimation *animation)
422 _gtk_icon_helper_clear (self);
424 if (animation != NULL)
426 self->priv->storage_type = GTK_IMAGE_ANIMATION;
427 self->priv->animation = g_object_ref (animation);
432 _gtk_icon_helper_set_stock_id (GtkIconHelper *self,
433 const gchar *stock_id,
434 GtkIconSize icon_size)
436 _gtk_icon_helper_clear (self);
438 if (stock_id != NULL)
440 self->priv->storage_type = GTK_IMAGE_STOCK;
441 self->priv->stock_id = g_strdup (stock_id);
442 _gtk_icon_helper_set_icon_size (self, icon_size);
447 _gtk_icon_helper_set_icon_size (GtkIconHelper *self,
448 GtkIconSize icon_size)
450 if (self->priv->icon_size != icon_size)
452 self->priv->icon_size = icon_size;
453 _gtk_icon_helper_invalidate (self);
458 _gtk_icon_helper_set_pixel_size (GtkIconHelper *self,
461 if (self->priv->pixel_size != pixel_size)
463 self->priv->pixel_size = pixel_size;
464 _gtk_icon_helper_invalidate (self);
469 _gtk_icon_helper_set_use_fallback (GtkIconHelper *self,
470 gboolean use_fallback)
472 if (self->priv->use_fallback != use_fallback)
474 self->priv->use_fallback = use_fallback;
475 _gtk_icon_helper_invalidate (self);
480 _gtk_icon_helper_get_storage_type (GtkIconHelper *self)
482 return self->priv->storage_type;
486 _gtk_icon_helper_get_use_fallback (GtkIconHelper *self)
488 return self->priv->use_fallback;
492 _gtk_icon_helper_get_icon_size (GtkIconHelper *self)
494 return self->priv->icon_size;
498 _gtk_icon_helper_get_pixel_size (GtkIconHelper *self)
500 return self->priv->pixel_size;
504 _gtk_icon_helper_peek_pixbuf (GtkIconHelper *self)
506 return self->priv->orig_pixbuf;
510 _gtk_icon_helper_peek_gicon (GtkIconHelper *self)
512 return self->priv->gicon;
516 _gtk_icon_helper_peek_animation (GtkIconHelper *self)
518 return self->priv->animation;
522 _gtk_icon_helper_peek_icon_set (GtkIconHelper *self)
524 return self->priv->icon_set;
528 _gtk_icon_helper_get_stock_id (GtkIconHelper *self)
530 return self->priv->stock_id;
534 _gtk_icon_helper_get_icon_name (GtkIconHelper *self)
536 return self->priv->icon_name;
540 _gtk_icon_helper_new (void)
542 return g_object_new (GTK_TYPE_ICON_HELPER, NULL);
546 _gtk_icon_helper_draw (GtkIconHelper *self,
547 GtkStyleContext *context,
554 pixbuf = _gtk_icon_helper_ensure_pixbuf (self, context);
558 gtk_render_icon (context, cr, pixbuf, x, y);
559 g_object_unref (pixbuf);
564 _gtk_icon_helper_get_is_empty (GtkIconHelper *self)
566 return (self->priv->storage_type == GTK_IMAGE_EMPTY);