Adjusting port assignments for ports outside or inside a node's visual representation
When layouting a graph (and/or routing its edges), yFiles' layout algorithms automatically determine an edge's source point and target point or, in yFiles Viewer speak, its source and target port. Depending on the layout algorithm, ports are usually placed on the center of the associated node or on the border of the node's bounding box. For some use cases, these port assignments are insufficient. E.g. for nodes with non-rectangular visual representations, the second of the above mentioned strategies oftentimes results in ports outside the node.
Class PortCalculator
is a LayoutStage
that can be used to improve the ports outside the node situtation. PortCalculator queries each edge for appropriate implementations of interface IntersectionCalculator
, which know enough about the visual representation of the edge's source or target node to calculate an appropriate port location.
yFiles' Viewer framework comes with a generic IntersectionCalculator provider (NodeRealizerIntersectionCalculator
), which can be used with Graph2D
instances:
graph.addDataProvider(
IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY,
new NodeRealizerIntersectionCalculator(graph, true));
graph.addDataProvider(
IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY,
new NodeRealizerIntersectionCalculator(graph, false));
(new PortCalculator()).doLayout(graph);
graph.removeDataProvider(IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY);
graph.removeDataProvider(IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY);
|
| Note |
|
When working with graphs that are not of type Graph2D, custom IntersectionCalculator implementations have to be provided.
|
For the case where ports are assigned to some point inside a node's visual representation, yFiles' Viewer framework automatically displays edges as if ports were placed on the border of the node's visual representation. Still, ports can be moved from the inside of a node to its border using a similar approach like PortCalculator as demonstrated by PortCalculator2, ContainsTest, and NodeRealizerContainsTest, which are attached to this article. This works best if ports are not outside of a node's visual representation, which suggests to run this strategy right after PortCalculator has done its thing.
graph.addDataProvider(
IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY,
new NodeRealizerIntersectionCalculator(graph, true));
graph.addDataProvider(
IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY,
new NodeRealizerIntersectionCalculator(graph, false));
graph.addDataProvider(
ContainsTest.CONTAINS_TEST_DPKEY,
new NodeRealizerContainsTest());
final CompositeLayoutStage cls = new CompositeLayoutStage();
cls.prependStage(new PortCalculator());
cls.prependStage(new PortCalculator2());
cls.doLayout(graph);
graph.removeDataProvider(ContainsTest.CONTAINS_TEST_DPKEY);
graph.removeDataProvider(IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY);
graph.removeDataProvider(IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY);
|