refactor: move selection to core/location

This commit is contained in:
Lucas.Xu 2022-10-10 10:39:42 +08:00
commit 20d53c825a
27 changed files with 158 additions and 73 deletions

View file

@ -5,8 +5,8 @@ export 'src/infra/log.dart';
export 'src/render/style/editor_style.dart'; export 'src/render/style/editor_style.dart';
export 'src/core/document/node.dart'; export 'src/core/document/node.dart';
export 'src/core/document/path.dart'; export 'src/core/document/path.dart';
export 'src/core/selection/position.dart'; export 'src/core/location/position.dart';
export 'src/document/selection.dart'; export 'src/core/location/selection.dart';
export 'src/document/state_tree.dart'; export 'src/document/state_tree.dart';
export 'src/core/document/text_delta.dart'; export 'src/core/document/text_delta.dart';
export 'src/core/document/attributes.dart'; export 'src/core/document/attributes.dart';

View file

@ -4,7 +4,7 @@ import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart'; import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
Future<void> formatBuiltInTextAttributes( Future<void> formatBuiltInTextAttributes(

View file

@ -4,7 +4,7 @@ import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/core/document/attributes.dart'; import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart'; import 'package:appflowy_editor/src/operation/transaction_builder.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';

View file

@ -1,6 +1,6 @@
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
// get formatted [TextNode] // get formatted [TextNode]

View file

@ -0,0 +1,40 @@
import 'package:appflowy_editor/src/core/document/path.dart';
class Position {
final Path path;
final int offset;
Position({
required this.path,
this.offset = 0,
});
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Position &&
other.path.equals(path) &&
other.offset == offset;
}
@override
int get hashCode => Object.hash(offset, Object.hashAll(path));
@override
String toString() => 'path = $path, offset = $offset';
Position copyWith({Path? path, int? offset}) {
return Position(
path: path ?? this.path,
offset: offset ?? this.offset,
);
}
Map<String, dynamic> toJson() {
return {
'path': path,
'offset': offset,
};
}
}

View file

@ -0,0 +1,107 @@
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/core/location/position.dart';
/// Selection represents the selected area or the cursor area in the editor.
///
/// [Selection] is directional.
///
/// 1. forward,the end position is before the start position.
/// 2. backward, the end position is after the start position.
/// 3. collapsed, the end position is equal to the start position.
class Selection {
/// Create a selection with [start], [end].
Selection({
required this.start,
required this.end,
});
/// Create a selection with [Path], [startOffset] and [endOffset].
///
/// The [endOffset] is optional.
///
/// This constructor will return a collapsed [Selection] if [endOffset] is null.
///
Selection.single({
required Path path,
required int startOffset,
int? endOffset,
}) : start = Position(path: path, offset: startOffset),
end = Position(path: path, offset: endOffset ?? startOffset);
/// Create a collapsed selection with [position].
Selection.collapsed(Position position)
: start = position,
end = position;
final Position start;
final Position end;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Selection && other.start == start && other.end == end;
}
@override
int get hashCode => start.hashCode ^ end.hashCode;
@override
String toString() => 'start = $start, end = $end';
/// Returns a Boolean indicating whether the selection's start and end points
/// are at the same position.
bool get isCollapsed => start == end;
/// Returns a Boolean indicating whether the selection's start and end points
/// are at the same path.
bool get isSingle => start.path.equals(end.path);
/// Returns a Boolean indicating whether the selection is forward.
bool get isForward =>
(start.path > end.path) || (isSingle && start.offset > end.offset);
/// Returns a Boolean indicating whether the selection is backward.
bool get isBackward =>
(start.path < end.path) || (isSingle && start.offset < end.offset);
/// Returns a normalized selection that direction is forward.
Selection get normalized => isBackward ? copyWith() : reversed.copyWith();
/// Returns a reversed selection.
Selection get reversed => copyWith(start: end, end: start);
/// Returns the offset in the starting position under the normalized selection.
int get startIndex => normalized.start.offset;
/// Returns the offset in the ending position under the normalized selection.
int get endIndex => normalized.end.offset;
int get length => endIndex - startIndex;
/// Collapses the current selection to a single point.
///
/// If [atStart] is true, the selection will be collapsed to the start point.
/// If [atStart] is false, the selection will be collapsed to the end point.
Selection collapse({bool atStart = false}) {
if (atStart) {
return copyWith(end: start);
} else {
return copyWith(start: end);
}
}
Selection copyWith({Position? start, Position? end}) {
return Selection(
start: start ?? this.start,
end: end ?? this.end,
);
}
Map<String, dynamic> toJson() {
return {
'start': start.toJson(),
'end': end.toJson(),
};
}
}

