Skip to content

Commit

Permalink
core, layered: Added individual vertical and horizontal label port sp…
Browse files Browse the repository at this point in the history
…acing. (#788)

Signed-off-by: Soeren Domroes <sdo@informatik.uni-kiel.de>
  • Loading branch information
soerendomroes committed Mar 21, 2022
1 parent 68de8ea commit fd54e21
Show file tree
Hide file tree
Showing 20 changed files with 138 additions and 93 deletions.
Expand Up @@ -80,8 +80,10 @@ public final class NodeContext {
public final double labelCellSpacing;
/** Space between a port and another port. */
public final double portPortSpacing;
/** Space between a port and its labels. */
public final double portLabelSpacing;
/** Horizontal space between a port and its labels. */
public final double portLabelSpacingHorizontal;
/** Vertical space between a port and its labels. */
public final double portLabelSpacingVertical;
/** Margin to leave around the set of ports on each side. */
public final ElkMargin surroundingPortMargins;

Expand Down Expand Up @@ -152,7 +154,10 @@ public NodeContext(final GraphAdapter<?> parentGraph, final NodeAdapter<?> node)
nodeLabelSpacing = IndividualSpacings.getIndividualOrInherited(node, CoreOptions.SPACING_LABEL_NODE);
labelLabelSpacing = IndividualSpacings.getIndividualOrInherited(node, CoreOptions.SPACING_LABEL_LABEL);
portPortSpacing = IndividualSpacings.getIndividualOrInherited(node, CoreOptions.SPACING_PORT_PORT);
portLabelSpacing = IndividualSpacings.getIndividualOrInherited(node, CoreOptions.SPACING_LABEL_PORT);
portLabelSpacingHorizontal =
IndividualSpacings.getIndividualOrInherited(node, CoreOptions.SPACING_LABEL_PORT_HORIZONTAL);
portLabelSpacingVertical =
IndividualSpacings.getIndividualOrInherited(node, CoreOptions.SPACING_LABEL_PORT_VERTICAL);
surroundingPortMargins = IndividualSpacings.getIndividualOrInherited(
node, CoreOptions.SPACING_PORTS_SURROUNDING);

Expand Down
Expand Up @@ -336,7 +336,7 @@ private static void computeHorizontalPortMargins(final NodeContext nodeContext,
// The label is either placed outside (right to the port) or possibly inside, but for a compound
// node, which means that it is placed right of the port as well to keep it from overlapping with
// inside edges
portContext.portMargin.right = nodeContext.portLabelSpacing + labelWidth;
portContext.portMargin.right = nodeContext.portLabelSpacingHorizontal + labelWidth;
}
} else if (PortLabelPlacement.isFixed(nodeContext.portLabelsPlacement)) {
// The fixed port label is not considered with portContext.portLabelCell. Nevertheless, a port margin
Expand Down
Expand Up @@ -78,11 +78,11 @@ private static void setupNorthOrSouthPortLabelCell(final NodeContext nodeContext

switch (portSide) {
case NORTH:
padding.top = nodeContext.portLabelSpacing;
padding.top = nodeContext.portLabelSpacingVertical;
break;

case SOUTH:
padding.bottom = nodeContext.portLabelSpacing;
padding.bottom = nodeContext.portLabelSpacingVertical;
break;
}

Expand Down Expand Up @@ -127,11 +127,11 @@ private static void calculateWidthDueToLabels(final NodeContext nodeContext, fin
if (minCellSize.x > 0) {
switch (portSide) {
case EAST:
theAppropriateCell.getPadding().right = nodeContext.portLabelSpacing;
theAppropriateCell.getPadding().right = nodeContext.portLabelSpacingHorizontal;
break;

case WEST:
theAppropriateCell.getPadding().left = nodeContext.portLabelSpacing;
theAppropriateCell.getPadding().left = nodeContext.portLabelSpacingHorizontal;
break;
}
}
Expand Down
Expand Up @@ -95,7 +95,8 @@ private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext

// Some spacings we may need later
double labelBorderOffset = portLabelBorderOffsetForPortSide(nodeContext, portSide);
double portLabelSpacing = nodeContext.portLabelSpacing;
double portLabelSpacingHorizontal = nodeContext.portLabelSpacingHorizontal;
double portLabelSpacingVertical = nodeContext.portLabelSpacingVertical;

for (PortContext portContext : nodeContext.portContexts.get(portSide)) {
// If the port doesn't have labels, skip
Expand All @@ -122,7 +123,7 @@ private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext
case NORTH:
portLabelCellRect.x = portContext.labelsNextToPort
? (portSize.x - portLabelCellRect.width) / 2
: portSize.x + portLabelSpacing;
: portSize.x + portLabelSpacingHorizontal;
portLabelCellRect.y = portSize.y + portBorderOffset + labelBorderOffset;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.CENTER);
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.TOP);
Expand All @@ -131,7 +132,7 @@ private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext
case SOUTH:
portLabelCellRect.x = portContext.labelsNextToPort
? (portSize.x - portLabelCellRect.width) / 2
: portSize.x + portLabelSpacing;
: portSize.x + portLabelSpacingHorizontal;
portLabelCellRect.y = -portBorderOffset - labelBorderOffset - portLabelCellRect.height;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.CENTER);
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.BOTTOM);
Expand All @@ -145,7 +146,7 @@ private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext
: portLabelCell.getLabels().get(0).getSize().y;
portLabelCellRect.y = (portSize.y - labelHeight) / 2;
} else {
portLabelCellRect.y = portSize.y + portLabelSpacing;
portLabelCellRect.y = portSize.y + portLabelSpacingVertical;
}
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.CENTER);
Expand All @@ -159,7 +160,7 @@ private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext
: portLabelCell.getLabels().get(0).getSize().y;
portLabelCellRect.y = (portSize.y - labelHeight) / 2;
} else {
portLabelCellRect.y = portSize.y + portLabelSpacing;
portLabelCellRect.y = portSize.y + portLabelSpacingVertical;
}
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.LEFT);
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.CENTER);
Expand Down Expand Up @@ -188,16 +189,16 @@ private static void simpleInsidePortLabelPlacement(final NodeContext nodeContext
private static double portLabelBorderOffsetForPortSide(final NodeContext nodeContext, final PortSide portSide) {
switch (portSide) {
case NORTH:
return nodeContext.nodeContainer.getPadding().top + nodeContext.portLabelSpacing;
return nodeContext.nodeContainer.getPadding().top + nodeContext.portLabelSpacingVertical;

case SOUTH:
return nodeContext.nodeContainer.getPadding().bottom + nodeContext.portLabelSpacing;
return nodeContext.nodeContainer.getPadding().bottom + nodeContext.portLabelSpacingVertical;

case EAST:
return nodeContext.nodeContainer.getPadding().right + nodeContext.portLabelSpacing;
return nodeContext.nodeContainer.getPadding().right + nodeContext.portLabelSpacingHorizontal;

case WEST:
return nodeContext.nodeContainer.getPadding().left + nodeContext.portLabelSpacing;
return nodeContext.nodeContainer.getPadding().left + nodeContext.portLabelSpacingHorizontal;

default:
assert false;
Expand Down Expand Up @@ -247,7 +248,7 @@ private static void constrainedInsidePortLabelPlacement(final NodeContext nodeCo
// Obtain a rectangle strip overlap remover, which will actually do most of the work
RectangleStripOverlapRemover overlapRemover = RectangleStripOverlapRemover
.createForDirection(overlapRemovalDirection)
.withGap(nodeContext.portLabelSpacing);
.withGap(nodeContext.portLabelSpacingHorizontal, nodeContext.portLabelSpacingVertical);

// Iterate over our ports and add rectangles to the overlap remover. Also, calculate the start coordinate
double startCoordinate = portSide == PortSide.NORTH
Expand Down Expand Up @@ -285,8 +286,8 @@ private static void constrainedInsidePortLabelPlacement(final NodeContext nodeCo

// The start coordinate needs to be offset by the port-label space
startCoordinate += portSide == PortSide.NORTH
? nodeContext.portLabelSpacing
: -nodeContext.portLabelSpacing;
? nodeContext.portLabelSpacingVertical
: -nodeContext.portLabelSpacingVertical;

// Invoke the overlap remover
double stripHeight = overlapRemover
Expand Down Expand Up @@ -372,13 +373,13 @@ private static void simpleOutsidePortLabelPlacement(final NodeContext nodeContex
portLabelCellRect.x = (portSize.x - portLabelCellRect.width) / 2;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.CENTER);
} else if (placeFirstPortDifferently) {
portLabelCellRect.x = -portLabelCellRect.width - nodeContext.portLabelSpacing;
portLabelCellRect.x = -portLabelCellRect.width - nodeContext.portLabelSpacingHorizontal;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
} else {
portLabelCellRect.x = portSize.x + nodeContext.portLabelSpacing;
portLabelCellRect.x = portSize.x + nodeContext.portLabelSpacingHorizontal;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.LEFT);
}
portLabelCellRect.y = -portLabelCellRect.height - nodeContext.portLabelSpacing;
portLabelCellRect.y = -portLabelCellRect.height - nodeContext.portLabelSpacingVertical;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.BOTTOM);
break;

Expand All @@ -387,13 +388,13 @@ private static void simpleOutsidePortLabelPlacement(final NodeContext nodeContex
portLabelCellRect.x = (portSize.x - portLabelCellRect.width) / 2;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.CENTER);
} else if (placeFirstPortDifferently) {
portLabelCellRect.x = -portLabelCellRect.width - nodeContext.portLabelSpacing;
portLabelCellRect.x = -portLabelCellRect.width - nodeContext.portLabelSpacingHorizontal;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
} else {
portLabelCellRect.x = portSize.x + nodeContext.portLabelSpacing;
portLabelCellRect.x = portSize.x + nodeContext.portLabelSpacingHorizontal;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.LEFT);
}
portLabelCellRect.y = portSize.y + nodeContext.portLabelSpacing;
portLabelCellRect.y = portSize.y + nodeContext.portLabelSpacingVertical;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.TOP);
break;

