GroupNode<T> class

A group node that creates a region for containing other nodes.

Group nodes create visual boundaries that can contain nodes. The membership and sizing behavior is determined by behavior:

  • GroupBehavior.bounds: Spatial containment - nodes inside bounds move with group. Group is manually resizable. Nodes can escape by dragging out.

  • GroupBehavior.explicit: Explicit membership - nodes are specified by ID. Group auto-sizes to fit member nodes + padding. Not resizable.

  • GroupBehavior.parent: Parent-child link - nodes specified by ID move with group when dragged. Group is manually resizable. Nodes can be positioned outside group bounds.

Optional Ports for Subflow Patterns

Group nodes can optionally have input/output ports, enabling them to act as subflow containers where the group itself can be connected to other nodes.

Features

  • Manual resizing from 8 handle positions (except for explicit behavior)
  • Customizable title and color
  • When moved, automatically moves contained/linked nodes
  • Typically rendered behind nodes (background layer)
  • Not included in marquee selection (selectable: false)

Example

// Bounds behavior (default) - spatial containment
final regionGroup = GroupNode<String>(
  id: 'region-1',
  position: Offset(100, 100),
  size: Size(400, 300),
  title: 'Processing Region',
  data: 'group-data',
);

// Explicit behavior - auto-sized to fit members
final explicitGroup = GroupNode<String>(
  id: 'explicit-1',
  position: Offset.zero, // Will be computed
  size: Size.zero,       // Will be computed
  title: 'Data Pipeline',
  data: 'pipeline-data',
  behavior: GroupBehavior.explicit,
  nodeIds: {'node-1', 'node-2', 'node-3'},
);
explicitGroup.fitToNodes((id) => controller.nodes[id]);

// Group with ports for subflow connections
final subflowGroup = GroupNode<String>(
  id: 'subflow-1',
  position: Offset(50, 50),
  size: Size(500, 400),
  title: 'Subflow',
  data: 'subflow-data',
  inputPorts: [
    Port(id: 'in-1', name: 'Input', position: PortPosition.left),
  ],
  outputPorts: [
    Port(id: 'out-1', name: 'Output', position: PortPosition.right),
  ],
);
Inheritance
Mixed-in types
Available extensions

Constructors

GroupNode({required String id, required Offset position, required Size size, required String title, required T data, Color color = Colors.blue, GroupBehavior behavior = GroupBehavior.bounds, Set<String>? nodeIds, EdgeInsets padding = kGroupNodeDefaultPadding, int zIndex = -1, bool isVisible = true, bool locked = false, List<Port> inputPorts = const [], List<Port> outputPorts = const []})

Properties

allPorts List<Port>
Gets all ports (input and output combined).
no setterinherited
behavior GroupBehavior
The behavior that determines how this group manages node membership.
no setter
bounds Rect
Gets the bounding rectangle for the group in graph coordinates.
no setter
currentColor Color
The current color value (non-reactive).
no setter
currentSize Size
The current size of the group.
no setter
currentTitle String
The current title value (non-reactive).
no setter
currentZIndex int
Gets the current z-index value.
getter/setter pairinherited
data → T
Custom data associated with this node.
finalinherited
dragging → Observable<bool>
Observable dragging state.
finalinherited
groupContext NodeDragContext<T>?
The current group context, if attached.
no setterinherited
groupedNodeIds Set<String>
The set of node IDs this node is currently grouping.
no setteroverride
hasContext bool
Whether this node has a group context attached.
no setterinherited
hashCode int
The hash code for this object.
no setterinherited
id String
Unique identifier for this node.
finalinherited
inputPorts → ObservableList<Port>
Observable list of input ports for incoming connections.
finalinherited
isDragging bool
Gets the current dragging state.
getter/setter pairinherited
isEditing bool
Gets the current editing state.
getter/setter pairinherited
isEmpty bool
Whether this node is considered empty.
no setteroverride
isGroupable bool
Whether this node actively groups/monitors other nodes.
no setteroverride
isResizable bool
Whether this group can be manually resized.
no setteroverride
isSelected bool
Gets the current selection state.
getter/setter pairinherited
isVisible bool
Gets the current visibility state.
getter/setter pairinherited
layer NodeRenderLayer
Rendering layer for this node.
finalinherited
locked bool
Whether this node is locked from user interactions.
finalinherited
minSize Size
Minimum size constraints for resize operations.
no setteroverride
nodeIds Set<String>
The set of explicitly linked node IDs.
no setter
observableBehavior → Observable<GroupBehavior>
Reactive observable for the group's behavior.
no setter
observableColor → Observable<Color>
Reactive observable for the group's color.
no setter
observableSize → Observable<Size>
Reactive observable for the group's size.
no setter
observableTitle → Observable<String>
Reactive observable for the group's title.
no setter
outputPorts → ObservableList<Port>
Observable list of output ports for outgoing connections.
finalinherited
padding EdgeInsets
Padding around member nodes when computing bounds for GroupBehavior.explicit.
final
position → Observable<Offset>
Observable position of the node in graph coordinates.
finalinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
selectable bool
Whether this node participates in marquee selection.
finalinherited
selected → Observable<bool>
Observable selection state.
finalinherited
shouldRemoveWhenEmpty bool
Whether this node should be removed when it becomes empty.
no setteroverride
size → Observable<Size>
Observable size of the node.
finalinherited
type String
Type classification for this node.
finalinherited
visualPosition → Observable<Offset>
Observable visual position for rendering (may include snap-to-grid).
finalinherited
zIndex → Observable<int>
Observable z-index for stacking order.
finalinherited

