diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2012-11-28 09:54:49 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2012-12-15 20:04:56 +0000 |
commit | a5c4e56d8e33eb2e2ca4a0617ab837229d0d3dce (patch) | |
tree | a51f9441d259e1d52e6e272e4df854ac798f20ba | |
parent | e72a7235658bc4fae66b0b94a9f88f3547b514a1 (diff) | |
download | clutter-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.c | 81 | ||||
-rw-r--r-- | 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 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]; }; /** |