createGroupNodeAroundNodes method

GroupNode<T> createGroupNodeAroundNodes({
  1. required String title,
  2. required Set<String> nodeIds,
  3. required T data,
  4. String? id,
  5. EdgeInsets padding = const EdgeInsets.all(20.0),
  6. Color color = const Color(0xFF2196F3),
  7. GroupBehavior behavior = GroupBehavior.bounds,
  8. List<Port> inputPorts = const [],
  9. List<Port> outputPorts = const [],
})

Creates and adds a group node that surrounds the specified nodes.

This is a convenience method that calculates the bounding box of the given nodes and creates a group that encompasses them with padding.

Parameters:

  • title: Display title for the group header
  • nodeIds: Set of node IDs to surround
  • data: Custom data of type T associated with this node
  • id: Optional custom ID (auto-generated if not provided)
  • padding: Space between the group boundary and the nodes (default: 20.0)
  • color: Background color of the group (default: blue)
  • behavior: How the group manages node membership (default: bounds)
  • inputPorts: Optional input ports for subflow patterns
  • outputPorts: Optional output ports for subflow patterns

Returns the created GroupNode.

Example:

controller.createGroupNodeAroundNodes(
  title: 'Input Processing',
  nodeIds: {'node1', 'node2', 'node3'},
  data: MyNodeData(),
  padding: EdgeInsets.all(30),
  color: Colors.blue,
);

Implementation

GroupNode<T> createGroupNodeAroundNodes({
  required String title,
  required Set<String> nodeIds,
  required T data,
  String? id,
  EdgeInsets padding = const EdgeInsets.all(20.0),
  Color color = const Color(0xFF2196F3), // Blue
  GroupBehavior behavior = GroupBehavior.bounds,
  List<Port> inputPorts = const [],
  List<Port> outputPorts = const [],
}) {
  final dependentNodes = nodeIds
      .map((nodeId) => _nodes[nodeId])
      .where((node) => node != null)
      .cast<Node<T>>()
      .toList();

  Offset initialPosition = Offset.zero;
  Size initialSize = const Size(200, 150);

  if (dependentNodes.isNotEmpty) {
    // Calculate bounding box of all dependent nodes
    double minX = double.infinity;
    double minY = double.infinity;
    double maxX = double.negativeInfinity;
    double maxY = double.negativeInfinity;

    for (final node in dependentNodes) {
      final pos = node.visualPosition.value;
      final size = node.size.value;

      minX = math.min(minX, pos.dx);
      minY = math.min(minY, pos.dy);
      maxX = math.max(maxX, pos.dx + size.width);
      maxY = math.max(maxY, pos.dy + size.height);
    }

    // Add padding around the nodes
    minX -= padding.left;
    minY -= padding.top;
    maxX += padding.right;
    maxY += padding.bottom;

    initialPosition = Offset(minX, minY);
    initialSize = Size(maxX - minX, maxY - minY);
  }

  final node = GroupNode<T>(
    id: id ?? 'group-${DateTime.now().millisecondsSinceEpoch}',
    position: initialPosition,
    size: initialSize,
    title: title,
    data: data,
    color: color,
    behavior: behavior,
    nodeIds: behavior != GroupBehavior.bounds ? nodeIds : null,
    padding: padding,
    inputPorts: inputPorts,
    outputPorts: outputPorts,
  );
  addNode(node);
  return node;
}