use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class LabelDummySwitcher method computeLayerWidthSums.
/**
* Computes an array in which entry i refers to the combined width of layers [0, i]. The combined width is
* estimated based on the currently estimated layer width and a wild guess as to the layer spacing.
*/
private double[] computeLayerWidthSums(final LabelDummyInfo labelDummyInfo) {
// The minimum space that we think will be left between
LGraph lgraph = labelDummyInfo.labelDummy.getGraph();
double edgeNodeSpacing = lgraph.getProperty(LayeredOptions.SPACING_EDGE_NODE_BETWEEN_LAYERS) * 2;
double nodeNodeSpacing = lgraph.getProperty(LayeredOptions.SPACING_NODE_NODE_BETWEEN_LAYERS);
double minSpaceBetweenLayers = Math.max(edgeNodeSpacing, nodeNodeSpacing);
// The array that will hold the accumulated widths
double[] layerWidthSums = new double[labelDummyInfo.totalDummyCount()];
double currentWidthSum = -minSpaceBetweenLayers;
int currentIndex = 0;
for (LNode leftDummy : labelDummyInfo.leftLongEdgeDummies) {
currentWidthSum += layerWidths[leftDummy.getLayer().id] + minSpaceBetweenLayers;
layerWidthSums[currentIndex++] = currentWidthSum;
}
currentWidthSum += layerWidths[labelDummyInfo.labelDummy.getLayer().id] + minSpaceBetweenLayers;
layerWidthSums[currentIndex++] = currentWidthSum;
for (LNode rightDummy : labelDummyInfo.rightLongEdgeDummies) {
currentWidthSum += layerWidths[rightDummy.getLayer().id] + minSpaceBetweenLayers;
layerWidthSums[currentIndex++] = currentWidthSum;
}
return layerWidthSums;
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class LabelManagementProcessor method manageNonCenterLabels.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Everything Except Center Edge Labels
/**
* Calls label management on all labels that are not edge center labels.
*/
private void manageNonCenterLabels(final LGraph lGraph, final ILabelManager labelManager, final double labelLabelSpacing) {
boolean verticalLayout = lGraph.getProperty(LayeredOptions.DIRECTION).isVertical();
// Iterate over the layers
for (Layer layer : lGraph) {
// Apply label management to node and port labels
for (LNode node : layer) {
if (node.getType() == NodeType.NORMAL) {
// Handle node labels
doManageLabels(labelManager, node.getLabels(), MIN_WIDTH_NODE_LABELS, labelLabelSpacing, verticalLayout);
// Handle ports
List<LPort> ports = node.getPorts();
for (LPort port : ports) {
doManageLabels(labelManager, port.getLabels(), MIN_WIDTH_PORT_LABELS, labelLabelSpacing, verticalLayout);
}
// Handle attached comments
if (node.hasProperty(InternalProperties.TOP_COMMENTS)) {
doManageAttachedCommentLabels(labelManager, node.getProperty(InternalProperties.TOP_COMMENTS), MIN_WIDTH_NODE_LABELS, verticalLayout);
}
if (node.hasProperty(InternalProperties.BOTTOM_COMMENTS)) {
doManageAttachedCommentLabels(labelManager, node.getProperty(InternalProperties.BOTTOM_COMMENTS), MIN_WIDTH_NODE_LABELS, verticalLayout);
}
}
// point, only head and tail labels remain)
for (LEdge edge : node.getOutgoingEdges()) {
doManageLabels(labelManager, edge.getLabels(), MIN_WIDTH_EDGE_LABELS, 0, verticalLayout);
}
}
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class LabelManagementProcessor method manageCenterLabels.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Center Edge Labels
/**
* Calls label management on all edge center labels.
*/
private void manageCenterLabels(final LGraph lGraph, final ILabelManager labelManager, final double edgeLabelSpacing, final double labelLabelSpacing) {
boolean verticalLayout = lGraph.getProperty(LayeredOptions.DIRECTION).isVertical();
// Iterate over the layers and find label dummy nodes
for (Layer layer : lGraph) {
// The maximum width is used as the target width for center edge labels
double maxWidth = Math.max(MIN_WIDTH_EDGE_LABELS, LGraphUtil.findMaxNonDummyNodeWidth(layer, false));
for (LNode node : layer) {
if (node.getType() == NodeType.LABEL) {
LEdge edge = node.getConnectedEdges().iterator().next();
double edgeThickness = edge.getProperty(LayeredOptions.EDGE_THICKNESS).doubleValue();
// The list of labels should never be empty (otherwise the label dummy wouldn't have been created
// in the first place)
Iterable<LLabel> labels = node.getProperty(InternalProperties.REPRESENTED_LABELS);
KVector spaceRequiredForLabels = doManageLabels(labelManager, labels, maxWidth, labelLabelSpacing, verticalLayout);
// Apply the space required for labels to the dummy node (we don't bother with the ports here since
// they will be meddled with later by the LabelSideSelector anyway)
node.getSize().x = spaceRequiredForLabels.x;
node.getSize().y = spaceRequiredForLabels.y + edgeThickness + edgeLabelSpacing;
}
}
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class LabelSideSelector method smart.
// //////////////////////////////////////////////////////////////////////////////////////
// Smart Placement Strategy
/**
* Chooses label sides depending on certain patterns. If in doubt, uses the given default side.
*/
private void smart(final LGraph graph, final LabelSide defaultSide) {
// We will collect consecutive runs of certain dummy nodes while we iterate through layers
Deque<LNode> dummyNodeQueue = new ArrayDeque<>();
for (Layer layer : graph) {
// The first call to any method
boolean topGroup = true;
int labelDummiesInQueue = 0;
for (LNode node : layer) {
switch(node.getType()) {
case LABEL:
labelDummiesInQueue++;
// Intended fall-through to add the label dummy to the queue
case LONG_EDGE:
dummyNodeQueue.add(node);
break;
case NORMAL:
smartForRegularNode(node, defaultSide);
default:
// Empty dummy node queue
if (!dummyNodeQueue.isEmpty()) {
smartForConsecutiveDummyNodeRun(dummyNodeQueue, labelDummiesInQueue, topGroup, false, defaultSide);
}
// Reset things
topGroup = false;
labelDummiesInQueue = 0;
}
}
// Do stuff with the nodes in the queue
if (!dummyNodeQueue.isEmpty()) {
smartForConsecutiveDummyNodeRun(dummyNodeQueue, labelDummiesInQueue, topGroup, true, defaultSide);
}
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class LayerConstraintPostprocessor method moveFirstAndLastNodes.
/**
* Moves nodes with {@link LayerConstraint#FIRST} and {@link LayerConstraint#LAST} to their respective layers and
* removes layers that have become empty.
*/
private void moveFirstAndLastNodes(final LGraph layeredGraph, final Layer firstLayer, final Layer lastLayer, final Layer firstLabelLayer, final Layer lastLabelLayer) {
// We'll start by moving FIRST and LAST nodes (as well as connected label dummies) to their proper layers
for (Layer layer : layeredGraph) {
// Iterate through a node array to avoid ConcurrentModificationExceptions
LNode[] nodes = LGraphUtil.toNodeArray(layer.getNodes());
for (LNode node : nodes) {
switch(node.getProperty(LayeredOptions.LAYERING_LAYER_CONSTRAINT)) {
case FIRST:
throwUpUnlessNoIncomingEdges(node);
node.setLayer(firstLayer);
moveLabelsToLabelLayer(node, true, firstLabelLayer);
break;
case LAST:
throwUpUnlessNoOutgoingEdges(node);
node.setLayer(lastLayer);
moveLabelsToLabelLayer(node, false, lastLabelLayer);
break;
}
}
}
// All the movement can cause layers to be empty. Instead of going to great lengths trying to prevent that in
// the code above, we simply iterate over all layers and remove the empty ones
ListIterator<Layer> layerIter = layeredGraph.getLayers().listIterator();
while (layerIter.hasNext()) {
if (layerIter.next().getNodes().isEmpty()) {
layerIter.remove();
}
}
}
Aggregations