[gtk+] Support scale marks in builder markup
- From: Matthias Clasen <matthiasc src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+] Support scale marks in builder markup
- Date: Sun, 3 May 2009 12:26:07 -0400 (EDT)
commit dc8f36e2549021a9f51291267d916b73f8d909df
Author: Matthias Clasen <mclasen redhat com>
Date: Sat May 2 21:02:12 2009 -0400
Support scale marks in builder markup
---
NEWS | 4 +
docs/reference/gtk/tmpl/gtkbuilder.sgml | 3 +-
docs/reference/gtk/tmpl/gtkscale.sgml | 24 ++-
gtk/gtkscale.c | 256 ++++++++++++++++++++++++++++++-
4 files changed, 277 insertions(+), 10 deletions(-)
diff --git a/NEWS b/NEWS
index 5037f3e..c47eb47 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,10 @@
Overview of Changes from GTK+ 2.16.x to 2.17.0
==============================================
+* GtkBuilder:
+ - Scale marks can now be specified in builder markup
+ - GtkAssistant action widgets can be added in builder markup
+
* Changes that are relevant for theme authors
- GtkEntry now has a ::invisible-char style property that allows
themes to set the preferred invisible character
diff --git a/docs/reference/gtk/tmpl/gtkbuilder.sgml b/docs/reference/gtk/tmpl/gtkbuilder.sgml
index fe10530..8dc1eb5 100644
--- a/docs/reference/gtk/tmpl/gtkbuilder.sgml
+++ b/docs/reference/gtk/tmpl/gtkbuilder.sgml
@@ -229,7 +229,8 @@ respective objects, see
<link linkend="GtkUIManager-BUILDER-UI">GtkUIManager</link>,
<link linkend="GtkActionGroup-BUILDER-UI">GtkActionGroup</link>.
<link linkend="GtkMenuItem-BUILDER-UI">GtkMenuItem</link>,
-<link linkend="GtkAssistant-BUILDER-UI">GtkAssistant</link>.
+<link linkend="GtkAssistant-BUILDER-UI">GtkAssistant</link>,
+<link linkend="GtkScale-BUILDER-UI">GtkScale</link>.
</para>
</refsect2>
diff --git a/docs/reference/gtk/tmpl/gtkscale.sgml b/docs/reference/gtk/tmpl/gtkscale.sgml
index 3955e9f..2ac9a18 100644
--- a/docs/reference/gtk/tmpl/gtkscale.sgml
+++ b/docs/reference/gtk/tmpl/gtkscale.sgml
@@ -7,18 +7,28 @@ Base class for GtkHScale and GtkVScale
<!-- ##### SECTION Long_Description ##### -->
<para>
A #GtkScale is a slider control used to select a numeric value.
-To use it, you'll probably want to investigate the methods on
+To use it, you'll probably want to investigate the methods on
its base class, #GtkRange, in addition to the methods for #GtkScale itself.
-To set the value of a scale, you would normally use gtk_range_set_value().
-To detect changes to the value, you would normally use the "value_changed"
+To set the value of a scale, you would normally use gtk_range_set_value().
+To detect changes to the value, you would normally use the "value_changed"
signal.
</para>
<para>
The #GtkScale widget is an abstract class, used only for deriving the
-subclasses #GtkHScale and #GtkVScale. To create a scale widget,
+subclasses #GtkHScale and #GtkVScale. To create a scale widget,
call gtk_hscale_new_with_range() or gtk_vscale_new_with_range().
</para>
+<refsect2 id="GtkScale-BUILDER-UI"><title>GtkScale as GtkBuildable</title>
+<para>
+GtkScale supports a custom <marks> element, which
+can contain multiple <mark> elements. The "value" and "position"
+attributes have the same meaning as gtk_scale_add_mark() parameters of the
+same name. If the element is not empty, its content is taken as the markup
+to show at the mark. It can be translated with the usual "translatable and
+"context" attributes.
+</para>
+
<!-- ##### SECTION See_Also ##### -->
<para>
@@ -39,9 +49,9 @@ the accessor functions.
</para>
- scale:
- value:
- Returns:
+ scale:
+ value:
+ Returns:
<!-- ##### ARG GtkScale:digits ##### -->
<para>
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
index b738d6d..87aa469 100644
--- a/gtk/gtkscale.c
+++ b/gtk/gtkscale.c
@@ -38,6 +38,8 @@
#include "gtkbindings.h"
#include "gtkprivate.h"
#include "gtkintl.h"
+#include "gtkbuildable.h"
+#include "gtkbuilderprivate.h"
#include "gtkalias.h"
@@ -56,7 +58,7 @@ typedef struct _GtkScaleMark GtkScaleMark;
struct _GtkScaleMark
{
gdouble value;
- const gchar *markup;
+ gchar *markup;
GtkPositionType position;
};
@@ -110,8 +112,24 @@ static gboolean gtk_scale_expose (GtkWidget *widget,
static void gtk_scale_real_get_layout_offsets (GtkScale *scale,
gint *x,
gint *y);
+static void gtk_scale_buildable_interface_init (GtkBuildableIface *iface);
+static gboolean gtk_scale_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data);
+static void gtk_scale_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data);
+
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkScale, gtk_scale, GTK_TYPE_RANGE,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_scale_buildable_interface_init))
-G_DEFINE_ABSTRACT_TYPE (GtkScale, gtk_scale, GTK_TYPE_RANGE)
static gboolean
single_string_accumulator (GSignalInvocationHint *ihint,
@@ -1355,6 +1373,240 @@ gtk_scale_add_mark (GtkScale *scale,
gtk_widget_queue_resize (GTK_WIDGET (scale));
}
+static GtkBuildableIface *parent_buildable_iface;
+
+static void
+gtk_scale_buildable_interface_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+ iface->custom_tag_start = gtk_scale_buildable_custom_tag_start;
+ iface->custom_finished = gtk_scale_buildable_custom_finished;
+}
+
+typedef struct
+{
+ GtkScale *scale;
+ GtkBuilder *builder;
+ GSList *marks;
+} MarksSubparserData;
+
+typedef struct
+{
+ gdouble value;
+ GtkPositionType position;
+ GString *markup;
+ gchar *context;
+ gboolean translatable;
+} MarkData;
+
+static void
+mark_data_free (MarkData *data)
+{
+ g_string_free (data->markup, TRUE);
+ g_free (data->context);
+ g_slice_free (MarkData, data);
+}
+
+static void
+marks_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ MarksSubparserData *parser_data = (MarksSubparserData*)user_data;
+ guint i;
+ gint line_number, char_number;
+
+ if (strcmp (element_name, "marks") == 0)
+ ;
+ else if (strcmp (element_name, "mark") == 0)
+ {
+ gdouble value;
+ gboolean has_value = FALSE;
+ GtkPositionType position = GTK_POS_BOTTOM;
+ const gchar *msg_context = NULL;
+ gboolean translatable = FALSE;
+ MarkData *mark;
+
+ for (i = 0; names[i]; i++)
+ {
+ if (strcmp (names[i], "translatable") == 0)
+ {
+ if (!_gtk_builder_boolean_from_string (values[i], &translatable, error))
+ return;
+ }
+ else if (strcmp (names[i], "comments") == 0)
+ {
+ /* do nothing, comments are for translators */
+ }
+ else if (strcmp (names[i], "context") == 0)
+ msg_context = values[i];
+ else if (strcmp (names[i], "value") == 0)
+ {
+ GValue gvalue = { 0, };
+
+ if (!gtk_builder_value_from_string_type (parser_data->builder, G_TYPE_DOUBLE, values[i], &gvalue, error))
+ return;
+
+ value = g_value_get_double (&gvalue);
+ has_value = TRUE;
+ }
+ else if (strcmp (names[i], "position") == 0)
+ {
+ GValue gvalue = { 0, };
+
+ if (!gtk_builder_value_from_string_type (parser_data->builder, GTK_TYPE_POSITION_TYPE, values[i], &gvalue, error))
+ return;
+
+ position = g_value_get_enum (&gvalue);
+ }
+ 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], "mark");
+ return;
+ }
+ }
+
+ if (!has_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, "mark",
+ "value");
+ return;
+ }
+
+ mark = g_slice_new (MarkData);
+ mark->value = value;
+ mark->position = position;
+ mark->markup = g_string_new ("");
+ mark->context = g_strdup (msg_context);
+ mark->translatable = translatable;
+
+ parser_data->marks = g_slist_prepend (parser_data->marks, mark);
+ }
+ else
+ {
+ 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 unsupported tag for GtkScale: \"%s\"",
+ "<input>",
+ line_number, char_number, element_name);
+ return;
+ }
+}
+
+static void
+marks_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ MarksSubparserData *data = (MarksSubparserData*)user_data;
+
+ if (strcmp (g_markup_parse_context_get_element (context), "mark") == 0)
+ {
+ MarkData *mark = data->marks->data;
+
+ g_string_append_len (mark->markup, text, text_len);
+ }
+}
+
+static const GMarkupParser marks_parser =
+ {
+ marks_start_element,
+ NULL,
+ marks_text,
+ };
+
+
+static gboolean
+gtk_scale_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data)
+{
+ MarksSubparserData *parser_data;
+
+ if (child)
+ return FALSE;
+
+ if (strcmp (tagname, "marks") == 0)
+ {
+ parser_data = g_slice_new0 (MarksSubparserData);
+ parser_data->scale = GTK_SCALE (buildable);
+ parser_data->marks = NULL;
+
+ *parser = marks_parser;
+ *data = parser_data;
+ return TRUE;
+ }
+
+ return parent_buildable_iface->custom_tag_start (buildable, builder, child,
+ tagname, parser, data);
+}
+
+static void
+gtk_scale_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data)
+{
+ GtkScale *scale = GTK_SCALE (buildable);
+ MarksSubparserData *marks_data;
+ GtkWidget *toplevel;
+
+ if (strcmp (tagname, "marks") == 0)
+ {
+ GSList *m;
+ gchar *markup;
+
+ marks_data = (MarksSubparserData *)user_data;
+
+ for (m = marks_data->marks; m; m = m->next)
+ {
+ MarkData *mdata = m->data;
+
+ if (mdata->translatable && mdata->markup->len)
+ markup = _gtk_builder_parser_translate (gtk_builder_get_translation_domain (builder),
+ mdata->context,
+ mdata->markup->str);
+ else
+ markup = mdata->markup->str;
+
+ gtk_scale_add_mark (scale, mdata->value, mdata->position, markup);
+
+ mark_data_free (mdata);
+ }
+
+ g_slist_free (marks_data->marks);
+ g_slice_free (MarksSubparserData, marks_data);
+ }
+}
#define __GTK_SCALE_C__
#include "gtkaliasdef.c"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]