[clutter/wip/apocalypses/apocalypse-1: 1/43] actor: Provide add/remove child and get children methods



commit 8abd4281b65faa9994ef1b31de088327226460d4
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Thu Nov 17 15:03:32 2011 +0000

    actor: Provide add/remove child and get children methods
    
    Let's try and move away from the reverse implicit scene graph build API,
    which we mutuated from GTK+, towards a more traditional node/child API.
    
    The set_parent()/unparent() API is confusing, unless you know the
    history; having a add_child()/remove_child() methods pair makes it more
    explicit.
    
    We can easily implement the old set_parent()/unparent() pair in terms of
    the newly add_child()/remove_child() one.

 clutter/clutter-actor.c |  180 +++++++++++++++++++++++++++++------------------
 clutter/clutter-actor.h |    5 ++
 2 files changed, 116 insertions(+), 69 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 3c20406..795356b 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -8181,103 +8181,133 @@ clutter_actor_get_clip (ClutterActor *self,
 }
 
 /**
- * clutter_actor_set_parent:
- * @self: A #ClutterActor
- * @parent: A new #ClutterActor parent
+ * clutter_actor_get_children:
+ * @self: a #ClutterActor
+ *
+ * Retrieves the list of children of @self.
  *
- * Sets the parent of @self to @parent.  The opposite function is
- * clutter_actor_unparent().
+ * Return value: (transfer container) (element-type ClutterActor): A newly
+ *   allocated #GList of #ClutterActor<!-- -->s. Use g_list_free() when
+ *   done.
  *
- * This function should not be used by applications, but by custom
- * container actor subclasses.
+ * Since: 1.10
+ */
+GList *
+clutter_actor_get_children (ClutterActor *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
+
+  return g_list_copy (self->priv->children);
+}
+
+/**
+ * clutter_actor_add_child:
+ * @self: a #ClutterActor
+ * @child: a #ClutterActor
+ *
+ * Adds @child to the children of @self.
+ *
+ * This function will acquire a reference on @child.
+ *
+ * Since: 1.10
  */
 void
-clutter_actor_set_parent (ClutterActor *self,
-		          ClutterActor *parent)
+clutter_actor_add_child (ClutterActor *self,
+                         ClutterActor *child)
 {
-  ClutterActorPrivate *priv;
-  ClutterActorPrivate *parent_priv;
   ClutterTextDirection text_dir;
 
   g_return_if_fail (CLUTTER_IS_ACTOR (self));
-  g_return_if_fail (CLUTTER_IS_ACTOR (parent));
-  g_return_if_fail (self != parent);
-
-  priv = self->priv;
+  g_return_if_fail (CLUTTER_IS_ACTOR (child));
+  g_return_if_fail (self != child);
 
-  if (priv->parent_actor != NULL)
+  if (child->priv->parent_actor != NULL)
     {
       g_warning ("Cannot set a parent on an actor which has a parent.\n"
 		 "You must use clutter_actor_unparent() first.\n");
       return;
     }
 
-  if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
+  if (CLUTTER_ACTOR_IS_TOPLEVEL (child))
     {
       g_warning ("Cannot set a parent on a toplevel actor\n");
       return;
     }
 
-  if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
+  if (CLUTTER_ACTOR_IN_DESTRUCTION (child))
     {
       g_warning ("Cannot set a parent currently being destroyed");
       return;
     }
 
-  g_object_ref_sink (self);
-  priv->parent_actor = parent;
+  g_object_ref_sink (child);
+  child->priv->parent_actor = self;
 
   /* Maintain an explicit list of children for every actor... */
-  parent_priv = parent->priv;
-  parent_priv->children =
-    g_list_prepend (parent_priv->children, self);
-  parent_priv->n_children++;
+  self->priv->children = g_list_prepend (self->priv->children, child);
+  self->priv->n_children++;
 
   /* if push_internal() has been called then we automatically set
    * the flag on the actor
    */
-  if (parent->priv->internal_child)
-    CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_INTERNAL_CHILD);
+  if (self->priv->internal_child)
+    CLUTTER_SET_PRIVATE_FLAGS (child, CLUTTER_INTERNAL_CHILD);
 
   /* clutter_actor_reparent() will emit ::parent-set for us */
