Skip to content
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

feat: enable drag-and-drop functionality for text in the editor #685

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
cursor,
selection,
block,
dragAndDrop,
}

/// [BlockSelectionArea] is a widget that renders the selection area or the cursor of a block.
Expand All @@ -22,12 +23,14 @@
required this.node,
required this.delegate,
required this.listenable,
this.dragAndDropListenable,
required this.cursorColor,
required this.selectionColor,
required this.blockColor,
this.supportTypes = const [
BlockSelectionType.cursor,
BlockSelectionType.selection,
BlockSelectionType.dragAndDrop,
],
});

Expand All @@ -37,6 +40,10 @@
// get the selection from the listenable
final ValueListenable<Selection?> listenable;

// obtain the selection from dragAndDropListenable
// if it's `null`, construct the cursor for the drag-and-drop pointer
final ValueListenable<Selection?>? dragAndDropListenable;

// the color of the cursor
final Color cursorColor;

Expand All @@ -60,6 +67,9 @@
debugLabel: 'cursor_${widget.node.path}',
);

// keep the previous drag and drop selection rects
// to avoid unnecessary rebuild
List<Rect>? prevDragAndDropSelectionRects;
// keep the previous cursor rect to avoid unnecessary rebuild
Rect? prevCursorRect;
// keep the previous selection rects to avoid unnecessary rebuild
Expand Down Expand Up @@ -91,6 +101,24 @@
valueListenable: widget.listenable,
builder: ((context, value, child) {
final sizedBox = child ?? const SizedBox.shrink();

final dragAndDropSelection =
context.read<EditorState>().dragAndDropSelection;
if (dragAndDropSelection != null &&
widget.dragAndDropListenable != null) {
if (!widget.supportTypes.contains(BlockSelectionType.dragAndDrop) ||
prevDragAndDropSelectionRects == null ||
prevDragAndDropSelectionRects!.isEmpty ||
(prevDragAndDropSelectionRects!.length == 1 &&
prevDragAndDropSelectionRects!.first.width == 0)) {

Check warning on line 113 in lib/src/editor/block_component/base_component/selection/block_selection_area.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/base_component/selection/block_selection_area.dart#L111-L113

Added lines #L111 - L113 were not covered by tests
return sizedBox;
}
return SelectionAreaPaint(
rects: prevDragAndDropSelectionRects!,
selectionColor: widget.selectionColor,

Check warning on line 118 in lib/src/editor/block_component/base_component/selection/block_selection_area.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/base_component/selection/block_selection_area.dart#L116-L118

Added lines #L116 - L118 were not covered by tests
);
}

final selection = value?.normalized;

if (selection == null) {
Expand Down Expand Up @@ -162,12 +190,29 @@
if (!mounted) {
return;
}

final selection = widget.listenable.value?.normalized;
final path = widget.node.path;

Selection? dragAndDropSelection;
if (widget.dragAndDropListenable != null) {
dragAndDropSelection = widget.dragAndDropListenable!.value?.normalized;
}

if (dragAndDropSelection != null) {
if (widget.supportTypes.contains(BlockSelectionType.dragAndDrop)) {
final rects = widget.delegate.getRectsInSelection(dragAndDropSelection);
if (!_deepEqual(rects, prevSelectionRects)) {
setState(() {
prevDragAndDropSelectionRects = rects;
prevSelectionRects = null;
prevCursorRect = null;
prevBlockRect = null;
});
}
}
}
// the current path is in the selection
if (selection != null && path.inSelection(selection)) {
else if (selection != null && path.inSelection(selection)) {
if (widget.supportTypes.contains(BlockSelectionType.block) &&
context.read<EditorState>().selectionType == SelectionType.block) {
if (!path.equals(selection.start.path)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ class BlockSelectionContainer extends StatelessWidget {
required this.node,
required this.delegate,
required this.listenable,
required this.dragAndDropListenable,
this.cursorColor = Colors.black,
this.selectionColor = Colors.blue,
this.blockColor = Colors.blue,
this.supportTypes = const [
BlockSelectionType.cursor,
BlockSelectionType.selection,
BlockSelectionType.dragAndDrop,
],
required this.child,
});
Expand All @@ -24,6 +26,8 @@ class BlockSelectionContainer extends StatelessWidget {
// get the selection from the listenable
final ValueListenable<Selection?> listenable;

final ValueListenable<Selection?> dragAndDropListenable;

// the color of the cursor
final Color cursorColor;

Expand Down Expand Up @@ -55,6 +59,7 @@ class BlockSelectionContainer extends StatelessWidget {
node: node,
delegate: delegate,
listenable: listenable,
dragAndDropListenable: dragAndDropListenable,
cursorColor: cursorColor,
selectionColor: selectionColor,
blockColor: blockColor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,42 @@
@override
Node get node => widget.node;

CursorStyle _cursorStyle = CursorStyle.verticalLine;

@override
CursorStyle get cursorStyle => _cursorStyle;

set cursorStyle(CursorStyle cursorStyle) {
_cursorStyle = cursorStyle;

Check warning on line 115 in lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart#L114-L115

Added lines #L114 - L115 were not covered by tests
}

bool _shouldCursorBlink = true;

@override
bool get shouldCursorBlink => _shouldCursorBlink;

set shouldCursorBlink(bool value) {
_shouldCursorBlink = value;

Check warning on line 124 in lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart#L123-L124

Added lines #L123 - L124 were not covered by tests
}

void _onCursorStyleChange() {
cursorStyle = editorState.cursorStyle;

Check warning on line 128 in lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart#L127-L128

Added lines #L127 - L128 were not covered by tests

shouldCursorBlink = cursorStyle != CursorStyle.dottedVerticalLine;

Check warning on line 130 in lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/bulleted_list_block_component/bulleted_list_block_component.dart#L130

Added line #L130 was not covered by tests
}

@override
void initState() {
super.initState();
editorState.cursorStyleNotifier.addListener(_onCursorStyleChange);
}

@override
void dispose() {
editorState.cursorStyleNotifier.removeListener(_onCursorStyleChange);
super.dispose();
}

@override
Widget buildComponent(
BuildContext context, {
Expand Down Expand Up @@ -168,6 +204,7 @@
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable: editorState.dragAndDropSelectionNotifier,
blockColor: editorState.editorStyle.selectionColor,
supportTypes: const [
BlockSelectionType.block,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class _DividerBlockComponentWidgetState
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable: editorState.dragAndDropSelectionNotifier,
blockColor: editorState.editorStyle.selectionColor,
cursorColor: editorState.editorStyle.cursorColor,
selectionColor: editorState.editorStyle.selectionColor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,42 @@

int get level => widget.node.attributes[HeadingBlockKeys.level] as int? ?? 1;

CursorStyle _cursorStyle = CursorStyle.verticalLine;

@override
CursorStyle get cursorStyle => _cursorStyle;

set cursorStyle(CursorStyle cursorStyle) {
_cursorStyle = cursorStyle;

Check warning on line 128 in lib/src/editor/block_component/heading_block_component/heading_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/heading_block_component/heading_block_component.dart#L127-L128

Added lines #L127 - L128 were not covered by tests
}

bool _shouldCursorBlink = true;

@override
bool get shouldCursorBlink => _shouldCursorBlink;

set shouldCursorBlink(bool value) {
_shouldCursorBlink = value;

Check warning on line 137 in lib/src/editor/block_component/heading_block_component/heading_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/heading_block_component/heading_block_component.dart#L136-L137

Added lines #L136 - L137 were not covered by tests
}

void _onCursorStyleChange() {
cursorStyle = editorState.cursorStyle;

Check warning on line 141 in lib/src/editor/block_component/heading_block_component/heading_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/heading_block_component/heading_block_component.dart#L140-L141

Added lines #L140 - L141 were not covered by tests

shouldCursorBlink = cursorStyle != CursorStyle.dottedVerticalLine;

Check warning on line 143 in lib/src/editor/block_component/heading_block_component/heading_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/heading_block_component/heading_block_component.dart#L143

Added line #L143 was not covered by tests
}

@override
void initState() {
super.initState();
editorState.cursorStyleNotifier.addListener(_onCursorStyleChange);
}

@override
void dispose() {
editorState.cursorStyleNotifier.removeListener(_onCursorStyleChange);
super.dispose();
}

@override
Widget build(BuildContext context) {
final textDirection = calculateTextDirection(
Expand Down Expand Up @@ -183,6 +219,7 @@
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable: editorState.dragAndDropSelectionNotifier,
blockColor: editorState.editorStyle.selectionColor,
supportTypes: const [
BlockSelectionType.block,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class ImageBlockComponentWidgetState extends State<ImageBlockComponentWidget>
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable: editorState.dragAndDropSelectionNotifier,
blockColor: editorState.editorStyle.selectionColor,
supportTypes: const [
BlockSelectionType.block,
Expand Down Expand Up @@ -196,6 +197,8 @@ class ImageBlockComponentWidgetState extends State<ImageBlockComponentWidget>
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable:
editorState.dragAndDropSelectionNotifier,
cursorColor: editorState.editorStyle.cursorColor,
selectionColor: editorState.editorStyle.selectionColor,
child: child!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,42 @@
@override
Node get node => widget.node;

CursorStyle _cursorStyle = CursorStyle.verticalLine;

@override
CursorStyle get cursorStyle => _cursorStyle;

set cursorStyle(CursorStyle cursorStyle) {
_cursorStyle = cursorStyle;

Check warning on line 121 in lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart#L120-L121

Added lines #L120 - L121 were not covered by tests
}

bool _shouldCursorBlink = true;

@override
bool get shouldCursorBlink => _shouldCursorBlink;

set shouldCursorBlink(bool value) {
_shouldCursorBlink = value;

Check warning on line 130 in lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart#L129-L130

Added lines #L129 - L130 were not covered by tests
}

void _onCursorStyleChange() {
cursorStyle = editorState.cursorStyle;

Check warning on line 134 in lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart#L133-L134

Added lines #L133 - L134 were not covered by tests

shouldCursorBlink = cursorStyle != CursorStyle.dottedVerticalLine;

Check warning on line 136 in lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/numbered_list_block_component/numbered_list_block_component.dart#L136

Added line #L136 was not covered by tests
}

@override
void initState() {
super.initState();
editorState.cursorStyleNotifier.addListener(_onCursorStyleChange);
}

@override
void dispose() {
editorState.cursorStyleNotifier.removeListener(_onCursorStyleChange);
super.dispose();
}

@override
Widget buildComponent(
BuildContext context, {
Expand Down Expand Up @@ -175,6 +211,7 @@
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable: editorState.dragAndDropSelectionNotifier,
blockColor: editorState.editorStyle.selectionColor,
supportTypes: const [
BlockSelectionType.block,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,36 @@

bool _showPlaceholder = false;

CursorStyle _cursorStyle = CursorStyle.verticalLine;

@override
CursorStyle get cursorStyle => _cursorStyle;

set cursorStyle(CursorStyle cursorStyle) {
_cursorStyle = cursorStyle;

Check warning on line 120 in lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart#L119-L120

Added lines #L119 - L120 were not covered by tests
}

bool _shouldCursorBlink = true;

@override
bool get shouldCursorBlink => _shouldCursorBlink;

set shouldCursorBlink(bool value) {
_shouldCursorBlink = value;

Check warning on line 129 in lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart#L128-L129

Added lines #L128 - L129 were not covered by tests
}

@override
void initState() {
super.initState();
editorState.selectionNotifier.addListener(_onSelectionChange);
editorState.cursorStyleNotifier.addListener(_onCursorStyleChange);
_onSelectionChange();
}

@override
void dispose() {
editorState.selectionNotifier.removeListener(_onSelectionChange);
editorState.cursorStyleNotifier.removeListener(_onCursorStyleChange);
super.dispose();
}

Expand All @@ -140,6 +160,12 @@
}
}

void _onCursorStyleChange() {
cursorStyle = editorState.cursorStyle;

Check warning on line 164 in lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart#L163-L164

Added lines #L163 - L164 were not covered by tests

shouldCursorBlink = cursorStyle != CursorStyle.dottedVerticalLine;

Check warning on line 166 in lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/block_component/paragraph_block_component/paragraph_block_component.dart#L166

Added line #L166 was not covered by tests
}

@override
Widget buildComponent(
BuildContext context, {
Expand Down Expand Up @@ -191,6 +217,7 @@
node: node,
delegate: this,
listenable: editorState.selectionNotifier,
dragAndDropListenable: editorState.dragAndDropSelectionNotifier,
blockColor: editorState.editorStyle.selectionColor,
supportTypes: const [
BlockSelectionType.block,
Expand Down
Loading
Loading