The management of a graph hierarchy is a multi-faceted undertaking that is handled by a small number of classes. Adding support for grouping and nesting to a "flat" graph can easily be achieved with little effort.
Class HierarchyManager
maintains the model that is behind graph hierarchies, and manages all changes
relevant to this model.
Among other things, the HierarchyManager's responsibilities include:
Adding support for both grouping and nesting to a graph is achieved by creating a HierarchyManager object that is associated with a given graph, which is considered the hierarchy's root graph. Example 7.1, “Adding support for grouping and nesting to a graph” demonstrates how to add a HierarchyManager object to a yet "flat" graph, i.e., one that lacks support for grouping or nesting.
There must not be more than one HierarchyManager associated with a given graph.
Example 7.1. Adding support for grouping and nesting to a graph
// 'rootGraph' is of type y.base.Graph2D. // Create a hierarchy manager with the given graph. HierarchyManager hm = new HierarchyManager(rootGraph);
Conceptually, grouped nodes are one level below their containing group node in the graph hierarchy. Technically, however, they are in the same graph as their enclosing group node. Example 7.2, “Grouping nodes” shows the creation of a group node and how to add content to it.
Example 7.2. Grouping nodes
// 'hm' is of type y.view.hierarchy.HierarchyManager. NodeList nl = new NodeList(); nl.add(rootGraph.firstNode()); // Create a new node in the root graph that is a group node. Node groupNode = hm.createGroupNode(rootGraph); // Add a single node to the group. hm.groupSubgraph(nl, groupNode);
Conceptually, a nested graph structure is contained within its folder node. In the graph hierarchy, it is one level below its folder node, and is accordingly called the inner graph of the folder node. Technically, however, a nested graph structure is a proper graph that is stored separately from its parent graph, i.e., the graph where the folder node resides in.
The folder node within the parent graph serves as an anchor for the nested graph structure. This is why a folder node is also called an anchor node sometimes. Example 7.3, “Nesting nodes” shows the creation of a folder node and how to add content to it. Also, extracting a nested graph structure from a folder node is shown, too.
Example 7.3. Nesting nodes
// 'hm' is of type y.view.hierarchy.HierarchyManager. NodeList nl = new NodeList(); nl.add(rootGraph.firstNode()); // Create a new node in the root graph that is a folder node. Node folderNode = hm.createFolderNode(rootGraph); // Add a single node to the folder. hm.foldSubgraph(nl, folderNode); // Count the inner graph's nodes. int innerGraphNodeCount = hm.getInnerGraph(folderNode).N(); // Move the folder node's content up one level back to the parent graph. hm.unfoldSubGraph(hm.getInnerGraph(folderNode), nl);
Whenever the HierarchyManager is asked to populate a folder node, the involved nodes are removed from their original graph and created anew inside the folder node's inner graph.
In a hierarchically organized graph that contains folder nodes, there can also occur edges that connect nodes from inner graphs to nodes from other graphs within the graph hierarchy. Generally, these edges have to be remodeled to connect nodes that are on the same hierarchy level, since an edge whose nodes are in different graphs is not legal.
Remodeling an edge to an inter-edge that represents its original is automatically done by the HierarchyManager. Both edge ends are promoted to the nearest common graph up in the hierarchy that contains all folder nodes of the involved inner graphs.
The HierarchyManager afterwards provides information on the "real" source and target of the inter-edge. See API Excerpt 7.1, “Methods relating to inter-edges” for the methods to get the real source and target of an inter-edge.
The HierarchyManager instance that has been added to a graph is also responsible for maintaining the node visiting order that is used, e.g., for drawing or for hit-testing the graph elements. API Excerpt 7.2, “Methods to control the node visiting order” lists methods that provide a way to affect the node visiting order by changing the order of children of either group node or folder node.
API Excerpt 7.2. Methods to control the node visiting order
// Makes the given node the first child of its parent. void moveToFirst(Node childNode) // Makes the given node the last child of its parent. void moveToLast(Node childNode)
The visiting order that is maintained by class HierarchyManager is not preserved when the hierarchically organized graph is saved to a file.
To preserve the visiting order between file export and import, all
HierarchyManager operations that affect the node order have to be accompanied
by corresponding Graph
operations on the
particular graph (root graph or nested graph).
See Table 7.1, “Corresponding node order methods”.
Table 7.1. Corresponding node order methods
| HierarchyManager | Graph |
|---|---|
| moveToFirst(Node) |
moveToFirst(Node) |
| moveToLast(Node) |
moveToLast(Node) |
Class HierarchyManager offers two different node traversal orders which can be applied to a hierarchically organized graph:
API Excerpt 7.3, “Node traversal methods” lists HierarchyManager's methods for both traversal policies.
API Excerpt 7.3. Node traversal methods
// Node traversal used for drawing. void postTraverse(HierarchyManager.NodeVisitor visitor) void postTraverse(Node rootNode, HierarchyManager.NodeVisitor visitor) // Node traversal used for hit-testing. void preTraverse(HierarchyManager.NodeVisitor visitor) void preTraverse(Node rootNode, HierarchyManager.NodeVisitor visitor)
Pre-traverse is used, e.g., for drawing the nodes of a hierarchically organized graph, since it makes sure that children are drawn atop their parents. Post-traverse on the other hand, is useful for hit-testing the graph elements, since elements atop of others should receive hit events first.
Class
DefaultHierarchyGraphFactory
is
used by HierarchyManager objects to have new graph elements within the
hierarchically organized graph created and properly configured.
The graph factory handles creation of both normal graph elements as well nested
graph structures.
It also creates and configures the corresponding proxy nodes, i.e., either
group nodes or folder nodes.
Nested graph structures created by DefaultHierarchyGraphFactory are of type
Graph2D
, the realizer implementations
taken for group nodes and folder nodes can be controlled using appropriate
methods.
By default, class
GroupNodeRealizer
is used for
both group nodes and folder nodes, since it can render both presentations.
See also the section called “Node Realizers”.
Whenever a new graph is created by this graph factory, it will inherit all listeners that are registered with its parent graph, i.e., all GraphListener, Graph2DListener, and Graph2DSelectionListener references are copied.
To control the creation of graph objects the instance of DefaultGraphFactory that is used can be replaced with a customized factory using the appropriate method of class HierarchyManager.
HierarchyDemo.java is an extensive tutorial demo application that discusses all aspects of graph hierarchies. The README file gives an overview of the application's features and functionality.
|
Copyright ©2004-2008, yWorks GmbH. All rights reserved. |