updateSelection method

void updateSelection({
  1. Offset? startPoint,
  2. Rect? rectangle,
  3. List<String>? intersectingNodes,
  4. bool? toggle,
  5. dynamic selectNodes(
    1. List<String>, {
    2. bool toggle,
    })?,
})

Updates selection rectangle state and handles node selection.

This method manages the selection rectangle during drag-selection operations and calls the selectNodes callback with nodes that intersect the rectangle.

The method supports two selection modes:

  • Normal mode: Replaces the current selection with intersecting nodes
  • Toggle mode: Toggles the selection state of intersecting nodes while preventing flicker by only toggling nodes whose intersection state changed

Parameters:

  • startPoint - Starting point of the selection rectangle
  • rectangle - Current bounds of the selection rectangle
  • intersectingNodes - List of node IDs that intersect the rectangle
  • toggle - Whether to toggle selection instead of replacing
  • selectNodes - Callback to select/deselect nodes

Implementation

void updateSelection({
  Offset? startPoint,
  Rect? rectangle,
  List<String>? intersectingNodes,
  bool? toggle,
  Function(List<String>, {bool toggle})? selectNodes,
}) {
  runInAction(() {
    if (startPoint != null) {
      selectionStartPoint.value = startPoint;
    }
    if (rectangle != null) {
      selectionRectangle.value = rectangle;
    }

    // Handle selection logic
    if (intersectingNodes != null && selectNodes != null) {
      final isToggle = toggle ?? false;

      if (isToggle) {
        // Cmd+drag: only toggle nodes that have changed state to prevent flickering
        final currentIntersecting = intersectingNodes.toSet();
        final nodesToToggle = currentIntersecting
            .difference(_previouslyIntersecting.toSet())
            .union(
              _previouslyIntersecting.toSet().difference(currentIntersecting),
            )
            .toList();

        if (nodesToToggle.isNotEmpty) {
          selectNodes(nodesToToggle, toggle: true);
        }

        _previouslyIntersecting = currentIntersecting;
      } else {
        // Shift+drag: replace selection normally
        selectNodes(intersectingNodes, toggle: false);
        _previouslyIntersecting.clear();
      }
    }
  });
}