[gnome-shell] Move shared container methods from st-private to a common base class



commit 54d11b65a1c4a6622279bd0cf98d9a7ade352388
Author: Florian Müllner <fmuellner src gnome org>
Date:   Sat Mar 27 05:09:53 2010 +0100

    Move shared container methods from st-private to a common base class
    
    Add StContainer, which implements the ClutterContainer interface based
    on the container methods in st-private and make the existing containers
    subclass it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=613907

 src/Makefile-st.am            |    2 +
 src/shell-generic-container.c |  109 ++------------
 src/shell-generic-container.h |    5 +-
 src/st/st-box-layout.c        |  220 +++++---------------------
 src/st/st-box-layout.h        |   16 +--
 src/st/st-container.c         |  348 +++++++++++++++++++++++++++++++++++++++++
 src/st/st-container.h         |   68 ++++++++
 src/st/st-overflow-box.c      |  163 ++-----------------
 src/st/st-overflow-box.h      |    6 +-
 src/st/st-private.c           |  228 ---------------------------
 src/st/st-private.h           |   21 ---
 src/st/st-table.c             |  140 +++++------------
 src/st/st-table.h             |    6 +-
 13 files changed, 535 insertions(+), 797 deletions(-)
---
diff --git a/src/Makefile-st.am b/src/Makefile-st.am
index c9428d1..d3597fd 100644
--- a/src/Makefile-st.am
+++ b/src/Makefile-st.am
@@ -74,6 +74,7 @@ st_source_h =					\
     st/st-button.h				\
     st/st-clickable.h           \
     st/st-clipboard.h				\
+    st/st-container.h				\
     st/st-drawing-area.h        \
     st/st-entry.h				\
     st/st-im-text.h				\
@@ -120,6 +121,7 @@ st_source_c =					\
     st/st-button.c				\
     st/st-clickable.c           \
     st/st-clipboard.c				\
+    st/st-container.c				\
     st/st-drawing-area.c        \
     st/st-entry.c				\
     st/st-im-text.c				\
diff --git a/src/shell-generic-container.c b/src/shell-generic-container.c
index 9143368..a177311 100644
--- a/src/shell-generic-container.c
+++ b/src/shell-generic-container.c
@@ -25,12 +25,11 @@ static void shell_generic_container_iface_init (ClutterContainerIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE(ShellGenericContainer,
                         shell_generic_container,
-                        ST_TYPE_WIDGET,
+                        ST_TYPE_CONTAINER,
                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
                                                shell_generic_container_iface_init));
 
 struct _ShellGenericContainerPrivate {
-  GList *children;
   GHashTable *skip_paint;
 };
 
