Alexandre,
Thanks for addition of the rubberband feature. Having considered the
ROExample some more, I think it would provide a better show by
highlighting the available target nodes, so (to keep the application
code concise) I was thinking of rearranging the API as follows...
---------------
rubberband := RORubberBand new
targeting: [:sourceElement | sourceElement view
allElementsSelect: [:targetElement | [targetElement
model first asInteger = (sourceElement model first asInteger + 1)]]];
highlightTargets;
onDrop: [:rawNewEdge |
rawNewEdge + ROLine.
rawNewEdge to removeAllEdgesTo.
rawNewEdge to view add: rawNewEdge.
ROTreeLayout on: rawView elements].
--------------
where I was adding ROView>>allElementsSelect: as...
--------------
allElementsSelect: aBlock
| newCollection |
newCollection := OrderedCollection new.
self allElementsDo: [:each | (aBlock value: each) ifTrue:
[newCollection add: each]].
^newCollection
--------------
However I bumped into an issue where (unless you see a more elegant
solution) I feel the right thing might be to rename #allElementsDo: to
#allElementsAndEdgesDo (or #alllAbstractElementsDo:) and create two new
methods #allEdgesDo: and #allElementsDo:
The issue is that I was assuming I would be safe with the code
"sourceElement model first" since I _know_ the model is a string,
however I was surprised that this failed - due to #allElementsDo also
processing edges which had no model. However trying to workaround this
with the following also fails...
--------------
allElementsSelect: [:targetElement |
(targetElement isKindOf: ROElement)
and: (targetElement model first
asInteger = (sourceElement model first asInteger + 1)) ]
--------------
since the right-side is not bypassed when the left-side evaluates to
#true as per other languages (as well it clutters the application code)
Hence it seems useful for the (targetElement isKindOf: ROElement) to be
pushed upstream. However what would such a method be called?
#allElementsDo: is already taken, unless as mentioned above
#allElementsDo: is renamed to #allAbstactElementsDo: and new
#allEdgesDo: and #allElementsDo: are created.
Actually a new thought just occurs.... since Roassal has two major
components ROEdge and ROElement, and I think it will be _very_ common to
filter between them, having something like #allElementsKindOf:do: (as
well as #allElementsKindOf:select:) might be useful, such that the
application code would be...
--------------
rubberband := RORubberBand new
targeting: [:sourceElement | sourceElement view
allElementsKindOf: ROElement select: [:targetElement
| [targetElement model first asInteger = (sourceElement model first
asInteger + 1)]]];
highlightTargets;
onDrop: [:rawNewEdge |
rawNewEdge + ROLine.
rawNewEdge to removeAllEdgesTo.
rawNewEdge to view add: rawNewEdge.
ROTreeLayout on: rawView elements].
--------------
This could leave the rubberbanding mechanism flexible to later drop
edges onto other edges - which might be randomly useful for something
like the hyperedges discussed recently. Do you have any other ideas on
achieving something similar to the last example?
cheers -ben
P.S. While it is elegant that ROAbstractElement has only one instance
variable 'elements' containing both ROElements and ROEdges, it is a
little unfortunate when considering the term 'elements' in general
discussion and documentation that there is a semantic overlap between
ROAbstactElement and ROElement that may at times be open to confusion.