15.3.3 Adding edges
Edges are specified using primarily edges:from:to:
. The first argument provides a collection of entities that are meant to be the models for the edges. The second and the third arguments are expected to be blocks with one argument for each entity in the input collection.
For example, suppose we want to draw edges from each class to its superclass:
view nodes: classGroup.
view edges: classGroup from: [ :each | each superclass ] to: [ :each | each ].
The first instruction creates nodes for all the entities in the classGroup
collection. The second instruction, takes again the entities from the input collection and for each, it tries to produce an edge from the node corresponding to each superclass
to the node corresponding to each
. If at least one of the edge ends are not found, the edge is not created.
The ViewRenderer offers several other convenience constructors for edges. First, it provides several shorter forms.
For example, given the example above, we can see that we are specifying two superfluous pieces of information:
-
classGroup
is provided once to the nodes, and once to the edges, and - the
[ :each | each ]
block simply says that we want the input entity.
For convenience, we can use simply edgesFrom:
and the rest is filled it by the engine:
view nodes: classGroup.
view edgesFrom: [ :each | each superclass ].
Another set of messages deal with building edges based on 1-to-n or n-to-n relationships.
For example, the above example is based on the model of a class having at most one superclass relationship with another class. However, suppose we want to draw edges from each class to all classes invoked by that classes. In this case, we deal with a 1-to-n relationship because from one class we want to produce multiple edges.
One way to approach the problem is to decompose it by first traversing the collection:
view nodes: classGroup.
classGroup do: [ :eachClass |
view edges: eachClass invokedClasses from: eachClass to: [ :eachInvoked | eachInvoked ].
].
The external loop takes care of one dimension, and at each step we deal again with 1-to-1 relationships. For convenience, we can use the dedicated messages:
-
edges:from:toAll:
— for 1-to-n relationships, -
edges:fromAll:to:
— for n-to-1 relationships, and -
edges:fromAll:toAll:
— for n-to-n relationships.
Thus, our example becomes simply:
view nodes: classes.
view edges: classes from: [ :each | each ] toAll: [:each | each invokedClasses].
the lookup fromGlobal toGlobal