From 3c2defee9def13ce41162028b709fbc00a28a893 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 7 Jun 2007 14:41:35 +0000 Subject: [PATCH] 2007-06-07 Emmanuele Bassi * 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. --- ChangeLog | 24 ++ clutter/Makefile.am | 8 +- clutter/clutter-actor.c | 19 +- clutter/clutter-group.c | 497 ++++++++++++-------------- clutter/clutter-group.h | 35 +- clutter/clutter-label.c | 57 ++- clutter/clutter-main.c | 2 +- clutter/clutter.h | 2 + doc/reference/ChangeLog | 6 + doc/reference/clutter-docs.sgml | 4 +- doc/reference/clutter-sections.txt | 43 +++ doc/reference/clutter.types | 1 + doc/reference/tmpl/clutter-alpha.sgml | 6 +- doc/reference/tmpl/clutter-group.sgml | 47 +-- examples/behave.c | 4 +- examples/slider.c | 19 +- examples/super-oh.c | 7 +- examples/test-entry.c | 2 +- examples/test-text.c | 4 +- examples/test.c | 8 +- tests/test-textures.c | 4 +- 21 files changed, 439 insertions(+), 360 deletions(-) diff --git a/ChangeLog b/ChangeLog index a67b59ae4..9be27d347 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2007-06-07 Emmanuele Bassi + + * 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 * clutter/clutter-timeline.[ch]: Add a "delay" property, which diff --git a/clutter/Makefile.am b/clutter/Makefile.am index f59814845..a144374a5 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -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 \ diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 93b5e55df..62e3914bb 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -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) diff --git a/clutter/clutter-group.c b/clutter/clutter-group.c index 26b0d068e..e8eac2b30 100644 --- a/clutter/clutter-group.c +++ b/clutter/clutter-group.c @@ -32,14 +32,17 @@ * 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 #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) { - g_object_ref (actor); + ClutterGroup *group = CLUTTER_GROUP (container); + ClutterGroupPrivate *priv = group->priv; - group->priv->children = g_list_append (group->priv->children, actor); + 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); + + 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) { - g_object_ref (actor); + ClutterGroup *group = CLUTTER_GROUP (container); + ClutterGroupPrivate *priv = group->priv; - group->priv->children = g_list_remove (group->priv->children, actor); + 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); + + 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)); @@ -233,12 +266,35 @@ 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)); } @@ -295,22 +365,124 @@ clutter_group_new (void) return g_object_new (CLUTTER_TYPE_GROUP, NULL); } +/** + * 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) +{ + clutter_container_add_actor (CLUTTER_CONTAINER (self), actor); +} + +/** + * clutter_group_add_many_valist: + * @self: a #ClutterGroup + * @first_actor: the #ClutterActor actor to add to the group + * @args: the actors to be added + * + * 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) +{ + clutter_container_add_valist (CLUTTER_CONTAINER (self), first_actor, args); +} + +/** + * clutter_group_add_many: + * @self: A #ClutterGroup + * @first_actor: the #ClutterActor actor to add to the group + * @Varargs: additional actors to add to the group + * + * 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, + ClutterActor *first_actor, + ...) +{ + va_list args; + + va_start (args, first_actor); + clutter_container_add_valist (CLUTTER_CONTAINER (self), first_actor, args); + va_end (args); +} + +/** + * clutter_group_remove + * @self: A #ClutterGroup + * @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) +{ + clutter_container_remove_actor (CLUTTER_CONTAINER (self), actor); +} + +/** + * clutter_group_remove_all: + * @self: A #ClutterGroup + * + * Remove all children actors from the #ClutterGroup. + */ +void +clutter_group_remove_all (ClutterGroup *self) +{ + GList *child_item, *next; + + g_return_if_fail (CLUTTER_IS_GROUP (self)); + + if ((child_item = self->priv->children) == NULL) + return; + + do + { + next = g_list_next(child_item); + 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 GList containing child #ClutterActors. You - * should free the returned list using g_list_free() when - * finished using it. + * 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) { - g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL); - - return g_list_copy(self->priv->children); + return clutter_container_get_children (CLUTTER_CONTAINER (self)); } /** @@ -351,203 +523,6 @@ clutter_group_get_nth_child (ClutterGroup *self, 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. - **/ -void -clutter_group_add (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) - { - 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_group_add_many_valist: - * @self: a #ClutterGroup - * @first_actor: the #ClutterActor actor to add to the group - * @args: the actors to be added - * - * Similar to clutter_group_add_many() but using a va_list. Use this - * function inside bindings. - */ -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_group_add_many: - * @self: A #ClutterGroup - * @first_actor: the #ClutterActor actor to add to the group - * @Varargs: additional actors to add to the group - * - * 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. - */ -void -clutter_group_add_many (ClutterGroup *self, - ClutterActor *first_actor, - ...) -{ - va_list args; - - va_start (args, first_actor); - clutter_group_add_many_valist (self, first_actor, args); - va_end (args); -} - -/** - * clutter_group_remove - * @self: A #ClutterGroup - * @actor: A #ClutterActor - * - * Remove a child #ClutterActor from the #ClutterGroup. - **/ -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_group_remove_all: - * @self: A #ClutterGroup - * - * Remove all child #ClutterActor from the #ClutterGroup. - */ -void -clutter_group_remove_all (ClutterGroup *self) -{ - GList *child_item, *next; - - g_return_if_fail (CLUTTER_IS_GROUP (self)); - - if ((child_item = self->priv->children) == NULL) - return; - - do - { - next = g_list_next(child_item); - clutter_group_remove (self, CLUTTER_ACTOR(child_item->data)); - } - while ((child_item = next) != NULL); -} - /** * clutter_group_find_child_by_id: * @self: A #ClutterGroup @@ -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); + if (clutter_actor_get_id (CLUTTER_ACTOR (self)) == id) + return CLUTTER_ACTOR (self); - child_item = self->priv->children; - - if (child_item) + for (l = self->priv->children; l; l = l->next) { - do - { - inner_actor = (ClutterActor*)child_item->data; + ClutterActor *child = l->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; - } + 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))) diff --git a/clutter/clutter-group.h b/clutter/clutter-group.h index 82ac3e4ab..091c3c46c 100644 --- a/clutter/clutter-group.h +++ b/clutter/clutter-group.h @@ -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); diff --git a/clutter/clutter-label.c b/clutter/clutter-label.c index 4455b2b2a..432b4dbc1 100644 --- a/clutter/clutter-label.c +++ b/clutter/clutter-label.c @@ -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" @@ -43,7 +44,13 @@ #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; diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 38ea47b6d..61ce79ed1 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -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), diff --git a/clutter/clutter.h b/clutter/clutter.h index 6eb4a69f9..10a1dbe24 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -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" diff --git a/doc/reference/ChangeLog b/doc/reference/ChangeLog index 4a5d8171c..632e0ba36 100644 --- a/doc/reference/ChangeLog +++ b/doc/reference/ChangeLog @@ -1,3 +1,9 @@ +2007-05-31 Emmanuele Bassi + + * clutter.types: + * clutter-sections.txt: + * clutter-docs.sgml: Add ClutterLayout API. + 2007-06-07 Emmanuele Bassi * clutter-sections.txt: Add new ClutterTimeline API. diff --git a/doc/reference/clutter-docs.sgml b/doc/reference/clutter-docs.sgml index b7d41a58a..ab1c6e706 100644 --- a/doc/reference/clutter-docs.sgml +++ b/doc/reference/clutter-docs.sgml @@ -66,8 +66,10 @@ Clutter Actors And Objects - + + + diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index 75e5ae221..902243443 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -209,6 +209,49 @@ ClutterGroupPrivate clutter_group_get_type +
+clutter-container +ClutterContainer +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 + +CLUTTER_TYPE_CONTAINER +CLUTTER_CONTAINER +CLUTTER_IS_CONTAINER +CLUTTER_CONTAINER_GET_IFACE + +clutter_container_get_type +
+ +
+clutter-layout +ClutterLayout +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 + +CLUTTER_TYPE_LAYOUT +CLUTTER_LAYOUT +CLUTTER_IS_LAYOUT +CLUTTER_LAYOUT_GET_IFACE + +clutter_layout_get_type +
+
clutter-rectangle ClutterRectangle diff --git a/doc/reference/clutter.types b/doc/reference/clutter.types index fe71df390..74df12883 100644 --- a/doc/reference/clutter.types +++ b/doc/reference/clutter.types @@ -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 diff --git a/doc/reference/tmpl/clutter-alpha.sgml b/doc/reference/tmpl/clutter-alpha.sgml index 10bc72b69..4b4b0fd39 100644 --- a/doc/reference/tmpl/clutter-alpha.sgml +++ b/doc/reference/tmpl/clutter-alpha.sgml @@ -193,7 +193,7 @@ Symbolic name for passing clutter_sine_func(). -Symbolic name for passing clutter_sine_inc_func(). + @@ -210,7 +210,7 @@ Symbolic name for passing clutter_sine_inc_func(). -Symbolic name for passing clutter_sine_dec_func(). + @@ -227,7 +227,7 @@ Symbolic name for passing clutter_sine_dec_func(). -Symbolic name for passing clutter_sine_hav_func(). + diff --git a/doc/reference/tmpl/clutter-group.sgml b/doc/reference/tmpl/clutter-group.sgml index a9dcaf9c9..8d4f1042a 100644 --- a/doc/reference/tmpl/clutter-group.sgml +++ b/doc/reference/tmpl/clutter-group.sgml @@ -53,15 +53,6 @@ The #ClutterActor @arg1 was removed from the group. @Returns: - - - - - -@self: -@Returns: - - @@ -81,22 +72,12 @@ The #ClutterActor @arg1 was removed from the group. @Returns: - - - - - -@self: -@callback: -@user_data: - - -@self: +@group: @actor: @@ -105,9 +86,9 @@ The #ClutterActor @arg1 was removed from the group. -@self: +@group: @first_actor: -@args: +@var_args: @@ -115,7 +96,7 @@ The #ClutterActor @arg1 was removed from the group. -@self: +@group: @first_actor: @Varargs: @@ -125,7 +106,7 @@ The #ClutterActor @arg1 was removed from the group. -@self: +@group: @actor: @@ -134,23 +115,7 @@ The #ClutterActor @arg1 was removed from the group. -@self: - - - - - - - -@self: - - - - - - - -@self: +@group: diff --git a/examples/behave.c b/examples/behave.c index 87718fa22..93d0ae029 100644 --- a/examples/behave.c +++ b/examples/behave.c @@ -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 */ diff --git a/examples/slider.c b/examples/slider.c index 31385c6f9..383f09a31 100644 --- a/examples/slider.c +++ b/examples/slider.c @@ -1,3 +1,6 @@ +#include +#include + #include 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); diff --git a/examples/super-oh.c b/examples/super-oh.c index 23256b128..1c8a1e4da 100644 --- a/examples/super-oh.c +++ b/examples/super-oh.c @@ -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); diff --git a/examples/test-entry.c b/examples/test-entry.c index 6e52a5f8d..d0109c8cd 100644 --- a/examples/test-entry.c +++ b/examples/test-entry.c @@ -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); diff --git a/examples/test-text.c b/examples/test-text.c index 7bac8afb3..4b77fdcba 100644 --- a/examples/test-text.c +++ b/examples/test-text.c @@ -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 */ diff --git a/examples/test.c b/examples/test.c index c4874e8ba..8e311c7a0 100644 --- a/examples/test.c +++ b/examples/test.c @@ -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); diff --git a/tests/test-textures.c b/tests/test-textures.c index 972a6f21a..770b0d663 100644 --- a/tests/test-textures.c +++ b/tests/test-textures.c @@ -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;