Tuesday, March 04, 2008

the power of Containments

In Plasma all the "top level" groupings of widgets are Containments. Desktops are containments, panels are Containments ... everything that holds a group of desktop widgets is a Containment. In addition to being the atom of grouping, Containments are responsible for the presentation of things beneath widgets (e.g. wallpapers) and around widgets (e.g. context menus, toolboxes). All the Containments live in the scene, which is called Corona in the code.

Containments themselves are plugins; in fact, they are a specialization of Plasma::Applet and come with all the same flexibility plus a little bit extra. (I suppose that means that in theory you could have a superkaramba theme or a Mac Dashboard widget as your desktop or panel ... it would require some minor patching in corona.cpp around line 400 to work in practice, however.)

Right now there are four Containments that I'm aware of available for the Plasma workspace: DefaultDesktop, Panel, Null and AnalogClock (of course ;). I believe the Amarok guys have also written a Containment specifically for Amarok's needs. To give you an idea of the complexity involved, Panel is 329 lines of code (including the header) and DefaultDesktop is 2,213 lines (though that also currently includes wallpaper Package support, threaded wallpaper rendering and all the legacy Desktop directory loading code). With scripting, you could do this without C++ even (though right now we lack some useful/necessary bindings to the Containment class to make this practical ... not a huge amount of work though).

The runtime definition for a Containment (such as your desktop area on a given physical screen) is stored in the configuration file looking something like this:


[Containments][1]
formfactor=0
geometry=0,0,1280,800
location=0
locked=false
plugin=desktop
screen=0


The Containment plugin that is loaded is defined by the plugin= entry. Change that entry and you change the containment. The widgets inside stay the same, only the Containment changes ... (to protect the innocent?)

Changing the screen= entry alters which physical screen, if any, a containment is associated with. This is where this feature overlaps with the zooming: zooming out is how one gets an overview of all available containments (modulo panels) to switch between them or just interact with widgets that on other Containments (including moving them between Containments). This has all been there since 4.0.

(By the by, if you have been looking for a longer explanation of the zooming concept, here's a blog from last July where I wrote such a thing.)

Plasma has been designed with this idea of switching Containments as a very basic and rather central concept. Those following closely will have noticed that I've mentioned this idea more than once in various screencasts and blogs in the last year or two.

However, it seems that the full implications of this particular feature set is being missed, because when, in passing, I noted what this means in relation to something like the toolbox (remember, that's the containment's job) on panel-devel people were ... surprised. I was surprised they were surprised. I thought I was stating the bleeding obvious, but apparently I wasn't. So, lots of surprised people all around. To join in the party of surprised people, here it is:

If you want a different feature set, select a different Containment.


So if you want no toolbox, a completely different neat/crazy background concept, something that incorporates a different widget layout schema, or $WHATEVER ... you just need to find a containment that provides that. This is similar to how instead of having one clock applet with a bazillion configuration options and widgets, we instead have clock visualizations that share most of their code with each other and you select between the different clock faces when choosing a clock to stare at.

The inspiration for this approach was watching the various Kicker PanelExtension classes and feeling the pain of just how limited they were in what they were allowed to do. Because of that, people creating things like the Mac dock would fork bits of kicker, write their own panel system from scratch, do it in Superkaramba, etc. That seemed really unfortunate. People want radically different ways of dealing with panels, and I figured they'd want the same with their desktops, media centers and mobile devices. So why not make that part of the interface a plugin that's as flexible as any desktop widget itself is?

Now let's reflect on the idea that I'm not keen on making the desktop toolbox configurable: maybe it starts to make sense to you that it's an unnecessary complication because the whole Containment is a plugin. The toolbox has a point and purpose, it's improving nicely as we go and, yes, I personally think it will become something rather compelling .. but at the end of the day it's just part of another plugin loaded at runtime. The only hardcoded bit is that it's the default plugin to load in lieu of other configuration directives.

(If you're wondering if other Containments can take advantage of the toolbox if they wish, yes they can. The Containment class provides access to it for any Containment plugin that so wishes to use it.)

Currently, Containment switching and creation is "hidden" in the appletsrc config file. We will be making UI for it, hopefully for 4.1. It's been pending completion of the DefaultDesktop config dialog which we will then genericize into a general Containment config. To the user this will appear pretty much like any other wallpaper setting dialog, only with a hell of a lot more punch as it will give access to more than just wallpaper changes when you hit that "Ok" button.