ElementScope class
A unified interaction scope for draggable elements (nodes, annotations, ports).
This widget provides consistent gesture handling and drag lifecycle management across all interactive elements in the node flow editor. It solves the problem of gesture recognizer callbacks not firing when widgets rebuild during drag operations (due to MobX Observer rebuilds).
Key Features
-
StatefulWidget Architecture: The State object persists across widget rebuilds, maintaining drag state even when the parent Observer rebuilds.
-
Local Drag Tracking: Uses
_isDraggingto track whether this widget instance started a drag, preventing duplicate start/end calls. -
Dispose Cleanup: If the widget is removed while dragging (e.g., element deleted),
dispose()ensures proper cleanup by callingonDragEnd. -
Guard Clauses: All drag methods check
_isDraggingstate to prevent invalid operations (double-start, end without start, etc.). -
Pointer ID Tracking: Tracks which pointer started the drag to prevent interference from other pointers (e.g., trackpad taps during mouse drag).
Gesture Handling
Uses RawGestureDetector with NonTrackpadPanGestureRecognizer to:
- Handle mouse/touch drag gestures
- Reject trackpad gestures (allowing them to bubble up for canvas panning)
- Support double-tap and context menu (right-click) gestures
Widget Tree Structure
ElementScope (StatefulWidget)
└── Listener (immediate tap feedback, pointer ID tracking)
└── RawGestureDetector (drag, double-tap, context menu)
└── MouseRegion (cursor, hover callbacks)
└── child (provided by parent)
Example Usage
For element movement (nodes, annotations):
ElementScope(
onDragStart: (_) => controller.startNodeDrag(nodeId),
onDragUpdate: (details) => controller.moveNodeDrag(details.delta),
onDragEnd: (_) => controller.endNodeDrag(),
onTap: () => controller.selectNode(nodeId),
cursor: SystemMouseCursors.grab,
child: NodeVisual(...),
)
For connection creation (ports):
ElementScope(
onDragStart: (details) => controller.startConnection(details.globalPosition),
onDragUpdate: (details) => controller.updateConnection(details.globalPosition),
onDragEnd: (details) => controller.completeConnection(),
dragStartBehavior: DragStartBehavior.down, // Start immediately on pointer down
child: PortVisual(...),
)
See also:
- NodeWidget which uses this for node interactions
- AnnotationWidget which uses this for annotation interactions
- PortWidget which uses this for connection creation
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- ElementScope
Constructors
- ElementScope({Key? key, required Widget child, required void onDragStart(DragStartDetails details), required void onDragUpdate(DragUpdateDetails details), required void onDragEnd(DragEndDetails details), VoidCallback? onDragCancel, bool isDraggable = true, DragStartBehavior dragStartBehavior = DragStartBehavior.start, VoidCallback? onTap, VoidCallback? onDoubleTap, void onContextMenu(Offset globalPosition)?, VoidCallback? onMouseEnter, VoidCallback? onMouseLeave, MouseCursor? cursor, HitTestBehavior hitTestBehavior = HitTestBehavior.opaque})
-
Creates an element scope with the specified interaction callbacks.
const
Properties
- child → Widget
-
The child widget to wrap with interaction handling.
final
- cursor → MouseCursor?
-
The cursor to display when hovering over the element.
final
- dragStartBehavior → DragStartBehavior
-
Determines when a drag gesture formally starts.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- hitTestBehavior → HitTestBehavior
-
How to behave during hit testing.
final
- isDraggable → bool
-
Whether this element can be dragged.
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- onContextMenu → void Function(Offset globalPosition)?
-
Called when the element is right-clicked (context menu).
final
- onDoubleTap → VoidCallback?
-
Called when the element is double-tapped.
final
- onDragCancel → VoidCallback?
-
Called when a drag operation is cancelled.
final
- onDragEnd → void Function(DragEndDetails details)
-
Called when a drag operation ends normally.
final
- onDragStart → void Function(DragStartDetails details)
-
Called when a drag operation starts.
final
- onDragUpdate → void Function(DragUpdateDetails details)
-
Called during drag with update details.
final
- onMouseEnter → VoidCallback?
-
Called when the mouse enters the element bounds.
final
- onMouseLeave → VoidCallback?
-
Called when the mouse leaves the element bounds.
final
- onTap → VoidCallback?
-
Called when the element is tapped.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< ElementScope> -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited