From c0a061319d91154e3a56af68c8c5015262ab22f3 Mon Sep 17 00:00:00 2001 From: Tobias Weimar Date: Wed, 11 Dec 2024 14:07:26 +0100 Subject: [PATCH 1/4] IndentedTree Added an indented tree layout algorithm for filesystem-like representations --- org.eclipse.elk.alg.indentedtree/.project | 34 ++++ .../docs/SpacingsAnnotated.svg | 81 +++++++++ .../docs/indentedTree.md | 10 + .../eclipse/elk/alg/indentedtree/.gitignore | 1 + .../IndentedtreeLayoutProvider.java | 171 ++++++++++++++++++ .../elk/alg/indentedtree/indentedtree.melk | 47 +++++ .../options/InternalProperties.java | 33 ++++ 7 files changed, 377 insertions(+) create mode 100644 org.eclipse.elk.alg.indentedtree/.project create mode 100644 org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg create mode 100644 org.eclipse.elk.alg.indentedtree/docs/indentedTree.md create mode 100644 org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore create mode 100644 org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java create mode 100644 org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk create mode 100644 org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java diff --git a/org.eclipse.elk.alg.indentedtree/.project b/org.eclipse.elk.alg.indentedtree/.project new file mode 100644 index 000000000..c02b11d37 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/.project @@ -0,0 +1,34 @@ + + + org.eclipse.elk.alg.indentedtree + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg b/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg new file mode 100644 index 000000000..627af7d84 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg @@ -0,0 +1,81 @@ + + + + +Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Tuesday, December 10, 2024 at 3:58:10 PM Central European Standard Time + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md b/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md new file mode 100644 index 000000000..ad89ea401 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md @@ -0,0 +1,10 @@ +This algorithm takes a directed forest (a graph whose every component is a tree) and generates from it a layout reminiscient of the traditional representations of file systems. +I.e. the root of a tree is placed at the top left corner, and each node afterwards is placed in its own row, indented according to its position in the hierarchy. +If the graph has several components, the next tree is again placed on the first level, below the preceding tree. +Children of the same parent node (in the graph theory sense, not as in nodes contained by other nodes) are placed below one another, indented at least as much as the parent. +This algorithm allows the user to set three main parameters: +- horizontal Edge Indentation, which decides how far the outgoing edges of a parent (by design exiting that parent at the bottom) should be offset compared to the parent's left edge +- relative Indentation, which decides how far a should should be indented horizontally relative to the position of its incoming edge. +- vertical Node Spacing, which determines the vertical distance between a node and its immediate successor, independent of hierarchy. +The horizontal Edge Intentation of its parent and the relative Indentation add up to give the total indentation of a node. +![Interpretation of Properties](SpacingsAnnotated.svg) \ No newline at end of file diff --git a/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore b/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore new file mode 100644 index 000000000..7275ad321 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore @@ -0,0 +1 @@ +/IndentedtreeMetadataProvider.java diff --git a/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java b/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java new file mode 100644 index 000000000..a945f1072 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java @@ -0,0 +1,171 @@ +package org.eclipse.elk.alg.indentedtree; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.elk.core.AbstractLayoutProvider; +import org.eclipse.elk.core.math.ElkPadding; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkEdge; +import org.eclipse.elk.graph.ElkEdgeSection; +import org.eclipse.elk.graph.ElkNode; +import org.eclipse.elk.graph.util.ElkGraphUtil; +import org.eclipse.elk.alg.indentedtree.options.IndentedtreeOptions; +import org.eclipse.elk.alg.indentedtree.options.InternalProperties; + +/** + * A layout algorithm for creating a filesystem-like layout. + * This assumes that the graph is a tree and that no ports exist + * + * @author tobias + */ +public class IndentedtreeLayoutProvider extends AbstractLayoutProvider { + + @Override + public void layout(ElkNode layoutGraph, IElkProgressMonitor progressMonitor) { + // Start progress monitor + progressMonitor.begin("Org.eclipse.elk.alg.indentedtree", 2); + progressMonitor.log("Algorithm began"); + + // Retrieve padding + ElkPadding padding = layoutGraph.getProperty(IndentedtreeOptions.PADDING); + + // Get the list of nodes to lay out + List nodes = new ArrayList<>(layoutGraph.getChildren()); + + // Create a sub monitor for node placement + IElkProgressMonitor nodePlacingMonitor = progressMonitor.subTask(1); + nodePlacingMonitor.begin("Node Spacing", nodes.size()); + + // Positions + double currY = padding.top; + double maxX = 0.0; + + // Make an output to the debug log + nodePlacingMonitor.log("left padding: " + padding.getLeft()); + nodePlacingMonitor.log("top padding: " + padding.getTop()); + + nodePlacingMonitor.logGraph(layoutGraph, "No node placed yet"); + + // find sources + List sources = new LinkedList<>(); + for (ElkNode node : nodes) { + if (node.getIncomingEdges().isEmpty()) { + sources.add(node); + } + } + + // declare outside of loop for later use when setting graph bounds + double currentVerticalSpacing = 0.0; + + // iterate through every tree in the forest + for (ElkNode source : sources) { + List orderedNodes = new LinkedList<>(); + // find ordered list of nodes + dfs(source, orderedNodes, 0.0); + // iterate through a single tree in order, as determined by depth-first-search + for (ElkNode n : orderedNodes) { + double currentDepth = padding.getLeft() + n.getProperty(InternalProperties.DEPTH); + n.setX(currentDepth); + n.setY(currY); // currY increases monotonically + + // update maxX in order to know the real bounds of the graph + maxX = Math.max(maxX, currentDepth + n.getWidth()); + + currentVerticalSpacing = n.getProperty(IndentedtreeOptions.VERTICAL_NODE_SPACING); + // increase y counter by the node's height plus its vertical node spacing + currY += n.getHeight() + currentVerticalSpacing; + + nodePlacingMonitor.log("currX: " + n.getProperty(InternalProperties.DEPTH)); + nodePlacingMonitor.logGraph(layoutGraph, n.getIdentifier() + " placed"); + } + + } + + // Close the sub monitor + nodePlacingMonitor.done(); + progressMonitor.log("Node Placing done!"); + + // Create sub monitor for edge routing + IElkProgressMonitor edgeRoutingMonitor = progressMonitor.subTask(1); + edgeRoutingMonitor.begin("Edge Routing", layoutGraph.getContainedEdges().size()); + edgeRoutingMonitor.logGraph(layoutGraph, "No edge routed yet"); + + // Route the edges + if (!layoutGraph.getContainedEdges().isEmpty()) { + + // iterate through all edges in the graph + for (ElkEdge edge : layoutGraph.getContainedEdges()) { + // obtain source and target + ElkNode source = ElkGraphUtil.connectableShapeToNode(edge.getSources().get(0)); + ElkNode target = ElkGraphUtil.connectableShapeToNode(edge.getTargets().get(0)); + + // create one section for the new edge + ElkEdgeSection section = ElkGraphUtil.firstEdgeSection(edge, true, true); + + // set starting location for new edge + // Math.min(...) ensures that the starting location is not further to the right than + // the right border of the source node. + // Omitting Math.min(...) and leaving only the horizontalEdgeIndentation will cause + // diagonal edges if source node is narrower than horizontalEdgeIndentation. + section.setStartLocation( + source.getX() + Math.min(source.getWidth(), + source.getProperty( + IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION)), + source.getY() + source.getHeight()); + // end location: middle of left border of target + section.setEndLocation(target.getX(), target.getY() + target.getHeight() / 2); + + // create a bend point at "longitude" of start point and "latitude" of end point + ElkGraphUtil.createBendPoint(section, section.getStartX(), section.getEndY()); + + edgeRoutingMonitor.log("bendPoint created at y=" + currY); + edgeRoutingMonitor.logGraph(layoutGraph, + source.getIdentifier() + " -> " + target.getIdentifier()); + } + + } + + // Close the sub monitor + edgeRoutingMonitor.done(); + + progressMonitor.log("Edge Routing done!"); + + // Set the size of the final diagram + layoutGraph.setWidth(maxX + padding.right); // TODO should left/top padding be respected + // here? + layoutGraph.setHeight(currY + padding.bottom - currentVerticalSpacing); + + // End the progress monitor + progressMonitor.log("Algorithm executed"); + progressMonitor.logGraph(layoutGraph, "Final graph"); + progressMonitor.done(); + } + + /** + * Depth-first-search through a tree + * + * @param origin + * the root node of the current subtree + * @param list + * the list of all nodes already visited + * @param depth + * the accumulated horizontal indentation of the origin + * @return a list of all nodes in the (sub-)tree beginning with origin + */ + private List dfs(ElkNode origin, List list, Double depth) { + // add received depth to relativeIndentation and save to property + depth = depth + origin.getProperty(IndentedtreeOptions.RELATIVE_INDENTATION); + origin.setProperty(InternalProperties.DEPTH, depth); + + list.add(origin); + // iterate through origin's "children" + for (ElkEdge out : origin.getOutgoingEdges()) { + // recursion + dfs(ElkGraphUtil.connectableShapeToNode(out.getTargets().get(0)), list, + depth + origin.getProperty(IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION)); + } + return list; + } +} diff --git a/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk b/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk new file mode 100644 index 000000000..fea709153 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk @@ -0,0 +1,47 @@ +package org.eclipse.elk.alg.indentedtree + +import org.eclipse.elk.alg.indentedtree.IndentedtreeLayoutProvider +import org.eclipse.elk.core.math.ElkPadding + +bundle { + metadataClass IndentedtreeMetadataProvider + idPrefix org.eclipse.elk.alg.indentedtree +} + + + +algorithm indentedtree(IndentedtreeLayoutProvider) { + label "indentedtree" + description "Create a filesystem-like layout for trees. Assume that the graph is a tree and that no ports exist." + metadataClass options.IndentedtreeOptions + supports org.eclipse.elk.padding = new ElkPadding(10) + + supports verticalNodeSpacing + supports relativeIndentation + supports horizontalEdgeIndentation +} + + +option relativeIndentation: double { + label "relativeIndentation" + description "indentation relative to the vertical edge to the left of this node" + default = 5.0 + lowerBound = 0.0 + targets nodes +} + +option horizontalEdgeIndentation: double { + label "horizontalEdgeIndentation" + description "horizontal indentation of the edge leading from a node to its children" + default = 5.0 + lowerBound = 0.0 + targets nodes +} + +option verticalNodeSpacing: double { + label "verticalNodeSpacing" + description "vertical spacing between a node and its successor" + default = 5.0 + lowerBound = 0.0 + targets nodes +} \ No newline at end of file diff --git a/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java b/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java new file mode 100644 index 000000000..6eaec5e93 --- /dev/null +++ b/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java @@ -0,0 +1,33 @@ +/* + * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient + * + * http://rtsys.informatik.uni-kiel.de/kieler + * + * Copyright ${year} by + * + Kiel University + * + Department of Computer Science + * + Real-Time and Embedded Systems Group + * + * This code is provided under the terms of the Eclipse Public License (EPL). + */ +package org.eclipse.elk.alg.indentedtree.options; + +import org.eclipse.elk.graph.properties.IProperty; +import org.eclipse.elk.graph.properties.Property; + +/** + * + */ +public final class InternalProperties { + + + /** + * the total indentation of a node, as calculated through a depth-first search + */ + public static final IProperty DEPTH = new Property("depth", 0.0); + + /** + * the indentation of the edge to the left of a node, inherited from its "parent" + */ + public static final IProperty EDGE_INDENTATION = new Property("edge_indentation", 0.0); +} From a772f588965b0299107c71a0e17071c969e9d25e Mon Sep 17 00:00:00 2001 From: Tobias Weimar Date: Wed, 11 Dec 2024 15:00:56 +0100 Subject: [PATCH 2/4] Moved IndentedTree Moved IntentedTree to correct the level in the hierarchy --- .../org.eclipse.elk.alg.indentedtree}/.project | 0 .../.settings/org.eclipse.jdt.core.prefs | 9 +++++++++ .../META-INF/MANIFEST.MF | 13 +++++++++++++ .../build.properties | 5 +++++ .../docs/SpacingsAnnotated.svg | 0 .../docs/indentedTree.md | 0 .../org/eclipse/elk/alg/indentedtree/.gitignore | 0 ...rg.eclipse.elk.core.data.ILayoutMetaDataProvider | 1 + .../indentedtree/IndentedtreeLayoutProvider.java | 0 .../eclipse/elk/alg/indentedtree/indentedtree.melk | 0 .../indentedtree/options/InternalProperties.java | 0 11 files changed, 28 insertions(+) rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/.project (100%) create mode 100644 plugins/org.eclipse.elk.alg.indentedtree/.settings/org.eclipse.jdt.core.prefs create mode 100644 plugins/org.eclipse.elk.alg.indentedtree/META-INF/MANIFEST.MF create mode 100644 plugins/org.eclipse.elk.alg.indentedtree/build.properties rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/docs/SpacingsAnnotated.svg (100%) rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/docs/indentedTree.md (100%) rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore (100%) create mode 100644 plugins/org.eclipse.elk.alg.indentedtree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java (100%) rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk (100%) rename {org.eclipse.elk.alg.indentedtree => plugins/org.eclipse.elk.alg.indentedtree}/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java (100%) diff --git a/org.eclipse.elk.alg.indentedtree/.project b/plugins/org.eclipse.elk.alg.indentedtree/.project similarity index 100% rename from org.eclipse.elk.alg.indentedtree/.project rename to plugins/org.eclipse.elk.alg.indentedtree/.project diff --git a/plugins/org.eclipse.elk.alg.indentedtree/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.elk.alg.indentedtree/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..c9545f06a --- /dev/null +++ b/plugins/org.eclipse.elk.alg.indentedtree/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/plugins/org.eclipse.elk.alg.indentedtree/META-INF/MANIFEST.MF b/plugins/org.eclipse.elk.alg.indentedtree/META-INF/MANIFEST.MF new file mode 100644 index 000000000..10e120e15 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.indentedtree/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: ELK Indented Tree Layout Algorithm +Bundle-SymbolicName: org.eclipse.elk.alg.indentedtree;singleton:=true +Bundle-Vendor: Eclipse Modeling Project +Bundle-Version: 0.10.0.qualifier +Require-Bundle: org.eclipse.elk.core, + org.eclipse.elk.graph, + org.eclipse.elk.alg.common, + com.google.guava, + org.eclipse.emf.common +Automatic-Module-Name: org.eclipse.elk.alg.indentedtree +Bundle-RequiredExecutionEnvironment: JavaSE-11 diff --git a/plugins/org.eclipse.elk.alg.indentedtree/build.properties b/plugins/org.eclipse.elk.alg.indentedtree/build.properties new file mode 100644 index 000000000..2b0d95b6b --- /dev/null +++ b/plugins/org.eclipse.elk.alg.indentedtree/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + . diff --git a/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg b/plugins/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg similarity index 100% rename from org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg rename to plugins/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg diff --git a/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md b/plugins/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md similarity index 100% rename from org.eclipse.elk.alg.indentedtree/docs/indentedTree.md rename to plugins/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md diff --git a/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore b/plugins/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore similarity index 100% rename from org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore rename to plugins/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider b/plugins/org.eclipse.elk.alg.indentedtree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider new file mode 100644 index 000000000..686df688f --- /dev/null +++ b/plugins/org.eclipse.elk.alg.indentedtree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider @@ -0,0 +1 @@ +org.eclipse.elk.alg.indentedtree.IndentedtreeMetadataProvider \ No newline at end of file diff --git a/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java similarity index 100% rename from org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java rename to plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java diff --git a/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk similarity index 100% rename from org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk rename to plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk diff --git a/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java similarity index 100% rename from org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java rename to plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java From bc32b081d23377c575ffea23ea7d090f2d611004 Mon Sep 17 00:00:00 2001 From: Tobias Weimar Date: Wed, 11 Dec 2024 16:42:04 +0100 Subject: [PATCH 3/4] Spacings and documentation Updated Spacings to only have default values where appropriate; improved documentation of spacing options, including graphics. --- .../docs/Spacings.svg | 587 ++++++++++++++++++ .../docs/SpacingsAnnotated.svg | 81 --- .../docs/indentedTree.md | 2 +- .../IndentedtreeLayoutProvider.java | 35 +- .../elk/alg/indentedtree/indentedtree.melk | 18 +- 5 files changed, 621 insertions(+), 102 deletions(-) create mode 100644 plugins/org.eclipse.elk.alg.indentedtree/docs/Spacings.svg delete mode 100644 plugins/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg diff --git a/plugins/org.eclipse.elk.alg.indentedtree/docs/Spacings.svg b/plugins/org.eclipse.elk.alg.indentedtree/docs/Spacings.svg new file mode 100644 index 000000000..9c301e711 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.indentedtree/docs/Spacings.svg @@ -0,0 +1,587 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Wednesday, December 11, 2024 at 4:19:31 PM Central European Standard Time + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Indented Tree Layout AlgorithmPurple: Horizontal Edge IndentationBlue: Relative IndentationGreen: Vertical Node Spacing + + + + diff --git a/plugins/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg b/plugins/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg deleted file mode 100644 index 627af7d84..000000000 --- a/plugins/org.eclipse.elk.alg.indentedtree/docs/SpacingsAnnotated.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - -Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Tuesday, December 10, 2024 at 3:58:10 PM Central European Standard Time - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md b/plugins/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md index ad89ea401..ac64bc99a 100644 --- a/plugins/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md +++ b/plugins/org.eclipse.elk.alg.indentedtree/docs/indentedTree.md @@ -7,4 +7,4 @@ This algorithm allows the user to set three main parameters: - relative Indentation, which decides how far a should should be indented horizontally relative to the position of its incoming edge. - vertical Node Spacing, which determines the vertical distance between a node and its immediate successor, independent of hierarchy. The horizontal Edge Intentation of its parent and the relative Indentation add up to give the total indentation of a node. -![Interpretation of Properties](SpacingsAnnotated.svg) \ No newline at end of file +![Interpretation of Properties](Spacings.svg) \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java index a945f1072..b67a806be 100644 --- a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java +++ b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java @@ -5,6 +5,7 @@ import java.util.List; import org.eclipse.elk.core.AbstractLayoutProvider; +import org.eclipse.elk.core.UnsupportedGraphException; import org.eclipse.elk.core.math.ElkPadding; import org.eclipse.elk.core.util.IElkProgressMonitor; import org.eclipse.elk.graph.ElkEdge; @@ -15,8 +16,8 @@ import org.eclipse.elk.alg.indentedtree.options.InternalProperties; /** - * A layout algorithm for creating a filesystem-like layout. - * This assumes that the graph is a tree and that no ports exist + * A layout algorithm for creating a filesystem-like layout. This assumes that the graph is a tree + * and that no ports exist * * @author tobias */ @@ -104,16 +105,28 @@ public void layout(ElkNode layoutGraph, IElkProgressMonitor progressMonitor) { // create one section for the new edge ElkEdgeSection section = ElkGraphUtil.firstEdgeSection(edge, true, true); + + + // if horizontal edge indentation is set, use that, otherwise, use half of the + // parent's width + double horizontalEdgeIndentation; + if (source.hasProperty(IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION)) { + horizontalEdgeIndentation = + source.getProperty(IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION); + } else { + horizontalEdgeIndentation = source.getWidth() / 2; + } + + // throw error if edge would have to be placed far away from the parent node + if (source.getWidth() < horizontalEdgeIndentation) { + throw new UnsupportedGraphException( + "Horizontal Edge Indentation is larger than its parent node's width"); + } + // set starting location for new edge - // Math.min(...) ensures that the starting location is not further to the right than - // the right border of the source node. - // Omitting Math.min(...) and leaving only the horizontalEdgeIndentation will cause - // diagonal edges if source node is narrower than horizontalEdgeIndentation. - section.setStartLocation( - source.getX() + Math.min(source.getWidth(), - source.getProperty( - IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION)), + section.setStartLocation(source.getX() + horizontalEdgeIndentation, source.getY() + source.getHeight()); + // end location: middle of left border of target section.setEndLocation(target.getX(), target.getY() + target.getHeight() / 2); @@ -164,7 +177,7 @@ private List dfs(ElkNode origin, List list, Double depth) { for (ElkEdge out : origin.getOutgoingEdges()) { // recursion dfs(ElkGraphUtil.connectableShapeToNode(out.getTargets().get(0)), list, - depth + origin.getProperty(IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION)); + depth + (origin.hasProperty(IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION) ? origin.getProperty(IndentedtreeOptions.HORIZONTAL_EDGE_INDENTATION) : origin.getWidth()/2)); } return list; } diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk index fea709153..9bf9c235d 100644 --- a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk +++ b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk @@ -8,23 +8,21 @@ bundle { idPrefix org.eclipse.elk.alg.indentedtree } - - algorithm indentedtree(IndentedtreeLayoutProvider) { label "indentedtree" - description "Create a filesystem-like layout for trees. Assume that the graph is a tree and that no ports exist." + description + "Create a filesystem-like layout for trees. Assume that the graph is a tree and that no ports exist." metadataClass options.IndentedtreeOptions supports org.eclipse.elk.padding = new ElkPadding(10) - supports verticalNodeSpacing supports relativeIndentation supports horizontalEdgeIndentation } - option relativeIndentation: double { label "relativeIndentation" - description "indentation relative to the vertical edge to the left of this node" + description + "indentation relative to the vertical edge to the left of this node" default = 5.0 lowerBound = 0.0 targets nodes @@ -32,15 +30,17 @@ option relativeIndentation: double { option horizontalEdgeIndentation: double { label "horizontalEdgeIndentation" - description "horizontal indentation of the edge leading from a node to its children" - default = 5.0 + description + "horizontal indentation of the edge leading from a node to its children" lowerBound = 0.0 + // no default value, as that is dynamically set to half the parent node's width if option is not set targets nodes } option verticalNodeSpacing: double { label "verticalNodeSpacing" - description "vertical spacing between a node and its successor" + description + "vertical spacing between a node and its successor" default = 5.0 lowerBound = 0.0 targets nodes From e8accadee790ea8c719e41e7a1b8bae18e3fbc11 Mon Sep 17 00:00:00 2001 From: Tobias Weimar Date: Tue, 7 Jan 2025 15:06:21 +0100 Subject: [PATCH 4/4] Small cleanups copyright headers, newlines, removed .gitignore from src-gen/ folder --- .../eclipse/elk/alg/indentedtree/.gitignore | 1 - .../IndentedtreeLayoutProvider.java | 10 ++++++++- .../elk/alg/indentedtree/indentedtree.melk | 11 +++++++++- .../options/InternalProperties.java | 21 ++++++++----------- 4 files changed, 28 insertions(+), 15 deletions(-) delete mode 100644 plugins/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore b/plugins/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore deleted file mode 100644 index 7275ad321..000000000 --- a/plugins/org.eclipse.elk.alg.indentedtree/src-gen/org/eclipse/elk/alg/indentedtree/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/IndentedtreeMetadataProvider.java diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java index b67a806be..8307bc312 100644 --- a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java +++ b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/IndentedtreeLayoutProvider.java @@ -1,3 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2024 Kiel University and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ package org.eclipse.elk.alg.indentedtree; import java.util.ArrayList; @@ -19,7 +28,6 @@ * A layout algorithm for creating a filesystem-like layout. This assumes that the graph is a tree * and that no ports exist * - * @author tobias */ public class IndentedtreeLayoutProvider extends AbstractLayoutProvider { diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk index 9bf9c235d..f251a20f5 100644 --- a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk +++ b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/indentedtree.melk @@ -1,3 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2024 Kiel University and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ package org.eclipse.elk.alg.indentedtree import org.eclipse.elk.alg.indentedtree.IndentedtreeLayoutProvider @@ -44,4 +53,4 @@ option verticalNodeSpacing: double { default = 5.0 lowerBound = 0.0 targets nodes -} \ No newline at end of file +} diff --git a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java index 6eaec5e93..a1cc861dd 100644 --- a/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java +++ b/plugins/org.eclipse.elk.alg.indentedtree/src/org/eclipse/elk/alg/indentedtree/options/InternalProperties.java @@ -1,22 +1,19 @@ -/* - * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient - * - * http://rtsys.informatik.uni-kiel.de/kieler - * - * Copyright ${year} by - * + Kiel University - * + Department of Computer Science - * + Real-Time and Embedded Systems Group +/******************************************************************************* + * Copyright (c) 2024 Kiel University and others. * - * This code is provided under the terms of the Eclipse Public License (EPL). - */ + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ package org.eclipse.elk.alg.indentedtree.options; import org.eclipse.elk.graph.properties.IProperty; import org.eclipse.elk.graph.properties.Property; /** - * + * Internal Property definitions for the Indented Tree Layout Algorithm */ public final class InternalProperties {