/* giFTui * Copyright (C) 2002 Naba Kumar * Copyright (C) 2003 the giFTui team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "main.h" #include #include "gtkcellrendererprogress.h" static void gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress); static void gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *class); static void gtk_cell_renderer_progress_finalize (GObject *object); static void gtk_cell_renderer_progress_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void gtk_cell_renderer_progress_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height); static void gtk_cell_renderer_progress_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, guint flags); enum { PROP_0, PROP_VALUE, PROP_VALUE_START, PROP_MARKUP, PROP_ATTRIBUTES, PROP_BACKGROUND, PROP_FOREGROUND, PROP_PROGRESSGROUND, PROP_PROGRESSGROUND_ACTIVE, PROP_PROGRESSGROUND_COMPLETED, PROP_PROGRESSGROUND_PAUSED, PROP_PROGRESSGROUND_CANCELED, PROP_BACKGROUND_GDK, PROP_FOREGROUND_GDK, PROP_PROGRESSGROUND_ACTIVE_GDK, PROP_PROGRESSGROUND_COMPLETED_GDK, PROP_PROGRESSGROUND_PAUSED_GDK, PROP_PROGRESSGROUND_CANCELED_GDK, /* Font */ PROP_FONT, PROP_FONT_DESC, PROP_FAMILY, PROP_STYLE, PROP_VARIANT, PROP_WEIGHT, PROP_STRETCH, PROP_SIZE, PROP_SIZE_POINTS, PROP_SCALE, PROP_STRIKETHROUGH, PROP_UNDERLINE, PROP_RISE, /* Whether-a-style-arg-is-set args */ PROP_BACKGROUND_SET, PROP_FOREGROUND_SET, PROP_PROGRESSGROUND_SET, PROP_FAMILY_SET, PROP_STYLE_SET, PROP_VARIANT_SET, PROP_WEIGHT_SET, PROP_STRETCH_SET, PROP_SIZE_SET, PROP_SCALE_SET, PROP_STRIKETHROUGH_SET, PROP_UNDERLINE_SET, PROP_RISE_SET }; static gpointer parent_class; /**/ GType gtk_cell_renderer_progress_get_type (void) { static GtkType cell_progress_type = 0; if (!cell_progress_type) { static const GTypeInfo cell_progress_info = { sizeof (GtkCellRendererProgressClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gtk_cell_renderer_progress_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GtkCellRendererProgress), 0, /* n_preallocs */ (GInstanceInitFunc) gtk_cell_renderer_progress_init, }; cell_progress_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererProgress", &cell_progress_info, 0); } return cell_progress_type; } static void gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress) { cellprogress->value = 0; cellprogress->value_start = 0; cellprogress->progressground = &cellprogress->progressground_active; cellprogress->foreground_set = TRUE; cellprogress->progressground_set = TRUE; cellprogress->fixed_height_rows = -1; cellprogress->font = pango_font_description_new (); return; } static void gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class); parent_class = g_type_class_peek_parent (class); object_class->finalize = gtk_cell_renderer_progress_finalize; object_class->get_property = gtk_cell_renderer_progress_get_property; object_class->set_property = gtk_cell_renderer_progress_set_property; cell_class->get_size = gtk_cell_renderer_progress_get_size; cell_class->render = gtk_cell_renderer_progress_render; g_object_class_install_property (object_class, PROP_VALUE, g_param_spec_float ("value", "Value", "Value of the progress bar", 0, 100, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_VALUE_START, g_param_spec_float ("value_start", "Value start", "Value start of the progress bar", 0, 100, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_MARKUP, g_param_spec_string ("markup", _("Markup"), _("Marked up text to render"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_ATTRIBUTES, g_param_spec_boxed ("attributes", _("Attributes"), _("A list of style attributes to apply to the text of the renderer"), PANGO_TYPE_ATTR_LIST, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_BACKGROUND, g_param_spec_string ("background", _("Background color name"), _("Background color as a string"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_BACKGROUND_GDK, g_param_spec_boxed ("background_gdk", _("Background color"), _("Background color as a GdkColor"), GDK_TYPE_COLOR, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FOREGROUND, g_param_spec_string ("foreground", _("Foreground color name"), _("Foreground color as a string"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_FOREGROUND_GDK, g_param_spec_boxed ("foreground_gdk", _("Foreground color"), _("Foreground color as a GdkColor"), GDK_TYPE_COLOR, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND, g_param_spec_uint ("progressground", _("Progressground color"), _("Progressound color as an integer"), 0, G_MAXUINT, 0, G_PARAM_READWRITE)); /**/ g_object_class_install_property (object_class, PROP_PROGRESSGROUND_ACTIVE, g_param_spec_string ("progressground_active", _("Progressground active color name"), _("Progressground active color as a string"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_ACTIVE_GDK, g_param_spec_boxed ("progressground_active_gdk", _("Progressground active color"), _("Progressground active color as a GdkColor"), GDK_TYPE_COLOR, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_COMPLETED, g_param_spec_string ("progressground_completed", _("Progressground completed color name"), _("Progressground completed color as a string"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_COMPLETED_GDK, g_param_spec_boxed ("progressground_completed_gdk", _("Progressground completed color"), _("Progressground completed color as a GdkColor"), GDK_TYPE_COLOR, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_PAUSED, g_param_spec_string ("progressground_paused", _("Progressground paused color name"), _("Progressground paused color as a string"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_PAUSED_GDK, g_param_spec_boxed ("progressground_paused_gdk", _("Progressground paused color"), _("Progressground paused color as a GdkColor"), GDK_TYPE_COLOR, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_CANCELED, g_param_spec_string ("progressground_canceled", _("Progressground canceled color name"), _("Progressground canceled color as a string"), NULL, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_PROGRESSGROUND_CANCELED_GDK, g_param_spec_boxed ("progressground_canceled_gdk", _("Progressground canceled color"), _("Progressground canceled color as a GdkColor"), GDK_TYPE_COLOR, G_PARAM_READWRITE)); /**/ g_object_class_install_property (object_class, PROP_FONT, g_param_spec_string ("font", _("Font"), _("Font description as a string"), NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FONT_DESC, g_param_spec_boxed ("font_desc", _("Font"), _("Font description as a PangoFontDescription struct"), PANGO_TYPE_FONT_DESCRIPTION, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FAMILY, g_param_spec_string ("family", _("Font family"), _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"), NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_STYLE, g_param_spec_enum ("style", _("Font style"), _("Font style"), PANGO_TYPE_STYLE, PANGO_STYLE_NORMAL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_VARIANT, g_param_spec_enum ("variant", _("Font variant"), _("Font variant"), PANGO_TYPE_VARIANT, PANGO_VARIANT_NORMAL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_WEIGHT, g_param_spec_int ("weight", _("Font weight"), _("Font weight"), 0, G_MAXINT, PANGO_WEIGHT_NORMAL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_STRETCH, g_param_spec_enum ("stretch", _("Font stretch"), _("Font stretch"), PANGO_TYPE_STRETCH, PANGO_STRETCH_NORMAL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SIZE, g_param_spec_int ("size", _("Font size"), _("Font size"), 0, G_MAXINT, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SIZE_POINTS, g_param_spec_double ("size_points", _("Font points"), _("Font size in points"), 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SCALE, g_param_spec_double ("scale", _("Font scale"), _("Font scaling factor"), 0.0, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_RISE, g_param_spec_int ("rise", _("Rise"), _("Offset of text above the baseline (below the baseline if rise is negative)"), -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_STRIKETHROUGH, g_param_spec_boolean ("strikethrough", _("Strikethrough"), _("Whether to strike through the text"), FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_UNDERLINE, g_param_spec_enum ("underline", _("Underline"), _("Style of underline for this text"), PANGO_TYPE_UNDERLINE, PANGO_UNDERLINE_NONE, G_PARAM_READWRITE)); /* Style props are set or not */ #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READWRITE)) ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET, _("Background set"), _("Whether this tag affects the background color")); ADD_SET_PROP ("foreground_set", PROP_FOREGROUND_SET, _("Foreground set"), _("Whether this tag affects the foreground color")); ADD_SET_PROP ("progressground_set", PROP_PROGRESSGROUND_SET, _("Progressground set"), _("Whether this tag affects the progressground color")); ADD_SET_PROP ("family_set", PROP_FAMILY_SET, _("Font family set"), _("Whether this tag affects the font family")); ADD_SET_PROP ("style_set", PROP_STYLE_SET, _("Font style set"), _("Whether this tag affects the font style")); ADD_SET_PROP ("variant_set", PROP_VARIANT_SET, _("Font variant set"), _("Whether this tag affects the font variant")); ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET, _("Font weight set"), _("Whether this tag affects the font weight")); ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET, _("Font stretch set"), _("Whether this tag affects the font stretch")); ADD_SET_PROP ("size_set", PROP_SIZE_SET, _("Font size set"), _("Whether this tag affects the font size")); ADD_SET_PROP ("scale_set", PROP_SCALE_SET, _("Font scale set"), _("Whether this tag scales the font size by a factor")); ADD_SET_PROP ("rise_set", PROP_RISE_SET, _("Rise set"), _("Whether this tag affects the rise")); ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET, _("Strikethrough set"), _("Whether this tag affects strikethrough")); ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET, _("Underline set"), _("Whether this tag affects underlining")); return; } static PangoFontMask get_property_font_set_mask (guint prop_id) { switch (prop_id) { case PROP_FAMILY_SET: return PANGO_FONT_MASK_FAMILY; case PROP_STYLE_SET: return PANGO_FONT_MASK_STYLE; case PROP_VARIANT_SET: return PANGO_FONT_MASK_VARIANT; case PROP_WEIGHT_SET: return PANGO_FONT_MASK_WEIGHT; case PROP_STRETCH_SET: return PANGO_FONT_MASK_STRETCH; case PROP_SIZE_SET: return PANGO_FONT_MASK_SIZE; } return 0; } static void gtk_cell_renderer_progress_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object); switch (param_id) { case PROP_VALUE: g_value_set_float (value, cellprogress->value); break; case PROP_VALUE_START: g_value_set_float (value, cellprogress->value_start); break; case PROP_ATTRIBUTES: g_value_set_boxed (value, cellprogress->extra_attrs); break; case PROP_BACKGROUND_GDK: { GdkColor color; color.red = cellprogress->background.red; color.green = cellprogress->background.green; color.blue = cellprogress->background.blue; g_value_set_boxed (value, &color); break; } case PROP_FOREGROUND_GDK: { GdkColor color; color.red = cellprogress->foreground.red; color.green = cellprogress->foreground.green; color.blue = cellprogress->foreground.blue; g_value_set_boxed (value, &color); break; } case PROP_PROGRESSGROUND: if (cellprogress->progressground == &cellprogress->progressground_active) g_value_set_int (value, GTK_CELL_RENDERER_PROGRESS_ACTIVE); else if (cellprogress->progressground == &cellprogress->progressground_completed) g_value_set_int (value, GTK_CELL_RENDERER_PROGRESS_COMPLETED); else if (cellprogress->progressground == &cellprogress->progressground_paused) g_value_set_int (value, GTK_CELL_RENDERER_PROGRESS_PAUSED); else if (cellprogress->progressground == &cellprogress->progressground_canceled) g_value_set_int (value, GTK_CELL_RENDERER_PROGRESS_CANCELED); break; case PROP_PROGRESSGROUND_ACTIVE_GDK: g_value_set_boxed (value, &cellprogress->progressground_active); break; case PROP_PROGRESSGROUND_COMPLETED_GDK: g_value_set_boxed (value, &cellprogress->progressground_completed); break; case PROP_PROGRESSGROUND_PAUSED_GDK: g_value_set_boxed (value, &cellprogress->progressground_paused); break; case PROP_PROGRESSGROUND_CANCELED_GDK: g_value_set_boxed (value, &cellprogress->progressground_canceled); break; case PROP_FONT: { /* FIXME GValue imposes a totally gratuitous string copy * here, we could just hand off string ownership */ gchar *str = pango_font_description_to_string (cellprogress->font); g_value_set_string (value, str); g_free (str); break; } case PROP_FONT_DESC: g_value_set_boxed (value, cellprogress->font); break; case PROP_FAMILY: g_value_set_string (value, pango_font_description_get_family (cellprogress->font)); break; case PROP_STYLE: g_value_set_enum (value, pango_font_description_get_style (cellprogress->font)); break; case PROP_VARIANT: g_value_set_enum (value, pango_font_description_get_variant (cellprogress->font)); break; case PROP_WEIGHT: g_value_set_int (value, pango_font_description_get_weight (cellprogress->font)); break; case PROP_STRETCH: g_value_set_enum (value, pango_font_description_get_stretch (cellprogress->font)); break; case PROP_SIZE: g_value_set_int (value, pango_font_description_get_size (cellprogress->font)); break; case PROP_SIZE_POINTS: g_value_set_double (value, ((gdouble) pango_font_description_get_size (cellprogress->font)) / (gdouble) PANGO_SCALE); break; case PROP_SCALE: g_value_set_double (value, cellprogress->font_scale); break; case PROP_STRIKETHROUGH: g_value_set_boolean (value, cellprogress->strikethrough); break; case PROP_UNDERLINE: g_value_set_enum (value, cellprogress->underline_style); break; case PROP_RISE: g_value_set_int (value, cellprogress->rise); break; case PROP_BACKGROUND_SET: g_value_set_boolean (value, cellprogress->background_set); break; case PROP_FOREGROUND_SET: g_value_set_boolean (value, cellprogress->foreground_set); break; case PROP_PROGRESSGROUND_SET: g_value_set_boolean (value, cellprogress->progressground_set); break; case PROP_FAMILY_SET: case PROP_STYLE_SET: case PROP_VARIANT_SET: case PROP_WEIGHT_SET: case PROP_STRETCH_SET: case PROP_SIZE_SET: { PangoFontMask mask = get_property_font_set_mask (param_id); g_value_set_boolean (value, (pango_font_description_get_set_fields (cellprogress->font) & mask) != 0); break; } case PROP_SCALE_SET: g_value_set_boolean (value, cellprogress->scale_set); break; case PROP_STRIKETHROUGH_SET: g_value_set_boolean (value, cellprogress->strikethrough_set); break; case PROP_UNDERLINE_SET: g_value_set_boolean (value, cellprogress->underline_set); break; case PROP_RISE_SET: g_value_set_boolean (value, cellprogress->rise_set); break; case PROP_BACKGROUND: case PROP_FOREGROUND: case PROP_PROGRESSGROUND_ACTIVE: case PROP_PROGRESSGROUND_COMPLETED: case PROP_PROGRESSGROUND_PAUSED: case PROP_PROGRESSGROUND_CANCELED: case PROP_MARKUP: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } return; } static void set_bg_color (GtkCellRendererProgress *cellprogress, const PangoColor *color) { if (color) { if (!cellprogress->background_set) { cellprogress->background_set = TRUE; g_object_notify (G_OBJECT (cellprogress), "background_set"); } cellprogress->background = *color; } else { if (cellprogress->background_set) { cellprogress->background_set = FALSE; g_object_notify (G_OBJECT (cellprogress), "background_set"); } } return; } static void set_fg_color (GtkCellRendererProgress *cellprogress, const PangoColor *color) { if (color) { if (!cellprogress->foreground_set) { cellprogress->foreground_set = TRUE; g_object_notify (G_OBJECT (cellprogress), "foreground_set"); } cellprogress->foreground = *color; } else { if (cellprogress->foreground_set) { cellprogress->foreground_set = FALSE; g_object_notify (G_OBJECT (cellprogress), "foreground_set"); } } return; } static void set_pg_color (GtkCellRendererProgress *cellprogress, GdkColor *color, const GdkColor *new_color) { if (new_color) { if (!cellprogress->progressground_set) { cellprogress->progressground_set = TRUE; g_object_notify (G_OBJECT (cellprogress), "progressground_set"); } *color = *new_color; } else { if (cellprogress->progressground_set) { cellprogress->progressground_set = FALSE; g_object_notify (G_OBJECT (cellprogress), "progressground_set"); } } return; } static void set_pg_color_str (GtkCellRendererProgress *cellprogress, GdkColor *color, const gchar *str) { GdkColor c; if (!str) set_pg_color (cellprogress, color, NULL); else if (gdk_color_parse (str, &c)) set_pg_color (cellprogress, color, &c); else g_warning ("Don't know color `%s'", str); return; } static PangoFontMask set_font_desc_fields (PangoFontDescription *desc, PangoFontMask to_set) { PangoFontMask changed_mask = 0; if (to_set & PANGO_FONT_MASK_FAMILY) { const char *family = pango_font_description_get_family (desc); if (!family) { family = "sans"; changed_mask |= PANGO_FONT_MASK_FAMILY; } pango_font_description_set_family (desc, family); } if (to_set & PANGO_FONT_MASK_STYLE) pango_font_description_set_style (desc, pango_font_description_get_style (desc)); if (to_set & PANGO_FONT_MASK_VARIANT) pango_font_description_set_variant (desc, pango_font_description_get_variant (desc)); if (to_set & PANGO_FONT_MASK_WEIGHT) pango_font_description_set_weight (desc, pango_font_description_get_weight (desc)); if (to_set & PANGO_FONT_MASK_STRETCH) pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc)); if (to_set & PANGO_FONT_MASK_SIZE) { gint size = pango_font_description_get_size (desc); if (size <= 0) { size = 10 * PANGO_SCALE; changed_mask |= PANGO_FONT_MASK_SIZE; } pango_font_description_set_size (desc, size); } return changed_mask; } static void notify_set_changed (GObject *object, PangoFontMask changed_mask) { if (changed_mask & PANGO_FONT_MASK_FAMILY) g_object_notify (object, "family_set"); if (changed_mask & PANGO_FONT_MASK_STYLE) g_object_notify (object, "style_set"); if (changed_mask & PANGO_FONT_MASK_VARIANT) g_object_notify (object, "variant_set"); if (changed_mask & PANGO_FONT_MASK_WEIGHT) g_object_notify (object, "weight_set"); if (changed_mask & PANGO_FONT_MASK_STRETCH) g_object_notify (object, "stretch_set"); if (changed_mask & PANGO_FONT_MASK_SIZE) g_object_notify (object, "size_set"); return; } static void notify_fields_changed (GObject *object, PangoFontMask changed_mask) { if (changed_mask & PANGO_FONT_MASK_FAMILY) g_object_notify (object, "family"); if (changed_mask & PANGO_FONT_MASK_STYLE) g_object_notify (object, "style"); if (changed_mask & PANGO_FONT_MASK_VARIANT) g_object_notify (object, "variant"); if (changed_mask & PANGO_FONT_MASK_WEIGHT) g_object_notify (object, "weight"); if (changed_mask & PANGO_FONT_MASK_STRETCH) g_object_notify (object, "stretch"); if (changed_mask & PANGO_FONT_MASK_SIZE) g_object_notify (object, "size"); return; } static void set_font_description (GtkCellRendererProgress *cellprogress, PangoFontDescription *font_desc) { GObject *object = G_OBJECT (cellprogress); PangoFontDescription *new_font_desc; PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask; if (font_desc) new_font_desc = pango_font_description_copy (font_desc); else new_font_desc = pango_font_description_new (); old_mask = pango_font_description_get_set_fields (cellprogress->font); new_mask = pango_font_description_get_set_fields (new_font_desc); changed_mask = old_mask | new_mask; set_changed_mask = old_mask ^ new_mask; pango_font_description_free (cellprogress->font); cellprogress->font = new_font_desc; g_object_freeze_notify (object); g_object_notify (object, "font_desc"); g_object_notify (object, "font"); if (changed_mask & PANGO_FONT_MASK_FAMILY) g_object_notify (object, "family"); if (changed_mask & PANGO_FONT_MASK_STYLE) g_object_notify (object, "style"); if (changed_mask & PANGO_FONT_MASK_VARIANT) g_object_notify (object, "variant"); if (changed_mask & PANGO_FONT_MASK_WEIGHT) g_object_notify (object, "weight"); if (changed_mask & PANGO_FONT_MASK_STRETCH) g_object_notify (object, "stretch"); if (changed_mask & PANGO_FONT_MASK_SIZE) { g_object_notify (object, "size"); g_object_notify (object, "size_points"); } notify_set_changed (object, set_changed_mask); g_object_thaw_notify (object); return; } static void gtk_cell_renderer_progress_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object); switch (param_id) { case PROP_VALUE: cellprogress->value = g_value_get_float (value); break; case PROP_VALUE_START: cellprogress->value_start = g_value_get_float (value); break; case PROP_ATTRIBUTES: if (cellprogress->extra_attrs) pango_attr_list_unref (cellprogress->extra_attrs); cellprogress->extra_attrs = g_value_get_boxed (value); if (cellprogress->extra_attrs) pango_attr_list_ref (cellprogress->extra_attrs); break; case PROP_MARKUP: { const gchar *str; gchar *text = NULL; GError *error = NULL; PangoAttrList *attrs = NULL; if (cellprogress->extra_attrs) pango_attr_list_unref (cellprogress->extra_attrs); str = g_value_get_string (value); if (str && !pango_parse_markup (str, -1, 0, &attrs, &text, NULL, &error)) { g_warning ("Failed to set cell text from markup due to error parsing markup: %s", error->message); g_error_free (error); return; } cellprogress->value = atol(text); cellprogress->extra_attrs = attrs; break; } case PROP_BACKGROUND: { PangoColor color; if (!g_value_get_string (value)) set_bg_color (cellprogress, NULL); /* reset to background_set to FALSE */ else if (pango_color_parse (&color, g_value_get_string (value))) set_bg_color (cellprogress, &color); else g_warning ("Don't know color `%s'", g_value_get_string (value)); g_object_notify (object, "background_gdk"); break; } case PROP_FOREGROUND: { PangoColor color; if (!g_value_get_string (value)) set_fg_color (cellprogress, NULL); /* reset to foreground_set to FALSE */ else if (pango_color_parse (&color, g_value_get_string (value))) set_fg_color (cellprogress, &color); else g_warning ("Don't know color `%s'", g_value_get_string (value)); g_object_notify (object, "foreground_gdk"); break; } case PROP_PROGRESSGROUND: switch (g_value_get_uint (value)) { case GTK_CELL_RENDERER_PROGRESS_ACTIVE: cellprogress->progressground = &cellprogress->progressground_active; break; case GTK_CELL_RENDERER_PROGRESS_COMPLETED: cellprogress->progressground = &cellprogress->progressground_completed; break; case GTK_CELL_RENDERER_PROGRESS_PAUSED: cellprogress->progressground = &cellprogress->progressground_paused; break; case GTK_CELL_RENDERER_PROGRESS_CANCELED: cellprogress->progressground = &cellprogress->progressground_canceled; break; default: g_warning ("Bad color `%i'", g_value_get_int (value)); break; } g_object_notify (object, "progressground"); break; case PROP_PROGRESSGROUND_ACTIVE: set_pg_color_str (cellprogress, &cellprogress->progressground_active, g_value_get_string (value)); break; case PROP_PROGRESSGROUND_COMPLETED: set_pg_color_str (cellprogress, &cellprogress->progressground_completed, g_value_get_string (value)); break; case PROP_PROGRESSGROUND_PAUSED: set_pg_color_str (cellprogress, &cellprogress->progressground_paused, g_value_get_string (value)); break; case PROP_PROGRESSGROUND_CANCELED: set_pg_color_str (cellprogress, &cellprogress->progressground_canceled, g_value_get_string (value)); break; case PROP_BACKGROUND_GDK: set_bg_color (cellprogress, g_value_get_boxed (value)); break; case PROP_FOREGROUND_GDK: set_fg_color (cellprogress, g_value_get_boxed (value)); break; case PROP_PROGRESSGROUND_ACTIVE_GDK: set_pg_color (cellprogress, &cellprogress->progressground_active, g_value_get_boxed (value)); break; case PROP_PROGRESSGROUND_COMPLETED_GDK: set_pg_color (cellprogress, &cellprogress->progressground_completed, g_value_get_boxed (value)); break; case PROP_PROGRESSGROUND_PAUSED_GDK: set_pg_color (cellprogress, &cellprogress->progressground_paused, g_value_get_boxed (value)); break; case PROP_PROGRESSGROUND_CANCELED_GDK: set_pg_color (cellprogress, &cellprogress->progressground_canceled, g_value_get_boxed (value)); break; case PROP_FONT: { PangoFontDescription *font_desc = NULL; const gchar *name; name = g_value_get_string (value); if (name) font_desc = pango_font_description_from_string (name); set_font_description (cellprogress, font_desc); break; } case PROP_FONT_DESC: set_font_description (cellprogress, g_value_get_boxed (value)); break; case PROP_FAMILY: case PROP_STYLE: case PROP_VARIANT: case PROP_WEIGHT: case PROP_STRETCH: case PROP_SIZE: case PROP_SIZE_POINTS: { PangoFontMask old_set_mask = pango_font_description_get_set_fields (cellprogress->font); switch (param_id) { case PROP_FAMILY: pango_font_description_set_family (cellprogress->font, g_value_get_string (value)); break; case PROP_STYLE: pango_font_description_set_style (cellprogress->font, g_value_get_enum (value)); break; case PROP_VARIANT: pango_font_description_set_variant (cellprogress->font, g_value_get_enum (value)); break; case PROP_WEIGHT: pango_font_description_set_weight (cellprogress->font, g_value_get_int (value)); break; case PROP_STRETCH: pango_font_description_set_stretch (cellprogress->font, g_value_get_enum (value)); break; case PROP_SIZE: pango_font_description_set_size (cellprogress->font, g_value_get_int (value)); g_object_notify (object, "size_points"); break; case PROP_SIZE_POINTS: pango_font_description_set_size (cellprogress->font, g_value_get_double (value) * PANGO_SCALE); g_object_notify (object, "size"); break; default: break; } notify_set_changed (G_OBJECT (cellprogress), old_set_mask & pango_font_description_get_set_fields (cellprogress->font)); g_object_notify (object, "font_desc"); g_object_notify (object, "font"); break; } case PROP_SCALE: cellprogress->font_scale = g_value_get_double (value); cellprogress->scale_set = TRUE; if (cellprogress->fixed_height_rows != -1) cellprogress->calc_fixed_height = TRUE; g_object_notify (object, "scale_set"); break; case PROP_STRIKETHROUGH: cellprogress->strikethrough = g_value_get_boolean (value); cellprogress->strikethrough_set = TRUE; g_object_notify (object, "strikethrough_set"); break; case PROP_UNDERLINE: cellprogress->underline_style = g_value_get_enum (value); cellprogress->underline_set = TRUE; g_object_notify (object, "underline_set"); break; case PROP_RISE: cellprogress->rise = g_value_get_int (value); cellprogress->rise_set = TRUE; g_object_notify (object, "rise_set"); if (cellprogress->fixed_height_rows != -1) cellprogress->calc_fixed_height = TRUE; break; case PROP_BACKGROUND_SET: cellprogress->background_set = g_value_get_boolean (value); break; case PROP_FOREGROUND_SET: cellprogress->foreground_set = g_value_get_boolean (value); break; case PROP_PROGRESSGROUND_SET: cellprogress->progressground_set = g_value_get_boolean (value); break; case PROP_FAMILY_SET: case PROP_STYLE_SET: case PROP_VARIANT_SET: case PROP_WEIGHT_SET: case PROP_STRETCH_SET: case PROP_SIZE_SET: if (!g_value_get_boolean (value)) { pango_font_description_unset_fields (cellprogress->font, get_property_font_set_mask (param_id)); } else { PangoFontMask changed_mask; changed_mask = set_font_desc_fields (cellprogress->font, get_property_font_set_mask (param_id)); notify_fields_changed (G_OBJECT (cellprogress), changed_mask); } break; case PROP_SCALE_SET: cellprogress->scale_set = g_value_get_boolean (value); break; case PROP_STRIKETHROUGH_SET: cellprogress->strikethrough_set = g_value_get_boolean (value); break; case PROP_UNDERLINE_SET: cellprogress->underline_set = g_value_get_boolean (value); break; case PROP_RISE_SET: cellprogress->rise_set = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } g_object_notify (object, "value"); return; } GtkCellRenderer * gtk_cell_renderer_progress_new (void) { return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL); } static void add_attr (PangoAttrList *attr_list, PangoAttribute *attr) { attr->start_index = 0; attr->end_index = G_MAXINT; pango_attr_list_insert (attr_list, attr); return; } static PangoLayout * get_layout (GtkCellRendererProgress *cellprogress, GtkWidget *widget, gboolean will_render, GtkCellRendererState flags) { gchar *text; PangoAttrList *attr_list; PangoLayout *layout; PangoUnderline uline; text = g_strdup_printf ("%.1f%%", cellprogress->value); layout = gtk_widget_create_pango_layout (widget, text); g_free (text); if (cellprogress->extra_attrs) attr_list = pango_attr_list_copy (cellprogress->extra_attrs); else attr_list = pango_attr_list_new (); if (will_render) { /* Add options that affect appearance but not size */ /* note that background doesn't go here, since it affects * background_area not the PangoLayout area */ if (cellprogress->foreground_set) { PangoColor color; color = cellprogress->foreground; add_attr (attr_list, pango_attr_foreground_new (color.red, color.green, color.blue)); } if (cellprogress->strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (cellprogress->strikethrough)); } add_attr (attr_list, pango_attr_font_desc_new (cellprogress->font)); if (cellprogress->scale_set && cellprogress->font_scale != 1.0) add_attr (attr_list, pango_attr_scale_new (cellprogress->font_scale)); if (cellprogress->underline_set) uline = cellprogress->underline_style; else uline = PANGO_UNDERLINE_NONE; if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT) { switch (uline) { case PANGO_UNDERLINE_NONE: uline = PANGO_UNDERLINE_SINGLE; break; case PANGO_UNDERLINE_SINGLE: uline = PANGO_UNDERLINE_DOUBLE; break; default: break; } } if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (cellprogress->underline_style)); if (cellprogress->rise_set) add_attr (attr_list, pango_attr_rise_new (cellprogress->rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); return layout; } static void gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { GtkCellRendererProgress *cellprogress = (GtkCellRendererProgress *) cell; PangoRectangle rect; PangoLayout *layout; if (cellprogress->calc_fixed_height) { PangoContext *context; PangoFontMetrics *metrics; PangoFontDescription *font_desc; gint row_height; font_desc = pango_font_description_copy (widget->style->font_desc); pango_font_description_merge (font_desc, cellprogress->font, TRUE); if (cellprogress->scale_set) pango_font_description_set_size (font_desc, cellprogress->font_scale * pango_font_description_get_size (font_desc)); context = gtk_widget_get_pango_context (widget); metrics = pango_context_get_metrics (context, font_desc, pango_context_get_language (context)); row_height = (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics)); pango_font_metrics_unref (metrics); gtk_cell_renderer_set_fixed_size (cell, cell->width, 2*cell->ypad + cellprogress->fixed_height_rows * PANGO_PIXELS (row_height)); if (height) { *height = cell->height; height = NULL; } cellprogress->calc_fixed_height = FALSE; if (width == NULL) return; } layout = get_layout (cellprogress, widget, FALSE, 0); pango_layout_get_pixel_extents (layout, NULL, &rect); if (width) *width = GTK_CELL_RENDERER (cellprogress)->xpad * 2 + rect.width; if (height) *height = GTK_CELL_RENDERER (cellprogress)->ypad * 2 + rect.height; if (cell_area) { if (x_offset) { *x_offset = cell->xalign * (cell_area->width - rect.width - (2 * cell->xpad)); *x_offset = MAX (*x_offset, 0); } if (y_offset) { *y_offset = cell->yalign * (cell_area->height - rect.height - (2 * cell->ypad)); *y_offset = MAX (*y_offset, 0); } } g_object_unref (layout); return; } static void gtk_cell_renderer_progress_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, guint flags) { gint draw_width, draw_start, x_offset, y_offset; GdkColor color; GdkGC *gc; GtkStateType state; GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell); PangoLayout *layout; layout = get_layout (cellprogress, widget, TRUE, flags); gtk_cell_renderer_progress_get_size (cell, widget, cell_area, &x_offset, &y_offset, NULL, NULL); if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) { if (GTK_WIDGET_HAS_FOCUS (widget)) state = GTK_STATE_SELECTED; else state = GTK_STATE_ACTIVE; } else { if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE) state = GTK_STATE_INSENSITIVE; else state = GTK_STATE_NORMAL; } gc = gdk_gc_new (window); if (cellprogress->background_set) { color.red = cellprogress->background.red; color.green = cellprogress->background.green; color.blue = cellprogress->background.blue; gdk_gc_set_rgb_fg_color (gc, &color); gdk_draw_rectangle (window, gc, TRUE, cell_area->x, cell_area->y, cell_area->width, cell_area->height); } if (cellprogress->foreground_set) { color.red = cellprogress->foreground.red; color.green = cellprogress->foreground.green; color.blue = cellprogress->foreground.blue; gdk_gc_set_rgb_fg_color (gc, &color); gdk_draw_rectangle (window, gc, FALSE, cell_area->x, cell_area->y, cell_area->width - 2, cell_area->height - 1); } if (cellprogress->progressground_set) { gdk_gc_set_rgb_fg_color (gc, cellprogress->progressground); draw_width = (cellprogress->value * (cell_area->width - 4)) / 100.0; draw_start = (cellprogress->value_start * (cell_area->width - 4)) / 100.0; gdk_draw_rectangle (window, gc, TRUE, cell_area->x + 2 + draw_start, cell_area->y + 2, draw_width, cell_area->height - 4); } gtk_paint_layout (widget->style, window, state, TRUE, cell_area, widget, "cellrendererprogress", cell_area->x + x_offset + cell->xpad, cell_area->y + y_offset + cell->ypad, layout); g_object_unref (layout); g_object_unref (gc); return; } static void gtk_cell_renderer_progress_finalize (GObject *object) { GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object); pango_font_description_free (cellprogress->font); if (cellprogress->extra_attrs) pango_attr_list_unref (cellprogress->extra_attrs); (* G_OBJECT_CLASS (parent_class)->finalize) (object); return; }