Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lib/src/editor/config/editor_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class QuillEditorConfig {
this.textSelectionThemeData,
this.showCursor,
this.paintCursorAboveText,
this.paintSelectionAboveText = true,
this.enableInteractiveSelection = true,
this.enableSelectionToolbar = true,
this.scrollBottomInset = 0,
Expand Down Expand Up @@ -248,6 +249,11 @@ class QuillEditorConfig {
final bool? showCursor;
final bool? paintCursorAboveText;

/// Whether to paint selection above text.
///
/// Defaults to `true`.
final bool paintSelectionAboveText;

/// The [readOnlyMouseCursor] is used for Windows, macOS when [readOnly] is [true]
final MouseCursor readOnlyMouseCursor;

Expand Down Expand Up @@ -504,6 +510,7 @@ class QuillEditorConfig {
KeyEventResult? Function(KeyEvent event, Node? node)? onKeyPressed,
bool? showCursor,
bool? paintCursorAboveText,
bool? paintSelectionAboveText,
MouseCursor? readOnlyMouseCursor,
bool? enableInteractiveSelection,
bool? enableSelectionToolbar,
Expand Down Expand Up @@ -565,6 +572,8 @@ class QuillEditorConfig {
onTapOutside: onTapOutside ?? this.onTapOutside,
showCursor: showCursor ?? this.showCursor,
paintCursorAboveText: paintCursorAboveText ?? this.paintCursorAboveText,
paintSelectionAboveText:
paintSelectionAboveText ?? this.paintSelectionAboveText,
readOnlyMouseCursor: readOnlyMouseCursor ?? this.readOnlyMouseCursor,
enableInteractiveSelection:
enableInteractiveSelection ?? this.enableInteractiveSelection,
Expand Down
1 change: 1 addition & 0 deletions lib/src/editor/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ class QuillEditorState extends State<QuillEditor>
: null,
showSelectionHandles: isMobile,
showCursor: config.showCursor ?? true,
paintSelectionAboveText: config.paintSelectionAboveText,
cursorStyle: CursorStyle(
color: cursorColor,
backgroundColor: Colors.grey,
Expand Down
4 changes: 4 additions & 0 deletions lib/src/editor/raw_editor/config/raw_editor_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class QuillRawEditorConfig {
this.spaceShortcutEvents = const [],
@experimental this.onKeyPressed,
this.showCursor = true,
this.paintSelectionAboveText = true,
this.scrollable = true,
this.padding = EdgeInsets.zero,
this.readOnly = false,
Expand Down Expand Up @@ -246,6 +247,9 @@ class QuillRawEditorConfig {
/// handles.
final bool showCursor;

/// Whether to paint selection above text.
final bool paintSelectionAboveText;

/// The style to be used for the editing cursor.
final CursorStyle cursorStyle;

Expand Down
2 changes: 2 additions & 0 deletions lib/src/editor/raw_editor/raw_editor_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ class QuillRawEditorState extends EditorState
customStyleBuilder: widget.config.customStyleBuilder,
customLinkPrefixes: widget.config.customLinkPrefixes,
composingRange: composingRange.value,
paintSelectionAboveText: widget.config.paintSelectionAboveText,
);
result.add(
Directionality(
Expand Down Expand Up @@ -687,6 +688,7 @@ class QuillRawEditorState extends EditorState
MediaQuery.devicePixelRatioOf(context),
_cursorCont,
_styles!.inlineCode!,
widget.config.paintSelectionAboveText,
_getDecoration(node, _styles, attrs),
);
return editableTextLine;
Expand Down
3 changes: 3 additions & 0 deletions lib/src/editor/widgets/text/text_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class EditableTextBlock extends StatelessWidget {
required this.readOnly,
required this.customRecognizerBuilder,
required this.composingRange,
required this.paintSelectionAboveText,
this.checkBoxReadOnly,
this.onLaunchUrl,
this.customStyleBuilder,
Expand Down Expand Up @@ -114,6 +115,7 @@ class EditableTextBlock extends StatelessWidget {
final bool? checkBoxReadOnly;
final List<String> customLinkPrefixes;
final TextRange composingRange;
final bool paintSelectionAboveText;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -214,6 +216,7 @@ class EditableTextBlock extends StatelessWidget {
MediaQuery.devicePixelRatioOf(context),
cursorCont,
styles!.inlineCode!,
paintSelectionAboveText,
null,
);
final nodeTextDirection = getDirectionOfNode(line, textDirection);
Expand Down
62 changes: 42 additions & 20 deletions lib/src/editor/widgets/text/text_line.dart
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ class EditableTextLine extends RenderObjectWidget {
this.devicePixelRatio,
this.cursorCont,
this.inlineCodeStyle,
this.paintSelectionAboveText,
this.decoration, {
super.key,
});
Expand All @@ -795,6 +796,7 @@ class EditableTextLine extends RenderObjectWidget {
final double devicePixelRatio;
final CursorCont cursorCont;
final InlineCodeStyle inlineCodeStyle;
final bool paintSelectionAboveText;
final BoxDecoration? decoration;

@override
Expand All @@ -815,6 +817,7 @@ class EditableTextLine extends RenderObjectWidget {
color,
cursorCont,
inlineCodeStyle,
paintSelectionAboveText,
decoration,
);
}
Expand All @@ -835,6 +838,7 @@ class EditableTextLine extends RenderObjectWidget {
..setDevicePixelRatio(devicePixelRatio)
..setCursorCont(cursorCont)
..setInlineCodeStyle(inlineCodeStyle)
..setPaintSelectionAboveText(paintSelectionAboveText)
..setDecoration(decoration);
}

Expand Down Expand Up @@ -863,6 +867,7 @@ class RenderEditableTextLine extends RenderEditableBox {
this.color,
this.cursorCont,
this.inlineCodeStyle,
this.paintSelectionAboveText,
this.decoration,
);

Expand All @@ -882,6 +887,7 @@ class RenderEditableTextLine extends RenderEditableBox {
List<TextBox>? _selectedRects;
late Rect _caretPrototype;
InlineCodeStyle inlineCodeStyle;
bool paintSelectionAboveText;
BoxDecoration? decoration;
final Map<TextLineSlot, RenderBox> children = <TextLineSlot, RenderBox>{};

Expand Down Expand Up @@ -998,6 +1004,12 @@ class RenderEditableTextLine extends RenderEditableBox {
markNeedsLayout();
}

void setPaintSelectionAboveText(bool value) {
if (paintSelectionAboveText == value) return;
paintSelectionAboveText = value;
markNeedsPaint();
}

void setDecoration(BoxDecoration? newDecoration) {
if (decoration == newDecoration) return;
decoration = newDecoration;
Expand Down Expand Up @@ -1460,6 +1472,35 @@ class RenderEditableTextLine extends RenderEditableBox {
}
}

final showSelection =
enableInteractiveSelection &&
line.documentOffset <= textSelection.end &&
textSelection.start <= line.documentOffset + line.length - 1;

if (showSelection) {
if (_selectedRects == null) {
final local = localSelection(line, textSelection, false);
_selectedRects = _body!.getBoxesForSelection(local);

// Paint a small rect at the start of empty lines that
// are contained by the selection.
if (line.isEmpty &&
textSelection.baseOffset <= line.offset &&
textSelection.extentOffset > line.offset) {
final lineHeight = preferredLineHeight(
TextPosition(offset: line.offset),
);
_selectedRects!.add(
TextBox.fromLTRBD(0, 0, 3, lineHeight, textDirection),
);
}
}
}

if (showSelection && !paintSelectionAboveText) {
_paintSelection(context, effectiveOffset);
}

if (hasFocus &&
cursorCont.show.value &&
containsCursor() &&
Expand All @@ -1476,26 +1517,7 @@ class RenderEditableTextLine extends RenderEditableBox {
_paintCursor(context, effectiveOffset, line.hasEmbed);
}

// paint the selection on the top
if (enableInteractiveSelection &&
line.documentOffset <= textSelection.end &&
textSelection.start <= line.documentOffset + line.length - 1) {
final local = localSelection(line, textSelection, false);
_selectedRects ??= _body!.getBoxesForSelection(local);

// Paint a small rect at the start of empty lines that
// are contained by the selection.
if (line.isEmpty &&
textSelection.baseOffset <= line.offset &&
textSelection.extentOffset > line.offset) {
final lineHeight = preferredLineHeight(
TextPosition(offset: line.offset),
);
_selectedRects?.add(
TextBox.fromLTRBD(0, 0, 3, lineHeight, textDirection),
);
}

if (showSelection && paintSelectionAboveText) {
_paintSelection(context, effectiveOffset);
}
}
Expand Down