Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
angelosilvestre committed Nov 23, 2024
1 parent 5abdfd6 commit f11f566
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,29 @@ class SuperEditorAndroidControlsController {
}
}

/// {@template are_selection_handles_allowed}
/// Whether or not the selection handles are allowed to be displayed.
///
/// Typically, whenever the selection changes the drag handles are displayed. However,
/// there are some cases where we want to select some content, but don't show the
/// drag handles. For example, when the user taps a misspelled word, we might want to select
/// the misspelled word without showing any handles.
///
/// Defaults to `true`.
/// {@endtemplate}
ValueListenable<bool> get areSelectionHandlesAllowed => _areSelectionHandlesAllowed;
final _areSelectionHandlesAllowed = ValueNotifier<bool>(true);

/// Temporarily prevents any selection handles from being displayed.
///
/// Call this when you want to select some content, but don't want to show the drag handles.
/// [allowSelectionHandles] must be called to allow the drag handles to be displayed again.
void preventSelectionHandles() => _areSelectionHandlesAllowed.value = false;

/// Allows the selection handles to be displayed after they have been temporarily
/// prevented by [preventSelectionHandles].
void allowSelectionHandles() => _areSelectionHandlesAllowed.value = true;

/// (Optional) Builder to create the visual representation of the expanded drag handles.
///
/// If [expandedHandlesBuilder] is `null`, default Android handles are displayed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,18 @@ class SuperEditorIosControlsController {
/// Tells the caret to stop blinking by setting [shouldCaretBlink] to `false`.
void doNotBlinkCaret() => _shouldCaretBlink.value = false;

/// {@macro are_selection_handles_allowed}
ValueListenable<bool> get areSelectionHandlesAllowed => _areSelectionHandlesAllowed;
final _areSelectionHandlesAllowed = ValueNotifier<bool>(true);

/// Temporarily prevents any selection handles from being displayed.
///
/// Call this when you want to select some content, but don't want to show the drag handles.
/// [allowSelectionHandles] must be called to allow the drag handles to be displayed again.
void allowSelectionHandles() => _areSelectionHandlesAllowed.value = true;

/// Allows the selection handles to be displayed after they have been temporarily
/// prevented by [preventSelectionHandles].
void preventSelectionHandles() => _areSelectionHandlesAllowed.value = false;

/// Controls the iOS floating cursor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class SpellingAndGrammarStyler extends SingleColumnLayoutStylePhase {
SpellingAndGrammarStyler({
UnderlineStyle? spellingErrorUnderlineStyle,
UnderlineStyle? grammarErrorUnderlineStyle,
this.selectionStyles = defaultSelectionStyle,
this.selectionHighlightColor = Colors.transparent,
}) : _spellingErrorUnderlineStyle = spellingErrorUnderlineStyle,
_grammarErrorUnderlineStyle = grammarErrorUnderlineStyle;
Expand All @@ -36,8 +35,15 @@ class SpellingAndGrammarStyler extends SingleColumnLayoutStylePhase {
markDirty();
}

/// Whether or not we should to override the default selection color with [selectionHighlightColor].
///
/// On mobile platforms, when the suggestions popover is opened, the selected text uses a different
/// highlight color.
bool _overrideSelectionColor = false;

/// The color to use for the selection highlight [overrideSelectionColor] is called.
final Color selectionHighlightColor;

final _errorsByNode = <String, Set<TextError>>{};
final _dirtyNodes = <String>{};

Expand All @@ -63,21 +69,18 @@ class SpellingAndGrammarStyler extends SingleColumnLayoutStylePhase {
markDirty();
}

/// Temporarily use the [selectionHighlightColor] to override the default selection color.
void overrideSelectionColor() {
_overrideSelectionColor = true;
markDirty();
}

/// Restore the default selection color.
void useDefaultSelectionColor() {
_overrideSelectionColor = false;
markDirty();
}

//final SpellingErrorSuggestion? Function()? onGetCurrentSuggestion;
final Color selectionHighlightColor;