-  if (!CLUTTER_ACTOR_IN_REPARENT (self))
-    g_signal_emit (self, actor_signals[PARENT_SET], 0, NULL);
+  if (!CLUTTER_ACTOR_IN_REPARENT (child))
+    g_signal_emit (child, actor_signals[PARENT_SET], 0, NULL);
 
   /* If parent is mapped or realized, we need to also be mapped or
    * realized once we're inside the parent.
    */
-  clutter_actor_update_map_state (self, MAP_STATE_CHECK);
+  clutter_actor_update_map_state (child, MAP_STATE_CHECK);
 
   /* propagate the parent's text direction to the child */
-  text_dir = clutter_actor_get_text_direction (parent);
-  clutter_actor_set_text_direction (self, text_dir);
+  text_dir = clutter_actor_get_text_direction (self);
+  clutter_actor_set_text_direction (child, text_dir);
 
-  if (priv->show_on_set_parent)
-    clutter_actor_show (self);
+  if (child->priv->show_on_set_parent)
+    clutter_actor_show (child);
 
-  if (CLUTTER_ACTOR_IS_MAPPED (self))
-    clutter_actor_queue_redraw (self);
+  if (CLUTTER_ACTOR_IS_MAPPED (child))
+    clutter_actor_queue_redraw (child);
 
   /* maintain the invariant that if an actor needs layout,
    * its parents do as well
    */
-  if (priv->needs_width_request ||
-      priv->needs_height_request ||
-      priv->needs_allocation)
+  if (child->priv->needs_width_request ||
+      child->priv->needs_height_request ||
+      child->priv->needs_allocation)
     {
       /* we work around the short-circuiting we do
        * in clutter_actor_queue_relayout() since we
        * want to force a relayout
        */
-      priv->needs_width_request = TRUE;
-      priv->needs_height_request = TRUE;
-      priv->needs_allocation = TRUE;
+      child->priv->needs_width_request = TRUE;
+      child->priv->needs_height_request = TRUE;
+      child->priv->needs_allocation = TRUE;
 
-      clutter_actor_queue_relayout (priv->parent_actor);
+      clutter_actor_queue_relayout (child->priv->parent_actor);
     }
 }
 
 /**
+ * clutter_actor_set_parent:
+ * @self: A #ClutterActor
+ * @parent: A new #ClutterActor parent
+ *
+ * Sets the parent of @self to @parent.
+ *
+ * This function just calls clutter_actor_add_child().
+ */
+void
+clutter_actor_set_parent (ClutterActor *self,
+		          ClutterActor *parent)
+{
+  clutter_actor_add_child (parent, self);
+}
+
+/**
  * clutter_actor_get_parent:
  * @self: A #ClutterActor
  *
@@ -8332,35 +8362,33 @@ invalidate_queue_redraw_entry (ClutterActor *self,
 }
 
 /**
- * clutter_actor_unparent:
+ * clutter_actor_remove_child:
  * @self: a #ClutterActor
+ * @child: a #ClutterActor
  *
- * Removes the parent of @self.
- *
- * This function should not be used in applications.
+ * Removes @child from the children of @self.
  *
- * This function should only be called by implementations of the
- * #ClutterContainer interface, or by composite actors that do
- * not implicitly create their children.
+ * This function will release the reference added by
+ * clutter_actor_add_child().
  *
- * Since: 0.1.1
+ * Since: 1.10
  */
 void
