|
Search this API | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object y.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 GroupBoundsCalculator
s 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 PortCandidate
s or the
conversion
of PortConstraint
s into
PortCandidate
s. Hence, they only work well if the applied layout algorithm supports PortCandidate
s.
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 components (i.e. sub-graphs) which are internally enclosed by a temporary group
node. To assign a specific Layouter
instance for a component, simply map the component Id to
the desired Layouter
in a DataProvider
registered with
key TemporaryGroupNodeInsertionStage.COMPONENT_LAYOUT_ALGORITHM_DPKEY
.
It is then not necessary to use key GROUP_NODE_LAYOUTER_DPKEY
. Note, however, that only non-nested
components are supported by the mentioned stage.
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 PortCandidate s 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 PortConstraint s of inter-edges are temporarily replaced by PortCandidate s. |
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 PortCandidate s 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 PortConstraint s of inter-edges are temporarily replaced by PortCandidate s. |
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_LAYOUTER
public 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 steppublic 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 sizesMethod 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()
PortCandidate
s are inserted to improve the routing of inter-edges.
If enabled, RecursiveGroupLayouter
will insert PortCandidate
s for all inter-edges that cross a
group node border. Those PortCandidate
s are located at the relative position of the real source/target node.
Inter-edges that connect to such PortCandidate
s 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 PortCandidate
s,
inter-edges will always end at the border/center of the corresponding
group node. Thus, they are rerouted afterwards using an
edge routing algorithm
.
PortCandidate
s are always satisfied depending on the used layout algorithm, even if this
option is disabled.PortCandidate
s will only have an effect if the layout algorithm supports them.true
if temporary port candidates are insertedsetAutoAssignPortCandidatesEnabled(boolean)
,
routeInterEdges(LayoutGraph, EdgeList)
,
setInterEdgeRouter(Layouter)
,
PortCandidate
public void setAutoAssignPortCandidatesEnabled(boolean autoAssignPortCandidatesEnabled)
PortCandidate
s are inserted to improve the routing of inter-edges.
If enabled, RecursiveGroupLayouter
will insert PortCandidate
s for all inter-edges that cross a
group node border. Those PortCandidate
s are located at the relative position of the real source/target node.
Inter-edges that connect to such PortCandidate
s 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 PortCandidate
s,
inter-edges will always end at the border/center of the corresponding
group node. Thus, they are rerouted afterwards using an
edge routing algorithm
.
PortCandidate
s are always satisfied depending on the used layout algorithm, even if this
option is disabled.PortCandidate
s will only have an effect if the layout algorithm supports them.PortCandidate
s are added.autoAssignPortCandidatesEnabled
- true
if temporary port candidates should be insertedrouteInterEdges(LayoutGraph, EdgeList)
,
PortCandidate
false | true |
public boolean isReplacingPortConstraintsEnabled()
PortConstraint
s of inter-edges are temporarily replaced by PortCandidate
s.
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.
PortCandidate
s are always satisfied depending on the used layout algorithm, even if this
option is disabled.PortConstraint
s will only have an effect if the layout algorithm
supports PortCandidate
s.setReplacingPortConstraintsEnabled(boolean)
,
routeInterEdges(LayoutGraph, EdgeList)
,
PortCandidate
public void setReplacingPortConstraintsEnabled(boolean replacingPortConstraintsEnabled)
PortConstraint
s of inter-edges are temporarily replaced by PortCandidate
s.
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.
PortCandidate
s are always satisfied depending on the used layout algorithm, even if this
option is disabled.PortConstraint
s will only have an effect if the layout algorithm
supports PortCandidate
s.PortConstraint
s are temporarily replaced with corresponding PortCandidate
s.replacingPortConstraintsEnabled
- whether or not port constraints should be replacedrouteInterEdges(LayoutGraph, EdgeList)
,
PortCandidate
public 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 nodesInitial 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_EDGES
interEdgesDpKey
- the inter edge selection key
java.lang.IllegalArgumentException
- if the specified key is null
setInterEdgeRouter(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 PortCandidate
s 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.
MinimumSizeGroupBoundsCalculator
groupBoundsCalculator
- the new GroupBoundsCalculator
instance
|
© Copyright 2000-2022, yWorks GmbH. All rights reserved. |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |