public class MultiPageLayout extends AbstractLayoutStage
LayoutGraph
s (called page graphs) such that the
layout (calculated by the specified core layout algorithm
) of each graph
fits the specified maximum page size
.
The algorithm adds special nodes to guarantee that no information is lost when splitting edges that connect nodes placed on different pages (for more details take a look at the concept described below).
The input graph.
The input graph is subdivided into two pages with size 500x500
. Circular nodes denote the so-called connectors
that split edges to nodes placed on other pages. The label of a connector corresponds to that of the opposite node of
the split edge.
This multi-page layout algorithm subdivides the input graph into several smaller ones and applies existing layout
algorithms to each of them. Hence, its layout style heavily depends on the selected core layout algorithm
used for each single page. Furthermore, the algorithm uses several refinement steps to produce more compact results.
Similar to the layout style, the supported feature set mainly depends on the features supported by the specified
core layout algorithm
. Note that due to the underlying
approach of the MultiPageLayout
it doesn't support PartitionGrid
s.
To guarantee that no information is lost, this layout algorithm replaces edges between nodes on different pages by
so-called connector nodes
. Furthermore, it may replicate nodes (the clones are called
proxy nodes
) and insert special nodes to refer to such nodes (so-called
proxy reference nodes
).
Unlike other yFiles layout algorithms, MultiPageLayout
does not modify its input graph but returns its result as
a MultiPageLayoutResult
. To be able to profit as much as possible from existing layout support, this layout
algorithm implements the ILayoutAlgorithm
interface, although method doLayout
does not specify a return value. Therefore, client code has to register
a ILayoutCallback
that is invoked when the algorithm has calculated a new multi-page result.
IDataProvider
s for keys NODE_ID_DPKEY
, EDGE_ID_DPKEY
,
NODE_LABEL_ID_DPKEY
, and EDGE_LABEL_ID_DPKEY
before calling applyLayout(LayoutGraph)
or
calculateLayout(LayoutGraph)
.Modifier and Type | Field and Description |
---|---|
static EdgeDpKey<Object> |
EDGE_ID_DPKEY
A
DataProvider key for mapping each edge of the input graph to a unique ID.
|
static IEdgeLabelLayoutDpKey<Object> |
EDGE_LABEL_ID_DPKEY
A
DataProvider key for mapping each edge label of the input graph to a unique ID.
|
static EdgeDpKey<Object> |
EDGE_TYPE_DPKEY
A
DataProvider key for specifying the type of multi-edges.
|
static NodeDpKey<Object> |
NODE_CLUSTER_ID_DPKEY
A
DataProvider key for assigning a cluster ID to common (non-group) nodes.
|
static NodeDpKey<Object> |
NODE_ID_DPKEY
A
DataProvider key for mapping each node of the input graph to a unique ID.
|
static INodeLabelLayoutDpKey<Object> |
NODE_LABEL_ID_DPKEY
A
DataProvider key for mapping each node label of the input graph to a unique ID.
|
Constructor and Description |
---|
MultiPageLayout(ILayoutAlgorithm core)
Creates a new
MultiPageLayout instance. |
Modifier and Type | Method and Description |
---|---|
protected void |
applyIncrementalLayout(LayoutGraph graph,
IDataProvider incrementalNodesDP,
LayoutContext context)
This method is called to further improve the layout results.
|
void |
applyLayout(LayoutGraph graph)
Calculates a new multi-page layout for the specified graph.
|
MultiPageLayoutResult |
calculateLayout(LayoutGraph graph)
Calculates a new multi-page layout for the specified graph.
|
protected IElementFactory |
createElementFactory()
This method creates the
element factory for multi-page layouts. |
EdgeBundleModes |
getEdgeBundleModeMask()
Gets the bit mask for defining edge bundles.
|
IElementFactory |
getElementFactory()
Gets the
element factory for creating special nodes and edges in a multi-page layout. |
GroupingMode |
getGroupingMode()
Gets how to handle special nodes (like connector and proxy nodes) with respect to groups.
|
ILayoutStage |
getLabeling()
Gets the
ILayoutStage that places the labels of the input graph. |
ILayoutCallback |
getLayoutCallback()
Gets the
callback that is notified upon completion of multi-page layout calculation runs. |
long |
getMaximumDuration()
Gets the preferred time limit (in milliseconds) for the layout algorithm.
|
YDimension |
getMaximumPageSize()
Gets the maximum size of a single page.
|
boolean |
isLabelingEnabled()
Gets whether or not the given
labeling algorithm places the labels of the input
graph. |
boolean |
isStrictClusterSeparationEnabled()
Gets whether or not the algorithm should separate nodes with different
cluster IDs . |
protected boolean |
removeConnectorPair(Node connector1,
Node connector2,
YList originalEdgeIds,
LayoutContext context)
This method is called during a postprocessing step that reduces the number of connectors.
|
protected void |
routeRestoredEdges(LayoutGraph graph,
IDataProvider selectedEdgesDP,
YRectangle boundingRectangle)
This method is called by
removeConnectorPair(Node, Node, YList, LayoutContext) to route the restored edges. |
void |
setEdgeBundleModeMask(EdgeBundleModes value)
Sets the bit mask for defining edge bundles.
|
void |
setElementFactory(IElementFactory value)
Sets the
element factory for creating special nodes and edges in a multi-page layout. |
void |
setGroupingMode(GroupingMode value)
Sets how to handle special nodes (like connector and proxy nodes) with respect to groups.
|
void |
setLabeling(ILayoutStage value)
Sets the
ILayoutStage that places the labels of the input graph. |
void |
setLabelingEnabled(boolean value)
Sets whether or not the given
labeling algorithm places the labels of the input
graph. |
void |
setLayoutCallback(ILayoutCallback value)
Sets the
callback that is notified upon completion of multi-page layout calculation runs. |
void |
setMaximumDuration(long value)
Sets the preferred time limit (in milliseconds) for the layout algorithm.
|
void |
setMaximumPageSize(YDimension value)
Sets the maximum size of a single page.
|
void |
setStrictClusterSeparationEnabled(boolean value)
Sets whether or not the algorithm should separate nodes with different
cluster IDs . |
applyLayoutCore, getCoreLayout, setCoreLayout
public static final EdgeDpKey<Object> EDGE_ID_DPKEY
DataProvider
key for mapping each edge of the input graph to a unique ID.
IDataProvider
has to be specified by the user!public static final IEdgeLabelLayoutDpKey<Object> EDGE_LABEL_ID_DPKEY
DataProvider
key for mapping each edge label of the input graph to a unique ID.
IDataProvider
has to be specified by the user!public static final EdgeDpKey<Object> EDGE_TYPE_DPKEY
DataProvider
key for specifying the type of multi-edges.
If EdgeBundleModeMask
& EdgeBundleModes.DISTINGUISH_TYPES
== 1, multi-edges
(edges with same endpoints) associated with different types (objects) are distinguished, i.e., they are split by
different connector pairs (see NodeType.CONNECTOR
).
public static final NodeDpKey<Object> NODE_CLUSTER_ID_DPKEY
DataProvider
key for assigning a cluster ID to common (non-group) nodes.
IDataProvider
associated with this key, the algorithm assumes that there are no such
preferences.setStrictClusterSeparationEnabled(boolean)
public static final NodeDpKey<Object> NODE_ID_DPKEY
DataProvider
key for mapping each node of the input graph to a unique ID.
IDataProvider
has to be specified by the user!public static final INodeLabelLayoutDpKey<Object> NODE_LABEL_ID_DPKEY
DataProvider
key for mapping each node label of the input graph to a unique ID.
IDataProvider
has to be specified by the user!public MultiPageLayout(ILayoutAlgorithm core)
MultiPageLayout
instance.core
- the layout algorithm used for a single pageprotected void applyIncrementalLayout(LayoutGraph graph, IDataProvider incrementalNodesDP, LayoutContext context)
The marked nodes have to be placed without changing the coordinates of the fixed (non-marked) elements and without exceeding the specified maximum page size. Furthermore, the basic layout properties should be maintained.
Subclasses may implement a custom layout strategy for this step.
graph
- the input graphincrementalNodesDP
- a IDataProvider
that returns a boolean value indicating whether or not a node is marked; the positions of the
non-marked nodes are not allowed to changecontext
- the current layout contextLayoutContext
public void applyLayout(LayoutGraph graph)
This method calls calculateLayout(LayoutGraph)
and notifies the registered layout callback
of the calculated result.
applyLayout
in interface ILayoutAlgorithm
applyLayout
in class AbstractLayoutStage
ILayoutAlgorithm.applyLayout(LayoutGraph)
method, the result of the layout
calculation will not be applied to the input graph.graph
- the input graphpublic MultiPageLayoutResult calculateLayout(LayoutGraph graph)
Unlike method applyLayout(LayoutGraph)
, this method ignores the registered layout callback
and directly returns the calculated MultiPageLayoutResult
.
IllegalArgumentException
- if for one of the keys NODE_ID_DPKEY
, EDGE_ID_DPKEY
, NODE_LABEL_ID_DPKEY
and EDGE_LABEL_ID_DPKEY
no IDataProvider
is registered with the given graphILayoutAlgorithm.applyLayout(LayoutGraph)
method, the result of the layout
calculation will not be applied to the input graph.graph
- the input graphMultiPageLayoutResult
that represents the result of the layout runMultiPageLayoutResult
protected IElementFactory createElementFactory()
element factory
for multi-page layouts.
It is called once from ElementFactory
if no factory has been explicitly set using
ElementFactory
. By default, this method returns an instance of
DefaultElementFactory
.
Subclasses may create a custom implementation of the element factory.
setElementFactory(IElementFactory)
,
getElementFactory()
,
IElementFactory
public EdgeBundleModes getEdgeBundleModeMask()
All multi-edges (edges with same endpoints) belonging to the same edge bundle are split by the same connector pair (see
NodeType.CONNECTOR
).
NodeType.CONNECTOR
,
setEdgeBundleModeMask(EdgeBundleModes)
public IElementFactory getElementFactory()
element factory
for creating special nodes and edges in a multi-page layout.
If no element factory is set explicitly (see method ElementFactory
), a new
instance is created and set by method createElementFactory()
during the first layout run.
DefaultElementFactory
. If no element factory is set explicitly, the algorithm uses an instance of
DefaultElementFactory
.createElementFactory()
,
IElementFactory
,
setElementFactory(IElementFactory)
public GroupingMode getGroupingMode()
IllegalArgumentException
- if the specified group mode is unknownGroupingMode.ALL_NODES
. Special nodes are also assigned to the associated groups.NodeType.CONNECTOR
,
NodeType.PROXY
,
setGroupingMode(GroupingMode)
public ILayoutStage getLabeling()
ILayoutStage
that places the labels of the input graph.ILayoutStage
needs to be activated
in order to take effect.GenericLabeling
. An instance of GenericLabeling
with MaximumDuration
set to 0
.ILayoutStage
instancesetLabelingEnabled(boolean)
,
GenericLabeling
,
setLabeling(ILayoutStage)
public ILayoutCallback getLayoutCallback()
callback
that is notified upon completion of multi-page layout calculation runs.null
. No layout callback is set.ILayoutCallback
instance that is notifiedILayoutCallback
,
setLayoutCallback(ILayoutCallback)
public long getMaximumDuration()
The specified value has to be non-negative.
IllegalArgumentException
- if the preferred time limit is negativeLong.MAX_VALUE
. The layout algorithm runs unrestricted.setMaximumDuration(long)
public YDimension getMaximumPageSize()
The layout algorithm subdivides the input graph such that each part is placed on a different page that fits the specified maximum size.
Both the specified width and height have to be positive.
IllegalArgumentException
- if the specified width or height is not positiveMaximumDuration
.1000
.setMaximumDuration(long)
,
setMaximumPageSize(YDimension)
public boolean isLabelingEnabled()
labeling algorithm
places the labels of the input
graph.
If this option is disabled, the labels are either ignored or placed by the integrated labeling approach of the
core layout algorithm
.
false
. The given labeling algorithm does not place labels.true
if the given label layouter places the labels, false
otherwisesetLabeling(ILayoutStage)
,
setLabelingEnabled(boolean)
public boolean isStrictClusterSeparationEnabled()
cluster IDs
.
More precisely, if this option is enabled, the algorithm doesn't place nodes with different cluster IDs onto the same page. Otherwise, such a placement is possible.
false
. Nodes with different cluster IDs may be placed on the same page.true
if the algorithm separates nodes with different cluster IDs, false
otherwiseNODE_CLUSTER_ID_DPKEY
,
setStrictClusterSeparationEnabled(boolean)
protected boolean removeConnectorPair(Node connector1, Node connector2, YList originalEdgeIds, LayoutContext context)
A pair of connectors can be removed if both connector nodes are placed on the same page. The method removes both
connector nodes and restores the original edges by calling
routeRestoredEdges(LayoutGraph, IDataProvider, YRectangle)
.
Subclasses may implement a custom remove/restore strategy.
false
the graph was not changed, i.e., the connector pair still exists.connector1
- the first connector of the connector pairconnector2
- the second connector of the connector pairoriginalEdgeIds
- the IDs of the original edges that have to be restoredcontext
- the current layout contexttrue
if the removal of the connector pair was successful, false
otherwiserouteRestoredEdges(LayoutGraph, IDataProvider, YRectangle)
protected void routeRestoredEdges(LayoutGraph graph, IDataProvider selectedEdgesDP, YRectangle boundingRectangle)
removeConnectorPair(Node, Node, YList, LayoutContext)
to route the restored edges.
It has to guarantee that the routes are fully contained within the given bounding rectangle.
Subclasses may implement a custom routing strategy for the restored edges.
graph
- the relevant graphselectedEdgesDP
- a IDataProvider
that returns a boolean value indicating whether or not an edge should be reroutedboundingRectangle
- the edge routes should be fully contained within this rectangleremoveConnectorPair(Node, Node, YList, LayoutContext)
public void setEdgeBundleModeMask(EdgeBundleModes value)
All multi-edges (edges with same endpoints) belonging to the same edge bundle are split by the same connector pair (see
NodeType.CONNECTOR
).
value
- the bit mask for defining edge bundlesNodeType.CONNECTOR
,
getEdgeBundleModeMask()
public void setElementFactory(IElementFactory value)
element factory
for creating special nodes and edges in a multi-page layout.
If no element factory is set explicitly (see method ElementFactory
), a new
instance is created and set by method createElementFactory()
during the first layout run.
DefaultElementFactory
. If no element factory is set explicitly, the algorithm uses an instance of
DefaultElementFactory
.value
- the element factory for creating special nodes and edgescreateElementFactory()
,
IElementFactory
,
getElementFactory()
public void setGroupingMode(GroupingMode value)
IllegalArgumentException
- if the specified group mode is unknownGroupingMode.ALL_NODES
. Special nodes are also assigned to the associated groups.value
- the current node grouping specifierNodeType.CONNECTOR
,
NodeType.PROXY
,
getGroupingMode()
public void setLabeling(ILayoutStage value)
ILayoutStage
that places the labels of the input graph.ILayoutStage
needs to be activated
in order to take effect.GenericLabeling
. An instance of GenericLabeling
with MaximumDuration
set to 0
.value
- the ILayoutStage
instancesetLabelingEnabled(boolean)
,
GenericLabeling
,
getLabeling()
public void setLabelingEnabled(boolean value)
labeling algorithm
places the labels of the input
graph.
If this option is disabled, the labels are either ignored or placed by the integrated labeling approach of the
core layout algorithm
.
false
. The given labeling algorithm does not place labels.value
- true
if the given label layouter places the labels, false
otherwisesetLabeling(ILayoutStage)
,
isLabelingEnabled()
public void setLayoutCallback(ILayoutCallback value)
callback
that is notified upon completion of multi-page layout calculation runs.null
. No layout callback is set.value
- the ILayoutCallback
instance that is notifiedILayoutCallback
,
getLayoutCallback()
public void setMaximumDuration(long value)
The specified value has to be non-negative.
IllegalArgumentException
- if the preferred time limit is negativeLong.MAX_VALUE
. The layout algorithm runs unrestricted.value
- the preferred time limitgetMaximumDuration()
public void setMaximumPageSize(YDimension value)
The layout algorithm subdivides the input graph such that each part is placed on a different page that fits the specified maximum size.
Both the specified width and height have to be positive.
IllegalArgumentException
- if the specified width or height is not positiveMaximumDuration
.1000
.value
- the maximum size for a single pagesetMaximumDuration(long)
,
getMaximumPageSize()
public void setStrictClusterSeparationEnabled(boolean value)
cluster IDs
.
More precisely, if this option is enabled, the algorithm doesn't place nodes with different cluster IDs onto the same page. Otherwise, such a placement is possible.
false
. Nodes with different cluster IDs may be placed on the same page.value
- true
if the algorithm separates nodes with different cluster IDs, false
otherwiseNODE_CLUSTER_ID_DPKEY
,
isStrictClusterSeparationEnabled()