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.
In order to know if a layout property exists and retrieve its
description in form of a GParamSpec, we need a wrapper API inside
ClutterLayoutManager. This allows introspecting a LayoutManager
sub-class and eventually serialize and deserialize it.
When calling remove_child_meta() we check if there is a LayoutMeta
already attached to the Actor, and if that LayoutMeta matches the
(manager, container, actor) tuple. If the LayoutMeta does not match,
though, we create a new LayoutMeta instance -- in order to remove it
right afterwards.
Instead of doing this, we can simply check for a matching LayoutMeta
and if present, remove it.
In case of an existing, non-matching LayoutMeta, we're left with a
dangling instance, but it does not matter: the removal happens in the
unparenting phase of a ClutterContainer, so either the Actor will be
destroyed and thus the LayoutMeta will be disposed along with it; or
it will be parented to another container, and thus the LayoutMeta
will be replaced.
The layout manager reference should have some documentation on how
to use a LayoutManager object inside a container and how to implement
a LayoutManager sub-class correctly.
The LayoutManager implementation might opt to take a back pointer
to the Container that is using the layout instance; this allows
direct access to the container itself from within the implementation.
Instead of overloading ClutterChildMeta with both container and layout
metadata and delegate to every LayoutManager implementation to keep a
backpointer to the layout manager instance, we can simply subclass
ChildMeta into LayoutMeta and presto! everything works out pretty well
for everyone.
The ChildMeta object is a storage for child-container properties,
that is properties that exist only when an actor is inside a specific
container. The LayoutManager delegate class should also have
layout-specific properties -- so, for this job, we can "recycle"
ChildMeta as the storage.
If a sub-class of LayoutManager wishes to implement a parametrized
layout policy it also needs a way to notify the container using the
layout manager that the layout has changed. We cannot do it directly
and automatically from the LayoutManager because a) it has no back
link to the actor that it is using it and b) it can be attached to
multiple actors.
This is a job for <cue raising dramatic music> signals!
By adding ClutterLayoutManager::layout-changed (and its relative
emitted function) we can notify actors using the layout manager that
the layout parameters have been changed, and thus they should queue
a relayout.
A layout manager instance makes only sense if it's owned by a
container. For this reason, it should have a floating reference
instead of a full reference on construction; this allows constructing
Boxes like:
box = clutter_box_new (clutter_fixed_layout_new ());
without leaking the layout manager instance.
The LayoutManager class is an abstract proxy for the size requesition
and size allocation process in ClutterActor.
A ClutterLayoutManager sub-class must implement get_preferred_width(),
get_preferred_height() and allocate(); a ClutterContainer using the
LayoutManager API will then proxy the corresponding Actor virtual
functions to the LayoutManager instance. This allows having a generic
"blank" ClutterActor sub-class, implementing the ClutterContainer
interface, which leaves only the layout management implementation to
the application developers.