Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Add support for extending selection to paragraph on ctrl + shift + ar…
Browse files Browse the repository at this point in the history
…row up/down on Non-Apple platforms (#120151)

* Add support for extending selection to paragraph on ctrl + shift + arrow up/down for common keyboard actions

* Add ctrl + shift + arrow up/down common text editing shortcuts/actions

* fix analyzer

---------

Co-authored-by: Renzo Olivares <roliv@google.com>
  • Loading branch information
Renzo-Olivares and Renzo Olivares committed Feb 8, 2023
1 parent f94fa7e commit 99b6bd8
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: false, collapseSelection: false),
const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: true, collapseSelection: false),

const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true, control: true): const ExtendSelectionToNextParagraphBoundaryIntent(forward: false, collapseSelection: false),
const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true, control: true): const ExtendSelectionToNextParagraphBoundaryIntent(forward: true, collapseSelection: false),

// Page Up / Down: Move selection by page.
const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true),
const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true),
Expand Down
1 change: 1 addition & 0 deletions packages/flutter/lib/src/widgets/editable_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4424,6 +4424,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
ExtendSelectionByCharacterIntent: _makeOverridable(_UpdateTextSelectionAction<ExtendSelectionByCharacterIntent>(this, _characterBoundary, _moveBeyondTextBoundary, ignoreNonCollapsedSelection: false)),
ExtendSelectionByPageIntent: _makeOverridable(CallbackAction<ExtendSelectionByPageIntent>(onInvoke: _extendSelectionByPage)),
ExtendSelectionToNextWordBoundaryIntent: _makeOverridable(_UpdateTextSelectionAction<ExtendSelectionToNextWordBoundaryIntent>(this, _nextWordBoundary, _moveBeyondTextBoundary, ignoreNonCollapsedSelection: true)),
ExtendSelectionToNextParagraphBoundaryIntent : _makeOverridable(_UpdateTextSelectionAction<ExtendSelectionToNextParagraphBoundaryIntent>(this, _paragraphBoundary, _moveBeyondTextBoundary, ignoreNonCollapsedSelection: true)),
ExtendSelectionToLineBreakIntent: _makeOverridable(_UpdateTextSelectionAction<ExtendSelectionToLineBreakIntent>(this, _linebreak, _moveToTextBoundary, ignoreNonCollapsedSelection: true)),
ExtendSelectionVerticallyToAdjacentLineIntent: _makeOverridable(_verticalSelectionUpdateAction),
ExtendSelectionVerticallyToAdjacentPageIntent: _makeOverridable(_verticalSelectionUpdateAction),
Expand Down
17 changes: 15 additions & 2 deletions packages/flutter/lib/src/widgets/text_editing_intents.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,25 @@ class ExtendSelectionVerticallyToAdjacentPageIntent extends DirectionalCaretMove
}) : super(forward, collapseSelection);
}

/// Extends, or moves the current selection from the current
/// [TextSelection.extent] position to the previous or the next paragraph
/// boundary.
class ExtendSelectionToNextParagraphBoundaryIntent extends DirectionalCaretMovementIntent {
/// Creates an [ExtendSelectionToNextParagraphBoundaryIntent].
const ExtendSelectionToNextParagraphBoundaryIntent({
required bool forward,
required bool collapseSelection,
}) : super(forward, collapseSelection);
}

/// Extends, or moves the current selection from the current
/// [TextSelection.extent] position to the previous or the next paragraph
/// boundary depending on the [forward] parameter.
///
/// This [Intent] collapses the selection when the order of [TextSelection.base]
/// and [TextSelection.extent] would reverse.
/// This [Intent] typically has the same effect as an
/// [ExtendSelectionToNextParagraphBoundaryIntent], except it collapses the selection
/// when the order of [TextSelection.base] and [TextSelection.extent] would
/// reverse.
///
/// This is typically only used on MacOS.
class ExtendSelectionToNextParagraphBoundaryOrCaretLocationIntent extends DirectionalCaretMovementIntent {
Expand Down
57 changes: 42 additions & 15 deletions packages/flutter/test/widgets/editable_text_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6723,7 +6723,7 @@ void main() {
);
expect(controller.text, equals(testText), reason: 'on $platform');

final bool platformCanSelectByParagraph = defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS;
final bool platformIsApple = defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS;
// Move down one paragraph.
await sendKeys(
tester,
Expand All @@ -6738,9 +6738,9 @@ void main() {
expect(
selection,
equals(
TextSelection(
const TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 20 : 10,
extentOffset: 20,
),
),
reason: 'on $platform',
Expand All @@ -6760,9 +6760,9 @@ void main() {
expect(
selection,
equals(
TextSelection(
const TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 36 : 10,
extentOffset: 36,
),
),
reason: 'on $platform',
Expand All @@ -6782,9 +6782,9 @@ void main() {
expect(
selection,
equals(
TextSelection(
const TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 55 : 10,
extentOffset: 55,
),
),
reason: 'on $platform',
Expand All @@ -6804,9 +6804,9 @@ void main() {
expect(
selection,
equals(
TextSelection(
const TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 36 : 10,
extentOffset: 36,
),
),
reason: 'on $platform',
Expand All @@ -6826,15 +6826,16 @@ void main() {
expect(
selection,
equals(
TextSelection(
const TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 20 : 10,
extentOffset: 20,
),
),
reason: 'on $platform',
);

// Move up back to the origin.
// Move up. This will collapse the selection to the origin on Apple platforms, and
// extend to the previous paragraph boundary on other platforms.
await sendKeys(
tester,
<LogicalKeyboardKey>[
Expand All @@ -6850,13 +6851,15 @@ void main() {
equals(
TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 10 : 10,
extentOffset: platformIsApple ? 10 : 0,
),
),
reason: 'on $platform',
);

// Move up, extending the selection backwards to the next paragraph.
// Move up, extending the selection backwards to the previous paragraph on Apple platforms.
// On other platforms this does nothing since our extent is already at 0 from the previous
// set of keys sent.
await sendKeys(
tester,
<LogicalKeyboardKey>[
Expand All @@ -6867,12 +6870,36 @@ void main() {
targetPlatform: defaultTargetPlatform,
);

expect(
selection,
equals(
const TextSelection(
baseOffset: 10,
extentOffset: 0,
),
),
reason: 'on $platform',
);

// Move down, collapsing the selection to the origin on Apple platforms.
// On other platforms this moves the selection's extent to the next paragraph boundary.
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.arrowDown,
],
shift: true,
wordModifier: true,
targetPlatform: defaultTargetPlatform,
);

expect(
selection,
equals(
TextSelection(
baseOffset: 10,
extentOffset: platformCanSelectByParagraph ? 0 : 10,
extentOffset: platformIsApple ? 10 : 20,
affinity: platformIsApple ? TextAffinity.upstream : TextAffinity.downstream,
),
),
reason: 'on $platform',
Expand Down

0 comments on commit 99b6bd8

Please sign in to comment.