From 6b2b2aa57837e464c7f9e67525bf3657ae2c4d4f Mon Sep 17 00:00:00 2001 From: X Code Date: Mon, 27 Dec 2021 18:38:08 -0800 Subject: [PATCH] Add comment --- lib/src/widgets/delegate.dart | 174 +++++++++++++++++++++++++++++++++- lib/src/widgets/editor.dart | 3 +- 2 files changed, 173 insertions(+), 4 deletions(-) diff --git a/lib/src/widgets/delegate.dart b/lib/src/widgets/delegate.dart index 8b98803e..c64d2dab 100644 --- a/lib/src/widgets/delegate.dart +++ b/lib/src/widgets/delegate.dart @@ -18,29 +18,94 @@ abstract class EditorTextSelectionGestureDetectorBuilderDelegate { bool getSelectionEnabled(); } +/// Builds a [EditorTextSelectionGestureDetector] to wrap an [EditableText]. +/// +/// The class implements sensible defaults for many user interactions +/// with an [EditableText] (see the documentation of the various gesture handler +/// methods, e.g. [onTapDown], [onForcePressStart], etc.). Subclasses of +/// [EditorTextSelectionGestureDetectorBuilder] can change the behavior +/// performed in responds to these gesture events by overriding +/// the corresponding handler methods of this class. +/// +/// The resulting [EditorTextSelectionGestureDetector] to wrap an [EditableText] +/// is obtained by calling [buildGestureDetector]. +/// +/// See also: +/// +/// * [TextField], which uses a subclass to implement the Material-specific +/// gesture logic of an [EditableText]. +/// * [CupertinoTextField], which uses a subclass to implement the +/// Cupertino-specific gesture logic of an [EditableText]. class EditorTextSelectionGestureDetectorBuilder { - EditorTextSelectionGestureDetectorBuilder(this.delegate); + /// Creates a [EditorTextSelectionGestureDetectorBuilder]. + /// + /// The [delegate] must not be null. + EditorTextSelectionGestureDetectorBuilder({required this.delegate}); + /// The delegate for this [EditorTextSelectionGestureDetectorBuilder]. + /// + /// The delegate provides the builder with information about what actions can + /// currently be performed on the textfield. Based on this, the builder adds + /// the correct gesture handlers to the gesture detector. + @protected final EditorTextSelectionGestureDetectorBuilderDelegate delegate; + + /// Whether to show the selection toolbar. + /// + /// It is based on the signal source when a [onTapDown] is called. This getter + /// will return true if current [onTapDown] event is triggered by a touch or + /// a stylus. bool shouldShowSelectionToolbar = true; + /// The [State] of the [EditableText] for which the builder will provide a + /// [EditorTextSelectionGestureDetector]. + @protected EditorState? getEditor() { return delegate.getEditableTextKey().currentState; } + /// The [RenderObject] of the [EditableText] for which the builder will + /// provide a [EditorTextSelectionGestureDetector]. + @protected RenderEditor? getRenderEditor() { return getEditor()!.getRenderEditor(); } + /// Handler for [EditorTextSelectionGestureDetector.onTapDown]. + /// + /// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets + /// [shouldShowSelectionToolbar] to true if the tap was initiated by a finger + /// or stylus. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onTapDown], + /// which triggers this callback. + @protected void onTapDown(TapDownDetails details) { getRenderEditor()!.handleTapDown(details); - + // The selection overlay should only be shown when the user is interacting + // through a touch screen (via either a finger or a stylus). + // A mouse shouldn't trigger the selection overlay. + // For backwards-compatibility, we treat a null kind the same as touch. final kind = details.kind; shouldShowSelectionToolbar = kind == null || kind == PointerDeviceKind.touch || kind == PointerDeviceKind.stylus; } + /// Handler for [EditorTextSelectionGestureDetector.onForcePressStart]. + /// + /// By default, it selects the word at the position of the force press, + /// if selection is enabled. + /// + /// This callback is only applicable when force press is enabled. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onForcePressStart], + /// which triggers this callback. + @protected void onForcePressStart(ForcePressDetails details) { assert(delegate.getForcePressEnabled()); shouldShowSelectionToolbar = true; @@ -53,6 +118,18 @@ class EditorTextSelectionGestureDetectorBuilder { } } + /// Handler for [EditorTextSelectionGestureDetector.onForcePressEnd]. + /// + /// By default, it selects words in the range specified in [details] and shows + /// toolbar if it is necessary. + /// + /// This callback is only applicable when force press is enabled. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onForcePressEnd], + /// which triggers this callback. + @protected void onForcePressEnd(ForcePressDetails details) { assert(delegate.getForcePressEnabled()); getRenderEditor()!.selectWordsInRange( @@ -65,14 +142,44 @@ class EditorTextSelectionGestureDetectorBuilder { } } + /// Handler for [EditorTextSelectionGestureDetector.onSingleTapUp]. + /// + /// By default, it selects word edge if selection is enabled. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onSingleTapUp], which triggers + /// this callback. + @protected void onSingleTapUp(TapUpDetails details) { if (delegate.getSelectionEnabled()) { getRenderEditor()!.selectWordEdge(SelectionChangedCause.tap); } } - void onSingleTapCancel() {} + /// Handler for [EditorTextSelectionGestureDetector.onSingleTapCancel]. + /// + /// By default, it services as place holder to enable subclass override. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onSingleTapCancel], which triggers + /// this callback. + @protected + void onSingleTapCancel() { + /* Subclass should override this method if needed. */ + } + /// Handler for [EditorTextSelectionGestureDetector.onSingleLongTapStart]. + /// + /// By default, it selects text position specified in [details] if selection + /// is enabled. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onSingleLongTapStart], + /// which triggers this callback. + @protected void onSingleLongTapStart(LongPressStartDetails details) { if (delegate.getSelectionEnabled()) { getRenderEditor()!.selectPositionAt( @@ -82,6 +189,16 @@ class EditorTextSelectionGestureDetectorBuilder { } } + /// Handler for [EditorTextSelectionGestureDetector.onSingleLongTapMoveUpdate] + /// + /// By default, it updates the selection location specified in [details] if + /// selection is enabled. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onSingleLongTapMoveUpdate], which + /// triggers this callback. + @protected void onSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) { if (delegate.getSelectionEnabled()) { getRenderEditor()!.selectPositionAt( @@ -91,12 +208,31 @@ class EditorTextSelectionGestureDetectorBuilder { } } + /// Handler for [EditorTextSelectionGestureDetector.onSingleLongTapEnd]. + /// + /// By default, it shows toolbar if necessary. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onSingleLongTapEnd], + /// which triggers this callback. + @protected void onSingleLongTapEnd(LongPressEndDetails details) { if (shouldShowSelectionToolbar) { getEditor()!.showToolbar(); } } + /// Handler for [EditorTextSelectionGestureDetector.onDoubleTapDown]. + /// + /// By default, it selects a word through [RenderEditable.selectWord] if + /// selectionEnabled and shows toolbar if necessary. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onDoubleTapDown], + /// which triggers this callback. + @protected void onDoubleTapDown(TapDownDetails details) { if (delegate.getSelectionEnabled()) { getRenderEditor()!.selectWord(SelectionChangedCause.tap); @@ -106,20 +242,52 @@ class EditorTextSelectionGestureDetectorBuilder { } } + /// Handler for [EditorTextSelectionGestureDetector.onDragSelectionStart]. + /// + /// By default, it selects a text position specified in [details]. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onDragSelectionStart], + /// which triggers this callback. + @protected void onDragSelectionStart(DragStartDetails details) { getRenderEditor()!.handleDragStart(details); } + /// Handler for [EditorTextSelectionGestureDetector.onDragSelectionUpdate]. + /// + /// By default, it updates the selection location specified in the provided + /// details objects. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onDragSelectionUpdate], + /// which triggers this callback./lib/src/material/text_field.dart + @protected void onDragSelectionUpdate( DragStartDetails startDetails, DragUpdateDetails updateDetails) { getRenderEditor()!.extendSelection(updateDetails.globalPosition, cause: SelectionChangedCause.drag); } + /// Handler for [EditorTextSelectionGestureDetector.onDragSelectionEnd]. + /// + /// By default, it services as place holder to enable subclass override. + /// + /// See also: + /// + /// * [EditorTextSelectionGestureDetector.onDragSelectionEnd], + /// which triggers this callback. + @protected void onDragSelectionEnd(DragEndDetails details) { getRenderEditor()!.handleDragEnd(details); } + /// Returns a [EditorTextSelectionGestureDetector] configured with + /// the handlers provided by this builder. + /// + /// The [child] or its subtree should contain [EditableText]. Widget build(HitTestBehavior behavior, Widget child) { return EditorTextSelectionGestureDetector( onTapDown: onTapDown, diff --git a/lib/src/widgets/editor.dart b/lib/src/widgets/editor.dart index b55047ae..41317604 100644 --- a/lib/src/widgets/editor.dart +++ b/lib/src/widgets/editor.dart @@ -463,7 +463,8 @@ class _QuillEditorState extends State class _QuillEditorSelectionGestureDetectorBuilder extends EditorTextSelectionGestureDetectorBuilder { - _QuillEditorSelectionGestureDetectorBuilder(this._state) : super(_state); + _QuillEditorSelectionGestureDetectorBuilder(this._state) + : super(delegate: _state); final _QuillEditorState _state;