[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.
This commit is contained in:
Emmanuele Bassi 2009-09-15 23:20:51 +01:00
parent a2086f1178
commit aaae60e178
4 changed files with 210 additions and 19 deletions

View File

@ -11,6 +11,9 @@
#include "config.h"
#endif
#include <glib-object.h>
#include <gobject/gvaluecollector.h>
#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);
}

View File

@ -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__ */

View File

@ -1806,6 +1806,8 @@ ClutterBox
ClutterBoxClass
clutter_box_new
clutter_box_get_layout_manager
clutter_box_add
clutter_box_addv
<SUBSECTION Standard>
CLUTTER_TYPE_BOX

View File

@ -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),