Search in sources :

Example 11 with LabelCell

use of org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell in project elk by eclipse.

the class PortContextCreator method createPortContext.

/**
 * Creates a port context for the given adapter and initializes it properly.
 */
private static void createPortContext(final NodeContext nodeContext, final PortAdapter<?> port, final boolean imPortLabels) {
    PortContext portContext = new PortContext(nodeContext, port);
    nodeContext.portContexts.put(port.getSide(), portContext);
    // If the port has labels and if port labels are to be placed, we need to remember them
    if (imPortLabels && !PortLabelPlacement.isFixed(nodeContext.portLabelsPlacement)) {
        portContext.portLabelCell = new LabelCell(nodeContext.labelLabelSpacing);
        port.getLabels().forEach(label -> portContext.portLabelCell.addLabel(label));
    }
}
Also used : LabelCell(org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell) PortContext(org.eclipse.elk.alg.common.nodespacing.internal.PortContext)

Example 12 with LabelCell

use of org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell in project elk by eclipse.

the class PortLabelPlacementCalculator method constrainedInsidePortLabelPlacement.

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constrained Inside Port Labels
/**
 * Place the port label cells outside of the node in the knowledge that there might not be enough space to place
 * them without overlaps.
 */
private static void constrainedInsidePortLabelPlacement(final NodeContext nodeContext, final PortSide portSide) {
    Collection<PortContext> portContexts = nodeContext.portContexts.get(portSide);
    // If it's neither the northern nor the southern side, simply revert to simple port label placement
    if (portSide == PortSide.EAST || portSide == PortSide.WEST) {
        simpleInsidePortLabelPlacement(nodeContext, portSide);
        return;
    }
    // Prepare things
    OverlapRemovalDirection overlapRemovalDirection = portSide == PortSide.NORTH ? OverlapRemovalDirection.DOWN : OverlapRemovalDirection.UP;
    VerticalLabelAlignment verticalLabelAlignment = portSide == PortSide.NORTH ? VerticalLabelAlignment.TOP : VerticalLabelAlignment.BOTTOM;
    // To keep labels from extending over the content area of the inside port label container, we need to know
    // where its content area's left and right boundaries are. We also make sure to always keep a bit of space to
    // the node border
    AtomicCell insidePortLabelContainer = nodeContext.insidePortLabelCells.get(portSide);
    ElkRectangle labelContainerRect = insidePortLabelContainer.getCellRectangle();
    double leftBorder = labelContainerRect.x + ElkMath.maxd(insidePortLabelContainer.getPadding().left, nodeContext.surroundingPortMargins.left, nodeContext.nodeLabelSpacing);
    double rightBorder = labelContainerRect.x + labelContainerRect.width - ElkMath.maxd(insidePortLabelContainer.getPadding().right, nodeContext.surroundingPortMargins.right, nodeContext.nodeLabelSpacing);
    // Obtain a rectangle strip overlap remover, which will actually do most of the work
    RectangleStripOverlapRemover overlapRemover = RectangleStripOverlapRemover.createForDirection(overlapRemovalDirection).withGap(nodeContext.portLabelSpacing);
    // Iterate over our ports and add rectangles to the overlap remover. Also, calculate the start coordinate
    double startCoordinate = portSide == PortSide.NORTH ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
    for (PortContext portContext : portContexts) {
        if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
            continue;
        }
        KVector portSize = portContext.port.getSize();
        KVector portPosition = portContext.portPosition;
        LabelCell portLabelCell = portContext.portLabelCell;
        ElkRectangle portLabelCellRect = portLabelCell.getCellRectangle();
        // Setup the less interesting cell properties
        portLabelCellRect.width = portLabelCell.getMinimumWidth();
        portLabelCellRect.height = portLabelCell.getMinimumHeight();
        portLabelCell.setVerticalAlignment(verticalLabelAlignment);
        portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
        // Center the label, but make sure it doesn't hang over the node boundaries
        centerPortLabel(portLabelCellRect, portPosition, portSize, leftBorder, rightBorder);
        // Add the rectangle to the overlap remover
        overlapRemover.addRectangle(portLabelCellRect);
        // Update start coordinate
        startCoordinate = portSide == PortSide.NORTH ? Math.max(startCoordinate, portPosition.y + portContext.port.getSize().y) : Math.min(startCoordinate, portPosition.y);
    }
    // The start coordinate needs to be offset by the port-label space
    startCoordinate += portSide == PortSide.NORTH ? nodeContext.portLabelSpacing : -nodeContext.portLabelSpacing;
    // Invoke the overlap remover
    double stripHeight = overlapRemover.withStartCoordinate(startCoordinate).removeOverlaps();
    if (stripHeight > 0) {
        nodeContext.insidePortLabelCells.get(portSide).getMinimumContentAreaSize().y = stripHeight;
    }
    // We need to update the label cell's coordinates to be relative to the ports
    for (PortContext portContext : portContexts) {
        if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
            continue;
        }
        ElkRectangle portLabelCellRect = portContext.portLabelCell.getCellRectangle();
        // Setup the label cell's cell rectangle
        portLabelCellRect.x -= portContext.portPosition.x;
        portLabelCellRect.y -= portContext.portPosition.y;
    }
}
Also used : RectangleStripOverlapRemover(org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover) LabelCell(org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell) VerticalLabelAlignment(org.eclipse.elk.alg.common.nodespacing.cellsystem.VerticalLabelAlignment) OverlapRemovalDirection(org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover.OverlapRemovalDirection) AtomicCell(org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) KVector(org.eclipse.elk.core.math.KVector) PortContext(org.eclipse.elk.alg.common.nodespacing.internal.PortContext)

