script: Allow resolving signals states added from code

Currently, defining states for object signals can only be done by
defining a ClutterState inside the ClutterScript definition. We should
allow creating a (named) ClutterState in code, and associating it to a
ClutterScript instance — and have the Script resolve the "state" field
of a signal definition correctly.
This commit is contained in:
Emmanuele Bassi 2011-06-10 17:16:45 +01:00
parent e745ce52e7
commit 29d7c5a297
3 changed files with 125 additions and 55 deletions

View File

@ -592,20 +592,11 @@ parse_signals (ClutterScript *script,
} }
} }
/* mandatory: "state" */ /* mandatory: "target-state" or "handler" */
if (json_object_has_member (object, "state")) if (json_object_has_member (object, "target-state"))
{ {
const gchar *state; const gchar *state = NULL;
const gchar *target; const gchar *target = NULL;
state = json_object_get_string_member (object, "state");
if (state == NULL)
{
_clutter_script_warn_invalid_value (script,
"state", "string",
val);
continue;
}
target = json_object_get_string_member (object, "target-state"); target = json_object_get_string_member (object, "target-state");
if (target == NULL) if (target == NULL)
@ -616,10 +607,13 @@ parse_signals (ClutterScript *script,
continue; continue;
} }
if (json_object_has_member (object, "state"))
state = json_object_get_string_member (object, "state");
CLUTTER_NOTE (SCRIPT, CLUTTER_NOTE (SCRIPT,
"Added signal '%s' (state:%s, target:%s)", "Added signal '%s' (state:%s, target:%s)",
name, name,
state, target); state != NULL ? state : "<default>", target);
sinfo = g_slice_new0 (SignalInfo); sinfo = g_slice_new0 (SignalInfo);
sinfo->is_handler = FALSE; sinfo->is_handler = FALSE;
@ -627,9 +621,7 @@ parse_signals (ClutterScript *script,
sinfo->state = g_strdup (state); sinfo->state = g_strdup (state);
sinfo->target = g_strdup (target); sinfo->target = g_strdup (target);
} }
else if (json_object_has_member (object, "handler"))
/* mandatory: "handler" */
if (json_object_has_member (object, "handler"))
{ {
const gchar *handler; const gchar *handler;
const gchar *connect; const gchar *connect;
@ -676,13 +668,12 @@ parse_signals (ClutterScript *script,
sinfo->object = g_strdup (connect); sinfo->object = g_strdup (connect);
sinfo->flags = flags; sinfo->flags = flags;
} }
if (sinfo != NULL)
retval = g_list_prepend (retval, sinfo);
else else
_clutter_script_warn_missing_attribute (script, _clutter_script_warn_missing_attribute (script,
NULL, NULL,
"handler or state"); "handler or state");
if (sinfo != NULL)
retval = g_list_prepend (retval, sinfo);
} }
return retval; return retval;

View File

