Concepts

The task of a layout algorithm is a major undertaking that involves arbitrarily complex logic. However, there can be identified a number of well-defined (sub-)tasks that even completely different algorithms do in a similar manner. Factoring out such tasks so that they can be reused in varying contexts, greatly reduces the complexity of any layout algorithm.

The yFiles library allows to formulate complex layout processes by plugging together so-called "layout stages" that, among other things, can be used to handle such well-defined (sub-)tasks.

The Layout Stages Concept

A layout stage serves as a kind of container that encapsulates arbitrary layout functionality, and provides a general means to string together multiple stages into a compound layout process. Interface ILayoutStage defines the basis for a layout stage. It is a specialization of interface ILayouter, and thus can be used as a stand-alone layout provider as well as a part of a larger layout process.

Figure 5.2. ILayoutStage

ILayoutStage.

The methods of interface ILayoutStage are used to establish a relationship to another ILayouter implementation, the so-called "core layouter." The core layouter's invocation is entirely bracketed by the layout stage's logic.

When used in the context of a larger layout process, the layout stage can easily be used to simplify the core layouter's task. It performs preprocessing steps on the input graph before the core layouter's invocation, and postprocessing steps thereafter.

Table 5.1, “Predefined layout stages” lists some of the predefined ILayoutStage implementations, most of them being part of the default compound layout process as described below. Further layout stages are described in the section called “Layout Stages”.

Table 5.1. Predefined layout stages

Classname Description
SelfLoopLayouter Calculates orthogonal edge paths for a graph's self-loops (reflexive edges).
ParallelEdgeLayouter Calculates edge paths for all edges with identical source node and target node. (Self-loops are not processed.)
OrientationLayouter Changes the orientation of a computed layout.
SubgraphLayouter Reduces the original graph to the subgraph that is induced by selected nodes.

Figure 5.3, “Layout stages complex” shows the class hierarchy for the layout stages.

Figure 5.3. Layout stages complex

Layout stages complex.

Default Compound Layout Process

The most prominent example for a complex layout process can be observed with abstract class CanonicMultiStageLayouter. It is the superclass for the yFiles major layout algorithms, and provides a conveniently configurable layout pipeline for performing preprocessing steps on the input graph before the core layouter's invocation, and postprocessing steps thereafter. The central role of CanonicMultiStageLayouter can also be seen in Figure 5.9, “The yFiles layout algorithms”.

All layout stages from Table 5.1, “Predefined layout stages” are part of the compound layout process defined by CanonicMultiStageLayouter. The following methods of class CanonicMultiStageLayouter can be used for configuring the layout process:

void AppendStage(ILayoutStage stage)
void PrependStage(ILayoutStage stage)
void RemoveStage(ILayoutStage stage)
Description Methods to add and remove individual layout stages.
void EnableOnlyCore()
bool ComponentLayouterEnabled { get; set; }
bool SelfLoopLayouterEnabled { get; set; }
Description Methods and properties for enabling and disabling the predefined layout stages, and also for controlling their enabled state. (Excerpt.)
ILayoutStage ComponentLayouter { get; set; }
ILayoutStage SelfLoopLayouter { get; set; }
Description Properties for predefined layout stages. (Excerpt.)

Providing Supplemental Layout Data

The yFiles layout algorithms support advanced functionality that can take into account even individual information for single graph elements. However, individual setup like, e.g., attaching a preferred edge length to each edge, is beyond the means a graph structure provides. Instead, a data provision scheme is used to provide the individual setup as supplemental information to a layout algorithm.

The supplemental data for the graph elements is bound to the graph using a so-called "data provider key." During layout calculation, the algorithm then retrieves the data provider that contains the data from the graph by using the same key.

Depending on the data provider key, the algorithm expects the returned data provider to hold values of specific type for either nodes or edges of the graph. Example 5.4, “Binding supplemental data (IGraph API)” shows the use of an IMapper as the data provider for an IGraph-based graph. The mapper returns an integral value for each edge indicating the edge's preferred length to the organic layout algorithm.

Example 5.4. Binding supplemental data (IGraph API)

// 'graph' is of type yWorks.yFiles.UI.Model.IGraph.

// Create an implicit IMapper and add it to the mapper registry of the graph
// using a so-called data provider look-up key as its tag.
// The key is then used by the layout algorithm to retrieve the supplemental
// data.
graph.MapperRegistry.AddMapper<IEdge, int>(
    SmartOrganicLayouter.PreferredEdgeLengthDpKey,
    delegate(IEdge e) { return (int)(200 * GetLength(e)); }
);

// Invoke organic layout on the graph.
SmartOrganicLayouter sol = new SmartOrganicLayouter();
graph.ApplyLayout(sol);