Example 13 with LabelCell

use of org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell in project elk by eclipse.

the class PortLabelPlacementCalculator method simpleInsidePortLabelPlacement.

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Simple Inside Port Labels
/**
 * Place the port label cells on the node's insides.
 */
private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext, final PortSide portSide) {
    // For northern and southern port labels, we need to set the inside port label cell's client height later
    double insideNorthOrSouthPortLabelAreaHeight = 0;
    // Some spacings we may need later
    double labelBorderOffset = portLabelBorderOffsetForPortSide(nodeContext, portSide);
    double portLabelSpacing = nodeContext.portLabelSpacing;
    for (PortContext portContext : nodeContext.portContexts.get(portSide)) {
        // If the port doesn't have labels, skip
        if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
            continue;
        }
        // Retrieve information about the port itself
        KVector portSize = portContext.port.getSize();
        double portBorderOffset = portContext.port.hasProperty(CoreOptions.PORT_BORDER_OFFSET) ? portContext.port.getProperty(CoreOptions.PORT_BORDER_OFFSET) : 0;
        // Retrieve the label cell and its rectangle and set the rectangle's size (we will use the rectangle to
        // place the cell relative to the port below)
        LabelCell portLabelCell = portContext.portLabelCell;
        ElkRectangle portLabelCellRect = portLabelCell.getCellRectangle();
        portLabelCellRect.width = portLabelCell.getMinimumWidth();
        portLabelCellRect.height = portLabelCell.getMinimumHeight();
        // place port labels such that edges won't cross them
        switch(portSide) {
            case NORTH:
                portLabelCellRect.x = portContext.labelsNextToPort ? (portSize.x - portLabelCellRect.width) / 2 : portSize.x + portLabelSpacing;
                portLabelCellRect.y = portSize.y + portBorderOffset + labelBorderOffset;
                portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.CENTER);
                portLabelCell.setVerticalAlignment(VerticalLabelAlignment.TOP);
                break;
            case SOUTH:
                portLabelCellRect.x = portContext.labelsNextToPort ? (portSize.x - portLabelCellRect.width) / 2 : portSize.x + portLabelSpacing;
                portLabelCellRect.y = -portBorderOffset - labelBorderOffset - portLabelCellRect.height;
                portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.CENTER);
                portLabelCell.setVerticalAlignment(VerticalLabelAlignment.BOTTOM);
                break;
            case EAST:
                portLabelCellRect.x = -portBorderOffset - labelBorderOffset - portLabelCellRect.width;
                if (portContext.labelsNextToPort) {
                    double labelHeight = nodeContext.portLabelsTreatAsGroup ? portLabelCellRect.height : portLabelCell.getLabels().get(0).getSize().y;
                    portLabelCellRect.y = (portSize.y - labelHeight) / 2;
                } else {
                    portLabelCellRect.y = portSize.y + portLabelSpacing;
                }
                portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
                portLabelCell.setVerticalAlignment(VerticalLabelAlignment.CENTER);
                break;
            case WEST:
                portLabelCellRect.x = portSize.x + portBorderOffset + labelBorderOffset;
                if (portContext.labelsNextToPort) {
                    double labelHeight = nodeContext.portLabelsTreatAsGroup ? portLabelCellRect.height : portLabelCell.getLabels().get(0).getSize().y;
                    portLabelCellRect.y = (portSize.y - labelHeight) / 2;
                } else {
                    portLabelCellRect.y = portSize.y + portLabelSpacing;
                }
                portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.LEFT);
                portLabelCell.setVerticalAlignment(VerticalLabelAlignment.CENTER);
                break;
        }
        // If we have a north or south port, update our port label area height
        if (portSide == PortSide.NORTH || portSide == PortSide.SOUTH) {
            insideNorthOrSouthPortLabelAreaHeight = Math.max(insideNorthOrSouthPortLabelAreaHeight, portLabelCellRect.height);
        }
    }
    // If we have a northern or southern label area height, apply it
    if (insideNorthOrSouthPortLabelAreaHeight > 0) {
        nodeContext.insidePortLabelCells.get(portSide).getMinimumContentAreaSize().y = insideNorthOrSouthPortLabelAreaHeight;
    }
}
Also used : LabelCell(org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell) KVector(org.eclipse.elk.core.math.KVector) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) PortContext(org.eclipse.elk.alg.common.nodespacing.internal.PortContext)

Aggregations

LabelCell (org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell)13 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)7 KVector (org.eclipse.elk.core.math.KVector)6 PortContext (org.eclipse.elk.alg.common.nodespacing.internal.PortContext)5 LPort (org.eclipse.elk.alg.layered.graph.LPort)3 VerticalLabelAlignment (org.eclipse.elk.alg.common.nodespacing.cellsystem.VerticalLabelAlignment)2 RectangleStripOverlapRemover (org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover)2 OverlapRemovalDirection (org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover.OverlapRemovalDirection)2 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)2 Lists (com.google.common.collect.Lists)1 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Collectors (java.util.stream.Collectors)1 AtomicCell (org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell)1 StripContainerCell (org.eclipse.elk.alg.common.nodespacing.cellsystem.StripContainerCell)1 NodeLabelLocation (org.eclipse.elk.alg.common.nodespacing.internal.NodeLabelLocation)1 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)1 LMargin (org.eclipse.elk.alg.layered.graph.LMargin)1 LNode (org.eclipse.elk.alg.layered.graph.LNode)1