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));
}
}
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;
}
}
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;
}
}
Aggregations