2007-06-07 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Thu, 7 Jun 2007 14:41:35 +0000 (14:41 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Thu, 7 Jun 2007 14:41:35 +0000 (14:41 +0000)
* clutter/clutter-container.[ch]: Add a generic actor container
interface, for actors to implement without subclassing ClutterGroup.

* clutter/clutter-group.[ch]: Make ClutterGroup implement the
ClutterContainer interface, and deprecate the colliding methods.

* clutter/clutter-layout.[ch]: Add extended layout interface.
Actors and containers requiring or honouring complex layout
management should implement this interface and provide at least
one of the available layout types: width for height, height for
width, natural size, iterative size request.

* clutter/clutter-label.c: A ClutterLabel requires height for
width layout management, so it implements the ClutterLayout
interface.

* clutter/Makefile.am: Add new files to the build.

* tests/*.c:
* examples/*.c: Update tests and examples code to use the
new ClutterContainer API instead of ClutterGroup.

21 files changed:
ChangeLog
clutter/Makefile.am
clutter/clutter-actor.c
clutter/clutter-group.c
clutter/clutter-group.h
clutter/clutter-label.c
clutter/clutter-main.c
clutter/clutter.h
doc/reference/ChangeLog
doc/reference/clutter-docs.sgml
doc/reference/clutter-sections.txt
doc/reference/clutter.types
doc/reference/tmpl/clutter-alpha.sgml
doc/reference/tmpl/clutter-group.sgml
examples/behave.c
examples/slider.c
examples/super-oh.c
examples/test-entry.c
examples/test-text.c
examples/test.c
tests/test-textures.c

index a67b59a..9be27d3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2007-06-07  Emmanuele Bassi  <ebassi@openedhand.com>
+
+       * clutter/clutter-container.[ch]: Add a generic actor container
+       interface, for actors to implement without subclassing ClutterGroup.
+
+       * clutter/clutter-group.[ch]: Make ClutterGroup implement the
+       ClutterContainer interface, and deprecate the colliding methods.
+
+       * clutter/clutter-layout.[ch]: Add extended layout interface.
+       Actors and containers requiring or honouring complex layout
+       management should implement this interface and provide at least
+       one of the available layout types: width for height, height for
+       width, natural size, iterative size request.
+
+       * clutter/clutter-label.c: A ClutterLabel requires height for
+       width layout management, so it implements the ClutterLayout
+       interface.
+
+       * clutter/Makefile.am: Add new files to the build.
+
+       * tests/*.c:
+       * examples/*.c: Update tests and examples code to use the
+       new ClutterContainer API instead of ClutterGroup.
+
 2007-06-07  Emmanuele Bassi  <ebassi@o-hand.com>
 
        * clutter/clutter-timeline.[ch]: Add a "delay" property, which
index f598148..a144374 100644 (file)
@@ -47,14 +47,16 @@ source_h =                                  \
        $(srcdir)/clutter-behaviour-scale.h     \
        $(srcdir)/clutter-clone-texture.h       \
        $(srcdir)/clutter-color.h               \
-        $(srcdir)/clutter-event.h              \
+        $(srcdir)/clutter-container.h          \
         $(srcdir)/clutter-entry.h               \
+       $(srcdir)/clutter-event.h               \
        $(srcdir)/clutter-feature.h             \
        $(srcdir)/clutter-fixed.h               \
        $(srcdir)/clutter-group.h               \
        $(srcdir)/clutter-keysyms.h             \
        $(srcdir)/clutter-label.h               \
-        $(srcdir)/clutter-main.h               \
+        $(srcdir)/clutter-layout.h             \
+       $(srcdir)/clutter-main.h                \
        $(srcdir)/clutter-media.h               \
        $(srcdir)/clutter-rectangle.h           \
        $(srcdir)/clutter-stage.h               \
@@ -135,6 +137,7 @@ source_c = \
        clutter-behaviour-rotate.c      \
        clutter-behaviour-scale.c       \
        clutter-color.c                 \
+       clutter-container.c             \
        clutter-clone-texture.c         \
        clutter-enum-types.c            \
         clutter-event.c                \
@@ -143,6 +146,7 @@ source_c = \
        clutter-fixed.c                 \
        clutter-group.c                 \
        clutter-label.c                 \
+       clutter-layout.c                \
        clutter-main.c                  \
        clutter-marshal.c               \
        clutter-media.c                 \
index 93b5e55..62e3914 100644 (file)
@@ -33,7 +33,7 @@
 #include "config.h"
 
 #include "clutter-actor.h"
-#include "clutter-group.h"
+#include "clutter-container.h"
 #include "clutter-main.h"
 #include "clutter-enum-types.h"
 #include "clutter-marshal.h"
@@ -2551,6 +2551,8 @@ void
 clutter_actor_reparent (ClutterActor *self,
                         ClutterActor *new_parent)
 {
+  ClutterActorPrivate *priv;
+
   g_return_if_fail (CLUTTER_IS_ACTOR (self));
   g_return_if_fail (CLUTTER_IS_ACTOR (new_parent));
   g_return_if_fail (self != new_parent);
@@ -2561,7 +2563,9 @@ clutter_actor_reparent (ClutterActor *self,
       return;
     }
 
-  if (self->priv->parent_actor != new_parent)
+  priv = self->priv;
+
+  if (priv->parent_actor != new_parent)
     {
       ClutterActor *old_parent;
 
@@ -2575,13 +2579,14 @@ clutter_actor_reparent (ClutterActor *self,
           CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_REPARENT);
         }
 
-      old_parent = self->priv->parent_actor;
+      old_parent = priv->parent_actor;
 
       g_object_ref (self);
-      /* FIXME: below assumes only groups can reparent
-      */
-      clutter_group_remove (CLUTTER_GROUP (self->priv->parent_actor), self);
-      clutter_group_add (CLUTTER_GROUP (new_parent), self);
+
+      /* XXX: below assumes only containers can reparent */
+      clutter_container_remove_actor (CLUTTER_CONTAINER (priv->parent_actor), self);
+      clutter_container_add_actor (CLUTTER_CONTAINER (new_parent), self);
+
       g_object_unref (self);
 
       if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT)
