2007-10-10 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/json/json-parser.c: Use the commodity JsonNode API
	and accept bare values as root nodes.

	* clutter/clutter-script-private.h:
	* clutter/clutter-script.c: Unreference the created objects
	only if they are top-levels, like ClutterBehaviour and
	ClutterTimelines. Actors have floating references, so we
	just transfer ownership to their containers, and the stage
	is owned by the backend. Add the "type_func" key to the
	object definition, so the user can supply its own GType
	function if the class name doesn't follow the GObject rules.
	Document the ClutterScript public API.
This commit is contained in:
Emmanuele Bassi 2007-10-10 10:42:19 +00:00
parent 8faf9b9964
commit 7aa52af5dd
7 changed files with 183 additions and 54 deletions

View File

@ -1,3 +1,18 @@
2007-10-10 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/json/json-parser.c: Use the commodity JsonNode API
and accept bare values as root nodes.
* clutter/clutter-script-private.h:
* clutter/clutter-script.c: Unreference the created objects
only if they are top-levels, like ClutterBehaviour and
ClutterTimelines. Actors have floating references, so we
just transfer ownership to their containers, and the stage
is owned by the backend. Add the "type_func" key to the
object definition, so the user can supply its own GType
function if the class name doesn't follow the GObject rules.
Document the ClutterScript public API.
2007-10-10 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.c:

View File

