Morphs as composition of traits?

Igor Stasenko siguctua at gmail.com
Sat Feb 9 19:34:25 UTC 2008


On 09/02/2008, stephane ducasse <stephane.ducasse at free.fr> wrote:
> > 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.
>
So, it was discussed earlier, can you give me any references where i
can read about it?

> Yes
> Our first example was taken from rectangleMorph and rectangle and all
> the current delegation
>
> > 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.
>
> One idea was that rectangleMorph just plug rectangleShapeTrait to gain
> all the rectangle oriented behavior.
> >
> >
> > 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?
>
> This is interesing. Now the problem is that you may have to recompile
> (and copy down) the methods
> where you have instance variable offset conflicts.
>

It's not a problem, because these methods are generated automatically,
so you can't have offset conflicts in principle.
You may have a name clashing (when two traits using variable with same
name). But this can be resolved easily: we can state that if two
different traits require state with same name, they should use the
same state slot.

> >
> > 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.
>
> Why anonymous? We could just have a normal class
> because most of the time you will want to add new behavior to that
> class or resolve conflicts.

Maybe that was a point, to prevent developer to be able to edit this
class directly, to make sure he is unable to change the generated
composition of methods.
How do you think, is it possible to design such architecture, that
there will be no sense to make any changes in final class?
A system which provide enough facilities, that any direct intrusion in
morph class is pointless.

> >
> >
> > 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.
> >
> >
>
>
>


-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list