index 26b0d06..e8eac2b 100644 (file)
  * relative to the #ClutterGroup position. Other operations such as scaling, 
  * rotating and clipping of the group will child actors.
  *
- * A ClutterGroup's size is defined by the size and position of it
- * it children. Resize requests via parent #ClutterActor will be ignored.
+ * A #ClutterGroup's size is defined by the size and position of it
+ * it children. Resize requests via parent #ClutterActor API will be
+ * ignored.
  */
 
 #include "config.h"
 #include <stdarg.h>
 
 #include "clutter-group.h"
+
+#include "clutter-container.h"
 #include "clutter-main.h"
 #include "clutter-private.h"
 #include "clutter-debug.h"
@@ -58,7 +61,13 @@ enum
 
 static guint group_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (ClutterGroup, clutter_group, CLUTTER_TYPE_ACTOR);
+static void clutter_container_iface_init (ClutterContainerIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (ClutterGroup,
+                         clutter_group,
+                         CLUTTER_TYPE_ACTOR,
+                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
+                                                clutter_container_iface_init));
 
 #define CLUTTER_GROUP_GET_PRIVATE(obj) \
 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_GROUP, ClutterGroupPrivate))
@@ -170,27 +179,23 @@ static void
 clutter_group_dispose (GObject *object)
 {
   ClutterGroup *self = CLUTTER_GROUP (object);
+  ClutterGroupPrivate *priv = self->priv;
 
-  clutter_group_foreach (self,
-                        CLUTTER_CALLBACK (clutter_actor_destroy),
-                        NULL);
+  if (priv->children)
+    {
+      g_list_foreach (priv->children, (GFunc) clutter_actor_destroy, NULL);
+      priv->children = NULL;
+    }
   
   G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object);
 }
 
-
-static void 
-clutter_group_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (clutter_group_parent_class)->finalize (object);
-}
-
 static void
 clutter_group_real_show_all (ClutterActor *actor)
 {
-  clutter_group_foreach (CLUTTER_GROUP (actor),
-                         CLUTTER_CALLBACK (clutter_actor_show),
-                         NULL);
+  clutter_container_foreach (CLUTTER_CONTAINER (actor),
+                             CLUTTER_CALLBACK (clutter_actor_show),
+                             NULL);
   clutter_actor_show (actor);
 }
 
@@ -198,19 +203,31 @@ static void
 clutter_group_real_hide_all (ClutterActor *actor)
 {
   clutter_actor_hide (actor);
-  clutter_group_foreach (CLUTTER_GROUP (actor),
-                         CLUTTER_CALLBACK (clutter_actor_hide),
-                         NULL);
+  clutter_container_foreach (CLUTTER_CONTAINER (actor),
+                             CLUTTER_CALLBACK (clutter_actor_hide),
+                             NULL);
 }
 
 static void