View file

@ -5,7 +5,7 @@ import 'package:appflowy_editor/src/render/style/editor_style.dart';
import 'package:appflowy_editor/src/service/service.dart'; import 'package:appflowy_editor/src/service/service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/document/state_tree.dart'; import 'package:appflowy_editor/src/document/state_tree.dart';
import 'package:appflowy_editor/src/operation/operation.dart'; import 'package:appflowy_editor/src/operation/operation.dart';
import 'package:appflowy_editor/src/operation/transaction.dart'; import 'package:appflowy_editor/src/operation/transaction.dart';

View file

@ -1,6 +1,6 @@
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/extensions/object_extensions.dart'; import 'package:appflowy_editor/src/extensions/object_extensions.dart';
import 'package:appflowy_editor/src/render/selection/selectable.dart'; import 'package:appflowy_editor/src/render/selection/selectable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View file

@ -1,7 +1,7 @@
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/core/document/text_delta.dart'; import 'package:appflowy_editor/src/core/document/text_delta.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart'; import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';

View file

@ -1,6 +1,6 @@
import 'dart:collection'; import 'dart:collection';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import './operation.dart'; import './operation.dart';
/// A [Transaction] has a list of [Operation] objects that will be applied /// A [Transaction] has a list of [Operation] objects that will be applied

View file

@ -4,8 +4,8 @@ import 'dart:math';
import 'package:appflowy_editor/src/core/document/attributes.dart'; import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/core/document/text_delta.dart'; import 'package:appflowy_editor/src/core/document/text_delta.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/operation/operation.dart'; import 'package:appflowy_editor/src/operation/operation.dart';

View file

@ -1,7 +1,7 @@
import 'package:appflowy_editor/src/extensions/object_extensions.dart'; import 'package:appflowy_editor/src/extensions/object_extensions.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/infra/flowy_svg.dart'; import 'package:appflowy_editor/src/infra/flowy_svg.dart';
import 'package:appflowy_editor/src/render/selection/selectable.dart'; import 'package:appflowy_editor/src/render/selection/selectable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View file

@ -1,5 +1,5 @@
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/render/selection/selectable.dart'; import 'package:appflowy_editor/src/render/selection/selectable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View file

@ -7,8 +7,8 @@ import 'package:flutter/rendering.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/core/document/text_delta.dart'; import 'package:appflowy_editor/src/core/document/text_delta.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/extensions/url_launcher_extension.dart'; import 'package:appflowy_editor/src/extensions/url_launcher_extension.dart';

View file

