alignNodes method

void alignNodes(
  1. List<String> nodeIds,
  2. NodeAlignment alignment
)

Aligns multiple nodes according to the specified alignment option.

Requires at least 2 nodes. Calculates alignment based on the bounds of all specified nodes.

Parameters:

  • nodeIds: List of node IDs to align (must contain at least 2 nodes)
  • alignment: The alignment type (top, right, bottom, left, center, horizontalCenter, verticalCenter)

Does nothing if fewer than 2 valid nodes are provided.

Example:

controller.alignNodes(
  ['node1', 'node2', 'node3'],
  NodeAlignment.left,
);

Implementation

void alignNodes(List<String> nodeIds, NodeAlignment alignment) {
  if (nodeIds.length < 2) return;

  final nodes = nodeIds.map((id) => _nodes[id]).whereType<Node<T>>().toList();
  if (nodes.length < 2) return;

  // Calculate proper bounds of all nodes including their sizes
  final bounds = _calculateNodesBounds(nodes);
  if (bounds == null) return;

  // Extract alignment reference points from the bounds
  final leftmost = bounds.left;
  final rightmost = bounds.right;
  final topmost = bounds.top;
  final bottommost = bounds.bottom;
  final centerX = bounds.center.dx;
  final centerY = bounds.center.dy;

  runInAction(() {
    for (final node in nodes) {
      final currentPos = node.position.value;
      double newX = currentPos.dx;
      double newY = currentPos.dy;

      // Determine target position based on alignment
      switch (alignment) {
        case NodeAlignment.left:
          // Align left edges - position.dx should equal leftmost
          newX = leftmost;
          break;
        case NodeAlignment.right:
          // Align right edges - position.dx + width should equal rightmost
          newX = rightmost - node.size.value.width;
          break;
        case NodeAlignment.top:
          // Align top edges - position.dy should equal topmost
          newY = topmost;
          break;
        case NodeAlignment.bottom:
          // Align bottom edges - position.dy + height should equal bottommost
          newY = bottommost - node.size.value.height;
          break;
        case NodeAlignment.center:
          // Align center points on both axes
          newX = centerX - node.size.value.width / 2;
          newY = centerY - node.size.value.height / 2;
          break;
        case NodeAlignment.horizontalCenter:
          // Align center points horizontally only
          newX = centerX - node.size.value.width / 2;
          // Keep original Y position
          break;
        case NodeAlignment.verticalCenter:
          // Align center points vertically only
          newY = centerY - node.size.value.height / 2;
          // Keep original X position
          break;
      }

      final newPosition = Offset(newX, newY);
      node.position.value = newPosition;
      // Update visual position with snapping
      node.setVisualPosition(_config.snapToGridIfEnabled(newPosition));
    }
  });
}