/* * glade-gtk-label.c - GladeWidgetAdaptor for GtkLabel * * Copyright (C) 2013 Tristan Van Berkom * * Authors: * Tristan Van Berkom * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "glade-label-editor.h" #include "glade-attributes.h" #include "glade-gtk.h" void glade_gtk_label_post_create (GladeWidgetAdaptor * adaptor, GObject * object, GladeCreateReason reason) { GladeWidget *glabel = glade_widget_get_from_gobject (object); if (reason == GLADE_CREATE_USER) glade_widget_property_set_sensitive (glabel, "mnemonic-widget", FALSE, MNEMONIC_INSENSITIVE_MSG); } static void glade_gtk_label_set_label (GObject * object, const GValue * value) { GladeWidget *glabel; gboolean use_markup = FALSE, use_underline = FALSE; glabel = glade_widget_get_from_gobject (object); glade_widget_property_get (glabel, "use-markup", &use_markup); if (use_markup) gtk_label_set_markup (GTK_LABEL (object), g_value_get_string (value)); else gtk_label_set_text (GTK_LABEL (object), g_value_get_string (value)); glade_widget_property_get (glabel, "use-underline", &use_underline); if (use_underline) gtk_label_set_use_underline (GTK_LABEL (object), use_underline); } static void glade_gtk_label_set_attributes (GObject * object, const GValue * value) { GladeAttribute *gattr; PangoAttribute *attribute; PangoLanguage *language; PangoFontDescription *font_desc; PangoAttrList *attrs = NULL; GdkColor *color; GList *list; for (list = g_value_get_boxed (value); list; list = list->next) { gattr = list->data; attribute = NULL; switch (gattr->type) { /* PangoFontDescription */ case PANGO_ATTR_FONT_DESC: if ((font_desc = pango_font_description_from_string (g_value_get_string (&gattr->value)))) { attribute = pango_attr_font_desc_new (font_desc); pango_font_description_free (font_desc); } break; /* PangoAttrLanguage */ case PANGO_ATTR_LANGUAGE: if ((language = pango_language_from_string (g_value_get_string (&gattr->value)))) attribute = pango_attr_language_new (language); break; /* PangoAttrInt */ case PANGO_ATTR_STYLE: attribute = pango_attr_style_new (g_value_get_enum (&(gattr->value))); break; case PANGO_ATTR_WEIGHT: attribute = pango_attr_weight_new (g_value_get_enum (&(gattr->value))); break; case PANGO_ATTR_VARIANT: attribute = pango_attr_variant_new (g_value_get_enum (&(gattr->value))); break; case PANGO_ATTR_STRETCH: attribute = pango_attr_stretch_new (g_value_get_enum (&(gattr->value))); break; case PANGO_ATTR_UNDERLINE: attribute = pango_attr_underline_new (g_value_get_boolean (&(gattr->value))); break; case PANGO_ATTR_STRIKETHROUGH: attribute = pango_attr_strikethrough_new (g_value_get_boolean (&(gattr->value))); break; case PANGO_ATTR_GRAVITY: attribute = pango_attr_gravity_new (g_value_get_enum (&(gattr->value))); break; case PANGO_ATTR_GRAVITY_HINT: attribute = pango_attr_gravity_hint_new (g_value_get_enum (&(gattr->value))); break; /* PangoAttrString */ case PANGO_ATTR_FAMILY: attribute = pango_attr_family_new (g_value_get_string (&(gattr->value))); break; /* PangoAttrSize */ case PANGO_ATTR_SIZE: attribute = pango_attr_size_new (g_value_get_int (&(gattr->value))); break; case PANGO_ATTR_ABSOLUTE_SIZE: attribute = pango_attr_size_new_absolute (g_value_get_int (&(gattr->value))); break; /* PangoAttrColor */ case PANGO_ATTR_FOREGROUND: color = g_value_get_boxed (&(gattr->value)); attribute = pango_attr_foreground_new (color->red, color->green, color->blue); break; case PANGO_ATTR_BACKGROUND: color = g_value_get_boxed (&(gattr->value)); attribute = pango_attr_background_new (color->red, color->green, color->blue); break; case PANGO_ATTR_UNDERLINE_COLOR: color = g_value_get_boxed (&(gattr->value)); attribute = pango_attr_underline_color_new (color->red, color->green, color->blue); break; case PANGO_ATTR_STRIKETHROUGH_COLOR: color = g_value_get_boxed (&(gattr->value)); attribute = pango_attr_strikethrough_color_new (color->red, color->green, color->blue); break; /* PangoAttrShape */ case PANGO_ATTR_SHAPE: /* Unsupported for now */ break; /* PangoAttrFloat */ case PANGO_ATTR_SCALE: attribute = pango_attr_scale_new (g_value_get_double (&(gattr->value))); break; case PANGO_ATTR_INVALID: case PANGO_ATTR_LETTER_SPACING: case PANGO_ATTR_RISE: case PANGO_ATTR_FALLBACK: default: break; } if (attribute) { if (!attrs) attrs = pango_attr_list_new (); pango_attr_list_insert (attrs, attribute); } } gtk_label_set_attributes (GTK_LABEL (object), attrs); pango_attr_list_unref (attrs); } static void glade_gtk_label_set_content_mode (GObject * object, const GValue * value) { GladeLabelContentMode mode = g_value_get_int (value); GladeWidget *glabel; glabel = glade_widget_get_from_gobject (object); glade_widget_property_set_sensitive (glabel, "glade-attributes", FALSE, NOT_SELECTED_MSG); glade_widget_property_set_sensitive (glabel, "use-markup", FALSE, NOT_SELECTED_MSG); glade_widget_property_set_sensitive (glabel, "pattern", FALSE, NOT_SELECTED_MSG); switch (mode) { case GLADE_LABEL_MODE_ATTRIBUTES: glade_widget_property_set_sensitive (glabel, "glade-attributes", TRUE, NULL); break; case GLADE_LABEL_MODE_MARKUP: glade_widget_property_set_sensitive (glabel, "use-markup", TRUE, NULL); break; case GLADE_LABEL_MODE_PATTERN: glade_widget_property_set_sensitive (glabel, "pattern", TRUE, NULL); break; default: break; } } static void glade_gtk_label_update_lines_sensitivity (GObject * object) { GladeWidget *glabel; PangoEllipsizeMode ellipsize_mode; gint wrap_mode; glabel = glade_widget_get_from_gobject (object); glade_widget_property_get (glabel, "label-wrap-mode", &wrap_mode); glade_widget_property_get (glabel, "ellipsize", &ellipsize_mode); if (wrap_mode == GLADE_LABEL_WRAP_MODE && ellipsize_mode != PANGO_ELLIPSIZE_NONE) glade_widget_property_set_sensitive (glabel, "lines", TRUE, NULL); else glade_widget_property_set_sensitive (glabel, "lines", FALSE, _("This property only applies if ellipsize and wrapping are enabled")); } static void glade_gtk_label_set_wrap_mode (GObject * object, const GValue * value) { GladeLabelWrapMode mode = g_value_get_int (value); GladeWidget *glabel; glabel = glade_widget_get_from_gobject (object); glade_widget_property_set_sensitive (glabel, "single-line-mode", FALSE, NOT_SELECTED_MSG); glade_widget_property_set_sensitive (glabel, "wrap-mode", FALSE, NOT_SELECTED_MSG); if (mode == GLADE_LABEL_SINGLE_LINE) glade_widget_property_set_sensitive (glabel, "single-line-mode", TRUE, NULL); else if (mode == GLADE_LABEL_WRAP_MODE) glade_widget_property_set_sensitive (glabel, "wrap-mode", TRUE, NULL); glade_gtk_label_update_lines_sensitivity (object); } static void glade_gtk_label_set_use_underline (GObject * object, const GValue * value) { GladeWidget *glabel; glabel = glade_widget_get_from_gobject (object); if (g_value_get_boolean (value)) glade_widget_property_set_sensitive (glabel, "mnemonic-widget", TRUE, NULL); else glade_widget_property_set_sensitive (glabel, "mnemonic-widget", FALSE, MNEMONIC_INSENSITIVE_MSG); gtk_label_set_use_underline (GTK_LABEL (object), g_value_get_boolean (value)); } void glade_gtk_label_set_property (GladeWidgetAdaptor * adaptor, GObject * object, const gchar * id, const GValue * value) { if (!strcmp (id, "label")) glade_gtk_label_set_label (object, value); else if (!strcmp (id, "glade-attributes")) glade_gtk_label_set_attributes (object, value); else if (!strcmp (id, "label-content-mode")) glade_gtk_label_set_content_mode (object, value); else if (!strcmp (id, "label-wrap-mode")) glade_gtk_label_set_wrap_mode (object, value); else if (!strcmp (id, "use-underline")) glade_gtk_label_set_use_underline (object, value); else { if (!strcmp (id, "ellipsize")) glade_gtk_label_update_lines_sensitivity (object); GWA_GET_CLASS (GTK_TYPE_WIDGET)->set_property (adaptor, object, id, value); } } static void glade_gtk_parse_attributes (GladeWidget * widget, GladeXmlNode * node) { PangoAttrType attr_type; GladeXmlNode *prop; GladeAttribute *attr; GList *attrs = NULL; gchar *name, *value; for (prop = glade_xml_node_get_children (node); prop; prop = glade_xml_node_next (prop)) { if (!glade_xml_node_verify (prop, GLADE_TAG_ATTRIBUTE)) continue; if (!(name = glade_xml_get_property_string_required (prop, GLADE_XML_TAG_NAME, NULL))) continue; if (!(value = glade_xml_get_property_string_required (prop, GLADE_TAG_VALUE, NULL))) { /* for a while, Glade was broken and was storing * attributes in the node contents */ if (!(value = glade_xml_get_content (prop))) { g_free (name); continue; } } if ((attr_type = glade_utils_enum_value_from_string (PANGO_TYPE_ATTR_TYPE, name)) == 0) continue; /* Parse attribute and add to list */ if ((attr = glade_gtk_attribute_from_string (attr_type, value)) != NULL) attrs = g_list_prepend (attrs, attr); /* XXX deal with start/end here ... */ g_free (name); g_free (value); } glade_widget_property_set (widget, "glade-attributes", g_list_reverse (attrs)); glade_attr_list_free (attrs); } static void glade_gtk_label_read_attributes (GladeWidget * widget, GladeXmlNode * node) { GladeXmlNode *attrs_node; if ((attrs_node = glade_xml_search_child (node, GLADE_TAG_ATTRIBUTES)) != NULL) { /* Generic attributes parsing */ glade_gtk_parse_attributes (widget, attrs_node); } } void glade_gtk_label_read_widget (GladeWidgetAdaptor * adaptor, GladeWidget * widget, GladeXmlNode * node) { GladeProperty *prop; if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) || glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE))) return; /* First chain up and read in all the normal properties.. */ GWA_GET_CLASS (GTK_TYPE_WIDGET)->read_widget (adaptor, widget, node); glade_gtk_label_read_attributes (widget, node); /* sync label property after a load... */ prop = glade_widget_get_property (widget, "label"); glade_gtk_label_set_label (glade_widget_get_object (widget), glade_property_inline_value (prop)); /* Resolve "label-content-mode" virtual control property */ if (!glade_widget_property_original_default (widget, "use-markup")) glade_widget_property_set (widget, "label-content-mode", GLADE_LABEL_MODE_MARKUP); else if (!glade_widget_property_original_default (widget, "pattern")) glade_widget_property_set (widget, "label-content-mode", GLADE_LABEL_MODE_PATTERN); else glade_widget_property_set (widget, "label-content-mode", GLADE_LABEL_MODE_ATTRIBUTES); /* Resolve "label-wrap-mode" virtual control property */ if (!glade_widget_property_original_default (widget, "single-line-mode")) glade_widget_property_set (widget, "label-wrap-mode", GLADE_LABEL_SINGLE_LINE); else if (!glade_widget_property_original_default (widget, "wrap")) glade_widget_property_set (widget, "label-wrap-mode", GLADE_LABEL_WRAP_MODE); else glade_widget_property_set (widget, "label-wrap-mode", GLADE_LABEL_WRAP_FREE); if (glade_widget_property_original_default (widget, "use-underline")) glade_widget_property_set_sensitive (widget, "mnemonic-widget", FALSE, MNEMONIC_INSENSITIVE_MSG); } static void glade_gtk_label_write_attributes (GladeWidget * widget, GladeXmlContext * context, GladeXmlNode * node) { GladeXmlNode *attr_node; GList *attrs = NULL, *l; GladeAttribute *gattr; gchar *attr_type; gchar *attr_value; if (!glade_widget_property_get (widget, "glade-attributes", &attrs) || !attrs) return; for (l = attrs; l; l = l->next) { gattr = l->data; attr_type = glade_utils_enum_string_from_value (PANGO_TYPE_ATTR_TYPE, gattr->type); attr_value = glade_gtk_string_from_attr (gattr); attr_node = glade_xml_node_new (context, GLADE_TAG_ATTRIBUTE); glade_xml_node_append_child (node, attr_node); glade_xml_node_set_property_string (attr_node, GLADE_TAG_NAME, attr_type); glade_xml_node_set_property_string (attr_node, GLADE_TAG_VALUE, attr_value); } } void glade_gtk_label_write_widget (GladeWidgetAdaptor * adaptor, GladeWidget * widget, GladeXmlContext * context, GladeXmlNode * node) { GladeXmlNode *attrs_node; if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) || glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE))) return; /* First chain up and read in all the normal properties.. */ GWA_GET_CLASS (GTK_TYPE_WIDGET)->write_widget (adaptor, widget, context, node); attrs_node = glade_xml_node_new (context, GLADE_TAG_ATTRIBUTES); glade_gtk_label_write_attributes (widget, context, attrs_node); if (!glade_xml_node_get_children (attrs_node)) glade_xml_node_delete (attrs_node); else glade_xml_node_append_child (node, attrs_node); } gchar * glade_gtk_label_string_from_value (GladeWidgetAdaptor * adaptor, GladePropertyClass * klass, const GValue * value) { GParamSpec *pspec; pspec = glade_property_class_get_pspec (klass); if (pspec->value_type == GLADE_TYPE_ATTR_GLIST) { GList *l, *list = g_value_get_boxed (value); GString *string = g_string_new (""); gchar *str; for (l = list; l; l = g_list_next (l)) { GladeAttribute *attr = l->data; /* Return something usefull at least to for the backend to compare */ gchar *attr_str = glade_gtk_string_from_attr (attr); g_string_append_printf (string, "%d=%s ", attr->type, attr_str); g_free (attr_str); } str = string->str; g_string_free (string, FALSE); return str; } else return GWA_GET_CLASS (GTK_TYPE_WIDGET)->string_from_value (adaptor, klass, value); } GladeEditorProperty * glade_gtk_label_create_eprop (GladeWidgetAdaptor * adaptor, GladePropertyClass * klass, gboolean use_command) { GladeEditorProperty *eprop; GParamSpec *pspec; pspec = glade_property_class_get_pspec (klass); /* chain up.. */ if (pspec->value_type == GLADE_TYPE_ATTR_GLIST) { eprop = g_object_new (GLADE_TYPE_EPROP_ATTRS, "property-class", klass, "use-command", use_command, NULL); } else eprop = GWA_GET_CLASS (GTK_TYPE_WIDGET)->create_eprop (adaptor, klass, use_command); return eprop; } GladeEditable * glade_gtk_label_create_editable (GladeWidgetAdaptor * adaptor, GladeEditorPageType type) { GladeEditable *editable; if (type == GLADE_PAGE_GENERAL) editable = (GladeEditable *) glade_label_editor_new (); else editable = GWA_GET_CLASS (GTK_TYPE_WIDGET)->create_editable (adaptor, type); return editable; }