model: Implement ClutterScriptable interface
authorBastian Winkler <buz@netbuz.org>
Thu, 25 Feb 2010 22:47:49 +0000 (23:47 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Thu, 25 Feb 2010 23:09:11 +0000 (23:09 +0000)
Allow a ClutterModel to be constructed through the ClutterScript API.
Currently this allows a model to be generated like like this:

{
  "id" : "test-model",
  "type" : "ClutterListModel",
  "columns" : [
    [ "text-column", "gchararray" ],
    [ "int-column", "gint" ],
    [ "actor-column", "ClutterRectangle" ]
  ]
}

where 'columns' is an array containing arrays of column-name,
column-type pairs.

http://bugzilla.openedhand.com/show_bug.cgi?id=2007

.gitignore
clutter/clutter-model.c
tests/conform/test-conform-main.c
tests/conform/test-model.c
tests/data/test-script-model.json [new file with mode: 0644]

index fe8c173..04d8919 100644 (file)
@@ -238,6 +238,7 @@ TAGS
 /tests/conform/test-texture-fbo
 /tests/conform/test-script-single
 /tests/conform/test-script-child
+/tests/conform/test-list-model-from-script
 /tests/conform/test-script-implicit-alpha
 /tests/conform/test-script-object-property
 /tests/conform/test-script-animation
index b8c68d5..27e0daf 100644 (file)
 #include "clutter-marshal.h"
 #include "clutter-private.h"
 #include "clutter-debug.h"
+#include "clutter-scriptable.h"
 
-G_DEFINE_ABSTRACT_TYPE (ClutterModel, clutter_model, G_TYPE_OBJECT);
+static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE
+        (ClutterModel, clutter_model, G_TYPE_OBJECT,
+         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
+                                clutter_scriptable_iface_init));
 
 enum
 {
@@ -445,6 +451,103 @@ clutter_model_check_type (GType gtype)
 }
 
 
+typedef struct {
+    gchar *name;
+    GType  type;
+} ColumnInfo;
+
+static gboolean
+clutter_model_parse_custom_node (ClutterScriptable *scriptable,
+                                 ClutterScript     *script,
+                                 GValue            *value,
+                                 const gchar       *name,
+                                 JsonNode          *node)
+{
+  GSList *columns = NULL;
+  GList *elements, *l;
+
+  if (strcmp (name, "columns") != 0)
+    return FALSE;
+
+  if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
+    return FALSE;
+
+  elements = json_array_get_elements (json_node_get_array (node));
+
+  for (l = elements; l != NULL; l = l->next)
+    {
+      JsonNode *child_node = l->data;
+      JsonArray *array = json_node_get_array (child_node);
+      ColumnInfo *cinfo;
+      const gchar *column_name;
+      const gchar *type_name;
+
+      if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY ||
+          json_array_get_length (array) != 2)
+        {
+          g_warning ("A column must be an array of "
+                     "[\"column-name\", \"GType-name\"] pairs");
+          return FALSE;
+        }
+
+      column_name = json_array_get_string_element (array, 0);
+      type_name = json_array_get_string_element (array, 1);
+
+      cinfo = g_slice_new0 (ColumnInfo);
+      cinfo->name = g_strdup (column_name);
+      cinfo->type = clutter_script_get_type_from_name (script, type_name);
+
+      columns = g_slist_prepend (columns, cinfo);
+    }
+
+  g_list_free (elements);
+
+  g_value_init (value, G_TYPE_POINTER);
+  g_value_set_pointer (value, g_slist_reverse (columns));
+
+  return TRUE;
+}
+
+static void
+clutter_model_set_custom_property (ClutterScriptable *scriptable,
+                                   ClutterScript     *script,
+                                   const gchar       *name,
+                                   const GValue      *value)
+{
+  if (strcmp (name, "columns") == 0)
+    {
+      ClutterModel *model = CLUTTER_MODEL (scriptable);
+      GSList *columns, *l;
+      guint n_columns;
+      gint i;
+
+      columns = g_value_get_pointer (value);
+      n_columns = g_slist_length (columns);
+
+      clutter_model_set_n_columns (model, n_columns, TRUE, TRUE);
+
+      for (i = 0, l = columns; l != NULL; l = l->next, i++)
+        {
+          ColumnInfo *cinfo = l->data;
+
+          clutter_model_set_column_name (model, i, cinfo->name);
+          clutter_model_set_column_type (model, i, cinfo->type);
+
+          g_free (cinfo->name);
+          g_slice_free (ColumnInfo, cinfo);
+        }
+
+      g_slist_free (columns);
+    }
+}
+
+
+static void
+clutter_scriptable_iface_init (ClutterScriptableIface *iface)
+{
+  iface->parse_custom_node = clutter_model_parse_custom_node;
+  iface->set_custom_property = clutter_model_set_custom_property;
+}
 
 /**
  * clutter_model_resort:
index df551b5..54c4fd9 100644 (file)
@@ -158,6 +158,7 @@ main (int argc, char **argv)
   TEST_CONFORM_SIMPLE ("/model", test_list_model_populate);
   TEST_CONFORM_SIMPLE ("/model", test_list_model_iterate);
   TEST_CONFORM_SIMPLE ("/model", test_list_model_filter);
+  TEST_CONFORM_SIMPLE ("/model", test_list_model_from_script);
 
   TEST_CONFORM_SIMPLE ("/color", test_color_from_string);
   TEST_CONFORM_SIMPLE ("/color", test_color_to_string);
index 45ffc64..056537e 100644 (file)
@@ -335,3 +335,37 @@ test_list_model_populate (TestConformSimpleFixture *fixture,
 
   g_object_unref (test_data.model);
 }
+
+void
+test_list_model_from_script (TestConformSimpleFixture *fixture,
+                             gconstpointer dummy)
+{
+  ClutterScript *script = clutter_script_new ();
+  GObject *model;
+  GError *error = NULL;
+  gchar *test_file;
+  const gchar *name;
+  GType type;
+
+  test_file = clutter_test_get_data_file ("test-script-model.json");
+  clutter_script_load_from_file (script, test_file, &error);
+  if (g_test_verbose () && error)
+    g_print ("Error: %s", error->message);
+  g_assert (error == NULL);
+
+  model = clutter_script_get_object (script, "test-model");
+
+  g_assert (CLUTTER_IS_MODEL (model));
+  g_assert (clutter_model_get_n_columns (CLUTTER_MODEL (model)) == 3);
+
+  name = clutter_model_get_column_name (CLUTTER_MODEL (model), 0);
+  type = clutter_model_get_column_type (CLUTTER_MODEL (model), 0);
+  g_assert (strcmp (name, "text-column") == 0);
+  g_assert (type == G_TYPE_STRING);
+
+  name = clutter_model_get_column_name (CLUTTER_MODEL (model), 2);
+  type = clutter_model_get_column_type (CLUTTER_MODEL (model), 2);
+  g_print ("type: %s\n", g_type_name (type));
+  g_assert (strcmp (name, "actor-column") == 0);
+  g_assert (type == CLUTTER_TYPE_RECTANGLE);
+}
diff --git a/tests/data/test-script-model.json b/tests/data/test-script-model.json
new file mode 100644 (file)
index 0000000..075bfbe
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "id" : "test-model",
+  "type" : "ClutterListModel",
+  "columns" : [
+    [ "text-column", "gchararray" ],
+    [ "int-column", "gint" ],
+    [ "actor-column", "ClutterRectangle" ]
+  ]
+}