Morphs as composition of traits?

Igor Stasenko siguctua at gmail.com
Sat Feb 9 05:52:39 UTC 2008


During walk with my dog, i just have different thoughts about morphs,
and about what schemes is best fit to adequately model the morphic
system.

Here, is my thoughts:
it's really hard to tell what properties morphs can be kept as basic(core) ones.
Dimenstions(shape)? No. There is morphs which never show-up on screen
and therefore don't need any dimension/shape info.
Visual aspects? Again - no. Depending on morph, they can be very
different, including colors, borders or font style for text.

So, maybe, i thought, better to think of morph as composition of
different traits, which in sum defining an original morph.

Let me pick an example, to better illustrate what i have in mind

Rectangle morph.
It should include a 'shape' trait, because rectangle is just a kind of
shape (lets assume it's a ShapeTrait subclass - RectangularShape).
Now, with having shape we can speak of different visual aspects, like
border and fill.
Note, that once you defined shape, it's should not mean, by default
that it can have border or fill - it's another traits (but in this
turn, the traits of shape).
So, for instance i could have 3 kinds of rectangle morph: with fill
only, with border only and with border and fill both.
If you see, by using such approach, it's really looks like i'm
building morph from composition of different traits which are
organized in tree-like manner.

Okay , we just defined a set of traits which should define a rectange morph.
Now, is how to build a real instance of it (or class which producing them).
Instance of such class would require from us a state, which will
reflect a different trait-based properties of it.
How about using anonymous classes, and using special methods, in
traits class, which should describe what state should be included into
resulting class?
Then, we can create a morph class on the fly, using UI by picking
traits and compositing them, and in result we will have a class, ready
to work with.

As one of the variants it can be a #statevars method:

FillTrait class>>statevars
 ^ #(fillstyle)

Now suppose we have a class named MorphClassBuilder which simply
builds for us an anonymous morph class.

MorphClassBuilder>>numvars
| numvars size |
size := 0.
self allIncludedTraits do: [:trait | size := size + trait statevars size ].
^ size

By having a #numvars, it's easy to add a #new method for our future morph class:

resultingClass addClassMethod: 'new ^ self basicNew' , builder numvars asString.

.. and, it's really easy to add accessors to such class:

MorphClassBuilder>>addAccessors
| allvars |
allvars := OrderedCollection new.
allvars := self allIncludedTraits do:[:trait | allvars addAll: trait
statevars ].

allvars withIndexDo: [:i :selector |
   resultingClass compileMethod: selector , ' ^ self at:' , i asString
. "read accessor"
   resultingClass compileMethod: selector , ': value  ^ self at:' , i
asString , ' put: value' . "write accessor"

.. as you can see, nothing really hard, here: just implement a
MorphClassBuilder, and you'll have a powers to create virtually any
kind of morph by combining wide variety of traits.

Back to example, our rectangle morph with fill and border require 3 state vars:
- bounds
- fillstyle
- borderstyle

So, a MorphClassBuilder should produce a morph class with following methods:

new
  ^ self basicNew: 3

bounds
  ^ self at: 1
bounds: value
  ^ self at: 1 put: value

fillstyle
  ^ self at: 2
fillstyle: value
  ^ self at: 2 put: value

borderstyle
  ^ self at: 3
borderstyle: value
  ^ self at: 3 put: value


I don't know (it's not clear the future of Traits in squeak), but i
think it's easy to overcome a stateless limits of traits by
introducing schemes which i just illustrated.
Also, if you considered given example, being stateless not really an
issue - it can always can be added dynamically :)

-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list