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, see <http://www.gnu.org/licenses/>.
22 #include "gtkiconhelperprivate.h"
24 G_DEFINE_TYPE (GtkIconHelper, _gtk_icon_helper, G_TYPE_OBJECT)
26 struct _GtkIconHelperPrivate {
27 GtkImageType storage_type;
29 GdkPixbuf *orig_pixbuf;
30 GdkPixbufAnimation *animation;
36 GtkIconSize icon_size;
39 gboolean use_fallback;
41 GdkPixbuf *rendered_pixbuf;
42 GtkStateFlags last_rendered_state;
46 _gtk_icon_helper_clear (GtkIconHelper *self)
48 g_clear_object (&self->priv->gicon);
49 g_clear_object (&self->priv->orig_pixbuf);
50 g_clear_object (&self->priv->animation);
51 g_clear_object (&self->priv->rendered_pixbuf);
53 if (self->priv->icon_set != NULL)
55 gtk_icon_set_unref (self->priv->icon_set);
56 self->priv->icon_set = NULL;
59 g_free (self->priv->icon_name);
60 self->priv->icon_name = NULL;
62 g_free (self->priv->stock_id);
63 self->priv->stock_id = NULL;
65 self->priv->storage_type = GTK_IMAGE_EMPTY;
66 self->priv->icon_size = GTK_ICON_SIZE_INVALID;
67 self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
71 _gtk_icon_helper_invalidate (GtkIconHelper *self)
73 g_clear_object (&self->priv->rendered_pixbuf);
77 gtk_icon_helper_finalize (GObject *object)
79 GtkIconHelper *self = GTK_ICON_HELPER (object);
81 _gtk_icon_helper_clear (self);
83 G_OBJECT_CLASS (_gtk_icon_helper_parent_class)->finalize (object);
87 _gtk_icon_helper_class_init (GtkIconHelperClass *klass)
91 oclass = G_OBJECT_CLASS (klass);
92 oclass->finalize = gtk_icon_helper_finalize;
94 g_type_class_add_private (klass, sizeof (GtkIconHelperPrivate));
98 _gtk_icon_helper_init (GtkIconHelper *self)
100 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_ICON_HELPER, GtkIconHelperPrivate);
102 self->priv->storage_type = GTK_IMAGE_EMPTY;
103 self->priv->icon_size = GTK_ICON_SIZE_INVALID;
104 self->priv->pixel_size = -1;
105 self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
109 ensure_icon_size (GtkIconHelper *self,
110 GtkStyleContext *context,
115 GtkSettings *settings;
118 screen = gtk_style_context_get_screen (context);
119 settings = gtk_settings_get_for_screen (screen);
121 if (self->priv->pixel_size != -1)
123 width = height = self->priv->pixel_size;
125 else if (!gtk_icon_size_lookup_for_settings (settings,
126 self->priv->icon_size,
129 if (self->priv->icon_size == GTK_ICON_SIZE_INVALID)
135 g_warning ("Invalid icon size %d\n", self->priv->icon_size);
141 *height_out = height;
145 ensure_stated_icon_from_info (GtkIconHelper *self,
146 GtkStyleContext *context,
149 GdkPixbuf *destination = NULL;
156 gtk_icon_info_load_symbolic_for_context (info,
161 if (destination == NULL)
163 GtkIconSet *icon_set;
164 icon_set = gtk_style_context_lookup_icon_set (context, GTK_STOCK_MISSING_IMAGE);
167 gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
171 GtkIconSource *source;
174 source = gtk_icon_source_new ();
175 gtk_icon_source_set_pixbuf (source, destination);
176 /* The size here is arbitrary; since size isn't
177 * wildcarded in the source, it isn't supposed to be
178 * scaled by the engine function
180 gtk_icon_source_set_size (source,
181 GTK_ICON_SIZE_SMALL_TOOLBAR);
182 gtk_icon_source_set_size_wildcarded (source, FALSE);
184 rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
185 gtk_icon_source_free (source);
187 g_object_unref (destination);
188 destination = rendered;
195 check_invalidate_pixbuf (GtkIconHelper *self,
196 GtkStyleContext *context)
200 state = gtk_style_context_get_state (context);
202 if ((self->priv->rendered_pixbuf != NULL) &&
203 (self->priv->last_rendered_state == state))
206 self->priv->last_rendered_state = state;
207 g_clear_object (&self->priv->rendered_pixbuf);
212 static GtkIconLookupFlags
213 get_icon_lookup_flags (GtkIconHelper *self)
215 GtkIconLookupFlags flags = GTK_ICON_LOOKUP_USE_BUILTIN;
217 if (self->priv->use_fallback)
218 flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
219 if (self->priv->pixel_size != -1)
220 flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
226 ensure_pixbuf_for_icon_name_or_gicon (GtkIconHelper *self,
227 GtkStyleContext *context)
229 GtkIconTheme *icon_theme;
232 GtkIconLookupFlags flags;
234 if (!check_invalidate_pixbuf (self, context))
237 icon_theme = gtk_icon_theme_get_default ();
238 flags = get_icon_lookup_flags (self);
240 ensure_icon_size (self, context, &width, &height);
242 if (self->priv->storage_type == GTK_IMAGE_ICON_NAME &&
243 self->priv->icon_name != NULL)
245 info = gtk_icon_theme_lookup_icon (icon_theme,
246 self->priv->icon_name,
247 MIN (width, height), flags);
249 else if (self->priv->storage_type == GTK_IMAGE_GICON &&
250 self->priv->gicon != NULL)
252 info = gtk_icon_theme_lookup_by_gicon (icon_theme,
254 MIN (width, height), flags);
258 g_assert_not_reached ();
262 self->priv->rendered_pixbuf = ensure_stated_icon_from_info (self, context, info);
265 gtk_icon_info_free (info);
269 ensure_pixbuf_for_icon_set (GtkIconHelper *self,
270 GtkStyleContext *context,
271 GtkIconSet *icon_set)
273 if (!check_invalidate_pixbuf (self, context))
276 self->priv->rendered_pixbuf =
277 gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
281 _gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
282 GtkStyleContext *context)
284 GdkPixbuf *pixbuf = NULL;
285 GtkIconSet *icon_set;
287 switch (self->priv->storage_type)
289 case GTK_IMAGE_PIXBUF:
290 pixbuf = g_object_ref (self->priv->orig_pixbuf);
293 case GTK_IMAGE_STOCK:
294 icon_set = gtk_style_context_lookup_icon_set (context, self->priv->stock_id);
295 ensure_pixbuf_for_icon_set (self, context, icon_set);
298 case GTK_IMAGE_ICON_SET:
299 icon_set = self->priv->icon_set;
300 ensure_pixbuf_for_icon_set (self, context, icon_set);
303 case GTK_IMAGE_ICON_NAME:
304 case GTK_IMAGE_GICON:
305 ensure_pixbuf_for_icon_name_or_gicon (self, context);
308 case GTK_IMAGE_ANIMATION:
309 case GTK_IMAGE_EMPTY:
315 if (pixbuf == NULL &&
316 self->priv->rendered_pixbuf != NULL)
317 pixbuf = g_object_ref (self->priv->rendered_pixbuf);
323 _gtk_icon_helper_get_size (GtkIconHelper *self,
324 GtkStyleContext *context,
332 pix = _gtk_icon_helper_ensure_pixbuf (self, context);
336 width = gdk_pixbuf_get_width (pix);
337 height = gdk_pixbuf_get_height (pix);
339 g_object_unref (pix);
341 else if (self->priv->storage_type == GTK_IMAGE_ANIMATION)
343 width = gdk_pixbuf_animation_get_width (self->priv->animation);
344 height = gdk_pixbuf_animation_get_height (self->priv->animation);
346 else if (self->priv->icon_size != -1)
348 ensure_icon_size (self, context, &width, &height);
354 *height_out = height;
358 _gtk_icon_helper_set_gicon (GtkIconHelper *self,
360 GtkIconSize icon_size)
362 _gtk_icon_helper_clear (self);
366 self->priv->storage_type = GTK_IMAGE_GICON;
367 self->priv->gicon = g_object_ref (gicon);
368 _gtk_icon_helper_set_icon_size (self, icon_size);
373 _gtk_icon_helper_set_icon_name (GtkIconHelper *self,
374 const gchar *icon_name,
375 GtkIconSize icon_size)
377 _gtk_icon_helper_clear (self);
379 if (icon_name != NULL &&
380 g_strcmp0 (icon_name, "") != 0)
382 self->priv->storage_type = GTK_IMAGE_ICON_NAME;
383 self->priv->icon_name = g_strdup (icon_name);
384 _gtk_icon_helper_set_icon_size (self, icon_size);
389 _gtk_icon_helper_set_icon_set (GtkIconHelper *self,
390 GtkIconSet *icon_set,
391 GtkIconSize icon_size)
393 _gtk_icon_helper_clear (self);
395 if (icon_set != NULL)
397 self->priv->storage_type = GTK_IMAGE_ICON_SET;
398 self->priv->icon_set = gtk_icon_set_ref (icon_set);
399 _gtk_icon_helper_set_icon_size (self, icon_size);
404 _gtk_icon_helper_set_pixbuf (GtkIconHelper *self,
407 _gtk_icon_helper_clear (self);
411 self->priv->storage_type = GTK_IMAGE_PIXBUF;
412 self->priv->orig_pixbuf = g_object_ref (pixbuf);
417 _gtk_icon_helper_set_animation (GtkIconHelper *self,
418 GdkPixbufAnimation *animation)
420 _gtk_icon_helper_clear (self);
422 if (animation != NULL)
424 self->priv->storage_type = GTK_IMAGE_ANIMATION;
425 self->priv->animation = g_object_ref (animation);
430 _gtk_icon_helper_set_stock_id (GtkIconHelper *self,
431 const gchar *stock_id,
432 GtkIconSize icon_size)
434 _gtk_icon_helper_clear (self);
436 if (stock_id != NULL)
438 self->priv->storage_type = GTK_IMAGE_STOCK;
439 self->priv->stock_id = g_strdup (stock_id);
440 _gtk_icon_helper_set_icon_size (self, icon_size);
445 _gtk_icon_helper_set_icon_size (GtkIconHelper *self,
446 GtkIconSize icon_size)
448 if (self->priv->icon_size != icon_size)
450 self->priv->icon_size = icon_size;
451 _gtk_icon_helper_invalidate (self);
456 _gtk_icon_helper_set_pixel_size (GtkIconHelper *self,
459 if (self->priv->pixel_size != pixel_size)
461 self->priv->pixel_size = pixel_size;
462 _gtk_icon_helper_invalidate (self);
467 _gtk_icon_helper_set_use_fallback (GtkIconHelper *self,
468 gboolean use_fallback)
470 if (self->priv->use_fallback != use_fallback)
472 self->priv->use_fallback = use_fallback;
473 _gtk_icon_helper_invalidate (self);
478 _gtk_icon_helper_get_storage_type (GtkIconHelper *self)
480 return self->priv->storage_type;
484 _gtk_icon_helper_get_use_fallback (GtkIconHelper *self)
486 return self->priv->use_fallback;
490 _gtk_icon_helper_get_icon_size (GtkIconHelper *self)
492 return self->priv->icon_size;
496 _gtk_icon_helper_get_pixel_size (GtkIconHelper *self)
498 return self->priv->pixel_size;
502 _gtk_icon_helper_peek_pixbuf (GtkIconHelper *self)
504 return self->priv->orig_pixbuf;
508 _gtk_icon_helper_peek_gicon (GtkIconHelper *self)
510 return self->priv->gicon;
514 _gtk_icon_helper_peek_animation (GtkIconHelper *self)
516 return self->priv->animation;
520 _gtk_icon_helper_peek_icon_set (GtkIconHelper *self)
522 return self->priv->icon_set;
526 _gtk_icon_helper_get_stock_id (GtkIconHelper *self)
528 return self->priv->stock_id;
532 _gtk_icon_helper_get_icon_name (GtkIconHelper *self)
534 return self->priv->icon_name;
538 _gtk_icon_helper_new (void)
540 return g_object_new (GTK_TYPE_ICON_HELPER, NULL);
544 _gtk_icon_helper_draw (GtkIconHelper *self,
545 GtkStyleContext *context,
552 pixbuf = _gtk_icon_helper_ensure_pixbuf (self, context);
556 gtk_render_icon (context, cr, pixbuf, x, y);
557 g_object_unref (pixbuf);
562 _gtk_icon_helper_get_is_empty (GtkIconHelper *self)
564 return (self->priv->storage_type == GTK_IMAGE_EMPTY);