From 27ce96150e27c968dfba4108d1f2a06805327353 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 13 Aug 2007 17:00:58 +0000 Subject: [PATCH] Move depth ordering methods from ClutterGroup to ClutterContainer Since ClutterActor directly calls ClutterGroup methods we need ClutterContainer to provide them, so that every container actor behaves the same way. This patch makes ::raise, ::lower and ::sort_depth_order virtual functions of the ClutterContainer interface, implemented by ClutterGroup. The documentation has been added and deprecation warnings have been added as well. --- clutter/clutter-container.c | 67 +++++++++ clutter/clutter-container.h | 19 ++- clutter/clutter-group.c | 223 +++++++++++++++++------------ clutter/clutter-group.h | 3 +- doc/reference/clutter-sections.txt | 3 + 5 files changed, 222 insertions(+), 93 deletions(-) diff --git a/clutter/clutter-container.c b/clutter/clutter-container.c index 2f918074c..9f41349c4 100644 --- a/clutter/clutter-container.c +++ b/clutter/clutter-container.c @@ -399,3 +399,70 @@ clutter_container_find_child_by_id (ClutterContainer *container, return CLUTTER_CONTAINER_GET_IFACE (container)->find_child_by_id (container, child_id); } + +/** + * clutter_container_raise: + * @container: a #ClutterContainer + * @actor: the actor to raise + * @sibling: the sibling to raise to, or %NULL to raise at the top + * + * Raises @actor at @sibling level, in the depth ordering. + * + * Since: 0.6 + */ +void +clutter_container_raise (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + if (actor == sibling) + return; + + CLUTTER_CONTAINER_GET_IFACE (container)->raise (container, actor, sibling); +} + +/** + * clutter_container_lower: + * @container: a #ClutterContainer + * @actor: the actor to raise + * @sibling: the sibling to lower to, or %NULL to lower at the bottom + * + * Lowers @actor at @sibling level, in the depth ordering. + * + * Since: 0.6 + */ +void +clutter_container_lower (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + if (actor == sibling) + return; + + CLUTTER_CONTAINER_GET_IFACE (container)->raise (container, actor, sibling); +} + +/** + * clutter_container_sort_depth_order: + * @container: a #ClutterContainer + * + * Sorts a container children using their depth. This function should not + * be normally used by applications. + * + * Since: 0.6 + */ +void +clutter_container_sort_depth_order (ClutterContainer *container) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + + CLUTTER_CONTAINER_GET_IFACE (container)->sort_depth_order (container); +} diff --git a/clutter/clutter-container.h b/clutter/clutter-container.h index 0e85d2ac8..013bb46da 100644 --- a/clutter/clutter-container.h +++ b/clutter/clutter-container.h @@ -49,6 +49,10 @@ typedef struct _ClutterContainerIface ClutterContainerIface; * @find_child_by_id: virtual function for searching a container children * using its unique id. Should recurse through its children. This function * is used when "picking" actors (e.g. by clutter_stage_get_actor_at_pos()) + * @raise: virtual function for raising a child + * @lower: virtual function for lowering a child + * @sort_depth_order: virtual function for sorting the children of a + * container depending on their depth * @actor_added: signal class handler for ClutterContainer::actor_added * @actor_removed: signal class handler for ClutterContainer::actor_removed * @@ -71,6 +75,13 @@ struct _ClutterContainerIface gpointer user_data); ClutterActor *(* find_child_by_id) (ClutterContainer *container, guint child_id); + void (* raise) (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); + void (* lower) (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); + void (* sort_depth_order) (ClutterContainer *container); /* signals */ void (* actor_added) (ClutterContainer *container, @@ -103,7 +114,13 @@ void clutter_container_foreach (ClutterContainer *container, gpointer user_data); ClutterActor *clutter_container_find_child_by_id (ClutterContainer *container, guint child_id); - +void clutter_container_raise (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); +void clutter_container_lower (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); +void clutter_container_sort_depth_order (ClutterContainer *container); G_END_DECLS diff --git a/clutter/clutter-group.c b/clutter/clutter-group.c index 5d5ce4747..c67cc1d9e 100644 --- a/clutter/clutter-group.c +++ b/clutter/clutter-group.c @@ -317,6 +317,114 @@ clutter_group_real_find_child_by_id (ClutterContainer *container, return actor; } +static void +clutter_group_real_raise (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + ClutterGroup *self = CLUTTER_GROUP (container); + ClutterGroupPrivate *priv = self->priv; + gint pos; + + pos = g_list_index (priv->children, actor) + 1; + + priv->children = g_list_remove (priv->children, actor); + + /* Raise at the top */ + if (!sibling) + { + GList *last_item; + + last_item = g_list_last (priv->children); + + if (last_item) + sibling = last_item->data; + + priv->children = g_list_append (priv->children, actor); + } + else + { + priv->children = g_list_insert (priv->children, actor, pos); + } + + /* set Z ordering a value below, this will then call sort + * as values are equal ordering shouldn't change but Z + * values will be correct. + * + * FIXME: optimise + */ + if (sibling && + clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) + { + clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); + } +} + +static void +clutter_group_real_lower (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + ClutterGroup *self = CLUTTER_GROUP (container); + ClutterGroupPrivate *priv = self->priv; + gint pos; + + pos = g_list_index (priv->children, actor) - 1; + + priv->children = g_list_remove (priv->children, actor); + + /* Push to bottom */ + if (!sibling) + { + GList *last_item; + + last_item = g_list_first (priv->children); + + if (last_item) + sibling = last_item->data; + + priv->children = g_list_prepend (priv->children, actor); + } + else + priv->children = g_list_insert (priv->children, actor, pos); + + /* See comment in group_raise for this */ + if (sibling && + clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) + { + clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); + } +} + +static gint +sort_z_order (gconstpointer a, + gconstpointer b) +{ + ClutterActor *actor_a = CLUTTER_ACTOR (a); + ClutterActor *actor_b = CLUTTER_ACTOR (b); + + if (clutter_actor_get_depth (actor_a) == clutter_actor_get_depth (actor_b)) + return 0; + + if (clutter_actor_get_depth (actor_a) > clutter_actor_get_depth (actor_b)) + return 1; + + return -1; +} + +static void +clutter_group_real_sort_depth_order (ClutterContainer *container) +{ + ClutterGroup *self = CLUTTER_GROUP (container); + ClutterGroupPrivate *priv = self->priv; + + priv->children = g_list_sort (priv->children, sort_z_order); + + if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (self))) + clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); + +} + static void clutter_container_iface_init (ClutterContainerIface *iface) { @@ -324,6 +432,9 @@ clutter_container_iface_init (ClutterContainerIface *iface) iface->remove = clutter_group_real_remove; iface->foreach = clutter_group_real_foreach; iface->find_child_by_id = clutter_group_real_find_child_by_id; + iface->raise = clutter_group_real_raise; + iface->lower = clutter_group_real_lower; + iface->sort_depth_order = clutter_group_real_sort_depth_order; } static void @@ -589,50 +700,22 @@ clutter_group_find_child_by_id (ClutterGroup *self, * @sibling: a #ClutterActor * * FIXME + * + * Deprecated: 0.6: Use clutter_container_raise() instead. */ void clutter_group_raise (ClutterGroup *self, ClutterActor *actor, ClutterActor *sibling) { - ClutterGroupPrivate *priv; - gint pos; + g_return_if_fail (CLUTTER_IS_GROUP (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); - g_return_if_fail (actor != sibling); - - priv = self->priv; - - pos = g_list_index (priv->children, actor) + 1; - - priv->children = g_list_remove (priv->children, actor); - - if (sibling == NULL) - { - GList *last_item; - - /* Raise top */ - last_item = g_list_last (priv->children); - - if (last_item) - sibling = last_item->data; - - priv->children = g_list_append (priv->children, actor); - } - else - { - priv->children = g_list_insert (priv->children, actor, pos); - } - - /* set Z ordering a value below, this will then call sort - * as values are equal ordering shouldn't change but Z - * values will be correct. - * FIXME: optimise - */ - if ( sibling && - clutter_actor_get_depth(sibling) != clutter_actor_get_depth (actor)) - clutter_actor_set_depth (actor, - clutter_actor_get_depth (sibling)); + if (actor == sibling) + return; + clutter_container_raise (CLUTTER_CONTAINER (self), actor, sibling); } /** @@ -642,57 +725,22 @@ clutter_group_raise (ClutterGroup *self, * @sibling: a #ClutterActor * * FIXME + * + * Deprecated: 0.6: Use clutter_container_lower() instead */ void -clutter_group_lower (ClutterGroup *self, +clutter_group_lower (ClutterGroup *self, ClutterActor *actor, ClutterActor *sibling) { - ClutterGroupPrivate *priv; - gint pos; + g_return_if_fail (CLUTTER_IS_GROUP (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); - g_return_if_fail (actor != sibling); + if (actor == sibling) + return; - priv = self->priv; - - pos = g_list_index (priv->children, actor) - 1; - - priv->children = g_list_remove (priv->children, actor); - - if (sibling == NULL) - { - GList *last_item; - /* Raise top */ - last_item = g_list_first (priv->children); - - if (last_item) - sibling = last_item->data; - - priv->children = g_list_prepend (priv->children, actor); - } - else - priv->children = g_list_insert (priv->children, actor, pos); - - /* See comment in group_raise for this */ - if (sibling && - clutter_actor_get_depth(sibling) != clutter_actor_get_depth(actor)) - clutter_actor_set_depth (actor, - clutter_actor_get_depth(sibling)); -} - -static gint -sort_z_order (gconstpointer a, - gconstpointer b) -{ - if (clutter_actor_get_depth (CLUTTER_ACTOR(a)) - == clutter_actor_get_depth (CLUTTER_ACTOR(b))) - return 0; - - if (clutter_actor_get_depth (CLUTTER_ACTOR(a)) - > clutter_actor_get_depth (CLUTTER_ACTOR(b))) - return 1; - - return -1; + clutter_container_lower (CLUTTER_CONTAINER (self), actor, sibling); } /** @@ -701,18 +749,13 @@ sort_z_order (gconstpointer a, * * Sorts a #ClutterGroup's children by there depth value. * This function should not be used by applications. - **/ + * + * Deprecated: 0.6: Use clutter_container_sort_depth_order() instead. + */ void clutter_group_sort_depth_order (ClutterGroup *self) { - ClutterGroupPrivate *priv; + g_return_if_fail (CLUTTER_IS_GROUP (self)); - g_return_if_fail (CLUTTER_IS_GROUP(self)); - - priv = self->priv; - - priv->children = g_list_sort (priv->children, sort_z_order); - - if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR(self))) - clutter_actor_queue_redraw (CLUTTER_ACTOR(self)); + clutter_container_sort_depth_order (CLUTTER_CONTAINER (self)); } diff --git a/clutter/clutter-group.h b/clutter/clutter-group.h index 360bdf23c..d36f6a285 100644 --- a/clutter/clutter-group.h +++ b/clutter/clutter-group.h @@ -104,8 +104,6 @@ void clutter_group_remove (ClutterGroup *group, ClutterActor *actor); ClutterActor *clutter_group_find_child_by_id (ClutterGroup *self, guint id); -#endif /* CLUTTER_DISABLE_DEPRECATED */ - void clutter_group_raise (ClutterGroup *self, ClutterActor *actor, ClutterActor *sibling); @@ -113,6 +111,7 @@ void clutter_group_lower (ClutterGroup *self, ClutterActor *actor, ClutterActor *sibling); void clutter_group_sort_depth_order (ClutterGroup *self); +#endif /* CLUTTER_DISABLE_DEPRECATED */ G_END_DECLS diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index 6026a4534..ee6158e1c 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -219,6 +219,9 @@ clutter_container_remove_valist clutter_container_get_children clutter_container_foreach clutter_container_find_child_by_id +clutter_container_raise +clutter_container_lower +clutter_container_sort_depth_order ClutterContainer CLUTTER_TYPE_CONTAINER