Class ComponentLayouter

Class ComponentLayouter provides services for arranging the connected components of a graph. When invoked, it calls its core layouter on each of the input graph's components. After the core layouter has successively performed its layout processes, ComponentLayouter regains control and arranges the separate components.

Using ComponentLayouter's services with a given ILayouter implementation as its core layouter, has several benefits:

Supplemental Layout Data

Class ComponentLayouter knows a number of data provider keys which are used to retrieve supplemental layout data for a graph's elements. The data is bound to the graph by means of a data provider, which is registered using a given look-up key. Table 10.19, “Data provider look-up keys” lists all look-up keys for ComponentLayouter.

Binding supplemental layout data to a graph is described in the section called “Providing Supplemental Layout Data”.

Table 10.19. Data provider look-up keys

Key Element Type Value Type Description
LayoutNodeDpKey node bool For each node a boolean value indicating whether it should be layouted or not.
GivenComponentDpKey node object For each node an arbitrary object indicating the component it is affiliated with.
NodeHaloDpKey node NodeHalo A NodeHalo object that specifies the halo sizes at each side of a node.
AbortHandlerDpKey graph AbortHandler An AbortHandler instance that will be queried by the layout algorithm to determine whether layout calculation shall be terminated.

Layout Options

Class ComponentLayouter provides a set of options that affect its behavior.

Component Arrangement Style
API
ComponentArrangementStyles Style { get; set; }
Description Specifies the style for arranging the components of a graph.

The component arrangement style can be set as follows:

Example 10.14. Setting a component arrangement style

SmartOrganicLayouter sol = new SmartOrganicLayouter();
ComponentLayouter cl = sol.ComponentLayouter as ComponentLayouter;

// Set another arrangement style instead of the default
// ComponentArrangementStyles.Rows.
cl.Style = ComponentArrangementStyles.PackedCompactRectangle;

// Invoke layout with component arrangement.
graph.ApplyLayout(sol);
Arranging Components
API
bool ComponentArrangement { get; set; }
Description Determines whether the separate components should be arranged or not. By default, component arrangement is enabled.
Component Spacing
API
double ComponentSpacing { get; set; }
Description Defines the minimum distance between the bounding boxes of adjacent components.
Grid Spacing
API
double GridSpacing { get; set; }
Description Defines the spacing of the grid on which the separate components are placed.
Label Awareness
API
bool LabelAwareness { get; set; }
Description Determines whether node and edge labels are taken into account when computing the bounding boxes of components.
Preferred Layout Size
API
void SetPreferredLayoutSize(double width, double height)
Description Defines the preferred size of the layout.
Support for Grouped Graphs
API
bool GroupingActive { get; set; }
Description Specifies whether the grouped graph's hierarchy of nodes is taken into account when determining its components.

In addition to these options, ComponentLayouter by default also supports node halos as soon as they are declared using the data provider key NodeHaloDpKey.

Advanced Layout Techniques

Class ComponentLayouter offers the possibility to call the core layouter only on a subset of the graph's components, effectively excluding the coset of components from layout calculation. This technique is presented in the following code example:

Example 10.15. Excluding components from layout calculation (IGraph API)

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

// Get a graph instance that the analysis algorithm can work with.
YGraphAdapter graphAdapter = new YGraphAdapter(graph);
NodeList[] components =
    GraphConnectivity.ConnectedComponents(graphAdapter.YGraph);

// Create an IMapper to hold boolean values indicating whether a component
// should be considered for layout calculation.
IMapper<INode, bool> nm = new DictionaryMapper<INode, bool>();

// Every second component of the graph is marked so that a layout is calculated
// for it. The other components, while being arranged nevertheless, are not
// considered for layout calculation.
for (int i = 0; i < components.Length; i += 2) {
  nm[graphAdapter.GetOriginalNode(components[i].FirstNode())] = true;
}

// Add the mapper to the mapper registry of the graph.
// Use the "well-known" look-up key defined in class ComponentLayouter as tag.
graph.MapperRegistry.AddMapper(ComponentLayouter.LayoutNodeDpKey, nm);

// The default ComponentLayouter stage of SmartOrganicLayouter arranges all
// components.
graph.ApplyLayout(new SmartOrganicLayouter());

Figure 10.8, “Using ComponentLayouter in conjunction with LayoutMultiplexer” presents the resulting layout when different layout algorithms are invoked for the separate components of a graph using ComponentLayouter in conjunction with class LayoutMultiplexer as outlined in Example 10.16, “Using different layout algorithms for components (IGraph API)”. Each of the three components shows another layout style: hierarchical, organic, and orthogonal layout (from left to right). Arrangement of the components in a row has been done by ComponentLayouter.

Figure 10.8. Using ComponentLayouter in conjunction with LayoutMultiplexer

Using ComponentLayouter in conjunction with LayoutMultiplexer
A single graph that has three separate components, each showing another layout style.

Example 10.16. Using different layout algorithms for components (IGraph API)

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

// Get a graph instance that the analysis algorithm can work with.
YGraphAdapter graphAdapter = new YGraphAdapter(graph);
NodeList[] components =
    GraphConnectivity.ConnectedComponents(graphAdapter.YGraph);

// Create an IMapper to hold an ILayouter implementation for each of the
// components. This layouter will be used for layout calculation.
IMapper<INode, ILayouter> nm = new DictionaryMapper<INode, ILayouter>();

// For each component one of the layouters is set. (Actually, a layouter is set
// for the component's first node only. Nevertheless, this layouter is used for
// the entire component, since LayoutMultiplexer takes the first non-null
// ILayouter it can retrieve from the data provider.)
ILayouter[] coreLayouter = { new IncrementalHierarchicLayouter(),
                             new SmartOrganicLayouter(),
                             new OrthogonalLayouter() };
for (int i = 0; i < components.Length; i++) {
  nm[graphAdapter.GetOriginalNode(components[i].FirstNode())] =
      coreLayouter[i % 3];
}

// Add the mapper to the mapper registry of the graph.
// Use the "well-known" look-up key defined in class LayoutMultiplexer as tag.
graph.MapperRegistry.AddMapper(LayoutMultiplexer.LayouterDpKey, nm);

// ComponentLayouter uses LayoutMultiplexer as its core layouter, which, for
// each component, invokes the layouter retrieved from the data provider
// registered with the graph.
// Afterwards, the ComponentLayouter nicely arranges the components.
ComponentLayouter cl = new ComponentLayouter();
cl.CoreLayouter = new LayoutMultiplexer();
graph.ApplyLayout(cl);

Tutorial Demo Code

The layout module class ComponentLayoutModule.cs from the LayoutModulesWindow demo application presents the setup of class ComponentLayouter in an application context.