@ -1,5 +1,5 @@
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
enum CursorStyle { enum CursorStyle {

View file

@ -1,8 +1,8 @@
import 'package:appflowy_editor/src/core/document/attributes.dart'; import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart'; import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/core/selection/position.dart'; import 'package:appflowy_editor/src/core/location/position.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart'; import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart'; import 'package:appflowy_editor/src/operation/transaction_builder.dart';

View file

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/extensions/node_extensions.dart'; import 'package:appflowy_editor/src/extensions/node_extensions.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart'; import 'package:appflowy_editor/src/operation/transaction_builder.dart';

View file

@ -220,7 +220,7 @@ ShortcutEventHandler cursorEndSelect = (editorState, event) {
KeyEventResult cursorUp(EditorState editorState, RawKeyEvent event) { KeyEventResult cursorUp(EditorState editorState, RawKeyEvent event) {
final nodes = editorState.service.selectionService.currentSelectedNodes; final nodes = editorState.service.selectionService.currentSelectedNodes;
final selection = final selection =
editorState.service.selectionService.currentSelection.value?.normalize; editorState.service.selectionService.currentSelection.value?.normalized;
if (nodes.isEmpty || selection == null) { if (nodes.isEmpty || selection == null) {
return KeyEventResult.ignored; return KeyEventResult.ignored;
} }
@ -234,7 +234,7 @@ KeyEventResult cursorUp(EditorState editorState, RawKeyEvent event) {
KeyEventResult cursorDown(EditorState editorState, RawKeyEvent event) { KeyEventResult cursorDown(EditorState editorState, RawKeyEvent event) {
final nodes = editorState.service.selectionService.currentSelectedNodes; final nodes = editorState.service.selectionService.currentSelectedNodes;
final selection = final selection =
editorState.service.selectionService.currentSelection.value?.normalize; editorState.service.selectionService.currentSelection.value?.normalized;
if (nodes.isEmpty || selection == null) { if (nodes.isEmpty || selection == null) {
return KeyEventResult.ignored; return KeyEventResult.ignored;
} }
@ -248,7 +248,7 @@ KeyEventResult cursorDown(EditorState editorState, RawKeyEvent event) {
KeyEventResult cursorLeft(EditorState editorState, RawKeyEvent event) { KeyEventResult cursorLeft(EditorState editorState, RawKeyEvent event) {
final nodes = editorState.service.selectionService.currentSelectedNodes; final nodes = editorState.service.selectionService.currentSelectedNodes;
final selection = final selection =
editorState.service.selectionService.currentSelection.value?.normalize; editorState.service.selectionService.currentSelection.value?.normalized;
if (nodes.isEmpty || selection == null) { if (nodes.isEmpty || selection == null) {
return KeyEventResult.ignored; return KeyEventResult.ignored;
} }
@ -270,7 +270,7 @@ KeyEventResult cursorLeft(EditorState editorState, RawKeyEvent event) {
KeyEventResult cursorRight(EditorState editorState, RawKeyEvent event) { KeyEventResult cursorRight(EditorState editorState, RawKeyEvent event) {
final nodes = editorState.service.selectionService.currentSelectedNodes; final nodes = editorState.service.selectionService.currentSelectedNodes;
final selection = final selection =
editorState.service.selectionService.currentSelection.value?.normalize; editorState.service.selectionService.currentSelection.value?.normalized;
if (nodes.isEmpty || selection == null) { if (nodes.isEmpty || selection == null) {
return KeyEventResult.ignored; return KeyEventResult.ignored;
} }

View file

@ -25,7 +25,7 @@ Selection _computeSelectionAfterPasteMultipleNodes(
} }
void _handleCopy(EditorState editorState) async { void _handleCopy(EditorState editorState) async {
final selection = editorState.cursorSelection?.normalize; final selection = editorState.cursorSelection?.normalized;
if (selection == null || selection.isCollapsed) { if (selection == null || selection.isCollapsed) {
return; return;
} }
@ -65,7 +65,7 @@ void _handleCopy(EditorState editorState) async {
} }
void _pasteHTML(EditorState editorState, String html) { void _pasteHTML(EditorState editorState, String html) {
final selection = editorState.cursorSelection?.normalize; final selection = editorState.cursorSelection?.normalized;
if (selection == null) { if (selection == null) {
return; return;
} }
@ -234,7 +234,7 @@ Delta _lineContentToDelta(String lineContent) {
} }
void _handlePastePlainText(EditorState editorState, String plainText) { void _handlePastePlainText(EditorState editorState, String plainText) {
final selection = editorState.cursorSelection?.normalize; final selection = editorState.cursorSelection?.normalized;
if (selection == null) { if (selection == null) {
return; return;
} }
@ -300,7 +300,7 @@ void _handleCut(EditorState editorState) {
} }
void _deleteSelectedContent(EditorState editorState) { void _deleteSelectedContent(EditorState editorState) {
final selection = editorState.cursorSelection?.normalize; final selection = editorState.cursorSelection?.normalized;
if (selection == null || selection.isCollapsed) { if (selection == null || selection.isCollapsed) {
return; return;
} }

View file

@ -1,4 +1,4 @@
import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/core/location/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart'; import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart'; import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart'; import 'package:appflowy_editor/src/operation/transaction_builder.dart';

Some files were not shown because too many files have changed in this diff Show more