actor: Add child insertion methods

We should allow inserting children at given indices, and at given
stacking positions (relative or not to other children).
This commit is contained in:
Emmanuele Bassi 2011-11-29 17:41:33 +00:00 committed by Emmanuele Bassi
parent 8c2118542c
commit 86ec629776
2 changed files with 257 additions and 31 deletions

View File

@ -8976,7 +8976,7 @@ clutter_actor_get_children (ClutterActor *self)
} }
/*< private > /*< private >
* clutter_actor_insert_child: * insert_child_at_depth:
* @self: a #ClutterActor * @self: a #ClutterActor
* @child: a #ClutterActor * @child: a #ClutterActor
* *
@ -8984,8 +8984,9 @@ clutter_actor_get_children (ClutterActor *self)
* the depth as the insertion criteria. * the depth as the insertion criteria.
*/ */
static void static void
clutter_actor_insert_child (ClutterActor *self, insert_child_at_depth (ClutterActor *self,
ClutterActor *child) ClutterActor *child,
gpointer dummy G_GNUC_UNUSED)
{ {
ClutterActorPrivate *priv = self->priv; ClutterActorPrivate *priv = self->priv;
GList *l, *prev = NULL; GList *l, *prev = NULL;
@ -9014,31 +9015,114 @@ clutter_actor_insert_child (ClutterActor *self,
} }
else else
priv->children = l; priv->children = l;
priv->n_children++;
} }
/** static void
* clutter_actor_add_child: insert_child_at_index (ClutterActor *self,
* @self: a #ClutterActor ClutterActor *child,
* @child: a #ClutterActor gpointer data_)
* {
* Adds @child to the children of @self. gint index_ = GPOINTER_TO_INT (data_);
* ClutterActorPrivate *priv;
* This function will acquire a reference on @child.
* priv = self->priv;
* Since: 1.10
*/ if (index_ == 0)
void priv->children = g_list_prepend (priv->children, child);
clutter_actor_add_child (ClutterActor *self, else if (index < 0)
ClutterActor *child) priv->children = g_list_append (priv->children, child);
else
priv->children = g_list_insert (priv->children, child, index_);
}
static void
insert_child_above (ClutterActor *self,
ClutterActor *child,
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);
return;
}
for (l = priv->children; l != NULL; l = l->next)
{
ClutterActor *iter = l->data;
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;
}
}
static void
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);
return;
}
for (l = priv->children; l != NULL; l = l->next)
{
ClutterActor *iter = l->data;
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;
}
typedef void (* ClutterActorAddChildFunc) (ClutterActor *parent,
ClutterActor *child,
gpointer data);
static void
clutter_actor_add_child_internal (ClutterActor *self,
ClutterActor *child,
ClutterActorAddChildFunc add_func,
gpointer data)
{ {
ClutterTextDirection text_dir; ClutterTextDirection text_dir;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
g_return_if_fail (self != child);
if (child->priv->parent_actor != NULL) if (child->priv->parent_actor != NULL)
{ {
g_warning ("Cannot set a parent on an actor which has a parent. " g_warning ("Cannot set a parent on an actor which has a parent. "
@ -9061,8 +9145,10 @@ clutter_actor_add_child (ClutterActor *self,
g_object_ref_sink (child); g_object_ref_sink (child);
child->priv->parent_actor = self; child->priv->parent_actor = self;
/* Maintain an explicit list of children for every actor... */ /* delegate the actual insertion */
clutter_actor_insert_child (self, child); add_func (self, child, data);
self->priv->n_children += 1;
/* if push_internal() has been called then we automatically set /* if push_internal() has been called then we automatically set
* the flag on the actor * the flag on the actor
@ -9124,6 +9210,136 @@ clutter_actor_add_child (ClutterActor *self,
} }
} }
/**
* clutter_actor_add_child:
* @self: a #ClutterActor
* @child: a #ClutterActor
*
* Adds @child to the children of @self.
*
* This function will acquire a reference on @child that will only
* be released when calling clutter_actor_remove_child().
*
* This function will take into consideration the #ClutterActor:depth
* of @child, and will keep the list of children sorted.
*
* Since: 1.10
*/
void
clutter_actor_add_child (ClutterActor *self,
ClutterActor *child)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
g_return_if_fail (self != child);
clutter_actor_add_child_internal (self, child,
insert_child_at_depth,
NULL);
}
/**
* clutter_actor_insert_child_at_index:
* @self: a #ClutterActor
* @child: a #ClutterActor
* @index_: the index
*
* Inserts @child into the list of children of @self, using the
* given @index_.
*
* This function will acquire a reference on @child that will only
* be released when calling clutter_actor_remove_child().
*
* This function will not take into consideration the #ClutterActor:depth
* of @child.
*
* Since: 1.10
*/
void
clutter_actor_insert_child_at_index (ClutterActor *self,
ClutterActor *child,
gint index_)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
g_return_if_fail (child->priv->parent_actor == NULL);
g_return_if_fail (index_ < self->priv->n_children);
clutter_actor_add_child_internal (self, child,
insert_child_at_index,
GINT_TO_POINTER (index_));
}
/**
* clutter_actor_insert_child_above:
* @self: a #ClutterActor
* @child: a #ClutterActor
* @sibling: (allow-none): a child of @self, or %NULL
*
* Inserts @child into the list of children of @self, above another
* child of @self or, if @sibling is %NULL, above all the children
* of @self.
*
* This function will acquire a reference on @child that will only
* be released when calling clutter_actor_remove_child().
*
* This function will not take into consideration the #ClutterActor:depth
* of @child.
*
* Since: 1.10
*/
void
clutter_actor_insert_child_above (ClutterActor *self,
ClutterActor *child,
ClutterActor *sibling)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
g_return_if_fail (child->priv->parent_actor == NULL);
g_return_if_fail (sibling == NULL ||
(CLUTTER_IS_ACTOR (sibling) &&
sibling->priv->parent_actor == self));
clutter_actor_add_child_internal (self, child,
insert_child_above,
sibling);
}
/**
* clutter_actor_insert_child_below:
* @self: a #ClutterActor
* @child: a #ClutterActor
* @sibling: (allow-none): a child of @self, or %NULL
*
* Inserts @child into the list of children of @self, below another
* child of @self or, if @sibling is %NULL, below all the children
* of @self.
*
* This function will acquire a reference on @child that will only
* be released when calling clutter_actor_remove_child().
*
* This function will not take into consideration the #ClutterActor:depth
* of @child.
*
* Since: 1.10
*/
void
clutter_actor_insert_child_below (ClutterActor *self,
ClutterActor *child,
ClutterActor *sibling)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
g_return_if_fail (child->priv->parent_actor == NULL);
g_return_if_fail (sibling == NULL ||
(CLUTTER_IS_ACTOR (sibling) &&
sibling->priv->parent_actor == self));
clutter_actor_add_child_internal (self, child,
insert_child_below,
sibling);
}
/** /**
* clutter_actor_set_parent: * clutter_actor_set_parent:
* @self: A #ClutterActor * @self: A #ClutterActor
@ -9164,9 +9380,9 @@ clutter_actor_get_parent (ClutterActor *self)
* Retrieves the 'paint' visibility of an actor recursively checking for non * Retrieves the 'paint' visibility of an actor recursively checking for non
* visible parents. * visible parents.
* *
* This is by definition the same as CLUTTER_ACTOR_IS_MAPPED(). * This is by definition the same as %CLUTTER_ACTOR_IS_MAPPED.
* *
* Return Value: TRUE if the actor is visibile and will be painted. * Return Value: %TRUE if the actor is visibile and will be painted.
* *
* Since: 0.8.4 * Since: 0.8.4
*/ */

View File

@ -351,6 +351,7 @@ gboolean clutter_actor_get_fixed_position_set (ClutterActor
void clutter_actor_set_fixed_position_set (ClutterActor *self, void clutter_actor_set_fixed_position_set (ClutterActor *self,
gboolean is_set); gboolean is_set);
/* Actor geometry */
gfloat clutter_actor_get_width (ClutterActor *self); gfloat clutter_actor_get_width (ClutterActor *self);
gfloat clutter_actor_get_height (ClutterActor *self); gfloat clutter_actor_get_height (ClutterActor *self);
void clutter_actor_set_width (ClutterActor *self, void clutter_actor_set_width (ClutterActor *self,
@ -363,6 +364,9 @@ void clutter_actor_set_x (ClutterActor
gfloat x); gfloat x);
void clutter_actor_set_y (ClutterActor *self, void clutter_actor_set_y (ClutterActor *self,
gfloat y); gfloat y);
void clutter_actor_set_depth (ClutterActor *self,
gfloat depth);
gfloat clutter_actor_get_depth (ClutterActor *self);
void clutter_actor_set_layout_manager (ClutterActor *self, void clutter_actor_set_layout_manager (ClutterActor *self,
ClutterLayoutManager *manager); ClutterLayoutManager *manager);
ClutterLayoutManager *clutter_actor_get_layout_manager (ClutterActor *self); ClutterLayoutManager *clutter_actor_get_layout_manager (ClutterActor *self);
@ -445,8 +449,18 @@ void clutter_actor_set_clip_to_allocation (ClutterActor
gboolean clip_set); gboolean clip_set);
gboolean clutter_actor_get_clip_to_allocation (ClutterActor *self); gboolean clutter_actor_get_clip_to_allocation (ClutterActor *self);
/* Actor hierarchy */
void clutter_actor_add_child (ClutterActor *self, void clutter_actor_add_child (ClutterActor *self,
ClutterActor *child); ClutterActor *child);
void clutter_actor_insert_child_at_index (ClutterActor *self,
ClutterActor *child,
gint index_);
void clutter_actor_insert_child_above (ClutterActor *self,
ClutterActor *child,
ClutterActor *sibling);
void clutter_actor_insert_child_below (ClutterActor *self,
ClutterActor *child,
ClutterActor *sibling);
void clutter_actor_remove_child (ClutterActor *self, void clutter_actor_remove_child (ClutterActor *self,
ClutterActor *child); ClutterActor *child);
GList * clutter_actor_get_children (ClutterActor *self); GList * clutter_actor_get_children (ClutterActor *self);
@ -459,16 +473,12 @@ void clutter_actor_unparent (ClutterActor
gboolean clutter_actor_contains (ClutterActor *self, gboolean clutter_actor_contains (ClutterActor *self,
ClutterActor *descendant); ClutterActor *descendant);
ClutterActor* clutter_actor_get_stage (ClutterActor *actor); ClutterActor* clutter_actor_get_stage (ClutterActor *actor);
void clutter_actor_raise (ClutterActor *self, void clutter_actor_raise (ClutterActor *self,
ClutterActor *below); ClutterActor *below);
void clutter_actor_lower (ClutterActor *self, void clutter_actor_lower (ClutterActor *self,
ClutterActor *above); ClutterActor *above);
void clutter_actor_raise_top (ClutterActor *self); void clutter_actor_raise_top (ClutterActor *self);
void clutter_actor_lower_bottom (ClutterActor *self); void clutter_actor_lower_bottom (ClutterActor *self);
void clutter_actor_set_depth (ClutterActor *self,
gfloat depth);
gfloat clutter_actor_get_depth (ClutterActor *self);
void clutter_actor_set_scale (ClutterActor *self, void clutter_actor_set_scale (ClutterActor *self,
gdouble scale_x, gdouble scale_x,