summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <juanpablougarte@gmail.com>2012-12-10 11:23:01 -0300
committerJuan Pablo Ugarte <juanpablougarte@gmail.com>2012-12-10 11:24:47 -0300
commit13870e733cb1ea7ad7449e53b13434189e609a41 (patch)
tree5797131eae54f96c879ecc2ca71f7e336f91938d
parente0ce659f342e8e485a245ea40a34ff37bfbd2720 (diff)
downloadgtk+-13870e733cb1ea7ad7449e53b13434189e609a41.tar.gz
Renamed <template> tag with <external-object> and keep <template> tag for new inline type definitions
-rw-r--r--gtk/gtkbuilderparser.c163
-rw-r--r--gtk/gtkbuilderprivate.h3
-rw-r--r--gtk/gtkcontainer.c5
-rw-r--r--gtk/tests/builder.c134
4 files changed, 172 insertions, 133 deletions
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index 6ddd2108fb..ebb7f056c7 100644
--- a/gtk/gtkbuilderparser.c
+++ b/gtk/gtkbuilderparser.c
@@ -447,7 +447,8 @@ parse_object (GMarkupParseContext *context,
return;
}
}
- else if (data->template_level && !data->template_object)
+ else if ((data->in_external_object && !data->external_object) ||
+ data->template_level)
return;
object_info = g_slice_new0 (ObjectInfo);
@@ -683,10 +684,8 @@ parse_signal (ParserData *data,
typedef struct
{
- const gchar *tmpl_class, *tmpl_id;
-
- gboolean tmpl_found, done;
-
+ const gchar *tmpl_class;
+ gboolean found, done, in_tmpl;
GString *xml;
} TemplateParseData;
@@ -705,21 +704,26 @@ extract_template_start_element (GMarkupParseContext *context,
if (g_strcmp0 (element_name, "template") == 0)
{
- gboolean right_class = FALSE, right_id = FALSE;
-
for (i = 0; attribute_names[i]; i++)
{
if (!g_strcmp0 (attribute_names[i], "class"))
- right_class = (g_strcmp0 (attribute_values[i], state->tmpl_class) == 0);
- else if (!g_strcmp0 (attribute_names[i], "id"))
- right_id = (g_strcmp0 (attribute_values[i], state->tmpl_id) == 0);
+ state->found = (g_strcmp0 (attribute_values[i], state->tmpl_class) == 0);
}
- if (right_class && right_id)
- state->tmpl_found = TRUE;
+ if (state->found)
+ {
+ state->in_tmpl = TRUE;
+ g_string_append_printf (state->xml, "<external-object class=\"%s\" id=\"%s\">",
+ state->tmpl_class,
+ state->tmpl_class);
+ return;
+ }
+ else
+ g_string_append_printf (state->xml, "<%s", element_name);
}
+ else
+ g_string_append_printf (state->xml, "<%s", element_name);
- g_string_append_printf (state->xml, "<%s", element_name);
for (i = 0; attribute_names[i]; i++)
{
g_string_append_printf (state->xml, " %s=\"%s\"",
@@ -737,10 +741,16 @@ extract_template_end_element (GMarkupParseContext *context,
TemplateParseData *state = user_data;
if (state->done) return;
-
- g_string_append_printf (state->xml, "</%s>", element_name);
- if (g_strcmp0 (element_name, "interface") == 0 && state->tmpl_found)
+ if (g_strcmp0 (element_name, "template") == 0 && state->in_tmpl)
+ {
+ state->in_tmpl = FALSE;
+ g_string_append (state->xml, "</external-object>");
+ }
+ else
+ g_string_append_printf (state->xml, "</%s>", element_name);
+
+ if (g_strcmp0 (element_name, "interface") == 0 && state->found)
state->done = TRUE;
}
@@ -759,10 +769,10 @@ extract_template_text (GMarkupParseContext *context,
}
static gchar *
-extract_template (const gchar *buffer, const gchar *class_name, const gchar *class_id)
+extract_template (const gchar *buffer, const gchar *class_name)
{
GMarkupParser parser = { extract_template_start_element, extract_template_end_element, extract_template_text };
- TemplateParseData state = { class_name, class_id, FALSE, FALSE, g_string_new ("")};
+ TemplateParseData state = { class_name, FALSE, FALSE, FALSE, g_string_new ("")};
GMarkupParseContext *context;
context = g_markup_parse_context_new (&parser,
@@ -790,20 +800,19 @@ typedef struct
{
GTypeInfo *info;
gchar *tmpl;
- gchar *id;
} TmplClassData;
static void
composite_template_derived_class_init (gpointer g_class, gpointer class_data)
{
TmplClassData *data = class_data;
- gtk_container_class_set_template_from_string (g_class, data->tmpl, data->id);
+ gtk_container_class_set_template_from_string (g_class, data->tmpl,
+ G_OBJECT_CLASS_NAME (g_class));
}
static GType
create_inline_type (GType parent_type,
const gchar *class_name,
- const gchar *class_id,
const gchar *template_xml)
{
TmplClassData *tmpl;
@@ -814,8 +823,7 @@ create_inline_type (GType parent_type,
tmpl = g_new0 (TmplClassData, 1);
tmpl->info = info = g_new0 (GTypeInfo, 1);
- tmpl->tmpl = extract_template (template_xml, class_name, class_id);
- tmpl->id = g_strdup (class_id);
+ tmpl->tmpl = extract_template (template_xml, class_name);
info->class_size = query.class_size;
info->class_init = composite_template_derived_class_init;
@@ -834,9 +842,8 @@ parse_template (ParserData *data,
{
const gchar *parent_class = NULL;
const gchar *class_name = NULL;
- const gchar *id = NULL;
const GSList *l, *p;
- GObject *parent;
+ GType parent_type;
gint i;
data->template_level++;
@@ -856,6 +863,61 @@ parse_template (ParserData *data,
class_name = values[i];
else if (strcmp (names[i], "parent") == 0)
parent_class = values[i];
+ else
+ {
+ error_invalid_attribute (data, element_name, names[i], error);
+ return;
+ }
+ }
+
+ if (!class_name)
+ {
+ error_missing_attribute (data, element_name, "class", error);
+ return;
+ }
+
+ if (!parent_class)
+ {
+ error_missing_attribute (data, element_name, "parent", error);
+ return;
+ }
+
+ if (g_type_from_name (class_name))
+ {
+ error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
+ element_name, "template class '%s' already registered", class_name);
+ return;
+ }
+
+ if (!(parent_type = gtk_builder_get_type_from_name (data->builder, parent_class)))
+ {
+ error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
+ element_name, "invalid parent class type found '%s'", parent_class);
+ return;
+ }
+
+ /* Generate inline type */
+ create_inline_type (parent_type, class_name, data->buffer);
+}
+
+static void
+parse_external_object (ParserData *data,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ GError **error)
+{
+ const gchar *class_name = NULL;
+ const gchar *id = NULL;
+ GObject *parent;
+ gint i;
+
+ data->in_external_object = TRUE;
+
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (strcmp (names[i], "class") == 0)
+ class_name = values[i];
else if (strcmp (names[i], "id") == 0)
id = values[i];
else
@@ -898,18 +960,9 @@ parse_template (ParserData *data,
return;
}
- if (parent_class &&
- !g_type_is_a (class_type, g_type_from_name (parent_class)))
- {
- error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
- element_name, "class %s should derive from parent %s",
- class_name, parent_class);
- return;
- }
-
/* push parent to build its children from the template */
object_info = g_slice_new0 (ObjectInfo);
- object_info->object = data->template_object = parent;
+ object_info->object = data->external_object = parent;
object_info->object_type = parent_type;
object_info->id = g_strdup (_gtk_builder_object_get_name (parent));
object_info->tag.name = "object";
@@ -918,27 +971,6 @@ parse_template (ParserData *data,
parser_add_object_id (data, object_info->id, error);
}
- else if (parent_class)
- {
- GType parent_type;
-
- if (g_type_from_name (class_name))
- {
- error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
- element_name, "template class '%s' already registered", class_name);
- return;
- }
-
- if (!(parent_type = gtk_builder_get_type_from_name (data->builder, parent_class)))
- {
- error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
- element_name, "invalid parent class type found '%s'", parent_class);
- return;
- }
-
- /* Generate inline type */
- create_inline_type (parent_type, class_name, id, data->buffer);
- }
}
/* Called by GtkBuilder */
@@ -1188,10 +1220,13 @@ start_element (GMarkupParseContext *context,
parse_requires (data, element_name, names, values, error);
else if (strcmp (element_name, "template") == 0)
parse_template (data, element_name, names, values, error);
+ else if (strcmp (element_name, "external-object") == 0)
+ parse_external_object (data, element_name, names, values, error);
else if (strcmp (element_name, "object") == 0)
parse_object (context, data, element_name, names, values, error);
else if ((data->requested_objects && !data->inside_requested_object) ||
- (data->template_level && !data->template_object))
+ (data->in_external_object && !data->external_object) ||
+ data->template_level)
{
/* If outside a requested object, simply ignore this tag */
return;
@@ -1280,9 +1315,12 @@ end_element (GMarkupParseContext *context,
else if (strcmp (element_name, "template") == 0)
{
data->template_level--;
-
- /* Yes its a template! */
- if (data->template_object)
+ }
+ else if (strcmp (element_name, "external-object") == 0)
+ {
+ data->in_external_object = FALSE;
+
+ if (data->external_object)
{
ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
@@ -1295,11 +1333,12 @@ end_element (GMarkupParseContext *context,
_gtk_builder_add_signals (data->builder, object_info->signals);
free_object_info (object_info);
- data->template_object = NULL;
+ data->external_object = NULL;
}
}
else if ((data->requested_objects && !data->inside_requested_object) ||
- (data->template_level && !data->template_object))
+ (data->in_external_object && !data->external_object) ||
+ data->template_level)
{
/* If outside a requested object or template, simply ignore this tag */
return;
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
index 025dfdf418..f2aa6a1307 100644
--- a/gtk/gtkbuilderprivate.h
+++ b/gtk/gtkbuilderprivate.h
@@ -109,7 +109,8 @@ typedef struct {
GHashTable *object_ids;
- GObject *template_object;
+ GObject *external_object;
+ gint in_external_object;
gint template_level;
} ParserData;
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 90b800cd5f..8ea8b7aa8e 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -1471,9 +1471,8 @@ gtk_container_class_set_template_from_string (GtkContainerClass *container_class
* Instances with an assigned template will have their children built at object
* construct time.
*
- * The provided xml is expected to have a <template> tag instead of <object>
- * with id=@template_id and an extra 'parent' property specifying from which type
- * the new class derives from.
+ * The provided xml is expected to have a <external-object> tag instead of
+ * <object> with id=@template_id.
*
* Since: 3.8
*/
diff --git a/gtk/tests/builder.c b/gtk/tests/builder.c
index 7a516df2ab..30eb86c9b0 100644
--- a/gtk/tests/builder.c
+++ b/gtk/tests/builder.c
@@ -2715,8 +2715,58 @@ test_level_bar (void)
g_object_unref (builder);
}
+static GObject *external_object = NULL, *external_object_swapped = NULL;
+
+void
+on_button_clicked (GtkButton *button, GObject *data)
+{
+ external_object = data;
+}
+
+void
+on_button_clicked_swapped (GObject *data, GtkButton *button)
+{
+ external_object_swapped = data;
+}
+
static void
-test_template_real (gboolean use_add_objects)
+test_expose_object (void)
+{
+ GtkBuilder *builder;
+ GError *error = NULL;
+ GtkWidget *image;
+ GObject *obj;
+ const gchar buffer[] =
+ "<interface>"
+ " <object class=\"GtkButton\" id=\"button\">"
+ " <property name=\"image\">external_image</property>"
+ " <signal name=\"clicked\" handler=\"on_button_clicked\" object=\"builder\" swapped=\"no\"/>"
+ " <signal name=\"clicked\" handler=\"on_button_clicked_swapped\" object=\"builder\"/>"
+ " </object>"
+ "</interface>";
+
+ image = gtk_image_new ();
+ builder = gtk_builder_new ();
+ gtk_builder_expose_object (builder, "external_image", G_OBJECT (image));
+ gtk_builder_expose_object (builder, "builder", G_OBJECT (builder));
+ gtk_builder_add_from_string (builder, buffer, -1, &error);
+ g_assert (error == NULL);
+
+ obj = gtk_builder_get_object (builder, "button");
+ g_assert (GTK_IS_BUTTON (obj));
+
+ g_assert (gtk_button_get_image (GTK_BUTTON (obj)) == image);
+
+ /* Connect signals and fake clicked event */
+ gtk_builder_connect_signals (builder, NULL);
+ gtk_button_clicked (GTK_BUTTON (obj));
+
+ g_assert (external_object == G_OBJECT (builder));
+ g_assert (external_object_swapped == G_OBJECT (builder));
+}
+
+static void
+test_external_object_real (gboolean use_add_objects)
{
GError *error = NULL;
GtkBuilder *builder;
@@ -2726,25 +2776,25 @@ test_template_real (gboolean use_add_objects)
guint padding = 0;
const gchar buffer[] =
"<interface>\n"
- " <template class=\"GtkGrid\" id=\"mygrid\">\n"
+ " <external-object class=\"GtkGrid\" id=\"mygrid\">\n"
" <property name=\"visible\">True</property>\n"
" <child>\n"
" <object class=\"GtkLabel\" id=\"gridlabel\">\n"
" <property name=\"visible\">True</property>\n"
" </object>\n"
" </child>\n"
- " </template>\n"
- /* This template should get ignored */
- " <template class=\"GtkGrid\" id=\"mygrid2\">\n"
+ " </external-object>\n"
+ /* This external_object should get ignored */
+ " <external-object class=\"GtkGrid\" id=\"mygrid2\">\n"
" <property name=\"visible\">True</property>\n"
" <child>\n"
" <object class=\"GtkLabel\" id=\"grid2label\">\n"
" <property name=\"visible\">True</property>\n"
" </object>\n"
" </child>\n"
- " </template>\n"
- /* This is the template we are interested in! */
- " <template class=\"GtkBox\" id=\"mybox\">\n"
+ " </external-object>\n"
+ /* This is the external_object we are interested in! */
+ " <external-object class=\"GtkBox\" id=\"mybox\">\n"
" <property name=\"visible\">True</property>\n"
" <property name=\"can_focus\">False</property>\n"
" <property name=\"orientation\">vertical</property>\n"
@@ -2776,7 +2826,7 @@ test_template_real (gboolean use_add_objects)
" <property name=\"position\">1</property>\n"
" </packing>\n"
" </child>\n"
- " </template>\n"
+ " </external-object>\n"
" <object class=\"GtkWindow\" id=\"window\">"
" <child>\n"
" <object class=\"GtkLabel\" id=\"winlabel\">\n"
@@ -2805,7 +2855,7 @@ test_template_real (gboolean use_add_objects)
/* Check if requested object creation works */
g_assert (GTK_IS_WINDOW (gtk_builder_get_object (builder, "window")));
- /* Templates should be ignored if we requested a specific object */
+ /* external objects should be ignored if we requested a specific object */
g_assert (gtk_builder_get_object (builder, "winlabel"));
}
else
@@ -2839,20 +2889,20 @@ test_template_real (gboolean use_add_objects)
}
static void
-test_template (void)
+test_external_object (void)
{
- test_template_real (FALSE);
- test_template_real (TRUE);
+ test_external_object_real (FALSE);
+ test_external_object_real (TRUE);
}
static void
-test_inline_template ()
+test_template ()
{
GError *error = NULL;
GtkBuilder *builder;
const gchar buffer[] =
"<interface>\n"
- " <template class=\"MyGtkGrid\" parent=\"GtkGrid\" id=\"mygrid_tmpl\">\n"
+ " <template class=\"MyGtkGrid\" parent=\"GtkGrid\">\n"
" <property name=\"visible\">True</property>\n"
" <child>\n"
" <object class=\"GtkLabel\" id=\"gridlabel\">\n"
@@ -2892,56 +2942,6 @@ test_inline_template ()
g_object_unref (builder);
}
-static GObject *external_object = NULL, *external_object_swapped = NULL;
-
-void
-on_button_clicked (GtkButton *button, GObject *data)
-{
- external_object = data;
-}
-
-void
-on_button_clicked_swapped (GObject *data, GtkButton *button)
-{
- external_object_swapped = data;
-}
-
-static void
-test_expose_object (void)
-{
- GtkBuilder *builder;
- GError *error = NULL;
- GtkWidget *image;
- GObject *obj;
- const gchar buffer[] =
- "<interface>"
- " <object class=\"GtkButton\" id=\"button\">"
- " <property name=\"image\">external_image</property>"
- " <signal name=\"clicked\" handler=\"on_button_clicked\" object=\"builder\" swapped=\"no\"/>"
- " <signal name=\"clicked\" handler=\"on_button_clicked_swapped\" object=\"builder\"/>"
- " </object>"
- "</interface>";
-
- image = gtk_image_new ();
- builder = gtk_builder_new ();
- gtk_builder_expose_object (builder, "external_image", G_OBJECT (image));
- gtk_builder_expose_object (builder, "builder", G_OBJECT (builder));
- gtk_builder_add_from_string (builder, buffer, -1, &error);
- g_assert (error == NULL);
-
- obj = gtk_builder_get_object (builder, "button");
- g_assert (GTK_IS_BUTTON (obj));
-
- g_assert (gtk_button_get_image (GTK_BUTTON (obj)) == image);
-
- /* Connect signals and fake clicked event */
- gtk_builder_connect_signals (builder, NULL);
- gtk_button_clicked (GTK_BUTTON (obj));
-
- g_assert (external_object == G_OBJECT (builder));
- g_assert (external_object_swapped == G_OBJECT (builder));
-}
-
int
main (int argc, char **argv)
{
@@ -2990,9 +2990,9 @@ main (int argc, char **argv)
g_test_add_func ("/Builder/MessageDialog", test_message_dialog);
g_test_add_func ("/Builder/GMenu", test_gmenu);
g_test_add_func ("/Builder/LevelBar", test_level_bar);
- g_test_add_func ("/Builder/Template", test_template);
- g_test_add_func ("/Builder/Inline Template", test_inline_template);
g_test_add_func ("/Builder/Expose Object", test_expose_object);
+ g_test_add_func ("/Builder/External Object", test_external_object);
+ g_test_add_func ("/Builder/Template", test_template);
return g_test_run();
}