/* * gtknumerableicon.c: an emblemed icon with number emblems * * Copyright (C) 2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library. If not, see . * * Authors: Cosimo Cecchi */ /** * SECTION:gtknumerableicon * @Title: GtkNumerableIcon * @Short_description: A GIcon that allows numbered emblems * * GtkNumerableIcon is a subclass of #GEmblemedIcon that can * show a number or short string as an emblem. The number can * be overlayed on top of another emblem, if desired. * * It supports theming by taking font and color information * from a provided #GtkStyleContext; see * gtk_numerable_icon_set_style_context(). * * * Typical numerable icons * * * */ #include #include "gtknumerableicon.h" #include "gtknumerableiconprivate.h" #include "gtkicontheme.h" #include "gtkintl.h" #include "gtkwidget.h" #include "gtkwidgetpath.h" #include "gtkwindow.h" #include #include #include struct _GtkNumerableIconPrivate { gint count; gint icon_size; gchar *label; GIcon *background_icon; gchar *background_icon_name; GdkRGBA *background; GdkRGBA *foreground; PangoFontDescription *font; cairo_pattern_t *background_image; gint border_size; GtkStyleContext *style; gulong style_changed_id; gchar *rendered_string; }; enum { PROP_COUNT = 1, PROP_LABEL, PROP_STYLE, PROP_BACKGROUND_ICON, PROP_BACKGROUND_ICON_NAME, NUM_PROPERTIES }; #define DEFAULT_SURFACE_SIZE 256 #define DEFAULT_BORDER_SIZE DEFAULT_SURFACE_SIZE * 0.06 #define DEFAULT_RADIUS DEFAULT_SURFACE_SIZE / 2 #define DEFAULT_BACKGROUND "#000000" #define DEFAULT_FOREGROUND "#ffffff" static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; G_DEFINE_TYPE (GtkNumerableIcon, gtk_numerable_icon, G_TYPE_EMBLEMED_ICON); static gint get_surface_size (cairo_surface_t *surface) { return MAX (cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface)); } static gdouble get_border_size (GtkNumerableIcon *self) { return self->priv->border_size; } static cairo_surface_t * draw_default_surface (GtkNumerableIcon *self) { cairo_surface_t *surface; cairo_t *cr; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, DEFAULT_SURFACE_SIZE, DEFAULT_SURFACE_SIZE); cr = cairo_create (surface); cairo_arc (cr, DEFAULT_SURFACE_SIZE / 2., DEFAULT_SURFACE_SIZE / 2., DEFAULT_RADIUS, 0., 2 * G_PI); gdk_cairo_set_source_rgba (cr, self->priv->background); cairo_fill (cr); cairo_arc (cr, DEFAULT_SURFACE_SIZE / 2., DEFAULT_SURFACE_SIZE / 2., DEFAULT_RADIUS - DEFAULT_BORDER_SIZE, 0., 2 * G_PI); gdk_cairo_set_source_rgba (cr, self->priv->foreground); cairo_fill (cr); cairo_arc (cr, DEFAULT_SURFACE_SIZE / 2., DEFAULT_SURFACE_SIZE / 2., DEFAULT_RADIUS - 2 * DEFAULT_BORDER_SIZE, 0., 2 * G_PI); gdk_cairo_set_source_rgba (cr, self->priv->background); cairo_fill (cr); cairo_destroy (cr); return surface; } static cairo_surface_t * draw_from_gradient (cairo_pattern_t *pattern) { cairo_surface_t *surface; cairo_matrix_t matrix; cairo_t *cr; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, DEFAULT_SURFACE_SIZE, DEFAULT_SURFACE_SIZE); cr = cairo_create (surface); /* scale the gradient points to the user space coordinates */ cairo_matrix_init_scale (&matrix, 1. / (double) DEFAULT_SURFACE_SIZE, 1. / (double) DEFAULT_SURFACE_SIZE); cairo_pattern_set_matrix (pattern, &matrix); cairo_arc (cr, DEFAULT_SURFACE_SIZE / 2., DEFAULT_SURFACE_SIZE / 2., DEFAULT_RADIUS, 0., 2 * G_PI); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_destroy (cr); return surface; } /* copy the surface */ static cairo_surface_t * draw_from_image (cairo_surface_t *image) { cairo_surface_t *surface; cairo_t *cr; surface = cairo_surface_create_similar (image, CAIRO_CONTENT_COLOR_ALPHA, cairo_image_surface_get_width (image), cairo_image_surface_get_height (image)); cr = cairo_create (surface); cairo_set_source_surface (cr, image, 0, 0); cairo_paint (cr); cairo_destroy (cr); return surface; } static cairo_surface_t * draw_from_gicon (GtkNumerableIcon *self) { GtkIconTheme *theme; GdkScreen *screen; GtkIconInfo *info; GdkPixbuf *pixbuf; cairo_surface_t *surface; cairo_t *cr; if (self->priv->style != NULL) { screen = gtk_style_context_get_screen (self->priv->style); theme = gtk_icon_theme_get_for_screen (screen); } else { theme = gtk_icon_theme_get_default (); } info = gtk_icon_theme_lookup_by_gicon (theme, self->priv->background_icon, self->priv->icon_size, GTK_ICON_LOOKUP_GENERIC_FALLBACK); if (info == NULL) return NULL; pixbuf = gtk_icon_info_load_icon (info, NULL); g_object_unref (info); if (pixbuf == NULL) return NULL; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); cr = cairo_create (surface); gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); cairo_paint (cr); cairo_destroy (cr); g_object_unref (pixbuf); return surface; } static cairo_surface_t * get_image_surface (GtkNumerableIcon *self) { cairo_surface_t *retval = NULL, *image; if (self->priv->background_icon != NULL) { retval = draw_from_gicon (self); self->priv->border_size = 0; } else if (self->priv->background_image != NULL) { if (cairo_pattern_get_surface (self->priv->background_image, &image) == CAIRO_STATUS_SUCCESS) retval = draw_from_image (image); else retval = draw_from_gradient (self->priv->background_image); self->priv->border_size = 0; } if (retval == NULL) { retval = draw_default_surface (self); self->priv->border_size = DEFAULT_BORDER_SIZE; } return retval; } static PangoLayout * get_pango_layout (GtkNumerableIcon *self) { PangoContext *context; GdkScreen *screen; PangoLayout *layout; if (self->priv->style != NULL) { screen = gtk_style_context_get_screen (self->priv->style); context = gdk_pango_context_get_for_screen (screen); layout = pango_layout_new (context); if (self->priv->font != NULL) pango_layout_set_font_description (layout, self->priv->font); pango_layout_set_text (layout, self->priv->rendered_string, -1); g_object_unref (context); } else { GtkWidget *fake; /* steal gtk text settings from the window */ fake = gtk_window_new (GTK_WINDOW_TOPLEVEL); layout = gtk_widget_create_pango_layout (fake, self->priv->rendered_string); gtk_widget_destroy (fake); } return layout; } static void gtk_numerable_icon_ensure_emblem (GtkNumerableIcon *self) { cairo_t *cr; cairo_surface_t *surface; PangoLayout *layout; GEmblem *emblem; gint width, height; gdouble scale; PangoAttrList *attr_list; PangoAttribute *attr; GdkPixbuf *pixbuf; /* don't draw anything if the count is zero */ if (self->priv->rendered_string == NULL) { g_emblemed_icon_clear_emblems (G_EMBLEMED_ICON (self)); return; } surface = get_image_surface (self); cr = cairo_create (surface); layout = get_pango_layout (self); pango_layout_get_pixel_size (layout, &width, &height); /* scale the layout to be 0.75 of the size still available for drawing */ scale = ((get_surface_size (surface) - 2 * get_border_size (self)) * 0.75) / (MAX (height, width)); attr_list = pango_attr_list_new (); attr = pango_attr_scale_new (scale); pango_attr_list_insert (attr_list, attr); attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); pango_attr_list_insert (attr_list, attr); pango_layout_set_attributes (layout, attr_list); /* update these values */ pango_layout_get_pixel_size (layout, &width, &height); /* move to the center */ cairo_move_to (cr, get_surface_size (surface) / 2. - (gdouble) width / 2., get_surface_size (surface) / 2. - (gdouble) height / 2.); gdk_cairo_set_source_rgba (cr, self->priv->foreground); pango_cairo_show_layout (cr, layout); cairo_destroy (cr); pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, get_surface_size (surface), get_surface_size (surface)); emblem = g_emblem_new (G_ICON (pixbuf)); g_emblemed_icon_clear_emblems (G_EMBLEMED_ICON (self)); g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (self), emblem); g_object_unref (layout); g_object_unref (emblem); g_object_unref (pixbuf); cairo_surface_destroy (surface); pango_attr_list_unref (attr_list); } static void gtk_numerable_icon_update_properties_from_style (GtkNumerableIcon *self) { GtkStyleContext *style = self->priv->style; GtkWidgetPath *path, *saved; cairo_pattern_t *pattern = NULL; GdkRGBA background, foreground; PangoFontDescription *font = NULL; /* save an unmodified copy of the original widget path, in order * to restore it later */ path = gtk_widget_path_copy (gtk_style_context_get_path (style)); saved = gtk_widget_path_copy (path); if (!gtk_widget_path_is_type (path, GTK_TYPE_NUMERABLE_ICON)) { /* append our GType to the style context to fetch appropriate colors */ gtk_widget_path_append_type (path, GTK_TYPE_NUMERABLE_ICON); gtk_style_context_set_path (style, path); } gtk_style_context_get_background_color (style, gtk_style_context_get_state (style), &background); gtk_style_context_get_color (style, gtk_style_context_get_state (style), &foreground); if (self->priv->background != NULL) gdk_rgba_free (self->priv->background); self->priv->background = gdk_rgba_copy (&background); if (self->priv->foreground != NULL) gdk_rgba_free (self->priv->foreground); self->priv->foreground = gdk_rgba_copy (&foreground); gtk_style_context_get (style, gtk_style_context_get_state (style), GTK_STYLE_PROPERTY_BACKGROUND_IMAGE, &pattern, NULL); if (pattern != NULL) { if (self->priv->background_image != NULL) cairo_pattern_destroy (self->priv->background_image); self->priv->background_image = pattern; } gtk_style_context_get (style, gtk_style_context_get_state (style), GTK_STYLE_PROPERTY_FONT, &font, NULL); if (font != NULL) { if (self->priv->font != NULL) pango_font_description_free (self->priv->font); self->priv->font = font; } gtk_numerable_icon_ensure_emblem (self); /* restore original widget path */ gtk_style_context_set_path (style, saved); gtk_widget_path_free (path); gtk_widget_path_free (saved); } static void gtk_numerable_icon_init_style (GtkNumerableIcon *self) { GtkStyleContext *style = self->priv->style; if (style == NULL) return; gtk_numerable_icon_update_properties_from_style (self); self->priv->style_changed_id = g_signal_connect_swapped (style, "changed", G_CALLBACK (gtk_numerable_icon_update_properties_from_style), self); } static void gtk_numerable_icon_ensure_and_replace_label (GtkNumerableIcon *self, gint count, const gchar *label) { g_assert (!(label != NULL && count != 0)); g_free (self->priv->rendered_string); self->priv->rendered_string = NULL; if (count != 0) { if (self->priv->label != NULL) { g_free (self->priv->label); self->priv->label = NULL; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LABEL]); } if (count > 99) count = 99; if (count < -99) count = -99; self->priv->count = count; /* Translators: the format here is used to build the string that will be rendered * in the number emblem. */ self->priv->rendered_string = g_strdup_printf (C_("Number format", "%d"), count); return; } if (label != NULL) { if (self->priv->count != 0) { self->priv->count = 0; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COUNT]); } g_free (self->priv->label); if (g_strcmp0 (label, "") == 0) { self->priv->label = NULL; return; } self->priv->label = g_strdup (label); self->priv->rendered_string = g_strdup (label); } } static gboolean real_set_background_icon (GtkNumerableIcon *self, GIcon *icon) { if (!g_icon_equal (self->priv->background_icon, icon)) { g_clear_object (&self->priv->background_icon); if (icon != NULL) self->priv->background_icon = g_object_ref (icon); gtk_numerable_icon_ensure_emblem (self); return TRUE; } return FALSE; } static void gtk_numerable_icon_constructed (GObject *object) { GtkNumerableIcon *self = GTK_NUMERABLE_ICON (object); if (G_OBJECT_CLASS (gtk_numerable_icon_parent_class)->constructed != NULL) G_OBJECT_CLASS (gtk_numerable_icon_parent_class)->constructed (object); gtk_numerable_icon_ensure_emblem (self); } static void gtk_numerable_icon_finalize (GObject *object) { GtkNumerableIcon *self = GTK_NUMERABLE_ICON (object); g_free (self->priv->label); g_free (self->priv->rendered_string); gdk_rgba_free (self->priv->background); gdk_rgba_free (self->priv->foreground); pango_font_description_free (self->priv->font); cairo_pattern_destroy (self->priv->background_image); G_OBJECT_CLASS (gtk_numerable_icon_parent_class)->finalize (object); } static void gtk_numerable_icon_dispose (GObject *object) { GtkNumerableIcon *self = GTK_NUMERABLE_ICON (object); if (self->priv->style_changed_id != 0) { g_signal_handler_disconnect (self->priv->style, self->priv->style_changed_id); self->priv->style_changed_id = 0; } g_clear_object (&self->priv->style); g_clear_object (&self->priv->background_icon); G_OBJECT_CLASS (gtk_numerable_icon_parent_class)->dispose (object); } static void gtk_numerable_icon_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GtkNumerableIcon *self = GTK_NUMERABLE_ICON (object); switch (property_id) { case PROP_COUNT: gtk_numerable_icon_set_count (self, g_value_get_int (value)); break; case PROP_LABEL: gtk_numerable_icon_set_label (self, g_value_get_string (value)); break; case PROP_STYLE: gtk_numerable_icon_set_style_context (self, g_value_get_object (value)); break; case PROP_BACKGROUND_ICON: gtk_numerable_icon_set_background_gicon (self, g_value_get_object (value)); break; case PROP_BACKGROUND_ICON_NAME: gtk_numerable_icon_set_background_icon_name (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gtk_numerable_icon_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GtkNumerableIcon *self = GTK_NUMERABLE_ICON (object); switch (property_id) { case PROP_COUNT: g_value_set_int (value, self->priv->count); break; case PROP_LABEL: g_value_set_string (value, self->priv->label); break; case PROP_STYLE: g_value_set_object (value, self->priv->style); break; case PROP_BACKGROUND_ICON: if (self->priv->background_icon != NULL) g_value_set_object (value, self->priv->background_icon); break; case PROP_BACKGROUND_ICON_NAME: g_value_set_string (value, self->priv->background_icon_name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gtk_numerable_icon_class_init (GtkNumerableIconClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); oclass->get_property = gtk_numerable_icon_get_property; oclass->set_property = gtk_numerable_icon_set_property; oclass->constructed = gtk_numerable_icon_constructed; oclass->dispose = gtk_numerable_icon_dispose; oclass->finalize = gtk_numerable_icon_finalize; g_type_class_add_private (klass, sizeof (GtkNumerableIconPrivate)); properties[PROP_COUNT] = g_param_spec_int ("count", P_("Icon's count"), P_("The count of the emblem currently displayed"), -99, 99, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_LABEL] = g_param_spec_string ("label", P_("Icon's label"), P_("The label to be displayed over the icon"), NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_STYLE] = g_param_spec_object ("style-context", P_("Icon's style context"), P_("The style context to theme the icon appearance"), GTK_TYPE_STYLE_CONTEXT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_BACKGROUND_ICON] = g_param_spec_object ("background-icon", P_("Background icon"), P_("The icon for the number emblem background"), G_TYPE_ICON, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_BACKGROUND_ICON_NAME] = g_param_spec_string ("background-icon-name", P_("Background icon name"), P_("The icon name for the number emblem background"), NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); } static void gtk_numerable_icon_init (GtkNumerableIcon *self) { GdkRGBA bg; GdkRGBA fg; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_NUMERABLE_ICON, GtkNumerableIconPrivate); gdk_rgba_parse (&bg, DEFAULT_BACKGROUND); gdk_rgba_parse (&fg, DEFAULT_FOREGROUND); self->priv->background = gdk_rgba_copy (&bg); self->priv->foreground = gdk_rgba_copy (&fg); self->priv->icon_size = 48; } /* private */ void _gtk_numerable_icon_set_background_icon_size (GtkNumerableIcon *self, gint icon_size) { if (self->priv->background_icon == NULL) return; if (self->priv->icon_size != icon_size) { self->priv->icon_size = icon_size; gtk_numerable_icon_ensure_emblem (self); } } /** * gtk_numerable_icon_get_label: * @self: a #GtkNumerableIcon * * Returns the currently displayed label of the icon, or %NULL. * * Returns: the currently displayed label * * Since: 3.0 */ const gchar * gtk_numerable_icon_get_label (GtkNumerableIcon *self) { g_return_val_if_fail (GTK_IS_NUMERABLE_ICON (self), NULL); return self->priv->label; } /** * gtk_numerable_icon_set_label: * @self: a #GtkNumerableIcon * @label: (allow-none): a short label, or %NULL * * Sets the currently displayed value of @self to the string * in @label. Setting an empty label removes the emblem. * * Note that this is meant for displaying short labels, such as * roman numbers, or single letters. For roman numbers, consider * using the Unicode characters U+2160 - U+217F. Strings longer * than two characters will likely not be rendered very well. * * If this method is called, and a number was already set on the * icon, it will automatically be reset to zero before rendering * the label, i.e. the last method called between * gtk_numerable_icon_set_label() and gtk_numerable_icon_set_count() * has always priority. * * Since: 3.0 */ void gtk_numerable_icon_set_label (GtkNumerableIcon *self, const gchar *label) { g_return_if_fail (GTK_IS_NUMERABLE_ICON (self)); if (g_strcmp0 (label, self->priv->label) != 0) { gtk_numerable_icon_ensure_and_replace_label (self, 0, label); gtk_numerable_icon_ensure_emblem (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LABEL]); } } /** * gtk_numerable_icon_get_count: * @self: a #GtkNumerableIcon * * Returns the value currently displayed by @self. * * Returns: the currently displayed value * * Since: 3.0 */ gint gtk_numerable_icon_get_count (GtkNumerableIcon *self) { g_return_val_if_fail (GTK_IS_NUMERABLE_ICON (self), 0); return self->priv->count; } /** * gtk_numerable_icon_set_count: * @self: a #GtkNumerableIcon * @count: a number between -99 and 99 * * Sets the currently displayed value of @self to @count. * * The numeric value is always clamped to make it two digits, i.e. * between -99 and 99. Setting a count of zero removes the emblem. * If this method is called, and a label was already set on the icon, * it will automatically be reset to %NULL before rendering the number, * i.e. the last method called between gtk_numerable_icon_set_count() * and gtk_numerable_icon_set_label() has always priority. * * Since: 3.0 */ void gtk_numerable_icon_set_count (GtkNumerableIcon *self, gint count) { g_return_if_fail (GTK_IS_NUMERABLE_ICON (self)); if (count != self->priv->count) { gtk_numerable_icon_ensure_and_replace_label (self, count, NULL); gtk_numerable_icon_ensure_emblem (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COUNT]); } } /** * gtk_numerable_icon_get_style_context: * @self: a #GtkNumerableIcon * * Returns the #GtkStyleContext used by the icon for theming, * or %NULL if there's none. * * Returns: (transfer none): a #GtkStyleContext, or %NULL. * This object is internal to GTK+ and should not be unreffed. * Use g_object_ref() if you want to keep it around * * Since: 3.0 */ GtkStyleContext * gtk_numerable_icon_get_style_context (GtkNumerableIcon *self) { g_return_val_if_fail (GTK_IS_NUMERABLE_ICON (self), NULL); return self->priv->style; } /** * gtk_numerable_icon_set_style_context: * @self: a #GtkNumerableIcon * @style: a #GtkStyleContext * * Updates the icon to fetch theme information from the * given #GtkStyleContext. * * Since: 3.0 */ void gtk_numerable_icon_set_style_context (GtkNumerableIcon *self, GtkStyleContext *style) { g_return_if_fail (GTK_IS_NUMERABLE_ICON (self)); g_return_if_fail (GTK_IS_STYLE_CONTEXT (style)); if (style != self->priv->style) { if (self->priv->style_changed_id != 0) g_signal_handler_disconnect (self->priv->style, self->priv->style_changed_id); if (self->priv->style != NULL) g_object_unref (self->priv->style); self->priv->style = g_object_ref (style); gtk_numerable_icon_init_style (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STYLE]); } } /** * gtk_numerable_icon_set_background_gicon: * @self: a #GtkNumerableIcon * @icon: (allow-none): a #GIcon, or %NULL * * Updates the icon to use @icon as the base background image. * If @icon is %NULL, @self will go back using style information * or default theming for its background image. * * If this method is called and an icon name was already set as * background for the icon, @icon will be used, i.e. the last method * called between gtk_numerable_icon_set_background_gicon() and * gtk_numerable_icon_set_background_icon_name() has always priority. * * Since: 3.0 */ void gtk_numerable_icon_set_background_gicon (GtkNumerableIcon *self, GIcon *icon) { gboolean res; g_return_if_fail (GTK_IS_NUMERABLE_ICON (self)); if (self->priv->background_icon_name != NULL) { g_free (self->priv->background_icon_name); self->priv->background_icon_name = NULL; } res = real_set_background_icon (self, icon); if (res) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BACKGROUND_ICON]); } /** * gtk_numerable_icon_get_background_gicon: * @self: a #GtkNumerableIcon * * Returns the #GIcon that was set as the base background image, or * %NULL if there's none. The caller of this function does not own * a reference to the returned #GIcon. * * Returns: (transfer none): a #GIcon, or %NULL * * Since: 3.0 */ GIcon * gtk_numerable_icon_get_background_gicon (GtkNumerableIcon *self) { GIcon *retval = NULL; g_return_val_if_fail (GTK_IS_NUMERABLE_ICON (self), NULL); /* return the GIcon only if it wasn't created from an icon name */ if (self->priv->background_icon_name == NULL) retval = self->priv->background_icon; return retval; } /** * gtk_numerable_icon_set_background_icon_name: * @self: a #GtkNumerableIcon * @icon_name: (allow-none): an icon name, or %NULL * * Updates the icon to use the icon named @icon_name from the * current icon theme as the base background image. If @icon_name * is %NULL, @self will go back using style information or default * theming for its background image. * * If this method is called and a #GIcon was already set as * background for the icon, @icon_name will be used, i.e. the * last method called between gtk_numerable_icon_set_background_icon_name() * and gtk_numerable_icon_set_background_gicon() has always priority. * * Since: 3.0 */ void gtk_numerable_icon_set_background_icon_name (GtkNumerableIcon *self, const gchar *icon_name) { GIcon *icon = NULL; gboolean res; g_return_if_fail (GTK_IS_NUMERABLE_ICON (self)); if (g_strcmp0 (icon_name, self->priv->background_icon_name) != 0) { g_free (self->priv->background_icon_name); self->priv->background_icon_name = g_strdup (icon_name); } if (icon_name != NULL) icon = g_themed_icon_new_with_default_fallbacks (icon_name); res = real_set_background_icon (self, icon); if (res) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BACKGROUND_ICON_NAME]); if (icon != NULL) g_object_unref (icon); } /** * gtk_numerable_icon_get_background_icon_name: * @self: a #GtkNumerableIcon * * Returns the icon name used as the base background image, * or %NULL if there's none. * * Returns: an icon name, or %NULL * * Since: 3.0 */ const gchar * gtk_numerable_icon_get_background_icon_name (GtkNumerableIcon *self) { g_return_val_if_fail (GTK_IS_NUMERABLE_ICON (self), NULL); return self->priv->background_icon_name; } /** * gtk_numerable_icon_new: * @base_icon: a #GIcon to overlay on * * Creates a new unthemed #GtkNumerableIcon. * * Returns: (transfer full): a new #GIcon * * Since: 3.0 */ GIcon * gtk_numerable_icon_new (GIcon *base_icon) { g_return_val_if_fail (G_IS_ICON (base_icon), NULL); return g_object_new (GTK_TYPE_NUMERABLE_ICON, "gicon", base_icon, NULL); } /** * gtk_numerable_icon_new_with_style_context: * @base_icon: a #GIcon to overlay on * @context: a #GtkStyleContext * * Creates a new #GtkNumerableIcon which will themed according * to the passed #GtkStyleContext. This is a convenience constructor * that calls gtk_numerable_icon_set_style_context() internally. * * Returns: (transfer full): a new #GIcon * * Since: 3.0 */ GIcon * gtk_numerable_icon_new_with_style_context (GIcon *base_icon, GtkStyleContext *context) { g_return_val_if_fail (G_IS_ICON (base_icon), NULL); return g_object_new (GTK_TYPE_NUMERABLE_ICON, "gicon", base_icon, "style-context", context, NULL); }