three years ago Neil and I wrote the Model
API, to be included in Clutter. We tried encode in the design what we learned from the experience with GtkTreeModel
, and while it could be said that there are shortcomings (a base class instead of an interface, no bulk operations, some corner cases in the iterators API) I think we managed well enough not to repeat the same issues (boxed types, volatile iterators, and conflating a Tree and a List API into one) on top of those.
still, we made what I now think is the same design mistake all over again: we tried to provide a way to write MVC applications with Clutter, and we ended up collapsing the model with the controller — that is: we added a new data storage class that notifies you when something changed inside it ((gtk+, in a way, allows you to bolt a controller on top< of a data storage, but you still need the data storage to be a class inside the type system otherwise you won’t be able to implement the GtkTreeModel
interface)).
I now think it’s a mistake trying to conflate the data storage with the actual object notifying the views about changes: the controller should just be notified by the model and notify the views
GLib already provides a lot of data storage types: GArray
, GPtrArray
, GHashTable
, etc. — it would seem sensible to just use them and just wrap the insertion and removal functions instead of:
- create a
GObject
wrapper around a data structure; - wrap insertion, removal and iteration operations;
- add specialized code and signals to handle the changes and notify the views;
on top of these, if you want to write a generic storage you’ll have to:
- make every entry point a virtual function, to allow sub-classes overriding or providing a default behaviour;
- provide a generic iterator API;
- wrap everything with
GValue
s;
in essence, the complexity of the storage quickly balloons out of control — and all because you wanted to notify another object that you added a new item inside a GPtrArray
((and no: I don’t think that keeping the complexity under check by losing generality is a good trade-off; it’s just going to bite you in the rear later on)).
[caption id=”attachment_329” align=”alignright” width=”240” caption=”CONTROL! - by fatbwoy, CC-by-nd-2.0”][/caption]
wouldn’t it be good to have the “notify somebody that $SOMETHING
changed inside a data storage” thing nailed down with a generic API?
I did think it would be good, so I spent some free cycles last week to implement a generic Controller — the thing that notifies a view that something changed. it requires minimal additions to already existing data storage types provided by GLib — to the point that you don’t really need a GObject
wrapper around your model altogether.
the overall design is explained on the GNOME wiki, so I won’t rewrite it down here; and yes: if, by a cursory glance, it looks a lot like a certain platform’s API it’s because I think it’s a good representation of a correct approach.
the code lives in the GNOME Git repository; it currently has a stub LGPLv2.1 license because I think it should be seen as a 1700 lines patch to GObject/GIO under version control, and not as a stand-alone project ((it also gave me the chance to play with non-recursive autotools layouts, but that was just a side-effect)).
there are some things left to do, notably a GObjectController
which I think I described to a colleague as GObject::notify on PCP; for that to happen, though, I’ll need some changes in GObject
itself.