Graph Widgets
Both OrgChart
and Genogram
extend the BaseGraph
class, sharing a common set of properties, and customization options.
Core Properties
Property | Type | Default | Description |
---|---|---|---|
controller | BaseGraphController<E> | required | Controller that manages the graph data and layout |
builder | Widget Function(NodeBuilderDetails<E>) | required | Builder function for rendering individual nodes |
isDraggable | bool | true | Whether nodes can be dragged |
minScale | double | 0.001 | Minimum zoom scale |
maxScale | double | 5.6 | Maximum zoom scale |
Node Rendering
The builder
property accepts a function that receives NodeBuilderDetails<E>
and returns a widget. This allows for complete customization of each node's appearance.
OrgChart<Employee>(
controller: controller,
builder: (details) {
return Card(
color: details.isBeingDragged ? Colors.lightBlue : Colors.white,
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(details.item.name, style: TextStyle(fontWeight: FontWeight.bold)),
Text(details.item.position),
if (details.level > 1) // Not showing for root nodes
IconButton(
icon: Icon(details.nodesHidden ? Icons.add : Icons.remove),
onPressed: () => details.hideNodes(),
),
],
),
),
);
},
)
NodeBuilderDetails
Property | Type | Description |
---|---|---|
item | E | The data item for this node |
level | int | Depth level of this node (1 = root) |
hideNodes | Function({bool? hide, bool center}) | Function to toggle child visibility |
nodesHidden | bool | Whether this node's children are hidden |
isBeingDragged | bool | Whether this node is being dragged |
isOverlapped | bool | Whether this node is being overlapped by a dragged node |
Node Interaction
Nodes support several interaction modes:
- Drag and Drop: When
isDraggable
is true, users can drag nodes - Long Press: Displays a context menu for the node
- Toggle Children: Through the
hideNodes()
function available in builder callback
Edge Styling
You can customize the appearance of the lines connecting nodes:
OrgChart<Employee>(
// ...other properties
linePaint: Paint()
..color = Colors.blue
..strokeWidth = 2.0
..style = PaintingStyle.stroke,
cornerRadius: 15.0,
arrowStyle: const SolidGraphArrow(),
)
Property | Type | Default | Description |
---|---|---|---|
linePaint | Paint | Black, 0.5px, stroke | Paint object for lines |
cornerRadius | double | 10.0 | Radius for edge corners |
arrowStyle | GraphArrowStyle | SolidGraphArrow() | Style of arrows on lines |
Arrow Styles
The library provides two types of arrow styles:
1. Solid Arrow
// Default solid arrow
arrowStyle: const SolidGraphArrow()
The SolidGraphArrow
style creates a standard, continuous line with solid arrow heads.
2. Dashed Arrow
// Dashed arrow with custom dash pattern
arrowStyle: const DashedGraphArrow(
pattern: [5, 3], // Pattern of [dash length, gap length]
)
The DashedGraphArrow
style creates dashed lines with the following options:
Parameter | Type | Default | Description |
---|---|---|---|
pattern | Iterable<double> | [10, 5] | Alternating dash and gap lengths |
The pattern should contain an even number of values, representing alternating dash and gap lengths. For example:
[10, 5]
creates a 10px dash followed by a 5px gap[5, 2, 15, 3]
creates a 5px dash, 2px gap, 15px dash, 3px gap pattern that is repeated
Interactive Viewer
Both chart widgets use CustomInteractiveViewer
for pan, zoom, and navigation:
Property | Type | Default | Description |
---|---|---|---|
enableZoom | bool | true | Enables pinch to zoom |
enableRotation | bool | false | Enables rotation gestures |
enableFling | bool | true | Enables fling momentum after panning |
enablePan | bool | true | Enables panning/dragging the chart |
enableDoubleTapZoom | bool | true | Enables double-tap to zoom in |
doubleTapZoomFactor | double | 2.0 | Zoom multiplier on double-tap |
constrainBounds | bool | false | If true, prevents scrolling outside chart boundaries |
Keyboard & Accessibility
Both widgets support keyboard navigation for improved accessibility:
OrgChart<Employee>(
// ...other properties
enableKeyboardControls: true,
keyboardPanDistance: 30.0,
keyboardZoomFactor: 1.2,
focusNode: myFocusNode,
)
Property | Type | Default | Description |
---|---|---|---|
enableKeyboardControls | bool | true | Enable arrow key navigation |
keyboardPanDistance | double | 20.0 | Distance moved on each arrow key press |
keyboardZoomFactor | double | 1.1 | Zoom factor for + and - keys |
enableKeyRepeat | bool | true | Auto-repeat when keys are held |
keyRepeatInitialDelay | Duration | 500ms | Delay before key repeat starts |
keyRepeatInterval | Duration | 50ms | Interval between repeats |
invertArrowKeyDirection | bool | false | Inverts direction of arrow key navigation |
animateKeyboardTransitions | bool | true | Animate transitions from keyboard |
keyboardAnimationCurve | Curve | Curves.easeInOut | Animation curve for keyboard transitions |
keyboardAnimationDuration | Duration | 300ms | Duration of keyboard animations |
Context Menu
You can provide custom context menu options for nodes:
OrgChart<Employee>(
// ...other properties
optionsBuilder: (employee) => [
PopupMenuItem(
value: 'edit',
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
),
),
PopupMenuItem(
value: 'delete',
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
),
),
],
onOptionSelect: (employee, value) {
if (value == 'edit') {
// Show edit dialog
} else if (value == 'delete') {
// Show delete confirmation
}
},
)
Animation
Both widgets support animated transitions when node positions change:
Property | Type | Default | Description |
---|---|---|---|
curve | Curve | Curves.elasticOut | Animation curve for position changes |
duration | Duration | 700ms | Duration of node position animations |
Diagram Export
You can export the diagram as an image or PDF using the controller:
// Export as PNG
final Uint8List? pngBytes = await controller.exportAsImage();
if (pngBytes != null) {
// Save PNG bytes to a file or share them
}
// Export as PDF
final pw.Document? pdf = await controller.exportAsPdf();
if (pdf != null) {
// Save PDF or share it
final bytes = await pdf.save();
}
Differences Between Widgets
- OrgChart
- Genogram
The OrgChart
widget specializes in hierarchical structures with a single parent-child relationship. It includes:
onDrop
callback with three parameters: dragged item, target item, and a booleanisTargetSubnode
that helps prevent circular references- Support for collapsing/expanding subtrees
- Built-in level calculation
OrgChart<Employee>(
controller: controller,
builder: nodeBuilder,
onDrop: (dragged, target, isTargetSubnode) {
// Handle reorganization in your data model
if (!isTargetSubnode) {
// Safe to make dragged a child of target
}
},
)
The Genogram
widget specializes in family tree visualization with features for:
onDrop
callback with two parameters: dragged item and target item- Marriage relationships
- Multiple parent connections
- Gender-based styling
- Additional edge configurations for family relationships
Genogram<Person>(
controller: controller,
builder: nodeBuilder,
onDrop: (dragged, target) {
// Handle relationship changes in your data model
},
edgeConfig: GenogramEdgeConfig(
marriageLineWidth: 2.0,
siblingLineColor: Colors.blueGrey,
parentChildLineStyle: ParentChildLineStyle.angular,
),
marriageStatusProvider: (person, spouse) {
// Return marriage status based on data
return person.divorceIds.contains(spouse.id)
? MarriageStatus.divorced
: MarriageStatus.married;
},
)