Search in sources :

Example 16 with ElkLabel

use of org.eclipse.elk.graph.ElkLabel 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;
}
Also used : UnsupportedGraphException(org.eclipse.elk.core.UnsupportedGraphException) NodePlacementStrategy(org.eclipse.elk.alg.layered.options.NodePlacementStrategy) ElkNode(org.eclipse.elk.graph.ElkNode) LLabel(org.eclipse.elk.alg.layered.graph.LLabel) GraphProperties(org.eclipse.elk.alg.layered.options.GraphProperties) ElkPort(org.eclipse.elk.graph.ElkPort) LGraphElement(org.eclipse.elk.alg.layered.graph.LGraphElement) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) KVectorChain(org.eclipse.elk.core.math.KVectorChain) ElkConnectableShape(org.eclipse.elk.graph.ElkConnectableShape) ElkEdgeSection(org.eclipse.elk.graph.ElkEdgeSection) ElkLabel(org.eclipse.elk.graph.ElkLabel) LPort(org.eclipse.elk.alg.layered.graph.LPort) CrossingMinimizationStrategy(org.eclipse.elk.alg.layered.options.CrossingMinimizationStrategy) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) PortType(org.eclipse.elk.alg.layered.options.PortType)

Example 17 with ElkLabel

use of org.eclipse.elk.graph.ElkLabel in project elk by eclipse.

the class ElkUtil method ensureLabel.

/**
 * If the element does not already own a label, a label is created based on the element's
 * identifier.
 */
private static void ensureLabel(final ElkGraphElement klge) {
    if (klge.getLabels().isEmpty()) {
        if (!Strings.isNullOrEmpty(klge.getIdentifier())) {
            ElkLabel label = ElkGraphUtil.createLabel(klge);
            label.setText(klge.getIdentifier());
        }
    }
}
Also used : ElkLabel(org.eclipse.elk.graph.ElkLabel)

Example 18 with ElkLabel

use of org.eclipse.elk.graph.ElkLabel in project elk by eclipse.

the class ElkUtil method applyConfiguredNodeScaling.

/**
 * Applies the scaling factor configured in terms of {@link CoreOptions#SCALE_FACTOR} to {@code node}'s
 * size data, and updates the layout data of {@code node}'s ports and labels accordingly.<br>
 * <b>Note:</b> The scaled layout data won't be reverted during the layout process, see
 * {@link CoreOptions#SCALE_FACTOR}.
 *
 * @param node
 *            the node to be scaled
 */
public static void applyConfiguredNodeScaling(final ElkNode node) {
    final double scalingFactor = node.getProperty(CoreOptions.SCALE_FACTOR);
    if (scalingFactor == 1) {
        return;
    }
    node.setDimensions(scalingFactor * node.getWidth(), scalingFactor * node.getHeight());
    final Iterable<ElkLabel> portLabels = Iterables.concat(Iterables.transform(node.getPorts(), p -> p.getLabels()));
    for (ElkShape shape : Iterables.concat(node.getLabels(), node.getPorts(), portLabels)) {
        shape.setLocation(scalingFactor * shape.getX(), scalingFactor * shape.getY());
        shape.setDimensions(scalingFactor * shape.getWidth(), scalingFactor * shape.getHeight());
        final KVector anchor = shape.getProperty(CoreOptions.PORT_ANCHOR);
        if (anchor != null) {
            anchor.x *= scalingFactor;
            anchor.y *= scalingFactor;
        }
    }
}
Also used : CoreOptions(org.eclipse.elk.core.options.CoreOptions) Iterables(com.google.common.collect.Iterables) ListIterator(java.util.ListIterator) PortSide(org.eclipse.elk.core.options.PortSide) ContentAlignment(org.eclipse.elk.core.options.ContentAlignment) ElkGraphFactory(org.eclipse.elk.graph.ElkGraphFactory) ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) PortLabelPlacement(org.eclipse.elk.core.options.PortLabelPlacement) KVectorChain(org.eclipse.elk.core.math.KVectorChain) Iterators(com.google.common.collect.Iterators) ArrayList(java.util.ArrayList) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) Strings(com.google.common.base.Strings) LabelAdapter(org.eclipse.elk.core.util.adapters.GraphAdapters.LabelAdapter) Lists(com.google.common.collect.Lists) Map(java.util.Map) GraphValidationException(org.eclipse.elk.core.validation.GraphValidationException) PortAdapter(org.eclipse.elk.core.util.adapters.GraphAdapters.PortAdapter) Iterator(java.util.Iterator) PortConstraints(org.eclipse.elk.core.options.PortConstraints) ElkLabel(org.eclipse.elk.graph.ElkLabel) KVector(org.eclipse.elk.core.math.KVector) Collection(java.util.Collection) SizeOptions(org.eclipse.elk.core.options.SizeOptions) Set(java.util.Set) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) EObject(org.eclipse.emf.ecore.EObject) ElkShape(org.eclipse.elk.graph.ElkShape) Maps(com.google.common.collect.Maps) File(java.io.File) ElkConnectableShape(org.eclipse.elk.graph.ElkConnectableShape) List(java.util.List) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) NodeLabelPlacement(org.eclipse.elk.core.options.NodeLabelPlacement) ElkBendPoint(org.eclipse.elk.graph.ElkBendPoint) Direction(org.eclipse.elk.core.options.Direction) IValidatingGraphElementVisitor(org.eclipse.elk.core.validation.IValidatingGraphElementVisitor) ElkEdgeSection(org.eclipse.elk.graph.ElkEdgeSection) EdgeLabelPlacement(org.eclipse.elk.core.options.EdgeLabelPlacement) GraphIssue(org.eclipse.elk.core.validation.GraphIssue) ElkEdge(org.eclipse.elk.graph.ElkEdge) Pattern(java.util.regex.Pattern) ElkGraphUtil(org.eclipse.elk.graph.util.ElkGraphUtil) ElkLabel(org.eclipse.elk.graph.ElkLabel) ElkShape(org.eclipse.elk.graph.ElkShape) KVector(org.eclipse.elk.core.math.KVector)

