Players and Costumes


[This is from an old memo and needs to be updated]

In Tweak, each graphical object exists in a "dual" representation - as a "model" like object (called a "Player") and as "view" like object (called a "Costume"). The basic deal here is that "players direct costumes" (such as requesting them to appear at this or that position) and "costumes notify players" about certain events (such as a mouse down). What had been really bothersome was that there was only one kind of "primitive costume". While there are good reasons to have primitive costumes (basically, they encapsulate all of the uglyness of the framework internal stuff) it was problematic that players were always a mixture of "abstract and concrete" objects, not much different from morphs. Meaning that they contained certain state that the user is most definitely interested in but also some stuff which was essentially "implementation left-over".

For example, a ScrollBar had some state (such as its min, max, value etc) which the user would be modify but then also had state such as the forward and back button, the scroll area, its scroll knob etc. which really was very implementation specific. Meaning it is almost impossible to have "other kinds of scrollbars" which did not have any of these parts and just blitted a bitmap on the screen.

The breakthrough here was simply to realize that being a "player" or a "costume" are roles rather than types. In other words, the above definition of costume and player can be applied to any kind of object if it just fullfills the requirements. Changing a whole bunch of the implementation actually made this work - now every player can also act as a costume. Meaning that suddenly our scrollbar example breaks down to having a "scrollbar player" with the abstract state (min, max, value) and a "scrollbar costume" with the concrete state (forward, back button...) which is simply that scrollbar's costume.

One of the effect that I hadn't really anticipated here but which fell out for free, is that this scheme also gives us "viewing" for free - there is no reason that an object can only have "one costume"; there may be many costumes for the same object and it's simply the "primary one" which the player directs immediately. But other costumes can perfectly well "view" the state of the same player. So all that one has to do for the above scrollbar example to get "another view" is to create a new scrollbar costume and set its player to some other scrollbar - voila, they both show the same state, but appear in different places of the screen (as the player will only direct its "primary view" - the costume it knows about).

In addition, we can have various costumes for any kind of player - in fact we can change these interactively. So one of the things I'll probably be doing is to provide a number of "native costumes" which simply go straight to the OS and just use whatever it provides. The nice thing is that the application will never even be aware of this - all it deals with are the players and what kind of costumes these players wear is actually up to the user.

Also note that the players which "act as costumes" use other players as well - so for example, the "ScrollPane costume" I have defined can perfectly well use a "ScrollBar" which is carrying, say, an OSX-ScrollBar costume. It is really interesting to see how much most frameworks screw up in this regard. For example, take MVC - if I would implement the scroll pane I would have to refer to the scrollbar's view since it is the only object that provides graphical state (such as position, extent etc). So if the scroll pane needs to be able to re-arrange the scrollbars it cannot do that short of "poking around in the view". What Tweak provides here is a graphical model and its because of the ability to describe graphical models that you don't have to "look behind the curtain" to modify graphical aspects (to be precise it's a combination of delegating graphical state to the costume and keeping the "model" state in the players which achieves that).

Ownership of objects

The other really intriguing thing that happened lately is that I finally fully realized why "Tweak" is called that way. It turns out that it really is the ultimate user interface tweaking tool. Something that I hadn't even dreamt about when it started. So what does this mean?

One of the fundamental differences between Tweak and Squeak (or more appropriately: Morphic) is that there is a really strong notion of ownership. Most objects created are owned by others in a way which effectively means that they play an important role for their owner. For example, consider a window - it may have a close button, a collapse button, a label. These objects aren't random - they serve a well-defined purpose within that window and Tweak allows for very easy description of these roles.

As a completely random besides here, the term "owner" from Morphic is really wrong. The objects aren't owned they are contained within their "owner" (so "container" would be a much better term). Why is this problematic? Actually, it wouldn't be problematic at all if Morphic wouldn't allow us to change the composition of morphs. But since it does, treating the submorphs as parts of their container is really wrong. Formulated differently: Does a SystemWindow's closeButton change if I take it out of the window and put it on the desktop? No, it doesn't. It's still the SystemWindow's closeButton and acts like this window's closeButton.

The most profound implication for this is that when we interact with an object in Tweak graphically, we not only know about this object in its "primitive form" (such as: this is a button, or this is a label) but also about the role it plays in the entire construction. So if we interactively modify the close button in a window we can easily describe the modification in terms of "the user has changed the window's closeButton to have the color red". Since almost all objects are owned, it is trivial to pin-point precisely what modifications were done by a user, even if it gets lengthy such as "the user changed a ClassBrowser's systemCategoryList's listWidget's vScrollBar's backButton's color".

With a "tweak description" like this, we are able to take it and apply it to any object that "matches" (e.g., has the same type/properties) - so if we change that backButton, we can take any other browser and apply precisely the same changes.

What's more is that these tweak description are context-sensitive in the sense that we can describe local tweaks as part of an overall composition. For example, in the above we describe a change to a button but this change only applies to "the backButton of a vScrollBar of a listWidget of a systemCategoryList of a browser" (and not to all buttons in the world). So if we have a composite object, we can tweak it in any form or shape and have the tweaks apply only to that particular context. Practically, this means that while we can tweak "windows in general" (such as in the above) we can also tweak "a browser's window" to be different from "a text editor's window".

Finally, since we're exclusively dealing with "user tweaks", the application's behavior is not affected by it at all. If I am in the midst of using a browser and realize that I really don't like this or that graphical aspect, I can change it, and the system will save only the changes I have done interactively. Meaning that the next browser which comes up will carry the graphical changes but still work just like it did before.

What this really does is bring the "turnaround times" for user interface changes down to zero. There is simply no "programmer intervention" involved in changing any of the UI aspects and the changes are applied in a side-effect free way. In fact, the programmer may not have to provide any user interface at all - the browser could be build exclusively by applying "tweaks" in the graphical domain.

How so? It really goes together with the first part about players and costumes. If the programmer uses the appropriate "models" for the composition of some application, a user-interface designer can just choose "the right costumes" for the objects. So a Browser can just be defined as a set of lists, an editor and a UI designer can ask the system to hand it "a costume for the list", decide what kind of costume to use, bring it into the right place and save the composition as a "tweak" for the browser. The programmer doesn't have to be involved at all except from providing good and easy to use models.

And that's what good programmers are good at anyways: Building models.