public class RecursiveGroupLayout extends AbstractLayoutStage
layout algorithms which are
applied to the different group nodes. RecursiveGroupLayout is able to produce different layout styles for the
content of each group node.
This layout algorithm can be either applied if a layout algorithm cannot handle grouped graphs
by itself or if the content of (some) group nodes should be arranged differently.
RecursiveGroupLayout uses a hierarchy tree representation of the grouped graph in which the content nodes are
the children of their containing group node. That way, it can traverse the tree recursively while arranging only the
direct children of each group node. The layout algorithm starts by arranging the leaves in the hierarchy tree, then
works its way up to the root computing the layout for each group node in the tree.
All nodes other than the direct children are temporarily hidden. The layout algorithm performs two steps for each group node.
core layout algorithm or a
special layout algorithm retrieved from a IDataProvider registered with
GROUP_NODE_LAYOUT_DPKEY. The content of group nodes among the children is already arranged at this time and
will be ignored. These group nodes are handled like normal nodes with a size that encloses the content.
RecursiveGroupLayout computes the final size of the group node using an implementation of
IGroupBoundsCalculator. Customized IGroupBoundsCalculators can be specified using
GroupBoundsCalculator. Aside from the resulting layout,
this size is used in the following iteration.
After a layout is applied to all group nodes, the layout algorithm computes routes for the edges whose source node is
located at a different hierarchy level than its target node. The edge routing algorithm for these so-called inter-edges
can be customized.
Note that RecursiveGroupLayout can run without a
core layout algorithm. In this case no layout is calculated, instead the
group node bounds are merely adjusted to fit their respective contents.
layout algorithm by registering a IDataProvider
with key GROUP_NODE_LAYOUT_DPKEY. The content of the hierarchy root is arranged with the
core layout algorithm.
LayoutMultiplexer as core layout algorithm.
Since RecursiveGroupLayout delegates the actual arrangement of the graph to other layout algorithms, it will
support the same features as the currently used layout algorithm.
The improvement of the routing of inter-edges is based on the insertion
of PortCandidates or the conversion of
PortConstraints into PortCandidates. Hence, they only work well if the applied layout algorithm
supports PortCandidates.
This algorithm also provides a From Sketch mode that should be activated if the
applied layout algorithm runs in From Sketch mode, too. Otherwise, the initial coordinates may not be considered
correctly.
| Modifier and Type | Field and Description |
|---|---|
static NodeDpKey<ILayoutAlgorithm> |
GROUP_NODE_LAYOUT_DPKEY
A
DataProvider key for arranging the content of each group node with an individual layout algorithm.
|
static ILayoutAlgorithm |
NULL_LAYOUT
A constant that represents a
ILayoutAlgorithm implementation that does nothing. |
static EdgeDpKey<Object> |
SOURCE_SPLIT_ID_DPKEY
A
DataProvider key for assigning source split ids to edges connecting to group nodes.
|
static EdgeDpKey<Object> |
TARGET_SPLIT_ID_DPKEY
A
DataProvider key for assigning target split ids to edges connecting to group nodes.
|
| Constructor and Description |
|---|
RecursiveGroupLayout()
Creates a new instance of
RecursiveGroupLayout with an optional
core layout algorithm. |
RecursiveGroupLayout(ILayoutAlgorithm core)
Creates a new instance of
RecursiveGroupLayout with an optional
core layout algorithm. |
RecursiveGroupLayout(ILayoutAlgorithm core,
IGroupBoundsCalculator gbc)
Creates a new instance of
RecursiveGroupLayout with default settings using the given layout algorithm
and IGroupBoundsCalculator implementation. |
| Modifier and Type | Method and Description |
|---|---|
void |
applyLayout(LayoutGraph graph)
Invokes a recursive traversal through the grouping hierarchy of the given graph during which the specified
layout algorithms
are applied to the content of the groups. |
IGroupBoundsCalculator |
getGroupBoundsCalculator()
Gets a
IGroupBoundsCalculator which computes the sizes of all group nodes. |
ILayoutAlgorithm |
getInterEdgeRouter()
Gets the current edge routing algorithm for handling inter-edges.
|
Object |
getInterEdgesDpKey()
Gets the key for marking the inter-edges to be routed.
|
boolean |
isEmptyGroupsConsiderationEnabled()
Gets whether empty group nodes are handled like group nodes with content or like normal nodes.
|
boolean |
isFromSketchModeEnabled()
Gets whether or not to consider the initial coordinates of the graph elements.
|
boolean |
isPortCandidatesAutoAssignmentEnabled()
Gets whether or not temporary
PortCandidates are inserted to improve the routing of inter-edges. |
boolean |
isPortConstraintsReplacementEnabled()
Gets whether or not
PortConstraints of inter-edges are temporarily replaced by PortCandidates. |
protected void |
routeInterEdges(LayoutGraph graph,
EdgeList interEdges)
Reroutes the given inter-edges using the current
edge routing algorithm. |
void |
setEmptyGroupsConsiderationEnabled(boolean value)
Sets whether empty group nodes are handled like group nodes with content or like normal nodes.
|
void |
setFromSketchModeEnabled(boolean value)
Sets whether or not to consider the initial coordinates of the graph elements.
|
void |
setGroupBoundsCalculator(IGroupBoundsCalculator value)
Sets a
IGroupBoundsCalculator which computes the sizes of all group nodes. |
void |
setInterEdgeRouter(ILayoutAlgorithm value)
Sets the current edge routing algorithm for handling inter-edges.
|
void |
setInterEdgesDpKey(Object value)
Sets the key for marking the inter-edges to be routed.
|
void |
setPortCandidatesAutoAssignmentEnabled(boolean value)
Sets whether or not temporary
PortCandidates are inserted to improve the routing of inter-edges. |
void |
setPortConstraintsReplacementEnabled(boolean value)
Sets whether or not
PortConstraints of inter-edges are temporarily replaced by PortCandidates. |
applyLayoutCore, getCoreLayout, setCoreLayoutpublic static final NodeDpKey<ILayoutAlgorithm> GROUP_NODE_LAYOUT_DPKEY
DataProvider key for arranging the content of each group node with an individual layout algorithm.
The specified layouter instance is applied to the content of the group node. To arrange the top level elements the core layout algorithm
is used.
NULL_LAYOUT.IDataProvider returns null, RecursiveGroupLayout handles the corresponding group node
non-recursively. The group node and its content is arranged using the ILayoutAlgorithm instance specified for
the nearest ancestor of the group node which is associated with a layout algorithm.NULL_LAYOUTpublic static final ILayoutAlgorithm NULL_LAYOUT
ILayoutAlgorithm implementation that does nothing.
This implementation can be assigned to group nodes to keep their content unchanged. The layout algorithm will still calculate the sizes of the group nodes.
public static final EdgeDpKey<Object> SOURCE_SPLIT_ID_DPKEY
DataProvider key for assigning source split ids to edges connecting to group nodes.
The edges will be aligned with edges that connect to the same group node and have the same split id at their source (preferably) or target.
HierarchicLayout
is used as core layout algorithm. Also, the edges need to be
routed directly from the content of a group to the group itself.TARGET_SPLIT_ID_DPKEY,
HierarchicLayout,
EdgeLayoutDescriptor.setDirectGroupContentEdgeRoutingEnabled(boolean)public static final EdgeDpKey<Object> TARGET_SPLIT_ID_DPKEY
DataProvider key for assigning target split ids to edges connecting to group nodes.
The edges will be aligned with edges that connect to the same group node and have the same split id at their source or target (preferably).
HierarchicLayout
is used as core layout algorithm. Also, the edges need to be
routed directly from the content of a group to the group itself.SOURCE_SPLIT_ID_DPKEY,
HierarchicLayout,
EdgeLayoutDescriptor.setDirectGroupContentEdgeRoutingEnabled(boolean)public RecursiveGroupLayout()
RecursiveGroupLayout with an optional
core layout algorithm.public RecursiveGroupLayout(ILayoutAlgorithm core)
RecursiveGroupLayout with an optional
core layout algorithm.core - The layout algorithm that is applied in each recursion step.public RecursiveGroupLayout(ILayoutAlgorithm core, IGroupBoundsCalculator gbc)
RecursiveGroupLayout with default settings using the given layout algorithm
and IGroupBoundsCalculator implementation.core - the layout algorithm that is applied in each step of the recursiongbc - the IGroupBoundsCalculator for calculating group sizespublic void applyLayout(LayoutGraph graph)
layout algorithms
are applied to the content of the groups.applyLayout in interface ILayoutAlgorithmapplyLayout in class AbstractLayoutStagegraph - the input graphpublic IGroupBoundsCalculator getGroupBoundsCalculator()
IGroupBoundsCalculator which computes the sizes of all group nodes.
This IGroupBoundsCalculator is used each time after calculating the layout for a content graph.
MinimumSizeGroupBoundsCalculatorIGroupBoundsCalculator instancesetGroupBoundsCalculator(IGroupBoundsCalculator)public ILayoutAlgorithm getInterEdgeRouter()
During layout, edges that connect from outside a group node to the content inside (inter-edges) are temporarily connected to the group node itself. Hence, these edges have to be routed after restoring the original graph structure using this edge routing algorithm.
It is required that a suitable selection key is specified. The same selection key
must be used for setting the sphere of action for the edge router.
null. Edges are routed as straight lines from source to target.setInterEdgesDpKey(Object),
setInterEdgeRouter(ILayoutAlgorithm)public Object getInterEdgesDpKey()
The key should be used by the specified inter-edge routing algorithm to obtain the edges
to be routed. This layouter automatically marks these edges and registers the IDataProvider using the specified
key.
IllegalArgumentException - if the specified key is nullLayoutKeys.AFFECTED_EDGES_DPKEYgetInterEdgeRouter(),
setInterEdgesDpKey(Object)public boolean isEmptyGroupsConsiderationEnabled()
If they are handled like other group nodes, RecursiveGroupLayout will resize them according to their
(non-existing) content. This results in small empty group nodes. Handled like normal nodes, empty group nodes will keep
their initial size.
true. Empty group nodes are resized.true if empty groups are treated like group nodes, false if they are treated like normal nodessetEmptyGroupsConsiderationEnabled(boolean)public boolean isFromSketchModeEnabled()
When using the initial coordinates, RecursiveGroupLayout sets the coordinates of the nodes to their initial
position before the corresponding layout algorithm is called.
RecursiveGroupLayout uses a layout algorithm that runs
in From Sketch mode.false. The initial coordinates of the nodes are not taken into account.true if the initial coordinates of the graph elements are considered, false otherwisesetFromSketchModeEnabled(boolean)public boolean isPortCandidatesAutoAssignmentEnabled()
PortCandidates are inserted to improve the routing of inter-edges.
If enabled, RecursiveGroupLayout will insert PortCandidates for all inter-edges that cross a group node
border. Those PortCandidates are located at the relative position of the real source/target node. Inter-edges
that connect to such PortCandidates will be routed when the layout of the containing group node is calculated
and will not be rerouted later. This may produce more suitable edge
routes but cannot prevent edges from crossing nodes.
Without temporary or user specified PortCandidates, inter-edges will always end at the border/center of the
corresponding group node. Thus, they are rerouted afterwards using an
edge routing algorithm.
PortCandidates are always satisfied depending on the used layout algorithm, even if this option is
disabled.PortCandidates will only have an effect if the layout algorithm supports them.false. No temporary PortCandidates are added.true if temporary port candidates are insertedrouteInterEdges(LayoutGraph, EdgeList),
setInterEdgeRouter(ILayoutAlgorithm),
PortCandidate,
setPortCandidatesAutoAssignmentEnabled(boolean)public boolean isPortConstraintsReplacementEnabled()
PortConstraints of inter-edges are temporarily replaced by PortCandidates.
If disabled, inter-edges will always end at the border/center of the corresponding group node, even if those edges have
port constraints. Thus, they are rerouted later without considering the
constraint. Enabling this settings may produce more suitable edge routes but cannot prevent edges from crossing nodes.
Port candidates are automatically redirected to their original location. Hence, enabling this option may produce more suitable edge routes if the layout algorithm applied to the content of a group node can handle port candidates.
PortCandidates are always satisfied depending on the used layout algorithm, even if this option is
disabled.PortConstraints will only have an effect if the layout algorithm supports
PortCandidates.true. Existing PortConstraints are temporarily replaced with corresponding PortCandidates.routeInterEdges(LayoutGraph, EdgeList),
PortCandidate,
setPortConstraintsReplacementEnabled(boolean)protected void routeInterEdges(LayoutGraph graph, EdgeList interEdges)
edge routing algorithm.
This method is called after calculating the overall layout when the positions of all nodes and normal edges are fixed.
If no inter-edge router is specified, this method resets the path
of all inter-edges that don't connect to the proper location within the group. This may happen for inter-edges without
PortCandidates or if the applied layout algorithm doesn't support such constraints.
graph - the input graphinterEdges - the edges which traverse the boundary of a group nodesetPortCandidatesAutoAssignmentEnabled(boolean),
setPortConstraintsReplacementEnabled(boolean),
setInterEdgeRouter(ILayoutAlgorithm)public void setEmptyGroupsConsiderationEnabled(boolean value)
If they are handled like other group nodes, RecursiveGroupLayout will resize them according to their
(non-existing) content. This results in small empty group nodes. Handled like normal nodes, empty group nodes will keep
their initial size.
true. Empty group nodes are resized.value - true if empty groups are treated like group nodes, false if they are treated like normal nodesisEmptyGroupsConsiderationEnabled()public void setFromSketchModeEnabled(boolean value)
When using the initial coordinates, RecursiveGroupLayout sets the coordinates of the nodes to their initial
position before the corresponding layout algorithm is called.
RecursiveGroupLayout uses a layout algorithm that runs
in From Sketch mode.false. The initial coordinates of the nodes are not taken into account.value - true if the initial coordinates of the graph elements are considered, false otherwiseisFromSketchModeEnabled()public void setGroupBoundsCalculator(IGroupBoundsCalculator value)
IGroupBoundsCalculator which computes the sizes of all group nodes.
This IGroupBoundsCalculator is used each time after calculating the layout for a content graph.
MinimumSizeGroupBoundsCalculatorvalue - the current IGroupBoundsCalculator instancegetGroupBoundsCalculator()public void setInterEdgeRouter(ILayoutAlgorithm value)
During layout, edges that connect from outside a group node to the content inside (inter-edges) are temporarily connected to the group node itself. Hence, these edges have to be routed after restoring the original graph structure using this edge routing algorithm.
It is required that a suitable selection key is specified. The same selection key
must be used for setting the sphere of action for the edge router.
null. Edges are routed as straight lines from source to target.value - the edge routing algorithm for inter-edgessetInterEdgesDpKey(Object),
getInterEdgeRouter()public void setInterEdgesDpKey(Object value)
The key should be used by the specified inter-edge routing algorithm to obtain the edges
to be routed. This layouter automatically marks these edges and registers the IDataProvider using the specified
key.
IllegalArgumentException - if the specified key is nullLayoutKeys.AFFECTED_EDGES_DPKEYvalue - the inter edge selection keygetInterEdgeRouter(),
getInterEdgesDpKey()public void setPortCandidatesAutoAssignmentEnabled(boolean value)
PortCandidates are inserted to improve the routing of inter-edges.
If enabled, RecursiveGroupLayout will insert PortCandidates for all inter-edges that cross a group node
border. Those PortCandidates are located at the relative position of the real source/target node. Inter-edges
that connect to such PortCandidates will be routed when the layout of the containing group node is calculated
and will not be rerouted later. This may produce more suitable edge
routes but cannot prevent edges from crossing nodes.
Without temporary or user specified PortCandidates, inter-edges will always end at the border/center of the
corresponding group node. Thus, they are rerouted afterwards using an
edge routing algorithm.
PortCandidates are always satisfied depending on the used layout algorithm, even if this option is
disabled.PortCandidates will only have an effect if the layout algorithm supports them.false. No temporary PortCandidates are added.value - true if temporary port candidates are insertedrouteInterEdges(LayoutGraph, EdgeList),
setInterEdgeRouter(ILayoutAlgorithm),
PortCandidate,
isPortCandidatesAutoAssignmentEnabled()public void setPortConstraintsReplacementEnabled(boolean value)
PortConstraints of inter-edges are temporarily replaced by PortCandidates.
If disabled, inter-edges will always end at the border/center of the corresponding group node, even if those edges have
port constraints. Thus, they are rerouted later without considering the
constraint. Enabling this settings may produce more suitable edge routes but cannot prevent edges from crossing nodes.
Port candidates are automatically redirected to their original location. Hence, enabling this option may produce more suitable edge routes if the layout algorithm applied to the content of a group node can handle port candidates.
PortCandidates are always satisfied depending on the used layout algorithm, even if this option is
disabled.PortConstraints will only have an effect if the layout algorithm supports
PortCandidates.true. Existing PortConstraints are temporarily replaced with corresponding PortCandidates.value - whether or not port constraints are replacedrouteInterEdges(LayoutGraph, EdgeList),
PortCandidate,
isPortConstraintsReplacementEnabled()