@ -231,6 +231,8 @@ struct _ClutterScriptPrivate
ClutterScriptParser *parser; ClutterScriptParser *parser;
GHashTable *states;
gchar **search_paths; gchar **search_paths;
gchar *filename; gchar *filename;
@ -337,6 +339,7 @@ clutter_script_finalize (GObject *gobject)
g_hash_table_destroy (priv->objects); g_hash_table_destroy (priv->objects);
g_strfreev (priv->search_paths); g_strfreev (priv->search_paths);
g_free (priv->filename); g_free (priv->filename);
g_hash_table_destroy (priv->states);
G_OBJECT_CLASS (clutter_script_parent_class)->finalize (gobject); G_OBJECT_CLASS (clutter_script_parent_class)->finalize (gobject);
} }
@ -427,6 +430,9 @@ clutter_script_init (ClutterScript *script)
priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal, priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, NULL,
object_info_free); object_info_free);
priv->states = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify) g_object_unref);
} }
/** /**
@ -987,14 +993,22 @@ connect_each_object (gpointer key,
} }
else else
{ {
GObject *state_object; GObject *state_object = NULL;
const gchar *signal_name, *signal_detail; const gchar *signal_name, *signal_detail;
gchar **components; gchar **components;
GQuark signal_quark; GQuark signal_quark;
guint signal_id; guint signal_id;
HookData *hook_data; HookData *hook_data;
if (sinfo->state == NULL)
state_object = (GObject *) clutter_script_get_state (script, NULL);
else
{
state_object = clutter_script_get_object (script, sinfo->state); state_object = clutter_script_get_object (script, sinfo->state);
if (state_object == NULL)
state_object = (GObject *) clutter_script_get_state (script, sinfo->state);
}
if (state_object == NULL) if (state_object == NULL)
continue; continue;
@ -1254,6 +1268,66 @@ clutter_script_list_objects (ClutterScript *script)
return retval; return retval;
} }
/**
* clutter_script_add_state:
* @script: a #ClutterScript
* @state_name: (allow-none): a name for the @state, or %NULL to
* set the default #ClutterState
*
* Adds a #ClutterState using the given name to the #ClutterScript instance.
*
* The #ClutterScript instance will use @state to resolve target states when
* connecting signal handlers.
*
* The #ClutterScript instance will take a reference on the #ClutterState
* passed to this function.
*
* Since: 1.8
*/
void
clutter_script_add_state (ClutterScript *script,
const gchar *state_name,
ClutterState *state)
{
g_return_if_fail (CLUTTER_IS_SCRIPT (script));
g_return_if_fail (CLUTTER_IS_STATE (state));
if (state_name == NULL || *state_name == '\0')
state_name = "__clutter_script_default_state";
g_hash_table_replace (script->priv->states,
g_strdup (state_name),
g_object_ref (state));
}
/**
* clutter_script_get_state:
* @script: a #ClutterScript
* @state_name: (allow-none): the name of the #ClutterState, or %NULL
*
* Retrieves the #ClutterState for the given @state_name.
*
* If @state_name is %NULL, this function will return the default
* #ClutterState instance.
*
* Return value: (transfer none): a pointer to the #ClutterState for the
* given name. The #ClutterState is owned by the #ClutterScript instance
* and it should not be unreferenced
*
* Since: 1.8
*/
ClutterState *
clutter_script_get_state (ClutterScript *script,
const gchar *state_name)
{
g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL);
if (state_name == NULL || *state_name == '\0')
state_name = "__clutter_script_default_state";
return g_hash_table_lookup (script->priv->states, state_name);
}
/* /*
* _clutter_script_generate_fake_id: * _clutter_script_generate_fake_id:
* @script: a #ClutterScript * @script: a #ClutterScript

View File

@ -28,7 +28,8 @@
#ifndef __CLUTTER_SCRIPT_H__ #ifndef __CLUTTER_SCRIPT_H__
#define __CLUTTER_SCRIPT_H__ #define __CLUTTER_SCRIPT_H__
#include <glib-object.h> #include <clutter/clutter-types.h>
#include <clutter/clutter-state.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -145,7 +146,7 @@ struct _ClutterScriptClass
GType clutter_script_get_type (void) G_GNUC_CONST; GType clutter_script_get_type (void) G_GNUC_CONST;
ClutterScript *clutter_script_new (void); ClutterScript * clutter_script_new (void);
guint clutter_script_load_from_file (ClutterScript *script, guint clutter_script_load_from_file (ClutterScript *script,
const gchar *filename, const gchar *filename,
GError **error); GError **error);
@ -160,15 +161,15 @@ gint clutter_script_get_objects (ClutterScript *script,
const gchar *first_name, const gchar *first_name,
...) G_GNUC_NULL_TERMINATED; ...) G_GNUC_NULL_TERMINATED;
GList * clutter_script_list_objects (ClutterScript *script); GList * clutter_script_list_objects (ClutterScript *script);
void clutter_script_unmerge_objects (ClutterScript *script, void clutter_script_unmerge_objects (ClutterScript *script,
guint merge_id); guint merge_id);
void clutter_script_ensure_objects (ClutterScript *script); void clutter_script_ensure_objects (ClutterScript *script);
GType clutter_script_get_type_from_name (ClutterScript *script, void clutter_script_add_state (ClutterScript *script,
const gchar *type_name); const gchar *state_name,
ClutterState *state);
const gchar * clutter_get_script_id (GObject *gobject); ClutterState * clutter_script_get_state (ClutterScript *script,
const gchar *state_name);
void clutter_script_connect_signals (ClutterScript *script, void clutter_script_connect_signals (ClutterScript *script,
gpointer user_data); gpointer user_data);
@ -181,6 +182,10 @@ void clutter_script_add_search_paths (ClutterScript *script,
gsize n_paths); gsize n_paths);
gchar * clutter_script_lookup_filename (ClutterScript *script, gchar * clutter_script_lookup_filename (ClutterScript *script,
const gchar *filename) G_GNUC_MALLOC; const gchar *filename) G_GNUC_MALLOC;
GType clutter_script_get_type_from_name (ClutterScript *script,
const gchar *type_name);
const gchar * clutter_get_script_id (GObject *gobject);
G_END_DECLS G_END_DECLS