[gtk+/composite-templates: 17/17] Renamed <template> tag with <external-object> and keep <template> tag for new inline type definition



commit 13870e733cb1ea7ad7449e53b13434189e609a41
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Mon Dec 10 11:23:01 2012 -0300

    Renamed <template> tag with <external-object> and keep <template> tag for new inline type definitions

 gtk/gtkbuilderparser.c  |  163 +++++++++++++++++++++++++++++------------------
 gtk/gtkbuilderprivate.h |    3 +-
 gtk/gtkcontainer.c      |    5 +-
 gtk/tests/builder.c     |  134 +++++++++++++++++++-------------------
 4 files changed, 172 insertions(+), 133 deletions(-)
---
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index 6ddd210..ebb7f05 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 025dfdf..f2aa6a1 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 90b800c..8ea8b7a 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 7a516df..30eb86c 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();
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]