From 15a04a1dd39fd19f28132cbd3c22b49c05c0773b Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 30 Nov 2009 19:03:11 +0000 Subject: [PATCH] layout-manager: Create LayoutMeta on demand The ClutterLayoutMeta instances should be created on demand, whenever the layout manager needs them - if the layout manager supports layout properties. This removes the requirement to call add_child_meta() and remove_child_meta() on add and remove respectively; it also simplifies the implementation of LayoutManager sub-classes since we can add fallback code in the base abstract class. Eventually, this will also lead to an easier to implement ClutterScript parser for layout properties. With the new scheme, the ClutterLayoutMeta instance is created whenever the layout manager tries to access it; if there isn't an instance already attached to the container's child, one is created -- assuming that the LayoutManager sub-class has overridden the get_child_meta_type() virtual function and it's returning a valid GType. We can also provide a default implementation for create_child_meta(), by getting the GType and instantiating a ClutterLayoutMeta with all the fields already set. If the layout manager requires more work then it can obviously override the default implementation (and even chain up to it). The ClutterBox actor has been updated, as well as the ClutterBoxLayout layout manager, to take advantage of the changes of LayoutManager. --- clutter/clutter-box-layout.c | 13 -- clutter/clutter-box.c | 10 -- clutter/clutter-layout-manager.c | 221 +++++++++-------------------- clutter/clutter-layout-manager.h | 8 +- doc/reference/clutter/clutter-sections.txt | 2 - 5 files changed, 70 insertions(+), 184 deletions(-) diff --git a/clutter/clutter-box-layout.c b/clutter/clutter-box-layout.c index a92b921..6e42805 100644 --- a/clutter/clutter-box-layout.c +++ b/clutter/clutter-box-layout.c @@ -478,18 +478,6 @@ allocate_fill (ClutterActor *child, *childbox = allocation; } -static ClutterLayoutMeta * -clutter_box_layout_create_child_meta (ClutterLayoutManager *layout, - ClutterContainer *container, - ClutterActor *actor) -{ - return g_object_new (CLUTTER_TYPE_BOX_CHILD, - "manager", layout, - "container", container, - "actor", actor, - NULL); -} - static GType clutter_box_layout_get_child_meta_type (ClutterLayoutManager *manager) { @@ -895,7 +883,6 @@ clutter_box_layout_class_init (ClutterBoxLayoutClass *klass) clutter_box_layout_get_preferred_height; layout_class->allocate = clutter_box_layout_allocate; layout_class->set_container = clutter_box_layout_set_container; - layout_class->create_child_meta = clutter_box_layout_create_child_meta; layout_class->get_child_meta_type = clutter_box_layout_get_child_meta_type; diff --git a/clutter/clutter-box.c b/clutter/clutter-box.c index fd79eda..f9a09d1 100644 --- a/clutter/clutter-box.c +++ b/clutter/clutter-box.c @@ -118,11 +118,6 @@ clutter_box_real_add (ClutterContainer *container, clutter_actor_set_parent (actor, CLUTTER_ACTOR (container)); - if (priv->manager != NULL) - clutter_layout_manager_add_child_meta (priv->manager, - container, - actor); - clutter_actor_queue_relayout (actor); g_signal_emit_by_name (container, "actor-added", actor); @@ -141,11 +136,6 @@ clutter_box_real_remove (ClutterContainer *container, priv->children = g_list_remove (priv->children, actor); clutter_actor_unparent (actor); - if (priv->manager != NULL) - clutter_layout_manager_remove_child_meta (priv->manager, - container, - actor); - clutter_actor_queue_relayout (CLUTTER_ACTOR (container)); g_signal_emit_by_name (container, "actor-removed", actor); diff --git a/clutter/clutter-layout-manager.c b/clutter/clutter-layout-manager.c index 533c7de..a062158 100644 --- a/clutter/clutter-layout-manager.c +++ b/clutter/clutter-layout-manager.c @@ -78,6 +78,34 @@ * policies then it should emit the #ClutterLayoutManager::layout-changed * signal on itself by using the clutter_layout_manager_layout_changed() * function. + * If the layout manager has layout properties, that is properties that + * should exist only as the result of the presence of a specific (layout + * manager, container actor, child actor) combination, then it should + * override the ClutterLayoutManager::get_child_meta_type() + * virtual function to return the #GType of the #ClutterLayoutMeta sub-class + * used to store the layout properties; optionally, the #ClutterLayoutManager + * sub-class might also override the + * ClutterLayoutManager::create_child_meta() virtual + * function to control how the #ClutterLayoutMeta instance is created, + * otherwise the default implementation will be equivalent to: + * + * ClutterLayoutManagerClass *klass; + * GType meta_type; + * + * klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + * meta_type = klass->get_child_meta_type (manager); + * + * return g_object_new (meta_type, + * "manager", manager, + * "container", container, + * "actor", actor, + * NULL); + * + * Where manager is the + * #ClutterLayoutManager, container is the + * #ClutterContainer using the #ClutterLayoutManager and + * actor is the #ClutterActor child of the + * #ClutterContainer. * * * #ClutterLayoutManager is available since Clutter 1.2 @@ -163,6 +191,24 @@ layout_manager_real_create_child_meta (ClutterLayoutManager *manager, ClutterContainer *container, ClutterActor *actor) { + ClutterLayoutManagerClass *klass; + GType meta_type; + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + meta_type = klass->get_child_meta_type (manager); + + /* provide a default implementation to reduce common code */ + if (meta_type != G_TYPE_INVALID) + { + g_assert (g_type_is_a (meta_type, CLUTTER_TYPE_LAYOUT_META)); + + return g_object_new (meta_type, + "manager", manager, + "container", container, + "actor", actor, + NULL); + } + return NULL; } @@ -384,29 +430,10 @@ create_child_meta (ClutterLayoutManager *manager, ClutterLayoutManagerClass *klass; klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + if (klass->get_child_meta_type (manager) != G_TYPE_INVALID) + return klass->create_child_meta (manager, container, actor); - return klass->create_child_meta (manager, container, actor); -} - -static gboolean -has_child_meta (ClutterLayoutManager *manager, - ClutterContainer *container, - ClutterActor *actor) -{ - ClutterLayoutMeta *layout_meta = NULL; - - layout_meta = g_object_get_qdata (G_OBJECT (actor), quark_layout_meta); - if (layout_meta != NULL) - { - ClutterChildMeta *child_meta = CLUTTER_CHILD_META (layout_meta); - - if (layout_meta->manager == manager && - child_meta->container == container && - child_meta->actor == actor) - return TRUE; - } - - return FALSE; + return NULL; } static inline ClutterLayoutMeta * @@ -430,15 +457,15 @@ get_child_meta (ClutterLayoutManager *manager, * layout manager then we simply ask the layout manager * to replace it with the right one */ - layout = create_child_meta (manager, container, actor); - if (layout != NULL) - { - g_assert (CLUTTER_IS_LAYOUT_META (layout)); - g_object_set_qdata_full (G_OBJECT (actor), quark_layout_meta, - layout, - (GDestroyNotify) g_object_unref); - } + } + layout = create_child_meta (manager, container, actor); + if (layout != NULL) + { + g_assert (CLUTTER_IS_LAYOUT_META (layout)); + g_object_set_qdata_full (G_OBJECT (actor), quark_layout_meta, + layout, + (GDestroyNotify) g_object_unref); return layout; } @@ -452,9 +479,11 @@ get_child_meta (ClutterLayoutManager *manager, * @actor: a #ClutterActor child of @container * * Retrieves the #ClutterLayoutMeta that the layout @manager associated - * to the @actor child of @container + * to the @actor child of @container, eventually by creating one if the + * #ClutterLayoutManager supports layout properties * - * Return value: a #ClutterLayoutMeta or %NULL + * Return value: a #ClutterLayoutMeta, or %NULL if the #ClutterLayoutManager + * does not have layout properties * * Since: 1.0 */ @@ -470,118 +499,6 @@ clutter_layout_manager_get_child_meta (ClutterLayoutManager *manager, return get_child_meta (manager, container, actor); } -/** - * clutter_layout_manager_add_child_meta: - * @manager: a #ClutterLayoutManager - * @container: a #ClutterContainer using @manager - * @actor: a #ClutterActor child of @container - * - * Creates and binds a #ClutterLayoutMeta for @manager to - * a child of @container - * - * This function should only be used when implementing containers - * using #ClutterLayoutManager and not by application code - * - * Typically, containers should bind a #ClutterLayoutMeta created - * by a #ClutterLayoutManager when adding a new child, e.g.: - * - * |[ - * static void - * my_container_add (ClutterContainer *container, - * ClutterActor *actor) - * { - * MyContainer *self = MY_CONTAINER (container); - * - * self->children = g_slist_append (self->children, actor); - * clutter_actor_set_parent (actor, CLUTTER_ACTOR (self)); - * - * clutter_layout_manager_add_child_meta (self->layout, - * container, - * actor); - * - * clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); - * - * g_signal_emit_by_name (container, "actor-added"); - * } - * ]| - * - * The #ClutterLayoutMeta should be removed when removing an - * actor; see clutter_layout_manager_remove_child_meta() - * - * Since: 1.2 - */ -void -clutter_layout_manager_add_child_meta (ClutterLayoutManager *manager, - ClutterContainer *container, - ClutterActor *actor) -{ - ClutterLayoutMeta *meta; - - meta = create_child_meta (manager, container, actor); - if (meta == NULL) - return; - - g_object_set_qdata_full (G_OBJECT (actor), quark_layout_meta, - meta, - (GDestroyNotify) g_object_unref); -} - -/** - * clutter_layout_manager_remove_child_meta: - * @manager: a #ClutterLayoutManager - * @container: a #ClutterContainer using @manager - * @actor: a #ClutterActor child of @container - * - * Unbinds and unrefs a #ClutterLayoutMeta for @manager from - * a child of @container - * - * This function should only be used when implementing containers - * using #ClutterLayoutManager and not by application code - * - * Typically, containers should remove a #ClutterLayoutMeta created - * by a #ClutterLayoutManager when removing a child, e.g.: - * - * |[ - * static void - * my_container_remove (ClutterContainer *container, - * ClutterActor *actor) - * { - * MyContainer *self = MY_CONTAINER (container); - * - * g_object_ref (actor); - * - * self->children = g_slist_remove (self->children, actor); - * clutter_actor_unparent (actor); - * - * clutter_layout_manager_remove_child_meta (self->layout, - * container, - * actor); - * - * clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); - * - * g_signal_emit_by_name (container, "actor-removed"); - * - * g_object_unref (actor); - * } - * ]| - * - * See also clutter_layout_manager_add_child_meta() - * - * Since: 1.2 - */ -void -clutter_layout_manager_remove_child_meta (ClutterLayoutManager *manager, - ClutterContainer *container, - ClutterActor *actor) -{ - g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); - g_return_if_fail (CLUTTER_IS_CONTAINER (container)); - g_return_if_fail (CLUTTER_IS_ACTOR (actor)); - - if (has_child_meta (manager, container, actor)) - g_object_set_qdata (G_OBJECT (actor), quark_layout_meta, NULL); -} - static inline gboolean layout_set_property_internal (ClutterLayoutManager *manager, GObject *gobject, @@ -665,7 +582,7 @@ clutter_layout_manager_child_set (ClutterLayoutManager *manager, if (meta == NULL) { g_warning ("Layout managers of type '%s' do not support " - "child metadata", + "layout metadata", g_type_name (G_OBJECT_TYPE (manager))); return; } @@ -685,7 +602,7 @@ clutter_layout_manager_child_set (ClutterLayoutManager *manager, pspec = g_object_class_find_property (klass, pname); if (pspec == NULL) { - g_warning ("%s: Layout managers of type '%s' have no child " + g_warning ("%s: Layout managers of type '%s' have no layout " "property named '%s'", G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname); break; @@ -749,7 +666,7 @@ clutter_layout_manager_child_set_property (ClutterLayoutManager *manager, if (meta == NULL) { g_warning ("Layout managers of type '%s' do not support " - "child metadata", + "layout metadata", g_type_name (G_OBJECT_TYPE (manager))); return; } @@ -759,7 +676,7 @@ clutter_layout_manager_child_set_property (ClutterLayoutManager *manager, pspec = g_object_class_find_property (klass, property_name); if (pspec == NULL) { - g_warning ("%s: Layout managers of type '%s' have no child " + g_warning ("%s: Layout managers of type '%s' have no layout " "property named '%s'", G_STRLOC, G_OBJECT_TYPE_NAME (manager), property_name); return; @@ -803,7 +720,7 @@ clutter_layout_manager_child_get (ClutterLayoutManager *manager, if (meta == NULL) { g_warning ("Layout managers of type '%s' do not support " - "child metadata", + "layout metadata", g_type_name (G_OBJECT_TYPE (manager))); return; } @@ -823,7 +740,7 @@ clutter_layout_manager_child_get (ClutterLayoutManager *manager, pspec = g_object_class_find_property (klass, pname); if (pspec == NULL) { - g_warning ("%s: Layout managers of type '%s' have no child " + g_warning ("%s: Layout managers of type '%s' have no layout " "property named '%s'", G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname); break; @@ -895,7 +812,7 @@ clutter_layout_manager_child_get_property (ClutterLayoutManager *manager, if (meta == NULL) { g_warning ("Layout managers of type %s do not support " - "child metadata", + "layout metadata", g_type_name (G_OBJECT_TYPE (manager))); return; } @@ -905,7 +822,7 @@ clutter_layout_manager_child_get_property (ClutterLayoutManager *manager, pspec = g_object_class_find_property (klass, property_name); if (pspec == NULL) { - g_warning ("%s: Layout managers of type '%s' have no child " + g_warning ("%s: Layout managers of type '%s' have no layout " "property named '%s'", G_STRLOC, G_OBJECT_TYPE_NAME (manager), property_name); return; diff --git a/clutter/clutter-layout-manager.h b/clutter/clutter-layout-manager.h index 2b6c247..676837d 100644 --- a/clutter/clutter-layout-manager.h +++ b/clutter/clutter-layout-manager.h @@ -80,7 +80,7 @@ struct _ClutterLayoutManager * @get_child_meta_type: virtual function; override to return the #GType * of the #ClutterLayoutMeta sub-class used by the #ClutterLayoutManager * @create_child_meta: virtual function; override to create a - * #ClutterChildMeta instance associated to a #ClutterContainer and a + * #ClutterLayoutMeta instance associated to a #ClutterContainer and a * child #ClutterActor, used to maintain layout manager specific properties * @layout_changed: class handler for the #ClutterLayoutManager::layout-changed * signal @@ -162,12 +162,6 @@ GParamSpec ** clutter_layout_manager_list_child_properties (ClutterLayoutMa ClutterLayoutMeta *clutter_layout_manager_get_child_meta (ClutterLayoutManager *manager, ClutterContainer *container, ClutterActor *actor); -void clutter_layout_manager_add_child_meta (ClutterLayoutManager *manager, - ClutterContainer *container, - ClutterActor *actor); -void clutter_layout_manager_remove_child_meta (ClutterLayoutManager *manager, - ClutterContainer *container, - ClutterActor *actor); void clutter_layout_manager_child_set (ClutterLayoutManager *manager, ClutterContainer *container, diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 36b552d..8a57dc7 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1749,8 +1749,6 @@ clutter_layout_manager_layout_changed clutter_layout_manager_set_container -clutter_layout_manager_add_child_meta -clutter_layout_manager_remove_child_meta clutter_layout_manager_get_child_meta clutter_layout_manager_child_set clutter_layout_manager_child_set_property -- 2.7.4