script: Allow connecting signal to ClutterState states
One of the uses of a ClutterState state machine along with ClutterScript is to provide a quick way to transition from state to state in response to signal emitted on specific instances. Connecting a real function, in code, to a specific signal does not improve the ease of use of ClutterScript to define scenes. By adding a new signal definition to the current one we can have both a simple way to define application logic in code and in the UI definition file. The new syntax is trivial: { "name" : <signal name>, "state" : <state machine script id>, "target-state" : <target state> } The ClutterState instance is identified by its script id, and the target state is resolved at run-time, so it can be defined both in ClutterScript or in code. Ideally, we should find a way to associate a default ClutterState instance to the ClutterScript one that parses the definition; this way we would be able to remove the "state" member, or even "style" the behaviour of an object by replacing the ClutterState instance. The implementation uses a signal emission hook, to avoid knowing the signal signature; we check the emitter of the signal against the object that defined the signal, to avoid erroneous state changes.
This commit is contained in:
@ -560,12 +560,9 @@ parse_signals (ClutterScript *script,
|
||||
for (i = 0; i < array_len; i++)
|
||||
{
|
||||
JsonNode *val = json_array_get_element (array, i);
|
||||
SignalInfo *sinfo = NULL;
|
||||
JsonObject *object;
|
||||
SignalInfo *sinfo;
|
||||
const gchar *name;
|
||||
const gchar *handler;
|
||||
const gchar *connect;
|
||||
GConnectFlags flags = 0;
|
||||
|
||||
if (JSON_NODE_TYPE (val) != JSON_NODE_OBJECT)
|
||||
{
|
||||
@ -595,56 +592,97 @@ parse_signals (ClutterScript *script,
|
||||
}
|
||||
}
|
||||
|
||||
/* mandatory: "handler" */
|
||||
if (!json_object_has_member (object, "handler"))
|
||||
/* mandatory: "state" */
|
||||
if (json_object_has_member (object, "state"))
|
||||
{
|
||||
_clutter_script_warn_missing_attribute (script, NULL, "handler");
|
||||
continue;
|
||||
const gchar *state;
|
||||
const gchar *target;
|
||||
|
||||
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");
|
||||
if (target == NULL)
|
||||
{
|
||||
_clutter_script_warn_invalid_value (script,
|
||||
"target-state", "string",
|
||||
val);
|
||||
continue;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (SCRIPT,
|
||||
"Added signal '%s' (state:%s, target:%s)",
|
||||
name,
|
||||
state, target);
|
||||
|
||||
sinfo = g_slice_new0 (SignalInfo);
|
||||
sinfo->is_handler = FALSE;
|
||||
sinfo->name = g_strdup (name);
|
||||
sinfo->state = g_strdup (state);
|
||||
sinfo->target = g_strdup (target);
|
||||
}
|
||||
else
|
||||
|
||||
/* mandatory: "handler" */
|
||||
if (json_object_has_member (object, "handler"))
|
||||
{
|
||||
const gchar *handler;
|
||||
const gchar *connect;
|
||||
GConnectFlags flags = 0;
|
||||
|
||||
handler = json_object_get_string_member (object, "handler");
|
||||
if (!handler)
|
||||
if (handler == NULL)
|
||||
{
|
||||
_clutter_script_warn_invalid_value (script,
|
||||
"handler", "string",
|
||||
val);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* optional: "object" */
|
||||
if (json_object_has_member (object, "object"))
|
||||
connect = json_object_get_string_member (object, "object");
|
||||
else
|
||||
connect = NULL;
|
||||
|
||||
/* optional: "after" */
|
||||
if (json_object_has_member (object, "after"))
|
||||
{
|
||||
if (json_object_get_boolean_member (object, "after"))
|
||||
flags |= G_CONNECT_AFTER;
|
||||
}
|
||||
|
||||
/* optional: "swapped" */
|
||||
if (json_object_has_member (object, "swapped"))
|
||||
{
|
||||
if (json_object_get_boolean_member (object, "swapped"))
|
||||
flags |= G_CONNECT_SWAPPED;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (SCRIPT,
|
||||
"Added signal '%s' (handler:%s, object:%s, flags:%d)",
|
||||
name,
|
||||
handler, connect, flags);
|
||||
|
||||
sinfo = g_slice_new0 (SignalInfo);
|
||||
sinfo->is_handler = TRUE;
|
||||
sinfo->name = g_strdup (name);
|
||||
sinfo->handler = g_strdup (handler);
|
||||
sinfo->object = g_strdup (connect);
|
||||
sinfo->flags = flags;
|
||||
}
|
||||
|
||||
/* optional: "object" */
|
||||
if (json_object_has_member (object, "object"))
|
||||
connect = json_object_get_string_member (object, "object");
|
||||
if (sinfo != NULL)
|
||||
retval = g_list_prepend (retval, sinfo);
|
||||
else
|
||||
connect = NULL;
|
||||
|
||||
/* optional: "after" */
|
||||
if (json_object_has_member (object, "after"))
|
||||
{
|
||||
if (json_object_get_boolean_member (object, "after"))
|
||||
flags |= G_CONNECT_AFTER;
|
||||
}
|
||||
|
||||
/* optional: "swapped" */
|
||||
if (json_object_has_member (object, "swapped"))
|
||||
{
|
||||
if (json_object_get_boolean_member (object, "swapped"))
|
||||
flags |= G_CONNECT_SWAPPED;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (SCRIPT,
|
||||
"Parsing signal '%s' (handler:%s, object:%s, flags:%d)",
|
||||
name,
|
||||
handler, connect, flags);
|
||||
|
||||
sinfo = g_slice_new0 (SignalInfo);
|
||||
sinfo->name = g_strdup (name);
|
||||
sinfo->handler = g_strdup (handler);
|
||||
sinfo->object = g_strdup (connect);
|
||||
sinfo->flags = flags;
|
||||
|
||||
retval = g_list_prepend (retval, sinfo);
|
||||
_clutter_script_warn_missing_attribute (script,
|
||||
NULL,
|
||||
"handler or state");
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
Reference in New Issue
Block a user