Had a dream

as I wrote already in a previous blog post, if you try and compile an existing Clutter application with the current master, the first thing you will notice is that the compiler will start complaining about deprecated symbols.

a lot.

some of these symbols are little used API variants, or baggage we’ve been stringing along since the 0.x days and that we never managed to deprecate until now — and if you’ve been using them, then I’m not sure I want to know why, and you’ll have to trust me when I say that you’re better off not using them.

on the other hand, many of the deprecated symbols have been pretty central as to how a Clutter app is built and works; clutter_container_add_actor()? clutter_actor_raise()? ClutterBox? clutter_timeline_set_loop()?

in reality, not much has changed per se: the deprecation warnings will tell you how to port an app from the old API to the new one, and in basically all cases it’s juts a matter of changing functions or classes; plus, deprecated classes and functions will still work until we break API and release Clutter 2.0.

what really changed is how a Clutter app should be written from the get go — and this has more to do with the intent of the API, more than the actual form of the API.

case in point: if you look at the replacement for many of the deprecated functionality, as well as the new API introduced in 1.10, you will notice that it is overwhelmingly inside the ClutterActor class; the 1.9 development cycle stats for the clutter-actor.[ch] files alone are:

 git diff --stat clutter-1.8... clutter/clutter-actor.[ch]
 clutter/clutter-actor.c |20516 +++++++++++++++++++++++++++++------------------
 clutter/clutter-actor.h |  803 +-
 2 files changed, 13350 insertions(+), 7969 deletions(-)

so ClutterActor just gained around 5000 lines ((yes, I’m cheating a little bit, as a lot of documentation is inlined inside the source code, so that balloons the size of the delta)).

this growth reflects one of the fundamental tenets of how Clutter should be used:

it’s all about actors

Actors are not the base, abstract class for elements on the UI: they are now a concrete class that should be used directly, instead of through sub-classes. the ClutterActor class is the element of the scene graph; it holds children, it paints them, it lays them out. there is one API to learn, one class that holds the keys to all the behaviour, and one class to inherit from for custom controls.

obviously, ClutterActor cannot do everything by itself; but instead of creating sub-classes to specialize the behaviour right within Clutter, a delegation pattern was preferred. layout is now deferred to ClutterLayoutManager; painting is delegated to ClutterContent.

delegation means that composition is the approach for creating apps; Clutter is, now more than ever, like a set of blocks that can be composed together to achieve a compelling, dynamic user interface.

let’s start from an actual example: whereas until 1.8 you had to use the ClutterContainer interface as the public side for building and manipulating the actor tree, now ClutterActor owns the entire list of public entry points for adding, removing, and iterating children; this also applies to the implementation of container actors: the ClutterContainer interface is implemented directly by the ClutterActor class, so you can just subclass the latter and use the default implementation without having to care about internal children, or memory management, or mapping and unmapping. even painting and picking by default will do the right thing — so you don’t have to care any more. when you subclass the ClutterActor class you can now concentrate only on the things your class has to do — instead of having to care about Clutter internals.

moving all the API from within the containers to the actors also meant being able to add a bunch of convenience functions for manipulating and iterating the actor tree; usually, these functions had to be provided by container classes, and thus had to be re-implemented over, and over, and over again. now, instead, you can get the first and last child of an actor, and iterate over their siblings; or you can create a simple, stack allocated iterator structure, and safely iterate over the children of an actor. you can insert actors at a specific index in the paint and allocation sequence, or you can replace a child atomically. finally, you can remove, or destroy, all the children of an actor in one fell swoop.

implementing the Container interface inside ClutterActor also allowed us to seamlessly migrate the ClutterLayoutManager delegate over to ClutterActor; this means that every actor can now delegate the layout of its children to any layout manager without requiring weird incantations. ((the layout manager API still needs some adaptations, which will come in the 1.12 time frame))

building the actor tree, though, it’s just part of the job of creating a Clutter app; we’ll see in the next blog post what changes happened when you want to fill an app with content…

2 Replies to “Had a dream”

  1. Can you post some simple before/after examples about actors? (Or maybe this is coming in another blog post?)

  2. @Thiago: the wiki contains some example code in the Exegesis section of each Apocalypse; it’s pretty hard to come up with some meaningful example, but I’ll try to create a bunch of those.

Comments are closed.