mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 11:32:04 +00:00
model: Add support to define rows in ClutterScript
This adds a custom "rows" property, that allows to define the rows of a ClutterModel. A single row can either an array of all columns or an object with column-name : column-value pairs. http://bugzilla.clutter-project.org/show_bug.cgi?id=2528
This commit is contained in:
parent
95b3a718ef
commit
6bffd407fd
@ -117,13 +117,19 @@
|
||||
* <refsect2 id="ClutterModel-script">
|
||||
* <title>ClutterModel custom properties for #ClutterScript</title>
|
||||
* <para>#ClutterModel defines a custom property "columns" for #ClutterScript
|
||||
* which allows defining the column names and types.</para>
|
||||
* <example id="ClutterModel-script-column-example">
|
||||
* <title>Example of the "columns" custom property</title>
|
||||
* which allows defining the column names and types. It also defines a custom
|
||||
* "rows" property which allows filling the #ClutterModel with some
|
||||
* data.</para>
|
||||
* <example id="ClutterModel-script-example">
|
||||
* <title>Example of the "columns" and "rows" custom properties</title>
|
||||
* <para>The definition below will create a #ClutterListModel with three
|
||||
* columns: the first one with name "Name" and containing strings; the
|
||||
* second one with name "Score" and containing integers; the third one with
|
||||
* name "Icon" and containing #ClutterTexture<!-- -->s.</para>
|
||||
* name "Icon" and containing #ClutterTexture<!-- -->s. The model is filled
|
||||
* with three rows. A row can be defined either with an array that holds
|
||||
* all columns of a row, or an object that holds "column-name" :
|
||||
* "column-value" pairs.
|
||||
* </para>
|
||||
* <programlisting>
|
||||
* {
|
||||
* "type" : "ClutterListModel",
|
||||
@ -132,6 +138,11 @@
|
||||
* [ "Name", "gchararray" ],
|
||||
* [ "Score", "gint" ],
|
||||
* [ "Icon", "ClutterTexture" ]
|
||||
* ],
|
||||
* "rows" : [
|
||||
* [ "Team 1", 42, { "type" : "ClutterTexture", "filename" : "team1.png" } ],
|
||||
* [ "Team 2", 23, "team2-icon-script-id" ],
|
||||
* { "Name" : "Team 3", "Icon" : "team3-icon-script-id" }
|
||||
* ]
|
||||
* }
|
||||
* </programlisting>
|
||||
@ -157,6 +168,7 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-scriptable.h"
|
||||
#include "clutter-script-private.h"
|
||||
|
||||
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
||||
|
||||
@ -528,49 +540,73 @@ clutter_model_parse_custom_node (ClutterScriptable *scriptable,
|
||||
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)
|
||||
if (strcmp (name, "columns") == 0)
|
||||
{
|
||||
JsonNode *child_node = l->data;
|
||||
JsonArray *array = json_node_get_array (child_node);
|
||||
ColumnInfo *cinfo;
|
||||
const gchar *column_name;
|
||||
const gchar *type_name;
|
||||
GSList *columns = NULL;
|
||||
GList *elements, *l;
|
||||
|
||||
if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY ||
|
||||
json_array_get_length (array) != 2)
|
||||
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)
|
||||
{
|
||||
g_warning ("A column must be an array of "
|
||||
"[\"column-name\", \"GType-name\"] pairs");
|
||||
return FALSE;
|
||||
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);
|
||||
}
|
||||
|
||||
column_name = json_array_get_string_element (array, 0);
|
||||
type_name = json_array_get_string_element (array, 1);
|
||||
g_list_free (elements);
|
||||
|
||||
cinfo = g_slice_new0 (ColumnInfo);
|
||||
cinfo->name = g_strdup (column_name);
|
||||
cinfo->type = clutter_script_get_type_from_name (script, type_name);
|
||||
g_value_init (value, G_TYPE_POINTER);
|
||||
g_value_set_pointer (value, g_slist_reverse (columns));
|
||||
|
||||
columns = g_slist_prepend (columns, cinfo);
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (name, "rows") == 0)
|
||||
{
|
||||
GSList *rows = NULL;
|
||||
GList *elements, *l;
|
||||
|
||||
g_list_free (elements);
|
||||
if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
|
||||
return FALSE;
|
||||
|
||||
g_value_init (value, G_TYPE_POINTER);
|
||||
g_value_set_pointer (value, g_slist_reverse (columns));
|
||||
/*
|
||||
* at this point we have no information about the column types, so
|
||||
* we just copy the json elements and resolve them in the
|
||||
* set_custom_property method
|
||||
*/
|
||||
elements = json_array_get_elements (json_node_get_array (node));
|
||||
for (l = elements; l != NULL; l = l->next)
|
||||
rows = g_slist_prepend (rows, json_node_copy (l->data));
|
||||
g_list_free (elements);
|
||||
|
||||
return TRUE;
|
||||
g_value_init (value, G_TYPE_POINTER);
|
||||
g_value_set_pointer (value, g_slist_reverse (rows));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -604,6 +640,110 @@ clutter_model_set_custom_property (ClutterScriptable *scriptable,
|
||||
|
||||
g_slist_free (columns);
|
||||
}
|
||||
else if (strcmp (name, "rows") == 0)
|
||||
{
|
||||
ClutterModel *model = CLUTTER_MODEL (scriptable);
|
||||
GSList *rows, *l;
|
||||
guint n_columns, row = 0;
|
||||
|
||||
rows = g_value_get_pointer (value);
|
||||
n_columns = clutter_model_get_n_columns (model);
|
||||
|
||||
for (l = rows; l; l = l->next)
|
||||
{
|
||||
JsonNode *node = l->data;
|
||||
guint *columns, i, n_values = 0;
|
||||
GValueArray *values;
|
||||
|
||||
if (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY)
|
||||
{
|
||||
JsonArray *array = json_node_get_array (node);
|
||||
if (json_array_get_length (array) != n_columns)
|
||||
{
|
||||
g_warning ("Row %d contains the wrong count of columns",
|
||||
g_slist_position (rows, l) + 1);
|
||||
row++;
|
||||
continue;
|
||||
}
|
||||
|
||||
n_values = n_columns;
|
||||
columns = g_new (guint, n_values);
|
||||
values = g_value_array_new (n_values);
|
||||
|
||||
for (i = 0; i < n_values; i++)
|
||||
{
|
||||
GType column_type;
|
||||
const gchar *column_name;
|
||||
GValue v = { 0, };
|
||||
|
||||
column_type = clutter_model_get_column_type (model, i);
|
||||
column_name = clutter_model_get_column_name (model, i);
|
||||
columns[i] = i;
|
||||
g_value_init (&v, column_type);
|
||||
clutter_script_parse_node (script, &v, column_name,
|
||||
json_array_get_element (array, i),
|
||||
NULL);
|
||||
g_value_array_append (values, &v);
|
||||
g_value_unset (&v);
|
||||
}
|
||||
}
|
||||
else if (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT)
|
||||
{
|
||||
JsonObject *object = json_node_get_object (node);
|
||||
GList *members, *m;
|
||||
guint column = 0;
|
||||
|
||||
n_values = json_object_get_size (object);
|
||||
columns = g_new (guint, n_values);
|
||||
values = g_value_array_new (n_values);
|
||||
|
||||
members = json_object_get_members (object);
|
||||
for (m = members; m; m = m->next)
|
||||
{
|
||||
const gchar *mname = m->data;
|
||||
|
||||
for (i = 0; i < clutter_model_get_n_columns (model); i++)
|
||||
{
|
||||
const gchar *cname;
|
||||
|
||||
cname = clutter_model_get_column_name (model, i);
|
||||
if (strcmp (mname, cname) == 0)
|
||||
{
|
||||
JsonNode *member;
|
||||
GType col_type;
|
||||
const gchar *col_name;
|
||||
GValue v = { 0, };
|
||||
|
||||
col_type = clutter_model_get_column_type (model, i);
|
||||
col_name = clutter_model_get_column_name (model, i);
|
||||
columns[column] = i;
|
||||
g_value_init (&v, col_type);
|
||||
member = json_object_get_member (object, mname);
|
||||
clutter_script_parse_node (script, &v,
|
||||
col_name, member,
|
||||
NULL);
|
||||
g_value_array_append (values, &v);
|
||||
g_value_unset (&v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
column++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
row++;
|
||||
continue;
|
||||
}
|
||||
|
||||
clutter_model_insertv (model, row, n_values, columns, values->values);
|
||||
g_value_array_free (values);
|
||||
g_free (columns);
|
||||
json_node_free (node);
|
||||
row++;
|
||||
}
|
||||
g_slist_free (rows);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -363,6 +363,8 @@ test_list_model_from_script (TestConformSimpleFixture *fixture,
|
||||
gchar *test_file;
|
||||
const gchar *name;
|
||||
GType type;
|
||||
ClutterModelIter *iter;
|
||||
GValue value = { 0, };
|
||||
|
||||
test_file = clutter_test_get_data_file ("test-script-model.json");
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
@ -397,4 +399,37 @@ test_list_model_from_script (TestConformSimpleFixture *fixture,
|
||||
|
||||
g_assert (strcmp (name, "actor-column") == 0);
|
||||
g_assert (type == CLUTTER_TYPE_RECTANGLE);
|
||||
|
||||
g_assert (clutter_model_get_n_rows (CLUTTER_MODEL (model)) == 3);
|
||||
|
||||
iter = clutter_model_get_iter_at_row (CLUTTER_MODEL (model), 0);
|
||||
clutter_model_iter_get_value (iter, 0, &value);
|
||||
g_assert (G_VALUE_HOLDS_STRING (&value));
|
||||
g_assert (strcmp (g_value_get_string (&value), "text-row-1") == 0);
|
||||
g_value_unset (&value);
|
||||
|
||||
clutter_model_iter_get_value (iter, 1, &value);
|
||||
g_assert (G_VALUE_HOLDS_INT (&value));
|
||||
g_assert (g_value_get_int (&value) == 1);
|
||||
g_value_unset (&value);
|
||||
|
||||
clutter_model_iter_get_value (iter, 2, &value);
|
||||
g_assert (G_VALUE_HOLDS_OBJECT (&value));
|
||||
g_assert (g_value_get_object (&value) == NULL);
|
||||
g_value_unset (&value);
|
||||
|
||||
iter = clutter_model_iter_next (iter);
|
||||
clutter_model_iter_get_value (iter, 2, &value);
|
||||
g_assert (G_VALUE_HOLDS_OBJECT (&value));
|
||||
g_assert (CLUTTER_IS_RECTANGLE (g_value_get_object (&value)));
|
||||
g_value_unset (&value);
|
||||
|
||||
iter = clutter_model_iter_next (iter);
|
||||
clutter_model_iter_get_value (iter, 2, &value);
|
||||
g_assert (G_VALUE_HOLDS_OBJECT (&value));
|
||||
g_assert (CLUTTER_IS_RECTANGLE (g_value_get_object (&value)));
|
||||
g_assert (strcmp (clutter_actor_get_name (g_value_get_object (&value)),
|
||||
"actor-row-3") == 0);
|
||||
g_value_unset (&value);
|
||||
g_object_unref (iter);
|
||||
}
|
||||
|
@ -5,5 +5,13 @@
|
||||
[ "text-column", "gchararray" ],
|
||||
[ "int-column", "gint" ],
|
||||
[ "actor-column", "ClutterRectangle" ]
|
||||
],
|
||||
"rows" : [
|
||||
[ "text-row-1", 1, null ],
|
||||
[ "text-row-2", 2, { "type" : "ClutterRectangle", "color" : "blue" } ],
|
||||
{
|
||||
"int-column" : 3,
|
||||
"actor-column" : { "type" : "ClutterRectangle", "name" : "actor-row-3" }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user