-clutter_group_real_add (ClutterGroup *group,
-                        ClutterActor *actor)
+clutter_group_real_add (ClutterContainer *container,
+                        ClutterActor     *actor)
 {
+  ClutterGroup *group = CLUTTER_GROUP (container);
+  ClutterGroupPrivate *priv = group->priv;
+
   g_object_ref (actor);
+  
+  /* the old ClutterGroup::add signal was emitted before the
+   * actor was added to the group, so that the class handler
+   * would actually add it. we need to emit the ::add signal
+   * here so that handlers expecting it will not freak out.
+   */
+  g_signal_emit (group, group_signals[ADD], 0, actor);
 
-  group->priv->children = g_list_append (group->priv->children, actor);
+  priv->children = g_list_append (priv->children, actor);
   clutter_actor_set_parent (actor, CLUTTER_ACTOR (group));
+
+  g_signal_emit_by_name (container, "actor-added", actor);
   
   clutter_group_sort_depth_order (group); 
 
@@ -218,13 +235,29 @@ clutter_group_real_add (ClutterGroup *group,
 }
 
 static void
-clutter_group_real_remove (ClutterGroup *group,
-                           ClutterActor *actor)
+clutter_group_real_remove (ClutterContainer *container,
+                           ClutterActor     *actor)
 {
+  ClutterGroup *group = CLUTTER_GROUP (container);
+  ClutterGroupPrivate *priv = group->priv;
+
   g_object_ref (actor);
+  
+  /* the old ClutterGroup::remove signal was emitted before the
+   * actor was removed from the group. see the comment in
+   * clutter_group_real_add() above for why we need to emit ::remove
+   * here and not later
+   */
+  g_signal_emit (group, group_signals[REMOVE], 0, actor);
 
-  group->priv->children = g_list_remove (group->priv->children, actor);
+  priv->children = g_list_remove (priv->children, actor);
   clutter_actor_unparent (actor);
+
+  /* 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 (CLUTTER_ACTOR (group)))
     clutter_actor_queue_redraw (CLUTTER_ACTOR (group));
@@ -234,11 +267,34 @@ clutter_group_real_remove (ClutterGroup *group,
 }
 
 static void
+clutter_group_real_foreach (ClutterContainer *container,
+                            ClutterCallback   callback,
+                            gpointer          user_data)
+{
+  ClutterGroup *group = CLUTTER_GROUP (container);
+  ClutterGroupPrivate *priv = group->priv;
+  GList *l;
+
+  for (l = priv->children; l; l = l->next)
+    (* callback) (CLUTTER_ACTOR (l->data), user_data);
+}
+
+static void
+clutter_container_iface_init (ClutterContainerIface *iface)
+{
+  iface->add = clutter_group_real_add;
+  iface->remove = clutter_group_real_remove;
+  iface->foreach = clutter_group_real_foreach;
+}
+
+static void
 clutter_group_class_init (ClutterGroupClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
 
+  object_class->dispose = clutter_group_dispose;
+  
   actor_class->paint           = clutter_group_paint;
   actor_class->pick            = clutter_group_pick;
   actor_class->show_all        = clutter_group_real_show_all;
@@ -246,10 +302,17 @@ clutter_group_class_init (ClutterGroupClass *klass)
   actor_class->request_coords  = clutter_group_request_coords;
   actor_class->allocate_coords = clutter_group_allocate_coords;
 
-  /* GObject */
-  object_class->finalize = clutter_group_finalize;
-  object_class->dispose = clutter_group_dispose;
-
+  /**
+   * ClutterGroup::add:
+   * @group: the #ClutterGroup that received the signal
+   * @actor: the actor added to the group
+   *
+   * The ::add signal is emitted each time an actor has been added
+   * to the group.
+   *
+   * @Deprecated: 0.4: This signal is deprecated, you should connect
+   *   to the ClutterContainer::actor-added signal instead.
+   */
   group_signals[ADD] =
     g_signal_new ("add",
                  G_OBJECT_CLASS_TYPE (object_class),
@@ -259,7 +322,17 @@ clutter_group_class_init (ClutterGroupClass *klass)
                  clutter_marshal_VOID__OBJECT,
                  G_TYPE_NONE, 1,
                  CLUTTER_TYPE_ACTOR);
-
+  /**
+   * ClutterGroup::remove:
+   * @group: the #ClutterGroup that received the signal
+   * @actor: the actor added to the group
+   *
+   * The ::remove signal is emitted each time an actor has been removed
+   * from the group
+   *
+   * @Deprecated: 0.4: This signal is deprecated, you should connect
+   *   to the ClutterContainer::actor-removed signal instead
+   */
   group_signals[REMOVE] =
     g_signal_new ("remove",
                  G_OBJECT_CLASS_TYPE (object_class),
@@ -270,9 +343,6 @@ clutter_group_class_init (ClutterGroupClass *klass)
                  G_TYPE_NONE, 1,
                  CLUTTER_TYPE_ACTOR);
 
-  klass->add = clutter_group_real_add;
-  klass->remove = clutter_group_real_remove;
-
   g_type_class_add_private (object_class, sizeof (ClutterGroupPrivate));
 }
 
@@ -296,154 +366,20 @@ clutter_group_new (void)
 }
 
 /**
- * clutter_group_get_children:
- * @self: A #ClutterGroup
- * 
- * Get a list containing all actors contained in the group.
- * 
- * Return value: A GList containing child #ClutterActors.  You
- *   should free the returned list using g_list_free() when
- *   finished using it.
- */
-GList*
-clutter_group_get_children (ClutterGroup *self)
-{
-  g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL);
-
-  return g_list_copy(self->priv->children);
-}
-
-/**
- * clutter_group_get_n_children:
- * @self: A #ClutterGroup
- *
- * Gets the number of actors held in the group.
- * 
- * Return value: The number of child actors held in the group.
- * 
- * Since: 0.2
- **/
-gint
-clutter_group_get_n_children (ClutterGroup *self)
-{
-  g_return_val_if_fail (CLUTTER_IS_GROUP (self), 0);
-
-  return g_list_length (self->priv->children);
-}
-
-/**
- * clutter_group_get_nth_child:
- * @self: A #ClutterGroup
- * @index: the position of the requested actor. 
- * 
- * Gets a groups child held at position index in stack.
- *
- * Return value: A Clutter actor or NULL if index is invalid.
- *
- * Since: 0.2
- **/
-ClutterActor *
-clutter_group_get_nth_child (ClutterGroup *self,
-                            gint          index)
-{
-  g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL);
-
-  return g_list_nth_data (self->priv->children, index);
-}
-
-
-/**
- * clutter_group_foreach:
- * @self: A #ClutterGroup
- * @callback: a callback
- * @user_data: callback user data 
- * 
- * Invokes callback on each child of the group.
- **/
-void
-clutter_group_foreach (ClutterGroup      *self,
-                      ClutterCallback   callback,
-                      gpointer          user_data)
-{
-  ClutterActor *child;
-  GList          *children;
-
-  g_return_if_fail (CLUTTER_IS_GROUP (self));
-  g_return_if_fail (callback != NULL);
-
-  children = self->priv->children;
-
-  while (children)
-    {
-      child = children->data;
-
-      (*callback) (child, user_data);
-
-      children = g_list_next(children);
-    }
-}
-
-/**
- * clutter_group_show_all:
- * @self: A #ClutterGroup
- * 
- * Show all child actors of the group, like clutter_actor_show_all().
- *
- * @Deprecated: Use clutter_actor_show_all() instead.
- */
-void
-clutter_group_show_all (ClutterGroup *self)
-{
-  g_return_if_fail (CLUTTER_IS_GROUP (self));
-
-  clutter_actor_show_all (CLUTTER_ACTOR (self));
-}
-
-/**
- * clutter_group_hide_all:
- * @self: A #ClutterGroup
- * 
- * Hide all child actors of the group, like clutter_actor_hide_all().
- *
- * @Deprecated: Use clutter_actor_hide_all() instead
- */
-void
-clutter_group_hide_all (ClutterGroup *self)
-{
-  g_return_if_fail (CLUTTER_IS_GROUP (self));
-
-  clutter_actor_hide_all (CLUTTER_ACTOR (self));
-}
-
-/**
  * clutter_group_add:
  * @self: A #ClutterGroup
  * @actor: A #ClutterActor 
  *
  * Adds a new child #ClutterActor to the #ClutterGroup.
- **/
+ *
+ * @Deprecated: 0.4: This function is obsolete, use
+ *   clutter_container_add_actor() instead.
+ */
 void
 clutter_group_add (ClutterGroup *self,
-                  ClutterActor *actor)
+                   ClutterActor *actor)
 {
-  ClutterActor *parent;
-  
-  g_return_if_fail (CLUTTER_IS_GROUP (self));
-  g_return_if_fail (CLUTTER_IS_ACTOR (actor));
-
-  parent = clutter_actor_get_parent (actor);
-  if (parent)
-    {
-      g_warning ("Attempting to add actor of type `%s' to a "
-                "group of type `%s', but the actor has already "
-                "a parent of type `%s'.",
-                g_type_name (G_OBJECT_TYPE (actor)),
-                g_type_name (G_OBJECT_TYPE (self)),
-                g_type_name (G_OBJECT_TYPE (parent)));
-      return;
-    }
-
-  g_signal_emit (self, group_signals[ADD], 0, actor);
+  clutter_container_add_actor (CLUTTER_CONTAINER (self), actor);
 }
 
 /**
@@ -454,23 +390,16 @@ clutter_group_add (ClutterGroup *self,
  *
  * Similar to clutter_group_add_many() but using a va_list.  Use this
  * function inside bindings.
+ *
+ * @Deprecated: 0.4: This function is obsolete, use
+ *   clutter_container_add_valist() instead.
  */
 void
 clutter_group_add_many_valist (ClutterGroup *self,
                               ClutterActor *first_actor,
                               va_list       args)
 {
-  ClutterActor *actor;
-  
-  g_return_if_fail (CLUTTER_IS_GROUP (self));
-  g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
-
-  actor = first_actor;
-  while (actor)
-    {
-      clutter_group_add (self, actor);
-      actor = va_arg (args, ClutterActor *);
-    }
+  clutter_container_add_valist (CLUTTER_CONTAINER (self), first_actor, args);
 }
 
 /**
@@ -481,6 +410,9 @@ clutter_group_add_many_valist (ClutterGroup *self,
  *
  * Adds a NULL-terminated list of actors to a group.  This function is
  * equivalent to calling clutter_group_add() for each member of the list.
+ *
+ * @Deprecated: 0.4: This function is obsolete, use clutter_container_add()
+ *   instead.
  */
 void
 clutter_group_add_many (ClutterGroup *self,
@@ -490,7 +422,7 @@ clutter_group_add_many (ClutterGroup *self,
   va_list args;
 
   va_start (args, first_actor);
-  clutter_group_add_many_valist (self, first_actor, args);
+  clutter_container_add_valist (CLUTTER_CONTAINER (self), first_actor, args);
   va_end (args);
 }
 
@@ -500,35 +432,22 @@ clutter_group_add_many (ClutterGroup *self,
  * @actor: A #ClutterActor 
  *
  * Remove a child #ClutterActor from the #ClutterGroup.
- **/
+ *
+ * @Deprecated: 0.4: This function is obsolete, use
+ *   clutter_container_remove_actor() instead.
+ */
 void
 clutter_group_remove (ClutterGroup *self,
                      ClutterActor *actor)
 {
-  ClutterActor *parent;
-  
-  g_return_if_fail (CLUTTER_IS_GROUP (self));
-  g_return_if_fail (CLUTTER_IS_ACTOR (actor));
-
-  parent = clutter_actor_get_parent (actor);
-  if (parent != CLUTTER_ACTOR (self))
-    {
-      g_warning ("Attempting to remove actor of type `%s' from "
-                "group of class `%s', but the group is not the "
-                "actor's parent.",
-                g_type_name (G_OBJECT_TYPE (actor)),
-                g_type_name (G_OBJECT_TYPE (self)));
-      return;
-    }
-
-  g_signal_emit (self, group_signals[REMOVE], 0, actor);
+  clutter_container_remove_actor (CLUTTER_CONTAINER (self), actor);
 }
 
 /**
  * clutter_group_remove_all:
  * @self: A #ClutterGroup
  *
- * Remove all child #ClutterActor from the #ClutterGroup.
+ * Remove all children actors from the #ClutterGroup.
  */
 void
 clutter_group_remove_all (ClutterGroup *self)
@@ -543,12 +462,68 @@ clutter_group_remove_all (ClutterGroup *self)
   do 
     {
       next = g_list_next(child_item);
-      clutter_group_remove (self, CLUTTER_ACTOR(child_item->data));
+      clutter_group_remove (self, CLUTTER_ACTOR (child_item->data));
     }
   while ((child_item = next) != NULL);
 }
 
 /**
+ * clutter_group_get_children:
+ * @self: A #ClutterGroup
+ * 
+ * Get a list containing all actors contained in the group.
+ * 
+ * Return value: A list of #ClutterActors. You  should free the returned
+ *   list using g_list_free() when finished using it.
+ *
+ * @Deprecated: 0.4: This function is obsolete, use
+ *   clutter_container_get_children() instead.
+ */
+GList*
+clutter_group_get_children (ClutterGroup *self)
+{
+  return clutter_container_get_children (CLUTTER_CONTAINER (self));
+}
+
+/**
+ * clutter_group_get_n_children:
+ * @self: A #ClutterGroup
+ *
+ * Gets the number of actors held in the group.
+ * 
+ * Return value: The number of child actors held in the group.
+ * 
+ * Since: 0.2
+ **/
+gint
+clutter_group_get_n_children (ClutterGroup *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_GROUP (self), 0);
+
+  return g_list_length (self->priv->children);
+}
+
+/**
+ * clutter_group_get_nth_child:
+ * @self: A #ClutterGroup
+ * @index: the position of the requested actor. 
+ * 
+ * Gets a groups child held at position index in stack.
+ *
+ * Return value: A Clutter actor or NULL if index is invalid.
+ *
+ * Since: 0.2
+ **/
+ClutterActor *
+clutter_group_get_nth_child (ClutterGroup *self,
+                            gint          index)
+{
+  g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL);
+
+  return g_list_nth_data (self->priv->children, index);
+}
+
+/**
  * clutter_group_find_child_by_id:
  * @self: A #ClutterGroup
  * @id: A unique #Clutteractor ID
@@ -562,36 +537,30 @@ ClutterActor *
 clutter_group_find_child_by_id (ClutterGroup *self,
                                guint         id)
 {
-  ClutterActor *actor = NULL, *inner_actor;
-  GList          *child_item;
+  ClutterActor *actor = NULL;
+  GList *l;
 
   g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL);
 
-  if (clutter_actor_get_id (CLUTTER_ACTOR(self)) == id)
-    return CLUTTER_ACTOR(self);
-
-  child_item = self->priv->children;
+  if (clutter_actor_get_id (CLUTTER_ACTOR (self)) == id)
+    return CLUTTER_ACTOR (self);
 
-  if (child_item)
+  for (l = self->priv->children; l; l = l->next)
     {
-      do 
-       {
-         inner_actor = (ClutterActor*)child_item->data;
-
-         if (clutter_actor_get_id (inner_actor) == id)
-           return inner_actor;
-         
-         if (CLUTTER_IS_GROUP(inner_actor))
-           {
-             actor = 
-               clutter_group_find_child_by_id (CLUTTER_GROUP(inner_actor), 
-                                               id);
-             if (actor)
-               return actor;
-           }
-
+      ClutterActor *child = l->data;
+
+      if (clutter_actor_get_id (child) == id)
+        {
+          actor = child;
+          break;
+        }
+
+      if (CLUTTER_IS_GROUP (child))
+        {
+          actor = clutter_group_find_child_by_id (CLUTTER_GROUP (child), id);
+          if (actor)
+            break;
        }
-      while ((child_item = g_list_next(child_item)) != NULL);
     }
 
   return actor;
@@ -624,6 +593,7 @@ clutter_group_raise (ClutterGroup   *self,
   if (sibling == NULL)
     {
       GList *last_item;
+
       /* Raise top */
       last_item = g_list_last (priv->children);
       sibling = last_item->data;
