A Group is a just a ClutterActor with the layout-manager property set at
instance initialization time. It doesn't need anything else from
ClutterActor's vtable, except the slightly custom show_all/hide_all
implementation, and a simplified get_paint_volume.
Instead of chaining up, given that we want to bypass chaining up and
just set the allocation. This also allows us to bail out of the
overridden allocate vfunc check, given that we want the default Actor
behaviour to apply - including eventual layout manager delegates.
The usual way to implement a container actor is to override the
allocate() virtual function, chain up, and then allocate the actor's
children.
Clutter now has the ability to delegate layout management to
ClutterLayoutManager directly; in the allocation, this is done by
checking whether the actor has children, and then call
clutter_layout_manager_allocate() from within the default implementation
of the ClutterActor::allocate() vfunc. The same vfunc that everyone, has
been chaining up to.
Whoopsie.
Well, we can check if there's a layout manager, and if it's NULL, we
bail out. Except that there's a default layout manager, and it's the
fixed layout manager, so that classes like Group and Stage work by
default.
Double whoopsie.
The fix for this scenario is a bit nasty; we have to check if the actor
class has overridden the allocate() vfunc or not, before actually
looking at the layout manager. This means that classes that override the
allocate() vfunc are expected to do everything that ClutterActor's
default implementation does - which I think it's a fair requirement to
have.
For newly written code, though, it would probably be best if we just
provided a function that does the right thing by default, and that
you're supposed to be calling from within the allocate() vfunc
implementation, if you ever chose to override it. This new function,
clutter_actor_set_allocation(), should come with a warning the size of
Texas, to avoid people thinking it's a way to override the whole "call
allocate() on each child" mechanism. Plus, it should check if we're
inside an allocation sequence, and bail out if not.
If we want to set a default layout manager, we need to do so inside
init(), as it's not guaranteed that people subclassing Actor and
overriding ::constructed will actually chain up as they should.
The default pick() behaviour does not take into consideration the
children of a ClutterActor because the existing containter actors
usually override pick(), chain up, and then paint their children.
With ClutterActor now a concrete class, though, we need a way to pick
its children without requiring a sub-class; we could simply iterate over
the children inside the default pick() implementation, but this would
lead to double painting, which is not acceptable.
A moderately gross hack is to check if the Actor instance did override
the pick() implementation, and if it is not the case, paint the children
in pick mode.
The hide_all() method is pretty much pointless, as hiding an actor will
automatically prevent its children from being painted. The show_all()
method would only be marginally useful, if actors weren't set to be
visible by default when added to another actor - which was the case when
we introduced show_all() and hide_all().
* Abstracts the buffer for text in ClutterText
* Allows implementation of undo/redo.
* Allows use of non-pageable memory for text
in the case of sensitive passwords.
* Implement a test with two ClutterText using the same
buffer.
https://bugzilla.gnome.org/show_bug.cgi?id=652653
When dereferencing GArray.data to a C structure you need a double cast
from guint8* to void*, and then from void* to the actual type. This
avoids compiler warnings, especially when using clang on OSX.
The concept of "internal child" only meant anything when we had a
separate API for containers and actors. Now that we plugged that
particular hole, we can drop all the hacks we used to have in place
to work around its design limitations.
It can be convenient to be able to set, or get, all the components of an
actor's margin at the same time; since we already have a boxed type for
storing a margin, an accessors pair based on it is not a complicated
addition to the API.
Inside the set_child_[above|below]_sibling() and set_child_at_index() we
should be using the internal API for mutating the children list, instead
of the delegate functions. This ensures that we go through a single,
well-defined code path for all operations on the list of children of
an actor.
We have a replacement in ClutterActor, now.
The old ClutterContainer API needs to be deprecated, and the raise() and
lower() virtual functions need a default implementation, so we can check
for implementations overriding them, by using the diagnostic mode like
we do for add(), remove(), and foreach().
The sort_depth_order() virtual function just doesn't do anything, as it
should have been made ages ago.
The Actor wrappers for the Container methods also need to be deprecated.
ClutterActor provides four methods for changing the paint sequence order
of its children:
raise_top()
raise()
lower()
lower_bottom()
The first and last one being just wrappers around raise() and lower(),
respectively. These methods have various issues: they omit the parent,
preferring to retrieve it from the actor passed as the first argument;
this does not match the new style of API introduced to operate on the
list of children of an actor.
Additionally, the raise() and lower() methods of ClutterActor call into
the Container interface, and are not really aptly named (raise() in
particular collides with the completely unrelated 'raise' keyword in
Python, and usually needs to be wrapped in order to be used at all).
Furthermore, we need public methods that Container can call from its
default implementation, as well as methods to port current Container
implementations.
Finally, since we have insert_child_at_index(), we should also have an
equivalent set_child_at_index() as well.
The internal versions of add_child() and remove_child() currently use
boolean arguments to control things like the ChildMeta instances and
the emissions of signals; using more than one boolean argument is an
indication that you need flags to avoid readability issues, as well as
providing a way to add new behaviours without a combinatorial explosion
of arguments, later on.
I don't feel comfortable with this feature, and its implementation
still has too many rough edges. We can safely punt it for now, and
introduce it at a later point, as it doesn't block existing features
or API.
This virtual function will let layout managers with legacy expansion
flags be able to influence the lazy computation of the expansion flags
on ClutterActor.
We need to paint the background color in the default class handler for
two reasons: it's logically appropriate, and we don't want actor
subclasses overriding the ::paint class handler to change behaviour only
because somebody decided to set the background color.
The old add(), remove(), and foreach() virtual functions are deprecated;
ClutterContainer should warn if the public API detects that the vfuncs
have been overridden.
Strictly speaking, it's still legal to override those vfuncs: you can
chain up to the default vtable, or you could just provide an equivalent
implementation. The goal is to avoid having to override the Container
interface, until we can safely deprecate it and remove it in Clutter
2.0.
Instead of making ClutterActor implement the basic add/remove/foreach
virtual functions of ClutterContainer, we can simply do that from
within the ClutterContainer implementation.
The get_children(), foreach(), and foreach_with_internals() methods and
virtual functions are superceded by the Actor API, and should not be
used in newly written code.
Given the size and scope of the changes in ClutterActor, we ought to
rewrite the overall description of what an actor is, what it does, and
how are you supposed to use it and subclass it.
This will make things interesting.
We have better replacements in ClutterActor, that do The Right Thing™
instead of deferring control and requiring reimplementation in every
single container actor.
The correct sequence of actions should be remove(old) → insert(new), not
insert(new) → remove(old). We can implement a simple delegate insertion
functions to insert the new child between the previous and next siblings
of the old child.
While we're at it, let's also add a unit test for replace_child().
Providing a default get_paint_volume() that takes into account the
children of an actor was a goal of the whole First Apocalypse; if we
make all the containers rely on it, and yet we return a FALSE value
(meaning: we don't have a valid paint volume) even when we do have it,
then we are going to break the whole machinery, though.