startConnectionDrag method

ConnectionValidationResult startConnectionDrag({
  1. required String nodeId,
  2. required String portId,
  3. required bool isOutput,
  4. required Offset startPoint,
  5. required Rect nodeBounds,
  6. Offset? initialScreenPosition,
})

Starts a connection drag from a port.

Call this from PortWidget's GestureDetector.onPanStart.

Parameters:

  • nodeId: The ID of the node containing the port
  • portId: The ID of the port being dragged from
  • isOutput: Whether this is an output port
  • startPoint: The starting point in graph coordinates
  • nodeBounds: The bounds of the source node in graph coordinates

Returns the validation result. Check ConnectionValidationResult.allowed to determine if the drag started successfully.

Implementation

ConnectionValidationResult startConnectionDrag({
  required String nodeId,
  required String portId,
  required bool isOutput,
  required Offset startPoint,
  required Rect nodeBounds,
  Offset? initialScreenPosition,
}) {
  // Validate source port before starting
  final validationResult = canStartConnection(
    nodeId: nodeId,
    portId: portId,
    isOutput: isOutput,
  );
  if (!validationResult.allowed) {
    return validationResult;
  }

  // Fire connection start event
  events.connection?.onConnectStart?.call(nodeId, portId, isOutput);

  // Check if we need to remove existing connections
  // (for ports that don't allow multiple connections)
  final node = getNode(nodeId);
  if (node != null) {
    final port = node.allPorts.where((p) => p.id == portId).firstOrNull;
    if (port != null && !port.multiConnections) {
      // Remove existing connections from this port
      final connectionsToRemove = _connections
          .where(
            (conn) => isOutput
                ? (conn.sourceNodeId == nodeId && conn.sourcePortId == portId)
                : (conn.targetNodeId == nodeId &&
                      conn.targetPortId == portId),
          )
          .toList();
      runInAction(() {
        for (final connection in connectionsToRemove) {
          removeConnection(connection.id);
        }
      });
    }
  }

  // Create temporary connection
  // Use the initial screen position (converted to graph) for initialCurrentPoint
  // to avoid a sudden jump from port position to mouse position on first move.
  // Note: initialScreenPosition is in global coordinates, so we use globalToGraph.
  final initialCurrentPoint = initialScreenPosition != null
      ? globalToGraph(initialScreenPosition)
      : startPoint;

  runInAction(() {
    // Disable panning during connection drag so InteractiveViewer
    // doesn't steal the gesture from PortWidget's GestureDetector
    interaction.panEnabled.value = false;

    // Cursor is handled reactively via Observer in widget MouseRegions
    interaction.temporaryConnection.value = TemporaryConnection(
      startNodeId: nodeId,
      startPortId: portId,
      isStartFromOutput: isOutput,
      startPoint: startPoint,
      initialCurrentPoint: initialCurrentPoint,
      startNodeBounds: nodeBounds,
    );
  });

  return validationResult;
}