use of org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell in project elk by eclipse.
the class PortPlacementCalculator method placeVerticalFreePorts.
/**
* Places ports on the eastern and western side for the unconstrained cases.
*/
private static void placeVerticalFreePorts(final NodeContext nodeContext, final PortSide portSide) {
// If there are no ports on the given side, abort
if (nodeContext.portContexts.get(portSide).isEmpty()) {
return;
}
// Retrieve the proper inside port label cell, which will give us hints as to where to place our ports
AtomicCell insidePortLabelCell = nodeContext.insidePortLabelCells.get(portSide);
ElkRectangle insidePortLabelCellRectangle = insidePortLabelCell.getCellRectangle();
ElkPadding insidePortLabelCellPadding = insidePortLabelCell.getPadding();
// Note that we don't have to distinguish any cases here because the port margins already include space
// required for labels, if such space is to be reserved. Yay!
PortAlignment portAlignment = nodeContext.getPortAlignment(portSide);
double availableSpace = insidePortLabelCellRectangle.height - insidePortLabelCellPadding.top - insidePortLabelCellPadding.bottom;
double calculatedPortPlacementHeight = insidePortLabelCell.getMinimumContentAreaSize().y;
double currentYPos = insidePortLabelCellRectangle.y + insidePortLabelCellPadding.top;
double spaceBetweenPorts = nodeContext.portPortSpacing;
double nodeWidth = nodeContext.nodeSize.x;
// to center to keep things from looking stupid
if ((portAlignment == PortAlignment.DISTRIBUTED || portAlignment == PortAlignment.JUSTIFIED) && nodeContext.portContexts.get(portSide).size() == 1) {
calculatedPortPlacementHeight = modifiedPortPlacementSize(nodeContext, portAlignment, calculatedPortPlacementHeight);
portAlignment = PortAlignment.CENTER;
}
if (availableSpace < calculatedPortPlacementHeight && !nodeContext.sizeOptions.contains(SizeOptions.PORTS_OVERHANG)) {
// the space between them to cram them into the available space.
if (portAlignment == PortAlignment.DISTRIBUTED) {
spaceBetweenPorts += (availableSpace - calculatedPortPlacementHeight) / (nodeContext.portContexts.get(portSide).size() + 1);
currentYPos += spaceBetweenPorts;
} else {
spaceBetweenPorts += (availableSpace - calculatedPortPlacementHeight) / (nodeContext.portContexts.get(portSide).size() - 1);
}
} else {
// case where we should fall back to centered alignment
if (availableSpace < calculatedPortPlacementHeight) {
calculatedPortPlacementHeight = modifiedPortPlacementSize(nodeContext, portAlignment, calculatedPortPlacementHeight);
portAlignment = PortAlignment.CENTER;
}
// otherwise expect)
switch(portAlignment) {
case BEGIN:
// There's nothing to do here
break;
case CENTER:
currentYPos += (availableSpace - calculatedPortPlacementHeight) / 2;
break;
case END:
currentYPos += availableSpace - calculatedPortPlacementHeight;
break;
case DISTRIBUTED:
// In this case, if there is not enough space available to place the ports, we are allowed to overhang.
// We thus need to ensure that we're only ever increasing the port spacing here
double additionalSpaceBetweenPorts = (availableSpace - calculatedPortPlacementHeight) / (nodeContext.portContexts.get(portSide).size() + 1);
spaceBetweenPorts += Math.max(0, additionalSpaceBetweenPorts);
currentYPos += spaceBetweenPorts;
break;
case JUSTIFIED:
// In this case, if there is not enough space available to place the ports, we are allowed to overhang.
// We thus need to ensure that we're only ever increasing the port spacing here
additionalSpaceBetweenPorts = (availableSpace - calculatedPortPlacementHeight) / (nodeContext.portContexts.get(portSide).size() - 1);
spaceBetweenPorts += Math.max(0, additionalSpaceBetweenPorts);
break;
}
}
// Iterate over all ports and place them
for (PortContext portContext : nodeContext.portContexts.get(portSide)) {
portContext.portPosition.x = calculateVerticalPortXCoordinate(portContext, nodeWidth);
portContext.portPosition.y = currentYPos + portContext.portMargin.top;
// Update the y coordinate for the next port
currentYPos += portContext.portMargin.top + portContext.port.getSize().y + portContext.portMargin.bottom + spaceBetweenPorts;
}
}
use of org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell in project elk by eclipse.
the class PortPlacementCalculator method placeHorizontalFreePorts.
/**
* Places ports on the northern and southern side for the unconstrained cases.
*/
private static void placeHorizontalFreePorts(final NodeContext nodeContext, final PortSide portSide) {
// If there are no ports on the given side, abort
if (nodeContext.portContexts.get(portSide).isEmpty()) {
return;
}
// Retrieve the proper inside port label cell, which will give us hints as to where to place our ports
AtomicCell insidePortLabelCell = nodeContext.insidePortLabelCells.get(portSide);
ElkRectangle insidePortLabelCellRectangle = insidePortLabelCell.getCellRectangle();
ElkPadding insidePortLabelCellPadding = insidePortLabelCell.getPadding();
// Note that we don't have to distinguish any cases here because the port margins already include space
// required for labels, if such space is to be reserved. Yay!
PortAlignment portAlignment = nodeContext.getPortAlignment(portSide);
double availableSpace = insidePortLabelCellRectangle.width - insidePortLabelCellPadding.left - insidePortLabelCellPadding.right;
double calculatedPortPlacementWidth = insidePortLabelCell.getMinimumContentAreaSize().x;
double currentXPos = insidePortLabelCellRectangle.x + insidePortLabelCellPadding.left;
double spaceBetweenPorts = nodeContext.portPortSpacing;
// to center to keep things from looking stupid
if ((portAlignment == PortAlignment.DISTRIBUTED || portAlignment == PortAlignment.JUSTIFIED) && nodeContext.portContexts.get(portSide).size() == 1) {
calculatedPortPlacementWidth = modifiedPortPlacementSize(nodeContext, portAlignment, calculatedPortPlacementWidth);
portAlignment = PortAlignment.CENTER;
}
if (availableSpace < calculatedPortPlacementWidth && !nodeContext.sizeOptions.contains(SizeOptions.PORTS_OVERHANG)) {
// the space between them to cram them into the available space.
if (portAlignment == PortAlignment.DISTRIBUTED) {
spaceBetweenPorts += (availableSpace - calculatedPortPlacementWidth) / (nodeContext.portContexts.get(portSide).size() + 1);
currentXPos += spaceBetweenPorts;
} else {
spaceBetweenPorts += (availableSpace - calculatedPortPlacementWidth) / (nodeContext.portContexts.get(portSide).size() - 1);
}
} else {
// case where we should fall back to centered alignment
if (availableSpace < calculatedPortPlacementWidth) {
calculatedPortPlacementWidth = modifiedPortPlacementSize(nodeContext, portAlignment, calculatedPortPlacementWidth);
portAlignment = PortAlignment.CENTER;
}
// otherwise expect)
switch(portAlignment) {
case BEGIN:
// There's nothing to do here
break;
case CENTER:
currentXPos += (availableSpace - calculatedPortPlacementWidth) / 2;
break;
case END:
currentXPos += availableSpace - calculatedPortPlacementWidth;
break;
case DISTRIBUTED:
// In this case, if there is not enough space available to place the ports, we are allowed to overhang.
// We thus need to ensure that we're only ever increasing the port spacing here
double additionalSpaceBetweenPorts = (availableSpace - calculatedPortPlacementWidth) / (nodeContext.portContexts.get(portSide).size() + 1);
spaceBetweenPorts += Math.max(0, additionalSpaceBetweenPorts);
currentXPos += spaceBetweenPorts;
break;
case JUSTIFIED:
// In this case, if there is not enough space available to place the ports, we are allowed to overhang.
// We thus need to ensure that we're only ever increasing the port spacing here
additionalSpaceBetweenPorts = (availableSpace - calculatedPortPlacementWidth) / (nodeContext.portContexts.get(portSide).size() - 1);
spaceBetweenPorts += Math.max(0, additionalSpaceBetweenPorts);
break;
}
}
// Iterate over all ports and place them
for (PortContext portContext : nodeContext.portContexts.get(portSide)) {
portContext.portPosition.x = currentXPos + portContext.portMargin.left;
portContext.portPosition.y = calculateHorizontalPortYCoordinate(portContext);
// Update the x coordinate for the next port
currentXPos += portContext.portMargin.left + portContext.port.getSize().x + portContext.portMargin.right + spaceBetweenPorts;
}
}
use of org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell in project elk by eclipse.
the class VerticalPortPlacementSizeCalculator method calculateVerticalNodeSizeRequiredByFreePorts.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Free
/**
* Sets up inside port label spaces for free ports.
*/
private static void calculateVerticalNodeSizeRequiredByFreePorts(final NodeContext nodeContext, final PortSide portSide) {
AtomicCell cell = nodeContext.insidePortLabelCells.get(portSide);
// Handle the common case first: if there are no ports, set everything to zero
if (nodeContext.portContexts.get(portSide).isEmpty()) {
cell.getPadding().top = 0;
cell.getPadding().bottom = 0;
return;
}
// Set the padding to match the surrounding port space
cell.getPadding().top = nodeContext.surroundingPortMargins.top;
cell.getPadding().bottom = nodeContext.surroundingPortMargins.bottom;
// required for their labels
if (nodeContext.sizeConstraints.contains(SizeConstraint.PORT_LABELS)) {
setupPortMargins(nodeContext, portSide);
}
double height = portHeightPlusPortPortSpacing(nodeContext, portSide);
// For distributed port alignment, we need to surround the ports by a port-port spacing on each side
if (nodeContext.getPortAlignment(portSide) == PortAlignment.DISTRIBUTED) {
height += 2 * nodeContext.portPortSpacing;
}
// Set the cell size
cell.getMinimumContentAreaSize().y = height;
}
use of org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell in project elk by eclipse.
the class VerticalPortPlacementSizeCalculator method calculateVerticalNodeSizeRequiredByFixedPosPorts.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fixed Position
/**
* Sets up inside port label spaces for fixed position ports. If the node size constraints include ports, we also
* mess with the cell padding.
*/
private static void calculateVerticalNodeSizeRequiredByFixedPosPorts(final NodeContext nodeContext, final PortSide portSide) {
double bottommostPortBorder = 0.0;
// Check all ports on the correct side
for (PortContext portContext : nodeContext.portContexts.get(portSide)) {
bottommostPortBorder = Math.max(bottommostPortBorder, portContext.portPosition.y + portContext.port.getSize().y);
}
// Set the cell size and remove top padding since the cell size itself already includes all the space we need
AtomicCell cell = nodeContext.insidePortLabelCells.get(portSide);
cell.getPadding().top = 0;
cell.getMinimumContentAreaSize().y = bottommostPortBorder;
}
use of org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell in project elk by eclipse.
the class VerticalPortPlacementSizeCalculator method calculateVerticalNodeSizeRequiredByFixedRatioPorts.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fixed Ratio
/**
* Sets up inside port label spaces for fixed ratio ports. If the node size constraints include ports, we also
* mess with the cell padding.
*/
private static void calculateVerticalNodeSizeRequiredByFixedRatioPorts(final NodeContext nodeContext, final PortSide portSide) {
AtomicCell cell = nodeContext.insidePortLabelCells.get(portSide);
// Fetch the port contexts on the given side and abort if there are none
Collection<PortContext> portContexts = nodeContext.portContexts.get(portSide);
if (portContexts.isEmpty()) {
cell.getPadding().top = 0;
cell.getPadding().bottom = 0;
return;
}
boolean portLabelsInside = nodeContext.portLabelsPlacement.contains(PortLabelPlacement.INSIDE);
double minHeight = 0;
// and the port labels are not placed next to the port)
if (nodeContext.sizeConstraints.contains(SizeConstraint.PORT_LABELS)) {
setupPortMargins(nodeContext, portSide);
}
// Go over all pairs of consecutive ports
Iterator<PortContext> portContextIterator = portContexts.iterator();
PortContext previousPortContext = null;
double previousPortRatio = 0;
double previousPortHeight = 0;
while (portContextIterator.hasNext()) {
// Get the next port and find out things about it
PortContext currentPortContext = portContextIterator.next();
double currentPortRatio = currentPortContext.port.getProperty(PortPlacementCalculator.PORT_RATIO_OR_POSITION);
double currentPortHeight = currentPortContext.port.getSize().y;
if (previousPortContext == null) {
// port margins, if any
if (nodeContext.surroundingPortMargins != null && nodeContext.surroundingPortMargins.top > 0) {
minHeight = Math.max(minHeight, HorizontalPortPlacementSizeCalculator.minSizeRequiredToRespectSpacing(nodeContext.surroundingPortMargins.top + currentPortContext.portMargin.top, 0, currentPortRatio));
}
} else {
double requiredSpace = previousPortHeight + previousPortContext.portMargin.bottom + nodeContext.portPortSpacing + currentPortContext.portMargin.top;
minHeight = Math.max(minHeight, HorizontalPortPlacementSizeCalculator.minSizeRequiredToRespectSpacing(requiredSpace, previousPortRatio, currentPortRatio));
}
// Our current port is going to be the previous port during the next iteration
previousPortContext = currentPortContext;
previousPortRatio = currentPortRatio;
previousPortHeight = currentPortHeight;
}
// if there are bottom surrounding port margins, apply those as well
if (nodeContext.surroundingPortMargins != null && nodeContext.surroundingPortMargins.bottom > 0) {
// We're using the port's bare width here because we don't care about label sizes on the bottommost port
double requiredSpace = previousPortHeight + nodeContext.surroundingPortMargins.bottom;
// We're only interested in the port's bottom margin if it's label is placed inside
if (portLabelsInside) {
requiredSpace += previousPortContext.portMargin.bottom;
}
minHeight = Math.max(minHeight, HorizontalPortPlacementSizeCalculator.minSizeRequiredToRespectSpacing(requiredSpace, previousPortRatio, 1));
}
// Set the cell size and remove top padding since the cell size itself already includes all the space we need
cell.getPadding().top = 0;
cell.getMinimumContentAreaSize().y = minHeight;
}
Aggregations