summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2012-11-28 09:54:49 +0000
committerEmmanuele Bassi <ebassi@gnome.org>2012-12-15 20:04:56 +0000
commita5c4e56d8e33eb2e2ca4a0617ab837229d0d3dce (patch)
treea51f9441d259e1d52e6e272e4df854ac798f20ba
parente72a7235658bc4fae66b0b94a9f88f3547b514a1 (diff)
downloadclutter-wip/layout-children.tar.gz
actor: Add ClutterActorClass.layout_children()wip/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.
-rw-r--r--clutter/clutter-actor.c81
-rw-r--r--clutter/clutter-actor.h4
2 files changed, 43 insertions, 42 deletions
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 1495097fd..544891b76 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 = (priv->allocation.x2 - priv->allocation.x1);
+ children_box.y2 = (priv->allocation.y2 - priv->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),
+ priv->allocation.x1,
+ priv->allocation.y1,
+ (priv->allocation.x2 - priv->allocation.x1),
+ (priv->allocation.y2 - priv->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 50e9e04d5..09db522b0 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];
};
/**