Adding new edges to existing ports only
Tips & TricksSummary
Description
When a new edge is created, the CreateEdgeInputMode
queries the INode
's lookup for an IPortCandidateProvider
implementation.
The default candidate provider implementation tries to find an unoccupied port candidate and uses the center if none is found.
To suggest all existing ports as candidates, one has to implement an own port candidate provider:
public class ExistingPortsCandidateProvider extends AbstractPortCandidateProvider
{
/**
* The constructor sets the port owner, i.e. the node
*/
public function ExistingPortsCandidateProvider( owner:IPortOwner ) {
setPortOwner(owner);
}
/**
* Returns a list with port candidates representing the node's ports
*/
protected override function getPortCandidates(graph:IGraph):Iterable {
var list:ArrayList = new ArrayList();
var it:Iterator = this.portOwner.ports.iterator();
while( it.hasNext() ) {
list.addItem( DefaultPortCandidate.create( IPort(it.next()) ) );
}
return list;
}
}
There are three ways to install this customized port candidate provider:
- Register the port candidate provider in the node's lookup
- Register the port candidate provider in the graph's lookup chain (yFiles FLEX 1.2 and higher)
- Register the port candidate provider in the graph's NodeDecorator (yFiles FLEX 1.4.0.2 and higher)
Register the port candidate provider in the node's lookup
Installing the candidate provider into the node's lookup has the advantage that it is possible to install it only to selected nodes:
var lookup:IMutableLookup = node.lookup( IMutableLookup ) as IMutableLookup;
if (lookup != null) {
lookup.registerLookup(IPortCandidateProvider, new ExistingPortsCandidateProvider(node));
}
Register the port candidate provider in the graph's lookup chain (yFiles FLEX 1.2 and higher)
To change the behaviour of all nodes, the easiest way is to use the lookup chain of the graph implementation. To do so, first he has to write a simple ILookupChainLink implementation:
public class ExistingPortsLookupChainLink extends AbstractContextLookupChainLink
{
public override function lookupForItem(item:Object, type:Class):Object {
if (item is INode && type == IPortCandidateProvider) {
return new ExistingPortsCandidateProvider(item as INode);
}
return super.lookupForItem(item, type);
}
}
This chain link can be installed with:
var decorator:ILookupDecorator = graphCanvas.graph.lookup( ILookupDecorator ) as ILookupDecorator;
if( null != decorator ) {
if( decorator.canDecorate( INode ) ) {
decorator.addLookup(INode, new ExistingPortsLookupChainLink() );
}
}
Note, that this mechanism is available since yFiles FLEX 1.2. For earlier versions, one has register the custom port candidate provider "manually" to all nodes.
Register the port candidate provider in the graph's NodeDecorator (yFiles FLEX 1.4.0.2 and higher)
This is a more convenient way but effectively works the same as using a customIContextLookupChainLink
.A
com.yworks.graph.model.GraphDecorator
has to be looked up from the graph so the portCandidateProviderDecorator
of its nodeDecorator
property can be used to add the ExistingPortsCandidateProvider
:
var graphDecorator:GraphDecorator = graphCanvas.graph.lookup(GraphDecorator) as GraphDecorator;
graphDecorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
function(node:INode):IPortCandidateProvider {
return new ExistingPortsCandidateProvider(node);
});