VkGraph requires that all nodes that it contains be instances of either the VkNode class or a subclass of VkNode. The VkNode class is responsible for tracking the connectivity, display characteristics, and other features of the nodes. VkNode is a subclass of VkComponent.
The VkNode class provides basic support for interacting with the node widget. Specifically, you can set the string displayed as a label through the VkNode constructor. However, you can create subclasses of VkNode that support any widget type (refer to "Creating Node Subclasses" .)
Basic Node Functionality
This section describes the basic functionality provided of the VkNode class. Most VkNode functions other than the constructor are for use by VkGraph. However, you might use some utility and access functions useful.
Node constructor and destructor
The VkNode constructor has the following two forms:
- VkNode(const char *name, const char *label = NULL)
name is the node's component name (provide unique names for all nodes). label is the label that the node displays when visible in a graph. If you do not provide a label, the node uses the component name as the label. You can optionally provide a pointer to an existing node, which the constructor uses as a parent node for the new node.
For example, the following line of code creates the node state19 with the internal name "state19" and the label "Indiana":
VkNode state19 = new VkNode("state19", "Indiana");
The following line of code creates a new node, city41, as a child of state19. The name of the new node is "city41" and the label is "Terre Haute":
VkNode city41 = new VkNode("city41", state19, "Terre Haute");
Note: The VkNode constructor initializes internal variables, it does not create any widgets. The VkGraph object (of which a VkNode object is a member) can create and destroy node widgets as necessary. The VkGraph object calls the protected member function VkNode::build() when creating a node's widget is necessary. Refer to "Creating Node Subclasses" on page 261 for more detailed information on build().
The VkNode destructor destroys the node's widget if it exists and deallocates all other internal storage.
Node Utility Functions
VkNode maintains a list of child nodes that you can access using the access functions described in "Basic Node Functionality" . By default, the order of the child nodes in this list depends on the order in which you specified the child relationships. The first child node you specify has an index of 0, the second 1, and so on.You can use the VkNode::sortChildren() to sort the immediate child nodes of a node:
The default algorithm used by sortChildren() sorts nodes alphabetically by their internal node names (not their labels).
You can direct VkNode to use a different sort comparison function with VkNode::setSortFunction():
static void setSortFunction(VkNodeSortFunction func)
The type definition of VkNodeSortFunction is:
typedef int (*VkNodeSortFunction)(VkNode *, VkNode *)
The function you provide must be a static function that accepts as arguments two nodes, and returns an integer value less than zero if the first node comes before the second node, zero if the two nodes are equal, and greater than zero if the second node comes before the first node. For example, the following function sorts nodes by their label strings:
- static int sortNodesByLabel(VkNode *one, VkNode *two)
Refer to "Basic Node Functionality" for more detailed information about VkNode::label().
Node Access Functions
VkNode provides a number of access functions for obtaining values associated with a node.
You can retrieve the node's component name using VkNode::name():
char *name() const
You can retrieve the node's label string with VkNode::label():
virtual char *label()
If you did not provide a label string in the node constructor, the value of the label string is the same as the component's name.
You can determine the number of parent and child nodes with VkNode::nParents() and VkNode::nChildren() respectively:
int nParents() const
int nChildren() const
You can retrieve a specific parent or child node using VkNode::parent() and VkNode::child() respectively:
VkNode *parent(int index) const
VkNode *child(int index) const
By default, the order of the parent and child nodes depends on the order in which you specified the parent or child relationships. The first parent node specified has an index of 0, the second 1, and so on. Initially, the child nodes are numbered similarly. However, if you sort the child nodes using the sortChildren() function, the nodes are reordered according to the sort function you used. For example, if you sorted the child nodes alphabetically by component name, the first child node alphabetically has an index of 0, the second 1, and so on.
You can find a particular parent or child node by component name using VkNode::findParent() and VkNode::findChild() respectively:
VkNode *findParent(char *name)
VkNode *findChild(char *name)
These functions return a pointer to the node if found, and NULL if they do not find the node. These functions search only immediate parent or child nodes, not all ancestor or descendent nodes.
Creating Node Subclasses
You can create subclasses of VkNode to extend its features to maintain additional data, or to change the way the node displays itself in a graph:
- Providing access functions for setting and retrieving resources of the default SgIconGadget(3) widget provided by the VkNode base class.
- Using widgets other than the default SgIconGadget(3) widget.
- Creating additional data members and member functions to store application-specific node information.
You have a great deal of flexibility in deciding how to extend the VkNode class. The important restriction that you must keep in mind is that the VkGraph object of which a VkNode object is a member can create and destroy node widgets as needed. Therefore, in your subclass function definitions you cannot assume that your node's widget exists.
The VkGraph object calls a protected member function, VkNode::build(), whenever it needs to create a node's widget. If you want to use the additional features of the default SgIconGadget widget or if you want to use a different widget in you subclass, you must override build():
virtual void build(Widget parent)
If you simply want to use the additional features of the default SgIconGadget widget, you can call VkNode::build() from within your subclass's build() function to create the SgIconGadget widget and set the widget's label. Then, you can perform any additional operations you want. (Consult the SgIconGadget(3) reference page for more information on using this widget.) For example:
void MyNode::build(Widget parent)
// Additional setup...
If you want to use your own widget or widget hierarchy, create the widget(s) using parent as the parent widget, and assign the widget or root of a widget hierarchy to the _baseWidget data member. After creating the _baseWidget, call installDestroyHandler(), as described in "Handling Component Widget Destruction" .
From within a VkNode subclass you can also access the _label data member:
_label contains the node's label string as set by the VkNode constructor.