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 Layouter 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 5.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 5.19. Data provider look-up keys

Key Element Type Value Type Description
LAYOUT_NODE_DPKEY node Boolean For each node a boolean value indicating whether it should be layouted or not.
GIVEN_COMPONENT_ID_DPKEY node Object For each node an arbitrary Object indicating the component it is affiliated with.
NODE_HALO_DPKEY node NodeHalo A NodeHalo object that specifies the halo sizes at each side of a node.
ABORT_HANDLER_DPKEY 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
style:int
Description Specifies the style for arranging the components of a graph.

The component arrangement style can be set as follows:

Example 5.13. Setting a component arrangement style

var sol:SmartOrganicLayouter = new SmartOrganicLayouter();
var cl:ComponentLayouter = sol.componentLayouter as ComponentLayouter;

// Set another arrangement style instead of the default
// ComponentLayouter.STYLE_ROWS.
cl.style = ComponentLayouter.STYLE_PACKED_COMPACT_RECTANGLE;

// Invoke layout with component arrangement.
CopiedLayoutIGraph.applyLayout(graph, sol);
Arranging Components
API
componentArrangement:Boolean
Description Determines whether the separate components should be arranged or not. By default, component arrangement is enabled.
Component Spacing
API
componentSpacing:Number
Description Defines the minimum distance between the bounding boxes of adjacent components.
Grid Spacing
API
gridSpacing:Number
Description Defines the spacing of the grid on which the separate components are placed.
Label Awareness
API
labelAwareness:Boolean
Description Determines whether node and edge labels are taken into account when computing the bounding boxes of components.
Preferred Layout Size
API
setPreferredLayoutSize(width:Number, height:Number):void
Description Defines the preferred size of the layout.
Support for Grouped Graphs
API
groupingActive:Boolean
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 NODE_HALO_DPKEY.

Advanced Layout Techniques

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

// 'graph' is of type com.yworks.graph.model.IGraph.

// Get a graph instance that the analysis algorithm can work with.
var graphAdapter:YGraphAdapter = new YGraphAdapter(graph);
var components:Vector.<Object> =
    GraphConnectivity.connectedComponents(graphAdapter.yGraph);

// Create an IMapper to hold boolean values indicating whether a component
// should be considered for layout calculation.
var nm:IMapper = new DictionaryMapper();

// 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 (var i:int = 0; i < components.length; i += 2) {
  nm.mapValue(graphAdapter.getOriginalNode(NodeList(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.LAYOUT_NODE_DPKEY, nm);

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

Figure 5.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 5.15, “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 5.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 5.15. Using different layout algorithms for components (IGraph API)

// 'graph' is of type com.yworks.graph.model.IGraph.

// Get a graph instance that the analysis algorithm can work with.
var graphAdapter:YGraphAdapter = new YGraphAdapter(graph);
var components:Vector.<Object> =
    GraphConnectivity.connectedComponents(graphAdapter.yGraph);

// Create an IMapper to hold an Layouter implementation for each of the
// components. This layouter will be used for layout calculation.
var nm:IMapper = new DictionaryMapper();

// 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
// Layouter it can retrieve from the data provider.)
var coreLayouter:Array = new Array(new IncrementalHierarchicLayouter(),
                                   new SmartOrganicLayouter(),
                                   new OrthogonalLayouter());
for (var i:int = 0; i < components.length; i++) {
  nm.mapValue(graphAdapter.getOriginalNode(NodeList(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.LAYOUTER_DPKEY, 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.
var cl:ComponentLayouter = new ComponentLayouter();
cl.coreLayouter = new LayoutMultiplexer();
CopiedLayoutIGraph.applyLayout(graph, cl);