dragSelectDocumentFromPositionByOffset method
Future<void>
dragSelectDocumentFromPositionByOffset({
- required DocumentPosition from,
- required Offset delta,
- PointerDeviceKind? pointerDeviceKind,
- Finder? superEditorFinder,
Simulates a user drag that begins at the from
DocumentPosition
and drags a delta
amount from that point.
The drag simulation also introduces a very small x and y adjustment to ensure that the drag rectangle never has a zero-width or a zero-height, because such a drag rectangle wouldn't be seen as intersecting any content.
Provide a pointerDeviceKind
to override the device kind used in the gesture.
If pointerDeviceKind
is null
, it defaults to PointerDeviceKind.touch
on mobile, and PointerDeviceKind.mouse on other platforms.
Implementation
Future<void> dragSelectDocumentFromPositionByOffset({
required DocumentPosition from,
required Offset delta,
PointerDeviceKind? pointerDeviceKind,
Finder? superEditorFinder,
}) async {
final documentLayout = _findDocumentLayout(superEditorFinder);
final dragStartRect = documentLayout.getRectForPosition(from)!;
// TODO: use startDragFromPosition to start the drag instead of re-implementing it here
// We select an initial drag offset that sits furthest from the drag
// direction. Dragging recognition waits for a certain amount of drag
// slop before reporting a drag event. It's possible for a pointer or
// finger movement to move outside of a piece of content before the
// drag is ever reported. This results in an unexpected start position
// for the drag. To minimize this likelihood, we select a corner of
// the target content that sits furthest from the drag direction.
late Offset dragStartOffset;
if (delta.dy < 0 || delta.dx < 0) {
if (delta.dx < 0) {
// We're dragging up and left. To capture the content at `from`,
// drag from bottom right.
dragStartOffset = documentLayout.getAncestorOffsetFromDocumentOffset(dragStartRect.bottomRight);
} else {
// We're dragging up and right. To capture the content at `from`,
// drag from bottom left.
dragStartOffset = documentLayout.getAncestorOffsetFromDocumentOffset(dragStartRect.bottomLeft);
}
} else {
if (delta.dx < 0) {
// We're dragging down and left. To capture the content at `from`,
// drag from top right.
dragStartOffset = documentLayout.getAncestorOffsetFromDocumentOffset(dragStartRect.topRight);
} else {
// We're dragging down and right. To capture the content at `from`,
// drag from top left.
dragStartOffset = documentLayout.getAncestorOffsetFromDocumentOffset(dragStartRect.topLeft);
}
}
final deviceKind = pointerDeviceKind ??
(defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.android
? PointerDeviceKind.touch
: PointerDeviceKind.mouse);
// Simulate the drag.
final gesture = await startGesture(dragStartOffset, kind: deviceKind);
// Move slightly so that a "pan start" is reported.
//
// The slight offset moves in both directions so that we're
// guaranteed to have a drag rectangle with a non-zero width and
// a non-zero height. For example, consider a delta of
// Offset(300, 0). Without a slight adjustment, that drag rectangle
// would have a zero height and therefore it wouldn't report any
// content overlap.
await gesture.moveBy(const Offset(2, 2));
// Move by the desired delta.
await gesture.moveBy(delta);
// Release the drag and settle.
await endDocumentDragGesture(gesture);
}