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">
|
* <refsect2 id="ClutterModel-script">
|
||||||
* <title>ClutterModel custom properties for #ClutterScript</title>
|
* <title>ClutterModel custom properties for #ClutterScript</title>
|
||||||
* <para>#ClutterModel defines a custom property "columns" for #ClutterScript
|
* <para>#ClutterModel defines a custom property "columns" for #ClutterScript
|
||||||
* which allows defining the column names and types.</para>
|
* which allows defining the column names and types. It also defines a custom
|
||||||
* <example id="ClutterModel-script-column-example">
|
* "rows" property which allows filling the #ClutterModel with some
|
||||||
* <title>Example of the "columns" custom property</title>
|
* 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
|
* <para>The definition below will create a #ClutterListModel with three
|
||||||
* columns: the first one with name "Name" and containing strings; the
|
* columns: the first one with name "Name" and containing strings; the
|
||||||
* second one with name "Score" and containing integers; the third one with
|
* 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>
|
* <programlisting>
|
||||||
* {
|
* {
|
||||||
* "type" : "ClutterListModel",
|
* "type" : "ClutterListModel",
|
||||||
@ -132,6 +138,11 @@
|
|||||||
* [ "Name", "gchararray" ],
|
* [ "Name", "gchararray" ],
|
||||||
* [ "Score", "gint" ],
|
* [ "Score", "gint" ],
|
||||||
* [ "Icon", "ClutterTexture" ]
|
* [ "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>
|
* </programlisting>
|
||||||
@ -157,6 +168,7 @@
|
|||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-debug.h"
|
#include "clutter-debug.h"
|
||||||
#include "clutter-scriptable.h"
|
#include "clutter-scriptable.h"
|
||||||
|
#include "clutter-script-private.h"
|
||||||
|
|
||||||
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
||||||
|
|
||||||
@ -528,12 +540,11 @@ clutter_model_parse_custom_node (ClutterScriptable *scriptable,
|
|||||||
const gchar *name,
|
const gchar *name,
|
||||||
JsonNode *node)
|
JsonNode *node)
|
||||||
{
|
{
|
||||||
|
if (strcmp (name, "columns") == 0)
|
||||||
|
{
|
||||||
GSList *columns = NULL;
|
GSList *columns = NULL;
|
||||||
GList *elements, *l;
|
GList *elements, *l;
|
||||||
|
|
||||||
if (strcmp (name, "columns") != 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
|
if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -571,6 +582,31 @@ clutter_model_parse_custom_node (ClutterScriptable *scriptable,
|
|||||||
g_value_set_pointer (value, g_slist_reverse (columns));
|
g_value_set_pointer (value, g_slist_reverse (columns));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (strcmp (name, "rows") == 0)
|
||||||
|
{
|
||||||
|
GSList *rows = NULL;
|
||||||
|
GList *elements, *l;
|
||||||
|
|
||||||
|
if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
g_value_init (value, G_TYPE_POINTER);
|
||||||
|
g_value_set_pointer (value, g_slist_reverse (rows));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -604,6 +640,110 @@ clutter_model_set_custom_property (ClutterScriptable *scriptable,
|
|||||||
|
|
||||||
g_slist_free (columns);
|
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;
|
gchar *test_file;
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
GType type;
|
GType type;
|
||||||
|
ClutterModelIter *iter;
|
||||||
|
GValue value = { 0, };
|
||||||
|
|
||||||
test_file = clutter_test_get_data_file ("test-script-model.json");
|
test_file = clutter_test_get_data_file ("test-script-model.json");
|
||||||
clutter_script_load_from_file (script, test_file, &error);
|
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 (strcmp (name, "actor-column") == 0);
|
||||||
g_assert (type == CLUTTER_TYPE_RECTANGLE);
|
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" ],
|
[ "text-column", "gchararray" ],
|
||||||
[ "int-column", "gint" ],
|
[ "int-column", "gint" ],
|
||||||
[ "actor-column", "ClutterRectangle" ]
|
[ "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…
x
Reference in New Issue
Block a user