@@ -639,9 +609,9 @@ clutter_group_raise (ClutterGroup   *self,
    * values will be correct.
    * FIXME: optimise
    */
-  if (clutter_actor_get_depth(sibling) != clutter_actor_get_depth(actor))
+  if (clutter_actor_get_depth(sibling) != clutter_actor_get_depth (actor))
     clutter_actor_set_depth (actor,
-                            clutter_actor_get_depth(sibling));
+                            clutter_actor_get_depth (sibling));
 
 }
 
@@ -688,7 +658,8 @@ clutter_group_lower (ClutterGroup   *self,
 }
 
 static gint 
-sort_z_order (gconstpointer a, gconstpointer b)
+sort_z_order (gconstpointer a,
+              gconstpointer b)
 {
   if (clutter_actor_get_depth (CLUTTER_ACTOR(a)) 
          == clutter_actor_get_depth (CLUTTER_ACTOR(b))) 
index 82ac3e4..091c3c4 100644 (file)
@@ -86,31 +86,26 @@ struct _ClutterGroupClass
 
 GType         clutter_group_get_type         (void) G_GNUC_CONST;
 ClutterActor *clutter_group_new              (void);
-GList *       clutter_group_get_children     (ClutterGroup    *self);
-void          clutter_group_foreach          (ClutterGroup    *self,
-                                             ClutterCallback  callback,
-                                             gpointer         user_data);
-void          clutter_group_add              (ClutterGroup    *self,
-                                             ClutterActor    *actor); 
-void          clutter_group_add_many_valist  (ClutterGroup    *self,
-                                             ClutterActor    *first_actor,
-                                             va_list          args);
-void          clutter_group_add_many         (ClutterGroup    *self,
-                                             ClutterActor    *first_actor,
-                                             ...) G_GNUC_NULL_TERMINATED;
-void          clutter_group_remove           (ClutterGroup    *self,
-                                             ClutterActor    *actor); 
-void          clutter_group_remove_all       (ClutterGroup *self);
-#ifndef CLUTTER_DISABLE_DEPRECATED
-void          clutter_group_show_all         (ClutterGroup    *self);
-void          clutter_group_hide_all         (ClutterGroup    *self);
-#endif /* CLUTTER_DISABLE_DEPRECATED */
-
 ClutterActor *clutter_group_find_child_by_id (ClutterGroup    *self,
                                              guint            id);
 ClutterActor *clutter_group_get_nth_child    (ClutterGroup    *self,
                                               gint             index);
 gint          clutter_group_get_n_children   (ClutterGroup    *self);
+void          clutter_group_remove_all       (ClutterGroup    *group);
+
+#ifndef CLUTTER_DISABLE_DEPRECATED
+void          clutter_group_add              (ClutterGroup    *group,
+                                              ClutterActor    *actor);
+void          clutter_group_add_many         (ClutterGroup    *group,
+                                              ClutterActor    *first_actor,
+                                              ...) G_GNUC_NULL_TERMINATED;
+void          clutter_group_add_many_valist  (ClutterGroup    *group,
+                                              ClutterActor    *first_actor,
+                                              va_list          var_args);
+void          clutter_group_remove           (ClutterGroup    *group,
+                                              ClutterActor    *actor);
+#endif /* CLUTTER_DISABLE_DEPRECATED */
+
 void          clutter_group_raise            (ClutterGroup    *self,
                                              ClutterActor    *actor, 
                                              ClutterActor    *sibling);
index 4455b2b..432b4db 100644 (file)
@@ -33,6 +33,7 @@
 #include "config.h"
 
 #include "clutter-label.h"
+#include "clutter-layout.h"
 #include "clutter-main.h"
 #include "clutter-enum-types.h"
 #include "clutter-private.h"
 
 #define DEFAULT_FONT_NAME      "Sans 10"
 
-G_DEFINE_TYPE (ClutterLabel, clutter_label, CLUTTER_TYPE_ACTOR);
+static void clutter_layout_iface_init (ClutterLayoutIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (ClutterLabel,
+                         clutter_label,
+                         CLUTTER_TYPE_ACTOR,
+                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_LAYOUT,
+                                                clutter_layout_iface_init));
 
 /* Probably move into main */
 static PangoClutterFontMap  *_font_map = NULL;
@@ -61,6 +68,7 @@ enum
   PROP_WRAP,
   PROP_WRAP_MODE,
   PROP_ELLIPSIZE,
+  PROP_LAYOUT_FLAGS,
 };
 
 #define CLUTTER_LABEL_GET_PRIVATE(obj) \
