1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/services.dart';
import 'actions.dart';
/// An [Intent] to send the event straight to the engine.
///
/// See also:
///
/// * [DefaultTextEditingShortcuts], which triggers this [Intent].
class DoNothingAndStopPropagationTextIntent extends Intent {
/// Creates an instance of [DoNothingAndStopPropagationTextIntent].
const DoNothingAndStopPropagationTextIntent();
}
/// A text editing related [Intent] that performs an operation towards a given
/// direction of the current caret location.
abstract class DirectionalTextEditingIntent extends Intent {
/// Creates a [DirectionalTextEditingIntent].
const DirectionalTextEditingIntent(
this.forward,
);
/// Whether the input field, if applicable, should perform the text editing
/// operation from the current caret location towards the end of the document.
///
/// Unless otherwise specified by the recipient of this intent, this parameter
/// uses the logical order of characters in the string to determine the
/// direction, and is not affected by the writing direction of the text.
final bool forward;
}
/// Deletes the character before or after the caret location, based on whether
/// `forward` is true.
///
/// {@template flutter.widgets.TextEditingIntents.logicalOrder}
/// {@endtemplate}
///
/// Typically a text field will not respond to this intent if it has no active
/// caret ([TextSelection.isValid] is false for the current selection).
class DeleteCharacterIntent extends DirectionalTextEditingIntent {
/// Creates a [DeleteCharacterIntent].
const DeleteCharacterIntent({ required bool forward }) : super(forward);
}
/// Deletes from the current caret location to the previous or next word
/// boundary, based on whether `forward` is true.
class DeleteToNextWordBoundaryIntent extends DirectionalTextEditingIntent {
/// Creates a [DeleteToNextWordBoundaryIntent].
const DeleteToNextWordBoundaryIntent({ required bool forward }) : super(forward);
}
/// Deletes from the current caret location to the previous or next soft or hard
/// line break, based on whether `forward` is true.
class DeleteToLineBreakIntent extends DirectionalTextEditingIntent {
/// Creates a [DeleteToLineBreakIntent].
const DeleteToLineBreakIntent({ required bool forward }) : super(forward);
}
/// A [DirectionalTextEditingIntent] that moves the caret or the selection to a
/// new location.
abstract class DirectionalCaretMovementIntent extends DirectionalTextEditingIntent {
/// Creates a [DirectionalCaretMovementIntent].
const DirectionalCaretMovementIntent(
super.forward,
this.collapseSelection,
[
this.collapseAtReversal = false,
this.continuesAtWrap = false,
]
) : assert(!collapseSelection || !collapseAtReversal);
/// Whether this [Intent] should make the selection collapsed (so it becomes a
/// caret), after the movement.
///
/// When [collapseSelection] is false, the input field typically only moves
/// the current [TextSelection.extent] to the new location, while maintains
/// the current [TextSelection.base] location.
///
/// When [collapseSelection] is true, the input field typically should move
/// both the [TextSelection.base] and the [TextSelection.extent] to the new
/// location.
final bool collapseSelection;
/// Whether to collapse the selection when it would otherwise reverse order.
///
/// For example, consider when forward is true and the extent is before the
/// base. If collapseAtReversal is true, then this will cause the selection to
/// collapse at the base. If it's false, then the extent will be placed at the
/// linebreak, reversing the order of base and offset.
///
/// Cannot be true when collapseSelection is true.
final bool collapseAtReversal;
/// Whether or not to continue to the next line at a wordwrap.
///
/// If true, when an [Intent] to go to the beginning/end of a wordwrapped line
/// is received and the selection is already at the beginning/end of the line,
/// then the selection will be moved to the next/previous line. If false, the
/// selection will remain at the wordwrap.
final bool continuesAtWrap;
}
/// Extends, or moves the current selection from the current
/// [TextSelection.extent] position to the previous or the next character
/// boundary.
class ExtendSelectionByCharacterIntent extends DirectionalCaretMovementIntent {
/// Creates an [ExtendSelectionByCharacterIntent].
const ExtendSelectionByCharacterIntent({
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 word
/// boundary.
class ExtendSelectionToNextWordBoundaryIntent extends DirectionalCaretMovementIntent {
/// Creates an [ExtendSelectionToNextWordBoundaryIntent].
const ExtendSelectionToNextWordBoundaryIntent({
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 word
/// boundary, or the [TextSelection.base] position if it's closer in the move
/// direction.
///
/// This [Intent] typically has the same effect as an
/// [ExtendSelectionToNextWordBoundaryIntent], except it collapses the selection
/// when the order of [TextSelection.base] and [TextSelection.extent] would
/// reverse.
///
/// This is typically only used on MacOS.
class ExtendSelectionToNextWordBoundaryOrCaretLocationIntent extends DirectionalTextEditingIntent {
/// Creates an [ExtendSelectionToNextWordBoundaryOrCaretLocationIntent].
const ExtendSelectionToNextWordBoundaryOrCaretLocationIntent({
required bool forward,
}) : super(forward);
}
/// Expands the current selection to the document boundary in the direction
/// given by [forward].
///
/// Unlike [ExpandSelectionToLineBreakIntent], the extent will be moved, which
/// matches the behavior on MacOS.
///
/// See also:
///
/// [ExtendSelectionToDocumentBoundaryIntent], which is similar but always
/// moves the extent.
class ExpandSelectionToDocumentBoundaryIntent extends DirectionalTextEditingIntent {
/// Creates an [ExpandSelectionToDocumentBoundaryIntent].
const ExpandSelectionToDocumentBoundaryIntent({
required bool forward,
}) : super(forward);
}
/// Expands the current selection to the closest line break in the direction
/// given by [forward].
///
/// Either the base or extent can move, whichever is closer to the line break.
/// The selection will never shrink.
///
/// This behavior is common on MacOS.
///
/// See also:
///
/// [ExtendSelectionToLineBreakIntent], which is similar but always moves the
/// extent.
class ExpandSelectionToLineBreakIntent extends DirectionalTextEditingIntent {
/// Creates an [ExpandSelectionToLineBreakIntent].
const ExpandSelectionToLineBreakIntent({
required bool forward,
}) : super(forward);
}
/// Extends, or moves the current selection from the current
/// [TextSelection.extent] position to the closest line break in the direction
/// given by [forward].
///
/// See also:
///
/// [ExpandSelectionToLineBreakIntent], which is similar but always increases
/// the size of the selection.
class ExtendSelectionToLineBreakIntent extends DirectionalCaretMovementIntent {
/// Creates an [ExtendSelectionToLineBreakIntent].
const ExtendSelectionToLineBreakIntent({
required bool forward,
required bool collapseSelection,
bool collapseAtReversal = false,
bool continuesAtWrap = false,
}) : assert(!collapseSelection || !collapseAtReversal),
super(forward, collapseSelection, collapseAtReversal, continuesAtWrap);
}
/// Extends, or moves the current selection from the current
/// [TextSelection.extent] position to the closest position on the adjacent
/// line.
class ExtendSelectionVerticallyToAdjacentLineIntent extends DirectionalCaretMovementIntent {
/// Creates an [ExtendSelectionVerticallyToAdjacentLineIntent].
const ExtendSelectionVerticallyToAdjacentLineIntent({
required bool forward,
required bool collapseSelection,
}) : 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.
///
/// See also:
///
/// [ExtendSelectionToDocumentBoundaryIntent], which is similar but always
/// increases the size of the selection.
class ExtendSelectionToDocumentBoundaryIntent extends DirectionalCaretMovementIntent {
/// Creates an [ExtendSelectionToDocumentBoundaryIntent].
const ExtendSelectionToDocumentBoundaryIntent({
required bool forward,
required bool collapseSelection,
}) : super(forward, collapseSelection);
}
/// Scrolls to the beginning or end of the document depending on the [forward]
/// parameter.
class ScrollToDocumentBoundaryIntent extends DirectionalTextEditingIntent {
/// Creates a [ScrollToDocumentBoundaryIntent].
const ScrollToDocumentBoundaryIntent({
required bool forward,
}) : super(forward);
}
/// An [Intent] to select everything in the field.
class SelectAllTextIntent extends Intent {
/// Creates an instance of [SelectAllTextIntent].
const SelectAllTextIntent(this.cause);
/// {@template flutter.widgets.TextEditingIntents.cause}
/// The [SelectionChangedCause] that triggered the intent.
/// {@endtemplate}
final SelectionChangedCause cause;
}
/// An [Intent] that represents a user interaction that attempts to copy or cut
/// the current selection in the field.
class CopySelectionTextIntent extends Intent {
const CopySelectionTextIntent._(this.cause, this.collapseSelection);
/// Creates an [Intent] that represents a user interaction that attempts to
/// cut the current selection in the field.
const CopySelectionTextIntent.cut(SelectionChangedCause cause) : this._(cause, true);
/// An [Intent] that represents a user interaction that attempts to copy the
/// current selection in the field.
static const CopySelectionTextIntent copy = CopySelectionTextIntent._(SelectionChangedCause.keyboard, false);
/// {@macro flutter.widgets.TextEditingIntents.cause}
final SelectionChangedCause cause;
/// Whether the original text needs to be removed from the input field if the
/// copy action was successful.
final bool collapseSelection;
}
/// An [Intent] to paste text from [Clipboard] to the field.
class PasteTextIntent extends Intent {
/// Creates an instance of [PasteTextIntent].
const PasteTextIntent(this.cause);
/// {@macro flutter.widgets.TextEditingIntents.cause}
final SelectionChangedCause cause;
}
/// An [Intent] that represents a user interaction that attempts to go back to
/// the previous editing state.
class RedoTextIntent extends Intent {
/// Creates a [RedoTextIntent].
const RedoTextIntent(this.cause);
/// {@macro flutter.widgets.TextEditingIntents.cause}
final SelectionChangedCause cause;
}
/// An [Intent] that represents a user interaction that attempts to modify the
/// current [TextEditingValue] in an input field.
class ReplaceTextIntent extends Intent {
/// Creates a [ReplaceTextIntent].
const ReplaceTextIntent(this.currentTextEditingValue, this.replacementText, this.replacementRange, this.cause);
/// The [TextEditingValue] that this [Intent]'s action should perform on.
final TextEditingValue currentTextEditingValue;
/// The text to replace the original text within the [replacementRange] with.
final String replacementText;
/// The range of text in [currentTextEditingValue] that needs to be replaced.
final TextRange replacementRange;
/// {@macro flutter.widgets.TextEditingIntents.cause}
final SelectionChangedCause cause;
}
/// An [Intent] that represents a user interaction that attempts to go back to
/// the previous editing state.
class UndoTextIntent extends Intent {
/// Creates an [UndoTextIntent].
const UndoTextIntent(this.cause);
/// {@macro flutter.widgets.TextEditingIntents.cause}
final SelectionChangedCause cause;
}
/// An [Intent] that represents a user interaction that attempts to change the
/// selection in an input field.
class UpdateSelectionIntent extends Intent {
/// Creates an [UpdateSelectionIntent].
const UpdateSelectionIntent(this.currentTextEditingValue, this.newSelection, this.cause);
/// The [TextEditingValue] that this [Intent]'s action should perform on.
final TextEditingValue currentTextEditingValue;
/// The new [TextSelection] the input field should adopt.
final TextSelection newSelection;
/// {@macro flutter.widgets.TextEditingIntents.cause}
final SelectionChangedCause cause;
}
/// An [Intent] that represents a user interaction that attempts to swap the
/// characters immediately around the cursor.
class TransposeCharactersIntent extends Intent {
/// Creates a [TransposeCharactersIntent].
const TransposeCharactersIntent();
}