actor: Define the scene structure inside Actor
Instead of storing the list of children, let's turn Actor inside a proper node of a tree. This change adds the following members to the Actor private data structure: first_child last_child prev_sibling next_sibling and removes the "children" GList from it; iteration is performed through the direct pointers to the siblings and children. This change makes removal, insertion before a sibling, and insertion after a sibling constant time operations, but it still retains the feature of ClutterActor.add_child() to build the list of children while taking into account the depth set on the newly added child, to allow the default painter's algorithm we employ inside the paint() implementation to at least try and cope with the :depth property (albeit in a fairly naïve way). Changes in the :depth property will not change the paint sequence any more: this functionality will be restored later.
This commit is contained in:
parent
71545ae56f
commit
22259e0965
@ -390,8 +390,12 @@ struct _ClutterActorPrivate
|
||||
ClutterEffect *flatten_effect;
|
||||
|
||||
/* scene graph */
|
||||
ClutterActor *parent_actor;
|
||||
GList *children;
|
||||
ClutterActor *parent;
|
||||
ClutterActor *prev_sibling;
|
||||
ClutterActor *next_sibling;
|
||||
ClutterActor *first_child;
|
||||
ClutterActor *last_child;
|
||||
|
||||
gint n_children;
|
||||
|
||||
gchar *name; /* a non-unique name, used for debugging */
|
||||
@ -738,7 +742,7 @@ clutter_actor_verify_map_state (ClutterActor *self)
|
||||
*/
|
||||
if (!CLUTTER_ACTOR_IN_REPARENT (self))
|
||||
{
|
||||
if (priv->parent_actor == NULL)
|
||||
if (priv->parent == NULL)
|
||||
{
|
||||
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
|
||||
{
|
||||
@ -748,11 +752,11 @@ clutter_actor_verify_map_state (ClutterActor *self)
|
||||
"have a parent",
|
||||
_clutter_actor_get_debug_name (self));
|
||||
}
|
||||
else if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_actor))
|
||||
else if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
|
||||
{
|
||||
g_warning ("Realized actor %s has an unrealized parent %s",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
_clutter_actor_get_debug_name (priv->parent_actor));
|
||||
_clutter_actor_get_debug_name (priv->parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -768,7 +772,7 @@ clutter_actor_verify_map_state (ClutterActor *self)
|
||||
*/
|
||||
if (!CLUTTER_ACTOR_IN_REPARENT (self))
|
||||
{
|
||||
if (priv->parent_actor == NULL)
|
||||
if (priv->parent == NULL)
|
||||
{
|
||||
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
|
||||
{
|
||||
@ -800,32 +804,32 @@ clutter_actor_verify_map_state (ClutterActor *self)
|
||||
if (iter->priv->enable_paint_unmapped)
|
||||
return;
|
||||
|
||||
iter = iter->priv->parent_actor;
|
||||
iter = iter->priv->parent;
|
||||
}
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (priv->parent_actor))
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (priv->parent))
|
||||
{
|
||||
g_warning ("Actor '%s' should not be mapped if parent '%s'"
|
||||
"is not visible",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
_clutter_actor_get_debug_name (priv->parent_actor));
|
||||
_clutter_actor_get_debug_name (priv->parent));
|
||||
}
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_actor))
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
|
||||
{
|
||||
g_warning ("Actor '%s' should not be mapped if parent '%s'"
|
||||
"is not realized",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
_clutter_actor_get_debug_name (priv->parent_actor));
|
||||
_clutter_actor_get_debug_name (priv->parent));
|
||||
}
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_TOPLEVEL (priv->parent_actor))
|
||||
if (!CLUTTER_ACTOR_IS_TOPLEVEL (priv->parent))
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_MAPPED (priv->parent_actor))
|
||||
if (!CLUTTER_ACTOR_IS_MAPPED (priv->parent))
|
||||
g_warning ("Actor '%s' is mapped but its non-toplevel "
|
||||
"parent '%s' is not mapped",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
_clutter_actor_get_debug_name (priv->parent_actor));
|
||||
_clutter_actor_get_debug_name (priv->parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -924,7 +928,7 @@ clutter_actor_update_map_state (ClutterActor *self,
|
||||
else
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterActor *parent = priv->parent_actor;
|
||||
ClutterActor *parent = priv->parent;
|
||||
gboolean should_be_mapped;
|
||||
gboolean may_be_realized;
|
||||
gboolean must_be_realized;
|
||||
@ -992,7 +996,7 @@ clutter_actor_update_map_state (ClutterActor *self,
|
||||
*/
|
||||
if (priv->enable_paint_unmapped)
|
||||
{
|
||||
if (priv->parent_actor == NULL)
|
||||
if (priv->parent == NULL)
|
||||
g_warning ("Attempting to map an unparented actor '%s'",
|
||||
_clutter_actor_get_debug_name (self));
|
||||
|
||||
@ -1016,7 +1020,7 @@ clutter_actor_update_map_state (ClutterActor *self,
|
||||
"meet the necessary invariants: the actor '%s' "
|
||||
"is parented to an unmapped actor '%s'",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
_clutter_actor_get_debug_name (priv->parent_actor));
|
||||
_clutter_actor_get_debug_name (priv->parent));
|
||||
}
|
||||
|
||||
/* If in reparent, we temporarily suspend unmap and unrealize.
|
||||
@ -1067,8 +1071,7 @@ static void
|
||||
clutter_actor_real_map (ClutterActor *self)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterActor *stage;
|
||||
GList *c;
|
||||
ClutterActor *stage, *iter;
|
||||
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (self));
|
||||
|
||||
@ -1079,6 +1082,7 @@ clutter_actor_real_map (ClutterActor *self)
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (self);
|
||||
priv->pick_id = _clutter_stage_acquire_pick_id (CLUTTER_STAGE (stage), self);
|
||||
|
||||
CLUTTER_NOTE (ACTOR, "Pick id '%d' for actor '%s'",
|
||||
priv->pick_id,
|
||||
_clutter_actor_get_debug_name (self));
|
||||
@ -1088,10 +1092,11 @@ clutter_actor_real_map (ClutterActor *self)
|
||||
*/
|
||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MAPPED]);
|
||||
|
||||
for (c = self->priv->children; c; c = c->next)
|
||||
for (iter = self->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
ClutterActor *child = c->data;
|
||||
clutter_actor_map (child);
|
||||
clutter_actor_map (iter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1132,17 +1137,18 @@ static void
|
||||
clutter_actor_real_unmap (ClutterActor *self)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
GList *c;
|
||||
ClutterActor *iter;
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (self));
|
||||
|
||||
CLUTTER_NOTE (ACTOR, "Unmapping actor '%s'",
|
||||
_clutter_actor_get_debug_name (self));
|
||||
|
||||
for (c = priv->children; c; c = c->next)
|
||||
for (iter = self->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
ClutterActor *child = c->data;
|
||||
clutter_actor_unmap (child);
|
||||
clutter_actor_unmap (iter);
|
||||
}
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
|
||||
@ -1225,8 +1231,8 @@ clutter_actor_real_show (ClutterActor *self)
|
||||
/* we queue a relayout unless the actor is inside a
|
||||
* container that explicitly told us not to
|
||||
*/
|
||||
if (priv->parent_actor != NULL &&
|
||||
(!(priv->parent_actor->flags & CLUTTER_ACTOR_NO_LAYOUT)))
|
||||
if (priv->parent != NULL &&
|
||||
(!(priv->parent->flags & CLUTTER_ACTOR_NO_LAYOUT)))
|
||||
{
|
||||
/* While an actor is hidden the parent may not have
|
||||
* allocated/requested so we need to start from scratch
|
||||
@ -1252,7 +1258,7 @@ set_show_on_set_parent (ClutterActor *self,
|
||||
if (priv->show_on_set_parent == set_show)
|
||||
return;
|
||||
|
||||
if (priv->parent_actor == NULL)
|
||||
if (priv->parent == NULL)
|
||||
{
|
||||
priv->show_on_set_parent = set_show;
|
||||
g_object_notify_by_pspec (G_OBJECT (self),
|
||||
@ -1303,8 +1309,8 @@ clutter_actor_show (ClutterActor *self)
|
||||
g_signal_emit (self, actor_signals[SHOW], 0);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_VISIBLE]);
|
||||
|
||||
if (priv->parent_actor)
|
||||
clutter_actor_queue_redraw (priv->parent_actor);
|
||||
if (priv->parent)
|
||||
clutter_actor_queue_redraw (priv->parent);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
@ -1347,9 +1353,9 @@ clutter_actor_real_hide (ClutterActor *self)
|
||||
/* we queue a relayout unless the actor is inside a
|
||||
* container that explicitly told us not to
|
||||
*/
|
||||
if (priv->parent_actor != NULL &&
|
||||
(!(priv->parent_actor->flags & CLUTTER_ACTOR_NO_LAYOUT)))
|
||||
clutter_actor_queue_relayout (priv->parent_actor);
|
||||
if (priv->parent != NULL &&
|
||||
(!(priv->parent->flags & CLUTTER_ACTOR_NO_LAYOUT)))
|
||||
clutter_actor_queue_relayout (priv->parent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1396,8 +1402,8 @@ clutter_actor_hide (ClutterActor *self)
|
||||
g_signal_emit (self, actor_signals[HIDE], 0);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_VISIBLE]);
|
||||
|
||||
if (priv->parent_actor)
|
||||
clutter_actor_queue_redraw (priv->parent_actor);
|
||||
if (priv->parent)
|
||||
clutter_actor_queue_redraw (priv->parent);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
@ -1461,8 +1467,8 @@ clutter_actor_realize (ClutterActor *self)
|
||||
/* To be realized, our parent actors must be realized first.
|
||||
* This will only succeed if we're inside a toplevel.
|
||||
*/
|
||||
if (priv->parent_actor != NULL)
|
||||
clutter_actor_realize (priv->parent_actor);
|
||||
if (priv->parent != NULL)
|
||||
clutter_actor_realize (priv->parent);
|
||||
|
||||
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
|
||||
{
|
||||
@ -1477,8 +1483,8 @@ clutter_actor_realize (ClutterActor *self)
|
||||
* someone can fix it. But for now it's too hard to fix this
|
||||
* because e.g. ClutterTexture needs reworking.
|
||||
*/
|
||||
if (priv->parent_actor == NULL ||
|
||||
!CLUTTER_ACTOR_IS_REALIZED (priv->parent_actor))
|
||||
if (priv->parent == NULL ||
|
||||
!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1739,7 +1745,8 @@ clutter_actor_real_get_preferred_width (ClutterActor *self,
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->children != NULL && priv->layout_manager != NULL)
|
||||
if (priv->n_children != 0 &&
|
||||
priv->layout_manager != NULL)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (self);
|
||||
|
||||
@ -1778,7 +1785,8 @@ clutter_actor_real_get_preferred_height (ClutterActor *self,
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->children != NULL && priv->layout_manager != NULL)
|
||||
if (priv->n_children != 0 &&
|
||||
priv->layout_manager != NULL)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (self);
|
||||
|
||||
@ -1905,7 +1913,8 @@ clutter_actor_real_allocate (ClutterActor *self,
|
||||
* data out of the sub-tree of the scene graph that has this actor at
|
||||
* the root
|
||||
*/
|
||||
if (priv->children != NULL && priv->layout_manager != NULL)
|
||||
if (priv->n_children != 0 &&
|
||||
priv->layout_manager != NULL)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (self);
|
||||
gfloat width, height;
|
||||
@ -2041,8 +2050,8 @@ clutter_actor_real_queue_relayout (ClutterActor *self)
|
||||
N_CACHED_SIZE_REQUESTS * sizeof (SizeRequest));
|
||||
|
||||
/* We need to go all the way up the hierarchy */
|
||||
if (priv->parent_actor != NULL)
|
||||
_clutter_actor_queue_only_relayout (priv->parent_actor);
|
||||
if (priv->parent != NULL)
|
||||
_clutter_actor_queue_only_relayout (priv->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2849,19 +2858,17 @@ add_or_remove_flatten_effect (ClutterActor *self)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
foreach_child_paint (ClutterActor *child,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
clutter_actor_paint (child);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_real_paint (ClutterActor *actor)
|
||||
{
|
||||
_clutter_actor_foreach_child (actor, foreach_child_paint, NULL);
|
||||
ClutterActor *iter;
|
||||
|
||||
for (iter = actor->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
clutter_actor_paint (iter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2963,10 +2970,10 @@ clutter_actor_paint (ClutterActor *self)
|
||||
{
|
||||
g_string_append (buf, _clutter_actor_get_debug_name (parent));
|
||||
|
||||
if (parent->priv->parent_actor != NULL)
|
||||
if (parent->priv->parent != NULL)
|
||||
g_string_append (buf, "->");
|
||||
|
||||
parent = parent->priv->parent_actor;
|
||||
parent = parent->priv->parent;
|
||||
}
|
||||
|
||||
g_warning ("Unexpected transform found when painting actor "
|
||||
@ -4227,9 +4234,9 @@ clutter_actor_dispose (GObject *object)
|
||||
g_signal_emit (self, actor_signals[DESTROY], 0);
|
||||
|
||||
/* avoid recursing when called from clutter_actor_destroy() */
|
||||
if (priv->parent_actor != NULL)
|
||||
if (priv->parent != NULL)
|
||||
{
|
||||
ClutterActor *parent = priv->parent_actor;
|
||||
ClutterActor *parent = priv->parent;
|
||||
|
||||
/* go through the Container implementation unless this
|
||||
* is an internal child and has been marked as such
|
||||
@ -4241,7 +4248,7 @@ clutter_actor_dispose (GObject *object)
|
||||
}
|
||||
|
||||
/* parent should be gone */
|
||||
g_assert (priv->parent_actor == NULL);
|
||||
g_assert (priv->parent == NULL);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
|
||||
{
|
||||
@ -4340,8 +4347,8 @@ clutter_actor_real_get_paint_volume (ClutterActor *self,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterActor *child;
|
||||
gboolean res;
|
||||
GList *l;
|
||||
|
||||
/* this is the default return value: we cannot know if a class
|
||||
* is going to paint outside its allocation, so we take the
|
||||
@ -4375,16 +4382,17 @@ clutter_actor_real_get_paint_volume (ClutterActor *self,
|
||||
}
|
||||
|
||||
/* if we don't have children we just bail out here */
|
||||
if (priv->children == NULL)
|
||||
if (priv->n_children == 0)
|
||||
return res;
|
||||
|
||||
/* but if we have children then we ask for their paint volume in
|
||||
* our coordinates. if any of our children replies that it doesn't
|
||||
* have a paint volume, we bail out
|
||||
*/
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
for (child = priv->first_child;
|
||||
child != NULL;
|
||||
child = child->priv->next_sibling)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
const ClutterPaintVolume *child_volume;
|
||||
|
||||
child_volume = clutter_actor_get_transformed_paint_volume (child, self);
|
||||
@ -8721,7 +8729,7 @@ clutter_actor_get_paint_opacity_internal (ClutterActor *self)
|
||||
if (priv->opacity_override >= 0)
|
||||
return priv->opacity_override;
|
||||
|
||||
parent = priv->parent_actor;
|
||||
parent = priv->parent;
|
||||
|
||||
/* Factor in the actual actors opacity with parents */
|
||||
if (parent != NULL)
|
||||
@ -8975,20 +8983,6 @@ clutter_actor_set_depth (ClutterActor *self,
|
||||
/* Sets Z value - XXX 2.0: should we invert? */
|
||||
priv->z = depth;
|
||||
|
||||
if (priv->parent_actor != NULL)
|
||||
{
|
||||
ClutterContainer *parent;
|
||||
|
||||
/* We need to resort the container stacking order as to
|
||||
* correctly render alpha values.
|
||||
*
|
||||
* FIXME: This is sub-optimal. maybe queue the sort
|
||||
* before stacking
|
||||
*/
|
||||
parent = CLUTTER_CONTAINER (priv->parent_actor);
|
||||
clutter_container_sort_depth_order (parent);
|
||||
}
|
||||
|
||||
priv->transform_valid = FALSE;
|
||||
|
||||
clutter_actor_queue_redraw (self);
|
||||
@ -9331,9 +9325,22 @@ clutter_actor_get_clip (ClutterActor *self,
|
||||
GList *
|
||||
clutter_actor_get_children (ClutterActor *self)
|
||||
{
|
||||
ClutterActor *iter;
|
||||
GList *res;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
||||
|
||||
return g_list_copy (self->priv->children);
|
||||
/* we walk the list backward so that we can use prepend(),
|
||||
* which is O(1)
|
||||
*/
|
||||
for (iter = self->priv->last_child, res = NULL;
|
||||
iter != NULL;
|
||||
iter = iter->priv->prev_sibling)
|
||||
{
|
||||
res = g_list_prepend (res, iter);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
@ -9343,39 +9350,65 @@ clutter_actor_get_children (ClutterActor *self)
|
||||
*
|
||||
* Inserts @child inside the list of children held by @self, using
|
||||
* the depth as the insertion criteria.
|
||||
*
|
||||
* This sadly makes the insertion not O(1), but we can keep the
|
||||
* list sorted so that the painters algorithm we use for painting
|
||||
* the children will work correctly.
|
||||
*/
|
||||
static void
|
||||
insert_child_at_depth (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
GList *l, *prev = NULL;
|
||||
ClutterActor *iter;
|
||||
|
||||
if (self->priv->n_children == 0)
|
||||
{
|
||||
self->priv->first_child = child;
|
||||
self->priv->last_child = child;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the right place to insert the child so that it will still be
|
||||
sorted and the child will be after all of the actors at the same
|
||||
depth */
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
dept */
|
||||
for (iter = self->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
ClutterActor *iter = l->data;
|
||||
|
||||
if (iter->priv->z > child->priv->z)
|
||||
break;
|
||||
|
||||
prev = l;
|
||||
}
|
||||
|
||||
/* Insert the node before the found node */
|
||||
l = g_list_prepend (l, child);
|
||||
|
||||
/* Fixup the links */
|
||||
if (prev != NULL)
|
||||
if (iter != NULL)
|
||||
{
|
||||
prev->next = l;
|
||||
l->prev = prev;
|
||||
ClutterActor *tmp = iter->priv->prev_sibling;
|
||||
|
||||
if (tmp != NULL)
|
||||
tmp->priv->next_sibling = child;
|
||||
|
||||
/* Insert the node before the found one */
|
||||
child->priv->prev_sibling = iter->priv->prev_sibling;
|
||||
child->priv->next_sibling = iter;
|
||||
iter->priv->prev_sibling = child;
|
||||
|
||||
/* Update the head of the list */
|
||||
if (self->priv->first_child == iter)
|
||||
self->priv->first_child = child;
|
||||
}
|
||||
else
|
||||
priv->children = l;
|
||||
{
|
||||
ClutterActor *tmp = self->priv->last_child;
|
||||
|
||||
if (tmp != NULL)
|
||||
tmp->priv->next_sibling = child;
|
||||
|
||||
child->priv->prev_sibling = self->priv->last_child;
|
||||
child->priv->next_sibling = NULL;
|
||||
|
||||
self->priv->last_child = child;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -9384,16 +9417,59 @@ insert_child_at_index (ClutterActor *self,
|
||||
gpointer data_)
|
||||
{
|
||||
gint index_ = GPOINTER_TO_INT (data_);
|
||||
ClutterActorPrivate *priv;
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (index_ == 0)
|
||||
priv->children = g_list_prepend (priv->children, child);
|
||||
{
|
||||
ClutterActor *tmp = self->priv->first_child;
|
||||
|
||||
if (tmp != NULL)
|
||||
tmp->priv->prev_sibling = child;
|
||||
|
||||
child->priv->prev_sibling = NULL;
|
||||
child->priv->next_sibling = tmp;
|
||||
|
||||
self->priv->first_child = child;
|
||||
}
|
||||
else if (index < 0)
|
||||
priv->children = g_list_append (priv->children, child);
|
||||
{
|
||||
ClutterActor *tmp = self->priv->last_child;
|
||||
|
||||
if (tmp != NULL)
|
||||
tmp->priv->next_sibling = child;
|
||||
|
||||
child->priv->prev_sibling = tmp;
|
||||
child->priv->next_sibling = NULL;
|
||||
|
||||
self->priv->last_child = child;
|
||||
}
|
||||
else
|
||||
priv->children = g_list_insert (priv->children, child, index_);
|
||||
{
|
||||
ClutterActor *iter;
|
||||
int i;
|
||||
|
||||
for (iter = self->priv->first_child, i = 0;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling, i += 1)
|
||||
{
|
||||
if (index_ == i)
|
||||
{
|
||||
ClutterActor *tmp = iter->priv->prev_sibling;
|
||||
|
||||
child->priv->prev_sibling = iter->priv->prev_sibling;
|
||||
child->priv->next_sibling = iter;
|
||||
|
||||
iter->priv->prev_sibling = child;
|
||||
|
||||
if (tmp != NULL)
|
||||
tmp->priv->next_sibling = child;
|
||||
|
||||
if (self->priv->last_child == iter)
|
||||
self->priv->last_child = child;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -9402,37 +9478,17 @@ insert_child_above (ClutterActor *self,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *sibling = data;
|
||||
ClutterActorPrivate *priv;
|
||||
GList *l, *next = NULL;
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (sibling == NULL)
|
||||
{
|
||||
priv->children = g_list_append (priv->children, child);
|
||||
sibling = self->priv->last_child;
|
||||
|
||||
return;
|
||||
}
|
||||
child->priv->prev_sibling = sibling;
|
||||
child->priv->next_sibling = NULL;
|
||||
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *iter = l->data;
|
||||
sibling->priv->next_sibling = child;
|
||||
|
||||
next = l->next;
|
||||
|
||||
if (iter == sibling)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Insert the node after the found node */
|
||||
l = g_list_append (l, child);
|
||||
|
||||
/* Fixup the links */
|
||||
if (next != NULL)
|
||||
{
|
||||
l->next = next;
|
||||
next->prev = l;
|
||||
}
|
||||
if (self->priv->last_child == sibling)
|
||||
self->priv->last_child = child;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -9440,36 +9496,18 @@ insert_child_below (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterActor *sibling = data;
|
||||
GList *l, *prev = NULL;
|
||||
|
||||
if (sibling == NULL)
|
||||
{
|
||||
priv->children = g_list_prepend (priv->children, child);
|
||||
sibling = self->priv->first_child;
|
||||
|
||||
return;
|
||||
}
|
||||
child->priv->prev_sibling = NULL;
|
||||
child->priv->next_sibling = sibling;
|
||||
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *iter = l->data;
|
||||
sibling->priv->prev_sibling = child;
|
||||
|
||||
if (iter == sibling)
|
||||
break;
|
||||
|
||||
prev = l;
|
||||
}
|
||||
|
||||
l = g_list_prepend (l, child);
|
||||
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = l;
|
||||
l->prev = prev;
|
||||
}
|
||||
else
|
||||
priv->children = l;
|
||||
if (self->priv->first_child == sibling)
|
||||
self->priv->first_child = child;
|
||||
}
|
||||
|
||||
typedef void (* ClutterActorAddChildFunc) (ClutterActor *parent,
|
||||
@ -9486,7 +9524,7 @@ clutter_actor_add_child_internal (ClutterActor *self,
|
||||
{
|
||||
ClutterTextDirection text_dir;
|
||||
|
||||
if (child->priv->parent_actor != NULL)
|
||||
if (child->priv->parent != NULL)
|
||||
{
|
||||
g_warning ("Cannot set a parent on an actor which has a parent. "
|
||||
"You must use clutter_actor_remove_child() first.");
|
||||
@ -9509,7 +9547,7 @@ clutter_actor_add_child_internal (ClutterActor *self,
|
||||
clutter_container_create_child_meta (CLUTTER_CONTAINER (self), child);
|
||||
|
||||
g_object_ref_sink (child);
|
||||
child->priv->parent_actor = self;
|
||||
child->priv->parent = self;
|
||||
|
||||
/* delegate the actual insertion */
|
||||
add_func (self, child, data);
|
||||
@ -9556,7 +9594,7 @@ clutter_actor_add_child_internal (ClutterActor *self,
|
||||
child->priv->needs_height_request = TRUE;
|
||||
child->priv->needs_allocation = TRUE;
|
||||
|
||||
clutter_actor_queue_relayout (child->priv->parent_actor);
|
||||
clutter_actor_queue_relayout (child->priv->parent);
|
||||
}
|
||||
|
||||
/* child expand flags may cause the parent's expand flags
|
||||
@ -9603,7 +9641,7 @@ clutter_actor_add_child (ClutterActor *self,
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (child));
|
||||
g_return_if_fail (self != child);
|
||||
g_return_if_fail (child->priv->parent_actor == NULL);
|
||||
g_return_if_fail (child->priv->parent == NULL);
|
||||
|
||||
clutter_actor_add_child_internal (self, child,
|
||||
insert_child_at_depth,
|
||||
@ -9639,7 +9677,7 @@ clutter_actor_insert_child_at_index (ClutterActor *self,
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (child));
|
||||
g_return_if_fail (self != child);
|
||||
g_return_if_fail (child->priv->parent_actor == NULL);
|
||||
g_return_if_fail (child->priv->parent == NULL);
|
||||
g_return_if_fail (index_ < self->priv->n_children);
|
||||
|
||||
clutter_actor_add_child_internal (self, child,
|
||||
@ -9678,10 +9716,10 @@ clutter_actor_insert_child_above (ClutterActor *self,
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (child));
|
||||
g_return_if_fail (self != child);
|
||||
g_return_if_fail (child != sibling);
|
||||
g_return_if_fail (child->priv->parent_actor == NULL);
|
||||
g_return_if_fail (child->priv->parent == NULL);
|
||||
g_return_if_fail (sibling == NULL ||
|
||||
(CLUTTER_IS_ACTOR (sibling) &&
|
||||
sibling->priv->parent_actor == self));
|
||||
sibling->priv->parent == self));
|
||||
|
||||
clutter_actor_add_child_internal (self, child,
|
||||
insert_child_above,
|
||||
@ -9719,10 +9757,10 @@ clutter_actor_insert_child_below (ClutterActor *self,
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (child));
|
||||
g_return_if_fail (self != child);
|
||||
g_return_if_fail (child != sibling);
|
||||
g_return_if_fail (child->priv->parent_actor == NULL);
|
||||
g_return_if_fail (child->priv->parent == NULL);
|
||||
g_return_if_fail (sibling == NULL ||
|
||||
(CLUTTER_IS_ACTOR (sibling) &&
|
||||
sibling->priv->parent_actor == self));
|
||||
sibling->priv->parent == self));
|
||||
|
||||
clutter_actor_add_child_internal (self, child,
|
||||
insert_child_below,
|
||||
@ -9754,7 +9792,7 @@ clutter_actor_set_parent (ClutterActor *self,
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (parent));
|
||||
g_return_if_fail (self != parent);
|
||||
g_return_if_fail (self->priv->parent_actor == NULL);
|
||||
g_return_if_fail (self->priv->parent == NULL);
|
||||
|
||||
clutter_actor_add_child_internal (parent, self,
|
||||
insert_child_at_depth,
|
||||
@ -9777,7 +9815,7 @@ clutter_actor_get_parent (ClutterActor *self)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
||||
|
||||
return self->priv->parent_actor;
|
||||
return self->priv->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -9817,6 +9855,28 @@ invalidate_queue_redraw_entry (ClutterActor *self,
|
||||
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
remove_child (ClutterActor *self,
|
||||
ClutterActor *child)
|
||||
{
|
||||
ClutterActor *prev_sibling, *next_sibling;
|
||||
|
||||
prev_sibling = child->priv->prev_sibling;
|
||||
next_sibling = child->priv->next_sibling;
|
||||
|
||||
if (prev_sibling != NULL)
|
||||
prev_sibling->priv->next_sibling = next_sibling;
|
||||
|
||||
if (next_sibling != NULL)
|
||||
next_sibling->priv->prev_sibling = prev_sibling;
|
||||
|
||||
if (self->priv->first_child == child)
|
||||
self->priv->first_child = next_sibling;
|
||||
|
||||
if (self->priv->last_child == child)
|
||||
self->priv->last_child = prev_sibling;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_remove_child_internal (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
@ -9857,14 +9917,15 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
child->priv->parent_actor = NULL;
|
||||
child->priv->parent = NULL;
|
||||
|
||||
/* clutter_actor_reparent() will emit ::parent-set for us */
|
||||
if (!CLUTTER_ACTOR_IN_REPARENT (child))
|
||||
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
|
||||
|
||||
self->priv->children = g_list_remove (self->priv->children, child);
|
||||
self->priv->n_children--;
|
||||
remove_child (self, child);
|
||||
|
||||
self->priv->n_children -= 1;
|
||||
|
||||
/* if the child was mapped then we need to relayout ourselves to account
|
||||
* for the removed child
|
||||
@ -9915,8 +9976,8 @@ clutter_actor_remove_child (ClutterActor *self,
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (child));
|
||||
g_return_if_fail (self != child);
|
||||
g_return_if_fail (child->priv->parent_actor != NULL);
|
||||
g_return_if_fail (child->priv->parent_actor == self);
|
||||
g_return_if_fail (child->priv->parent != NULL);
|
||||
g_return_if_fail (child->priv->parent == self);
|
||||
|
||||
clutter_actor_remove_child_internal (self, child, TRUE, TRUE);
|
||||
}
|
||||
@ -9944,10 +10005,10 @@ clutter_actor_unparent (ClutterActor *self)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
if (self->priv->parent_actor == NULL)
|
||||
if (self->priv->parent == NULL)
|
||||
return;
|
||||
|
||||
clutter_actor_remove_child_internal (self->priv->parent_actor, self,
|
||||
clutter_actor_remove_child_internal (self->priv->parent, self,
|
||||
FALSE,
|
||||
FALSE);
|
||||
}
|
||||
@ -9990,13 +10051,13 @@ clutter_actor_reparent (ClutterActor *self,
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->parent_actor != new_parent)
|
||||
if (priv->parent != new_parent)
|
||||
{
|
||||
ClutterActor *old_parent;
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_REPARENT);
|
||||
|
||||
old_parent = priv->parent_actor;
|
||||
old_parent = priv->parent;
|
||||
|
||||
g_object_ref (self);
|
||||
|
||||
@ -10053,7 +10114,7 @@ clutter_actor_contains (ClutterActor *self,
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (descendant), FALSE);
|
||||
|
||||
for (actor = descendant; actor; actor = actor->priv->parent_actor)
|
||||
for (actor = descendant; actor; actor = actor->priv->parent)
|
||||
if (actor == self)
|
||||
return TRUE;
|
||||
|
||||
@ -10613,18 +10674,9 @@ container_raise (ClutterContainer *container,
|
||||
ClutterActor *sibling)
|
||||
{
|
||||
ClutterActor *self = CLUTTER_ACTOR (container);
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
|
||||
priv->children = g_list_remove (priv->children, child);
|
||||
|
||||
if (sibling == NULL)
|
||||
priv->children = g_list_append (priv->children, child);
|
||||
else
|
||||
{
|
||||
gint index_ = g_list_index (priv->children, sibling) + 1;
|
||||
|
||||
priv->children = g_list_insert (priv->children, child, index_);
|
||||
}
|
||||
remove_child (self, child);
|
||||
insert_child_above (self, child, sibling);
|
||||
|
||||
clutter_actor_queue_relayout (self);
|
||||
}
|
||||
@ -10635,46 +10687,16 @@ container_lower (ClutterContainer *container,
|
||||
ClutterActor *sibling)
|
||||
{
|
||||
ClutterActor *self = CLUTTER_ACTOR (container);
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
|
||||
priv->children = g_list_remove (priv->children, child);
|
||||
|
||||
if (sibling == NULL)
|
||||
priv->children = g_list_prepend (priv->children, child);
|
||||
else
|
||||
{
|
||||
gint index_ = g_list_index (priv->children, sibling);
|
||||
|
||||
priv->children = g_list_insert (priv->children, child, index_);
|
||||
}
|
||||
remove_child (self, child);
|
||||
insert_child_below (self, child, sibling);
|
||||
|
||||
clutter_actor_queue_relayout (self);
|
||||
}
|
||||
|
||||
static gint
|
||||
sort_by_depth (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const ClutterActor *actor_a = a;
|
||||
const ClutterActor *actor_b = b;
|
||||
|
||||
if (actor_a->priv->z < actor_b->priv->z)
|
||||
return -1;
|
||||
|
||||
if (actor_a->priv->z > actor_b->priv->z)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
container_sort_by_depth (ClutterContainer *container)
|
||||
{
|
||||
ClutterActorPrivate *priv = CLUTTER_ACTOR (container)->priv;
|
||||
|
||||
priv->children = g_list_sort (priv->children, sort_by_depth);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -12061,7 +12083,7 @@ ClutterActor *
|
||||
_clutter_actor_get_stage_internal (ClutterActor *actor)
|
||||
{
|
||||
while (actor && !CLUTTER_ACTOR_IS_TOPLEVEL (actor))
|
||||
actor = actor->priv->parent_actor;
|
||||
actor = actor->priv->parent;
|
||||
|
||||
return actor;
|
||||
}
|
||||
@ -13177,7 +13199,7 @@ clutter_actor_has_allocation (ClutterActor *self)
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
return priv->parent_actor != NULL &&
|
||||
return priv->parent != NULL &&
|
||||
CLUTTER_ACTOR_IS_VISIBLE (self) &&
|
||||
!priv->needs_allocation;
|
||||
}
|
||||
@ -14254,13 +14276,22 @@ ClutterActor *
|
||||
clutter_actor_get_child_at_index (ClutterActor *self,
|
||||
gint index_)
|
||||
{
|
||||
ClutterActor *iter;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
||||
g_return_val_if_fail (index_ <= self->priv->n_children, NULL);
|
||||
|
||||
return g_list_nth_data (self->priv->children, index_);
|
||||
for (iter = self->priv->first_child, i = 0;
|
||||
iter != NULL && i < index_;
|
||||
iter = iter->priv->next_sibling, i += 1)
|
||||
;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
/* _clutter_actor_foreach_child:
|
||||
/*< private >
|
||||
* _clutter_actor_foreach_child:
|
||||
* @actor: The actor whos children you want to iterate
|
||||
* @callback: The function to call for each child
|
||||
* @user_data: Private data to pass to @callback
|
||||
@ -14272,16 +14303,20 @@ clutter_actor_get_child_at_index (ClutterActor *self,
|
||||
* %FALSE if a callback broke out of iteration early.
|
||||
*/
|
||||
gboolean
|
||||
_clutter_actor_foreach_child (ClutterActor *self,
|
||||
ClutterForeachCallback callback,
|
||||
void *user_data)
|
||||
_clutter_actor_foreach_child (ClutterActor *self,
|
||||
ClutterForeachCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterActor *iter;
|
||||
gboolean cont;
|
||||
GList *l;
|
||||
|
||||
for (cont = TRUE, l = priv->children; cont && l; l = l->next)
|
||||
cont = callback (l->data, user_data);
|
||||
for (cont = TRUE, iter = priv->first_child;
|
||||
cont && iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
cont = callback (iter, user_data);
|
||||
}
|
||||
|
||||
return cont;
|
||||
}
|
||||
@ -14337,9 +14372,14 @@ _clutter_actor_traverse_breadth (ClutterActor *actor,
|
||||
break;
|
||||
else if (!(flags & CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN))
|
||||
{
|
||||
GList *l;
|
||||
for (l = actor->priv->children; l; l = l->next)
|
||||
g_queue_push_tail (queue, l->data);
|
||||
ClutterActor *iter;
|
||||
|
||||
for (iter = actor->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
g_queue_push_tail (queue, iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14361,14 +14401,18 @@ _clutter_actor_traverse_depth (ClutterActor *actor,
|
||||
|
||||
if (!(flags & CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN))
|
||||
{
|
||||
GList *l;
|
||||
for (l = actor->priv->children; l; l = l->next)
|
||||
ClutterActor *iter;
|
||||
|
||||
for (iter = actor->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
{
|
||||
flags = _clutter_actor_traverse_depth (l->data,
|
||||
flags = _clutter_actor_traverse_depth (iter,
|
||||
before_children_callback,
|
||||
after_children_callback,
|
||||
current_depth + 1,
|
||||
user_data);
|
||||
|
||||
if (flags & CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK)
|
||||
return CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK;
|
||||
}
|
||||
@ -14625,7 +14669,7 @@ clutter_actor_update_effective_expand (ClutterActor *self)
|
||||
/* we don't need to traverse the children of the actor if expand
|
||||
* has been explicitly set
|
||||
*/
|
||||
if (priv->children != NULL || !(priv->x_expand_set && priv->y_expand_set))
|
||||
if (priv->n_children != 0 || !(priv->x_expand_set && priv->y_expand_set))
|
||||
{
|
||||
gboolean dummy = FALSE;
|
||||
|
||||
@ -14743,7 +14787,7 @@ clutter_actor_queue_compute_expand (ClutterActor *self)
|
||||
changed_anything = TRUE;
|
||||
}
|
||||
|
||||
parent_actor = parent_actor->priv->parent_actor;
|
||||
parent_actor = parent_actor->priv->parent;
|
||||
}
|
||||
|
||||
if (changed_anything)
|
||||
|
Loading…
Reference in New Issue
Block a user