Skip to content

Add paintSelectionBehindText configuration option #2604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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
25 changes: 5 additions & 20 deletions example/.metadata
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.

version:
revision: "603104015dd692ea3403755b55d07813d5cf8965"
revision: "6fba2447e95c451518584c35e25f5433f14d888c"
channel: "stable"

project_type: app
Expand All @@ -13,26 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
- platform: android
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
- platform: ios
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
- platform: linux
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
- platform: macos
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
create_revision: 6fba2447e95c451518584c35e25f5433f14d888c
base_revision: 6fba2447e95c451518584c35e25f5433f14d888c
- platform: web
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
- platform: windows
create_revision: 603104015dd692ea3403755b55d07813d5cf8965
base_revision: 603104015dd692ea3403755b55d07813d5cf8965
create_revision: 6fba2447e95c451518584c35e25f5433f14d888c
base_revision: 6fba2447e95c451518584c35e25f5433f14d888c

# User provided section

Expand Down
4 changes: 2 additions & 2 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ packages:
path: ".."
relative: true
source: path
version: "11.4.1"
version: "11.4.1+fork"
flutter_quill_delta_from_html:
dependency: transitive
description:
Expand All @@ -245,7 +245,7 @@ packages:
path: "../flutter_quill_extensions"
relative: true
source: path
version: "11.0.0"
version: "11.0.0+fork"
flutter_quill_test:
dependency: "direct dev"
description:
Expand Down
9 changes: 7 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ dependencies:
flutter_localizations:
sdk: flutter

flutter_quill: ^11.0.0-dev.4
flutter_quill_extensions: ^11.0.0-dev.3
flutter_quill:
git:
url: git@github.com:singerdmx/flutter-quill.git
flutter_quill_extensions:
git:
url: git@github.com:singerdmx/flutter-quill.git
path: flutter_quill_extensions
path: ^1.9.0

