From aaae60e17837d6f0b330c04345f1e2c2be9f24b9 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 15 Sep 2009 23:20:51 +0100 Subject: [PATCH] [layout] Implement ClutterBox::add The ClutterBox::add method is a simple wrapper around the Container add_actor() method and the LayoutManager layout properties API. It allows adding an actor to a Box and setting the layout properties in one call. If the LayoutManager used by the Box does not support layout properties then the add() method short-circuits out. Along with the varargs version of the method there's also a vector-based variant, for language bindings to use. --- clutter/clutter-box.c | 186 +++++++++++++++++++++++++++++ clutter/clutter-box.h | 10 ++ doc/reference/clutter/clutter-sections.txt | 2 + tests/interactive/test-box.c | 31 ++--- 4 files changed, 210 insertions(+), 19 deletions(-) diff --git a/clutter/clutter-box.c b/clutter/clutter-box.c index c7ec8c4..6d55d7f 100644 --- a/clutter/clutter-box.c +++ b/clutter/clutter-box.c @@ -11,6 +11,9 @@ #include "config.h" #endif +#include +#include + #include "clutter-box.h" #include "clutter-debug.h" #include "clutter-enum-types.h" @@ -438,3 +441,186 @@ clutter_box_get_layout_manager (ClutterBox *box) return box->priv->manager; } + +/** + * clutter_box_addv: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @n_properties: the number of properties to set + * @properties: (array length=n_properties) (element-type utf8): a vector + * containing the property names to set + * @values: (array length=n_properties): a vector containing the property + * values to set + * + * Vector-based variant of clutter_box_add(), intended for language + * bindings to use + * + * Since: 1.2 + */ +void +clutter_box_addv (ClutterBox *box, + ClutterActor *actor, + guint n_properties, + const gchar * const properties[], + const GValue *values) +{ + ClutterContainer *container; + ClutterBoxPrivate *priv; + ClutterLayoutMeta *meta; + GObjectClass *klass; + gint i; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + container = CLUTTER_CONTAINER (box); + clutter_container_add_actor (container, actor); + + priv = box->priv; + + meta = clutter_layout_manager_get_child_meta (priv->manager, + container, + actor); + + if (meta == NULL) + return; + + klass = G_OBJECT_GET_CLASS (meta); + + for (i = 0; i < n_properties; i++) + { + const gchar *pname = properties[i]; + GParamSpec *pspec; + + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') does not exist", + G_STRLOC, + pname, + G_OBJECT_TYPE_NAME (priv->manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') is not writable", + G_STRLOC, + pspec->name, + G_OBJECT_TYPE_NAME (priv->manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + clutter_layout_manager_child_set_property (priv->manager, + container, actor, + pname, &values[i]); + } +} + +/** + * clutter_box_add: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @first_property: the name of the first property to set, or %NULL + * @Varargs: a list of property name and value pairs, terminated by %NULL + * + * Adds @actor to @box and sets layout properties at the same time, + * if the #ClutterLayoutManager used by @box has them + * + * This function is a wrapper around clutter_container_add_actor() + * and clutter_layout_manager_child_set() + * + * Language bindings should use the vector-based clutter_box_addv() + * variant instead + * + * Since: 1.2 + */ +void +clutter_box_add (ClutterBox *box, + ClutterActor *actor, + const gchar *first_property, + ...) +{ + ClutterBoxPrivate *priv; + ClutterContainer *container; + ClutterLayoutMeta *meta; + GObjectClass *klass; + const gchar *pname; + va_list var_args; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + container = CLUTTER_CONTAINER (box); + clutter_container_add_actor (container, actor); + + if (first_property == NULL || *first_property == '\0') + return; + + priv = box->priv; + + meta = clutter_layout_manager_get_child_meta (priv->manager, + container, + actor); + + if (meta == NULL) + return; + + klass = G_OBJECT_GET_CLASS (meta); + + va_start (var_args, first_property); + + pname = first_property; + while (pname) + { + GValue value = { 0, }; + GParamSpec *pspec; + gchar *error; + + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') does not exist", + G_STRLOC, + pname, + G_OBJECT_TYPE_NAME (priv->manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') is not writable", + G_STRLOC, + pspec->name, + G_OBJECT_TYPE_NAME (priv->manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + G_VALUE_COLLECT (&value, var_args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + clutter_layout_manager_child_set_property (priv->manager, + container, actor, + pspec->name, &value); + + g_value_unset (&value); + + pname = va_arg (var_args, gchar*); + } + + va_end (var_args); +} diff --git a/clutter/clutter-box.h b/clutter/clutter-box.h index 40d359c..3d47365 100644 --- a/clutter/clutter-box.h +++ b/clutter/clutter-box.h @@ -40,6 +40,16 @@ ClutterActor * clutter_box_new (ClutterLayoutManager *mana ClutterLayoutManager *clutter_box_get_layout_manager (ClutterBox *box); +void clutter_box_add (ClutterBox *box, + ClutterActor *actor, + const gchar *first_property, + ...) G_GNUC_NULL_TERMINATED; +void clutter_box_addv (ClutterBox *box, + ClutterActor *actor, + guint n_properties, + const gchar * const properties[], + const GValue *values); + G_END_DECLS #endif /* __CLUTTER_BOX_H__ */ diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 63c090d..d28f453 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1806,6 +1806,8 @@ ClutterBox ClutterBoxClass clutter_box_new clutter_box_get_layout_manager +clutter_box_add +clutter_box_addv CLUTTER_TYPE_BOX diff --git a/tests/interactive/test-box.c b/tests/interactive/test-box.c index 2c3d50e..1a51c84 100644 --- a/tests/interactive/test-box.c +++ b/tests/interactive/test-box.c @@ -117,15 +117,13 @@ test_box_main (int argc, char *argv[]) clutter_actor_set_name (box, "box"); rect = make_background (&bg_color, 200, 200); - clutter_container_add_actor (CLUTTER_CONTAINER (box), rect); + clutter_box_add (CLUTTER_BOX (box), rect, + "x-align", CLUTTER_BIN_ALIGNMENT_FILL, + "y-align", CLUTTER_BIN_ALIGNMENT_FILL, + NULL); clutter_actor_lower_bottom (rect); clutter_actor_set_name (rect, "background"); - clutter_bin_layout_set_alignment (CLUTTER_BIN_LAYOUT (layout), - CLUTTER_CONTAINER (box), - rect, - CLUTTER_BIN_ALIGNMENT_FILL, - CLUTTER_BIN_ALIGNMENT_FILL); { ClutterActor *tex; @@ -137,16 +135,13 @@ test_box_main (int argc, char *argv[]) g_error ("Unable to create texture: %s", error->message); clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (tex), TRUE); - clutter_container_add_actor (CLUTTER_CONTAINER (box), tex); + clutter_box_add (CLUTTER_BOX (box), tex, + "x-align", CLUTTER_BIN_ALIGNMENT_CENTER, + "y-align", CLUTTER_BIN_ALIGNMENT_CENTER, + NULL); clutter_actor_raise (tex, rect); clutter_actor_set_width (tex, 175); clutter_actor_set_name (tex, "texture"); - - clutter_bin_layout_set_alignment (CLUTTER_BIN_LAYOUT (layout), - CLUTTER_CONTAINER (box), - tex, - CLUTTER_BIN_ALIGNMENT_CENTER, - CLUTTER_BIN_ALIGNMENT_CENTER); } color = clutter_color_new (g_random_int_range (0, 255), @@ -155,17 +150,15 @@ test_box_main (int argc, char *argv[]) 224); rect = clutter_rectangle_new_with_color (color); - clutter_container_add_actor (CLUTTER_CONTAINER (box), rect); + clutter_box_add (CLUTTER_BOX (box), rect, + "x-align", CLUTTER_BIN_ALIGNMENT_END, + "y-align", CLUTTER_BIN_ALIGNMENT_END, + NULL); clutter_actor_set_size (rect, 50, 50); clutter_actor_set_opacity (rect, 0); clutter_actor_raise_top (rect); clutter_actor_set_name (rect, "emblem"); - clutter_bin_layout_set_alignment (CLUTTER_BIN_LAYOUT (layout), - CLUTTER_CONTAINER (box), - rect, - CLUTTER_BIN_ALIGNMENT_END, - CLUTTER_BIN_ALIGNMENT_END); g_signal_connect (box, "enter-event", G_CALLBACK (on_box_enter), -- 2.7.4