-clutter_actor_unparent (ClutterActor *self)
+clutter_actor_remove_child (ClutterActor *self,
+                            ClutterActor *child)
 {
-  ClutterActorPrivate *priv;
-  ClutterActor *old_parent;
-  ClutterActorPrivate *old_parent_priv;
   gboolean was_mapped;
 
   g_return_if_fail (CLUTTER_IS_ACTOR (self));
+  g_return_if_fail (CLUTTER_IS_ACTOR (child));
 
-  priv = self->priv;
+  if (child->priv->parent_actor == NULL)
+    return;
 
-  if (priv->parent_actor == NULL)
+  if (child->priv->parent_actor != self)
     return;
 
-  was_mapped = CLUTTER_ACTOR_IS_MAPPED (self);
+  was_mapped = CLUTTER_ACTOR_IS_MAPPED (child);
 
   /* we need to unrealize *before* we set parent_actor to NULL,
    * because in an unrealize method actors are dissociating from the
@@ -8368,7 +8396,7 @@ clutter_actor_unparent (ClutterActor *self)
    * clutter_actor_get_stage(). This should unmap and unrealize,
    * unless we're reparenting.
    */
-  clutter_actor_update_map_state (self, MAP_STATE_MAKE_UNREALIZED);
+  clutter_actor_update_map_state (child, MAP_STATE_MAKE_UNREALIZED);
 
    /* We take this opportunity to invalidate any queue redraw entry
     * associated with the actor and descendants since we won't be able to
@@ -8383,31 +8411,45 @@ clutter_actor_unparent (ClutterActor *self)
     *   http://bugzilla.clutter-project.org/show_bug.cgi?id=2621
     *   https://bugzilla.gnome.org/show_bug.cgi?id=652036
     */
-  _clutter_actor_traverse (self,
+  _clutter_actor_traverse (child,
                            0,
                            invalidate_queue_redraw_entry,
                            NULL,
                            NULL);
 
-  old_parent = priv->parent_actor;
-  priv->parent_actor = NULL;
+  child->priv->parent_actor = NULL;
 
   /* clutter_actor_reparent() will emit ::parent-set for us */
-  if (!CLUTTER_ACTOR_IN_REPARENT (self))
-    g_signal_emit (self, actor_signals[PARENT_SET], 0, old_parent);
+  if (!CLUTTER_ACTOR_IN_REPARENT (child))
+    g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
 
-  old_parent_priv = old_parent->priv;
-  old_parent_priv->children = g_list_remove (old_parent_priv->children, self);
-  old_parent_priv->n_children--;
+  self->priv->children = g_list_remove (self->priv->children, child);
+  self->priv->n_children--;
 
   /* Queue a redraw on old_parent only if we were painted in the first
    * place. Will be no-op if old parent is not shown.
    */
-  if (was_mapped && !CLUTTER_ACTOR_IS_MAPPED (self))
-    clutter_actor_queue_redraw (old_parent);
+  if (was_mapped && !CLUTTER_ACTOR_IS_MAPPED (child))
+    clutter_actor_queue_redraw (self);
 
   /* remove the reference we acquired in clutter_actor_set_parent() */
-  g_object_unref (self);
+  g_object_unref (child);
+}
+
+/**
+ * clutter_actor_unparent:
+ * @self: a #ClutterActor
+ *
+ * Removes the parent of @self.
+ *
+ * This function just calls clutter_actor_remove_child().
+ *
+ * Since: 0.1.1
+ */
+void
+clutter_actor_unparent (ClutterActor *self)
+{
+  clutter_actor_remove_child (self->priv->parent_actor, self);
 }
 
 /**
diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h
index 7adabf4..6cef2cb 100644
--- a/clutter/clutter-actor.h
+++ b/clutter/clutter-actor.h
@@ -409,6 +409,11 @@ void                  clutter_actor_set_clip_to_allocation    (ClutterActor
                                                                gboolean               clip_set);
 gboolean              clutter_actor_get_clip_to_allocation    (ClutterActor          *self);
 
+void                  clutter_actor_add_child                 (ClutterActor          *self,
+                                                               ClutterActor          *child);
+void                  clutter_actor_remove_child              (ClutterActor          *self,
+                                                               ClutterActor          *child);
+GList *               clutter_actor_get_children              (ClutterActor          *self);
 void                  clutter_actor_set_parent                (ClutterActor          *self,
                                                                ClutterActor          *parent);
 ClutterActor *        clutter_actor_get_parent                (ClutterActor          *self);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]