[clutter/wip/layout-children: 2/2] actor: Add ClutterActorClass.layout_children()



commit 15a35675c45fede8f8d76b40856a9e7fc29528b4
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Nov 28 09:54:49 2012 +0000

    actor: Add ClutterActorClass.layout_children()
    
    The allocate() virtual is far too complex, and it has far too many
    things that can possibly go wrong:
    
      - it needs to be chained up, to store the allocation of the actor;
        - unless you call set_allocation() to do that;
      - you can override it;
        - but you can also have a layout manager delegate;
      - you have to allocate() all the children after you chained up;
      - you may get signals mid-way through the allocation process;
      - you get a non-normalized box;
        - unless you're using a layout manager, which will get a
          normalized one.
    
    Let's try to keep this stuff simple, and minimize the amount of things
    to remember to get it right.
    
    First of all, we add a new virtual, called layout_children(); it gets
    passed the actor itself, and it will be called only if the actor has
    children to lay out. Its default implementation will call the layout
    manager's allocation method, if one is set. Inside the layout_children()
    virtual, you will need to iterate over the children, compute their
    bounds and call clutter_actor_allocate(), similarly to how you implement
    a paint() virtual. The layout_children() virtual is called after the
    allocation of the actor has been stored, so it's possible to safely
    query it without hitting slow code paths. You do not need to chain up,
    and you do not need to normalize boxes. All the signals and property
    notifications on the parent will happen before the layout_children()
    virtual has been called, so the actor's state is stable by the time you
    call allocate() on the children.

 clutter/clutter-actor.c |   81 +++++++++++++++++++++++------------------------
 clutter/clutter-actor.h |    4 ++-
 2 files changed, 43 insertions(+), 42 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 35658e6..b430c24 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -2417,13 +2417,45 @@ static void clutter_actor_real_allocate (ClutterActor           *self,
                                          const ClutterActorBox  *box,
                                          ClutterAllocationFlags  flags);
 
+static void
+clutter_actor_real_layout_children (ClutterActor *self)
+{
+  ClutterActorPrivate *priv = self->priv;
+
+  if (priv->layout_manager != NULL)
+    {
+      ClutterContainer *container = CLUTTER_CONTAINER (self);
+      ClutterActorBox children_box;
+
+      /* normalize the box passed to the layout manager */
+      children_box.x1 = children_box.y1 = 0.f;
+      children_box.x2 = (allocation->x2 - allocation->x1);
+      children_box.y2 = (allocation->y2 - allocation->y1);
+
+      CLUTTER_NOTE (LAYOUT,
+                    "Allocating %d children of %s "
+                    "at { %.2f, %.2f - %.2f x %.2f } "
+                    "using %s",
+                    priv->n_children,
+                    _clutter_actor_get_debug_name (self),
+                    allocation->x1,
+                    allocation->y1,
+                    (allocation->x2 - allocation->x1),
+                    (allocation->y2 - allocation->y1),
+                    G_OBJECT_TYPE_NAME (priv->layout_manager));
+
+      clutter_layout_manager_allocate (priv->layout_manager,
+                                       container,
+                                       &children_box,
+                                       CLUTTER_ALLOCATION_NONE);
+    }
+}
+
 static inline void
 clutter_actor_maybe_layout_children (ClutterActor           *self,
                                      const ClutterActorBox  *allocation,
                                      ClutterAllocationFlags  flags)
 {
-  ClutterActorPrivate *priv = self->priv;
-
   /* this is going to be a bit hard to follow, so let's put an explanation
    * here.
    *
@@ -2456,50 +2488,16 @@ clutter_actor_maybe_layout_children (ClutterActor           *self,
    */
 
   if (CLUTTER_ACTOR_GET_CLASS (self)->allocate == clutter_actor_real_allocate)
-    goto check_layout;
+    goto layout_children;
 
   if ((flags & CLUTTER_DELEGATE_LAYOUT) != 0)
-    goto check_layout;
+    goto layout_children;
 
   return;
 
-check_layout:
-  if (priv->n_children != 0 &&
-      priv->layout_manager != NULL)
-    {
-      ClutterContainer *container = CLUTTER_CONTAINER (self);
-      ClutterAllocationFlags children_flags;
-      ClutterActorBox children_box;
-
-      /* normalize the box passed to the layout manager */
-      children_box.x1 = children_box.y1 = 0.f;
-      children_box.x2 = (allocation->x2 - allocation->x1);
-      children_box.y2 = (allocation->y2 - allocation->y1);
-
-      /* remove the DELEGATE_LAYOUT flag; this won't be passed to
-       * the actor's children, since it refers only to the current
-       * actor's allocation.
-       */
-      children_flags = flags;
-      children_flags &= ~CLUTTER_DELEGATE_LAYOUT;
-
-      CLUTTER_NOTE (LAYOUT,
-                    "Allocating %d children of %s "
-                    "at { %.2f, %.2f - %.2f x %.2f } "
-                    "using %s",
-                    priv->n_children,
-                    _clutter_actor_get_debug_name (self),
-                    allocation->x1,
-                    allocation->y1,
-                    (allocation->x2 - allocation->x1),
-                    (allocation->y2 - allocation->y1),
-                    G_OBJECT_TYPE_NAME (priv->layout_manager));
-
-      clutter_layout_manager_allocate (priv->layout_manager,
-                                       container,
-                                       &children_box,
-                                       children_flags);
-    }
+layout_children:
+  if (self->priv->n_children != 0)
+    CLUTTER_ACTOR_GET_CLASS (self)->layout_children (self);
 }
 
 static void
@@ -6100,6 +6098,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
   klass->get_preferred_width = clutter_actor_real_get_preferred_width;
   klass->get_preferred_height = clutter_actor_real_get_preferred_height;
   klass->allocate = clutter_actor_real_allocate;
+  klass->layout_children = clutter_actor_real_layout_children;
   klass->queue_redraw = clutter_actor_real_queue_redraw;
   klass->queue_relayout = clutter_actor_real_queue_relayout;
   klass->apply_transform = clutter_actor_real_apply_transform;
diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h
index 50e9e04..09db522 100644
--- a/clutter/clutter-actor.h
+++ b/clutter/clutter-actor.h
@@ -267,9 +267,11 @@ struct _ClutterActorClass
   gboolean (* touch_event)          (ClutterActor         *self,
                                      ClutterTouchEvent    *event);
 
+  void     (* layout_children)      (ClutterActor         *self);
+
   /*< private >*/
   /* padding for future expansion */
-  gpointer _padding_dummy[26];
+  gpointer _padding_dummy[25];
 };
 
 /**



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