diff --git a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/Layered.melk b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/Layered.melk index f81942c8bb..0d32a253b0 100644 --- a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/Layered.melk +++ b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/Layered.melk @@ -190,6 +190,7 @@ algorithm layered(LayeredLayoutProvider) { supports considerModelOrder.crossingCounterNodeInfluence supports considerModelOrder.crossingCounterPortInfluence supports considerModelOrder.noModelOrder + supports considerModelOrder.components supports generatePositionAndLayerIds } @@ -947,6 +948,14 @@ group considerModelOrder { default = false targets nodes } + option components: boolean { + label "Consider Model Order for Components" + description + "If enabled orders components by their minimal node model order." + targets parents + default = false + requires org.eclipse.elk.separateConnectedComponents + } option longEdgeStrategy: LongEdgeOrderingStrategy { label "Long Edge Ordering Strategy" description diff --git a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/components/ComponentsProcessor.java b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/components/ComponentsProcessor.java index 223a99a6d2..2524fe3817 100644 --- a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/components/ComponentsProcessor.java +++ b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/components/ComponentsProcessor.java @@ -16,13 +16,13 @@ import java.util.Set; import org.eclipse.elk.alg.layered.graph.LGraph; +import org.eclipse.elk.alg.layered.graph.LGraphUtil; import org.eclipse.elk.alg.layered.graph.LNode; import org.eclipse.elk.alg.layered.graph.LNode.NodeType; import org.eclipse.elk.alg.layered.graph.LPort; import org.eclipse.elk.alg.layered.options.GraphProperties; import org.eclipse.elk.alg.layered.options.InternalProperties; import org.eclipse.elk.alg.layered.options.LayeredOptions; -import org.eclipse.elk.alg.layered.options.OrderingStrategy; import org.eclipse.elk.core.options.PortConstraints; import org.eclipse.elk.core.options.PortSide; import org.eclipse.elk.core.util.Pair; @@ -142,21 +142,10 @@ public List split(final LGraph graph) { } // If model order should be preserved the connected components should be ordered by their elements. // The component with the node with the smallest order should be first. - if (graph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE - || graph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER)) { + if (graph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_COMPONENTS)) { Collections.sort(result, (g1, g2) -> { - int g1Order = Integer.MAX_VALUE; - for (LNode node : g1.getLayerlessNodes()) { - if (node.hasProperty(InternalProperties.MODEL_ORDER)) { - g1Order = Math.min(g1Order, node.getProperty(InternalProperties.MODEL_ORDER)); - } - } - int g2Order = Integer.MAX_VALUE; - for (LNode node : g2.getLayerlessNodes()) { - if (node.hasProperty(InternalProperties.MODEL_ORDER)) { - g2Order = Math.min(g2Order, node.getProperty(InternalProperties.MODEL_ORDER)); - } - } + int g1Order = LGraphUtil.getMinimalModelOrder(g1); + int g2Order = LGraphUtil.getMinimalModelOrder(g2); return Integer.compare(g1Order, g2Order); }); } diff --git a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/LGraphUtil.java b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/LGraphUtil.java index 7199adbd98..6c120d8147 100644 --- a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/LGraphUtil.java +++ b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/LGraphUtil.java @@ -1139,5 +1139,20 @@ public static Direction getDirection(final LGraph graph) { } return direction; } + + /** + * Determines the minimal node order of an unlayered graph. + * + * @return model order or Integer.MAX_VALUE if no node with a model order could be found. + */ + public static int getMinimalModelOrder(final LGraph graph) { + int order = Integer.MAX_VALUE; + for (LNode node : graph.getLayerlessNodes()) { + if (node.hasProperty(InternalProperties.MODEL_ORDER)) { + order = Math.min(order, node.getProperty(InternalProperties.MODEL_ORDER)); + } + } + return order; + } } diff --git a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/transform/ElkGraphImporter.java b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/transform/ElkGraphImporter.java index 8ee8378030..c5f9e27f0d 100644 --- a/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/transform/ElkGraphImporter.java +++ b/plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/graph/transform/ElkGraphImporter.java @@ -228,7 +228,8 @@ private void importFlatGraph(final ElkNode elkgraph, final LGraph lgraph) { if ((elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE || elkgraph.getProperty(LayeredOptions.CYCLE_BREAKING_STRATEGY) == CycleBreakingStrategy.MODEL_ORDER - || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER)) + || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER) + || elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_COMPONENTS)) && !child.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_NO_MODEL_ORDER)) { child.setProperty(InternalProperties.MODEL_ORDER, index); index++; @@ -244,7 +245,8 @@ private void importFlatGraph(final ElkNode elkgraph, final LGraph lgraph) { if (elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE || elkgraph.getProperty(LayeredOptions.CYCLE_BREAKING_STRATEGY) == CycleBreakingStrategy.MODEL_ORDER - || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER)) { + || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER) + || elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_COMPONENTS)) { elkedge.setProperty(InternalProperties.MODEL_ORDER, index); index++; } @@ -308,7 +310,8 @@ private void importHierarchicalGraph(final ElkNode elkgraph, final LGraph lgraph if ((elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE || elkgraph.getProperty(LayeredOptions.CYCLE_BREAKING_STRATEGY) == CycleBreakingStrategy.MODEL_ORDER - || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER)) + || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER) + || elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_COMPONENTS)) && !elknode.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_NO_MODEL_ORDER)) { // Assign a model order to the nodes as they are read elknode.setProperty(InternalProperties.MODEL_ORDER, index++); @@ -379,7 +382,8 @@ private void importHierarchicalGraph(final ElkNode elkgraph, final LGraph lgraph if (elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE || elkgraph.getProperty(LayeredOptions.CYCLE_BREAKING_STRATEGY) == CycleBreakingStrategy.MODEL_ORDER - || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER)) { + || elkgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER) + || elkgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_COMPONENTS)) { // Assign a model order to the edges as they are read elkedge.setProperty(InternalProperties.MODEL_ORDER, index++); }