@@ -72,6 +80,8 @@ struct _ClutterLabelPrivate
   PangoFontDescription *desc;
   
   ClutterColor          fgcol;
+
+  ClutterLayoutFlags    layout_flags;
   
   gchar                *text;
   gchar                *font_name;
@@ -184,6 +194,9 @@ clutter_label_get_property (GObject    *object,
     case PROP_ELLIPSIZE:
       g_value_set_enum (value, priv->ellipsize);
       break;
+    case PROP_LAYOUT_FLAGS:
+      g_value_set_flags (value, priv->layout_flags);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -191,7 +204,8 @@ clutter_label_get_property (GObject    *object,
 }
 
 static void
-clutter_label_ensure_layout (ClutterLabel *label, gint width)
+clutter_label_ensure_layout (ClutterLabel *label,
+                             gint          width)
 {
   ClutterLabelPrivate  *priv;
 
@@ -256,9 +270,9 @@ clutter_label_paint (ClutterActor *self)
       return;
     }
 
-  clutter_label_ensure_layout (label, clutter_actor_get_width(self));
+  clutter_label_ensure_layout (label, clutter_actor_get_width (self));
 
-  priv->fgcol.alpha   =  clutter_actor_get_opacity(self);
+  priv->fgcol.alpha = clutter_actor_get_opacity(self);
 
   pango_clutter_render_layout (priv->layout, 0, 0, &priv->fgcol, 0);
 }
