script: Let ClutterActor parse behaviours
authorEmmanuele Bassi <ebassi@linux.intel.com>
Fri, 9 Jul 2010 13:59:32 +0000 (14:59 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Fri, 9 Jul 2010 13:59:32 +0000 (14:59 +0100)
Up until now, the "behaviours" member of an actor definition was parsed
by the ClutterScript parser itself - even though it's not strictly
necessary.

In an effort to minimize the ad hoc code in the Script parser, we should
let ClutterActor handle all the special cases that involve
actor-specific members.

clutter/clutter-actor.c
clutter/clutter-script-parser.c
clutter/clutter-script-private.h
clutter/clutter-script.c

index 1036344..16caeda 100644 (file)
 #include "clutter-action.h"
 #include "clutter-actor-meta-private.h"
 #include "clutter-animatable.h"
+#include "clutter-behaviour.h"
 #include "clutter-constraint.h"
 #include "clutter-container.h"
 #include "clutter-debug.h"
@@ -8340,6 +8341,40 @@ parse_actor_metas (ClutterScript *script,
   return g_slist_reverse (retval);
 }
 
+static GSList *
+parse_behaviours (ClutterScript *script,
+                  ClutterActor  *actor,
+                  JsonNode      *node)
+{
+  GList *elements, *l;
+  GSList *retval = NULL;
+
+  if (!JSON_NODE_HOLDS_ARRAY (node))
+    return NULL;
+
+  elements = json_array_get_elements (json_node_get_array (node));
+
+  for (l = elements; l != NULL; l = l->next)
+    {
+      JsonNode *element = l->data;
+      const gchar *id = _clutter_script_get_id_from_node (element);
+      GObject *behaviour;
+
+      if (id == NULL || *id == '\0')
+        continue;
+
+      behaviour = clutter_script_get_object (script, id);
+      if (behaviour == NULL)
+        continue;
+
+      retval = g_slist_prepend (retval, behaviour);
+    }
+
+  g_list_free (elements);
+
+  return g_slist_reverse (retval);
+}
+
 static gboolean
 clutter_actor_parse_custom_node (ClutterScriptable *scriptable,
                                  ClutterScript     *script,
@@ -8398,6 +8433,17 @@ clutter_actor_parse_custom_node (ClutterScriptable *scriptable,
       else
         g_slice_free (RotationInfo, info);
     }
+  else if (strcmp (name, "behaviours") == 0)
+    {
+      GSList *l;
+
+      l = parse_behaviours (script, actor, node);
+
+      g_value_init (value, G_TYPE_POINTER);
+      g_value_set_pointer (value, l);
+
+      retval = TRUE;
+    }
   else if (strcmp (name, "actions") == 0 ||
            strcmp (name, "constraints") == 0 ||
            strcmp (name, "effects") == 0)
@@ -8457,6 +8503,26 @@ clutter_actor_set_custom_property (ClutterScriptable *scriptable,
       return;
     }
 
+  if (strcmp (name, "behaviours") == 0)
+    {
+      GSList *behaviours, *l;
+
+      if (!G_VALUE_HOLDS (value, G_TYPE_POINTER))
+        return;
+
+      behaviours = g_value_get_pointer (value);
+      for (l = behaviours; l != NULL; l = l->next)
+        {
+          ClutterBehaviour *behaviour = l->data;
+
+          clutter_behaviour_apply (behaviour, actor);
+        }
+
+      g_slist_free (behaviours);
+
+      return;
+    }
+
   if (strcmp (name, "actions") == 0 ||
       strcmp (name, "constraints") == 0 ||
       strcmp (name, "effects") == 0)
index f2bfd3f..0fe8416 100644 (file)
@@ -35,7 +35,6 @@
 #include <gmodule.h>
 
 #include "clutter-actor.h"
-#include "clutter-behaviour.h"
 #include "clutter-container.h"
 #include "clutter-debug.h"
 #include "clutter-enum-types.h"
@@ -651,35 +650,6 @@ parse_signals (ClutterScript *script,
   return retval;
 }
 
-static GList *
-parse_behaviours (ObjectInfo *oinfo,
-                  JsonNode   *node)
-{
-  JsonArray *array;
-  GList *retval;
-  guint array_len, i;
-
-  if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
-    return NULL;
-
-  retval = oinfo->behaviours;
-
-  array = json_node_get_array (node);
-  array_len = json_array_get_length (array);
-
-  for (i = 0; i < array_len; i++)
-    {
-      JsonNode *child = json_array_get_element (array, i);
-      const gchar *id;
-
-      id = _clutter_script_get_id_from_node (child);
-      if (id)
-        retval = g_list_prepend (retval, g_strdup (id));
-    }
-
-  return g_list_reverse (retval);
-}
-
 static ClutterTimeline *
 construct_timeline (ClutterScript *script,
                     JsonObject    *object)
@@ -983,14 +953,6 @@ clutter_script_parser_object_end (JsonParser *json_parser,
       json_object_remove_member (object, "children");
     }
 
-  if (json_object_has_member (object, "behaviours"))
-    {
-      val = json_object_get_member (object, "behaviours");
-      oinfo->behaviours = parse_behaviours (oinfo, val);
-
-      json_object_remove_member (object, "behaviours");
-    }
-
   if (json_object_has_member (object, "signals"))
     {
       val = json_object_get_member (object, "signals");
@@ -1741,46 +1703,6 @@ apply_child_properties (ClutterScript    *script,
 }
 
 static void
-apply_behaviours (ClutterScript *script,
-                  ObjectInfo    *oinfo)
-{
-  ClutterActor *actor = CLUTTER_ACTOR (oinfo->object);
-  GList *l, *unresolved;
-
-  unresolved = NULL;
-  for (l = oinfo->behaviours; l != NULL; l = l->next)
-    {
-      const gchar *name = l->data;
-      ObjectInfo *behaviour_info;
-      GObject *object = NULL;
-
-      behaviour_info = _clutter_script_get_object_info (script, name);
-      if (behaviour_info != NULL)
-        {
-          _clutter_script_construct_object (script, behaviour_info);
-          object = behaviour_info->object;
-        }
-
-      if (object == NULL)
-        {
-          unresolved = g_list_prepend (unresolved, g_strdup (name));
-          continue;
-        }
-
-      CLUTTER_NOTE (SCRIPT, "Applying behaviour '%s' to actor of type '%s'",
-                    name,
-                    g_type_name (G_OBJECT_TYPE (actor)));
-
-      clutter_behaviour_apply (CLUTTER_BEHAVIOUR (object), actor);
-    }
-
-  g_list_foreach (oinfo->behaviours, (GFunc) g_free, NULL);
-  g_list_free (oinfo->behaviours);
-
-  oinfo->behaviours = unresolved;
-}
-
-static void
 add_children (ClutterScript *script,
               ObjectInfo    *oinfo)
 {
@@ -1839,9 +1761,6 @@ _clutter_script_check_unresolved (ClutterScript *script,
   if (oinfo->children != NULL && CLUTTER_IS_CONTAINER (oinfo->object))
     add_children (script, oinfo);
 
-  if (oinfo->behaviours != NULL && CLUTTER_IS_ACTOR (oinfo->object))
-    apply_behaviours (script, oinfo);
-
   /* this is a bit *eugh*, but it allows us to effectively make sure
    * that child and layout properties are parsed and applied to the
    * right child
@@ -1885,7 +1804,7 @@ _clutter_script_check_unresolved (ClutterScript *script,
         }
     }
 
-  if (oinfo->properties || oinfo->children || oinfo->behaviours)
+  if (oinfo->properties || oinfo->children)
     oinfo->has_unresolved = TRUE;
   else
     oinfo->has_unresolved = FALSE;
index 0b03d13..f69410c 100644 (file)
@@ -58,7 +58,6 @@ typedef struct {
 
   GList *properties;
   GList *children;
-  GList *behaviours;
   GList *signals;
 
   GType gtype;
index a286b72..92f0865 100644 (file)
@@ -308,9 +308,6 @@ object_info_free (gpointer data)
       g_list_foreach (oinfo->children, (GFunc) g_free, NULL);
       g_list_free (oinfo->children);
 
-      g_list_foreach (oinfo->behaviours, (GFunc) g_free, NULL);
-      g_list_free (oinfo->behaviours);
-
       /* we unref top-level objects and leave the actors alone,
        * unless we are unmerging in which case we have to destroy
        * the actor to unparent them