updateConnectionDrag method
void
updateConnectionDrag({})
Updates a connection drag with the current position.
Call this from PortWidget's GestureDetector.onPanUpdate.
Parameters:
graphPosition: Current pointer position in graph coordinatestargetNodeId: ID of node being hovered (null if none)targetPortId: ID of port being hovered (null if none)targetNodeBounds: Bounds of hovered node (null if none)
Implementation
void updateConnectionDrag({
required Offset graphPosition,
String? targetNodeId,
String? targetPortId,
Rect? targetNodeBounds,
}) {
final temp = interaction.temporaryConnection.value;
if (temp == null) return;
// Validate target port before highlighting
// Only highlight valid connection targets
// Skip custom validation during drag for performance - full validation runs at completion
final isValidTarget =
targetNodeId != null &&
targetPortId != null &&
canConnect(
targetNodeId: targetNodeId,
targetPortId: targetPortId,
skipCustomValidation: true,
).allowed;
// If target is invalid, treat as no target
final validTargetNodeId = isValidTarget ? targetNodeId : null;
final validTargetPortId = isValidTarget ? targetPortId : null;
final validTargetBounds = isValidTarget ? targetNodeBounds : null;
runInAction(() {
// Handle port highlighting when target port changes
final prevNodeId = temp.targetNodeId;
final prevPortId = temp.targetPortId;
final targetChanged =
prevNodeId != validTargetNodeId || prevPortId != validTargetPortId;
if (targetChanged) {
// Reset previous port's highlighted state
if (prevNodeId != null && prevPortId != null) {
final prevNode = _nodes[prevNodeId];
if (prevNode != null) {
final prevPort = prevNode.allPorts
.where((p) => p.id == prevPortId)
.firstOrNull;
prevPort?.highlighted.value = false;
}
}
// Set new port's highlighted state (only if valid target)
if (validTargetNodeId != null && validTargetPortId != null) {
final newNode = _nodes[validTargetNodeId];
if (newNode != null) {
final newPort = newNode.allPorts
.where((p) => p.id == validTargetPortId)
.firstOrNull;
newPort?.highlighted.value = true;
}
}
}
// Update connection endpoint - snap to target port if we have a valid one
if (validTargetNodeId != null && validTargetPortId != null) {
// Snap to the target port's connection point
final targetNode = _nodes[validTargetNodeId];
if (targetNode != null) {
final targetPort = targetNode.allPorts
.where((p) => p.id == validTargetPortId)
.firstOrNull;
if (targetPort != null) {
// Calculate the actual connection point on the target port
assert(
_theme != null,
'Theme must be set for connection operations',
);
final effectivePortSize = _theme!.portTheme.resolveSize(targetPort);
final snapPoint = targetNode.getConnectionPoint(
validTargetPortId,
portSize: effectivePortSize,
shape: nodeShapeBuilder?.call(targetNode),
);
temp.currentPoint = snapPoint;
} else {
temp.currentPoint = graphPosition;
}
} else {
temp.currentPoint = graphPosition;
}
} else {
// No valid target - follow mouse
temp.currentPoint = graphPosition;
}
if (temp.targetNodeId != validTargetNodeId) {
temp.targetNodeId = validTargetNodeId;
}
if (temp.targetPortId != validTargetPortId) {
temp.targetPortId = validTargetPortId;
}
if (temp.targetNodeBounds != validTargetBounds) {
temp.targetNodeBounds = validTargetBounds;
}
});
}