@@ -288,7 +302,7 @@ clutter_label_request_coords (ClutterActor        *self,
                              ClutterActorBox     *box)
 {
   /* do we need to do anything ? */
-  clutter_label_clear_layout (CLUTTER_LABEL(self));
+  clutter_label_clear_layout (CLUTTER_LABEL (self));
 }
 
 static void 
@@ -332,6 +346,34 @@ clutter_label_finalize (GObject *object)
   G_OBJECT_CLASS (clutter_label_parent_class)->finalize (object);
 }
 
+static ClutterLayoutFlags
+clutter_layout_label_get_layout_flags (ClutterLayout *layout)
+{
+  return CLUTTER_LABEL (layout)->priv->layout_flags;
+}
+
+static void
+clutter_layout_label_height_for_width (ClutterLayout *layout,
+                                       ClutterUnit    width,
+                                       ClutterUnit   *height)
+{
+  ClutterLabel *label = CLUTTER_LABEL (layout);
+  gint layout_height;
+
+  clutter_label_ensure_layout (label, CLUTTER_UNITS_TO_INT (width));
+  pango_layout_get_pixel_size (label->priv->layout, NULL, &layout_height);
+
+  if (height)
+    *height = CLUTTER_UNITS_FROM_INT (layout_height);
+}
+
+static void
+clutter_layout_iface_init (ClutterLayoutIface *iface)
+{
+  iface->get_layout_flags = clutter_layout_label_get_layout_flags;
+  iface->height_for_width = clutter_layout_label_height_for_width;
+}
+
 static void
 clutter_label_class_init (ClutterLabelClass *klass)
 {
@@ -426,6 +468,10 @@ clutter_label_class_init (ClutterLabelClass *klass)
                         PANGO_ALIGN_LEFT,
                         CLUTTER_PARAM_READWRITE));
 
+  g_object_class_override_property (gobject_class,
+                                    PROP_LAYOUT_FLAGS,
+                                    "layout-flags");
+
   g_type_class_add_private (gobject_class, sizeof (ClutterLabelPrivate));
 }
 
@@ -452,6 +498,7 @@ clutter_label_init (ClutterLabel *self)
   priv->layout        = NULL;
   priv->text          = NULL;
   priv->attrs         = NULL;
+  priv->layout_flags  = CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH;
 
   priv->fgcol.red     = 0;
   priv->fgcol.green   = 0;
