Just recording a bit of my learning the internals of
Roassal, since it helps me flesh out my understanding.
At first glance looking at [ROShape>>addLast:] this seemed to recursively call
itself with no exit-condition, but then I noticed its ivar 'next' is initialized
to ROChildrenShape this provides the exit condition inherited from RONullShape.
Exactly. This is an instance of the Null Object design pattern.
I try to avoid ifTrue:ifFalse: as much as I can. Only 7.6% of Roassal methods have an if
statement. Slightly less than Glamour (8.08%). Mondrian has 8.63%. This figure goes to
9.57% for Moose, 10.33% for Fame and 20.96% for AST. Less is better.
Adding a shape replaces this ROChildrenShape in
'next', but the new shape itself has a ROChildrenShape in its 'next' .
I haven't got as far looking at ROChildrenShape yet, but briefly thought it might be
a container holding other shapes, but then actually I think it is the ROElements ivar
'elements' that is the container of subview nodes - and that ROChildrenShape just
stores how to draw the subview nodes.
Yes. ROChildrenShape displays the children node. This shape is per default on an element.
On some point, we will be able to change this shape for a ROLevelledChildrenShape to
enable semantic zooming.
I guess it is the lack of the [drawOn:For:] method
that distinguishes between abstract and concrete ROShape classes. By the way, what is the
design decision of leaving [ROShape>>drawOn:For] blank rather than using [self
subclassResponsibility] ?
Because executing "self subclassResponsibility" raise an error. And drawOn: is a
method that is called by the UI thread. When you create a shape, you may forget to
redefine drawOn:For:.
Since in Pharo (as it was in Squeak), UI thread behaves heretically time to time, having a
blank ROShape>>drawOn:For: avoid having this infinite list of opening debugger,
which inevitably leads to killing the image.
Side node: Processing is a very cool graphic engine. I believe that one reason of the
success of Processing to that it rarely crashes. When you do something wrong, then it just
complains. There is no infinite loop of debugger opening or need to kill the running
process.
So, just to confirm my understanding, perhaps the
following or similar would be useful as a comment on ROShape>>addLast:
"Instance variable 'next' must be a RONullShape to provide the exit
condition of this recursive call. This is ensured by instance initialization"
Good idea.
In Roassal 1.96
Indeed, Roassal is not well documented. Instead, I tried to keep the code very simple.
A major documentation will soon be needed.
Cheers,
Alexandre
--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel
http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.