model: Implement ClutterScriptable interface

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
This commit is contained in:
Bastian Winkler 2010-02-25 23:47:49 +01:00 committed by Emmanuele Bassi
parent 63279f827e
commit 96c31bbf0e
5 changed files with 149 additions and 1 deletions

1
.gitignore vendored
View 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

View File

@ -132,8 +132,14 @@
#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:

View 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);

View 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);
}

View File

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