IO Tree Layout
Input-Output Tree Layout with Bidirectional Flow
Specialized tree layout that automatically adjusts connection points based on relationship direction, clearly showing input-output flows with support for horizontal and vertical orientations.
Functional Overview
This example demonstrates the IO tree layout (Input-Output tree layout), a tree layout algorithm specifically designed to clearly display input-output relationships between nodes. Unlike regular tree layouts, IO tree layout automatically adjusts connection point positions based on relationship direction (from parent to child or from child to parent), making each connection’s flow clearly visible. Supports both horizontal and vertical directions, as well as an option to allow node size changes during layout.
Implementation of Key Features
IO Tree Layout Configuration
Use io-tree layout type:
const graphOptionsH: RGOptions = {
layout: {
layoutName: 'io-tree',
treeNodeGapH: 10,
treeNodeGapV: 10,
from: 'left',
changeNodeSizeDuringLayout
},
defaultNodeWidth: 120,
defaultNodeHeight: 30,
defaultLineShape: RGLineShape.StandardOrthogonal,
defaultJunctionPoint: RGJunctionPoint.lr
};
The changeNodeSizeDuringLayout parameter controls whether the layout engine can adjust node sizes.
Dynamic Junction Point Adjustment
Dynamically set connection point positions based on node level relationships:
const updateLinesJunctionPoint = () => {
graphInstance.getLinks().forEach((link) => {
const lineProps: Partial<JsonLine> = {
text: '',
lineRadius: 13,
lineWidth: 2,
lineShape: 44,
fromJunctionPoint: link.line.fromJunctionPoint,
toJunctionPoint: link.line.toJunctionPoint
};
if (link.fromNode.lot?.level > link.toNode.lot?.level) {
// Connection from higher to lower level
if (treeFrom === 'top') {
lineProps.fromJunctionPoint = RGJunctionPoint.right;
lineProps.toJunctionPoint = changeNodeSizeDuringLayout ? 'horizontalLine' : RGJunctionPoint.bottom;
} else if (treeFrom === 'left') {
lineProps.fromJunctionPoint = RGJunctionPoint.bottom;
lineProps.toJunctionPoint = changeNodeSizeDuringLayout ? 'verticalLine' : RGJunctionPoint.right;
}
} else {
// Connection from lower to higher level
if (treeFrom === 'top') {
lineProps.fromJunctionPoint = changeNodeSizeDuringLayout ? 'horizontalLine' : RGJunctionPoint.bottom;
lineProps.toJunctionPoint = RGJunctionPoint.left;
} else if (treeFrom === 'left') {
lineProps.fromJunctionPoint = changeNodeSizeDuringLayout ? 'verticalLine' : RGJunctionPoint.right;
lineProps.toJunctionPoint = RGJunctionPoint.top;
}
}
graphInstance.updateLine(link.line.id, lineProps);
});
};
This ensures connection lines clearly display regardless of relationship direction.
Using Links Instead of Lines
Use getLinks() instead of getLines() for more information:
graphInstance.getLinks().forEach((link) => {
// link.line provides the line object
// link.fromNode and link.toNode provide source and target node objects
// This makes it easy to compare node levels
});
Links contain both lines and connected node objects, facilitating complex connection logic.
Manual Node Size Update
Manually update node sizes before layout:
graphInstance.getNodes().forEach((node) => {
graphInstance.updateNode(node, {
width: targetOptions.defaultNodeWidth,
height: targetOptions.defaultNodeHeight
});
});
Because default sizes in options don’t affect already added nodes, manual updates are needed.
Wait for Rendering Completion
Wait for browser rendering to complete before re-layout:
await graphInstance.sleep(100); // Wait for node size property modifications to be rendered by browser
await graphInstance.doLayout();
This ensures layout calculations use correct node dimensions.
Direction Switching Support
Support both horizontal (left-to-right) and vertical (top-to-bottom) layout directions:
<SimpleUISelect
data={[
{ value: 'left', text: 'Horizontal Tree' },
{ value: 'top', text: 'Vertical Tree' }
]}
currentValue={layoutFrom}
onChange={(newValue: string) => { setLayoutFrom(newValue); }}
/>
Switching directions automatically recalculates connection points and layout.
Creative Use Cases
Data Flow Visualization
Clearly display data flow direction in systems. For example, showing the complete path from sensors to processing units to storage systems.
Organizational Charts
Display organization reporting relationships, including upward reporting (subordinate to superior) and downward management (superior to subordinate) relationships.
Decision Tree Visualization
Display decision flows in decision trees, including forward decisions and reverse feedback loops, making the entire decision process clearly visible.
Supply Chain Networks
Visualize bidirectional relationships in supply chains, including suppliers to manufacturers (forward) and retailers to distributors (reverse) feedback.
Neural Network Architectures
Display connections between neurons in neural networks, including both forward propagation and backpropagation paths.
Project Dependency Relationships
Display task dependencies in project management, including prerequisite tasks and dependent tasks.
Financial Transaction Flows
Display complete financial transaction flows, including funds flowing in, out, and intermediate processing steps.
Workflow and Approval Processes
Visualize approval processes in workflow systems, clearly showing application submission paths and approval feedback paths.
Energy Flow Diagrams
In energy management systems, display energy production, transmission, and consumption, clearly showing bidirectional energy flows.
Message Passing Systems
Display message flows in distributed systems or message queues, including request and response paths.