Example 19 with ElkLabel

use of org.eclipse.elk.graph.ElkLabel in project elk by eclipse.

the class ElkUtil method resizeNode.

/**
 * Resize a node to the given width and height, adjusting port and label positions if needed.
 *
 * @param node a node
 * @param newWidth the new width to set
 * @param newHeight the new height to set
 * @param movePorts whether port positions should be adjusted
 * @param moveLabels whether label positions should be adjusted
 * @return a vector holding the width and height resizing ratio
 */
public static KVector resizeNode(final ElkNode node, final double newWidth, final double newHeight, final boolean movePorts, final boolean moveLabels) {
    KVector oldSize = new KVector(node.getWidth(), node.getHeight());
    KVector newSize = effectiveMinSizeConstraintFor(node);
    newSize.x = Math.max(newSize.x, newWidth);
    newSize.y = Math.max(newSize.y, newHeight);
    double widthRatio = newSize.x / oldSize.x;
    double heightRatio = newSize.y / oldSize.y;
    double widthDiff = newSize.x - oldSize.x;
    double heightDiff = newSize.y - oldSize.y;
    // update port positions
    if (movePorts) {
        Direction direction = node.getParent() == null ? node.getProperty(CoreOptions.DIRECTION) : node.getParent().getProperty(CoreOptions.DIRECTION);
        boolean fixedPorts = node.getProperty(CoreOptions.PORT_CONSTRAINTS) == PortConstraints.FIXED_POS;
        for (ElkPort port : node.getPorts()) {
            PortSide portSide = port.getProperty(CoreOptions.PORT_SIDE);
            if (portSide == PortSide.UNDEFINED) {
                portSide = calcPortSide(port, direction);
                port.setProperty(CoreOptions.PORT_SIDE, portSide);
            }
            switch(portSide) {
                case NORTH:
                    if (!fixedPorts) {
                        port.setX(port.getX() * widthRatio);
                    }
                    break;
                case EAST:
                    port.setX(port.getX() + widthDiff);
                    if (!fixedPorts) {
                        port.setY(port.getY() * heightRatio);
                    }
                    break;
                case SOUTH:
                    if (!fixedPorts) {
                        port.setX(port.getX() * widthRatio);
                    }
                    port.setY(port.getY() + heightDiff);
                    break;
                case WEST:
                    if (!fixedPorts) {
                        port.setY(port.getY() * heightRatio);
                    }
                    break;
            }
        }
    }
    // resize the node AFTER ports have been placed, since calcPortSide needs the old size
    node.setDimensions(newSize.x, newSize.y);
    // update label positions
    if (moveLabels) {
        for (ElkLabel label : node.getLabels()) {
            double midx = label.getX() + label.getWidth() / 2;
            double midy = label.getY() + label.getHeight() / 2;
            double widthPercent = midx / oldSize.x;
            double heightPercent = midy / oldSize.y;
            if (widthPercent + heightPercent >= 1) {
                if (widthPercent - heightPercent > 0 && midy >= 0) {
                    // label is on the right
                    label.setX(label.getX() + widthDiff);
                    label.setY(label.getY() + heightDiff * heightPercent);
                } else if (widthPercent - heightPercent < 0 && midx >= 0) {
                    // label is on the bottom
                    label.setX(label.getX() + widthDiff * widthPercent);
                    label.setY(label.getY() + heightDiff);
                }
            }
        }
    }
    // set fixed size option for the node: now the size is assumed to stay as determined here
    node.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, SizeConstraint.fixed());
    return new KVector(widthRatio, heightRatio);
}
Also used : ElkLabel(org.eclipse.elk.graph.ElkLabel) ElkPort(org.eclipse.elk.graph.ElkPort) KVector(org.eclipse.elk.core.math.KVector) PortSide(org.eclipse.elk.core.options.PortSide) Direction(org.eclipse.elk.core.options.Direction)

