dragSelectDocumentFromPositionByOffset method

Future<void> dragSelectDocumentFromPositionByOffset({
  1. required DocumentPosition from,
  2. required Offset delta,
  3. Finder? superReaderFinder,
})

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.

Implementation

Future<void> dragSelectDocumentFromPositionByOffset({
  required DocumentPosition from,
  required Offset delta,
  Finder? superReaderFinder,
}) async {
  final documentLayout = _findDocumentLayout(superReaderFinder);

  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);
    }
  }

  // Simulate the drag.
  final gesture = await startGesture(dragStartOffset, kind: PointerDeviceKind.mouse);

  // 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);
}