|
|
|
@ -47,6 +47,8 @@ const linkPrefixes = [ |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
abstract class EditorState extends State<RawEditor> { |
|
|
|
|
ScrollController get scrollController; |
|
|
|
|
|
|
|
|
|
TextEditingValue getTextEditingValue(); |
|
|
|
|
|
|
|
|
|
void setTextEditingValue(TextEditingValue value); |
|
|
|
@ -62,32 +64,75 @@ abstract class EditorState extends State<RawEditor> { |
|
|
|
|
void requestKeyboard(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Base interface for editable render objects. |
|
|
|
|
abstract class RenderAbstractEditor { |
|
|
|
|
TextSelection selectWordAtPosition(TextPosition position); |
|
|
|
|
|
|
|
|
|
TextSelection selectLineAtPosition(TextPosition position); |
|
|
|
|
|
|
|
|
|
/// Returns preferred line height at specified `position` in text. |
|
|
|
|
double preferredLineHeight(TextPosition position); |
|
|
|
|
|
|
|
|
|
/// Returns [Rect] for caret in local coordinates |
|
|
|
|
/// |
|
|
|
|
/// Useful to enforce visibility of full caret at given position |
|
|
|
|
Rect getLocalRectForCaret(TextPosition position); |
|
|
|
|
|
|
|
|
|
/// Returns the local coordinates of the endpoints of the given selection. |
|
|
|
|
/// |
|
|
|
|
/// If the selection is collapsed (and therefore occupies a single point), the |
|
|
|
|
/// returned list is of length one. Otherwise, the selection is not collapsed |
|
|
|
|
/// and the returned list is of length two. In this case, however, the two |
|
|
|
|
/// points might actually be co-located (e.g., because of a bidirectional |
|
|
|
|
/// selection that contains some text but whose ends meet in the middle). |
|
|
|
|
TextPosition getPositionForOffset(Offset offset); |
|
|
|
|
|
|
|
|
|
List<TextSelectionPoint> getEndpointsForSelection( |
|
|
|
|
TextSelection textSelection); |
|
|
|
|
|
|
|
|
|
/// If [ignorePointer] is false (the default) then this method is called by |
|
|
|
|
/// the internal gesture recognizer's [TapGestureRecognizer.onTapDown] |
|
|
|
|
/// callback. |
|
|
|
|
/// |
|
|
|
|
/// When [ignorePointer] is true, an ancestor widget must respond to tap |
|
|
|
|
/// down events by calling this method. |
|
|
|
|
void handleTapDown(TapDownDetails details); |
|
|
|
|
|
|
|
|
|
/// Selects the set words of a paragraph in a given range of global positions. |
|
|
|
|
/// |
|
|
|
|
/// The first and last endpoints of the selection will always be at the |
|
|
|
|
/// beginning and end of a word respectively. |
|
|
|
|
/// |
|
|
|
|
/// {@macro flutter.rendering.editable.select} |
|
|
|
|
void selectWordsInRange( |
|
|
|
|
Offset from, |
|
|
|
|
Offset to, |
|
|
|
|
SelectionChangedCause cause, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
/// Move the selection to the beginning or end of a word. |
|
|
|
|
/// |
|
|
|
|
/// {@macro flutter.rendering.editable.select} |
|
|
|
|
void selectWordEdge(SelectionChangedCause cause); |
|
|
|
|
|
|
|
|
|
/// Select text between the global positions [from] and [to]. |
|
|
|
|
void selectPositionAt(Offset from, Offset to, SelectionChangedCause cause); |
|
|
|
|
|
|
|
|
|
/// Select a word around the location of the last tap down. |
|
|
|
|
/// |
|
|
|
|
/// {@macro flutter.rendering.editable.select} |
|
|
|
|
void selectWord(SelectionChangedCause cause); |
|
|
|
|
|
|
|
|
|
/// Move selection to the location of the last tap down. |
|
|
|
|
/// |
|
|
|
|
/// {@template flutter.rendering.editable.select} |
|
|
|
|
/// This method is mainly used to translate user inputs in global positions |
|
|
|
|
/// into a [TextSelection]. When used in conjunction with a [EditableText], |
|
|
|
|
/// the selection change is fed back into [TextEditingController.selection]. |
|
|
|
|
/// |
|
|
|
|
/// If you have a [TextEditingController], it's generally easier to |
|
|
|
|
/// programmatically manipulate its `value` or `selection` directly. |
|
|
|
|
/// {@endtemplate} |
|
|
|
|
void selectPosition(SelectionChangedCause cause); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -988,7 +1033,8 @@ class RenderEditor extends RenderEditableContainerBox |
|
|
|
|
|
|
|
|
|
final caretTop = endpoint.point.dy - |
|
|
|
|
child.preferredLineHeight(TextPosition( |
|
|
|
|
offset: selection.extentOffset - child.getContainer().offset)) - |
|
|
|
|
offset: |
|
|
|
|
selection.extentOffset - child.getContainer().documentOffset)) - |
|
|
|
|
kMargin + |
|
|
|
|
offsetInViewport + |
|
|
|
|
scrollBottomInset; |
|
|
|
@ -1005,6 +1051,17 @@ class RenderEditor extends RenderEditableContainerBox |
|
|
|
|
} |
|
|
|
|
return math.max(dy, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
Rect getLocalRectForCaret(TextPosition position) { |
|
|
|
|
final targetChild = childAtPosition(position); |
|
|
|
|
final localPosition = targetChild.globalToLocalPosition(position); |
|
|
|
|
|
|
|
|
|
final childLocalRect = targetChild.getLocalRectForCaret(localPosition); |
|
|
|
|
|
|
|
|
|
final boxParentData = targetChild.parentData as BoxParentData; |
|
|
|
|
return childLocalRect.shift(Offset(0, boxParentData.offset.dy)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class EditableContainerParentData |
|
|
|
|