|
Search this API | ||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objecty.layout.AbstractLayoutStage
y.layout.grouping.RecursiveGroupLayouter
public class RecursiveGroupLayouter
This layout algorithm recursively traverses a hierarchically organized graph in a bottom-up fashion and applies a specified layout algorithm to the contents (direct children) of each group node.
The way a graph is arranged depends on the layout algorithms which are
applied to the different group nodes.
RecursiveGroupLayouter 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.

RecursiveGroupLayouter 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.
core layout algorithm or a special
layout algorithm retrieved from a DataProvider registered with GROUP_NODE_LAYOUTER_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.
The following two special cases should be considered.
If null is specified as layout algorithm for a group, the recursion will be disabled and the
group is handled non-recursively: the group itself and its content is arranged by the algorithm specified
for the nearest ancestor which has a non-null algorithm mapped to it.
Importantly, this must be distinguished from the second case where the layout of the group content should remain
unchanged. This is achieved when the group is associated with NULL_LAYOUTER as responsible layout
algorithm (or any another algorithm that does not change the layout).
RecursiveGroupLayouter computes the final size of the group node using an implementation of
GroupBoundsCalculator. Customized GroupBoundsCalculators can be specified using
setGroupBoundsCalculator(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 uses the
core layout algorithm to arrange the top level hierarchy.
Note that RecursiveGroupLayouter can run without a core layout. In this case no layout is calculated for
the top level hierarchy. Still, for group nodes with a non-null algorithm, the bounds are adjusted
to fit their respective contents.
Finally, routes for the edges whose source node is located at a different hierarchy level than its target node
are computed. The edge routing algorithm for these so-called inter-edges
can be customized.
There are two alternatives for applying different layout styles to the contents of group nodes:
layout algorithm by registering a DataProvider
with key GROUP_NODE_LAYOUTER_DPKEY. The content of the hierarchy root is arranged with the
core layout algorithm.
LayoutMultiplexer as core layout algorithm.
Since RecursiveGroupLayouter 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.
It is also possible to apply individual layout styles to different sub-graphs using this
algorithm without actually defining group nodes: Use TemporaryGroupNodeInsertionStage
and specify RecursiveGroupLayouter as its core layout algorithm.
The stage allows to define sub-graphs which are internally enclosed by a temporary group
node. To assign a specific Layouter instance for a temporary group, specify
the desired Layouter in the TemporaryGroupDescriptor's
property TemporaryGroupDescriptor.setRecursiveGroupLayoutAlgorithm(Layouter).
It is then not necessary to use key GROUP_NODE_LAYOUTER_DPKEY.
RecursiveGroupLayouter with core layout set to NULL_LAYOUTER and no
further configuration.![]() |
![]() |
![]() |
![]() |
| Field Summary | |
|---|---|
static java.lang.Object |
GROUP_NODE_LAYOUTER_DPKEY
A DataProvider key for arranging the content of each group node with an individual layout algorithm.
|
static java.lang.Object |
GROUP_NODE_PARTITION_GRID_DPKEY
A DataProvider key for specifying a local partition grid for each group node.
|
static Layouter |
NULL_LAYOUTER
A constant that represents a Layouter implementation that does nothing. |
static java.lang.Object |
SOURCE_SPLIT_ID_DPKEY
A DataProvider key for assigning source split ids to edges connecting to group nodes.
|
static java.lang.Object |
TARGET_SPLIT_ID_DPKEY
A DataProvider key for assigning target split ids to edges connecting to group nodes.
|
| Fields inherited from interface y.layout.Layouter |
|---|
EDGE_ID_DPKEY, NODE_ID_DPKEY, NODE_TYPE_DPKEY, SELECTED_EDGES, SELECTED_NODES |
| Constructor Summary | |
|---|---|
RecursiveGroupLayouter()
Creates a new instance of RecursiveGroupLayouter with default settings. |
|
RecursiveGroupLayouter(Layouter core)
Creates a new instance of RecursiveGroupLayouter with default settings using the given
layout algorithm. |
|
RecursiveGroupLayouter(Layouter core,
GroupBoundsCalculator gbc)
Creates a new instance of RecursiveGroupLayouter with default settings using the given
layout algorithm and GroupBoundsCalculator implementation. |
|
| Method Summary | |
|---|---|
boolean |
canLayout(LayoutGraph graph)
Accepts all general graphs without exception. |
void |
doLayout(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. |
GroupBoundsCalculator |
getGroupBoundsCalculator()
Returns a GroupBoundsCalculator which computes the sizes of all group nodes. |
Layouter |
getInterEdgeRouter()
Returns the current edge routing algorithm for handling inter-edges. |
java.lang.Object |
getInterEdgesDpKey()
Returns the key for marking the inter-edges to be routed. |
boolean |
isAutoAssignPortCandidatesEnabled()
Returns whether or not temporary PortCandidates are inserted to improve the routing of inter-edges. |
boolean |
isConsiderEmptyGroupsEnabled()
Returns whether empty group nodes are handled like group nodes with content or like normal nodes. |
boolean |
isConsiderSketchEnabled()
Returns whether or not to consider the initial coordinates of the graph elements. |
boolean |
isReplacingPortConstraintsEnabled()
Returns 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 |
setAutoAssignPortCandidatesEnabled(boolean autoAssignPortCandidatesEnabled)
Specifies whether or not temporary PortCandidates are inserted to improve the routing of inter-edges. |
void |
setConsiderEmptyGroupsEnabled(boolean enabled)
Specifies whether empty group nodes are handled like group nodes with content or like normal nodes. |
void |
setConsiderSketchEnabled(boolean fromSketchModeEnabled)
Specifies whether or not to consider the initial coordinates of the graph elements. |
void |
setGroupBoundsCalculator(GroupBoundsCalculator groupBoundsCalculator)
Specifies a GroupBoundsCalculator which computes the sizes of all group nodes. |
void |
setInterEdgeRouter(Layouter interEdgeRouter)
Specifies the current edge routing algorithm for handling inter-edges. |
void |
setInterEdgesDpKey(java.lang.Object interEdgesDpKey)
Specifies the key for marking the inter-edges to be routed. |
void |
setReplacingPortConstraintsEnabled(boolean replacingPortConstraintsEnabled)
Specifies whether or not PortConstraints of inter-edges are temporarily replaced by PortCandidates. |
| Methods inherited from class y.layout.AbstractLayoutStage |
|---|
canLayoutCore, doLayoutCore, getCoreLayouter, setCoreLayouter |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
public static final java.lang.Object GROUP_NODE_PARTITION_GRID_DPKEY
DataProvider key for specifying a local partition grid for each group node.
Each recursively handled group node can get its own local PartitionGrid.
The grid is then valid for the child nodes of the group and only visible for the
layout algorithm that is responsible for the group's content. Thus, to properly consider the
grid it is required that the responsible algorithm supports the partition grid structure.
The mapping of the nodes to the partition cells is still defined
by a single DataProvider registered with the graph with key PartitionGrid.PARTITION_CELL_DPKEY.
When creating the cell id it is important to call the creation
method on the correct partition grid instance.
In addition to the local partition grids it is also allowed to have a global grid which is defined as usual
via key PartitionGrid.PARTITION_GRID_DPKEY. This grid is handled by the core layout algorithm
responsible for the top-level hierarchy.
public static final java.lang.Object GROUP_NODE_LAYOUTER_DPKEY
DataProvider key for arranging the content of each group node with an individual layout algorithm.
The specified layout algorithm instance is applied to the content of the group node.
To arrange the top level elements the core layout algorithm is used.
The core layout is also applied to group nodes if there is no DataProvider registered. Importantly, this
must be distinguished from the case that there is a provider but it returns null for a group.
Then, RecursiveGroupLayouter handles the corresponding group node non-recursively. The group node and
its content is arranged using the layout algorithm instance specified for the nearest
ancestor of the group node which is associated with an algorithm.
NULL_LAYOUTER.NULL_LAYOUTERpublic static final java.lang.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.
IncrementalHierarchicLayouter 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,
IncrementalHierarchicLayouter,
EdgeLayoutDescriptor.setDirectGroupContentEdgeRoutingEnabled(boolean)![]() With source and target split ids | ![]() Without source and target split ids (inner edge is routed with inter-edge routing algorithm) |
public static final java.lang.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).
IncrementalHierarchicLayouter 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,
IncrementalHierarchicLayouter,
EdgeLayoutDescriptor.setDirectGroupContentEdgeRoutingEnabled(boolean)![]() With source and target split ids | ![]() Without source and target split ids (inner edge is routed with inter-edge routing algorithm) |
public static final Layouter NULL_LAYOUTER
Layouter 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.
| Constructor Detail |
|---|
public RecursiveGroupLayouter()
RecursiveGroupLayouter with default settings.
public RecursiveGroupLayouter(Layouter core)
RecursiveGroupLayouter with default settings using the given
layout algorithm.
core - the layout algorithm that is applied in each recursion step
public RecursiveGroupLayouter(Layouter core,
GroupBoundsCalculator gbc)
RecursiveGroupLayouter with default settings using the given
layout algorithm and GroupBoundsCalculator implementation.
core - the layout algorithm that is applied in each step of the recursiongbc - the GroupBoundsCalculator for calculating group sizes| Method Detail |
|---|
public boolean isConsiderSketchEnabled()
RecursiveGroupLayouter sets the coordinates of the nodes to their
initial position before the corresponding layout algorithm is called.
RecursiveGroupLayouter uses a layout algorithm
that runs in From Sketch mode.true if the initial coordinates of the graph elements are considered,
false otherwisesetConsiderSketchEnabled(boolean)public void setConsiderSketchEnabled(boolean fromSketchModeEnabled)
RecursiveGroupLayouter sets the coordinates of the nodes to their
initial position before the corresponding layout algorithm is called.
RecursiveGroupLayouter uses a layout algorithm
that runs in From Sketch mode.fromSketchModeEnabled - true if the initial coordinates of the graph elements should be
considered, false otherwisepublic boolean isAutoAssignPortCandidatesEnabled()
PortCandidates are inserted to improve the routing of inter-edges.
If enabled, RecursiveGroupLayouter 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.true if temporary port candidates are insertedsetAutoAssignPortCandidatesEnabled(boolean),
routeInterEdges(LayoutGraph, EdgeList),
setInterEdgeRouter(Layouter),
PortCandidatepublic void setAutoAssignPortCandidatesEnabled(boolean autoAssignPortCandidatesEnabled)
PortCandidates are inserted to improve the routing of inter-edges.
If enabled, RecursiveGroupLayouter 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.PortCandidates are added.autoAssignPortCandidatesEnabled - true if temporary port candidates should be insertedrouteInterEdges(LayoutGraph, EdgeList),
PortCandidate![]() false | ![]() true |
public boolean isReplacingPortConstraintsEnabled()
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.setReplacingPortConstraintsEnabled(boolean),
routeInterEdges(LayoutGraph, EdgeList),
PortCandidatepublic void setReplacingPortConstraintsEnabled(boolean replacingPortConstraintsEnabled)
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.PortConstraints are temporarily replaced with corresponding PortCandidates.replacingPortConstraintsEnabled - whether or not port constraints should be replacedrouteInterEdges(LayoutGraph, EdgeList),
PortCandidatepublic boolean isConsiderEmptyGroupsEnabled()
RecursiveGroupLayouter 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 if empty groups are treated like group nodes, false if they are treated like
normal nodessetConsiderEmptyGroupsEnabled(boolean)public void setConsiderEmptyGroupsEnabled(boolean enabled)
RecursiveGroupLayouter 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.
enabled - true if empty groups should be treated like group nodes, false if they are
treated like normal nodes![]() Initial graph | ![]() Empty group handled like normal node | ![]() Empty group handled like other group nodes |
public Layouter getInterEdgeRouter()
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.
setInterEdgeRouter(Layouter),
setInterEdgesDpKey(Object)public void setInterEdgeRouter(Layouter interEdgeRouter)
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.
interEdgeRouter - the edge routing algorithm for inter-edgessetInterEdgesDpKey(Object)public java.lang.Object getInterEdgesDpKey()
inter-edge routing algorithm to obtain the
edges to be routed. This layouter automatically marks these edges and registers the DataProvider using the
specified key.
getInterEdgeRouter()public void setInterEdgesDpKey(java.lang.Object interEdgesDpKey)
inter-edge routing algorithm to obtain the
edges to be routed. This layouter automatically marks these edges and registers the DataProvider using the
specified key.
Layouter.SELECTED_EDGESinterEdgesDpKey - the inter edge selection key
java.lang.IllegalArgumentException - if the specified key is nullsetInterEdgeRouter(Layouter)public boolean canLayout(LayoutGraph graph)
graph - the input graph
true if there is a graph that is not null, false otherwiseLayouter.doLayout(LayoutGraph)public void doLayout(LayoutGraph graph)
layout algorithms are applied to the content of the groups.
graph - the input graphLayouter.canLayout(LayoutGraph)
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 nodesetAutoAssignPortCandidatesEnabled(boolean),
setReplacingPortConstraintsEnabled(boolean),
setInterEdgeRouter(Layouter)public GroupBoundsCalculator getGroupBoundsCalculator()
GroupBoundsCalculator which computes the sizes of all group nodes.
This GroupBoundsCalculator is used each time after calculating the layout for a content graph.
GroupBoundsCalculator instancesetGroupBoundsCalculator(GroupBoundsCalculator)public void setGroupBoundsCalculator(GroupBoundsCalculator groupBoundsCalculator)
GroupBoundsCalculator which computes the sizes of all group nodes.
This GroupBoundsCalculator is used each time after calculating the layout for a content graph.
MinimumSizeGroupBoundsCalculatorgroupBoundsCalculator - the new GroupBoundsCalculator instance
|
© Copyright 2000-2025, yWorks GmbH. All rights reserved. |
||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||