index 38ea47b..61ce79e 100644 (file)
@@ -121,7 +121,7 @@ clutter_redraw (void)
     {
       ClutterPerspective perspective;
 
-      clutter_stage_get_perspectivex (stage, &perspective);
+      clutter_stage_get_perspectivex (CLUTTER_STAGE (stage), &perspective);
 
       cogl_setup_viewport (clutter_actor_get_width (stage),
                           clutter_actor_get_height (stage),
index 6eb4a69..10a1dbe 100644 (file)
@@ -44,6 +44,8 @@
 #include "clutter-stage.h"
 #include "clutter-actor.h"
 #include "clutter-rectangle.h"
+#include "clutter-container.h"
+#include "clutter-layout.h"
 #include "clutter-group.h"
 #include "clutter-texture.h"
 #include "clutter-clone-texture.h"
index 4a5d817..632e0ba 100644 (file)
@@ -1,3 +1,9 @@
+2007-05-31  Emmanuele Bassi  <ebassi@openedhand.com>
+
+       * clutter.types:
+       * clutter-sections.txt:
+       * clutter-docs.sgml: Add ClutterLayout API.
+
 2007-06-07  Emmanuele Bassi  <ebassi@o-hand.com>
 
        * clutter-sections.txt: Add new ClutterTimeline API.
index b7d41a5..ab1c6e7 100644 (file)
   <chapter>
     <title>Clutter Actors And Objects</title>
     <xi:include href="xml/clutter-actor.xml"/>
-    <xi:include href="xml/clutter-stage.xml"/>
+    <xi:include href="xml/clutter-container.xml"/>
+    <xi:include href="xml/clutter-layout.xml"/>
     <xi:include href="xml/clutter-group.xml"/>
+    <xi:include href="xml/clutter-stage.xml"/>
     <xi:include href="xml/clutter-rectangle.xml"/>
     <xi:include href="xml/clutter-texture.xml"/>
     <xi:include href="xml/clutter-clone-texture.xml"/>
index 75e5ae2..9022434 100644 (file)
@@ -210,6 +210,49 @@ clutter_group_get_type
 </SECTION>
 
 <SECTION>
+<FILE>clutter-container</FILE>
+<TITLE>ClutterContainer</TITLE>
+ClutterContainer
+ClutterContainerIface
+clutter_container_add_actor
+clutter_container_add
+clutter_container_add_valist
+clutter_container_remove_actor
+clutter_container_remove
+clutter_container_remove_valist
+clutter_container_get_children
+clutter_container_foreach
+<SUBSECTION Standard>
+CLUTTER_TYPE_CONTAINER
+CLUTTER_CONTAINER
+CLUTTER_IS_CONTAINER
+CLUTTER_CONTAINER_GET_IFACE
+<SUBSECTION Private>
+clutter_container_get_type
+</SECTION>
+
+<SECTION>
+<FILE>clutter-layout</FILE>
+<TITLE>ClutterLayout</TITLE>
+ClutterLayout
+ClutterLayoutIface
+ClutterLayoutFlags
+clutter_layout_get_layout_flags
+clutter_layout_get_type
+clutter_layout_height_for_width
+clutter_layout_natural_request
+clutter_layout_tune_request
+clutter_layout_width_for_height
+<SUBSECTION Standard>
+CLUTTER_TYPE_LAYOUT
+CLUTTER_LAYOUT
+CLUTTER_IS_LAYOUT
+CLUTTER_LAYOUT_GET_IFACE
+<SUBSECTION Private>
+clutter_layout_get_type
+</SECTION>
+
+<SECTION>
 <FILE>clutter-rectangle</FILE>
 <TITLE>ClutterRectangle</TITLE>
 ClutterRectangle
index fe71df3..74df128 100644 (file)
@@ -7,6 +7,7 @@ clutter_rectangle_get_type
 clutter_texture_get_type
 clutter_clone_texture_get_type
 clutter_label_get_type
+clutter_layout_get_type
 clutter_timeline_get_type
 clutter_media_get_type
 clutter_behaviour_get_type
index 10bc72b..4b4b0fd 100644 (file)
@@ -193,7 +193,7 @@ Symbolic name for passing clutter_sine_func().
 
 <!-- ##### MACRO CLUTTER_ALPHA_SINE_INC ##### -->
 <para>
-Symbolic name for passing clutter_sine_inc_func().
+
 </para>
 
 
@@ -210,7 +210,7 @@ Symbolic name for passing clutter_sine_inc_func().
 
 <!-- ##### MACRO CLUTTER_ALPHA_SINE_DEC ##### -->
 <para>
-Symbolic name for passing clutter_sine_dec_func().
+
 </para>
 
 
@@ -227,7 +227,7 @@ Symbolic name for passing clutter_sine_dec_func().
 
 <!-- ##### MACRO CLUTTER_ALPHA_SINE_HALF ##### -->
 <para>
-Symbolic name for passing clutter_sine_hav_func().
+
 </para>
 
 
index a9dcaf9..8d4f104 100644 (file)
@@ -53,15 +53,6 @@ The #ClutterActor @arg1 was removed from the group.
 @Returns: 
 
 
-<!-- ##### FUNCTION clutter_group_get_children ##### -->
-<para>
-
-</para>
-
-@self: 
-@Returns: 
-
-
 <!-- ##### FUNCTION clutter_group_get_n_children ##### -->
 <para>
 
@@ -81,22 +72,12 @@ The #ClutterActor @arg1 was removed from the group.
 @Returns: 
 
 
-<!-- ##### FUNCTION clutter_group_foreach ##### -->
-<para>
-
-</para>
-
-@self: 
-@callback: 
-@user_data: 
-
-
 <!-- ##### FUNCTION clutter_group_add ##### -->
 <para>
 
 </para>
 
-@self
+@group
 @actor: 
 
 
@@ -105,9 +86,9 @@ The #ClutterActor @arg1 was removed from the group.
 
 </para>
 
-@self
+@group
 @first_actor: 
-@args: 
+@var_args: 
 
 
 <!-- ##### FUNCTION clutter_group_add_many ##### -->
@@ -115,7 +96,7 @@ The #ClutterActor @arg1 was removed from the group.
 
 </para>
 
-@self
+@group
 @first_actor: 
 @Varargs: 
 
@@ -125,7 +106,7 @@ The #ClutterActor @arg1 was removed from the group.
 
 </para>
 
-@self
+@group
 @actor: 
 
 
@@ -134,23 +115,7 @@ The #ClutterActor @arg1 was removed from the group.
 
 </para>
 
-@self: 
-
-
-<!-- ##### FUNCTION clutter_group_show_all ##### -->
-<para>
-
-</para>
-
-@self: 
-
-
-<!-- ##### FUNCTION clutter_group_hide_all ##### -->
-<para>
-
-</para>
-
-@self: 
+@group: 
 
 
 <!-- ##### FUNCTION clutter_group_find_child_by_id ##### -->
index 87718fa..93d0ae0 100644 (file)
@@ -120,7 +120,7 @@ main (int argc, char *argv[])
 
   /* Make a hand */
   group = clutter_group_new ();
-  clutter_group_add (CLUTTER_GROUP (stage), group);
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
   clutter_actor_show (group);
   
   rect = clutter_rectangle_new ();
@@ -140,7 +140,7 @@ main (int argc, char *argv[])
   clutter_actor_set_position (hand, 0, 0);
   clutter_actor_show (hand);
 
-  clutter_group_add_many (CLUTTER_GROUP (group), rect, hand, NULL);
+  clutter_container_add (CLUTTER_CONTAINER (group), rect, hand, NULL);
   
   /* Make a timeline */
   timeline = clutter_timeline_new (100, 26); /* num frames, fps */
index 31385c6..383f09a 100644 (file)
@@ -1,3 +1,6 @@
+#include <stdlib.h>
+#include <stdio.h>
+
 #include <clutter/clutter.h>
 
 typedef struct Tile 
@@ -46,7 +49,8 @@ make_tiles (GdkPixbuf *pixbuf)
          if (pos != 15)
            {
              tile->actor = clutter_texture_new_from_pixbuf (subpixbuf);
-             clutter_group_add (CLUTTER_GROUP (group), tile->actor);
+             clutter_container_add_actor (CLUTTER_CONTAINER (group),
+                                           tile->actor);
              clutter_actor_set_position (tile->actor, x, y);
            } 
          else 
@@ -143,6 +147,7 @@ key_press_event_cb (ClutterStage    *stage,
 int
 main (int argc, char **argv)
 {
+  GError       *error;
   GdkPixbuf    *pixbuf;
   ClutterActor *stage, *group;
   ClutterColor  bgcolour;
@@ -158,11 +163,19 @@ main (int argc, char **argv)
   clutter_stage_set_color (CLUTTER_STAGE (stage), &bgcolour);
 
   /* Create Tiles */
-  pixbuf = gdk_pixbuf_new_from_file ("image.jpg", NULL);
+  error = NULL;
+  pixbuf = gdk_pixbuf_new_from_file ("image.jpg", &error);
+  if (error)
+    {
+      g_warning ("Unable to load `image.jpg': %s", error->message);
+      g_error_free (error);
+      return EXIT_FAILURE;
+    }
+
   group = make_tiles (pixbuf);
 
   /* Add to stage and center */
-  clutter_group_add (CLUTTER_GROUP (stage), group);
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
   clutter_actor_set_position (group, 
    (clutter_actor_get_width (stage) - clutter_actor_get_width (group)) / 2, 
    (clutter_actor_get_height (stage) - clutter_actor_get_height (group)) / 2);
index 23256b1..1c8a1e4 100644 (file)
@@ -198,7 +198,7 @@ main (int argc, char *argv[])
   clutter_actor_set_size (oh->bgtex, 
                          CLUTTER_STAGE_WIDTH(), CLUTTER_STAGE_HEIGHT());
   clutter_actor_set_opacity (oh->bgtex, 0x99);
-  clutter_group_add (CLUTTER_GROUP (stage), oh->bgtex);
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), oh->bgtex);
 #endif
 
   /* create a new group to hold multiple actors in a group */
@@ -232,7 +232,7 @@ main (int argc, char *argv[])
       clutter_actor_set_position (oh->hand[i], x, y);
 
       /* Add to our group group */
-      clutter_group_add (CLUTTER_GROUP (oh->group), oh->hand[i]);
+      clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]);
     }
 
 #if 0
