use of org.eclipse.elk.alg.layered.graph.LLabel in project elk by eclipse.
the class ElkGraphImporter method transformEdge.
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Edge Transformation
/**
* Transforms the given edge if it's not a hyperedge. If it is a hyperedge, throws an exception.
*
* @param elkedge the edge to transform
* @param elkparent the node in the original graph which currently gets transformed into {@code lgraph}
* @param lgraph the layered graph
* @return the transformed edge, or {@code null} if it cannot be transformed
* @throws UnsupportedGraphException if the edge is a hyperedge.
*/
private LEdge transformEdge(final ElkEdge elkedge, final ElkNode elkparent, final LGraph lgraph) {
checkEdgeValidity(elkedge);
// Get a few basic information about the edge
ElkConnectableShape elkSourceShape = elkedge.getSources().get(0);
ElkConnectableShape elkTargetShape = elkedge.getTargets().get(0);
ElkNode elkSourceNode = ElkGraphUtil.connectableShapeToNode(elkSourceShape);
ElkNode elkTargetNode = ElkGraphUtil.connectableShapeToNode(elkTargetShape);
ElkEdgeSection edgeSection = elkedge.getSections().isEmpty() ? null : elkedge.getSections().get(0);
// Find the transformed source and target nodes
LNode sourceLNode = (LNode) nodeAndPortMap.get(elkSourceNode);
LNode targetLNode = (LNode) nodeAndPortMap.get(elkTargetNode);
LPort sourceLPort = null;
LPort targetLPort = null;
// Find the transformed source port, if any
if (elkSourceShape instanceof ElkPort) {
// If the ElkPort is a regular port, it will map to an LPort; if it's an external port, it
// will map to an LNode
LGraphElement sourceElem = nodeAndPortMap.get(elkSourceShape);
if (sourceElem instanceof LPort) {
sourceLPort = (LPort) sourceElem;
} else if (sourceElem instanceof LNode) {
sourceLNode = (LNode) sourceElem;
sourceLPort = sourceLNode.getPorts().get(0);
}
}
// Find the transformed target port, if any
if (elkTargetShape instanceof ElkPort) {
// If the ElkPort is a regular port, it will map to an LPort; if it's an external port, it
// will map to an LNode
LGraphElement targetElem = nodeAndPortMap.get(elkTargetShape);
if (targetElem instanceof LPort) {
targetLPort = (LPort) targetElem;
} else if (targetElem instanceof LNode) {
targetLNode = (LNode) targetElem;
targetLPort = targetLNode.getPorts().get(0);
}
}
// reason, we back out
if (sourceLNode == null || targetLNode == null) {
throw new UnsupportedGraphException("The source or the target of edge " + elkedge + " could not be found. " + "This usually happens when an edge connects a node laid out by ELK Layered to a node in " + "another level of hierarchy laid out by either another instance of ELK Layered or another " + "layout algorithm alltogether. The former can be solved by setting the hierarchyHandling " + "option to INCLUDE_CHILDREN.");
}
// Create a layered edge
LEdge ledge = new LEdge();
ledge.copyProperties(elkedge);
ledge.setProperty(InternalProperties.ORIGIN, elkedge);
// Clear junction points, since they are recomputed from scratch
ledge.setProperty(LayeredOptions.JUNCTION_POINTS, null);
// If we have a self-loop, set the appropriate graph property
Set<GraphProperties> graphProperties = lgraph.getProperty(InternalProperties.GRAPH_PROPERTIES);
if (sourceLNode == targetLNode) {
graphProperties.add(GraphProperties.SELF_LOOPS);
}
// Create source and target ports if they do not exist yet
if (sourceLPort == null) {
PortType portType = PortType.OUTPUT;
KVector sourcePoint = null;
if (edgeSection != null && sourceLNode.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
sourcePoint = new KVector(edgeSection.getStartX(), edgeSection.getStartY());
// The coordinates need to be relative to us
ElkUtil.toAbsolute(sourcePoint, elkedge.getContainingNode());
ElkUtil.toRelative(sourcePoint, elkparent);
// source), we may need to adjust the coordinates
if (ElkGraphUtil.isDescendant(elkTargetNode, elkSourceNode)) {
// External source port: put it on the west side
portType = PortType.INPUT;
sourcePoint.add(sourceLNode.getPosition());
}
}
sourceLPort = LGraphUtil.createPort(sourceLNode, sourcePoint, portType, lgraph);
}
if (targetLPort == null) {
PortType portType = PortType.INPUT;
KVector targetPoint = null;
if (edgeSection != null && targetLNode.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
targetPoint = new KVector(edgeSection.getEndX(), edgeSection.getEndY());
// Adjust the coordinates
// MIGRATE Not sure yet if this really does what we want it to do
ElkUtil.toAbsolute(targetPoint, elkedge.getContainingNode());
ElkUtil.toRelative(targetPoint, elkparent);
}
targetLPort = LGraphUtil.createPort(targetLNode, targetPoint, portType, targetLNode.getGraph());
}
// Finally set the source and target of the edge
ledge.setSource(sourceLPort);
ledge.setTarget(targetLPort);
// If the ports have multiple incoming or outgoing edges, the HYPEREDGE property needs to be set
if (sourceLPort.getIncomingEdges().size() > 1 || sourceLPort.getOutgoingEdges().size() > 1 || targetLPort.getIncomingEdges().size() > 1 || targetLPort.getOutgoingEdges().size() > 1) {
graphProperties.add(GraphProperties.HYPEREDGES);
}
// Transform the edge's labels
for (ElkLabel elklabel : elkedge.getLabels()) {
if (!elklabel.getProperty(LayeredOptions.NO_LAYOUT) && !Strings.isNullOrEmpty(elklabel.getText())) {
LLabel llabel = transformLabel(elklabel);
ledge.getLabels().add(llabel);
// edge label placement is actually properly defined
switch(llabel.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT)) {
case HEAD:
case TAIL:
graphProperties.add(GraphProperties.END_LABELS);
break;
case CENTER:
graphProperties.add(GraphProperties.CENTER_LABELS);
llabel.setProperty(LayeredOptions.EDGE_LABELS_PLACEMENT, EdgeLabelPlacement.CENTER);
}
}
}
// Copy the original bend points of the edge in case they are required
CrossingMinimizationStrategy crossMinStrat = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
NodePlacementStrategy nodePlaceStrat = lgraph.getProperty(LayeredOptions.NODE_PLACEMENT_STRATEGY);
boolean bendPointsRequired = crossMinStrat == CrossingMinimizationStrategy.INTERACTIVE || nodePlaceStrat == NodePlacementStrategy.INTERACTIVE;
if (edgeSection != null && !edgeSection.getBendPoints().isEmpty() && bendPointsRequired) {
KVectorChain originalBendpoints = ElkUtil.createVectorChain(edgeSection);
KVectorChain importedBendpoints = new KVectorChain();
// MIGRATE We may have to do some coordinate conversion here
for (KVector point : originalBendpoints) {
importedBendpoints.add(new KVector(point));
}
ledge.setProperty(InternalProperties.ORIGINAL_BENDPOINTS, importedBendpoints);
}
return ledge;
}
use of org.eclipse.elk.alg.layered.graph.LLabel in project elk by eclipse.
the class ComponentsCompactor method addLGraphElementBounds.
private void addLGraphElementBounds(final List<Point> pts, final LShape element, final KVector offset) {
// extract the relevant margins object.
// there's LayoutOptions.MARGINS as well,
// however, this is only used outside of elk layered.
LMargin margins = null;
if (element instanceof LNode) {
margins = ((LNode) element).getMargin();
} else if (element instanceof LPort) {
margins = ((LPort) element).getMargin();
} else if (element instanceof LLabel) {
margins = new LMargin();
}
// add bounding box of the node
pts.add(new Point(element.getPosition().x - margins.left + offset.x, element.getPosition().y - margins.top + offset.y));
pts.add(new Point(element.getPosition().x - margins.left + offset.x, element.getPosition().y + element.getSize().y + margins.bottom + offset.y));
pts.add(new Point(element.getPosition().x + element.getSize().x + margins.right + offset.x, element.getPosition().y - margins.top + offset.y));
pts.add(new Point(element.getPosition().x + element.getSize().x + margins.right + offset.x, element.getPosition().y + element.getSize().y + margins.bottom + offset.y));
}
use of org.eclipse.elk.alg.layered.graph.LLabel in project elk by eclipse.
the class CompoundGraphPreprocessor method moveLabelsAndRemoveOriginalEdges.
/**
* Moves all labels of the original edges to the appropriate dummy edges and removes the
* original edges from the graph.
*
* @param graph
* the top-level graph.
*/
private void moveLabelsAndRemoveOriginalEdges(final LGraph graph) {
// edges from the graph
for (LEdge origEdge : crossHierarchyMap.keySet()) {
// segments
if (origEdge.getLabels().size() > 0) {
// retrieve and sort the edge segments introduced for the original edge
List<CrossHierarchyEdge> edgeSegments = new ArrayList<CrossHierarchyEdge>(crossHierarchyMap.get(origEdge));
Collections.sort(edgeSegments, new CrossHierarchyEdgeComparator(graph));
// iterate over the labels and move them to the edge segments
Iterator<LLabel> labelIterator = origEdge.getLabels().listIterator();
while (labelIterator.hasNext()) {
LLabel currLabel = labelIterator.next();
// find the index of the dummy edge we will move the label to
int targetDummyEdgeIndex = -1;
switch(currLabel.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT)) {
case HEAD:
targetDummyEdgeIndex = edgeSegments.size() - 1;
break;
case CENTER:
targetDummyEdgeIndex = getShallowestEdgeSegment(edgeSegments);
break;
case TAIL:
targetDummyEdgeIndex = 0;
break;
default:
}
// move the label if we were lucky enough to find a new home for it
if (targetDummyEdgeIndex != -1) {
CrossHierarchyEdge targetSegment = edgeSegments.get(targetDummyEdgeIndex);
targetSegment.getEdge().getLabels().add(currLabel);
targetSegment.getEdge().getSource().getNode().getGraph().getProperty(InternalProperties.GRAPH_PROPERTIES).add(GraphProperties.END_LABELS);
targetSegment.getEdge().getSource().getNode().getGraph().getProperty(InternalProperties.GRAPH_PROPERTIES).add(GraphProperties.CENTER_LABELS);
labelIterator.remove();
currLabel.setProperty(InternalProperties.ORIGINAL_LABEL_EDGE, origEdge);
}
}
}
// remove original edge
origEdge.setSource(null);
origEdge.setTarget(null);
}
}
use of org.eclipse.elk.alg.layered.graph.LLabel in project elk by eclipse.
the class AbstractGraphPlacer method moveGraph.
/**
* Move the source graph into the destination graph using a specified offset. This method should
* only be called once per graph, since it also applies the graph's set offset in addition to the
* one given in the methods of this argument.
*
* @param destGraph the destination graph.
* @param sourceGraph the source graph.
* @param offsetx x coordinate offset.
* @param offsety y coordinate offset.
*/
protected void moveGraph(final LGraph destGraph, final LGraph sourceGraph, final double offsetx, final double offsety) {
KVector graphOffset = sourceGraph.getOffset().add(offsetx, offsety);
for (LNode node : sourceGraph.getLayerlessNodes()) {
node.getPosition().add(graphOffset);
for (LPort port : node.getPorts()) {
for (LEdge edge : port.getOutgoingEdges()) {
edge.getBendPoints().offset(graphOffset);
KVectorChain junctionPoints = edge.getProperty(LayeredOptions.JUNCTION_POINTS);
if (junctionPoints != null) {
junctionPoints.offset(graphOffset);
}
for (LLabel label : edge.getLabels()) {
label.getPosition().add(graphOffset);
}
}
}
destGraph.getLayerlessNodes().add(node);
node.setGraph(destGraph);
}
}
use of org.eclipse.elk.alg.layered.graph.LLabel in project elk by eclipse.
the class LongEdgeSplitter method moveHeadLabels.
/**
* Moves all head labels from a given split edge to the new edge created to split it.
*
* @param oldEdge
* the old edge whose head labels are to be moved.
* @param newEdge
* the new edge whose head labels are to be moved.
*/
private static void moveHeadLabels(final LEdge oldEdge, final LEdge newEdge) {
ListIterator<LLabel> labelIterator = oldEdge.getLabels().listIterator();
while (labelIterator.hasNext()) {
LLabel label = labelIterator.next();
EdgeLabelPlacement labelPlacement = label.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT);
if (labelPlacement == EdgeLabelPlacement.HEAD) {
labelIterator.remove();
newEdge.getLabels().add(label);
if (!label.hasProperty(InternalProperties.END_LABEL_EDGE)) {
label.setProperty(InternalProperties.END_LABEL_EDGE, oldEdge);
}
}
}
}
Aggregations