Page Up / Page Down in text fields (#107602)
This commit is contained in:
parent
b375b4ac87
commit
563e0a4aae
1
AUTHORS
1
AUTHORS
@ -98,3 +98,4 @@ Elsabe Ros <hello@elsabe.dev>
|
||||
Nguyễn Phúc Lợi <nploi1998@gmail.com>
|
||||
Jingyi Chen <jingyichen@link.cuhk.edu.cn>
|
||||
Junhua Lin <1075209054@qq.com>
|
||||
Tomasz Gucio <tgucio@gmail.com>
|
||||
|
@ -108,10 +108,13 @@ class TextSelectionPoint {
|
||||
/// false. Similarly the [moveNext] method moves the caret to the next line, and
|
||||
/// returns false if the caret is already on the last line.
|
||||
///
|
||||
/// The [moveByOffset] method takes a pixel offset from the current position to move
|
||||
/// the caret up or down.
|
||||
///
|
||||
/// If the underlying paragraph's layout changes, [isValid] becomes false and
|
||||
/// the [VerticalCaretMovementRun] must not be used. The [isValid] property must
|
||||
/// be checked before calling [movePrevious] and [moveNext], or accessing
|
||||
/// [current].
|
||||
/// be checked before calling [movePrevious], [moveNext] and [moveByOffset],
|
||||
/// or accessing [current].
|
||||
class VerticalCaretMovementRun extends Iterator<TextPosition> {
|
||||
VerticalCaretMovementRun._(
|
||||
this._editable,
|
||||
@ -134,8 +137,8 @@ class VerticalCaretMovementRun extends Iterator<TextPosition> {
|
||||
/// A [VerticalCaretMovementRun] run is valid if the underlying text layout
|
||||
/// hasn't changed.
|
||||
///
|
||||
/// The [current] value and the [movePrevious] and [moveNext] methods must not
|
||||
/// be accessed when [isValid] is false.
|
||||
/// The [current] value and the [movePrevious], [moveNext] and [moveByOffset]
|
||||
/// methods must not be accessed when [isValid] is false.
|
||||
bool get isValid {
|
||||
if (!_isValid) {
|
||||
return false;
|
||||
@ -200,6 +203,30 @@ class VerticalCaretMovementRun extends Iterator<TextPosition> {
|
||||
_currentTextPosition = position.value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Move forward or backward by a number of elements determined
|
||||
/// by pixel [offset].
|
||||
///
|
||||
/// If [offset] is negative, move backward; otherwise move forward.
|
||||
///
|
||||
/// Returns true and updates [current] if successful.
|
||||
bool moveByOffset(double offset) {
|
||||
final Offset initialOffset = _currentOffset;
|
||||
if (offset >= 0.0) {
|
||||
while (_currentOffset.dy < initialOffset.dy + offset) {
|
||||
if (!moveNext()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (_currentOffset.dy > initialOffset.dy + offset) {
|
||||
if (!movePrevious()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return initialOffset != _currentOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/// Displays some text in a scrollable container with a potentially blinking
|
||||
|
@ -171,13 +171,13 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
SingleActivator(LogicalKeyboardKey.delete, alt: true, shift: pressShift): const DeleteToLineBreakIntent(forward: true),
|
||||
},
|
||||
|
||||
// Arrow: Move Selection.
|
||||
// Arrow: Move selection.
|
||||
const SingleActivator(LogicalKeyboardKey.arrowLeft): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: true),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowRight): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: true),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowUp): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: true),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowDown): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: true, collapseSelection: true),
|
||||
|
||||
// Shift + Arrow: Extend Selection.
|
||||
// Shift + Arrow: Extend selection.
|
||||
const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: false),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: false),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: false),
|
||||
@ -199,6 +199,14 @@ 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),
|
||||
|
||||
// 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),
|
||||
|
||||
// Shift + Page Up / Down: Extend selection by page.
|
||||
const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false),
|
||||
const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false),
|
||||
|
||||
const SingleActivator(LogicalKeyboardKey.keyX, control: true): const CopySelectionTextIntent.cut(SelectionChangedCause.keyboard),
|
||||
const SingleActivator(LogicalKeyboardKey.keyC, control: true): CopySelectionTextIntent.copy,
|
||||
const SingleActivator(LogicalKeyboardKey.keyV, control: true): const PasteTextIntent(SelectionChangedCause.keyboard),
|
||||
@ -258,10 +266,7 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
// macOS document shortcuts: https://support.apple.com/en-us/HT201236.
|
||||
// The macOS shortcuts uses different word/line modifiers than most other
|
||||
// platforms.
|
||||
static final Map<ShortcutActivator, Intent> _macShortcuts = _iOSShortcuts;
|
||||
|
||||
// There is no complete documentation of iOS shortcuts.
|
||||
static final Map<ShortcutActivator, Intent> _iOSShortcuts = <ShortcutActivator, Intent>{
|
||||
static final Map<ShortcutActivator, Intent> _macShortcuts = <ShortcutActivator, Intent>{
|
||||
for (final bool pressShift in const <bool>[true, false])
|
||||
...<SingleActivator, Intent>{
|
||||
SingleActivator(LogicalKeyboardKey.backspace, shift: pressShift): const DeleteCharacterIntent(forward: false),
|
||||
@ -277,7 +282,7 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
const SingleActivator(LogicalKeyboardKey.arrowUp): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: true),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowDown): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: true, collapseSelection: true),
|
||||
|
||||
// Shift + Arrow: Extend Selection.
|
||||
// Shift + Arrow: Extend selection.
|
||||
const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: false),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: false),
|
||||
const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: false),
|
||||
@ -310,6 +315,9 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: false),
|
||||
const SingleActivator(LogicalKeyboardKey.end, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: true),
|
||||
|
||||
const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false),
|
||||
const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false),
|
||||
|
||||
const SingleActivator(LogicalKeyboardKey.keyX, meta: true): const CopySelectionTextIntent.cut(SelectionChangedCause.keyboard),
|
||||
const SingleActivator(LogicalKeyboardKey.keyC, meta: true): CopySelectionTextIntent.copy,
|
||||
const SingleActivator(LogicalKeyboardKey.keyV, meta: true): const PasteTextIntent(SelectionChangedCause.keyboard),
|
||||
@ -335,6 +343,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
// * Control + shift? + Z
|
||||
};
|
||||
|
||||
// There is no complete documentation of iOS shortcuts: use macOS ones.
|
||||
static final Map<ShortcutActivator, Intent> _iOSShortcuts = _macShortcuts;
|
||||
|
||||
// The following key combinations have no effect on text editing on this
|
||||
// platform:
|
||||
@ -350,6 +360,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
// * Meta + backspace
|
||||
static final Map<ShortcutActivator, Intent> _windowsShortcuts = <ShortcutActivator, Intent>{
|
||||
..._commonShortcuts,
|
||||
const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true),
|
||||
const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true),
|
||||
const SingleActivator(LogicalKeyboardKey.home): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: true, continuesAtWrap: true),
|
||||
const SingleActivator(LogicalKeyboardKey.end): const ExtendSelectionToLineBreakIntent(forward: true, collapseSelection: true, continuesAtWrap: true),
|
||||
const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: false, continuesAtWrap: true),
|
||||
@ -385,7 +397,6 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
const SingleActivator(LogicalKeyboardKey.keyA, meta: true): const DoNothingAndStopPropagationTextIntent(),
|
||||
};
|
||||
|
||||
|
||||
static const Map<ShortcutActivator, Intent> _commonDisablingTextShortcuts = <ShortcutActivator, Intent>{
|
||||
SingleActivator(LogicalKeyboardKey.arrowDown, alt: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.arrowLeft, alt: true): DoNothingAndStopPropagationTextIntent(),
|
||||
@ -407,6 +418,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.pageUp, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.pageDown, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.end, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.home, shift: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.arrowDown): DoNothingAndStopPropagationTextIntent(),
|
||||
@ -417,6 +430,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
|
||||
SingleActivator(LogicalKeyboardKey.arrowRight, control: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.pageUp): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.pageDown): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.end): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.home): DoNothingAndStopPropagationTextIntent(),
|
||||
SingleActivator(LogicalKeyboardKey.end, control: true): DoNothingAndStopPropagationTextIntent(),
|
||||
@ -545,8 +560,8 @@ Intent? intentForMacOSSelector(String selectorName) {
|
||||
// TODO(knopp): Page Up/Down intents are missing (https://github.com/flutter/flutter/pull/105497)
|
||||
'scrollPageUp:': ScrollToDocumentBoundaryIntent(forward: false),
|
||||
'scrollPageDown:': ScrollToDocumentBoundaryIntent(forward: true),
|
||||
'pageUpAndModifySelection': ExpandSelectionToDocumentBoundaryIntent(forward: false),
|
||||
'pageDownAndModifySelection:': ExpandSelectionToDocumentBoundaryIntent(forward: true),
|
||||
'pageUpAndModifySelection:': ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false),
|
||||
'pageDownAndModifySelection:': ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false),
|
||||
|
||||
// Escape key when there's no IME selection popup.
|
||||
'cancelOperation:': DismissIntent(),
|
||||
|
@ -479,6 +479,7 @@ class _DiscreteKeyFrameSimulation extends Simulation {
|
||||
/// | [ExtendSelectionToNextWordBoundaryOrCaretLocationIntent](`collapseSelection: true`) | Collapses the selection to the word boundary before/after the selection's [TextSelection.extent] position, or [TextSelection.base], whichever is closest in the given direction | Moves the caret to the previous/next word boundary. |
|
||||
/// | [ExtendSelectionToLineBreakIntent](`collapseSelection: true`) | Collapses the selection to the start/end of the line at the selection's [TextSelection.extent] position | Moves the caret to the start/end of the current line .|
|
||||
/// | [ExtendSelectionVerticallyToAdjacentLineIntent](`collapseSelection: true`) | Collapses the selection to the position closest to the selection's [TextSelection.extent], on the previous/next adjacent line | Moves the caret to the closest position on the previous/next adjacent line. |
|
||||
/// | [ExtendSelectionVerticallyToAdjacentPageIntent](`collapseSelection: true`) | Collapses the selection to the position closest to the selection's [TextSelection.extent], on the previous/next adjacent page | Moves the caret to the closest position on the previous/next adjacent page. |
|
||||
/// | [ExtendSelectionToDocumentBoundaryIntent](`collapseSelection: true`) | Collapses the selection to the start/end of the document | Moves the caret to the start/end of the document. |
|
||||
///
|
||||
/// #### Intents for Extending the Selection
|
||||
@ -490,6 +491,7 @@ class _DiscreteKeyFrameSimulation extends Simulation {
|
||||
/// | [ExtendSelectionToNextWordBoundaryOrCaretLocationIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the previous/next word boundary, or [TextSelection.base] whichever is closest in the given direction | Moves the selection's [TextSelection.extent] to the previous/next word boundary. |
|
||||
/// | [ExtendSelectionToLineBreakIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the start/end of the line |
|
||||
/// | [ExtendSelectionVerticallyToAdjacentLineIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the closest position on the previous/next adjacent line |
|
||||
/// | [ExtendSelectionVerticallyToAdjacentPageIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the closest position on the previous/next adjacent page |
|
||||
/// | [ExtendSelectionToDocumentBoundaryIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the start/end of the document |
|
||||
/// | [SelectAllTextIntent] | Selects the entire document |
|
||||
///
|
||||
@ -3106,7 +3108,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
||||
// TODO(abarth): Teach RenderEditable about ValueNotifier<TextEditingValue>
|
||||
// to avoid this setState().
|
||||
setState(() { /* We use widget.controller.value in build(). */ });
|
||||
_adjacentLineAction.stopCurrentVerticalRunIfSelectionChanges();
|
||||
_verticalSelectionUpdateAction.stopCurrentVerticalRunIfSelectionChanges();
|
||||
}
|
||||
|
||||
void _handleFocusChanged() {
|
||||
@ -3589,7 +3591,8 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
||||
}
|
||||
late final Action<UpdateSelectionIntent> _updateSelectionAction = CallbackAction<UpdateSelectionIntent>(onInvoke: _updateSelection);
|
||||
|
||||
late final _UpdateTextSelectionToAdjacentLineAction<ExtendSelectionVerticallyToAdjacentLineIntent> _adjacentLineAction = _UpdateTextSelectionToAdjacentLineAction<ExtendSelectionVerticallyToAdjacentLineIntent>(this);
|
||||
late final _UpdateTextSelectionVerticallyAction<DirectionalCaretMovementIntent> _verticalSelectionUpdateAction =
|
||||
_UpdateTextSelectionVerticallyAction<DirectionalCaretMovementIntent>(this);
|
||||
|
||||
void _expandSelectionToDocumentBoundary(ExpandSelectionToDocumentBoundaryIntent intent) {
|
||||
final TextBoundary textBoundary = _documentBoundary(intent);
|
||||
@ -3717,7 +3720,8 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
||||
ExtendSelectionToLineBreakIntent: _makeOverridable(_UpdateTextSelectionAction<ExtendSelectionToLineBreakIntent>(this, true, _linebreak)),
|
||||
ExpandSelectionToLineBreakIntent: _makeOverridable(CallbackAction<ExpandSelectionToLineBreakIntent>(onInvoke: _expandSelectionToLinebreak)),
|
||||
ExpandSelectionToDocumentBoundaryIntent: _makeOverridable(CallbackAction<ExpandSelectionToDocumentBoundaryIntent>(onInvoke: _expandSelectionToDocumentBoundary)),
|
||||
ExtendSelectionVerticallyToAdjacentLineIntent: _makeOverridable(_adjacentLineAction),
|
||||
ExtendSelectionVerticallyToAdjacentLineIntent: _makeOverridable(_verticalSelectionUpdateAction),
|
||||
ExtendSelectionVerticallyToAdjacentPageIntent: _makeOverridable(_verticalSelectionUpdateAction),
|
||||
ExtendSelectionToDocumentBoundaryIntent: _makeOverridable(_UpdateTextSelectionAction<ExtendSelectionToDocumentBoundaryIntent>(this, true, _documentBoundary)),
|
||||
ExtendSelectionToNextWordBoundaryOrCaretLocationIntent: _makeOverridable(_ExtendSelectionOrCaretPositionAction(this, _nextWordBoundary)),
|
||||
ScrollToDocumentBoundaryIntent: _makeOverridable(CallbackAction<ScrollToDocumentBoundaryIntent>(onInvoke: _scrollToDocumentBoundary)),
|
||||
@ -4604,8 +4608,8 @@ class _ExtendSelectionOrCaretPositionAction extends ContextAction<ExtendSelectio
|
||||
bool get isActionEnabled => state.widget.selectionEnabled && state._value.selection.isValid;
|
||||
}
|
||||
|
||||
class _UpdateTextSelectionToAdjacentLineAction<T extends DirectionalCaretMovementIntent> extends ContextAction<T> {
|
||||
_UpdateTextSelectionToAdjacentLineAction(this.state);
|
||||
class _UpdateTextSelectionVerticallyAction<T extends DirectionalCaretMovementIntent> extends ContextAction<T> {
|
||||
_UpdateTextSelectionVerticallyAction(this.state);
|
||||
|
||||
final EditableTextState state;
|
||||
|
||||
@ -4647,10 +4651,12 @@ class _UpdateTextSelectionToAdjacentLineAction<T extends DirectionalCaretMovemen
|
||||
final VerticalCaretMovementRun currentRun = _verticalMovementRun
|
||||
?? state.renderEditable.startVerticalCaretMovement(state.renderEditable.selection!.extent);
|
||||
|
||||
final bool shouldMove = intent.forward ? currentRun.moveNext() : currentRun.movePrevious();
|
||||
final bool shouldMove = intent is ExtendSelectionVerticallyToAdjacentPageIntent
|
||||
? currentRun.moveByOffset((intent.forward ? 1.0 : -1.0) * state.renderEditable.size.height)
|
||||
: intent.forward ? currentRun.moveNext() : currentRun.movePrevious();
|
||||
final TextPosition newExtent = shouldMove
|
||||
? currentRun.current
|
||||
: (intent.forward ? TextPosition(offset: state._value.text.length) : const TextPosition(offset: 0));
|
||||
: intent.forward ? TextPosition(offset: state._value.text.length) : const TextPosition(offset: 0);
|
||||
final TextSelection newSelection = collapseSelection
|
||||
? TextSelection.fromPosition(newExtent)
|
||||
: value.selection.extendTo(newExtent);
|
||||
|
@ -210,6 +210,17 @@ class ExtendSelectionVerticallyToAdjacentLineIntent extends DirectionalCaretMove
|
||||
}) : super(forward, collapseSelection);
|
||||
}
|
||||
|
||||
/// Expands, or moves the current selection from the current
|
||||
/// [TextSelection.extent] position to the closest position on the adjacent
|
||||
/// page.
|
||||
class ExtendSelectionVerticallyToAdjacentPageIntent extends DirectionalCaretMovementIntent {
|
||||
/// Creates an [ExtendSelectionVerticallyToAdjacentPageIntent].
|
||||
const ExtendSelectionVerticallyToAdjacentPageIntent({
|
||||
required bool forward,
|
||||
required bool collapseSelection,
|
||||
}) : super(forward, collapseSelection);
|
||||
}
|
||||
|
||||
/// Extends, or moves the current selection from the current
|
||||
/// [TextSelection.extent] position to the start or the end of the document.
|
||||
///
|
||||
|
@ -121,6 +121,8 @@ void main() {
|
||||
LogicalKeyboardKey.arrowRight,
|
||||
LogicalKeyboardKey.arrowUp,
|
||||
LogicalKeyboardKey.arrowDown,
|
||||
LogicalKeyboardKey.pageUp,
|
||||
LogicalKeyboardKey.pageDown,
|
||||
LogicalKeyboardKey.home,
|
||||
LogicalKeyboardKey.end,
|
||||
];
|
||||
@ -1447,6 +1449,18 @@ void main() {
|
||||
reason: activator.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageUp)) {
|
||||
await sendKeyCombination(tester, activator);
|
||||
await tester.pump();
|
||||
|
||||
expect(controller.text, testText);
|
||||
expect(
|
||||
controller.selection,
|
||||
const TextSelection.collapsed(offset: 0),
|
||||
reason: activator.toString(),
|
||||
);
|
||||
}
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
testWidgets('at end', (WidgetTester tester) async {
|
||||
@ -1465,6 +1479,15 @@ void main() {
|
||||
expect(controller.selection.baseOffset, 72, reason: activator.toString());
|
||||
expect(controller.selection.extentOffset, 72, reason: activator.toString());
|
||||
}
|
||||
|
||||
for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageDown)) {
|
||||
await sendKeyCombination(tester, activator);
|
||||
await tester.pump();
|
||||
|
||||
expect(controller.text, testText);
|
||||
expect(controller.selection.baseOffset, 72, reason: activator.toString());
|
||||
expect(controller.selection.extentOffset, 72, reason: activator.toString());
|
||||
}
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
testWidgets('run', (WidgetTester tester) async {
|
||||
@ -1554,6 +1577,41 @@ void main() {
|
||||
));
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
testWidgets('run with page down/up', (WidgetTester tester) async {
|
||||
controller.text =
|
||||
'aa\n' // 3
|
||||
'a\n' // 3 + 2 = 5
|
||||
'aa\n' // 5 + 3 = 8
|
||||
'aaa\n' // 8 + 4 = 12
|
||||
'${"aaa\n" * 50}'
|
||||
'aaaa';
|
||||
|
||||
controller.selection = const TextSelection.collapsed(offset: 2);
|
||||
await tester.pumpWidget(buildEditableText());
|
||||
|
||||
await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.arrowDown));
|
||||
await tester.pump();
|
||||
expect(controller.selection, const TextSelection.collapsed(
|
||||
offset: 4,
|
||||
affinity: TextAffinity.upstream,
|
||||
));
|
||||
|
||||
await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageDown));
|
||||
await tester.pump();
|
||||
expect(controller.selection, const TextSelection.collapsed(offset: 82));
|
||||
|
||||
await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.arrowUp));
|
||||
await tester.pump();
|
||||
expect(controller.selection, const TextSelection.collapsed(offset: 78));
|
||||
|
||||
await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageUp));
|
||||
await tester.pump();
|
||||
expect(controller.selection, const TextSelection.collapsed(
|
||||
offset: 2,
|
||||
affinity: TextAffinity.upstream,
|
||||
));
|
||||
}, variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{TargetPlatform.iOS, TargetPlatform.macOS})); // intended: on macOS Page Up/Down only scrolls
|
||||
|
||||
testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async {
|
||||
controller.text =
|
||||
'aa\n' // 3
|
||||
|
@ -6164,6 +6164,88 @@ void main() {
|
||||
reason: 'on $platform',
|
||||
);
|
||||
|
||||
// Move down by page.
|
||||
await sendKeys(
|
||||
tester,
|
||||
<LogicalKeyboardKey>[
|
||||
LogicalKeyboardKey.pageDown,
|
||||
],
|
||||
targetPlatform: defaultTargetPlatform,
|
||||
);
|
||||
|
||||
// On macOS, pageDown/Up don't change selection.
|
||||
expect(
|
||||
selection,
|
||||
equals(
|
||||
defaultTargetPlatform == TargetPlatform.macOS
|
||||
|| defaultTargetPlatform == TargetPlatform.iOS
|
||||
? const TextSelection.collapsed(offset: 0)
|
||||
: const TextSelection.collapsed(offset: 55),
|
||||
),
|
||||
reason: 'on $platform',
|
||||
);
|
||||
|
||||
// Move up by page (to start).
|
||||
await sendKeys(
|
||||
tester,
|
||||
<LogicalKeyboardKey>[
|
||||
LogicalKeyboardKey.pageUp,
|
||||
],
|
||||
targetPlatform: defaultTargetPlatform,
|
||||
);
|
||||
|
||||
expect(
|
||||
selection,
|
||||
equals(
|
||||
const TextSelection.collapsed(
|
||||
offset: 0,
|
||||
),
|
||||
),
|
||||
reason: 'on $platform',
|
||||
);
|
||||
|
||||
// Select towards end by page.
|
||||
await sendKeys(
|
||||
tester,
|
||||
<LogicalKeyboardKey>[
|
||||
LogicalKeyboardKey.pageDown,
|
||||
],
|
||||
shift: true,
|
||||
targetPlatform: defaultTargetPlatform,
|
||||
);
|
||||
|
||||
expect(
|
||||
selection,
|
||||
equals(
|
||||
const TextSelection(
|
||||
baseOffset: 0,
|
||||
extentOffset: 55,
|
||||
affinity: TextAffinity.upstream,
|
||||
),
|
||||
),
|
||||
reason: 'on $platform',
|
||||
);
|
||||
|
||||
// Change selection extent towards start by page.
|
||||
await sendKeys(
|
||||
tester,
|
||||
<LogicalKeyboardKey>[
|
||||
LogicalKeyboardKey.pageUp,
|
||||
],
|
||||
shift: true,
|
||||
targetPlatform: defaultTargetPlatform,
|
||||
);
|
||||
|
||||
expect(
|
||||
selection,
|
||||
equals(
|
||||
const TextSelection.collapsed(
|
||||
offset: 0,
|
||||
),
|
||||
),
|
||||
reason: 'on $platform',
|
||||
);
|
||||
|
||||
// Jump forward three words.
|
||||
await sendKeys(
|
||||
tester,
|
||||
|
Loading…
x
Reference in New Issue
Block a user