@@ -251,7 +251,8 @@ main (int argc, char *argv[])
   clutter_actor_show_all (oh->group);
 
   /* Add the group to the stage */
-  clutter_group_add (CLUTTER_GROUP (stage), CLUTTER_ACTOR(oh->group));
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage),
+                               CLUTTER_ACTOR (oh->group));
 
   /* Show everying ( and map window ) */
   clutter_actor_show_all (stage);
index 6e52a5f..d0109c8 100644 (file)
@@ -46,7 +46,7 @@ main (int argc, char *argv[])
   /*clutter_entry_set_max_length (CLUTTER_ENTRY (entry), 50);*/
   
   clutter_group_add (CLUTTER_GROUP (stage), entry);
-  clutter_group_show_all (CLUTTER_GROUP (stage));
+  clutter_actor_show_all (CLUTTER_GROUP (stage));
 
   g_signal_connect (stage, "key-release-event",
                    G_CALLBACK (on_key_release_cb), (gpointer)entry);
index 7bac8af..4b77fdc 100644 (file)
@@ -36,8 +36,8 @@ main (int argc, char *argv[])
   label = clutter_label_new_with_text ("Mono 8", text);
   clutter_label_set_color (CLUTTER_LABEL (label), &label_color);
 
-  clutter_group_add (CLUTTER_GROUP (stage), label);
-  clutter_group_show_all (CLUTTER_GROUP (stage));
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), label);
+  clutter_actor_show_all (stage);
 
   timeline = clutter_timeline_new (400, 60); /* num frames, fps */
   g_object_set(timeline, "loop", TRUE, 0);   /* have it loop */
index c4874e8..8e311c7 100644 (file)
@@ -121,10 +121,10 @@ main (int argc, char *argv[])
   clutter_actor_set_position(para, 10, 10);
   clutter_actor_set_size(para, 200, 0);
 
-  clutter_group_add (CLUTTER_GROUP (stage), texture);
-  clutter_group_add (CLUTTER_GROUP (stage), label);
-  clutter_group_add (CLUTTER_GROUP (stage), rect);
-  clutter_group_add (CLUTTER_GROUP (stage), para);
+  clutter_container_add (CLUTTER_CONTAINER (stage),
+                         texture, label,
+                         rect, para,
+                         NULL);
 
   clutter_actor_set_size (CLUTTER_ACTOR (stage), 800, 600);
 
index 972a6f2..770b0d6 100644 (file)
@@ -84,7 +84,7 @@ main (int argc, char *argv[])
        
        printf("uploaded to texture... ");
        
-       clutter_group_add (CLUTTER_GROUP (stage), texture);
+       clutter_container_add (CLUTTER_CONTAINER (stage), texture, NULL);
        clutter_actor_set_size (texture, 400, 400);
        clutter_actor_show (texture);
        
@@ -94,7 +94,7 @@ main (int argc, char *argv[])
        
        SPIN();
 
-      clutter_group_remove (CLUTTER_GROUP (stage), texture);
+        clutter_container_remove (CLUTTER_CONTAINER (stage), texture, NULL);
     }
 
   return 0;