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->pixel_size = -1;
70 self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
74 _gtk_icon_helper_invalidate (GtkIconHelper *self)
76 g_clear_object (&self->priv->rendered_pixbuf);
80 gtk_icon_helper_finalize (GObject *object)
82 GtkIconHelper *self = GTK_ICON_HELPER (object);
84 _gtk_icon_helper_clear (self);
86 G_OBJECT_CLASS (_gtk_icon_helper_parent_class)->finalize (object);
90 _gtk_icon_helper_class_init (GtkIconHelperClass *klass)
94 oclass = G_OBJECT_CLASS (klass);
95 oclass->finalize = gtk_icon_helper_finalize;
97 g_type_class_add_private (klass, sizeof (GtkIconHelperPrivate));
101 _gtk_icon_helper_init (GtkIconHelper *self)
103 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_ICON_HELPER, GtkIconHelperPrivate);
105 self->priv->storage_type = GTK_IMAGE_EMPTY;
106 self->priv->icon_size = GTK_ICON_SIZE_INVALID;
107 self->priv->pixel_size = -1;
108 self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
112 ensure_icon_size (GtkIconHelper *self,
113 GtkStyleContext *context,
118 GtkSettings *settings;
121 screen = gtk_style_context_get_screen (context);
122 settings = gtk_settings_get_for_screen (screen);
124 if (self->priv->pixel_size != -1)
126 width = height = self->priv->pixel_size;
128 else if (!gtk_icon_size_lookup_for_settings (settings,
129 self->priv->icon_size,
132 g_warning ("Invalid icon size %d\n", self->priv->icon_size);
137 *height_out = height;
141 ensure_stated_icon_from_info (GtkIconHelper *self,
142 GtkStyleContext *context,
145 GdkPixbuf *destination = NULL;
152 gtk_icon_info_load_symbolic_for_context (info,
157 if (destination == NULL)
159 GtkIconSet *icon_set;
160 icon_set = gtk_style_context_lookup_icon_set (context, GTK_STOCK_MISSING_IMAGE);
163 gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
167 GtkIconSource *source;
170 source = gtk_icon_source_new ();
171 gtk_icon_source_set_pixbuf (source, destination);
172 /* The size here is arbitrary; since size isn't
173 * wildcarded in the source, it isn't supposed to be
174 * scaled by the engine function
176 gtk_icon_source_set_size (source,
177 GTK_ICON_SIZE_SMALL_TOOLBAR);
178 gtk_icon_source_set_size_wildcarded (source, FALSE);
180 rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
181 gtk_icon_source_free (source);
183 g_object_unref (destination);
184 destination = rendered;
191 check_invalidate_pixbuf (GtkIconHelper *self,
192 GtkStyleContext *context)
196 state = gtk_style_context_get_state (context);
198 if ((self->priv->rendered_pixbuf != NULL) &&
199 (self->priv->last_rendered_state == state))
202 self->priv->last_rendered_state = state;
203 g_clear_object (&self->priv->rendered_pixbuf);
208 static GtkIconLookupFlags
209 get_icon_lookup_flags (GtkIconHelper *self)
211 GtkIconLookupFlags flags = GTK_ICON_LOOKUP_USE_BUILTIN;
213 if (self->priv->use_fallback)
214 flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
215 if (self->priv->pixel_size != -1)
216 flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
222 ensure_pixbuf_for_icon_name_or_gicon (GtkIconHelper *self,
223 GtkStyleContext *context)
225 GtkIconTheme *icon_theme;
228 GtkIconLookupFlags flags;
230 if (!check_invalidate_pixbuf (self, context))
233 icon_theme = gtk_icon_theme_get_default ();
234 flags = get_icon_lookup_flags (self);
236 ensure_icon_size (self, context, &width, &height);
238 if (self->priv->storage_type == GTK_IMAGE_ICON_NAME &&
239 self->priv->icon_name != NULL)
241 info = gtk_icon_theme_lookup_icon (icon_theme,
242 self->priv->icon_name,
243 MIN (width, height), flags);
245 else if (self->priv->storage_type == GTK_IMAGE_GICON &&
246 self->priv->gicon != NULL)
248 info = gtk_icon_theme_lookup_by_gicon (icon_theme,
250 MIN (width, height), flags);
254 g_assert_not_reached ();
258 self->priv->rendered_pixbuf = ensure_stated_icon_from_info (self, context, info);
261 gtk_icon_info_free (info);
265 ensure_pixbuf_for_icon_set (GtkIconHelper *self,
266 GtkStyleContext *context,
267 GtkIconSet *icon_set)
269 if (!check_invalidate_pixbuf (self, context))
272 self->priv->rendered_pixbuf =
273 gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
277 _gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
278 GtkStyleContext *context)
280 GdkPixbuf *pixbuf = NULL;
281 GtkIconSet *icon_set;
283 switch (self->priv->storage_type)
285 case GTK_IMAGE_PIXBUF:
286 pixbuf = g_object_ref (self->priv->orig_pixbuf);
289 case GTK_IMAGE_STOCK:
290 icon_set = gtk_style_context_lookup_icon_set (context, self->priv->stock_id);
291 ensure_pixbuf_for_icon_set (self, context, icon_set);
294 case GTK_IMAGE_ICON_SET:
295 icon_set = self->priv->icon_set;
296 ensure_pixbuf_for_icon_set (self, context, icon_set);
299 case GTK_IMAGE_ICON_NAME:
300 case GTK_IMAGE_GICON:
301 ensure_pixbuf_for_icon_name_or_gicon (self, context);
304 case GTK_IMAGE_ANIMATION:
305 case GTK_IMAGE_EMPTY:
311 if (pixbuf == NULL &&
312 self->priv->rendered_pixbuf != NULL)
313 pixbuf = g_object_ref (self->priv->rendered_pixbuf);
319 _gtk_icon_helper_get_size (GtkIconHelper *self,
320 GtkStyleContext *context,
328 pix = _gtk_icon_helper_ensure_pixbuf (self, context);
332 width = gdk_pixbuf_get_width (pix);
333 height = gdk_pixbuf_get_height (pix);
335 g_object_unref (pix);
337 else if (self->priv->storage_type == GTK_IMAGE_ANIMATION)
339 width = gdk_pixbuf_animation_get_width (self->priv->animation);
340 height = gdk_pixbuf_animation_get_height (self->priv->animation);
342 else if (self->priv->icon_size != -1)
344 ensure_icon_size (self, context, &width, &height);
350 *height_out = height;
354 _gtk_icon_helper_set_gicon (GtkIconHelper *self,
356 GtkIconSize icon_size)
358 _gtk_icon_helper_clear (self);
362 self->priv->storage_type = GTK_IMAGE_GICON;
363 self->priv->gicon = g_object_ref (gicon);
364 _gtk_icon_helper_set_icon_size (self, icon_size);
369 _gtk_icon_helper_set_icon_name (GtkIconHelper *self,
370 const gchar *icon_name,
371 GtkIconSize icon_size)
373 _gtk_icon_helper_clear (self);
375 if (icon_name != NULL)
377 self->priv->storage_type = GTK_IMAGE_ICON_NAME;
378 self->priv->icon_name = g_strdup (icon_name);
379 _gtk_icon_helper_set_icon_size (self, icon_size);
384 _gtk_icon_helper_set_icon_set (GtkIconHelper *self,
385 GtkIconSet *icon_set,
386 GtkIconSize icon_size)
388 _gtk_icon_helper_clear (self);
390 if (icon_set != NULL)
392 self->priv->storage_type = GTK_IMAGE_ICON_SET;
393 self->priv->icon_set = gtk_icon_set_ref (icon_set);
394 _gtk_icon_helper_set_icon_size (self, icon_size);
399 _gtk_icon_helper_set_pixbuf (GtkIconHelper *self,
402 _gtk_icon_helper_clear (self);
406 self->priv->storage_type = GTK_IMAGE_PIXBUF;
407 self->priv->orig_pixbuf = g_object_ref (pixbuf);
412 _gtk_icon_helper_set_animation (GtkIconHelper *self,
413 GdkPixbufAnimation *animation)
415 _gtk_icon_helper_clear (self);
417 if (animation != NULL)
419 self->priv->storage_type = GTK_IMAGE_ANIMATION;
420 self->priv->animation = g_object_ref (animation);
425 _gtk_icon_helper_set_stock_id (GtkIconHelper *self,
426 const gchar *stock_id,
427 GtkIconSize icon_size)
429 _gtk_icon_helper_clear (self);
431 if (stock_id != NULL)
433 self->priv->storage_type = GTK_IMAGE_STOCK;
434 self->priv->stock_id = g_strdup (stock_id);
435 _gtk_icon_helper_set_icon_size (self, icon_size);
440 _gtk_icon_helper_set_icon_size (GtkIconHelper *self,
441 GtkIconSize icon_size)
443 if (self->priv->icon_size != icon_size)
445 self->priv->icon_size = icon_size;
446 _gtk_icon_helper_invalidate (self);
451 _gtk_icon_helper_set_pixel_size (GtkIconHelper *self,
454 if (self->priv->pixel_size != pixel_size)
456 self->priv->pixel_size = pixel_size;
457 _gtk_icon_helper_invalidate (self);
462 _gtk_icon_helper_set_use_fallback (GtkIconHelper *self,
463 gboolean use_fallback)
465 if (self->priv->use_fallback != use_fallback)
467 self->priv->use_fallback = use_fallback;
468 _gtk_icon_helper_invalidate (self);
473 _gtk_icon_helper_get_storage_type (GtkIconHelper *self)
475 return self->priv->storage_type;
479 _gtk_icon_helper_get_use_fallback (GtkIconHelper *self)
481 return self->priv->use_fallback;
485 _gtk_icon_helper_get_icon_size (GtkIconHelper *self)
487 return self->priv->icon_size;
491 _gtk_icon_helper_get_pixel_size (GtkIconHelper *self)
493 return self->priv->pixel_size;
497 _gtk_icon_helper_peek_pixbuf (GtkIconHelper *self)
499 g_return_val_if_fail (self->priv->storage_type == GTK_IMAGE_PIXBUF ||
500 self->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
502 return self->priv->orig_pixbuf;
506 _gtk_icon_helper_peek_gicon (GtkIconHelper *self)
508 g_return_val_if_fail (self->priv->storage_type == GTK_IMAGE_GICON ||
509 self->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
511 return self->priv->gicon;
515 _gtk_icon_helper_peek_animation (GtkIconHelper *self)
517 g_return_val_if_fail (self->priv->storage_type == GTK_IMAGE_ANIMATION ||
518 self->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
520 return self->priv->animation;
524 _gtk_icon_helper_peek_icon_set (GtkIconHelper *self)
526 g_return_val_if_fail (self->priv->storage_type == GTK_IMAGE_ICON_SET ||
527 self->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
529 return self->priv->icon_set;
533 _gtk_icon_helper_get_stock_id (GtkIconHelper *self)
535 g_return_val_if_fail (self->priv->storage_type == GTK_IMAGE_STOCK ||
536 self->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
538 return self->priv->stock_id;
542 _gtk_icon_helper_get_icon_name (GtkIconHelper *self)
544 g_return_val_if_fail (self->priv->storage_type == GTK_IMAGE_ICON_NAME ||
545 self->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
547 return self->priv->icon_name;
551 _gtk_icon_helper_new (void)
553 return g_object_new (GTK_TYPE_ICON_HELPER, NULL);
557 _gtk_icon_helper_draw (GtkIconHelper *self,
558 GtkStyleContext *context,
565 pixbuf = _gtk_icon_helper_ensure_pixbuf (self, context);
569 gtk_render_icon (context, cr, pixbuf, x, y);
570 g_object_unref (pixbuf);
575 _gtk_icon_helper_get_is_empty (GtkIconHelper *self)
577 return (self->priv->storage_type == GTK_IMAGE_EMPTY);