How to prevent cropping of edges at the node's bounds

Questions & Answers

Summary

This article shows how to draw an edge so that it ends at its assigned port and not at the node's bounds (i.e. prevent edge cropping).

Description

If a port is located inside the node bounds, the edge path is cropped at the node bounds per default.

Disable cropping by writing a custom edge style renderer

The easiest way to change this behaviour is to override the cropPath() function of

PolylineEdgeStyleRenderer to do nothing:

public class NeverCropPolylineEdgeStyleRenderer extends PolylineEdgeStyleRenderer
{
    protected override function cropPath(pathToCrop:GeneralPath):void { }
}

You can use the custom PolylineEdgeStyleRenderer by passing it to the com.yworks.graph.drawing.PolylineEdgeStyle constructor.

var edgeStyle:IEdgeStyle = new PolylineEdgeStyle(new NeverCropPolylineEdgeStyleRenderer());

Disable cropping using the lookup mechanism

A more flexible and more elegant approach is to change the edge's lookup: The default implementation of cropPath() queries the edge's port's lookup for an

com.yworks.graph.drawing.IEdgeIntersectionCalculator. Hence, you could also change the cropping behavior by returning a custom edge intersection calculator from the lookup() method of the edge's source and target ports.

The most convenient way to do so is to use the com.yworks.graph.model.GraphDecorator. TheGraphDecorator's portDecorator has an edgeIntersectionCalculator property which can be used to decorate the lookup for the ports:

Disable edge cropping for all ports

To disable the edge cropping for all ports the port's lookup has to return a IEdgeIntersectionCalculator implementation which does nothing.

public class EmptyEdgeIC implements IEdgeIntersectionCalculator
{
  public function cropEdgePath(edge:IEdge, atSource:Boolean, arrow:IArrow, edgePath:GeneralPath):void { }
}

The GraphDecorator can be used to configure the lookup upon initialization. Note that for folded graphs the view graph's decorator has to be used.

var decorator:GraphDecorator = graph.lookup(GraphDecorator) as GraphDecorator;
decorator.portDecorator.edgeIntersectionDecorator.setInstance(new EmptyEdgeIC());

Disable edge cropping for specific ports

The method setInstance() takes a predicate function as optional parameter. The predicate function takes a IPort as parameter and returns true if the custom implementation should be used and false if the default implementation should be used.

var decorator:GraphDecorator = graph.lookup(GraphDecorator) as GraphDecorator;
var predicate:Function = function(port:IPort):Boolean {
    if (/* the edge should be cropped at the given port */) {
      return true;
    }
    return false;
  };
decorator.portDecorator.edgeIntersectionDecorator.setInstance(new EmptyEdgeIC(), predicate);

Disable edge cropping for specific edges / edge ports

If the edge cropping should be disabled for specific edges or edge ports a wrapper can be used. The wrapper implementation decides in its cropEdgePath() method whether to use the default implementation or do nothing.

The following example shows how to disable edge cropping at the source ports only. It wraps the default implementation and delegates to the wrapped implementation for the target ports. For the source ports it does nothing.

public class NoSourceEICWrapper implements IEdgeIntersectionCalculator
{
  private var _wrapped:IEdgeIntersectionCalculator;

  public function NoSourceEICWrapper(wrapped:IEdgeIntersectionCalculator)
  {
    this._wrapped  = wrapped;
  }

  public function cropEdgePath(edge:IEdge, atSource:Boolean, arrow:IArrow, edgePath:GeneralPath):void
  {
    if (!atSource) {
      this._wrapped.cropEdgePath(edge, atSource, arrow, edgePath);
    }
  }

}

To wrap the default implementation the LookupDecorator's setImplementationWrapper() method can be used:

var decorator:GraphDecorator = graph.lookup(GraphDecorator) as GraphDecorator;
var wrapper:Function = function(port:IPort, wrapped:IEdgeIntersectionCalculator):IEdgeIntersectionCalculator {
    return new NoSourceEICWrapper(wrapped);
  };
decorator.portDecorator.edgeIntersectionDecorator.setImplementationWrapper(wrapper);

Categories this article belongs to:
yFiles FLEX > Architectural Concepts > Look-up Mechanism
yFiles FLEX > Displaying and Editing Graphs > Visual Representation of Graph Elements
Applies to:
yFiles FLEX: 1.4, 1.5, 1.6, 1.7, 1.8
Keywords:
edge - edge cropping - cropping - node bounds - lookup - GraphDecorator