gtk+ r19995 - in trunk: . gtk tests
- From: tvb svn gnome org
- To: svn-commits-list gnome org
- Subject: gtk+ r19995 - in trunk: . gtk tests
- Date: Fri, 11 Apr 2008 17:56:26 +0100 (BST)
Author: tvb
Date: Fri Apr 11 17:56:26 2008
New Revision: 19995
URL: http://svn.gnome.org/viewvc/gtk+?rev=19995&view=rev
Log:
* gtk/gtklabel.c: Added <attributes> / <attribute>
custom tags to parse pango attributes into labels.
* tests/buildertest.c: Added tests for GtkLabel custom
tag parsing.
Modified:
trunk/ChangeLog
trunk/gtk/gtkbuildable.h
trunk/gtk/gtklabel.c
trunk/tests/buildertest.c
Modified: trunk/gtk/gtkbuildable.h
==============================================================================
--- trunk/gtk/gtkbuildable.h (original)
+++ trunk/gtk/gtkbuildable.h Fri Apr 11 17:56:26 2008
@@ -33,6 +33,7 @@
#define GTK_IS_BUILDABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDABLE))
#define GTK_BUILDABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+
typedef struct _GtkBuildable GtkBuildable; /* Dummy typedef */
typedef struct _GtkBuildableIface GtkBuildableIface;
Modified: trunk/gtk/gtklabel.c
==============================================================================
--- trunk/gtk/gtklabel.c (original)
+++ trunk/gtk/gtklabel.c Fri Apr 11 17:56:26 2008
@@ -43,6 +43,7 @@
#include "gtknotebook.h"
#include "gtkstock.h"
#include "gtkbindings.h"
+#include "gtkbuildable.h"
#include "gtkprivate.h"
#include "gtkalias.h"
@@ -179,6 +180,20 @@
guint info,
guint time);
+static void gtk_label_buildable_interface_init (GtkBuildableIface *iface);
+static gboolean gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data);
+
+static void gtk_label_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data);
+
/* For selectable lables: */
static void gtk_label_move_cursor (GtkLabel *label,
@@ -197,7 +212,11 @@
static GQuark quark_angle = 0;
-G_DEFINE_TYPE (GtkLabel, gtk_label, GTK_TYPE_MISC)
+static GtkBuildableIface *buildable_parent_iface = NULL;
+
+G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_MISC,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_label_buildable_interface_init));
static void
add_move_binding (GtkBindingSet *binding_set,
@@ -811,6 +830,332 @@
gtk_label_set_text (label, "");
}
+
+static void
+gtk_label_buildable_interface_init (GtkBuildableIface *iface)
+{
+ buildable_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->custom_tag_start = gtk_label_buildable_custom_tag_start;
+ iface->custom_finished = gtk_label_buildable_custom_finished;
+}
+
+typedef struct {
+ GtkBuilder *builder;
+ GObject *object;
+ PangoAttrList *attrs;
+} PangoParserData;
+
+PangoAttribute *
+attribute_from_text (GtkBuilder *builder,
+ const gchar *name,
+ const gchar *value,
+ GError **error)
+{
+ PangoAttribute *attribute = NULL;
+ PangoAttrType type;
+ PangoLanguage *language;
+ PangoFontDescription *font_desc;
+ GdkColor *color;
+ GValue val = { 0, };
+
+ if (!gtk_builder_value_from_string_type (builder, PANGO_TYPE_ATTR_TYPE, name, &val, error))
+ return NULL;
+
+ type = g_value_get_enum (&val);
+ g_value_unset (&val);
+
+ switch (type)
+ {
+ /* PangoAttrLanguage */
+ case PANGO_ATTR_LANGUAGE:
+ if ((language = pango_language_from_string (value)))
+ {
+ attribute = pango_attr_language_new (language);
+ g_value_init (&val, G_TYPE_INT);
+ }
+ break;
+ /* PangoAttrInt */
+ case PANGO_ATTR_STYLE:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_STYLE, value, &val, error))
+ attribute = pango_attr_style_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_WEIGHT:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_WEIGHT, value, &val, error))
+ attribute = pango_attr_weight_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_VARIANT:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_VARIANT, value, &val, error))
+ attribute = pango_attr_variant_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_STRETCH:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_STRETCH, value, &val, error))
+ attribute = pango_attr_stretch_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_UNDERLINE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_underline_new (g_value_get_boolean (&val));
+ break;
+ case PANGO_ATTR_STRIKETHROUGH:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_strikethrough_new (g_value_get_boolean (&val));
+ break;
+ case PANGO_ATTR_GRAVITY:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY, value, &val, error))
+ attribute = pango_attr_gravity_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_GRAVITY_HINT:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY_HINT,
+ value, &val, error))
+ attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
+ break;
+
+ /* PangoAttrString */
+ case PANGO_ATTR_FAMILY:
+ attribute = pango_attr_family_new (value);
+ g_value_init (&val, G_TYPE_INT);
+ break;
+
+ /* PangoAttrSize */
+ case PANGO_ATTR_SIZE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT,
+ value, &val, error))
+ attribute = pango_attr_size_new (g_value_get_int (&val));
+ break;
+ case PANGO_ATTR_ABSOLUTE_SIZE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT,
+ value, &val, error))
+ attribute = pango_attr_size_new_absolute (g_value_get_int (&val));
+ break;
+
+ /* PangoAttrFontDesc */
+ case PANGO_ATTR_FONT_DESC:
+ if ((font_desc = pango_font_description_from_string (value)))
+ {
+ attribute = pango_attr_font_desc_new (font_desc);
+ pango_font_description_free (font_desc);
+ g_value_init (&val, G_TYPE_INT);
+ }
+ break;
+
+ /* PangoAttrColor */
+ case PANGO_ATTR_FOREGROUND:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_COLOR,
+ value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_foreground_new (color->red, color->green, color->blue);
+ }
+ break;
+ case PANGO_ATTR_BACKGROUND:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_COLOR,
+ value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_background_new (color->red, color->green, color->blue);
+ }
+ break;
+ case PANGO_ATTR_UNDERLINE_COLOR:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_COLOR,
+ value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_underline_color_new (color->red, color->green, color->blue);
+ }
+ break;
+ case PANGO_ATTR_STRIKETHROUGH_COLOR:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_COLOR,
+ value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ 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:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_DOUBLE,
+ value, &val, error))
+ attribute = pango_attr_scale_new (g_value_get_double (&val));
+ break;
+
+ case PANGO_ATTR_INVALID:
+ case PANGO_ATTR_LETTER_SPACING:
+ case PANGO_ATTR_RISE:
+ case PANGO_ATTR_FALLBACK:
+ default:
+ break;
+ }
+
+ g_value_unset (&val);
+
+ return attribute;
+}
+
+
+static void
+pango_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ PangoParserData *data = (PangoParserData*)user_data;
+ GValue val = { 0, };
+ guint i;
+ gint line_number, char_number;
+
+ if (strcmp (element_name, "attribute") == 0)
+ {
+ PangoAttribute *attr = NULL;
+ const gchar *name = NULL;
+ const gchar *value = NULL;
+ const gchar *start = NULL;
+ const gchar *end = NULL;
+ guint start_val = 0;
+ guint end_val = G_MAXUINT;
+
+ for (i = 0; names[i]; i++)
+ {
+ if (strcmp (names[i], "name") == 0)
+ name = values[i];
+ else if (strcmp (names[i], "value") == 0)
+ value = values[i];
+ else if (strcmp (names[i], "start") == 0)
+ start = values[i];
+ else if (strcmp (names[i], "end") == 0)
+ end = values[i];
+ else
+ {
+ g_markup_parse_context_get_position (context,
+ &line_number,
+ &char_number);
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_ATTRIBUTE,
+ "%s:%d:%d '%s' is not a valid attribute of <%s>",
+ "<input>",
+ line_number, char_number, names[i], "attribute");
+ return;
+ }
+ }
+
+ if (!name || !value)
+ {
+ g_markup_parse_context_get_position (context,
+ &line_number,
+ &char_number);
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
+ "%s:%d:%d <%s> requires attribute \"%s\"",
+ "<input>",
+ line_number, char_number, "attribute",
+ name ? "value" : "name");
+ return;
+ }
+
+ if (start)
+ {
+ if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_UINT,
+ start, &val, error))
+ return;
+ start_val = g_value_get_uint (&val);
+ g_value_unset (&val);
+ }
+
+ if (end)
+ {
+ if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_UINT,
+ end, &val, error))
+ return;
+ end_val = g_value_get_uint (&val);
+ g_value_unset (&val);
+ }
+
+ attr = attribute_from_text (data->builder, name, value, error);
+ attr->start_index = start_val;
+ attr->end_index = end_val;
+
+ if (attr)
+ {
+ if (!data->attrs)
+ data->attrs = pango_attr_list_new ();
+
+ pango_attr_list_insert (data->attrs, attr);
+ }
+ }
+ else if (strcmp (element_name, "attributes") == 0)
+ ;
+ else
+ g_warning ("Unsupported tag for GtkLabel: %s\n", element_name);
+}
+
+static const GMarkupParser pango_parser =
+ {
+ pango_start_element,
+ };
+
+static gboolean
+gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data)
+{
+ if (buildable_parent_iface->custom_tag_start (buildable, builder, child,
+ tagname, parser, data))
+ return TRUE;
+
+ if (strcmp (tagname, "attributes") == 0)
+ {
+ PangoParserData *parser_data;
+
+ parser_data = g_slice_new0 (PangoParserData);
+ parser_data->builder = g_object_ref (builder);
+ parser_data->object = g_object_ref (buildable);
+ *parser = pango_parser;
+ *data = parser_data;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+gtk_label_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data)
+{
+ PangoParserData *data;
+
+ buildable_parent_iface->custom_finished (buildable, builder, child,
+ tagname, user_data);
+
+ if (strcmp (tagname, "attributes") == 0)
+ {
+ data = (PangoParserData*)user_data;
+
+ if (data->attrs)
+ {
+ gtk_label_set_attributes (GTK_LABEL (buildable), data->attrs);
+ pango_attr_list_unref (data->attrs);
+ }
+
+ g_object_unref (data->object);
+ g_object_unref (data->builder);
+ g_slice_free (PangoParserData, data);
+ }
+}
+
+
/**
* gtk_label_new:
* @str: The text of the label
Modified: trunk/tests/buildertest.c
==============================================================================
--- trunk/tests/buildertest.c (original)
+++ trunk/tests/buildertest.c Fri Apr 11 17:56:26 2008
@@ -1914,6 +1914,118 @@
}
+typedef struct {
+ gboolean weight;
+ gboolean foreground;
+ gboolean underline;
+ gboolean size;
+ gboolean font_desc;
+ gboolean language;
+} FoundAttrs;
+
+static gboolean
+filter_pango_attrs (PangoAttribute *attr,
+ gpointer data)
+{
+ FoundAttrs *found = (FoundAttrs *)data;
+
+ if (attr->klass->type == PANGO_ATTR_WEIGHT)
+ found->weight = TRUE;
+ else if (attr->klass->type == PANGO_ATTR_FOREGROUND)
+ found->foreground = TRUE;
+ else if (attr->klass->type == PANGO_ATTR_UNDERLINE)
+ found->underline = TRUE;
+ /* Make sure optional start/end properties are working */
+ else if (attr->klass->type == PANGO_ATTR_SIZE &&
+ attr->start_index == 5 &&
+ attr->end_index == 10)
+ found->size = TRUE;
+ else if (attr->klass->type == PANGO_ATTR_FONT_DESC)
+ found->font_desc = TRUE;
+ else if (attr->klass->type == PANGO_ATTR_LANGUAGE)
+ found->language = TRUE;
+
+ return TRUE;
+}
+
+static void
+test_pango_attributes (void)
+{
+ GtkBuilder *builder;
+ FoundAttrs found = { 0, };
+ const gchar buffer[] =
+ "<interface>"
+ " <object class=\"GtkLabel\" id=\"label1\">"
+ " <attributes>"
+ " <attribute name=\"weight\" value=\"PANGO_WEIGHT_BOLD\"/>"
+ " <attribute name=\"foreground\" value=\"DarkSlateGray\"/>"
+ " <attribute name=\"underline\" value=\"True\"/>"
+ " <attribute name=\"size\" value=\"4\" start=\"5\" end=\"10\"/>"
+ " <attribute name=\"font-desc\" value=\"Sans Italic 22\"/>"
+ " <attribute name=\"language\" value=\"pt_BR\"/>"
+ " </attributes>"
+ " </object>"
+ "</interface>";
+ const gchar err_buffer1[] =
+ "<interface>"
+ " <object class=\"GtkLabel\" id=\"label1\">"
+ " <attributes>"
+ " <attribute name=\"weight\"/>"
+ " </attributes>"
+ " </object>"
+ "</interface>";
+ const gchar err_buffer2[] =
+ "<interface>"
+ " <object class=\"GtkLabel\" id=\"label1\">"
+ " <attributes>"
+ " <attribute name=\"weight\" value=\"PANGO_WEIGHT_BOLD\" unrecognized=\"True\"/>"
+ " </attributes>"
+ " </object>"
+ "</interface>";
+
+ GObject *label;
+ GError *error = NULL;
+ PangoAttrList *attrs, *filtered;
+
+ /* Test attributes are set */
+ builder = builder_new_from_string (buffer, -1, NULL);
+ label = gtk_builder_get_object (builder, "label1");
+ g_assert (label != NULL);
+
+ attrs = gtk_label_get_attributes (GTK_LABEL (label));
+ g_assert (attrs != NULL);
+
+ filtered = pango_attr_list_filter (attrs, filter_pango_attrs, &found);
+ g_assert (filtered);
+ pango_attr_list_unref (filtered);
+
+ g_assert (found.weight);
+ g_assert (found.foreground);
+ g_assert (found.underline);
+ g_assert (found.size);
+ g_assert (found.language);
+ g_assert (found.font_desc);
+
+ g_object_unref (builder);
+
+ /* Test errors are set */
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_string (builder, err_buffer1, -1, &error);
+ label = gtk_builder_get_object (builder, "label1");
+ g_assert (error);
+ g_object_unref (builder);
+ g_error_free (error);
+ error = NULL;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_string (builder, err_buffer2, -1, &error);
+ label = gtk_builder_get_object (builder, "label1");
+ g_assert (error);
+ g_object_unref (builder);
+ g_error_free (error);
+
+}
+
static void
test_file (const gchar *filename)
{
@@ -1996,6 +2108,7 @@
g_test_add_func ("/Builder/Reference Counting", test_reference_counting);
g_test_add_func ("/Builder/Window", test_window);
g_test_add_func ("/Builder/IconFactory", test_icon_factory);
+ g_test_add_func ("/Builder/PangoAttributes", test_pango_attributes);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]