final SelectionStyles selectionStyles;

@override
SingleColumnLayoutViewModel style(Document document, SingleColumnLayoutViewModel viewModel) {
final updatedViewModel = SingleColumnLayoutViewModel(
Expand Down
26 changes: 13 additions & 13 deletions super_editor/lib/src/default_editor/super_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ class SuperEditor extends StatefulWidget {
this.documentLayoutKey,
Stylesheet? stylesheet,
this.customStylePhases = const [],
this.prependedStylePhases = const [],
this.appendedStylePhases = const [],
List<ComponentBuilder>? componentBuilders,
SelectionStyles? selectionStyle,
Expand Down Expand Up @@ -238,7 +237,15 @@ class SuperEditor extends StatefulWidget {
/// knows how to interpret and apply table styles for your visual table component.
final List<SingleColumnLayoutStylePhase> customStylePhases;

final List<SingleColumnLayoutStylePhase> prependedStylePhases;
/// Custom style phases that are added to the very end of the style phases.
///
/// Typically, apps should use [customStylePhases]. However, the selection
/// styles are always applied after [customStylePhases]. If you need to
/// change the selection color, add the style phase that changes the selection
/// color here.
///
/// For example, a spellchecker might want to override the selection color
/// for misspelled words.
final List<SingleColumnLayoutStylePhase> appendedStylePhases;

/// The `SuperEditor` input source, e.g., keyboard or Input Method Engine.
Expand Down Expand Up @@ -292,15 +299,6 @@ class SuperEditor extends StatefulWidget {
/// nor the default tap behavior will be executed.
final List<SuperEditorContentTapDelegateFactory>? contentTapDelegateFactories;

/// Shows/hides a popover with spelling suggestions.
///
/// A [SpellCheckerPopoverDelegate] must be attached to this controller
/// before it can be used.
///
/// The `SpellingAndGrammarPlugin` provides a default implementation for
/// a [SpellCheckerPopoverDelegate].
//final SpellCheckerPopoverController? spellCheckerPopoverController;

/// Leader links that connect leader widgets near the user's selection
/// to carets, handles, and other things that want to follow the selection.
///
Expand Down Expand Up @@ -613,7 +611,6 @@ class SuperEditorState extends State<SuperEditor> {
document: document,
componentBuilders: widget.componentBuilders,
pipeline: [
...widget.prependedStylePhases,
_docStylesheetStyler,
_docLayoutPerComponentBlockStyler,
...widget.customStylePhases,
Expand All @@ -623,7 +620,8 @@ class SuperEditorState extends State<SuperEditor> {
composingRegion: editContext.composer.composingRegion,
showComposingUnderline: true,
),
// Selection changes are very volatile. Put that phase last
// Selection changes are very volatile. Put that phase last,
// just before the phases that the apps want to be at the end
// to minimize view model recalculations.
_docLayoutSelectionStyler,
...widget.appendedStylePhases,
Expand Down Expand Up @@ -1188,6 +1186,8 @@ abstract class SuperEditorPlugin {
/// Additional overlay [SuperEditorLayerBuilder]s that will be added to a given [SuperEditor].
List<SuperEditorLayerBuilder> get documentOverlayBuilders => [];

/// Optional handler that responds to taps on content, e.g., opening
/// a link when the user taps on text with a link attribution.
ContentTapDelegate? get contentTapDelegate => null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class AndroidHandlesDocumentLayer extends DocumentLayoutLayerStatefulWidget {
/// is retrieved from the root [SuperEditorAndroidControlsController].
final Color? caretColor;

/// {@macro are_selection_handles_allowed}
final ValueListenable<bool>? areSelectionHandlesAllowed;

final bool showDebugPaint;
Expand Down Expand Up @@ -323,6 +324,7 @@ class AndroidControlsDocumentLayerState
}

if (widget.areSelectionHandlesAllowed?.value == false) {
// We don't want to show any selection handles.
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ class IosHandlesDocumentLayer extends DocumentLayoutLayerStatefulWidget {

final void Function(DocumentSelection?, SelectionChangeType, String selectionReason) changeSelection;

/// {@macro are_selection_handles_allowed}
final ValueListenable<bool>? areSelectionHandlesAllowed;

/// Color the iOS-style text selection drag handles.
Expand Down Expand Up @@ -725,7 +726,8 @@ class IosControlsDocumentLayerState extends DocumentLayoutLayerState<IosHandlesD
return null;
}

if (widget.areSelectionHandlesAllowed!.value == false) {
if (widget.areSelectionHandlesAllowed?.value == false) {
/// We don't want to show any selection handles.
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,80 @@ import 'package:collection/collection.dart';
import 'package:super_editor/super_editor.dart';

/// Shows/hides a popover with spelling suggestions.
///
/// A [SpellCheckerPopoverController] must be attached to a [SpellCheckerPopoverDelegate],
/// which will effectively show/hide the popover.
class SpellCheckerPopoverController {
SpellCheckerPopoverDelegate? _delegate;

/// Attaches this controller to a delegate that knows how to
/// show a popover with spelling suggestions.
///
/// A [SpellCheckerPopoverDelegate] must call this method after
/// being mounted to the widget tree.
void attach(SpellCheckerPopoverDelegate delegate) {
_delegate = delegate;
}

/// Detaches this controller from the delegate.
///
/// This controller can't show/hide the popover while detached from a delegate.
///
/// A [SpellCheckerPopoverDelegate] must call this method after
/// being unmounted from the widget tree.
void detach() {
_delegate = null;
}

/// Shows spelling suggestions for the word at [wordRange].
void show(DocumentRange wordRange) {
_delegate?.showSuggestionsForWordAt(wordRange);
/// Shows the spelling suggestions popover with the suggetions
/// provided by [SpellingErrorSuggestion.suggestions].
///
/// Does nothing if [spelling] doesn't have any suggestions.
void showSuggestions(SpellingErrorSuggestion spelling) {
_delegate?.showSuggestions(spelling);
}

void showSuggestions(SpellingErrorSuggestion suggestions) {
_delegate?.showSuggestions(suggestions);
}

/// Hides the spelling suggestions popover.
/// Hides the spelling suggestions popover if it's visible.
void hide() {
_delegate?.hideSuggestionsPopover();
}

/// Finds spelling suggestions for the word at the given [wordRange].
///
/// Returns `null` if no suggestions are found.
SpellingErrorSuggestion? findSuggestionsForWordAt(DocumentRange wordRange) {
return _delegate?.findSuggestionsForWordAt(wordRange);
}
}

/// Delegate that's attached to a [SpellCheckerPopoverController], to show/hide
/// a popover with spelling suggestions.
///
/// A [SpellCheckerPopoverDelegate] must call [SpellCheckerPopoverController.attach]
/// after being mounted to the widget tree, and [SpellCheckerPopoverController.detach]
/// after being unmounted.
///
/// The popover should be displayed only upon a [showSuggestions] call. The delegate
/// should not display the popover on its own when selection changes.
abstract class SpellCheckerPopoverDelegate {
/// Shows spelling suggestions for the word at [wordRange].
void showSuggestionsForWordAt(DocumentRange wordRange) {}

/// Shows the spelling suggestions popover with the suggetions
/// provided by [SpellingErrorSuggestion.suggestions].
///
/// If the popover is already visible, this method should update
/// the suggestions with the new ones.
///
/// If the document changes while the popover is visible, the popover
/// should be closed.
///
/// This method should not update the document selection.
void showSuggestions(SpellingErrorSuggestion suggestions) {}

/// Hides the spelling suggestions popover.
/// Hides the spelling suggestions popover if it's visible.
void hideSuggestionsPopover() {}

/// Finds spelling suggestions for the word at the given [wordRange].
///
/// Returns `null` if no suggestions are found.
SpellingErrorSuggestion? findSuggestionsForWordAt(DocumentRange wordRange) => null;
}

Expand Down
Loading

0 comments on commit f11f566

Please sign in to comment.