Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide JSON coordinate options #1071

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
915fa24
Target platform changes?
skieffer Aug 24, 2024
d07e112
Update .gitignore
skieffer Aug 24, 2024
d34db90
Supply missing map clear
skieffer Aug 25, 2024
9976add
Add maps to support coordinate adjustments
skieffer Aug 25, 2024
3e63089
Add comments
skieffer Aug 25, 2024
7208ee3
Add `org.eclipse.elk.json.edgeCoords` property
skieffer Aug 25, 2024
4d49d8b
Adjust edge coordinates according to mode
skieffer Aug 25, 2024
4f76fa0
Use extension methods
skieffer Aug 25, 2024
3683032
Add unit tests
skieffer Aug 25, 2024
0300a97
Use do-while loop
skieffer Aug 25, 2024
f72a435
Remove diagnostic output
skieffer Aug 25, 2024
6d152c9
Revert incidental changes
skieffer Aug 25, 2024
1cdd859
Use static method instead of deprecated json parser constructor
skieffer Aug 26, 2024
b1a02bc
Avoid NPE
skieffer Aug 26, 2024
331b06a
Remove additional cases of deprecated json parser constructor
skieffer Aug 26, 2024
8c03b80
Use `PlainJavaInitialization` in test
skieffer Aug 27, 2024
9a4d24f
Determine edge coord modes more efficiently
skieffer Aug 28, 2024
5e581f5
Simplify adjustment method signature
skieffer Aug 28, 2024
0f8a544
Make edge labels use same coord system as edge
skieffer Aug 28, 2024
81e082b
Add EOF newline
skieffer Aug 28, 2024
52fed6d
Support `org.eclipse.elk.json.shapeCoords` property
skieffer Aug 29, 2024
5d7cf1a
Update docs to cover coordinate options
skieffer Aug 29, 2024
2312415
Write `container` property into edges only in CONTAINER mode
skieffer Aug 29, 2024
82ea83d
Improve property descriptions
skieffer Aug 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ Since ELK graphs are based on EMF, you can simply obtain an instance of the `Elk
One method of particular value to layout algorithm developers is `firstEdgeSection(edge, reset, removeOthers)`, which returns the first edge section of the given edge, optionally resetting its layout data and removing all other edge sections. If the edge doesn't have any edge sections yet, one is created and added to it. This method is handy for applying layout results.

* **Edge Containment:** Unless one uses one of the `create` methods to create edges, finding the node an edge should be contained in may be annoying (thus, don't). The `updateContainment(ElkEdge)` method automatically computes the best containment and puts the edge there. This requires at least one of the edge's end points to be set, since that is what determines the best containment.
Note that, when graphs are imported into ELK from JSON, `updateContainment()` is automatically called on each edge. Authors of graphs in JSON format are therefore not responsible for placing edges
inside their proper container nodes.

While computing the containment is a little intricate (hence the utility method), the actual rule that determines the best containment is rather simple: it is the lowest common ancestor of all end points, where the ancestors of a node are defined as the sequence of nodes from the node itself to the graph's root node. Taking the graph at the top of this page as an example, the rule has the following implications for different types of edges:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,51 @@ The coordinates of most elements are relative to their parent element. There are

* Edge labels are relative to the coordinate system their edge is relative to.
* Source points, bend points, and target points of edges are relative to the edge's containing node. Following the usual containment conventions (as implemented in `ElkGraphUtil`) results in what is displayed in the image above.

## JSON

One way of using ELK is to define a graph using JSON, and then
transfer the computed layout back to the initial JSON graph.
See [_JSON Format_]({{< relref "documentation/tooldevelopers/graphdatastructure/jsonformat.md" >}}).
When working this way, it is possible to control what type of coordinates you get,
using the `org.eclipse.elk.json.shapeCoords` and `org.eclipse.elk.json.edgeCoords` layout options.

### Shape Coords

This setting controls the coordinate system that will be used for all nodes, ports, and labels of nodes and ports.

There are three possible values:

* `INHERIT`: Inherit the value from the parent element.
* `PARENT`: Coordinates are relative to the parent element.
* `ROOT`: Coordinates are relative to the root node, i.e. global coordinates.

The default value is `INHERIT`, except at the root node, where the default is `PARENT`.
Thus, the default behavior is as described in the image at the top of this page.
Setting `ROOT` allows you to instead use a "flat" coordinate system.

### Edge Coords

This setting controls the coordinate system that will be used for all source, bend, and target points of edges,
as well as all edge labels.

There are four possible values:

* `INHERIT`: Inherit the value from the parent element.
* `CONTAINER`: Coordinates are relative to the edge's proper container node (see below).
* `PARENT`: Coordinates are relative to the node in which the edge was defined in the given JSON.
* `ROOT`: Coordinates are relative to the root node, i.e. global coordinates.

The default value is `INHERIT`, except at the root node, where the default is (for historical reasons) `CONTAINER`.
Thus, the default behavior is as described at the top of this page.

The definition of an edge's proper container is given at the end of the page on the
[_Graph Data Structure_]({{< relref "documentation/tooldevelopers/graphdatastructure.md" >}}).
It involves lowest common ancestors, and can be tricky to compute correctly.
In particular, since you are allowed to define an edge under any node whatsoever in the input JSON, the edge's
*parent* node (the one it is defined under) may be different from its container.

If you elect to work in `CONTAINER` mode, ELK helps you by writing a `container` property into each edge after layout,
giving the `id` of the edge's container node. This can then be used to interpret the coordinates.

If you elect to work in `PARENT` or `ROOT` mode instead, then you do not need to know about edge containers at all.
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ labels.
Nodes can have an arbitrary number of ports. Edges can connect to a node either directly or
through one of its ports. A node can also contain an arbitrary number of child nodes. A graph
is actually nothing more than a simple node whose children are the top-level nodes of the graph.
Finally, a node can contain edges. These edges do not necessarily connect to the node, but will
usually connect its children. The edge coordinates will be interpreted relative to the upper
left corner of the node which contains it.
Finally, a node can contain edges. While it is common to define those edges under a given node
that connect that node's children, in fact any edge may be defined under any node, regardless of its
end points. This allows for flexibility when defining hierarchy-crossing edges, as well as for
alternative schemes, such as defining all edges at the root level.
See [_Coordinate System_]({{< relref "documentation/tooldevelopers/graphdatastructure/coordinatesystem.md" >}})
for the rules for interpreting edge coordinates.

```json
{
Expand Down
23 changes: 23 additions & 0 deletions plugins/org.eclipse.elk.core/src/org/eclipse/elk/core/Core.melk
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,29 @@ advanced option omitNodeMicroLayout: boolean {
targets parents
}

// --- JSON
group json {

option shapeCoords: ShapeCoords {
label "Shape Coords"
description
"For layouts transferred into JSON graphs, specify the coordinate system
to be used for nodes, ports, and labels of nodes and ports."
default = ShapeCoords.INHERIT
targets parents
}

option edgeCoords: EdgeCoords {
label "Edge Coords"
description
"For layouts transferred into JSON graphs, specify the coordinate system
to be used for edge route points and edge labels."
default = EdgeCoords.INHERIT
targets parents
}

}

// --- SPACING
group spacing {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*******************************************************************************
* 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.core.options;

/**
* Edge coordinate systems for JSON output. To be accessed using {@link CoreOptions#JSON_EDGE_COORDS}.
* Applies to edges, and to labels of edges.
*/
public enum EdgeCoords {

/**
* Inherit the parent node's coordinate system. The root node has no parent node; here, this setting defaults to
* {@link #CONTAINER}.
*/
INHERIT,
/** relative to the edge's proper container node. */
CONTAINER,
/** relative to the edge's JSON parent node. */
PARENT,
/** relative to the root node, a.k.a. global coordinates. */
ROOT;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* 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.core.options;

/**
* Shape coordinate systems for JSON output. To be accessed using {@link CoreOptions#JSON_SHAPE_COORDS}.
* Applies to nodes, ports, and labels of nodes and ports.
*/
public enum ShapeCoords {

/**
* Inherit the parent shape's coordinate system. The root node has no parent shape; here, this setting defaults to
* {@link #PARENT}.
*/
INHERIT,
/** relative to the shape's JSON parent shape. */
PARENT,
/** relative to the root node, a.k.a. global coordinates. */
ROOT;

}
Loading