actor: Add a NO_LAYOUT flag for actors

Some actor implementation might avoid imposing any layout on their
children. The Actor base class usually assumes some sort of layout
management is in place, so it will queue relayouts when, for instance,
an actor is shown or is hidden. If the parent of the actor does not
impose any layout, though, showing or hiding one of its children will
not affect the layout of the others.

An example of this kind of container is ClutterGroup.

By adding a new Actor flag, CLUTTER_ACTOR_NO_LAYOUT, and by making
the Group actor set it on itself, the Actor base class can now decide
whether or not to queue a relayout. The flag is not meant to be used
by application code, and should only be set when implementing a new
container.

http://bugzilla.openedhand.com/show_bug.cgi?id=1838
This commit is contained in:
Emmanuele Bassi 2009-10-07 16:41:25 +01:00 committed by Emmanuele Bassi
parent 9ccdf2eb02
commit c4f27b1556
3 changed files with 43 additions and 15 deletions

View File

@ -74,8 +74,8 @@
* clutter_actor_set_width(); or it can have a preferred width and * clutter_actor_set_width(); or it can have a preferred width and
* height, which then allows a layout manager to implicitly size and * height, which then allows a layout manager to implicitly size and
* position it by "allocating" an area for an actor. This allows for * position it by "allocating" an area for an actor. This allows for
* actors to be manipulate in both a fixed or static parent container * actors to be manipulated in both a fixed (or static) parent container
* (i.e. children of #ClutterGroup) and a more automatic or dynamic * (i.e. children of #ClutterGroup) and a more automatic (or dynamic)
* layout based parent container. * layout based parent container.
* *
* When accessing the position and size of an actor, the simple accessors * When accessing the position and size of an actor, the simple accessors
@ -880,6 +880,7 @@ clutter_actor_real_map (ClutterActor *self)
g_assert (!CLUTTER_ACTOR_IS_MAPPED (self)); g_assert (!CLUTTER_ACTOR_IS_MAPPED (self));
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED); CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
/* notify on parent mapped before potentially mapping /* notify on parent mapped before potentially mapping
* children, so apps see a top-down notification. * children, so apps see a top-down notification.
*/ */
@ -993,20 +994,29 @@ clutter_actor_real_show (ClutterActor *self)
ClutterActorPrivate *priv = self->priv; ClutterActorPrivate *priv = self->priv;
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_VISIBLE); CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_VISIBLE);
/* we notify on the "visible" flag in the clutter_actor_show() /* we notify on the "visible" flag in the clutter_actor_show()
* wrapper so the entire show signal emission completes first * wrapper so the entire show signal emission completes first
* (?) * (?)
*/ */
clutter_actor_update_map_state (self, MAP_STATE_CHECK); clutter_actor_update_map_state (self, MAP_STATE_CHECK);
/* While an actor is hidden the parent may not have allocated/requested /* we queue a relayout unless the actor is inside a
* so we need to start from scratch and avoid the short-circuiting * container that explicitly told us not to
* in clutter_actor_queue_relayout().
*/ */
priv->needs_width_request = FALSE; if (priv->parent_actor &&
priv->needs_height_request = FALSE; (!(priv->parent_actor->flags & CLUTTER_ACTOR_NO_LAYOUT)))
priv->needs_allocation = FALSE; {
clutter_actor_queue_relayout (self); /* While an actor is hidden the parent may not have
* allocated/requested so we need to start from scratch
* and avoid the short-circuiting in
* clutter_actor_queue_relayout().
*/
priv->needs_width_request = FALSE;
priv->needs_height_request = FALSE;
priv->needs_allocation = FALSE;
clutter_actor_queue_relayout (self);
}
} }
} }
@ -1081,6 +1091,8 @@ clutter_actor_real_hide (ClutterActor *self)
{ {
if (CLUTTER_ACTOR_IS_VISIBLE (self)) if (CLUTTER_ACTOR_IS_VISIBLE (self))
{ {
ClutterActorPrivate *priv = self->priv;
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_VISIBLE); CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_VISIBLE);
/* we notify on the "visible" flag in the clutter_actor_hide() /* we notify on the "visible" flag in the clutter_actor_hide()
@ -1089,7 +1101,12 @@ clutter_actor_real_hide (ClutterActor *self)
*/ */
clutter_actor_update_map_state (self, MAP_STATE_CHECK); clutter_actor_update_map_state (self, MAP_STATE_CHECK);
clutter_actor_queue_relayout (self); /* we queue a relayout unless the actor is inside a
* container that explicitly told us not to
*/
if (priv->parent_actor &&
(!(priv->parent_actor->flags & CLUTTER_ACTOR_NO_LAYOUT)))
clutter_actor_queue_relayout (priv->parent_actor);
} }
} }

View File

@ -93,21 +93,26 @@ typedef void (*ClutterCallback) (ClutterActor *actor,
/** /**
* ClutterActorFlags: * ClutterActorFlags:
* @CLUTTER_ACTOR_MAPPED: the actor will be painted (is visible, and inside a toplevel, and all parents visible) * @CLUTTER_ACTOR_MAPPED: the actor will be painted (is visible, and inside
* a toplevel, and all parents visible)
* @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been * @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been
* allocated * allocated
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event * @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event
* signals * signals
* @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program * @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program
* @CLUTTER_ACTOR_NO_LAYOUT: the actor provides an explicit layout management
* policy for its children; this flag will prevent Clutter from automatic
* queueing of relayout and will defer all layouting to the actor itself
* *
* Flags used to signal the state of an actor. * Flags used to signal the state of an actor.
*/ */
typedef enum typedef enum
{ {
CLUTTER_ACTOR_MAPPED = 1 << 1, CLUTTER_ACTOR_MAPPED = 1 << 1,
CLUTTER_ACTOR_REALIZED = 1 << 2, CLUTTER_ACTOR_REALIZED = 1 << 2,
CLUTTER_ACTOR_REACTIVE = 1 << 3, CLUTTER_ACTOR_REACTIVE = 1 << 3,
CLUTTER_ACTOR_VISIBLE = 1 << 4 CLUTTER_ACTOR_VISIBLE = 1 << 4,
CLUTTER_ACTOR_NO_LAYOUT = 1 << 5
} ClutterActorFlags; } ClutterActorFlags;
/** /**

View File

@ -441,6 +441,12 @@ clutter_group_init (ClutterGroup *self)
self->priv->layout = clutter_fixed_layout_new (); self->priv->layout = clutter_fixed_layout_new ();
g_object_ref_sink (self->priv->layout); g_object_ref_sink (self->priv->layout);
/* signal Clutter that we don't impose any layout on
* our children, so we can shave off some relayout
* operations
*/
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_NO_LAYOUT);
} }
/** /**