Просмотр исходного кода

chore: add selection_service documentation and resymbol shortcut service.

Lucas.Xu 2 лет назад
Родитель
Сommit
1907284534

+ 1 - 1
frontend/app_flowy/packages/flowy_editor/example/lib/main.dart

@@ -96,7 +96,7 @@ class _MyHomePageState extends State<MyHomePage> {
             );
             return FlowyEditor(
               editorState: _editorState,
-              keyEventHandler: const [],
+              keyEventHandlers: const [],
               shortcuts: [
                 // TODO: this won't work, just a example for now.
                 {

+ 11 - 0
frontend/app_flowy/packages/flowy_editor/lib/extensions/node_extensions.dart

@@ -0,0 +1,11 @@
+import 'package:flowy_editor/document/node.dart';
+import 'package:flowy_editor/extensions/object_extensions.dart';
+import 'package:flowy_editor/render/selection/selectable.dart';
+import 'package:flutter/material.dart';
+
+extension NodeExtensions on Node {
+  RenderBox? get renderBox =>
+      key?.currentContext?.findRenderObject()?.unwrapOrNull<RenderBox>();
+
+  Selectable? get selectable => key?.currentState?.unwrapOrNull<Selectable>();
+}

+ 11 - 9
frontend/app_flowy/packages/flowy_editor/lib/service/editor_service.dart

@@ -1,25 +1,27 @@
 import 'package:flowy_editor/render/selection/floating_shortcut_widget.dart';
-import 'package:flowy_editor/service/floating_shortcut_service.dart';
-import 'package:flowy_editor/service/flowy_key_event_handlers/arrow_keys_handler.dart';
-import 'package:flowy_editor/service/flowy_key_event_handlers/delete_nodes_handler.dart';
-import 'package:flowy_editor/service/flowy_key_event_handlers/delete_single_text_node_handler.dart';
-import 'package:flowy_editor/service/flowy_key_event_handlers/shortcut_handler.dart';
+import 'package:flowy_editor/service/shortcut_service.dart';
+import 'package:flowy_editor/service/internal_key_event_handlers/arrow_keys_handler.dart';
+import 'package:flowy_editor/service/internal_key_event_handlers/delete_nodes_handler.dart';
+import 'package:flowy_editor/service/internal_key_event_handlers/delete_single_text_node_handler.dart';
+import 'package:flowy_editor/service/internal_key_event_handlers/shortcut_handler.dart';
 import 'package:flowy_editor/service/keyboard_service.dart';
 import 'package:flowy_editor/service/selection_service.dart';
+import 'package:flowy_editor/editor_state.dart';
 
-import '../editor_state.dart';
 import 'package:flutter/material.dart';
 
 class FlowyEditor extends StatefulWidget {
   const FlowyEditor({
     Key? key,
     required this.editorState,
-    required this.keyEventHandler,
+    required this.keyEventHandlers,
     required this.shortcuts,
   }) : super(key: key);
 
   final EditorState editorState;
-  final List<FlowyKeyEventHandler> keyEventHandler;
+  final List<FlowyKeyEventHandler> keyEventHandlers;
+
+  /// Shortcusts
   final FloatingShortcuts shortcuts;
 
   @override
@@ -41,7 +43,7 @@ class _FlowyEditorState extends State<FlowyEditor> {
           flowyDeleteNodesHandler,
           deleteSingleTextNodeHandler,
           arrowKeysHandler,
-          ...widget.keyEventHandler,
+          ...widget.keyEventHandlers,
         ],
         editorState: editorState,
         child: FloatingShortcut(

+ 0 - 0
frontend/app_flowy/packages/flowy_editor/lib/service/flowy_key_event_handlers/arrow_keys_handler.dart → frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/arrow_keys_handler.dart


+ 0 - 0
frontend/app_flowy/packages/flowy_editor/lib/service/flowy_key_event_handlers/delete_nodes_handler.dart → frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delete_nodes_handler.dart


+ 0 - 0
frontend/app_flowy/packages/flowy_editor/lib/service/flowy_key_event_handlers/delete_single_text_node_handler.dart → frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delete_single_text_node_handler.dart


+ 0 - 0
frontend/app_flowy/packages/flowy_editor/lib/service/flowy_key_event_handlers/shortcut_handler.dart → frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/shortcut_handler.dart


+ 46 - 42
frontend/app_flowy/packages/flowy_editor/lib/service/selection_service.dart

@@ -1,7 +1,8 @@
 import 'package:flowy_editor/render/selection/cursor_widget.dart';
 import 'package:flowy_editor/render/selection/flowy_selection_widget.dart';
 import 'package:flowy_editor/extensions/object_extensions.dart';
-import 'package:flowy_editor/service/floating_shortcut_service.dart';
+import 'package:flowy_editor/extensions/node_extensions.dart';
+import 'package:flowy_editor/service/shortcut_service.dart';
 import 'package:flutter/gestures.dart';
 import 'package:flutter/material.dart';
 
@@ -11,58 +12,65 @@ import '../render/selection/selectable.dart';
 
 /// Process selection and cursor
 mixin FlowySelectionService<T extends StatefulWidget> on State<T> {
-  /// [Pan] and [Tap] must be mutually exclusive.
-  /// Pan
-  Offset? panStartOffset;
-  Offset? panEndOffset;
-
-  /// Tap
-  Offset? tapOffset;
-
+  /// [start] and [end] are the offsets under the global coordinate system.
   void updateSelection(Offset start, Offset end);
 
+  /// [start] is the offset under the global coordinate system.
   void updateCursor(Offset start);
 
-  /// Returns selected node(s)
-  /// Returns empty list if no nodes are being selected.
+  /// Returns selected [Node]s. Empty list would be returned
+  ///   if no nodes are being selected.
+  ///
+  ///
+  /// [start] and [end] are the offsets under the global coordinate system.
+  ///
+  /// If end is not null, it means multiple selection,
+  ///   otherwise single selection.
   List<Node> getSelectedNodes(Offset start, [Offset? end]);
 
-  /// Compute selected node triggered by [Tap]
-  Node? computeSelectedNodeInOffset(
-    Node node,
-    Offset offset,
-  );
+  /// Return the [Node] or [Null] in single selection.
+  ///
+  /// [start] is the offset under the global coordinate system.
+  Node? computeSelectedNodeInOffset(Node node, Offset offset);
 
-  /// Compute selected nodes triggered by [Pan]
+  /// Return the [Node]s in multiple selection. Emtpy list would be returned
+  ///   if no nodes are in range.
+  ///
+  /// [start] is the offset under the global coordinate system.
   List<Node> computeSelectedNodesInRange(
     Node node,
     Offset start,
     Offset end,
   );
 
-  /// Pan
+  /// Return [bool] to identify the [Node] is in Range or not.
+  ///
+  /// [start] and [end] are the offsets under the global coordinate system.
   bool isNodeInSelection(
     Node node,
     Offset start,
     Offset end,
   );
 
-  /// Tap
-  bool isNodeInOffset(
-    Node node,
-    Offset offset,
-  );
+  /// Return [bool] to identify the [Node] contains [Offset] or not.
+  ///
+  /// [start] is the offset under the global coordinate system.
+  bool isNodeInOffset(Node node, Offset offset);
 }
 
 class FlowySelection extends StatefulWidget {
   const FlowySelection({
     Key? key,
+    this.cursorColor = Colors.black,
+    this.selectionColor = const Color.fromARGB(60, 61, 61, 213),
     required this.editorState,
     required this.child,
   }) : super(key: key);
 
   final EditorState editorState;
   final Widget child;
+  final Color cursorColor;
+  final Color selectionColor;
 
   @override
   State<FlowySelection> createState() => _FlowySelectionState();
@@ -75,6 +83,14 @@ class _FlowySelectionState extends State<FlowySelection>
   final List<OverlayEntry> _selectionOverlays = [];
   final List<OverlayEntry> _cursorOverlays = [];
 
+  /// [Pan] and [Tap] must be mutually exclusive.
+  /// Pan
+  Offset? panStartOffset;
+  Offset? panEndOffset;
+
+  /// Tap
+  Offset? tapOffset;
+
   EditorState get editorState => widget.editorState;
 
   @override
@@ -123,7 +139,7 @@ class _FlowySelectionState extends State<FlowySelection>
       for (final rect in selectionRects) {
         final overlay = OverlayEntry(
           builder: ((context) => SelectionWidget(
-                color: Colors.yellow.withAlpha(100),
+                color: widget.selectionColor,
                 layerLink: node.layerLink,
                 rect: rect,
               )),
@@ -154,7 +170,7 @@ class _FlowySelectionState extends State<FlowySelection>
       builder: ((context) => CursorWidget(
             key: _cursorKey,
             rect: rect,
-            color: Colors.red,
+            color: widget.cursorColor,
             layerLink: selectedNode.layerLink,
           )),
     );
@@ -165,16 +181,10 @@ class _FlowySelectionState extends State<FlowySelection>
   @override
   List<Node> getSelectedNodes(Offset start, [Offset? end]) {
     if (end != null) {
-      return computeSelectedNodesInRange(
-        editorState.document.root,
-        start,
-        end,
-      );
+      return computeSelectedNodesInRange(editorState.document.root, start, end);
     } else {
-      final reuslt = computeSelectedNodeInOffset(
-        editorState.document.root,
-        start,
-      );
+      final reuslt =
+          computeSelectedNodeInOffset(editorState.document.root, start);
       if (reuslt != null) {
         return [reuslt];
       }
@@ -190,13 +200,11 @@ class _FlowySelectionState extends State<FlowySelection>
         return result;
       }
     }
-
     if (node.parent != null && node.key != null) {
       if (isNodeInOffset(node, offset)) {
         return node;
       }
     }
-
     return null;
   }
 
@@ -217,9 +225,7 @@ class _FlowySelectionState extends State<FlowySelection>
 
   @override
   bool isNodeInOffset(Node node, Offset offset) {
-    assert(node.key != null);
-    final renderBox =
-        node.key?.currentContext?.findRenderObject() as RenderBox?;
+    final renderBox = node.renderBox;
     if (renderBox != null) {
       final boxOffset = renderBox.localToGlobal(Offset.zero);
       final boxRect = boxOffset & renderBox.size;
@@ -230,9 +236,7 @@ class _FlowySelectionState extends State<FlowySelection>
 
   @override
   bool isNodeInSelection(Node node, Offset start, Offset end) {
-    assert(node.key != null);
-    final renderBox =
-        node.key?.currentContext?.findRenderObject() as RenderBox?;
+    final renderBox = node.renderBox;
     if (renderBox != null) {
       final rect = Rect.fromPoints(start, end);
       final boxOffset = renderBox.localToGlobal(Offset.zero);

+ 1 - 1
frontend/app_flowy/packages/flowy_editor/lib/service/service.dart

@@ -1,4 +1,4 @@
-import 'package:flowy_editor/service/floating_shortcut_service.dart';
+import 'package:flowy_editor/service/shortcut_service.dart';
 import 'package:flowy_editor/service/selection_service.dart';
 import 'package:flutter/material.dart';
 

+ 0 - 0
frontend/app_flowy/packages/flowy_editor/lib/service/floating_shortcut_service.dart → frontend/app_flowy/packages/flowy_editor/lib/service/shortcut_service.dart