Methods

addInputPort(Port port) → void
Adds an input port to the node.
inherited
addNode(String nodeId) → void
Adds a node to the explicit membership.
addOutputPort(Port port) → void
Adds an output port to the node.
inherited
attachContext(NodeDragContext<T> context) → void
Attaches the group context when this node is added to the controller.
inherited
buildWidget(BuildContext context) Widget
Builds the widget for this node.
override
clearNodes() → void
Clears all explicitly linked nodes.
containsPoint(Offset point) bool
Checks if a point is within the node's rectangular bounds.
inherited
containsRect(Rect rect) bool
Checks if a given rectangle is completely contained within this group.
copyWith({String? id, Offset? position, Size? size, String? title, T? data, Color? color, GroupBehavior? behavior, Set<String>? nodeIds, EdgeInsets? padding, int? zIndex, bool? isVisible, bool? locked, List<Port>? inputPorts, List<Port>? outputPorts}) GroupNode<T>
Creates a copy of this group node with optional property overrides.
detachContext() → void
Detaches the group context when this node is removed from the controller.
inherited
dispose() → void
Disposes of resources used by this node.
inherited
findPort(String portId) Port?
Finds a port by ID in either input or output ports.
inherited
fitToNodes(NodeLookup lookup) → void
Recomputes the group's position and size to fit all member nodes.
getBounds() Rect
Gets the node's bounding rectangle.
inherited
getConnectionPoint(String portId, {required Size portSize, NodeShape? shape}) Offset

Available on Node<T>, provided by the NodePortGeometry extension

Gets the connection attachment point for a port in graph coordinates.
getPortCapsuleSide(String portId) CapsuleFlatSide

Available on Node<T>, provided by the NodePortGeometry extension

Gets the capsule flat side orientation for a port.
getPortCenter(String portId, {required Size portSize, NodeShape? shape}) Offset

Available on Node<T>, provided by the NodePortGeometry extension

Gets the visual center of a port in graph coordinates.
getVisualPortOrigin(String portId, {required Size portSize, NodeShape? shape}) Offset

Available on Node<T>, provided by the NodePortGeometry extension

Gets the visual position where a port should be rendered within the node container.
hasNode(String nodeId) bool
Checks if a node is an explicit member of this group.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onChildMoved(String nodeId, Offset newPosition) → void
Called when a child node is moved.
override
onChildrenDeleted(Set<String> nodeIds) → void
Called when child nodes are deleted from the graph.
override
onChildResized(String nodeId, Size newSize) → void
Called when a child node is resized.
override
onContextAttached() → void
Called when the context is attached (on add to graph or load).
override
onContextDetaching() → void
Called before the context is detached.
inherited
onDragEnd() → void
Called when a drag operation ends.
override
onDragMove(Offset delta, NodeDragContext context) → void
Called during a drag operation as the node moves.
override
onDragStart(NodeDragContext context) → void
Called when a drag operation starts on this node.
override
onNodeAdded(String nodeId, Rect nodeBounds) → void
Called when a node is added to the graph.
inherited
onSelectionChanged(Set<String> selectedNodeIds) → void
Called when node selection changes.
inherited
removeInputPort(String portId) bool
Removes an input port by ID.
inherited
removeNode(String nodeId) → void
Removes a node from the explicit membership.
removeOutputPort(String portId) bool
Removes an output port by ID.
inherited
removePort(String portId) bool
Removes a port by ID from either input or output ports.
inherited
resize(ResizeHandle handle, Offset delta) → void
Applies a resize operation based on the handle being dragged.
inherited
setBehavior(GroupBehavior newBehavior, {Set<String>? captureContainedNodes, NodeLookup? nodeLookup, bool clearNodesOnBoundsSwitch = true}) → void
Changes the group's behavior.
setSize(Size newSize) → void
Sets the group's size directly.
override
setVisualPosition(Offset snappedPosition) → void
Updates the visual position based on the actual position and snapping rules.
inherited
toJson(Object? toJsonT(T value)) Map<String, dynamic>
Converts this group node to a JSON map.
override
toString() String
A string representation of this object.
inherited
updateColor(Color newColor) → void
Updates the group's color.
updateInputPort(String portId, Port updatedPort) bool
Updates an existing input port by ID.
inherited
updateOutputPort(String portId, Port updatedPort) bool
Updates an existing output port by ID.
inherited
updatePort(String portId, Port updatedPort) bool
Updates a port by ID in either input or output ports.
inherited
updateTitle(String newTitle) → void
Updates the group's title.

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Methods

fromJsonMap<R>(Map<String, dynamic> json, R fromJsonT(Object? json)) GroupNode<R>
Creates a GroupNode from a JSON map.