@@ -126,11 +125,12 @@ static void
 shell_generic_container_paint (ClutterActor  *actor)
 {
   ShellGenericContainer *self = (ShellGenericContainer*) actor;
-  GList *iter;
+  GList *iter, *children;
 
   CLUTTER_ACTOR_CLASS (shell_generic_container_parent_class)->paint (actor);
 
-  for (iter = self->priv->children; iter; iter = iter->next)
+  children = st_container_get_children_list (ST_CONTAINER (actor));
+  for (iter = children; iter; iter = iter->next)
     {
       ClutterActor *child = iter->data;
 
@@ -146,11 +146,12 @@ shell_generic_container_pick (ClutterActor        *actor,
                               const ClutterColor  *color)
 {
   ShellGenericContainer *self = (ShellGenericContainer*) actor;
-  GList *iter;
+  GList *iter, *children;
 
   CLUTTER_ACTOR_CLASS (shell_generic_container_parent_class)->pick (actor, color);
 
-  for (iter = self->priv->children; iter; iter = iter->next)
+  children = st_container_get_children_list (ST_CONTAINER (actor));
+  for (iter = children; iter; iter = iter->next)
     {
       ClutterActor *child = iter->data;
 
@@ -215,29 +216,6 @@ shell_generic_container_set_skip_paint (ShellGenericContainer  *self,
     g_hash_table_insert (self->priv->skip_paint, child, child);
 }
 
-/**
- * shell_generic_container_remove_all:
- * @self: A #ShellGenericContainer
- *
- * Removes all child actors from @self.
- */
-void
-shell_generic_container_remove_all (ShellGenericContainer *self)
-{
-  /* copied from clutter_group_remove_all() */
-
-  GList *children;
-
-  children = self->priv->children;
-  while (children)
-    {
-      ClutterActor *child = children->data;
-      children = children->next;
-
-      clutter_container_remove_actor (CLUTTER_CONTAINER (self), child);
-    }
-}
-
 static void
 shell_generic_container_finalize (GObject *object)
 {
@@ -249,24 +227,12 @@ shell_generic_container_finalize (GObject *object)
 }
 
 static void
-shell_generic_container_dispose (GObject *object)
-{
-  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (object)->priv;
-
-  while (priv->children)
-    clutter_actor_destroy (priv->children->data);
-
-  G_OBJECT_CLASS (shell_generic_container_parent_class)->dispose (object);
-}
-
-static void
 shell_generic_container_class_init (ShellGenericContainerClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
 
   gobject_class->finalize = shell_generic_container_finalize;
-  gobject_class->dispose = shell_generic_container_dispose;
 
   actor_class->get_preferred_width = shell_generic_container_get_preferred_width;
   actor_class->get_preferred_height = shell_generic_container_get_preferred_height;
@@ -305,73 +271,18 @@ shell_generic_container_class_init (ShellGenericContainerClass *klass)
 }
 
 static void
-shell_generic_container_add_actor (ClutterContainer *container,
-                                   ClutterActor     *actor)
-{
-  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
-
-  _st_container_add_actor (container, actor, &priv->children);
-}
-
-static void
-shell_generic_container_remove_actor (ClutterContainer *container,
-                                      ClutterActor     *actor)
+shell_generic_container_actor_removed (ClutterContainer *container,
+                                       ClutterActor     *actor)
 {
   ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
 
   g_hash_table_remove (priv->skip_paint, actor);
-
-  _st_container_remove_actor (container, actor, &priv->children);
-}
-
-static void
-shell_generic_container_foreach (ClutterContainer *container,
-                                 ClutterCallback   callback,
-                                 gpointer          callback_data)
-{
-  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
-
-  _st_container_foreach (container, callback, callback_data,
-                         &priv->children);
-}
-
-static void
-shell_generic_container_lower (ClutterContainer *container,
-                               ClutterActor     *actor,
-                               ClutterActor     *sibling)
-{
-  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
-
-  _st_container_lower (container, actor, sibling, &priv->children);
-}
-
-static void
-shell_generic_container_raise (ClutterContainer *container,
-                        ClutterActor     *actor,
-                        ClutterActor     *sibling)
-{
-  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
-
-  _st_container_raise (container, actor, sibling, &priv->children);
-}
-
-static void
-shell_generic_container_sort_depth_order (ClutterContainer *container)
-{
-  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
-
-  _st_container_sort_depth_order (container, &priv->children);
 }
 
 static void
 shell_generic_container_iface_init (ClutterContainerIface *iface)
 {
-  iface->add = shell_generic_container_add_actor;
-  iface->remove = shell_generic_container_remove_actor;
-  iface->foreach = shell_generic_container_foreach;
-  iface->lower = shell_generic_container_lower;
-  iface->raise = shell_generic_container_raise;
-  iface->sort_depth_order = shell_generic_container_sort_depth_order;
+  iface->actor_removed = shell_generic_container_actor_removed;
 }
 
 static void
diff --git a/src/shell-generic-container.h b/src/shell-generic-container.h
index e14ef45..16170ec 100644
--- a/src/shell-generic-container.h
+++ b/src/shell-generic-container.h
@@ -29,14 +29,14 @@ typedef struct _ShellGenericContainerPrivate ShellGenericContainerPrivate;
 
 struct _ShellGenericContainer
 {
-    StWidget parent;
+    StContainer parent;
 
     ShellGenericContainerPrivate *priv;
 };
 
 struct _ShellGenericContainerClass
 {
-    StWidgetClass parent_class;
+    StContainerClass parent_class;
 };
 
 GType    shell_generic_container_get_type         (void) G_GNUC_CONST;
@@ -48,6 +48,5 @@ gboolean shell_generic_container_get_skip_paint   (ShellGenericContainer *self,
 void     shell_generic_container_set_skip_paint   (ShellGenericContainer *self,
                                                    ClutterActor          *actor,
                                                    gboolean               skip);
-void     shell_generic_container_remove_all       (ShellGenericContainer *self);
 
 #endif /* __SHELL_GENERIC_CONTAINER_H__ */
diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c
index 0b47770..89fd91b 100644
--- a/src/st/st-box-layout.c
+++ b/src/st/st-box-layout.c
@@ -57,11 +57,10 @@
 #include "st-box-layout-child.h"
 
 
-
 static void st_box_container_iface_init (ClutterContainerIface *iface);
 static void st_box_scrollable_interface_init (StScrollableInterface *iface);
 
-G_DEFINE_TYPE_WITH_CODE (StBoxLayout, st_box_layout, ST_TYPE_WIDGET,
+G_DEFINE_TYPE_WITH_CODE (StBoxLayout, st_box_layout, ST_TYPE_CONTAINER,
                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
                                                 st_box_container_iface_init)
                          G_IMPLEMENT_INTERFACE (ST_TYPE_SCROLLABLE,
@@ -82,8 +81,6 @@ enum {
 
 struct _StBoxLayoutPrivate
 {
-  GList        *children;
-
   guint         spacing;
 
   guint         is_vertical : 1;
@@ -94,6 +91,17 @@ struct _StBoxLayoutPrivate
 };
 
 /*
+ * ClutterContainer Interface Implementation
+ */
+static void
+st_box_sort_depth_order (ClutterContainer *container)
+{
+  /* The parent class' implementation would mess up the
+   * left-to-right order of the children - do nothing instead
+   */
+}
+
+/*
  * StScrollable Interface Implementation
  */
 static void
@@ -185,76 +193,10 @@ st_box_scrollable_interface_init (StScrollableInterface *iface)
   iface->get_adjustments = scrollable_get_adjustments;
 }
 
-/*
- * ClutterContainer Implementation
- */
-static void
-st_box_container_add_actor (ClutterContainer *container,
-                            ClutterActor     *actor)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv;
-
-  _st_container_add_actor (container, actor, &priv->children);
-}
-
-static void
-st_box_container_remove_actor (ClutterContainer *container,
-                               ClutterActor     *actor)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv;
-
-  _st_container_remove_actor (container, actor, &priv->children);
-}
-
-static void
-st_box_container_foreach (ClutterContainer *container,
-                          ClutterCallback   callback,
-                          gpointer          callback_data)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv;
-
-  _st_container_foreach (container, callback, callback_data,
-                         &priv->children);
-}
-
-static void
-st_box_container_lower (ClutterContainer *container,
-                        ClutterActor     *actor,
-                        ClutterActor     *sibling)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv;
-
-  _st_container_lower (container, actor, sibling, &priv->children);
-}
-
-static void
-st_box_container_raise (ClutterContainer *container,
-                        ClutterActor     *actor,
-                        ClutterActor     *sibling)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv;
-
-  _st_container_raise (container, actor, sibling, &priv->children);
-}
-
-static void
-st_box_container_sort_depth_order (ClutterContainer *container)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv;
-
-  _st_container_sort_depth_order (container, &priv->children);
-}
-
 static void
 st_box_container_iface_init (ClutterContainerIface *iface)
 {
-  iface->add = st_box_container_add_actor;
-  iface->remove = st_box_container_remove_actor;
-  iface->foreach = st_box_container_foreach;
-  iface->lower = st_box_container_lower;
-  iface->raise = st_box_container_raise;
-  iface->sort_depth_order = st_box_container_sort_depth_order;
-
+  iface->sort_depth_order = st_box_sort_depth_order;
   iface->child_meta_type = ST_TYPE_BOX_LAYOUT_CHILD;
 }
 
@@ -333,9 +275,6 @@ st_box_layout_dispose (GObject *object)
 {
   StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (object)->priv;
 
-  while (priv->children)
-    clutter_actor_destroy (priv->children->data);
-
   if (priv->hadjustment)
     {
       g_object_unref (priv->hadjustment);
@@ -361,12 +300,14 @@ get_content_preferred_width (StBoxLayout *self,
   gint n_children = 0;
   gint n_fixed = 0;
   gfloat min_width, natural_width;
-  GList *l;
+  GList *l, *children;
 
   min_width = 0;
   natural_width = 0;
 
-  for (l = priv->children; l; l = g_list_next (l))
+  children = st_container_get_children_list (ST_CONTAINER (self));
+
+  for (l = children; l; l = g_list_next (l))
     {
       ClutterActor *child = l->data;
       gfloat child_min = 0, child_nat = 0;
@@ -392,7 +333,7 @@ get_content_preferred_width (StBoxLayout *self,
         }
       else
         {
-          clutter_container_child_get ((ClutterContainer*) self, child,
+          clutter_container_child_get (CLUTTER_CONTAINER (self), child,
                                        "y-fill", &child_fill,
                                        NULL);
           _st_actor_get_preferred_width (child, for_height, child_fill,
@@ -442,12 +383,14 @@ get_content_preferred_height (StBoxLayout *self,
   gint n_children = 0;
   gint n_fixed = 0;
   gfloat min_height, natural_height;
-  GList *l;
+  GList *l, *children;
 
   min_height = 0;
   natural_height = 0;
 
-  for (l = priv->children; l; l = g_list_next (l))
+  children = st_container_get_children_list (ST_CONTAINER (self));
+
+  for (l = children; l; l = g_list_next (l))
     {
       ClutterActor *child = l->data;
       gfloat child_min = 0, child_nat = 0;
@@ -560,7 +503,8 @@ compute_shrinks (StBoxLayout *self,
                  gfloat       total_shrink)
 {
   StBoxLayoutPrivate *priv = self->priv;
-  int n_children = g_list_length (priv->children);
+  GList *children = st_container_get_children_list (ST_CONTAINER (self));
+  int n_children = g_list_length (children);
   BoxChildShrink *shrinks = g_new0 (BoxChildShrink, n_children);
   gfloat shrink_so_far;
   gfloat base_shrink = 0; /* the "= 0" is just to make gcc happy */
@@ -577,7 +521,7 @@ compute_shrinks (StBoxLayout *self,
 
   /* Find the amount of possible shrink for each child */
   int n_possible_shrink_children = 0;
-  for (l = priv->children, i = 0; l; l = l->next, i++)
+  for (l = children, i = 0; l; l = l->next, i++)
     {
       ClutterActor *child = l->data;
       gfloat child_min, child_nat;
@@ -678,7 +622,7 @@ st_box_layout_allocate (ClutterActor          *actor,
   ClutterActorBox content_box;
   gfloat avail_width, avail_height, min_width, natural_width, min_height, natural_height;
   gfloat position, next_position;
-  GList *l;
+  GList *l, *children;
   gint n_expand_children = 0, i;
   gfloat expand_amount, shrink_amount;
   BoxChildShrink *shrinks = NULL;
@@ -688,7 +632,8 @@ st_box_layout_allocate (ClutterActor          *actor,
   CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->allocate (actor, box,
                                                               flags);
 
-  if (priv->children == NULL)
+  children = st_container_get_children_list (ST_CONTAINER (actor));
+  if (children == NULL)
     return;
 
   st_theme_node_get_content_box (theme_node, box, &content_box);
@@ -762,7 +707,7 @@ st_box_layout_allocate (ClutterActor          *actor,
     {
       /* count the number of children with expand set to TRUE */
       n_expand_children = 0;
-      for (l = priv->children; l; l = l->next)
+      for (l = children; l; l = l->next)
         {
           ClutterActor *child = l->data;
           gboolean expand;
@@ -798,12 +743,12 @@ st_box_layout_allocate (ClutterActor          *actor,
 
   if (priv->is_pack_start)
     {
-      l = g_list_last (priv->children);
-      i = g_list_length (priv->children);
+      l = g_list_last (children);
+      i = g_list_length (children);
     }
   else
     {
-      l = priv->children;
+      l = children;
       i = 0;
     }
 
@@ -938,7 +883,7 @@ st_box_layout_paint (ClutterActor *actor)
 {
   StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv;
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
-  GList *l;
+  GList *l, *children;
   gdouble x, y;
   ClutterActorBox allocation_box;
   ClutterActorBox content_box;
@@ -968,7 +913,9 @@ st_box_layout_paint (ClutterActor *actor)
       cogl_pop_matrix ();
     }
 
-  if (priv->children == NULL)
+  children = st_container_get_children_list (ST_CONTAINER (actor));
+
+  if (children == NULL)
     return;
 
   clutter_actor_get_allocation_box (actor, &allocation_box);
@@ -988,7 +935,7 @@ st_box_layout_paint (ClutterActor *actor)
                               (int)content_box.x2,
                               (int)content_box.y2);
 
-  for (l = priv->children; l; l = g_list_next (l))
+  for (l = children; l; l = g_list_next (l))
     {
       ClutterActor *child = (ClutterActor*) l->data;
 
@@ -1006,7 +953,7 @@ st_box_layout_pick (ClutterActor       *actor,
 {
   StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv;
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
-  GList *l;
+  GList *l, *children;
   gdouble x, y;
   ClutterActorBox allocation_box;
   ClutterActorBox content_box;
@@ -1034,7 +981,9 @@ st_box_layout_pick (ClutterActor       *actor,
       cogl_pop_matrix ();
     }
 
-  if (priv->children == NULL)
+  children = st_container_get_children_list (ST_CONTAINER (actor));
+
+  if (children == NULL)
     return;
 
   clutter_actor_get_allocation_box (actor, &allocation_box);
@@ -1051,7 +1000,7 @@ st_box_layout_pick (ClutterActor       *actor,
                               (int)content_box.x2,
                               (int)content_box.y2);
 
-  for (l = priv->children; l; l = g_list_next (l))
+  for (l = children; l; l = g_list_next (l))
     {
       ClutterActor *child = (ClutterActor*) l->data;
 
@@ -1226,94 +1175,11 @@ st_box_layout_get_pack_start (StBoxLayout *box)
   return box->priv->is_pack_start;
 }
 
-static void
-st_box_layout_internal_remove_all (StBoxLayout *self,
-                                   gboolean     destroy)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (self)->priv;
-  ClutterActor *child;
-
-  while (priv->children)
-    {
-      child = priv->children->data;
-
-      g_object_ref (child);
-      priv->children = g_list_delete_link (priv->children, priv->children);
-      clutter_actor_unparent (child);
-      g_signal_emit_by_name (self, "actor-removed", child);
-      if (destroy)
-        clutter_actor_destroy (child);
-      g_object_unref (child);
-    }
-
-  clutter_actor_queue_relayout ((ClutterActor*) self);
-}
-
-/**
- * st_box_layout_remove_all:
- * @self:
- *
- * Efficiently unparent all children currently in this box.
- */
-void
-st_box_layout_remove_all (StBoxLayout *self)
-{
-  st_box_layout_internal_remove_all (self, FALSE);
-}
-
-/**
- * st_box_layout_destroy_children:
- * @self:
- *
- * Efficiently unparent and destroy all children currently in this box.
- */
-void
-st_box_layout_destroy_children (StBoxLayout *self)
-{
-  st_box_layout_internal_remove_all (self, TRUE);
-}
-
-/**
- * st_box_layout_get_n_children:
- * @self: a #StBoxLayout
- *
- * Returns the number of children in this box.
- */
-guint
-st_box_layout_get_n_children  (StBoxLayout *self)
-{
-  return g_list_length (self->priv->children);
-}
-
-void
-st_box_layout_move_child (StBoxLayout  *self,
-                          ClutterActor *actor,
-                          int           pos)
-{
-  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (self)->priv;
-
-  GList *item = NULL;
-
-  item = g_list_find (priv->children, actor);
-
-  if (item == NULL)
-    {
-      g_warning ("Actor of type '%s' is not a child of the StBoxLayout container",
-                 g_type_name (G_OBJECT_TYPE (actor)));
-      return;
-    }
-
-  priv->children = g_list_delete_link (priv->children, item);
-  priv->children = g_list_insert (priv->children, actor, pos);
-  clutter_actor_queue_relayout ((ClutterActor*) self);
-}
-
 void
 st_box_layout_insert_actor (StBoxLayout  *self,
                             ClutterActor *actor,
                             int           pos)
 {
   clutter_container_add_actor((ClutterContainer*) self, actor);
-  st_box_layout_move_child(self, actor, pos);
+  st_container_move_child (ST_CONTAINER (self), actor, pos);
 }
-
diff --git a/src/st/st-box-layout.h b/src/st/st-box-layout.h
index 33b5924..74644c9 100644
--- a/src/st/st-box-layout.h
+++ b/src/st/st-box-layout.h
@@ -28,7 +28,7 @@
 #ifndef _ST_BOX_LAYOUT_H
 #define _ST_BOX_LAYOUT_H
 
-#include <st/st-widget.h>
+#include <st/st-container.h>
 
 G_BEGIN_DECLS
 
@@ -67,14 +67,14 @@ typedef struct _StBoxLayoutPrivate StBoxLayoutPrivate;
 struct _StBoxLayout
 {
   /*< private >*/
-  StWidget parent;
+  StContainer parent;
 
   StBoxLayoutPrivate *priv;
 };
 
 struct _StBoxLayoutClass
 {
-  StWidgetClass parent_class;
+  StContainerClass parent_class;
 };
 
 GType st_box_layout_get_type (void);
@@ -89,16 +89,6 @@ void     st_box_layout_set_pack_start (StBoxLayout *box,
                                        gboolean     pack_start);
 gboolean st_box_layout_get_pack_start (StBoxLayout *box);
 
-void     st_box_layout_remove_all     (StBoxLayout *box);
-
-void     st_box_layout_destroy_children (StBoxLayout *box);
-
-guint    st_box_layout_get_n_children  (StBoxLayout *box);
-
-void     st_box_layout_move_child (StBoxLayout  *self,
-                                   ClutterActor *actor,
-                                   int           pos);
-
 void     st_box_layout_insert_actor (StBoxLayout  *self,
                                      ClutterActor *actor,
                                      int           pos);
diff --git a/src/st/st-container.c b/src/st/st-container.c
new file mode 100644
index 0000000..32083e0
--- /dev/null
+++ b/src/st/st-container.c
@@ -0,0 +1,348 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * st-container.c: Base class for St container actors
+ *
+ * Copyright 2007 OpenedHand
+ * Copyright 2008, 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Emmanuele Bassi <ebassi openedhand com>
+ *             Thomas Wood <thomas linux intel com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "st-container.h"
+
+#define ST_CONTAINER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),ST_TYPE_CONTAINER, StContainerPrivate))
+
+struct _StContainerPrivate
+{
+  GList *children;
+};
+
+static void clutter_container_iface_init (ClutterContainerIface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (StContainer, st_container, ST_TYPE_WIDGET,
+                                  G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
+                                                         clutter_container_iface_init));
+
+/**
+ * st_container_remove_all:
+ * @container: An #StContainer
+ *
+ * Removes all child actors from @container.
+ */
+void
+st_container_remove_all (StContainer *container)
+{
+  StContainerPrivate *priv = container->priv;
+
+  /* copied from clutter_group_remove_all() */
+  while (priv->children)
+    {
+      ClutterActor *child = priv->children->data;
+      priv->children = priv->children->next;
+
+      clutter_container_remove_actor (CLUTTER_CONTAINER (container), child);
+    }
+}
+
+/**
+ * st_container_destroy_children:
+ * @container: An #StContainer
+ *
+ * Destroys all child actors from @container.
+ */
+void
+st_container_destroy_children (StContainer *container)
+{
+  StContainerPrivate *priv = container->priv;
+
+  while (priv->children)
+    {
+      ClutterActor *child = priv->children->data;
+      priv->children = priv->children->next;
+
+      clutter_actor_destroy (child);
+    }
+}
+
+void
+st_container_move_child (StContainer  *container,
+                         ClutterActor *actor,
+                         int           pos)
+{
+  StContainerPrivate *priv = container->priv;
+  GList *item = NULL;
+
+  item = g_list_find (priv->children, actor);
+
+  if (item == NULL)
+    {
+      g_warning ("Actor of type '%s' is not a child of the %s container",
+                 g_type_name (G_OBJECT_TYPE (actor)),
+                 g_type_name (G_OBJECT_TYPE (container)));
+      return;
+    }
+
+  priv->children = g_list_delete_link (priv->children, item);
+  priv->children = g_list_insert (priv->children, actor, pos);
+  clutter_actor_queue_relayout ((ClutterActor*) container);
+}
+
+/**
+ * st_container_get_children_list:
+ * @container: An #StContainer
+ *
+ * Get the internal list of @container's child actors. This function
+ * should only be used by subclasses of StContainer
+ *
+ * Returns: list of @container's child actors
+ */
+GList *
+st_container_get_children_list (StContainer *container)
+{
+  g_return_val_if_fail (ST_IS_CONTAINER (container), NULL);
+
+  return container->priv->children;
+}
+
+static gint
+sort_z_order (gconstpointer a,
+              gconstpointer b)
+{
+  float depth_a, depth_b;
+
+  depth_a = clutter_actor_get_depth (CLUTTER_ACTOR (a));
+  depth_b = clutter_actor_get_depth (CLUTTER_ACTOR (b));
+
+  if (depth_a < depth_b)
+    return -1;
+  if (depth_a > depth_b)
+    return 1;
+  return 0;
+}
+
+static void
+st_container_add (ClutterContainer *container,
+                  ClutterActor     *actor)
+{
+  StContainerPrivate *priv = ST_CONTAINER (container)->priv;
+
+  g_object_ref (actor);
+
+  priv->children = g_list_append (priv->children, actor);
+  clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
+
+  /* queue a relayout, to get the correct positioning inside
+   * the ::actor-added signal handlers
+   */
+  clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
+
+  g_signal_emit_by_name (container, "actor-added", actor);
+
+  clutter_container_sort_depth_order (container);
+
+  g_object_unref (actor);
+}
+
+static void
+st_container_remove (ClutterContainer *container,
+                     ClutterActor     *actor)
+{
+  StContainerPrivate *priv = ST_CONTAINER (container)->priv;
+
+  g_object_ref (actor);
+
+  priv->children = g_list_remove (priv->children, actor);
+  clutter_actor_unparent (actor);
+
+  /* queue a relayout, to get the correct positioning inside
+   * the ::actor-removed signal handlers
+   */
+  clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
+
+  /* at this point, the actor passed to the "actor-removed" signal
+   * handlers is not parented anymore to the container but since we
+   * are holding a reference on it, it's still valid
+   */
+  g_signal_emit_by_name (container, "actor-removed", actor);
+
+  if (CLUTTER_ACTOR_IS_VISIBLE (container))
+    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
+
+  g_object_unref (actor);
+}
+
+static void
+st_container_foreach (ClutterContainer *container,
+                      ClutterCallback   callback,
+                      gpointer          user_data)
+{
+  StContainerPrivate *priv = ST_CONTAINER (container)->priv;
+
+  /* Using g_list_foreach instead of iterating the list manually
+   * because it has better protection against the current node being
+   * removed. This will happen for example if someone calls
+   * clutter_container_foreach(container, clutter_actor_destroy)
+   */
+  g_list_foreach (priv->children, (GFunc) callback, user_data);
+}
+
+static void
+st_container_raise (ClutterContainer *container,
+                    ClutterActor     *actor,
+                    ClutterActor     *sibling)
+{
+  StContainerPrivate *priv = ST_CONTAINER (container)->priv;
+
+  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
+    {
+      gint pos;
+
+      pos = g_list_index (priv->children, sibling) + 1;
+
+      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 (CLUTTER_ACTOR_IS_VISIBLE (container))
+    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
+}
+
+static void
+st_container_lower (ClutterContainer *container,
+                    ClutterActor     *actor,
+                    ClutterActor     *sibling)
+{
+  StContainerPrivate *priv = ST_CONTAINER (container)->priv;
+
+  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
+    {
+      gint pos;
+
+      pos = g_list_index (priv->children, sibling);
+
+      priv->children = g_list_insert (priv->children, actor, pos);
+    }
+
+  /* See comment in st_container_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));
+    }
+
+  if (CLUTTER_ACTOR_IS_VISIBLE (container))
+    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
+}
+
+static void
+st_container_sort_depth_order (ClutterContainer *container)
+{
+  StContainerPrivate *priv = ST_CONTAINER (container)->priv;
+
+  priv->children = g_list_sort (priv->children, sort_z_order);
+
+  if (CLUTTER_ACTOR_IS_VISIBLE (container))
+    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
+}
+
+static void
+st_container_dispose (GObject *object)
+{
+  StContainerPrivate *priv = ST_CONTAINER (object)->priv;
+
+  if (priv->children)
+    {
+      g_list_foreach (priv->children, (GFunc) clutter_actor_destroy, NULL);
+      g_list_free (priv->children);
+
+      priv->children = NULL;
+    }
+
+  G_OBJECT_CLASS (st_container_parent_class)->dispose (object);
+}
+
+static void
+clutter_container_iface_init (ClutterContainerIface *iface)
+{
+  iface->add = st_container_add;
+  iface->remove = st_container_remove;
+  iface->foreach = st_container_foreach;
+  iface->raise = st_container_raise;
+  iface->lower = st_container_lower;
+  iface->sort_depth_order = st_container_sort_depth_order;
+}
+
+static void
+st_container_init (StContainer *container)
+{
+  container->priv = ST_CONTAINER_GET_PRIVATE (container);
+}
+
+static void
+st_container_class_init (StContainerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (StContainerPrivate));
+
+  object_class->dispose = st_container_dispose;
+}
diff --git a/src/st/st-container.h b/src/st/st-container.h
new file mode 100644
index 0000000..ac9ef2c
--- /dev/null
+++ b/src/st/st-container.h
@@ -0,0 +1,68 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * st-container.h: Base class for St container actors
+ *
+ * Copyright 2007 OpenedHand
+ * Copyright 2008, 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
+#error "Only <st/st.h> can be included directly.h"
+#endif
+
+#ifndef __ST_CONTAINER_H__
+#define __ST_CONTAINER_H__
+
+#include <st/st-widget.h>
+
+G_BEGIN_DECLS
+
+#define ST_TYPE_CONTAINER            (st_container_get_type ())
+#define ST_CONTAINER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj),        ST_TYPE_CONTAINER, StContainer))
+#define ST_IS_CONTAINER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj),        ST_TYPE_CONTAINER))
+#define ST_CONTAINER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),         ST_TYPE_CONTAINER, StContainerClass))
+#define ST_IS_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),         ST_TYPE_CONTAINER))
+#define ST_CONTAINER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),         ST_TYPE_CONTAINER, StContainerClass))
+
+typedef struct _StContainer        StContainer;
+typedef struct _StContainerClass   StContainerClass;
+typedef struct _StContainerPrivate StContainerPrivate;
+
+struct _StContainer {
+  StWidget parent;
+  StContainerPrivate *priv;
+};
+
+struct _StContainerClass {
+  StWidgetClass parent_class;
+};
+
+GType   st_container_get_type             (void) G_GNUC_CONST;
+
+void    st_container_remove_all           (StContainer *container);
+void    st_container_destroy_children     (StContainer *container);
+
+/* Only to be used by subclasses of StContainer */
+void    st_container_move_child           (StContainer  *container,
+                                           ClutterActor *actor,
+                                           int           pos);
+GList *st_container_get_children_list     (StContainer *container);
+
+G_END_DECLS
+
+#endif /* __ST_CONTAINER_H__ */
diff --git a/src/st/st-overflow-box.c b/src/st/st-overflow-box.c
index 1528baf..9743955 100644
--- a/src/st/st-overflow-box.c
+++ b/src/st/st-overflow-box.c
@@ -41,11 +41,7 @@
 #include "st-private.h"
 #include "st-box-layout-child.h"
 
-static void st_overflow_box_container_iface_init (ClutterContainerIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (StOverflowBox, st_overflow_box, ST_TYPE_WIDGET,
-                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
-                                                st_overflow_box_container_iface_init));
+G_DEFINE_TYPE (StOverflowBox, st_overflow_box, ST_TYPE_CONTAINER)
 
 #define OVERFLOW_BOX_LAYOUT_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_OVERFLOW_BOX, StOverflowBoxPrivate))
@@ -58,84 +54,12 @@ enum {
 
 struct _StOverflowBoxPrivate
 {
-  GList        *children;
   guint         min_children;
   guint         n_visible;
 
   guint         spacing;
 };
 
-/*
- * ClutterContainer Implementation
- */
-static void
-st_overflow_box_add_actor (ClutterContainer *container,
-                           ClutterActor     *actor)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (container)->priv;
-
-  _st_container_add_actor (container, actor, &priv->children);
-}
-
-static void
-st_overflow_box_remove_actor (ClutterContainer *container,
-                              ClutterActor     *actor)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (container)->priv;
-
-  _st_container_remove_actor (container, actor, &priv->children);
-}
-
-static void
-st_overflow_box_foreach (ClutterContainer *container,
-                         ClutterCallback   callback,
-                         gpointer          callback_data)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (container)->priv;
-
-  _st_container_foreach (container, callback, callback_data,
-                         &priv->children);
-}
-
-static void
-st_overflow_box_lower (ClutterContainer *container,
-                       ClutterActor     *actor,
-                       ClutterActor     *sibling)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (container)->priv;
-
-  _st_container_lower (container, actor, sibling, &priv->children);
-}
-
-static void
-st_overflow_box_raise (ClutterContainer *container,
-                       ClutterActor     *actor,
-                       ClutterActor     *sibling)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (container)->priv;
-
-  _st_container_raise (container, actor, sibling, &priv->children);
-}
-
-static void
-st_overflow_box_sort_depth_order (ClutterContainer *container)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (container)->priv;
-
-  _st_container_sort_depth_order (container, &priv->children);
-}
-
-static void
-st_overflow_box_container_iface_init (ClutterContainerIface *iface)
-{
-  iface->add = st_overflow_box_add_actor;
-  iface->remove = st_overflow_box_remove_actor;
-  iface->foreach = st_overflow_box_foreach;
-  iface->lower = st_overflow_box_lower;
-  iface->raise = st_overflow_box_raise;
-  iface->sort_depth_order = st_overflow_box_sort_depth_order;
-}
-
 
 static void
 st_overflow_box_get_property (GObject    *object,
@@ -176,17 +100,6 @@ st_overflow_box_set_property (GObject      *object,
 }
 
 static void
-st_overflow_box_dispose (GObject *object)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (object)->priv;
-
-  while (priv->children)
-    clutter_actor_destroy (priv->children->data);
-
-  G_OBJECT_CLASS (st_overflow_box_parent_class)->dispose (object);
-}
-
-static void
 get_content_preferred_width (StOverflowBox *self,
                              gfloat         for_height,
                              gfloat        *min_width_p,
@@ -196,12 +109,13 @@ get_content_preferred_width (StOverflowBox *self,
   gint n_children = 0;
   gint n_fixed = 0;
   gfloat min_width, natural_width;
-  GList *l;
+  GList *l, *children;
 
   min_width = 0;
   natural_width = 0;
 
-  for (l = priv->children; l; l = g_list_next (l))
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (l = children; l; l = g_list_next (l))
     {
       ClutterActor *child = l->data;
       gfloat child_min = 0, child_nat = 0;
@@ -267,12 +181,13 @@ get_content_preferred_height (StOverflowBox *self,
   gint n_children = 0;
   gint n_fixed = 0;
   gfloat min_height, natural_height;
-  GList *l;
+  GList *l, *children;
 
   min_height = 0;
   natural_height = 0;
 
-  for (l = priv->children; l; l = g_list_next (l))
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (l = children; l; l = g_list_next (l))
     {
       ClutterActor *child = l->data;
       gfloat child_min = 0, child_nat = 0;
@@ -338,14 +253,15 @@ st_overflow_box_allocate (ClutterActor          *actor,
   ClutterActorBox content_box;
   gfloat position;
   float avail_width, avail_height;
-  GList *l;
+  GList *l, *children;
   int i;
   gboolean done_non_fixed;
 
   CLUTTER_ACTOR_CLASS (st_overflow_box_parent_class)->allocate (actor, box,
                                                                 flags);
 
-  if (priv->children == NULL)
+  children = st_container_get_children_list (ST_CONTAINER (actor));
+  if (children == NULL)
     return;
 
   st_theme_node_get_content_box (theme_node, box, &content_box);
@@ -357,7 +273,7 @@ st_overflow_box_allocate (ClutterActor          *actor,
   priv->n_visible = 0;
 
   done_non_fixed = FALSE;
-  for (l = priv->children, i = 0; l; l = l->next, i++)
+  for (l = children, i = 0; l; l = l->next, i++)
     {
       ClutterActor *child = (ClutterActor*) l->data;
       ClutterActorBox child_box;
@@ -401,11 +317,12 @@ static void
 st_overflow_box_internal_paint (StOverflowBox *box)
 {
   StOverflowBoxPrivate *priv = box->priv;
-  GList *l;
+  GList *l, *children;
   int i;
 
   i = 0;
-  for (l = priv->children; i < priv->n_visible && l; l = l->next)
+  children = st_container_get_children_list (ST_CONTAINER (box));
+  for (l = children; i < priv->n_visible && l; l = l->next)
     {
       ClutterActor *child = (ClutterActor*) l->data;
 
@@ -474,7 +391,6 @@ st_overflow_box_class_init (StOverflowBoxClass *klass)
 
   object_class->get_property = st_overflow_box_get_property;
   object_class->set_property = st_overflow_box_set_property;
-  object_class->dispose = st_overflow_box_dispose;
 
   actor_class->allocate = st_overflow_box_allocate;
   actor_class->get_preferred_width = st_overflow_box_get_preferred_width;
@@ -536,54 +452,6 @@ st_overflow_box_set_min_children (StOverflowBox *box,
     }
 }
 
-
-static void
-st_overflow_box_internal_remove_all (StOverflowBox *self,
-                                     gboolean       destroy)
-{
-  StOverflowBoxPrivate *priv = ST_OVERFLOW_BOX (self)->priv;
-  ClutterActor *child;
-
-  while (priv->children)
-    {
-      child = priv->children->data;
-
-      g_object_ref (child);
-      priv->children = g_list_delete_link (priv->children, priv->children);
-      clutter_actor_unparent (child);
-      g_signal_emit_by_name (self, "actor-removed", child);
-      if (destroy)
-        clutter_actor_destroy (child);
-      g_object_unref (child);
-    }
-
-  clutter_actor_queue_relayout ((ClutterActor*) self);
-}
-
-/**
- * st_overflow_box_remove_all:
- * @self:
- *
- * Efficiently unparent all children currently in this box.
- */
-void
-st_overflow_box_remove_all (StOverflowBox *self)
-{
-  st_overflow_box_internal_remove_all (self, FALSE);
-}
-
-/**
- * st_overflow_box_destroy_children:
- * @self:
- *
- * Efficiently unparent and destroy all children currently in this box.
- */
-void
-st_overflow_box_destroy_children (StOverflowBox *self)
-{
-  st_overflow_box_internal_remove_all (self, TRUE);
-}
-
 /**
  * st_overflow_box_get_n_children:
  * @self: a #StOverflowBox
@@ -593,7 +461,8 @@ st_overflow_box_destroy_children (StOverflowBox *self)
 guint
 st_overflow_box_get_n_children  (StOverflowBox *self)
 {
-  return g_list_length (self->priv->children);
+  GList *children = st_container_get_children_list (ST_CONTAINER (self));
+  return g_list_length (children);
 }
 
 /**
diff --git a/src/st/st-overflow-box.h b/src/st/st-overflow-box.h
index aad5953..47632ad 100644
--- a/src/st/st-overflow-box.h
+++ b/src/st/st-overflow-box.h
@@ -51,21 +51,19 @@ typedef struct _StOverflowBoxPrivate StOverflowBoxPrivate;
 struct _StOverflowBox
 {
   /*< private >*/
-  StWidget parent;
+  StContainer parent;
 
   StOverflowBoxPrivate *priv;
 };
 
 struct _StOverflowBoxClass
 {
-  StWidgetClass parent_class;
+  StContainerClass parent_class;
 };
 
 GType    st_overflow_box_get_type         (void);
 
 void     st_overflow_box_set_min_children (StOverflowBox *self,  guint min_children);
-void     st_overflow_box_remove_all       (StOverflowBox *box);
-void     st_overflow_box_destroy_children (StOverflowBox *box);
 guint    st_overflow_box_get_n_children   (StOverflowBox *box);
 guint    st_overflow_box_get_n_visible    (StOverflowBox *box);
 gboolean st_overflow_box_get_min_children (StOverflowBox *box);
diff --git a/src/st/st-private.c b/src/st/st-private.c
index e0fee5a..7586e2b 100644
--- a/src/st/st-private.c
+++ b/src/st/st-private.c
@@ -310,231 +310,3 @@ _st_set_text_from_style (ClutterText *text,
 
   pango_attr_list_unref (attribs);
 }
-
-/**
- * _st_container_add_actor:
- * @container: a #ClutterContainer
- * @actor: a #ClutterActor
- * @children: pointer to @container's list of children
- *
- * A basic implementation for clutter_container_add_actor().
- * Mostly copied from clutter_group_real_add().
- */
-void
-_st_container_add_actor (ClutterContainer  *container,
-                         ClutterActor      *actor,
-                         GList            **children)
-{
-  g_object_ref (actor);
-
-  *children = g_list_append (*children, actor);
-  clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
-
-  /* queue a relayout, to get the correct positioning inside
-   * the ::actor-added signal handlers
-   */
-  clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
-
-  g_signal_emit_by_name (container, "actor-added", actor);
-
-  clutter_container_sort_depth_order (container);
-
-  g_object_unref (actor);
-}
-
-/**
- * _st_container_remove_actor:
- * @container: a #ClutterContainer
- * @actor: a #ClutterActor
- * @children: pointer to @container's list of children
- *
- * A basic implementation for clutter_container_remove_actor().
- * Mostly copied from clutter_group_real_remove().
- */
-void
-_st_container_remove_actor (ClutterContainer  *container,
-                            ClutterActor      *actor,
-                            GList            **children)
-{
-  g_object_ref (actor);
-
-  *children = g_list_remove (*children, actor);
-  clutter_actor_unparent (actor);
-
-  /* queue a relayout, to get the correct positioning inside
-   * the ::actor-removed signal handlers
-   */
-  clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
-
-  /* at this point, the actor passed to the "actor-removed" signal
-   * handlers is not parented anymore to the container but since we
-   * are holding a reference on it, it's still valid
-   */
-  g_signal_emit_by_name (container, "actor-removed", actor);
-
-  if (CLUTTER_ACTOR_IS_VISIBLE (container))
-    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
-
-  g_object_unref (actor);
-}
-
-/**
- * _st_container_raise:
- * @container: a #ClutterContainer
- * @callback: callback
- * @user_data: data for @callback
- * @children: pointer to @container's list of children
- *
- * A basic implementation for clutter_container_foreach().
- * Mostly copied from clutter_group_real_foreach().
- */
-void
-_st_container_foreach (ClutterContainer  *container,
-                       ClutterCallback    callback,
-                       gpointer           user_data,
-                       GList            **children)
-{
-  GList *l;
-
-  for (l = *children; l; l = l->next)
-    (* callback) (CLUTTER_ACTOR (l->data), user_data);
-}
-
-/**
- * _st_container_raise:
- * @container: a #ClutterContainer
- * @actor: a #ClutterActor to raise
- * @sibling: the sibling to raise to, or %NULL to put on top
- * @children: pointer to @container's list of children
- *
- * A basic implementation for clutter_container_raise().
- * Mostly copied from clutter_group_real_raise().
- */
-void
-_st_container_raise (ClutterContainer  *container,
-                     ClutterActor      *actor,
-                     ClutterActor      *sibling,
-                     GList            **children)
-{
-  *children = g_list_remove (*children, actor);
-
-  /* Raise at the top */
-  if (!sibling)
-    {
-      GList *last_item;
-
-      last_item = g_list_last (*children);
-
-      if (last_item)
-	sibling = last_item->data;
-
-      *children = g_list_append (*children, actor);
-    }
-  else
-    {
-      gint pos;
-
-      pos = g_list_index (*children, sibling) + 1;
-
-      *children = g_list_insert (*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 (CLUTTER_ACTOR_IS_VISIBLE (container))
-    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
-}
-
-/**
- * _st_container_lower:
- * @container: a #ClutterContainer
- * @actor: a #ClutterActor to lower
- * @sibling: the sibling to lower to, or %NULL to put on bottom
- * @children: pointer to @container's list of children
- *
- * A basic implementation for clutter_container_lower().
- * Mostly copied from clutter_group_real_lower().
- */
-void
-_st_container_lower (ClutterContainer  *container,
-                     ClutterActor      *actor,
-                     ClutterActor      *sibling,
-                     GList            **children)
-{
-  *children = g_list_remove (*children, actor);
-
-  /* Push to bottom */
-  if (!sibling)
-    {
-      GList *last_item;
-
-      last_item = g_list_first (*children);
-
-      if (last_item)
-	sibling = last_item->data;
-
-      *children = g_list_prepend (*children, actor);
-    }
-  else
-    {
-      gint pos;
-
-      pos = g_list_index (*children, sibling);
-
-      *children = g_list_insert (*children, actor, pos);
-    }
-
-  /* See comment in _st_container_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));
-    }
-
-  if (CLUTTER_ACTOR_IS_VISIBLE (container))
-    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
-}
-
-static gint
-sort_z_order (gconstpointer a,
-              gconstpointer b)
-{
-  float depth_a, depth_b;
-
-  depth_a = clutter_actor_get_depth (CLUTTER_ACTOR (a));
-  depth_b = clutter_actor_get_depth (CLUTTER_ACTOR (b));
-
-  if (depth_a < depth_b)
-    return -1;
-  if (depth_a > depth_b)
-    return 1;
-  return 0;
-}
-
-/**
- * _st_container_sort_depth_order:
- * @container: a #ClutterContainer
- * @children: pointer to @container's list of children
- *
- * A basic implementation for clutter_container_sort_depth_order().
- * Mostly copied from clutter_group_real_sort_depth_order().
- */
-void
-_st_container_sort_depth_order (ClutterContainer  *container,
-                                GList            **children)
-{
-  *children = g_list_sort (*children, sort_z_order);
-
-  if (CLUTTER_ACTOR_IS_VISIBLE (container))
-    clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
-}
diff --git a/src/st/st-private.h b/src/st/st-private.h
index d22e11f..8368665 100644
--- a/src/st/st-private.h
+++ b/src/st/st-private.h
@@ -72,25 +72,4 @@ void _st_allocate_fill (StWidget        *parent,
 void _st_set_text_from_style (ClutterText *text,
                               StThemeNode *theme_node);
 
-void _st_container_add_actor        (ClutterContainer  *container,
-                                     ClutterActor      *actor,
-                                     GList            **children);
-void _st_container_remove_actor     (ClutterContainer  *container,
-                                     ClutterActor      *actor,
-                                     GList            **children);
-void _st_container_foreach          (ClutterContainer  *container,
-                                     ClutterCallback    callback,
-                                     gpointer           user_data,
-                                     GList            **children);
-void _st_container_raise            (ClutterContainer  *container,
-                                     ClutterActor      *actor,
-                                     ClutterActor      *sibling,
-                                     GList            **children);
-void _st_container_lower            (ClutterContainer  *container,
-                                     ClutterActor      *actor,
-                                     ClutterActor      *sibling,
-                                     GList            **children);
-void _st_container_sort_depth_order (ClutterContainer  *container,
-                                     GList            **children);
-
 #endif /* __ST_PRIVATE_H__ */
diff --git a/src/st/st-table.c b/src/st/st-table.c
index 27f4eae..878bc68 100644
--- a/src/st/st-table.c
+++ b/src/st/st-table.c
@@ -64,8 +64,6 @@ enum
 
 struct _StTablePrivate
 {
-  GList  *children;
-
   gint    col_spacing;
   gint    row_spacing;
 
@@ -91,7 +89,7 @@ struct _StTablePrivate
 
 static void st_table_container_iface_init (ClutterContainerIface *iface);
 
-G_DEFINE_TYPE_WITH_CODE (StTable, st_table, ST_TYPE_WIDGET,
+G_DEFINE_TYPE_WITH_CODE (StTable, st_table, ST_TYPE_CONTAINER,
                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
                                                 st_table_container_iface_init));
 
@@ -101,25 +99,17 @@ G_DEFINE_TYPE_WITH_CODE (StTable, st_table, ST_TYPE_WIDGET,
  * ClutterContainer Implementation
  */
 static void
-st_table_add_actor (ClutterContainer *container,
-                    ClutterActor     *actor)
-{
-  StTablePrivate *priv = ST_TABLE (container)->priv;
-
-  _st_container_add_actor (container, actor, &priv->children);
-}
-
-static void
-st_table_remove_actor (ClutterContainer *container,
-                       ClutterActor     *actor)
+st_table_actor_removed (ClutterContainer *container,
+                        ClutterActor     *actor)
 {
   StTablePrivate *priv = ST_TABLE (container)->priv;
-  GList *list;
+  GList *list, *children;
   gint n_rows = 0;
   gint n_cols = 0;
 
   /* Calculate and update the number of rows / columns */
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (container));
+  for (list = children; list; list = list->next)
     {
       ClutterActor *child = CLUTTER_ACTOR (list->data);
       StTableChild *meta;
@@ -147,59 +137,12 @@ st_table_remove_actor (ClutterContainer *container,
     }
 
   g_object_thaw_notify (G_OBJECT (container));
-
-  _st_container_remove_actor (container, actor, &priv->children);
-}
-
-static void
-st_table_foreach (ClutterContainer *container,
-                  ClutterCallback   callback,
-                  gpointer          callback_data)
-{
-  StTablePrivate *priv = ST_TABLE (container)->priv;
-
-  _st_container_foreach (container, callback, callback_data,
-                         &priv->children);
-}
-
-static void
-st_table_lower (ClutterContainer *container,
-                ClutterActor     *actor,
-                ClutterActor     *sibling)
-{
-  StTablePrivate *priv = ST_TABLE (container)->priv;
-
-  _st_container_lower (container, actor, sibling, &priv->children);
-}
-
-static void
-st_table_raise (ClutterContainer *container,
-                ClutterActor     *actor,
-                ClutterActor     *sibling)
-{
-  StTablePrivate *priv = ST_TABLE (container)->priv;
-
-  _st_container_raise (container, actor, sibling, &priv->children);
-}
-
-static void
-st_table_sort_depth_order (ClutterContainer *container)
-{
-  StTablePrivate *priv = ST_TABLE (container)->priv;
-
-  _st_container_sort_depth_order (container, &priv->children);
 }
 
 static void
 st_table_container_iface_init (ClutterContainerIface *iface)
 {
-  iface->add = st_table_add_actor;
-  iface->remove = st_table_remove_actor;
-  iface->foreach = st_table_foreach;
-  iface->lower = st_table_lower;
-  iface->raise = st_table_raise;
-  iface->sort_depth_order = st_table_sort_depth_order;
-
+  iface->actor_removed = st_table_actor_removed;
   iface->child_meta_type = ST_TYPE_TABLE_CHILD;
 }
 
@@ -278,22 +221,11 @@ st_table_finalize (GObject *gobject)
 }
 
 static void
-st_table_dispose (GObject *gobject)
-{
-  StTablePrivate *priv = ST_TABLE (gobject)->priv;
-
-  while (priv->children)
-    clutter_actor_destroy (priv->children->data);
-
-  G_OBJECT_CLASS (st_table_parent_class)->dispose (gobject);
-}
-
-static void
 st_table_homogeneous_allocate (ClutterActor          *self,
                                const ClutterActorBox *content_box,
                                gboolean               flags)
 {
-  GList *list;
+  GList *list, *children;
   gfloat col_width, row_height;
   gint row_spacing, col_spacing;
   StTablePrivate *priv = ST_TABLE (self)->priv;
@@ -309,7 +241,8 @@ st_table_homogeneous_allocate (ClutterActor          *self,
                 - (row_spacing * (priv->n_rows - 1)))
                / priv->n_rows;
 
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (list = children; list; list = list->next)
     {
       gint row, col, row_span, col_span;
       StTableChild *meta;
@@ -367,7 +300,7 @@ st_table_calculate_col_widths (StTable *table,
   gboolean *is_expand_col;
   gint extra_col_width, n_expanded_cols = 0, expanded_cols = 0;
   gint *pref_widths, *min_widths;
-  GList *list;
+  GList *list, *children;
 
   g_array_set_size (priv->is_expand_col, 0);
   g_array_set_size (priv->is_expand_col, priv->n_cols);
@@ -381,7 +314,9 @@ st_table_calculate_col_widths (StTable *table,
   g_array_set_size (priv->min_widths, priv->n_cols);
   min_widths = (gint *) priv->min_widths->data;
 
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (table));
+
+  for (list = children; list; list = list->next)
     {
       gint row, col;
       gfloat w_min, w_pref;
@@ -469,7 +404,7 @@ st_table_calculate_row_heights (StTable *table,
                                 gint   * col_widths)
 {
   StTablePrivate *priv = ST_TABLE (table)->priv;
-  GList *list;
+  GList *list, *children;
   gint *is_expand_row, *min_heights, *pref_heights, *row_heights, extra_row_height;
   gint i, total_min_height;
   gint expanded_rows = 0;
@@ -491,8 +426,8 @@ st_table_calculate_row_heights (StTable *table,
   g_array_set_size (priv->pref_heights, priv->n_rows);
   pref_heights = (gboolean *) priv->pref_heights->data;
 
-  /* calculate minimum row widths and column heights */
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (table));
+  for (list = children; list; list = list->next)
     {
       gint row, col, cell_width;
       gfloat h_min, h_pref;
@@ -643,7 +578,7 @@ st_table_preferred_allocate (ClutterActor          *self,
                              const ClutterActorBox *content_box,
                              gboolean               flags)
 {
-  GList *list;
+  GList *list, *children;
   gint row_spacing, col_spacing;
   gint i;
   gint *col_widths, *row_heights;
@@ -668,8 +603,8 @@ st_table_preferred_allocate (ClutterActor          *self,
 
   ltr = (st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR);
 
-
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (list = children; list; list = list->next)
     {
       gint row, col, row_span, col_span;
       gint col_width, row_height;
@@ -813,7 +748,7 @@ st_table_get_preferred_width (ClutterActor *self,
   gfloat total_min_width, total_pref_width;
   StTablePrivate *priv = ST_TABLE (self)->priv;
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
-  GList *list;
+  GList *list, *children;
   gint i;
 
   if (priv->n_cols < 1)
@@ -835,7 +770,8 @@ st_table_get_preferred_width (ClutterActor *self,
   pref_widths = (gint *) priv->pref_widths->data;
 
   /* calculate minimum row widths */
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (list = children; list; list = list->next)
     {
       gint col, col_span;
       gfloat w_min, w_pref;
@@ -896,7 +832,7 @@ st_table_get_preferred_height (ClutterActor *self,
   gfloat total_min_height, total_pref_height;
   StTablePrivate *priv = ST_TABLE (self)->priv;
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
-  GList *list;
+  GList *list, *children;
   gint i;
   gint *min_widths;
 
@@ -935,7 +871,8 @@ st_table_get_preferred_height (ClutterActor *self,
   pref_heights = (gint *) priv->pref_heights->data;
 
   /* calculate minimum row heights */
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (list = children; list; list = list->next)
     {
       gint row, col, col_span, cell_width, row_span;
       gfloat min, pref;
@@ -989,13 +926,13 @@ st_table_get_preferred_height (ClutterActor *self,
 static void
 st_table_paint (ClutterActor *self)
 {
-  StTablePrivate *priv = ST_TABLE (self)->priv;
-  GList *list;
+  GList *list, *children;
 
   /* make sure the background gets painted first */
   CLUTTER_ACTOR_CLASS (st_table_parent_class)->paint (self);
 
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (list = children; list; list = list->next)
     {
       ClutterActor *child = CLUTTER_ACTOR (list->data);
       if (CLUTTER_ACTOR_IS_VISIBLE (child))
@@ -1007,13 +944,13 @@ static void
 st_table_pick (ClutterActor       *self,
                const ClutterColor *color)
 {
-  StTablePrivate *priv = ST_TABLE (self)->priv;
-  GList *list;
+  GList *list, *children;
 
   /* Chain up so we get a bounding box painted (if we are reactive) */
   CLUTTER_ACTOR_CLASS (st_table_parent_class)->pick (self, color);
 
-  for (list = priv->children; list; list = list->next)
+  children = st_container_get_children_list (ST_CONTAINER (self));
+  for (list = children; list; list = list->next)
     {
       if (CLUTTER_ACTOR_IS_VISIBLE (list->data))
         clutter_actor_paint (CLUTTER_ACTOR (list->data));
@@ -1023,10 +960,10 @@ st_table_pick (ClutterActor       *self,
 static void
 st_table_show_all (ClutterActor *table)
 {
-  StTablePrivate *priv = ST_TABLE (table)->priv;
-  GList *l;
+  GList *l, *children;
 
-  for (l = priv->children; l; l = l->next)
+  children = st_container_get_children_list (ST_CONTAINER (table));
+  for (l = children; l; l = l->next)
     clutter_actor_show_all (CLUTTER_ACTOR (l->data));
 
   clutter_actor_show (table);
@@ -1035,12 +972,12 @@ st_table_show_all (ClutterActor *table)
 static void
 st_table_hide_all (ClutterActor *table)
 {
-  StTablePrivate *priv = ST_TABLE (table)->priv;
-  GList *l;
+  GList *l, *children;
 
   clutter_actor_hide (table);
 
-  for (l = priv->children; l; l = l->next)
+  children = st_container_get_children_list (ST_CONTAINER (table));
+  for (l = children; l; l = l->next)
     clutter_actor_hide_all (CLUTTER_ACTOR (l->data));
 }
 
@@ -1078,7 +1015,6 @@ st_table_class_init (StTableClass *klass)
 
   gobject_class->set_property = st_table_set_property;
   gobject_class->get_property = st_table_get_property;
-  gobject_class->dispose = st_table_dispose;
   gobject_class->finalize = st_table_finalize;
 
   actor_class->paint = st_table_paint;
diff --git a/src/st/st-table.h b/src/st/st-table.h
index 2bdc905..bce6084 100644
--- a/src/st/st-table.h
+++ b/src/st/st-table.h
@@ -30,7 +30,7 @@
 #define __ST_TABLE_H__
 
 #include <st/st-types.h>
-#include <st/st-widget.h>
+#include <st/st-container.h>
 
 G_BEGIN_DECLS
 
@@ -73,14 +73,14 @@ typedef struct _StTableClass         StTableClass;
 struct _StTable
 {
   /*< private >*/
-  StWidget parent_instance;
+  StContainer parent_instance;
 
   StTablePrivate *priv;
 };
 
 struct _StTableClass
 {
-  StWidgetClass parent_class;
+  StContainerClass parent_class;
 };
 
 GType st_table_get_type (void) G_GNUC_CONST;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]