mirror of
https://github.com/brl/mutter.git
synced 2025-05-05 22:54:56 +00:00
script: Support layout manager properties
Layout properties work similarly to child properties, with the added headache that they require the 3-tuple: ( layout manager, container, actor ) to be valid in order to be inspected, parsed and applied. This means using the newly added back-pointer from the container to the layout manager and then rejigging a bit how the ScriptParser handles the unresolved properties. Similarly to the child properties, which use the "child::" prefix, the layout manager properties use the "layout::" prefix and are defined with the child of a container holding a layout manager.
This commit is contained in:
parent
ab76584965
commit
4c22f122e1
1
.gitignore
vendored
1
.gitignore
vendored
@ -264,6 +264,7 @@ TAGS
|
|||||||
/tests/conform/test-state-base
|
/tests/conform/test-state-base
|
||||||
/tests/conform/test-texture-pick-with-alpha
|
/tests/conform/test-texture-pick-with-alpha
|
||||||
/tests/conform/test-cogl-object
|
/tests/conform/test-cogl-object
|
||||||
|
/tests/conform/test-script-layout-property
|
||||||
/tests/conform/wrappers
|
/tests/conform/wrappers
|
||||||
/tests/micro-bench/test-text-perf
|
/tests/micro-bench/test-text-perf
|
||||||
/tests/micro-bench/test-text
|
/tests/micro-bench/test-text
|
||||||
|
@ -1051,6 +1051,7 @@ clutter_script_parser_object_end (JsonParser *json_parser,
|
|||||||
pinfo->node = json_node_copy (node);
|
pinfo->node = json_node_copy (node);
|
||||||
pinfo->pspec = NULL;
|
pinfo->pspec = NULL;
|
||||||
pinfo->is_child = g_str_has_prefix (name, "child::") ? TRUE : FALSE;
|
pinfo->is_child = g_str_has_prefix (name, "child::") ? TRUE : FALSE;
|
||||||
|
pinfo->is_layout = g_str_has_prefix (name, "layout::") ? TRUE : FALSE;
|
||||||
|
|
||||||
oinfo->properties = g_list_prepend (oinfo->properties, pinfo);
|
oinfo->properties = g_list_prepend (oinfo->properties, pinfo);
|
||||||
}
|
}
|
||||||
@ -1422,9 +1423,11 @@ clutter_script_translate_parameters (ClutterScript *script,
|
|||||||
GParameter param = { NULL };
|
GParameter param = { NULL };
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
if (pinfo->is_child)
|
if (pinfo->is_child || pinfo->is_layout)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (SCRIPT, "Child property '%s' ignored", pinfo->name);
|
CLUTTER_NOTE (SCRIPT, "Skipping %s property '%s'",
|
||||||
|
pinfo->is_child ? "child" : "layout",
|
||||||
|
pinfo->name);
|
||||||
unparsed = g_list_prepend (unparsed, pinfo);
|
unparsed = g_list_prepend (unparsed, pinfo);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1530,6 +1533,112 @@ clutter_script_construct_parameters (ClutterScript *script,
|
|||||||
return unparsed;
|
return unparsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_layout_properties (ClutterScript *script,
|
||||||
|
ClutterContainer *container,
|
||||||
|
ClutterActor *actor,
|
||||||
|
ObjectInfo *oinfo)
|
||||||
|
{
|
||||||
|
ClutterScriptable *scriptable = NULL;
|
||||||
|
ClutterScriptableIface *iface = NULL;
|
||||||
|
gboolean set_custom_property = FALSE;
|
||||||
|
gboolean parse_custom_node = FALSE;
|
||||||
|
GList *l, *unresolved, *properties;
|
||||||
|
ClutterLayoutManager *manager;
|
||||||
|
GType meta_type;
|
||||||
|
|
||||||
|
manager = g_object_get_data (G_OBJECT (container), "clutter-layout-manager");
|
||||||
|
if (manager == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_type = _clutter_layout_manager_get_child_meta_type (manager);
|
||||||
|
if (meta_type == G_TYPE_INVALID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (SCRIPT, "Layout manager of type '%s' with meta type '%s'",
|
||||||
|
G_OBJECT_TYPE_NAME (manager),
|
||||||
|
g_type_name (meta_type));
|
||||||
|
|
||||||
|
/* shortcut, to avoid typechecking every time */
|
||||||
|
if (CLUTTER_IS_SCRIPTABLE (manager))
|
||||||
|
{
|
||||||
|
scriptable = CLUTTER_SCRIPTABLE (manager);
|
||||||
|
iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable);
|
||||||
|
|
||||||
|
parse_custom_node = iface->parse_custom_node != NULL ? TRUE : FALSE;
|
||||||
|
set_custom_property = iface->set_custom_property != NULL ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
properties = oinfo->properties;
|
||||||
|
oinfo->properties = NULL;
|
||||||
|
|
||||||
|
unresolved = NULL;
|
||||||
|
for (l = properties; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
PropertyInfo *pinfo = l->data;
|
||||||
|
GValue value = { 0, };
|
||||||
|
gboolean res = FALSE;
|
||||||
|
const gchar *name;
|
||||||
|
|
||||||
|
if (!pinfo->is_layout)
|
||||||
|
{
|
||||||
|
unresolved = g_list_prepend (unresolved, pinfo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = pinfo->name + strlen ("layout::");
|
||||||
|
|
||||||
|
pinfo->pspec =
|
||||||
|
clutter_layout_manager_find_child_property (manager, name);
|
||||||
|
|
||||||
|
if (pinfo->pspec != NULL)
|
||||||
|
g_param_spec_ref (pinfo->pspec);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (SCRIPT, "Parsing %s layout property (id:%s)",
|
||||||
|
pinfo->pspec != NULL ? "regular" : "custom",
|
||||||
|
name);
|
||||||
|
|
||||||
|
if (parse_custom_node)
|
||||||
|
res = iface->parse_custom_node (scriptable, script, &value,
|
||||||
|
name,
|
||||||
|
pinfo->node);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
res = clutter_script_parse_node (script, &value,
|
||||||
|
name,
|
||||||
|
pinfo->node,
|
||||||
|
pinfo->pspec);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (SCRIPT, "Layout property '%s' ignored", name);
|
||||||
|
unresolved = g_list_prepend (unresolved, pinfo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (SCRIPT,
|
||||||
|
"Setting %s layout property '%s' (type:%s) to "
|
||||||
|
"object '%s' (id:%s)",
|
||||||
|
set_custom_property ? "custom" : "regular",
|
||||||
|
name,
|
||||||
|
g_type_name (G_VALUE_TYPE (&value)),
|
||||||
|
g_type_name (oinfo->gtype),
|
||||||
|
oinfo->id);
|
||||||
|
|
||||||
|
clutter_layout_manager_child_set_property (manager, container, actor,
|
||||||
|
name,
|
||||||
|
&value);
|
||||||
|
|
||||||
|
g_value_unset (&value);
|
||||||
|
|
||||||
|
property_info_free (pinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (properties);
|
||||||
|
|
||||||
|
oinfo->properties = unresolved;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
apply_child_properties (ClutterScript *script,
|
apply_child_properties (ClutterScript *script,
|
||||||
ClutterContainer *container,
|
ClutterContainer *container,
|
||||||
@ -1715,10 +1824,6 @@ add_children (ClutterScript *script,
|
|||||||
g_type_name (G_OBJECT_TYPE (container)));
|
g_type_name (G_OBJECT_TYPE (container)));
|
||||||
|
|
||||||
clutter_container_add_actor (container, CLUTTER_ACTOR (object));
|
clutter_container_add_actor (container, CLUTTER_ACTOR (object));
|
||||||
|
|
||||||
apply_child_properties (script,
|
|
||||||
container, CLUTTER_ACTOR (object),
|
|
||||||
child_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_list_foreach (oinfo->children, (GFunc) g_free, NULL);
|
g_list_foreach (oinfo->children, (GFunc) g_free, NULL);
|
||||||
@ -1737,6 +1842,49 @@ _clutter_script_check_unresolved (ClutterScript *script,
|
|||||||
if (oinfo->behaviours != NULL && CLUTTER_IS_ACTOR (oinfo->object))
|
if (oinfo->behaviours != NULL && CLUTTER_IS_ACTOR (oinfo->object))
|
||||||
apply_behaviours (script, oinfo);
|
apply_behaviours (script, oinfo);
|
||||||
|
|
||||||
|
/* this is a bit *eugh*, but it allows us to effectively make sure
|
||||||
|
* that child and layout properties are parsed and applied to the
|
||||||
|
* right child
|
||||||
|
*/
|
||||||
|
if (oinfo->properties != NULL && CLUTTER_IS_ACTOR (oinfo->object))
|
||||||
|
{
|
||||||
|
ClutterActor *parent;
|
||||||
|
|
||||||
|
parent = clutter_actor_get_parent (CLUTTER_ACTOR (oinfo->object));
|
||||||
|
if (parent != NULL && CLUTTER_IS_CONTAINER (parent))
|
||||||
|
{
|
||||||
|
ClutterContainer *container = CLUTTER_CONTAINER (parent);
|
||||||
|
ClutterActor *actor = CLUTTER_ACTOR (oinfo->object);
|
||||||
|
GList *children, *l;
|
||||||
|
|
||||||
|
children = clutter_container_get_children (container);
|
||||||
|
|
||||||
|
for (l = children; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
GObject *child = l->data;
|
||||||
|
ObjectInfo *child_info;
|
||||||
|
const gchar *id;
|
||||||
|
|
||||||
|
id = clutter_get_script_id (child);
|
||||||
|
if (id == NULL || *id == '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
child_info = _clutter_script_get_object_info (script, id);
|
||||||
|
if (child_info == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
apply_child_properties (script, container,
|
||||||
|
actor,
|
||||||
|
child_info);
|
||||||
|
apply_layout_properties (script, container,
|
||||||
|
actor,
|
||||||
|
child_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (oinfo->properties || oinfo->children || oinfo->behaviours)
|
if (oinfo->properties || oinfo->children || oinfo->behaviours)
|
||||||
oinfo->has_unresolved = TRUE;
|
oinfo->has_unresolved = TRUE;
|
||||||
else
|
else
|
||||||
|
@ -80,6 +80,7 @@ typedef struct {
|
|||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
|
|
||||||
guint is_child : 1;
|
guint is_child : 1;
|
||||||
|
guint is_layout : 1;
|
||||||
} PropertyInfo;
|
} PropertyInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -186,6 +186,7 @@ main (int argc, char **argv)
|
|||||||
TEST_CONFORM_SIMPLE ("/script", test_animator_properties);
|
TEST_CONFORM_SIMPLE ("/script", test_animator_properties);
|
||||||
TEST_CONFORM_SIMPLE ("/script", test_animator_multi_properties);
|
TEST_CONFORM_SIMPLE ("/script", test_animator_multi_properties);
|
||||||
TEST_CONFORM_SIMPLE ("/script", test_state_base);
|
TEST_CONFORM_SIMPLE ("/script", test_state_base);
|
||||||
|
TEST_CONFORM_SIMPLE ("/script", test_script_layout_property);
|
||||||
|
|
||||||
TEST_CONFORM_SIMPLE ("/behaviours", test_behaviours);
|
TEST_CONFORM_SIMPLE ("/behaviours", test_behaviours);
|
||||||
|
|
||||||
|
@ -336,3 +336,54 @@ test_script_animation (TestConformSimpleFixture *fixture,
|
|||||||
g_object_unref (script);
|
g_object_unref (script);
|
||||||
g_free (test_file);
|
g_free (test_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_script_layout_property (TestConformSimpleFixture *fixture,
|
||||||
|
gconstpointer dummy G_GNUC_UNUSED)
|
||||||
|
{
|
||||||
|
ClutterScript *script = clutter_script_new ();
|
||||||
|
GObject *manager, *container, *actor;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *test_file;
|
||||||
|
gboolean x_fill, expand;
|
||||||
|
ClutterBoxAlignment y_align;
|
||||||
|
|
||||||
|
test_file = clutter_test_get_data_file ("test-script-layout-property.json");
|
||||||
|
clutter_script_load_from_file (script, test_file, &error);
|
||||||
|
if (g_test_verbose () && error)
|
||||||
|
g_print ("Error: %s", error->message);
|
||||||
|
|
||||||
|
#if GLIB_CHECK_VERSION (2, 20, 0)
|
||||||
|
g_assert_no_error (error);
|
||||||
|
#else
|
||||||
|
g_assert (error == NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
manager = container = actor = NULL;
|
||||||
|
clutter_script_get_objects (script,
|
||||||
|
"manager", &manager,
|
||||||
|
"container", &container,
|
||||||
|
"actor", &actor,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||||
|
g_assert (CLUTTER_IS_CONTAINER (container));
|
||||||
|
g_assert (CLUTTER_IS_ACTOR (actor));
|
||||||
|
|
||||||
|
x_fill = FALSE;
|
||||||
|
y_align = CLUTTER_BOX_ALIGNMENT_START;
|
||||||
|
expand = FALSE;
|
||||||
|
clutter_layout_manager_child_get (CLUTTER_LAYOUT_MANAGER (manager),
|
||||||
|
CLUTTER_CONTAINER (container),
|
||||||
|
CLUTTER_ACTOR (actor),
|
||||||
|
"x-fill", &x_fill,
|
||||||
|
"y-align", &y_align,
|
||||||
|
"expand", &expand,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (x_fill);
|
||||||
|
g_assert (y_align == CLUTTER_BOX_ALIGNMENT_CENTER);
|
||||||
|
g_assert (expand);
|
||||||
|
|
||||||
|
g_object_unref (script);
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ json_files = \
|
|||||||
test-animator-2.json \
|
test-animator-2.json \
|
||||||
test-animator-3.json \
|
test-animator-3.json \
|
||||||
test-state-1.json \
|
test-state-1.json \
|
||||||
|
test-script-layout-property.json \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
png_files = \
|
png_files = \
|
||||||
|
16
tests/data/test-script-layout-property.json
Normal file
16
tests/data/test-script-layout-property.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
{ "id" : "manager", "type" : "ClutterBoxLayout" },
|
||||||
|
|
||||||
|
{
|
||||||
|
"id" : "container", "type" : "ClutterBox",
|
||||||
|
"layout-manager" : "manager",
|
||||||
|
"children" : [
|
||||||
|
{
|
||||||
|
"id" : "actor", "type" : "ClutterRectangle",
|
||||||
|
"layout::x-fill" : true,
|
||||||
|
"layout::y-align" : "center",
|
||||||
|
"layout::expand" : true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
Loading…
x
Reference in New Issue
Block a user