Example 20 with ElkLabel

use of org.eclipse.elk.graph.ElkLabel in project elk by eclipse.

the class ElkUtil method printElementPath.

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEBUGGING
/**
 * Print information on the given graph element to the given string builder.
 */
public static void printElementPath(final ElkGraphElement element, final StringBuilder builder) {
    // Print the containing element
    if (element.eContainer() instanceof ElkGraphElement) {
        printElementPath((ElkGraphElement) element.eContainer(), builder);
        builder.append(" > ");
    } else {
        builder.append("Root ");
    }
    // Print the class name
    String className = element.eClass().getName();
    if (className.startsWith("Elk")) {
        // CHECKSTYLEOFF MagicNumber
        builder.append(className.substring(3));
    // CHECKSTYLEON MagicNumber
    } else {
        builder.append(className);
    }
    // Print the identifier if present
    String identifier = element.getIdentifier();
    if (!Strings.isNullOrEmpty(identifier)) {
        builder.append(' ').append(identifier);
        return;
    }
    // Print the label if present
    if (element instanceof ElkLabel) {
        String text = ((ElkLabel) element).getText();
        if (!Strings.isNullOrEmpty(text)) {
            builder.append(' ').append(text);
            return;
        }
    }
    for (ElkLabel label : element.getLabels()) {
        String text = label.getText();
        if (!Strings.isNullOrEmpty(text)) {
            builder.append(' ').append(text);
            return;
        }
    }
    // If it's an edge and no identifier nor label is present, print source and target
    if (element instanceof ElkEdge) {
        ElkEdge edge = (ElkEdge) element;
        if (edge.isConnected()) {
            builder.append(" (");
            ListIterator<ElkConnectableShape> sourceIter = edge.getSources().listIterator();
            while (sourceIter.hasNext()) {
                if (sourceIter.nextIndex() > 0) {
                    builder.append(", ");
                }
                printElementPath(sourceIter.next(), builder);
            }
            builder.append(" -> ");
            ListIterator<ElkConnectableShape> targetIter = edge.getTargets().listIterator();
            while (targetIter.hasNext()) {
                if (targetIter.nextIndex() > 0) {
                    builder.append(", ");
                }
                printElementPath(targetIter.next(), builder);
            }
            builder.append(")");
        }
    }
}
Also used : ElkLabel(org.eclipse.elk.graph.ElkLabel) ElkConnectableShape(org.eclipse.elk.graph.ElkConnectableShape) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Aggregations

ElkLabel (org.eclipse.elk.graph.ElkLabel)64 ElkNode (org.eclipse.elk.graph.ElkNode)33 KVector (org.eclipse.elk.core.math.KVector)25 ElkPort (org.eclipse.elk.graph.ElkPort)23 ElkEdge (org.eclipse.elk.graph.ElkEdge)20 ElkEdgeSection (org.eclipse.elk.graph.ElkEdgeSection)14 KVectorChain (org.eclipse.elk.core.math.KVectorChain)12 ElkPadding (org.eclipse.elk.core.math.ElkPadding)10 ElkGraphElement (org.eclipse.elk.graph.ElkGraphElement)9 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)7 PortSide (org.eclipse.elk.core.options.PortSide)6 List (java.util.List)5 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)5 LPort (org.eclipse.elk.alg.layered.graph.LPort)5 ElkBendPoint (org.eclipse.elk.graph.ElkBendPoint)5 ElkConnectableShape (org.eclipse.elk.graph.ElkConnectableShape)5 Test (org.junit.Test)5 Lists (com.google.common.collect.Lists)4 Rectangle (org.eclipse.draw2d.geometry.Rectangle)4 DCElement (org.eclipse.elk.alg.disco.graph.DCElement)4