dev_dependencies:
Expand Down
2 changes: 1 addition & 1 deletion flutter_quill_extensions/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_quill_extensions
description: Embed extensions for flutter_quill to support loading images and videos
version: 11.0.0
version: 11.0.0+fork
homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/
repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/
issue_tracker: https://github.com/singerdmx/flutter-quill/issues/
Expand Down
45 changes: 45 additions & 0 deletions lib/src/controller/quill_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,46 @@ class QuillController extends ChangeNotifier {
TextSelection get selection => _selection;
TextSelection _selection;

// Drag selection tracking for smooth scrolling on web
bool _isDragging = false;
TextSelection? _previousSelection;

bool get isDragging => _isDragging;

void startDragSelection() {
_isDragging = true;
_previousSelection = _selection;
}

void endDragSelection() {
_isDragging = false;
_previousSelection = null;
}

/// Get the appropriate caret position for scrolling during drag selection
TextPosition getCaretPositionForScrolling() {
if (!_isDragging || _previousSelection == null) {
return _selection.extent;
}

final oldSelection = _previousSelection!;
final newSelection = _selection;

// Did the base position change?
if (oldSelection.baseOffset != newSelection.baseOffset) {
// Base changed, track the base position
return newSelection.base;
}
// Did the extent position change?
else if (oldSelection.extentOffset != newSelection.extentOffset) {
// Extent changed, track the extent position
return newSelection.extent;
}

// If no change, use extent
return newSelection.extent;
}

/// Custom [replaceText] handler
/// Return false to ignore the event
ReplaceTextCallback? onReplaceText;
Expand Down Expand Up @@ -463,6 +503,11 @@ class QuillController extends ChangeNotifier {

void _updateSelection(TextSelection textSelection,
{bool insertNewline = false}) {
// Drag sırasında önceki selection'ı güncelle
if (_isDragging) {
_previousSelection = _selection;
}

_selection = textSelection;
final end = document.length - 1;
_selection = selection.copyWith(
Expand Down
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 @@ -42,6 +42,7 @@ class QuillEditorConfig {
this.paintCursorAboveText,
this.enableInteractiveSelection = true,
this.enableSelectionToolbar = true,
this.paintSelectionBehindText = true,
this.scrollBottomInset = 0,
this.minHeight,
this.maxHeight,
Expand Down Expand Up @@ -269,6 +270,11 @@ class QuillEditorConfig {
/// Whether to show the cut/copy/paste menu when selecting text.
final bool enableSelectionToolbar;

/// Whether to paint the selection behind the text (true) or in front of the text (false).
/// When true, the selection color can be opaque. When false, the selection color should be transparent.
/// Defaults to true.
final bool paintSelectionBehindText;

/// The minimum height to be occupied by this editor.
///
/// This only has effect if [scrollable] is set to `true` and [expands] is
Expand Down Expand Up @@ -494,6 +500,7 @@ class QuillEditorConfig {
MouseCursor? readOnlyMouseCursor,
bool? enableInteractiveSelection,
bool? enableSelectionToolbar,
bool? paintSelectionBehindText,
double? minHeight,
double? maxHeight,
double? maxContentWidth,
Expand Down Expand Up @@ -557,6 +564,8 @@ class QuillEditorConfig {
enableInteractiveSelection ?? this.enableInteractiveSelection,
enableSelectionToolbar:
enableSelectionToolbar ?? this.enableSelectionToolbar,
paintSelectionBehindText:
paintSelectionBehindText ?? this.paintSelectionBehindText,
minHeight: minHeight ?? this.minHeight,
maxHeight: maxHeight ?? this.maxHeight,
maxContentWidth: maxContentWidth ?? this.maxContentWidth,
Expand Down
23 changes: 20 additions & 3 deletions lib/src/editor/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ class QuillEditorState extends State<QuillEditor>
expands: config.expands,
autoFocus: config.autoFocus,
selectionColor: selectionColor,
paintSelectionBehindText: config.paintSelectionBehindText,
selectionCtrls: config.textSelectionControls ?? textSelectionControls,
keyboardAppearance: config.keyboardAppearance,
enableInteractiveSelection: config.enableInteractiveSelection,
Expand Down Expand Up @@ -680,6 +681,7 @@ class RenderEditor extends RenderEditableContainerBox
required this.onSelectionCompleted,
required super.scrollBottomInset,
required this.floatingCursorDisabled,
this.controller,
ViewportOffset? offset,
super.children,
EdgeInsets floatingCursorAddedMargin =
Expand All @@ -695,6 +697,7 @@ class RenderEditor extends RenderEditableContainerBox
container: document.root,
);

final QuillController? controller;
final CursorCont _cursorController;
final bool floatingCursorDisabled;
final bool scrollable;
Expand Down Expand Up @@ -923,6 +926,8 @@ class RenderEditor extends RenderEditableContainerBox

void handleDragStart(DragStartDetails details) {
_isDragging = true;
// Notify controller that drag has started
controller?.startDragSelection();

final newSelection = selectPositionAt(
from: details.globalPosition,
Expand All @@ -936,6 +941,8 @@ class RenderEditor extends RenderEditableContainerBox

void handleDragEnd(DragEndDetails details) {
_isDragging = false;
// Notify controller that drag has ended
controller?.endDragSelection();
onSelectionCompleted();
}

Expand Down Expand Up @@ -1233,9 +1240,19 @@ class RenderEditor extends RenderEditableContainerBox
return childLocalRect.shift(Offset(0, boxParentData.offset.dy));
}

TextPosition get caretTextPosition => _floatingCursorRect == null
? selection.extent
: _floatingCursorTextPosition;
TextPosition get caretTextPosition {
if (_floatingCursorRect != null) {
return _floatingCursorTextPosition;
}

// Get smart caret position from controller during drag on web platform
if (kIsWeb && controller != null && controller!.isDragging) {
return controller!.getCaretPositionForScrolling();
}

// Use extent in normal cases (cursor position)
return selection.extent;
}

// Start floating cursor

Expand Down
6 changes: 6 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 @@ -29,6 +29,7 @@ class QuillRawEditorConfig {
required this.embedBuilder,
required this.textSpanBuilder,
required this.autoFocus,
this.paintSelectionBehindText = true,
this.characterShortcutEvents = const [],
this.spaceShortcutEvents = const [],
@experimental this.onKeyPressed,
Expand Down Expand Up @@ -303,6 +304,11 @@ class QuillRawEditorConfig {
/// The color to use when painting the selection.
final Color selectionColor;

/// Whether to paint the selection behind the text (true) or in front of the text (false).
/// When true, the selection color can be opaque. When false, the selection color should be transparent.
/// Defaults to true.
final bool paintSelectionBehindText;

/// Delegate for building the text selection handles and toolbar.
///
/// The [QuillRawEditor] widget used on its own will not trigger the display
Expand Down
4 changes: 4 additions & 0 deletions lib/src/editor/raw_editor/raw_editor_render_object.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart' show ViewportOffset;

import '../../controller/quill_controller.dart';
import '../../document/document.dart';
import '../editor.dart';
import '../widgets/cursor.dart';
Expand All @@ -21,6 +22,7 @@ class QuillRawEditorMultiChildRenderObject
required this.scrollBottomInset,
required this.cursorController,
required this.floatingCursorDisabled,
this.controller,
super.key,
this.padding = EdgeInsets.zero,
this.maxContentWidth,
Expand All @@ -42,6 +44,7 @@ class QuillRawEditorMultiChildRenderObject
final double? maxContentWidth;
final CursorCont cursorController;
final bool floatingCursorDisabled;
final QuillController? controller;

@override
RenderEditor createRenderObject(BuildContext context) {
Expand All @@ -61,6 +64,7 @@ class QuillRawEditorMultiChildRenderObject
maxContentWidth: maxContentWidth,
scrollBottomInset: scrollBottomInset,
floatingCursorDisabled: floatingCursorDisabled,
controller: controller,
);
}

Expand Down
33 changes: 19 additions & 14 deletions lib/src/editor/raw_editor/raw_editor_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ class QuillRawEditorState extends EditorState
cursorController: _cursorCont,
floatingCursorDisabled:
widget.config.floatingCursorDisabled,
controller: controller,
children: _buildChildren(doc, context),
),
),
Expand Down Expand Up @@ -508,6 +509,7 @@ class QuillRawEditorState extends EditorState
padding: widget.config.padding,
maxContentWidth: widget.config.maxContentWidth,
floatingCursorDisabled: widget.config.floatingCursorDisabled,
controller: controller,
children: _buildChildren(doc, context),
),
),
Expand Down Expand Up @@ -653,6 +655,7 @@ class QuillRawEditorState extends EditorState
color: widget.config.selectionColor,
styles: _styles,
enableInteractiveSelection: widget.config.enableInteractiveSelection,
paintSelectionBehindText: widget.config.paintSelectionBehindText,
hasFocus: _hasFocus,
contentPadding: attrs.containsKey(Attribute.codeBlock.key)
? const EdgeInsets.all(16)
Expand Down Expand Up @@ -707,20 +710,22 @@ class QuillRawEditorState extends EditorState
composingRange: composingRange.value,
);
final editableTextLine = EditableTextLine(
node,
null,
textLine,
_getHorizontalSpacingForLine(node, _styles),
_getVerticalSpacingForLine(node, _styles),
_textDirection,
controller.selection,
widget.config.selectionColor,
widget.config.enableInteractiveSelection,
_hasFocus,
MediaQuery.devicePixelRatioOf(context),
_cursorCont,
_styles!.inlineCode!,
_getDecoration(node, _styles, attrs));
node,
null,
textLine,
_getHorizontalSpacingForLine(node, _styles),
_getVerticalSpacingForLine(node, _styles),
_textDirection,
controller.selection,
widget.config.selectionColor,
widget.config.enableInteractiveSelection,
_hasFocus,
MediaQuery.devicePixelRatioOf(context),
_cursorCont,
_styles!.inlineCode!,
_getDecoration(node, _styles, attrs),
widget.config.paintSelectionBehindText,
);
return editableTextLine;
}

Expand Down
6 changes: 5 additions & 1 deletion lib/src/editor/widgets/text/text_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class EditableTextBlock extends StatelessWidget {
required this.color,
required this.styles,
required this.enableInteractiveSelection,
required this.paintSelectionBehindText,
required this.hasFocus,
required this.contentPadding,
required this.embedBuilder,
Expand Down Expand Up @@ -98,6 +99,7 @@ class EditableTextBlock extends StatelessWidget {
final DefaultStyles? styles;
final LeadingBlockNodeBuilder? customLeadingBlockBuilder;
final bool enableInteractiveSelection;
final bool paintSelectionBehindText;
final bool hasFocus;
final EdgeInsets? contentPadding;
final EmbedsBuilder embedBuilder;
Expand Down Expand Up @@ -209,7 +211,9 @@ class EditableTextBlock extends StatelessWidget {
MediaQuery.devicePixelRatioOf(context),
cursorCont,
styles!.inlineCode!,
null);
null,
paintSelectionBehindText,
);
final nodeTextDirection = getDirectionOfNode(line, textDirection);
children.add(
Directionality(
Expand Down
Loading
Loading