@ -34,8 +34,9 @@ G_BEGIN_DECLS
typedef GType (* GTypeGetFunc) (void);
typedef struct {
gchar *class_name;
gchar *id;
gchar *class_name;
gchar *type_func;
GList *properties;
GList *children;
@ -43,6 +44,8 @@ typedef struct {
GType gtype;
GObject *object;
guint is_toplevel : 1;
} ObjectInfo;
typedef struct {

View File

@ -83,6 +83,18 @@
* }
* </programlisting>
*
* And then to apply a defined behaviour to an actor defined inside the
* definition of an actor, the "behaviour" member can be used:
*
* <programlisting>
* {
* "id" : "my-rotating-actor",
* "type" : "ClutterTexture",
* ...
* "behaviours" : [ "rotate-behaviour" ]
* }
* </programlisting>
*
* #ClutterScript is available since Clutter 0.6
*/
@ -130,6 +142,22 @@ G_DEFINE_TYPE (ClutterScript, clutter_script, G_TYPE_OBJECT);
static void object_info_free (gpointer data);
static GType
resolve_type (const gchar *symbol)
{
static GModule *module = NULL;
GTypeGetFunc func;
GType gtype = G_TYPE_INVALID;
if (!module)
module = g_module_open (NULL, 0);
if (g_module_symbol (module, symbol, (gpointer)&func))
gtype = func ();
return gtype;
}
/* tries to map a name in camel case into the corresponding get_type()
* function, e.g.:
*
@ -306,6 +334,7 @@ construct_timeline (ClutterScript *script,
retval = CLUTTER_TIMELINE (clutter_script_construct_object (script, oinfo));
/* it needs to survive */
g_object_ref (retval);
object_info_free (oinfo);
@ -536,6 +565,7 @@ json_object_end (JsonParser *parser,
JsonNode *val;
GList *members, *l;
/* ignore any non-named object */
if (!json_object_has_member (object, "id"))
return;
@ -555,6 +585,14 @@ json_object_end (JsonParser *parser,
val = json_object_get_member (object, "type");
oinfo->class_name = json_node_dup_string (val);
if (json_object_has_member (object, "type_func"))
{
val = json_object_get_member (object, "type_func");
oinfo->type_func = json_node_dup_string (val);
}
oinfo->is_toplevel = FALSE;
members = json_object_get_members (object);
for (l = members; l; l = l->next)
{
@ -708,6 +746,9 @@ translate_property (ClutterScript *script,
retval = TRUE;
break;
case G_TYPE_ENUM:
/* enumeration values can be expressed using the nick field
* of GEnumValue or the actual integer value
*/
if (G_VALUE_HOLDS (src, G_TYPE_STRING))
{
const gchar *string = g_value_get_string (src);
@ -736,6 +777,9 @@ translate_property (ClutterScript *script,
return retval;
}
/* translates the PropertyInfo structure into a GParameter array to
* be fed to g_object_newv()
*/
static void
translate_properties (ClutterScript *script,
ObjectInfo *oinfo,
@ -923,7 +967,11 @@ clutter_script_construct_object (ClutterScript *script,
if (oinfo->gtype == G_TYPE_INVALID)
{
oinfo->gtype = resolve_type_lazily (oinfo->class_name);
if (oinfo->type_func)
oinfo->gtype = resolve_type (oinfo->type_func);
else
oinfo->gtype = resolve_type_lazily (oinfo->class_name);
if (oinfo->gtype == G_TYPE_INVALID)
return NULL;
}
@ -958,6 +1006,10 @@ clutter_script_construct_object (ClutterScript *script,
if (CLUTTER_IS_ACTOR (oinfo->object) && oinfo->behaviours)
apply_behaviours (script, CLUTTER_ACTOR (oinfo->object), oinfo->behaviours);
if (CLUTTER_IS_BEHAVIOUR (oinfo->object) ||
CLUTTER_IS_TIMELINE (oinfo->object))
oinfo->is_toplevel = TRUE;
if (oinfo->id)
g_object_set_data_full (oinfo->object, "clutter-script-name",
g_strdup (oinfo->id),
@ -995,8 +1047,9 @@ object_info_free (gpointer data)
ObjectInfo *oinfo = data;
GList *l;
g_free (oinfo->class_name);
g_free (oinfo->id);
g_free (oinfo->class_name);
g_free (oinfo->type_func);
for (l = oinfo->properties; l; l = l->next)
{
@ -1014,7 +1067,7 @@ object_info_free (gpointer data)
g_list_foreach (oinfo->behaviours, (GFunc) g_free, NULL);
g_list_free (oinfo->behaviours);
if (oinfo->object)
if (oinfo->is_toplevel && oinfo->object)
g_object_unref (oinfo->object);
g_slice_free (ObjectInfo, oinfo);
@ -1066,12 +1119,40 @@ clutter_script_init (ClutterScript *script)
object_info_free);
}
/**
* clutter_script_new:
*
* Creates a new #ClutterScript instance. #ClutterScript can be used
* to load objects definitions for scenegraph elements, like actors,
* or behavioural elements, like behaviours and timelines. The
* definitions must be encoded using the JavaScript Object Notation (JSON)
* language.
*
* Return value: the newly created #ClutterScript instance. Use
* g_object_unref() when done.
*
* Since: 0.6
*/
ClutterScript *
clutter_script_new (void)
{
return g_object_new (CLUTTER_TYPE_SCRIPT, NULL);
}
/**
* clutter_script_load_from_file:
* @script: a #ClutterScript
* @filename: the full path to the definition file
* @error: return location for a #GError, or %NULL
*
* Loads the definitions from @filename into @script and merges with
* the currently loaded ones, if any.
*
* Return value: on error, zero is returned and @error is set
* accordingly. On success, a positive integer is returned.
*
* Since: 0.6
*/
guint
clutter_script_load_from_file (ClutterScript *script,
const gchar *filename,
@ -1102,6 +1183,22 @@ clutter_script_load_from_file (ClutterScript *script,
return priv->last_merge_id;
}
/**
* clutter_script_load_from_data:
* @script: a #ClutterScript
* @data: a buffer containing the definitions
* @length: the length of the buffer, or -1 if @data is a NUL-terminated
* buffer
* @error: return location for a #GError, or %NULL
*
* Loads the definitions from @data into @script and merges with
* the currently loaded ones, if any.
*
* Return value: on error, zero is returned and @error is set
* accordingly. On success, a positive integer is returned.
*
* Since: 0.6
*/
guint
clutter_script_load_from_data (ClutterScript *script,
const gchar *data,
@ -1133,6 +1230,19 @@ clutter_script_load_from_data (ClutterScript *script,
return priv->last_merge_id;
}
/**
* clutter_script_get_object:
* @script: a #ClutterScript
* @name: the name of the object to retrieve
*
* Retrieves the object bound to @name. This function does not increment
* the reference count of the returned object.
*
* Return value: the named object, or %NULL if no object with the
* given name was available
*
* Since: 0.6
*/
GObject *
clutter_script_get_object (ClutterScript *script,
const gchar *name)
@ -1169,6 +1279,20 @@ clutter_script_get_objects_valist (ClutterScript *script,
return g_list_reverse (retval);
}
/**
* clutter_script_get_objects:
* @script: a #ClutterScript
* @first_name: the name of the first object to retrieve
* @Varargs: a %NULL-terminated list of names
*
* Retrieves a list of objects for the given names. This function does
* not increment the reference count of the returned objects.
*
* Return value: a newly allocated #GList containing the found objects,
* or %NULL. Use g_list_free() when done using it.
*
* Since: 0.6
*/
GList *
clutter_script_get_objects (ClutterScript *script,
const gchar *first_name,

View File

@ -343,7 +343,6 @@ json_parse_array (JsonParser *parser,
while (token != G_TOKEN_RIGHT_BRACE)
{
JsonNode *node = NULL;
GValue value = { 0, };
if (token == G_TOKEN_COMMA)
{
@ -421,44 +420,25 @@ json_parse_array (JsonParser *parser,
switch (token)
{
case G_TOKEN_INT:
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, scanner->value.v_int);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_int (node, scanner->value.v_int);
break;
case G_TOKEN_FLOAT:
g_value_init (&value, G_TYPE_DOUBLE);
g_value_set_double (&value, scanner->value.v_float);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_double (node, scanner->value.v_float);
break;
case G_TOKEN_STRING:
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, scanner->value.v_string);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_string (node, scanner->value.v_string);
break;
case JSON_TOKEN_TRUE:
case JSON_TOKEN_FALSE:
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, token == JSON_TOKEN_TRUE ? TRUE : FALSE);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_boolean (node, token == JSON_TOKEN_TRUE ? TRUE
: FALSE);
break;
case JSON_TOKEN_NULL:
@ -515,7 +495,6 @@ json_parse_object (JsonParser *parser,
{
JsonNode *node = NULL;
gchar *name = NULL;
GValue value = { 0, };
if (token == G_TOKEN_COMMA)
{
@ -621,44 +600,25 @@ json_parse_object (JsonParser *parser,
switch (token)
{
case G_TOKEN_INT:
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, scanner->value.v_int);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_int (node, scanner->value.v_int);
break;
case G_TOKEN_FLOAT:
g_value_init (&value, G_TYPE_DOUBLE);
g_value_set_double (&value, scanner->value.v_float);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_double (node, scanner->value.v_float);
break;
case G_TOKEN_STRING:
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, scanner->value.v_string);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_string (node, scanner->value.v_string);
break;
case JSON_TOKEN_TRUE:
case JSON_TOKEN_FALSE:
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, token == JSON_TOKEN_TRUE ? TRUE : FALSE);
node = json_node_new (JSON_NODE_VALUE);
json_node_set_value (node, &value);
g_value_unset (&value);
json_node_set_boolean (node, token == JSON_TOKEN_TRUE ? TRUE
: FALSE);
break;
case JSON_TOKEN_NULL:
@ -713,6 +673,25 @@ json_parse_statement (JsonParser *parser,
priv->root = priv->current_node = json_node_new (JSON_NODE_NULL);
return G_TOKEN_NONE;
case JSON_TOKEN_TRUE:
case JSON_TOKEN_FALSE:
priv->root = priv->current_node = json_node_new (JSON_NODE_VALUE);
json_node_set_boolean (priv->current_node,
token == JSON_TOKEN_TRUE ? TRUE : FALSE);
return G_TOKEN_NONE;
case G_TOKEN_INT:
case G_TOKEN_FLOAT:
case G_TOKEN_STRING:
priv->root = priv->current_node = json_node_new (JSON_NODE_VALUE);
if (token == G_TOKEN_INT)
json_node_set_int (priv->current_node, scanner->value.v_int);
else if (token == G_TOKEN_FLOAT)
json_node_set_double (priv->current_node, scanner->value.v_float);
else
json_node_set_string (priv->current_node, scanner->value.v_string);
return G_TOKEN_NONE;
default:
g_scanner_get_next_token (scanner);
return G_TOKEN_SYMBOL;

View File

@ -1,3 +1,9 @@
2007-10-10 Emmanuele Bassi <ebassi@openedhand.com>
* clutter.types:
* Makefile.am: Add ClutterScript and ignore clutter-script-private.h
to avoid picking up private symbols.
2007-08-21 Emmanuele Bassi <ebassi@openedhand.com>
* clutter-sections.txt: Move ClutterStage and ClutterStageClass

View File

@ -54,6 +54,7 @@ IGNORE_HFILES=\
clutter-keysyms.h \
clutter-keysyms-table.h \
clutter-enum-types.h \
clutter-script-private.h \
stamp-clutter-enum-types.h \
stamp-clutter-marshal.h \
cogl \

View File

@ -24,3 +24,4 @@ clutter_entry_get_type
clutter_box_get_type
clutter_hbox_get_type
clutter_vbox_get_type
clutter_script_get_type