Expand All @@ -405,13 +406,13 @@ private static void simpleOutsidePortLabelPlacement(final NodeContext nodeContex
portLabelCellRect.y = (portSize.y - labelHeight) / 2;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.CENTER);
} else if (placeFirstPortDifferently) {
portLabelCellRect.y = -portLabelCellRect.height - nodeContext.portLabelSpacing;
portLabelCellRect.y = -portLabelCellRect.height - nodeContext.portLabelSpacingVertical;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.BOTTOM);
} else {
portLabelCellRect.y = portSize.y + nodeContext.portLabelSpacing;
portLabelCellRect.y = portSize.y + nodeContext.portLabelSpacingVertical;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.TOP);
}
portLabelCellRect.x = portSize.x + nodeContext.portLabelSpacing;
portLabelCellRect.x = portSize.x + nodeContext.portLabelSpacingHorizontal;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.LEFT);
break;

Expand All @@ -423,13 +424,13 @@ private static void simpleOutsidePortLabelPlacement(final NodeContext nodeContex
portLabelCellRect.y = (portSize.y - labelHeight) / 2;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.CENTER);
} else if (placeFirstPortDifferently) {
portLabelCellRect.y = -portLabelCellRect.height - nodeContext.portLabelSpacing;
portLabelCellRect.y = -portLabelCellRect.height - nodeContext.portLabelSpacingVertical;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.BOTTOM);
} else {
portLabelCellRect.y = portSize.y + nodeContext.portLabelSpacing;
portLabelCellRect.y = portSize.y + nodeContext.portLabelSpacingVertical;
portLabelCell.setVerticalAlignment(VerticalLabelAlignment.TOP);
}
portLabelCellRect.x = -portLabelCellRect.width - nodeContext.portLabelSpacing;
portLabelCellRect.x = -portLabelCellRect.width - nodeContext.portLabelSpacingHorizontal;
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
break;
}
Expand Down Expand Up @@ -472,7 +473,7 @@ private static void constrainedOutsidePortLabelPlacement(final NodeContext nodeC
// Obtain a rectangle strip overlap remover, which will actually do most of the work
RectangleStripOverlapRemover overlapRemover = RectangleStripOverlapRemover
.createForDirection(overlapRemovalDirection)
.withGap(nodeContext.portLabelSpacing);
.withGap(nodeContext.portLabelSpacingVertical, nodeContext.portLabelSpacingHorizontal);

// Iterate over our ports and add rectangles to the overlap remover. Also, calculate the start coordinate
double startCoordinate = portSide == PortSide.NORTH
Expand All @@ -493,10 +494,11 @@ private static void constrainedOutsidePortLabelPlacement(final NodeContext nodeC
portLabelCellRect.width = portLabelCell.getMinimumWidth();
portLabelCellRect.height = portLabelCell.getMinimumHeight();
if (portWithSpecialNeeds) {
portLabelCellRect.x = portPosition.x - portLabelCell.getMinimumWidth() - nodeContext.portLabelSpacing;
portLabelCellRect.x =
portPosition.x - portLabelCell.getMinimumWidth() - nodeContext.portLabelSpacingHorizontal;
portWithSpecialNeeds = false;
} else {
portLabelCellRect.x = portPosition.x + portSize.x + nodeContext.portLabelSpacing;
portLabelCellRect.x = portPosition.x + portSize.x + nodeContext.portLabelSpacingHorizontal;
}

portLabelCell.setVerticalAlignment(verticalLabelAlignment);
Expand All @@ -513,8 +515,8 @@ private static void constrainedOutsidePortLabelPlacement(final NodeContext nodeC

// The start coordinate needs to be offset by the port-label space
startCoordinate += portSide == PortSide.NORTH
? -nodeContext.portLabelSpacing
: nodeContext.portLabelSpacing;
? -nodeContext.portLabelSpacingVertical
: nodeContext.portLabelSpacingVertical;

// Invoke the overlap remover
overlapRemover
Expand Down
Expand Up @@ -319,7 +319,7 @@ private static void computeVerticalPortMargins(final NodeContext nodeContext, fi
// The label is either placed outside (below the port) or possibly inside, but for a compound node,
// which means that it is placed below the port as well to keep it from overlapping with inside
// edges
portContext.portMargin.bottom = nodeContext.portLabelSpacing + labelHeight;
portContext.portMargin.bottom = nodeContext.portLabelSpacingVertical + labelHeight;
}
} else if (PortLabelPlacement.isFixed(nodeContext.portLabelsPlacement)) {
// The fixed port label is not considered with portContext.portLabelCell. Nevertheless, a port margin
Expand Down
Expand Up @@ -24,7 +24,7 @@ public final class GreedyRectangleStripOverlapRemover implements IRectangleStrip

@Override
public double removeOverlaps(final RectangleStripOverlapRemover overlapRemover) {
final double gap = overlapRemover.getGap();
final double verticalGap = overlapRemover.getVerticalGap();
Set<RectangleNode> alreadyPlacedNodes = Sets.newHashSet();
double stripSize = 0;

Expand All @@ -43,10 +43,10 @@ public double removeOverlaps(final RectangleStripOverlapRemover overlapRemover)
ElkRectangle overlapRect = overlapNode.getRectangle();

// Check if the current y coordinate would cause an overlap with the overlap node
if (yPos < overlapRect.y + overlapRect.height + gap
&& yPos + currRect.height + gap > overlapRect.y) {
if (yPos < overlapRect.y + overlapRect.height + verticalGap
&& yPos + currRect.height + verticalGap > overlapRect.y) {

yPos = overlapRect.y + overlapRect.height + gap;
yPos = overlapRect.y + overlapRect.height + verticalGap;
}
}
}
Expand Down
Expand Up @@ -69,8 +69,10 @@ public final class RectangleStripOverlapRemover {

/** The direction in which to move rectangles to remove overlaps. */
private OverlapRemovalDirection overlapRemovalDirection;
/** Gap to be left between labels for them to not be considered overlapping. */
private double gap = DEFAULT_GAP;
/** Vertical gap to be left between labels for them to not be considered overlapping. */
private double gapVertical = DEFAULT_GAP;
/** Horizontal gap to be left between labels for them to not be considered overlapping. */
private double gapHorizontal = DEFAULT_GAP;
/** The coordinate where the first rectangles, viewed along the overlap removal direction, are placed. */
private double startCoordinate = 0;
/** The overlap strategy to use to actually remove overlaps. */
Expand Down Expand Up @@ -102,8 +104,9 @@ public static RectangleStripOverlapRemover createForDirection(final OverlapRemov
/**
* Configures the gap to be left between rectangles. Returns this instance to enable method chaining.
*/
public RectangleStripOverlapRemover withGap(final double theGap) {
gap = theGap;
public RectangleStripOverlapRemover withGap(final double theHorizontalGap, final double theVerticalGap) {
gapHorizontal = theHorizontalGap;
gapVertical = theVerticalGap;
return this;
}

Expand Down Expand Up @@ -141,10 +144,17 @@ public RectangleStripOverlapRemover addRectangle(final ElkRectangle rectangle) {
// Getters

/**
* Returns the gap to be left between rectangles.
* Returns the horizontal gap to be left between rectangles.
*/
public double getGap() {
return gap;
public double getHorizontalGap() {
return gapHorizontal;
}

/**
* Returns the horizontal gap to be left between rectangles.
*/
public double getVerticalGap() {
return gapVertical;
}

/**
Expand Down

0 comments on commit fd54e21

Please sign in to comment.