Kaynağa Gözat

Refactoring 3 scope objects into one

Anatoly Pulyaevskiy 6 yıl önce
ebeveyn
işleme
f938f7d635

+ 13
- 0
packages/zefyr/CHANGELOG.md Dosyayı Görüntüle

@@ -1,3 +1,16 @@
1
+## Unreleased
2
+
3
+* Added non-scrollable `ZefyrView` widget which allows previewing Notus documents inside
4
+  layouts using their own scrollables like ListView.
5
+* Breaking change: renamed `EditableRichText` to `ZefyrRichText`. User code is unlikely to be
6
+  affected unless you've extended Zefyr with custom implementations of block widgets.
7
+* Breaking change: renamed `RenderEditableParagraph` to `RenderZefyrParagraph`. User code is
8
+  unlikely to be affected unless you've extended Zefyr with custom implementations of block widgets.
9
+* Added `ZefyrScope` class - replaces previously used scope objects `ZefyrEditableTextScope` and
10
+  `ZefyrEditorScope`. Unified all shared resources under one class.
11
+* Breaking change: removed `ZefyrEditor.of` and `ZefyrEditableText.of` static methods.
12
+  Use `ZefyrScope.of` instead.
13
+
1 14
 ## 0.3.0
2 15
 
3 16
 This version introduces new widget `ZefyrScaffold` which allows embedding Zefyr in custom

+ 9
- 9
packages/zefyr/lib/src/widgets/buttons.dart Dosyayı Görüntüle

@@ -7,7 +7,7 @@ import 'package:image_picker/image_picker.dart';
7 7
 import 'package:notus/notus.dart';
8 8
 import 'package:url_launcher/url_launcher.dart';
9 9
 
10
-import 'editor.dart';
10
+import 'scope.dart';
11 11
 import 'theme.dart';
12 12
 import 'toolbar.dart';
13 13
 
@@ -94,7 +94,7 @@ class ZefyrButton extends StatelessWidget {
94 94
     }
95 95
   }
96 96
 
97
-  Color _getColor(ZefyrEditorScope editor, ZefyrToolbarTheme theme) {
97
+  Color _getColor(ZefyrScope editor, ZefyrToolbarTheme theme) {
98 98
     if (isAttributeAction) {
99 99
       final attribute = kZefyrToolbarAttributeActions[action];
100 100
       final isToggled = (attribute is NotusAttribute)
@@ -106,7 +106,7 @@ class ZefyrButton extends StatelessWidget {
106 106
   }
107 107
 
108 108
   VoidCallback _getPressedHandler(
109
-      ZefyrEditorScope editor, ZefyrToolbarState toolbar) {
109
+      ZefyrScope editor, ZefyrToolbarState toolbar) {
110 110
     if (onPressed != null) {
111 111
       return onPressed;
112 112
     } else if (isAttributeAction) {
@@ -123,7 +123,7 @@ class ZefyrButton extends StatelessWidget {
123 123
     return null;
124 124
   }
125 125
 
126
-  void _toggleAttribute(NotusAttribute attribute, ZefyrEditorScope editor) {
126
+  void _toggleAttribute(NotusAttribute attribute, ZefyrScope editor) {
127 127
     final isToggled = editor.selectionStyle.containsSame(attribute);
128 128
     if (isToggled) {
129 129
       editor.formatSelection(attribute.unset);
@@ -303,7 +303,7 @@ class _LinkButtonState extends State<LinkButton> {
303 303
   final TextEditingController _inputController = TextEditingController();
304 304
   Key _inputKey;
305 305
   bool _formatError = false;
306
-  ZefyrEditorScope _editor;
306
+  ZefyrScope _editor;
307 307
 
308 308
   bool get isEditing => _inputKey != null;
309 309
 
@@ -491,7 +491,7 @@ class _LinkInput extends StatefulWidget {
491 491
 class _LinkInputState extends State<_LinkInput> {
492 492
   final FocusNode _focusNode = FocusNode();
493 493
 
494
-  ZefyrEditorScope _editor;
494
+  ZefyrScope _editor;
495 495
   bool _didAutoFocus = false;
496 496
 
497 497
   @override
@@ -505,15 +505,15 @@ class _LinkInputState extends State<_LinkInput> {
505 505
     final toolbar = ZefyrToolbar.of(context);
506 506
 
507 507
     if (_editor != toolbar.editor) {
508
-      _editor?.setToolbarFocusNode(null);
508
+      _editor?.toolbarFocusNode = null;
509 509
       _editor = toolbar.editor;
510
-      _editor.setToolbarFocusNode(_focusNode);
510
+      _editor.toolbarFocusNode = _focusNode;
511 511
     }
512 512
   }
513 513
 
514 514
   @override
515 515
   void dispose() {
516
-    _editor?.setToolbarFocusNode(null);
516
+    _editor?.toolbarFocusNode = null;
517 517
     _focusNode.dispose();
518 518
     _editor = null;
519 519
     super.dispose();

+ 19
- 34
packages/zefyr/lib/src/widgets/common.dart Dosyayı Görüntüle

@@ -6,12 +6,11 @@ import 'package:flutter/widgets.dart';
6 6
 import 'package:notus/notus.dart';
7 7
 
8 8
 import 'editable_box.dart';
9
-import 'editable_text.dart';
10 9
 import 'horizontal_rule.dart';
11 10
 import 'image.dart';
12 11
 import 'rich_text.dart';
12
+import 'scope.dart';
13 13
 import 'theme.dart';
14
-import 'view.dart';
15 14
 
16 15
 /// Raw widget representing a single line of rich text document in Zefyr editor.
17 16
 ///
@@ -44,37 +43,31 @@ class _RawZefyrLineState extends State<RawZefyrLine> {
44 43
 
45 44
   @override
46 45
   Widget build(BuildContext context) {
47
-    ZefyrViewState view = ZefyrView.of(context);
48
-    ZefyrEditableTextScope editable;
49
-    if (view == null) {
50
-      editable = ZefyrEditableText.of(context);
51
-    }
52
-
53
-    final isEditable = editable != null;
46
+    final scope = ZefyrScope.of(context);
54 47
 
55
-    if (isEditable) {
56
-      ensureVisible(context);
48
+    if (scope.isEditable) {
49
+      ensureVisible(context, scope);
57 50
     }
58 51
     final theme = ZefyrTheme.of(context);
59 52
 
60 53
     Widget content;
61 54
     if (widget.node.hasEmbed) {
62
-      content = buildEmbed(context, view, editable);
55
+      content = buildEmbed(context, scope);
63 56
     } else {
64 57
       assert(widget.style != null);
65 58
 
66
-      final text = EditableRichText(
59
+      final text = ZefyrRichText(
67 60
         node: widget.node,
68 61
         text: buildText(context),
69 62
       );
70
-      if (isEditable) {
63
+      if (scope.isEditable) {
71 64
         content = EditableBox(
72 65
           child: text,
73 66
           node: widget.node,
74 67
           layerLink: _link,
75
-          renderContext: editable.renderContext,
76
-          showCursor: editable.showCursor,
77
-          selection: editable.selection,
68
+          renderContext: scope.renderContext,
69
+          showCursor: scope.showCursor,
70
+          selection: scope.selection,
78 71
           selectionColor: theme.selectionColor,
79 72
         );
80 73
         content = CompositedTransformTarget(link: _link, child: content);
@@ -89,10 +82,9 @@ class _RawZefyrLineState extends State<RawZefyrLine> {
89 82
     return content;
90 83
   }
91 84
 
92
-  void ensureVisible(BuildContext context) {
93
-    final editable = ZefyrEditableText.of(context);
94
-    if (editable.selection.isCollapsed &&
95
-        widget.node.containsOffset(editable.selection.extentOffset)) {
85
+  void ensureVisible(BuildContext context, ZefyrScope scope) {
86
+    if (scope.selection.isCollapsed &&
87
+        widget.node.containsOffset(scope.selection.extentOffset)) {
96 88
       WidgetsBinding.instance.addPostFrameCallback((_) {
97 89
         bringIntoView(context);
98 90
       });
@@ -150,10 +142,7 @@ class _RawZefyrLineState extends State<RawZefyrLine> {
150 142
     return result;
151 143
   }
152 144
 
153
-  Widget buildEmbed(BuildContext context, ZefyrViewState view,
154
-      ZefyrEditableTextScope editable) {
155
-    final isEditable = editable != null;
156
-
145
+  Widget buildEmbed(BuildContext context, ZefyrScope scope) {
157 146
     final theme = ZefyrTheme.of(context);
158 147
 
159 148
     EmbedNode node = widget.node.children.single;
@@ -163,16 +152,12 @@ class _RawZefyrLineState extends State<RawZefyrLine> {
163 152
     if (embed.type == EmbedType.horizontalRule) {
164 153
       result = ZefyrHorizontalRule(node: node);
165 154
     } else if (embed.type == EmbedType.image) {
166
-      if (isEditable) {
167
-        result = ZefyrImage(node: node, delegate: editable.imageDelegate);
168
-      } else {
169
-        result = ZefyrImage(node: node, delegate: view.imageDelegate);
170
-      }
155
+      result = ZefyrImage(node: node, delegate: scope.imageDelegate);
171 156
     } else {
172 157
       throw new UnimplementedError('Unimplemented embed type ${embed.type}');
173 158
     }
174 159
 
175
-    if (!isEditable) {
160
+    if (!scope.isEditable) {
176 161
       return result;
177 162
     }
178 163
 
@@ -180,9 +165,9 @@ class _RawZefyrLineState extends State<RawZefyrLine> {
180 165
       child: result,
181 166
       node: widget.node,
182 167
       layerLink: _link,
183
-      renderContext: editable.renderContext,
184
-      showCursor: editable.showCursor,
185
-      selection: editable.selection,
168
+      renderContext: scope.renderContext,
169
+      showCursor: scope.showCursor,
170
+      selection: scope.selection,
186 171
       selectionColor: theme.selectionColor,
187 172
     );
188 173
   }

+ 42
- 0
packages/zefyr/lib/src/widgets/cursor_timer.dart Dosyayı Görüntüle

@@ -0,0 +1,42 @@
1
+import 'dart:async';
2
+
3
+import 'package:flutter/material.dart';
4
+
5
+/// Helper class that keeps state relevant to the editing cursor.
6
+class CursorTimer {
7
+  static const _kCursorBlinkHalfPeriod = const Duration(milliseconds: 500);
8
+
9
+  Timer _timer;
10
+  final ValueNotifier<bool> _showCursor = new ValueNotifier<bool>(false);
11
+
12
+  ValueNotifier<bool> get value => _showCursor;
13
+
14
+  void _cursorTick(Timer timer) {
15
+    _showCursor.value = !_showCursor.value;
16
+  }
17
+
18
+  /// Starts cursor timer.
19
+  void start() {
20
+    _showCursor.value = true;
21
+    _timer = new Timer.periodic(_kCursorBlinkHalfPeriod, _cursorTick);
22
+  }
23
+
24
+  /// Stops cursor timer.
25
+  void stop() {
26
+    _timer?.cancel();
27
+    _timer = null;
28
+    _showCursor.value = false;
29
+  }
30
+
31
+  /// Starts or stops cursor timer based on current state of [focusNode]
32
+  /// and [selection].
33
+  void startOrStop(FocusNode focusNode, TextSelection selection) {
34
+    final hasFocus = focusNode.hasFocus;
35
+    final selectionCollapsed = selection.isCollapsed;
36
+    if (_timer == null && hasFocus && selectionCollapsed) {
37
+      start();
38
+    } else if (_timer != null && (!hasFocus || !selectionCollapsed)) {
39
+      stop();
40
+    }
41
+  }
42
+}

+ 8
- 61
packages/zefyr/lib/src/widgets/editable_text.dart Dosyayı Görüntüle

@@ -1,8 +1,6 @@
1 1
 // Copyright (c) 2018, the Zefyr project authors.  Please see the AUTHORS file
2 2
 // for details. All rights reserved. Use of this source code is governed by a
3 3
 // BSD-style license that can be found in the LICENSE file.
4
-import 'dart:async';
5
-
6 4
 import 'package:collection/collection.dart';
7 5
 import 'package:flutter/cupertino.dart';
8 6
 import 'package:flutter/widgets.dart';
@@ -11,6 +9,7 @@ import 'package:notus/notus.dart';
11 9
 import 'code.dart';
12 10
 import 'common.dart';
13 11
 import 'controller.dart';
12
+import 'cursor_timer.dart';
14 13
 import 'editable_box.dart';
15 14
 import 'editor.dart';
16 15
 import 'image.dart';
@@ -49,21 +48,15 @@ class ZefyrEditableText extends StatefulWidget {
49 48
   /// Padding around editable area.
50 49
   final EdgeInsets padding;
51 50
 
52
-  static ZefyrEditableTextScope of(BuildContext context) {
53
-    final ZefyrEditableTextScope result =
54
-        context.inheritFromWidgetOfExactType(ZefyrEditableTextScope);
55
-    return result;
56
-  }
57
-
58 51
   @override
59 52
   _ZefyrEditableTextState createState() => new _ZefyrEditableTextState();
60 53
 }
61 54
 
62 55
 /// Provides access to shared state of [ZefyrEditableText].
63
-class ZefyrEditableTextScope extends InheritedWidget {
56
+class _ZefyrEditableTextScope extends InheritedWidget {
64 57
   static const _kEquality = const SetEquality<RenderEditableBox>();
65 58
 
66
-  ZefyrEditableTextScope({
59
+  _ZefyrEditableTextScope({
67 60
     Key key,
68 61
     @required Widget child,
69 62
     @required this.selection,
@@ -80,7 +73,7 @@ class ZefyrEditableTextScope extends InheritedWidget {
80 73
   final Set<RenderEditableBox> _activeBoxes;
81 74
 
82 75
   @override
83
-  bool updateShouldNotify(ZefyrEditableTextScope oldWidget) {
76
+  bool updateShouldNotify(_ZefyrEditableTextScope oldWidget) {
84 77
     return selection != oldWidget.selection ||
85 78
         showCursor != oldWidget.showCursor ||
86 79
         imageDelegate != oldWidget.imageDelegate ||
@@ -127,7 +120,6 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
127 120
   Widget build(BuildContext context) {
128 121
     FocusScope.of(context).reparentIfNeeded(focusNode);
129 122
     super.build(context); // See AutomaticKeepAliveState.
130
-    ZefyrEditor.of(context);
131 123
 
132 124
     Widget body = ListBody(children: _buildChildren(context));
133 125
     if (widget.padding != null) {
@@ -149,13 +141,7 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
149 141
       ));
150 142
     }
151 143
 
152
-    return new ZefyrEditableTextScope(
153
-      selection: selection,
154
-      showCursor: showCursor,
155
-      renderContext: renderContext,
156
-      imageDelegate: widget.imageDelegate,
157
-      child: Stack(fit: StackFit.expand, children: layers),
158
-    );
144
+    return Stack(fit: StackFit.expand, children: layers);
159 145
   }
160 146
 
161 147
   @override
@@ -196,9 +182,9 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
196 182
   // Private members
197 183
   //
198 184
 
199
-  final ScrollController _scrollController = new ScrollController();
200
-  final ZefyrRenderContext _renderContext = new ZefyrRenderContext();
201
-  final _CursorTimer _cursorTimer = new _CursorTimer();
185
+  final ScrollController _scrollController = ScrollController();
186
+  final ZefyrRenderContext _renderContext = ZefyrRenderContext();
187
+  final CursorTimer _cursorTimer = CursorTimer();
202 188
   InputConnectionController _input;
203 189
   bool _didAutoFocus = false;
204 190
 
@@ -297,42 +283,3 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
297 283
     });
298 284
   }
299 285
 }
300
-
301
-/// Helper class that keeps state relevant to the cursor.
302
-class _CursorTimer {
303
-  static const _kCursorBlinkHalfPeriod = const Duration(milliseconds: 500);
304
-
305
-  Timer _timer;
306
-  final ValueNotifier<bool> _showCursor = new ValueNotifier<bool>(false);
307
-
308
-  ValueNotifier<bool> get value => _showCursor;
309
-
310
-  void _cursorTick(Timer timer) {
311
-    _showCursor.value = !_showCursor.value;
312
-  }
313
-
314
-  /// Starts cursor timer.
315
-  void start() {
316
-    _showCursor.value = true;
317
-    _timer = new Timer.periodic(_kCursorBlinkHalfPeriod, _cursorTick);
318
-  }
319
-
320
-  /// Stops cursor timer.
321
-  void stop() {
322
-    _timer?.cancel();
323
-    _timer = null;
324
-    _showCursor.value = false;
325
-  }
326
-
327
-  /// Starts or stops cursor timer based on current state of [focusNode]
328
-  /// and [selection].
329
-  void startOrStop(FocusNode focusNode, TextSelection selection) {
330
-    final hasFocus = focusNode.hasFocus;
331
-    final selectionCollapsed = selection.isCollapsed;
332
-    if (_timer == null && hasFocus && selectionCollapsed) {
333
-      start();
334
-    } else if (_timer != null && (!hasFocus || !selectionCollapsed)) {
335
-      stop();
336
-    }
337
-  }
338
-}

+ 9
- 163
packages/zefyr/lib/src/widgets/editor.dart Dosyayı Görüntüle

@@ -2,162 +2,15 @@
2 2
 // for details. All rights reserved. Use of this source code is governed by a
3 3
 // BSD-style license that can be found in the LICENSE file.
4 4
 import 'package:flutter/widgets.dart';
5
-import 'package:notus/notus.dart';
6 5
 
7 6
 import 'controller.dart';
8 7
 import 'editable_text.dart';
9 8
 import 'image.dart';
10 9
 import 'scaffold.dart';
10
+import 'scope.dart';
11 11
 import 'theme.dart';
12 12
 import 'toolbar.dart';
13 13
 
14
-class ZefyrEditorScope extends ChangeNotifier {
15
-  ZefyrEditorScope({
16
-    @required ZefyrImageDelegate imageDelegate,
17
-    @required ZefyrController controller,
18
-    @required FocusNode focusNode,
19
-    @required FocusScopeNode focusScope,
20
-  })  : _controller = controller,
21
-        _imageDelegate = imageDelegate,
22
-        _focusScope = focusScope,
23
-        _focusNode = focusNode {
24
-    _selectionStyle = _controller.getSelectionStyle();
25
-    _selection = _controller.selection;
26
-    _controller.addListener(_handleControllerChange);
27
-    _focusNode.addListener(_handleFocusChange);
28
-  }
29
-
30
-  bool _disposed = false;
31
-
32
-  ZefyrImageDelegate _imageDelegate;
33
-  ZefyrImageDelegate get imageDelegate => _imageDelegate;
34
-
35
-  FocusScopeNode _focusScope;
36
-  FocusNode _focusNode;
37
-
38
-  ZefyrController _controller;
39
-  NotusStyle get selectionStyle => _selectionStyle;
40
-  NotusStyle _selectionStyle;
41
-  TextSelection get selection => _selection;
42
-  TextSelection _selection;
43
-
44
-  @override
45
-  void dispose() {
46
-    assert(!_disposed);
47
-    _controller.removeListener(_handleControllerChange);
48
-    _focusNode.removeListener(_handleFocusChange);
49
-    _disposed = true;
50
-    super.dispose();
51
-  }
52
-
53
-  void _updateControllerIfNeeded(ZefyrController value) {
54
-    if (_controller != value) {
55
-      _controller.removeListener(_handleControllerChange);
56
-      _controller = value;
57
-      _selectionStyle = _controller.getSelectionStyle();
58
-      _selection = _controller.selection;
59
-      _controller.addListener(_handleControllerChange);
60
-      notifyListeners();
61
-    }
62
-  }
63
-
64
-  void _updateFocusNodeIfNeeded(FocusNode value) {
65
-    if (_focusNode != value) {
66
-      _focusNode.removeListener(_handleFocusChange);
67
-      _focusNode = value;
68
-      _focusNode.addListener(_handleFocusChange);
69
-      notifyListeners();
70
-    }
71
-  }
72
-
73
-  void _updateImageDelegateIfNeeded(ZefyrImageDelegate value) {
74
-    if (_imageDelegate != value) {
75
-      _imageDelegate = value;
76
-      notifyListeners();
77
-    }
78
-  }
79
-
80
-  void _handleControllerChange() {
81
-    assert(!_disposed);
82
-    final attrs = _controller.getSelectionStyle();
83
-    final selection = _controller.selection;
84
-    if (_selectionStyle != attrs || _selection != selection) {
85
-      _selectionStyle = attrs;
86
-      _selection = _controller.selection;
87
-      notifyListeners();
88
-    }
89
-  }
90
-
91
-  void _handleFocusChange() {
92
-    assert(!_disposed);
93
-    if (focusOwner == FocusOwner.none && !_selection.isCollapsed) {
94
-      // Collapse selection if there is nothing focused.
95
-      _controller.updateSelection(_selection.copyWith(
96
-        baseOffset: _selection.extentOffset,
97
-        extentOffset: _selection.extentOffset,
98
-      ));
99
-    }
100
-    notifyListeners();
101
-  }
102
-
103
-  FocusNode _toolbarFocusNode;
104
-
105
-  void setToolbarFocusNode(FocusNode node) {
106
-    assert(!_disposed || node == null);
107
-    if (_toolbarFocusNode != node) {
108
-      _toolbarFocusNode?.removeListener(_handleFocusChange);
109
-      _toolbarFocusNode = node;
110
-      _toolbarFocusNode?.addListener(_handleFocusChange);
111
-      // We do not notify listeners here because it will happen when
112
-      // focus state changes, see [_handleFocusChange].
113
-    }
114
-  }
115
-
116
-  FocusOwner get focusOwner {
117
-    assert(!_disposed);
118
-    if (_focusNode.hasFocus) {
119
-      return FocusOwner.editor;
120
-    } else if (_toolbarFocusNode?.hasFocus == true) {
121
-      return FocusOwner.toolbar;
122
-    } else {
123
-      return FocusOwner.none;
124
-    }
125
-  }
126
-
127
-  void updateSelection(TextSelection value,
128
-      {ChangeSource source: ChangeSource.remote}) {
129
-    assert(!_disposed);
130
-    _controller.updateSelection(value, source: source);
131
-  }
132
-
133
-  void formatSelection(NotusAttribute value) {
134
-    assert(!_disposed);
135
-    _controller.formatSelection(value);
136
-  }
137
-
138
-  void focus() {
139
-    assert(!_disposed);
140
-    _focusScope.requestFocus(_focusNode);
141
-  }
142
-
143
-  void hideKeyboard() {
144
-    assert(!_disposed);
145
-    _focusNode.unfocus();
146
-  }
147
-}
148
-
149
-class _ZefyrEditorScope extends InheritedWidget {
150
-  final ZefyrEditorScope scope;
151
-
152
-  _ZefyrEditorScope({Key key, Widget child, @required this.scope})
153
-      : super(key: key, child: child);
154
-
155
-  @override
156
-  bool updateShouldNotify(_ZefyrEditorScope oldWidget) {
157
-    return oldWidget.scope != scope;
158
-  }
159
-}
160
-
161 14
 /// Widget for editing Zefyr documents.
162 15
 class ZefyrEditor extends StatefulWidget {
163 16
   const ZefyrEditor({
@@ -183,19 +36,13 @@ class ZefyrEditor extends StatefulWidget {
183 36
   /// Padding around editable area.
184 37
   final EdgeInsets padding;
185 38
 
186
-  static ZefyrEditorScope of(BuildContext context) {
187
-    _ZefyrEditorScope widget =
188
-        context.inheritFromWidgetOfExactType(_ZefyrEditorScope);
189
-    return widget.scope;
190
-  }
191
-
192 39
   @override
193 40
   _ZefyrEditorState createState() => new _ZefyrEditorState();
194 41
 }
195 42
 
196 43
 class _ZefyrEditorState extends State<ZefyrEditor> {
197 44
   ZefyrImageDelegate _imageDelegate;
198
-  ZefyrEditorScope _scope;
45
+  ZefyrScope _scope;
199 46
   ZefyrThemeData _themeData;
200 47
   GlobalKey<ZefyrToolbarState> _toolbarKey;
201 48
   ZefyrScaffoldState _scaffold;
@@ -231,6 +78,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
231 78
     } else if (!hasToolbar) {
232 79
       showToolbar();
233 80
     } else {
81
+      // TODO: is there a nicer way to do this?
234 82
       WidgetsBinding.instance.addPostFrameCallback((_) {
235 83
         _toolbarKey?.currentState?.markNeedsRebuild();
236 84
       });
@@ -246,11 +94,11 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
246 94
   @override
247 95
   void didUpdateWidget(ZefyrEditor oldWidget) {
248 96
     super.didUpdateWidget(oldWidget);
249
-    _scope._updateControllerIfNeeded(widget.controller);
250
-    _scope._updateFocusNodeIfNeeded(widget.focusNode);
97
+    _scope.controller = widget.controller;
98
+    _scope.focusNode = widget.focusNode;
251 99
     if (widget.imageDelegate != oldWidget.imageDelegate) {
252 100
       _imageDelegate = widget.imageDelegate ?? new ZefyrDefaultImageDelegate();
253
-      _scope._updateImageDelegateIfNeeded(_imageDelegate);
101
+      _scope.imageDelegate = _imageDelegate;
254 102
     }
255 103
   }
256 104
 
@@ -264,7 +112,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
264 112
         : fallbackTheme;
265 113
 
266 114
     if (_scope == null) {
267
-      _scope = ZefyrEditorScope(
115
+      _scope = ZefyrScope.editable(
268 116
         imageDelegate: _imageDelegate,
269 117
         controller: widget.controller,
270 118
         focusNode: widget.focusNode,
@@ -273,9 +121,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
273 121
       _scope.addListener(_handleChange);
274 122
     } else {
275 123
       final focusScope = FocusScope.of(context);
276
-      if (focusScope != _scope._focusScope) {
277
-        _scope._focusScope = focusScope;
278
-      }
124
+      _scope.focusScope = focusScope;
279 125
     }
280 126
 
281 127
     final scaffold = ZefyrScaffold.of(context);
@@ -309,7 +155,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
309 155
 
310 156
     return ZefyrTheme(
311 157
       data: _themeData,
312
-      child: _ZefyrEditorScope(
158
+      child: ZefyrScopeAccess(
313 159
         scope: _scope,
314 160
         child: editable,
315 161
       ),

+ 3
- 2
packages/zefyr/lib/src/widgets/render_context.dart Dosyayı Görüntüle

@@ -97,9 +97,10 @@ class ZefyrRenderContext extends ChangeNotifier {
97 97
   /// Returns closest render box to the specified global [point].
98 98
   ///
99 99
   /// If [point] is inside of one of active render boxes that box is returned.
100
-  /// Otherwise this method checks if [point] is to the left or to the right
100
+  /// If no box found this method checks if [point] is to the left or to the right
101 101
   /// side of a box, e.g. if vertical offset of this point is inside of one of
102
-  /// the active boxes. If it is then that box is returned.
102
+  /// the active boxes. If it is then that box is returned. If not then this
103
+  /// method picks a box with shortest vertical distance to this [point].
103 104
   RenderEditableProxyBox closestBoxForGlobalPoint(Offset point) {
104 105
     assert(!_disposed);
105 106
     RenderEditableProxyBox box = boxForGlobalPoint(point);

+ 7
- 6
packages/zefyr/lib/src/widgets/rich_text.dart Dosyayı Görüntüle

@@ -11,8 +11,9 @@ import 'package:notus/notus.dart';
11 11
 import 'caret.dart';
12 12
 import 'editable_box.dart';
13 13
 
14
-class EditableRichText extends LeafRenderObjectWidget {
15
-  EditableRichText({
14
+/// Represents single paragraph of Zefyr rich-text.
15
+class ZefyrRichText extends LeafRenderObjectWidget {
16
+  ZefyrRichText({
16 17
     @required this.node,
17 18
     @required this.text,
18 19
   }) : assert(node != null && text != null);
@@ -22,7 +23,7 @@ class EditableRichText extends LeafRenderObjectWidget {
22 23
 
23 24
   @override
24 25
   RenderObject createRenderObject(BuildContext context) {
25
-    return new RenderEditableParagraph(
26
+    return new RenderZefyrParagraph(
26 27
       text,
27 28
       node: node,
28 29
       textDirection: Directionality.of(context),
@@ -31,16 +32,16 @@ class EditableRichText extends LeafRenderObjectWidget {
31 32
 
32 33
   @override
33 34
   void updateRenderObject(
34
-      BuildContext context, RenderEditableParagraph renderObject) {
35
+      BuildContext context, RenderZefyrParagraph renderObject) {
35 36
     renderObject
36 37
       ..text = text
37 38
       ..node = node;
38 39
   }
39 40
 }
40 41
 
41
-class RenderEditableParagraph extends RenderParagraph
42
+class RenderZefyrParagraph extends RenderParagraph
42 43
     implements RenderEditableBox {
43
-  RenderEditableParagraph(
44
+  RenderZefyrParagraph(
44 45
     TextSpan text, {
45 46
     @required ContainerNode node,
46 47
     TextAlign textAlign: TextAlign.start,

+ 207
- 0
packages/zefyr/lib/src/widgets/scope.dart Dosyayı Görüntüle

@@ -0,0 +1,207 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:notus/notus.dart';
3
+
4
+import 'controller.dart';
5
+import 'cursor_timer.dart';
6
+import 'image.dart';
7
+import 'render_context.dart';
8
+
9
+class ZefyrScope extends ChangeNotifier {
10
+  ZefyrScope.view({@required ZefyrImageDelegate imageDelegate})
11
+      : assert(imageDelegate != null),
12
+        isEditable = false,
13
+        _imageDelegate = imageDelegate;
14
+
15
+  ZefyrScope.editable({
16
+    @required ZefyrController controller,
17
+    @required ZefyrImageDelegate imageDelegate,
18
+    @required FocusNode focusNode,
19
+    @required FocusScopeNode focusScope,
20
+  })  : assert(controller != null),
21
+        assert(imageDelegate != null),
22
+        assert(focusNode != null),
23
+        assert(focusScope != null),
24
+        isEditable = true,
25
+        _controller = controller,
26
+        _imageDelegate = imageDelegate,
27
+        _focusNode = focusNode,
28
+        _focusScope = focusScope,
29
+        _cursorTimer = CursorTimer(),
30
+        _renderContext = ZefyrRenderContext() {
31
+    _selectionStyle = _controller.getSelectionStyle();
32
+    _selection = _controller.selection;
33
+    _controller.addListener(_handleControllerChange);
34
+    _focusNode.addListener(_handleFocusChange);
35
+  }
36
+
37
+  ZefyrImageDelegate _imageDelegate;
38
+  ZefyrImageDelegate get imageDelegate => _imageDelegate;
39
+  set imageDelegate(ZefyrImageDelegate value) {
40
+    assert(value != null);
41
+    if (_imageDelegate != value) {
42
+      _imageDelegate = value;
43
+      notifyListeners();
44
+    }
45
+  }
46
+
47
+  ZefyrController _controller;
48
+  ZefyrController get controller => _controller;
49
+  set controller(ZefyrController value) {
50
+    assert(isEditable && value != null);
51
+    if (_controller != value) {
52
+      _controller.removeListener(_handleControllerChange);
53
+      _controller = value;
54
+      _selectionStyle = _controller.getSelectionStyle();
55
+      _selection = _controller.selection;
56
+      _controller.addListener(_handleControllerChange);
57
+      notifyListeners();
58
+    }
59
+  }
60
+
61
+  FocusNode _focusNode;
62
+  FocusNode get focusNode => _focusNode;
63
+  set focusNode(FocusNode value) {
64
+    assert(isEditable && value != null);
65
+    if (_focusNode != value) {
66
+      _focusNode.removeListener(_handleFocusChange);
67
+      _focusNode = value;
68
+      _focusNode.addListener(_handleFocusChange);
69
+      notifyListeners();
70
+    }
71
+  }
72
+
73
+  FocusScopeNode _focusScope;
74
+  FocusScopeNode get focusScope => _focusScope;
75
+  set focusScope(FocusScopeNode value) {
76
+    assert(isEditable && value != null);
77
+    if (_focusScope != value) {
78
+      _focusScope = value;
79
+    }
80
+  }
81
+
82
+  CursorTimer _cursorTimer;
83
+  CursorTimer get cursorTimer => _cursorTimer;
84
+  ValueNotifier<bool> get showCursor => cursorTimer.value;
85
+
86
+  ZefyrRenderContext _renderContext;
87
+  ZefyrRenderContext get renderContext => _renderContext;
88
+
89
+  NotusStyle get selectionStyle => _selectionStyle;
90
+  NotusStyle _selectionStyle;
91
+  TextSelection get selection => _selection;
92
+  TextSelection _selection;
93
+
94
+  bool _disposed = false;
95
+  FocusNode _toolbarFocusNode;
96
+
97
+  /// Whether this scope is backed by editable Zefyr widgets or read-only view.
98
+  ///
99
+  /// Returns `true` if this scope provides Zefyr interface that allows editing
100
+  /// (e.g. created by [ZefyrEditor]). Returns `false` if this scope provides
101
+  /// read-only view (e.g. created by [ZefyrView]).
102
+  ///
103
+  /// Editable scope provides access to corresponding [controller], [focusNode],
104
+  /// [focusScope], [showCursor], [renderContext] and other shared objects. For
105
+  /// non-editable scopes these are set to `null`. You can still access
106
+  /// objects which are not dependent on editing flow, e.g. [imageDelegate].
107
+  final bool isEditable;
108
+
109
+  static ZefyrScope of(BuildContext context) {
110
+    final ZefyrScopeAccess widget =
111
+        context.inheritFromWidgetOfExactType(ZefyrScopeAccess);
112
+    return widget.scope;
113
+  }
114
+
115
+  set toolbarFocusNode(FocusNode node) {
116
+    assert(isEditable);
117
+    assert(!_disposed || node == null);
118
+    if (_toolbarFocusNode != node) {
119
+      _toolbarFocusNode?.removeListener(_handleFocusChange);
120
+      _toolbarFocusNode = node;
121
+      _toolbarFocusNode?.addListener(_handleFocusChange);
122
+      // We do not notify listeners here because it will happen when
123
+      // focus state changes, see [_handleFocusChange].
124
+    }
125
+  }
126
+
127
+  FocusOwner get focusOwner {
128
+    assert(isEditable);
129
+    assert(!_disposed);
130
+    if (_focusNode.hasFocus) {
131
+      return FocusOwner.editor;
132
+    } else if (_toolbarFocusNode?.hasFocus == true) {
133
+      return FocusOwner.toolbar;
134
+    } else {
135
+      return FocusOwner.none;
136
+    }
137
+  }
138
+
139
+  void updateSelection(TextSelection value,
140
+      {ChangeSource source: ChangeSource.remote}) {
141
+    assert(isEditable);
142
+    assert(!_disposed);
143
+    _controller.updateSelection(value, source: source);
144
+  }
145
+
146
+  void formatSelection(NotusAttribute value) {
147
+    assert(isEditable);
148
+    assert(!_disposed);
149
+    _controller.formatSelection(value);
150
+  }
151
+
152
+  void focus() {
153
+    assert(isEditable);
154
+    assert(!_disposed);
155
+    _focusScope.requestFocus(_focusNode);
156
+  }
157
+
158
+  void hideKeyboard() {
159
+    assert(isEditable);
160
+    assert(!_disposed);
161
+    _focusNode.unfocus();
162
+  }
163
+
164
+  @override
165
+  void dispose() {
166
+    assert(!_disposed);
167
+    _controller?.removeListener(_handleControllerChange);
168
+    _focusNode?.removeListener(_handleFocusChange);
169
+    _disposed = true;
170
+    super.dispose();
171
+  }
172
+
173
+  void _handleControllerChange() {
174
+    assert(!_disposed);
175
+    final attrs = _controller.getSelectionStyle();
176
+    final selection = _controller.selection;
177
+    if (_selectionStyle != attrs || _selection != selection) {
178
+      _selectionStyle = attrs;
179
+      _selection = _controller.selection;
180
+      notifyListeners();
181
+    }
182
+  }
183
+
184
+  void _handleFocusChange() {
185
+    assert(!_disposed);
186
+    if (focusOwner == FocusOwner.none && !_selection.isCollapsed) {
187
+      // Collapse selection if there is nothing focused.
188
+      _controller.updateSelection(_selection.copyWith(
189
+        baseOffset: _selection.extentOffset,
190
+        extentOffset: _selection.extentOffset,
191
+      ));
192
+    }
193
+    notifyListeners();
194
+  }
195
+}
196
+
197
+class ZefyrScopeAccess extends InheritedWidget {
198
+  final ZefyrScope scope;
199
+
200
+  ZefyrScopeAccess({Key key, @required this.scope, @required Widget child})
201
+      : super(key: key, child: child);
202
+
203
+  @override
204
+  bool updateShouldNotify(ZefyrScopeAccess oldWidget) {
205
+    return scope != oldWidget.scope;
206
+  }
207
+}

+ 22
- 25
packages/zefyr/lib/src/widgets/selection.dart Dosyayı Görüntüle

@@ -10,8 +10,7 @@ import 'package:zefyr/util.dart';
10 10
 
11 11
 import 'controller.dart';
12 12
 import 'editable_box.dart';
13
-import 'editable_text.dart';
14
-import 'editor.dart';
13
+import 'scope.dart';
15 14
 
16 15
 RenderEditableBox _getEditableBox(HitTestResult result) {
17 16
   for (var entry in result.path) {
@@ -73,14 +72,14 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
73 72
   }
74 73
 
75 74
   void showToolbar() {
76
-    final editable = ZefyrEditableText.of(context);
77
-    assert(editable != null);
75
+    final scope = ZefyrScope.of(context);
76
+    assert(scope != null);
78 77
     final toolbarOpacity = _toolbarController.view;
79 78
     _toolbar = new OverlayEntry(
80 79
       builder: (context) => new FadeTransition(
81 80
             opacity: toolbarOpacity,
82 81
             child: new _SelectionToolbar(
83
-              editable: editable,
82
+              scope: scope,
84 83
               controls: widget.controls,
85 84
               delegate: this,
86 85
             ),
@@ -117,7 +116,7 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
117 116
   @override
118 117
   void didChangeDependencies() {
119 118
     super.didChangeDependencies();
120
-    final editor = ZefyrEditor.of(context);
119
+    final editor = ZefyrScope.of(context);
121 120
     if (_editor != editor) {
122 121
       _editor?.removeListener(_handleChange);
123 122
       _editor = editor;
@@ -174,7 +173,7 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
174 173
   OverlayEntry _toolbar;
175 174
   AnimationController _toolbarController;
176 175
 
177
-  ZefyrEditorScope _editor;
176
+  ZefyrScope _editor;
178 177
   TextSelection _selection;
179 178
   FocusOwner _focusOwner;
180 179
 
@@ -190,9 +189,9 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
190 189
     if (!mounted) {
191 190
       return;
192 191
     }
193
-    final editor = ZefyrEditor.of(context);
194
-    final selection = editor.selection;
195
-    final focusOwner = editor.focusOwner;
192
+
193
+    final selection = _editor.selection;
194
+    final focusOwner = _editor.focusOwner;
196 195
     setState(() {
197 196
       if (focusOwner != FocusOwner.editor) {
198 197
         hideToolbar();
@@ -233,8 +232,8 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
233 232
 
234 233
     RenderEditableProxyBox box = _getEditableBox(result);
235 234
     if (box == null) {
236
-      final editable = ZefyrEditableText.of(context);
237
-      box = editable.renderContext.closestBoxForGlobalPoint(globalPoint);
235
+      final scope = ZefyrScope.of(context);
236
+      box = scope.renderContext.closestBoxForGlobalPoint(globalPoint);
238 237
     }
239 238
     if (box == null) return null;
240 239
 
@@ -327,8 +326,8 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
327 326
   @override
328 327
   void didChangeDependencies() {
329 328
     super.didChangeDependencies();
330
-    final editable = ZefyrEditableText.of(context);
331
-    _selection = editable.selection;
329
+    final scope = ZefyrScope.of(context);
330
+    _selection = scope.selection;
332 331
   }
333 332
 
334 333
   //
@@ -337,15 +336,14 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
337 336
 
338 337
   @override
339 338
   Widget build(BuildContext context) {
340
-    final editor = ZefyrEditor.of(context);
341
-    final editable = ZefyrEditableText.of(context);
339
+    final scope = ZefyrScope.of(context);
342 340
     if (selection == null ||
343 341
         selection.isCollapsed ||
344 342
         widget.controls == null ||
345
-        editor.focusOwner != FocusOwner.editor) {
343
+        scope.focusOwner != FocusOwner.editor) {
346 344
       return new Container();
347 345
     }
348
-    final block = editable.renderContext.boxForTextOffset(documentOffset);
346
+    final block = scope.renderContext.boxForTextOffset(documentOffset);
349 347
     final position = getPosition(block);
350 348
     Widget handle;
351 349
     if (position == null) {
@@ -395,9 +393,8 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
395 393
   void _handleDragUpdate(DragUpdateDetails details) {
396 394
     _dragPosition += details.delta;
397 395
     final globalPoint = _dragPosition;
398
-    final editor = ZefyrEditor.of(context);
399
-    final editable = ZefyrEditableText.of(context);
400
-    final paragraph = editable.renderContext.boxForGlobalPoint(globalPoint);
396
+    final scope = ZefyrScope.of(context);
397
+    final paragraph = scope.renderContext.boxForGlobalPoint(globalPoint);
401 398
     if (paragraph == null) {
402 399
       return;
403 400
     }
@@ -414,7 +411,7 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
414 411
     }
415 412
 
416 413
     if (newSelection != _selection) {
417
-      editor.updateSelection(newSelection, source: ChangeSource.local);
414
+      scope.updateSelection(newSelection, source: ChangeSource.local);
418 415
     }
419 416
   }
420 417
 }
@@ -422,12 +419,12 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
422 419
 class _SelectionToolbar extends StatefulWidget {
423 420
   const _SelectionToolbar({
424 421
     Key key,
425
-    @required this.editable,
422
+    @required this.scope,
426 423
     @required this.controls,
427 424
     @required this.delegate,
428 425
   }) : super(key: key);
429 426
 
430
-  final ZefyrEditableTextScope editable;
427
+  final ZefyrScope scope;
431 428
   final TextSelectionControls controls;
432 429
   final TextSelectionDelegate delegate;
433 430
 
@@ -436,7 +433,7 @@ class _SelectionToolbar extends StatefulWidget {
436 433
 }
437 434
 
438 435
 class _SelectionToolbarState extends State<_SelectionToolbar> {
439
-  ZefyrEditableTextScope get editable => widget.editable;
436
+  ZefyrScope get editable => widget.scope;
440 437
   TextSelection get selection => widget.delegate.textEditingValue.selection;
441 438
 
442 439
   @override

+ 3
- 3
packages/zefyr/lib/src/widgets/toolbar.dart Dosyayı Görüntüle

@@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
8 8
 import 'package:notus/notus.dart';
9 9
 
10 10
 import 'buttons.dart';
11
-import 'editor.dart';
11
+import 'scope.dart';
12 12
 import 'theme.dart';
13 13
 
14 14
 /// List of all button actions supported by [ZefyrToolbar] buttons.
@@ -107,7 +107,7 @@ class ZefyrToolbar extends StatefulWidget implements PreferredSizeWidget {
107 107
   }) : super(key: key);
108 108
 
109 109
   final ZefyrToolbarDelegate delegate;
110
-  final ZefyrEditorScope editor;
110
+  final ZefyrScope editor;
111 111
 
112 112
   /// Whether to automatically hide this toolbar when editor loses focus.
113 113
   final bool autoHide;
@@ -187,7 +187,7 @@ class ZefyrToolbarState extends State<ZefyrToolbar>
187 187
 
188 188
   bool get hasOverlay => _overlayBuilder != null;
189 189
 
190
-  ZefyrEditorScope get editor => widget.editor;
190
+  ZefyrScope get editor => widget.editor;
191 191
 
192 192
   @override
193 193
   void initState() {

+ 22
- 21
packages/zefyr/lib/src/widgets/view.dart Dosyayı Görüntüle

@@ -7,20 +7,9 @@ import 'image.dart';
7 7
 import 'list.dart';
8 8
 import 'paragraph.dart';
9 9
 import 'quote.dart';
10
+import 'scope.dart';
10 11
 import 'theme.dart';
11 12
 
12
-class _ZefyrViewAccess extends InheritedWidget {
13
-  final ZefyrViewState state;
14
-
15
-  _ZefyrViewAccess({Key key, @required this.state, Widget child})
16
-      : super(key: key, child: child);
17
-
18
-  @override
19
-  bool updateShouldNotify(_ZefyrViewAccess oldWidget) {
20
-    return state != oldWidget.state;
21
-  }
22
-}
23
-
24 13
 /// Non-scrollable read-only view of a Notus rich text document.
25 14
 class ZefyrView extends StatefulWidget {
26 15
   final NotusDocument document;
@@ -29,22 +18,28 @@ class ZefyrView extends StatefulWidget {
29 18
   const ZefyrView({Key key, this.document, this.imageDelegate})
30 19
       : super(key: key);
31 20
 
32
-  static ZefyrViewState of(BuildContext context) {
33
-    final _ZefyrViewAccess widget =
34
-        context.inheritFromWidgetOfExactType(_ZefyrViewAccess);
35
-    if (widget == null) return null;
36
-    return widget.state;
37
-  }
38
-
39 21
   @override
40 22
   ZefyrViewState createState() => ZefyrViewState();
41 23
 }
42 24
 
43 25
 class ZefyrViewState extends State<ZefyrView> {
26
+  ZefyrScope _scope;
44 27
   ZefyrThemeData _themeData;
45 28
 
46 29
   ZefyrImageDelegate get imageDelegate => widget.imageDelegate;
47 30
 
31
+  @override
32
+  void initState() {
33
+    super.initState();
34
+    _scope = ZefyrScope.view(imageDelegate: widget.imageDelegate);
35
+  }
36
+
37
+  @override
38
+  void didUpdateWidget(ZefyrView oldWidget) {
39
+    super.didUpdateWidget(oldWidget);
40
+    _scope.imageDelegate = widget.imageDelegate;
41
+  }
42
+
48 43
   @override
49 44
   void didChangeDependencies() {
50 45
     super.didChangeDependencies();
@@ -55,12 +50,18 @@ class ZefyrViewState extends State<ZefyrView> {
55 50
         : fallbackTheme;
56 51
   }
57 52
 
53
+  @override
54
+  void dispose() {
55
+    _scope.dispose();
56
+    super.dispose();
57
+  }
58
+
58 59
   @override
59 60
   Widget build(BuildContext context) {
60 61
     return ZefyrTheme(
61 62
       data: _themeData,
62
-      child: _ZefyrViewAccess(
63
-        state: this,
63
+      child: ZefyrScopeAccess(
64
+        scope: _scope,
64 65
         child: Column(
65 66
           crossAxisAlignment: CrossAxisAlignment.stretch,
66 67
           children: _buildChildren(context),

+ 1
- 0
packages/zefyr/lib/zefyr.dart Dosyayı Görüntüle

@@ -22,6 +22,7 @@ export 'src/widgets/list.dart';
22 22
 export 'src/widgets/paragraph.dart';
23 23
 export 'src/widgets/quote.dart';
24 24
 export 'src/widgets/scaffold.dart';
25
+export 'src/widgets/scope.dart' hide ZefyrScopeAccess;
25 26
 export 'src/widgets/selection.dart' hide SelectionHandleDriver;
26 27
 export 'src/widgets/theme.dart';
27 28
 export 'src/widgets/toolbar.dart';

+ 3
- 3
packages/zefyr/test/rendering/render_editable_paragraph_test.dart Dosyayı Görüntüle

@@ -11,18 +11,18 @@ import 'package:zefyr/src/widgets/rich_text.dart';
11 11
 import 'package:zefyr/zefyr.dart';
12 12
 
13 13
 void main() {
14
-  group('$RenderEditableParagraph', () {
14
+  group('$RenderZefyrParagraph', () {
15 15
     final doc = new NotusDocument();
16 16
     doc.insert(0, 'This House Is A Circus');
17 17
     final text = new TextSpan(text: 'This House Is A Circus');
18 18
 
19 19
     ZefyrRenderContext renderContext;
20
-    RenderEditableParagraph p;
20
+    RenderZefyrParagraph p;
21 21
 
22 22
     setUp(() {
23 23
       WidgetsFlutterBinding.ensureInitialized();
24 24
       renderContext = new ZefyrRenderContext();
25
-      p = new RenderEditableParagraph(
25
+      p = new RenderZefyrParagraph(
26 26
         text,
27 27
         node: doc.root.children.first,
28 28
         textDirection: TextDirection.ltr,

+ 67
- 67
packages/zefyr/test/widgets/editable_text_scope_test.dart Dosyayı Görüntüle

@@ -9,84 +9,84 @@ import 'package:zefyr/src/widgets/render_context.dart';
9 9
 import 'package:zefyr/zefyr.dart';
10 10
 
11 11
 void main() {
12
-  group('$ZefyrEditableTextScope', () {
12
+  group('ZefyrEditableTextScope', () {
13 13
     setUp(() {
14 14
       WidgetsFlutterBinding.ensureInitialized();
15 15
     });
16
-
17
-    test('updateShouldNotify for rendering context changes', () {
18
-      var context = new ZefyrRenderContext();
19
-      var paragraph1 = createParagraph(context);
20
-      var paragraph2 = createParagraph(context);
21
-      context.addBox(paragraph1);
22
-      context.markDirty(paragraph1, false);
23
-      var widget1 = createScope(renderingContext: context);
24
-      var widget2 = createScope(renderingContext: context);
25
-
26
-      expect(widget2.updateShouldNotify(widget1), isFalse);
27
-      context.addBox(paragraph2);
28
-      context.markDirty(paragraph2, false);
29
-      widget2 = createScope(renderingContext: context);
30
-      expect(widget2.updateShouldNotify(widget1), isTrue);
31
-    });
32
-
33
-    test('updateShouldNotify for selection changes', () {
34
-      var context = new ZefyrRenderContext();
35
-      var selection = new TextSelection.collapsed(offset: 0);
36
-      var widget1 =
37
-          createScope(renderingContext: context, selection: selection);
38
-      var widget2 =
39
-          createScope(renderingContext: context, selection: selection);
40
-
41
-      expect(widget2.updateShouldNotify(widget1), isFalse);
42
-      selection = new TextSelection.collapsed(offset: 1);
43
-      widget2 = createScope(renderingContext: context, selection: selection);
44
-      expect(widget2.updateShouldNotify(widget1), isTrue);
45
-    });
46
-
47
-    test('updateShouldNotify for showCursor changes', () {
48
-      var context = new ZefyrRenderContext();
49
-      var showCursor = new ValueNotifier<bool>(true);
50
-      var widget1 =
51
-          createScope(renderingContext: context, showCursor: showCursor);
52
-      var widget2 =
53
-          createScope(renderingContext: context, showCursor: showCursor);
54
-
55
-      expect(widget2.updateShouldNotify(widget1), isFalse);
56
-      showCursor = new ValueNotifier<bool>(true);
57
-      widget2 = createScope(renderingContext: context, showCursor: showCursor);
58
-      expect(widget2.updateShouldNotify(widget1), isTrue);
59
-    });
60
-
61
-    test('updateShouldNotify for imageDelegate changes', () {
62
-      var context = new ZefyrRenderContext();
63
-      var delegate = new ZefyrDefaultImageDelegate();
64
-      var widget1 =
65
-          createScope(renderingContext: context, imageDelegate: delegate);
66
-      var widget2 =
67
-          createScope(renderingContext: context, imageDelegate: delegate);
68
-
69
-      expect(widget2.updateShouldNotify(widget1), isFalse);
70
-      delegate = new ZefyrDefaultImageDelegate();
71
-      widget2 = createScope(renderingContext: context, imageDelegate: delegate);
72
-      expect(widget2.updateShouldNotify(widget1), isTrue);
73
-    });
16
+//
17
+//    test('updateShouldNotify for rendering context changes', () {
18
+//      var context = new ZefyrRenderContext();
19
+//      var paragraph1 = createParagraph(context);
20
+//      var paragraph2 = createParagraph(context);
21
+//      context.addBox(paragraph1);
22
+//      context.markDirty(paragraph1, false);
23
+//      var widget1 = createScope(renderingContext: context);
24
+//      var widget2 = createScope(renderingContext: context);
25
+//
26
+//      expect(widget2.updateShouldNotify(widget1), isFalse);
27
+//      context.addBox(paragraph2);
28
+//      context.markDirty(paragraph2, false);
29
+//      widget2 = createScope(renderingContext: context);
30
+//      expect(widget2.updateShouldNotify(widget1), isTrue);
31
+//    });
32
+//
33
+//    test('updateShouldNotify for selection changes', () {
34
+//      var context = new ZefyrRenderContext();
35
+//      var selection = new TextSelection.collapsed(offset: 0);
36
+//      var widget1 =
37
+//          createScope(renderingContext: context, selection: selection);
38
+//      var widget2 =
39
+//          createScope(renderingContext: context, selection: selection);
40
+//
41
+//      expect(widget2.updateShouldNotify(widget1), isFalse);
42
+//      selection = new TextSelection.collapsed(offset: 1);
43
+//      widget2 = createScope(renderingContext: context, selection: selection);
44
+//      expect(widget2.updateShouldNotify(widget1), isTrue);
45
+//    });
46
+//
47
+//    test('updateShouldNotify for showCursor changes', () {
48
+//      var context = new ZefyrRenderContext();
49
+//      var showCursor = new ValueNotifier<bool>(true);
50
+//      var widget1 =
51
+//          createScope(renderingContext: context, showCursor: showCursor);
52
+//      var widget2 =
53
+//          createScope(renderingContext: context, showCursor: showCursor);
54
+//
55
+//      expect(widget2.updateShouldNotify(widget1), isFalse);
56
+//      showCursor = new ValueNotifier<bool>(true);
57
+//      widget2 = createScope(renderingContext: context, showCursor: showCursor);
58
+//      expect(widget2.updateShouldNotify(widget1), isTrue);
59
+//    });
60
+//
61
+//    test('updateShouldNotify for imageDelegate changes', () {
62
+//      var context = new ZefyrRenderContext();
63
+//      var delegate = new ZefyrDefaultImageDelegate();
64
+//      var widget1 =
65
+//          createScope(renderingContext: context, imageDelegate: delegate);
66
+//      var widget2 =
67
+//          createScope(renderingContext: context, imageDelegate: delegate);
68
+//
69
+//      expect(widget2.updateShouldNotify(widget1), isFalse);
70
+//      delegate = new ZefyrDefaultImageDelegate();
71
+//      widget2 = createScope(renderingContext: context, imageDelegate: delegate);
72
+//      expect(widget2.updateShouldNotify(widget1), isTrue);
73
+//    });
74 74
   });
75 75
 }
76 76
 
77
-ZefyrEditableTextScope createScope({
77
+ZefyrScope createScope({
78 78
   @required ZefyrRenderContext renderingContext,
79 79
   TextSelection selection,
80 80
   ValueNotifier<bool> showCursor,
81 81
   ZefyrImageDelegate imageDelegate,
82 82
 }) {
83
-  return ZefyrEditableTextScope(
84
-    renderContext: renderingContext,
85
-    selection: selection,
86
-    showCursor: showCursor,
87
-    imageDelegate: imageDelegate,
88
-    child: null,
89
-  );
83
+//  return ZefyrScope.editable(
84
+//    renderContext: renderingContext,
85
+//    selection: selection,
86
+//    showCursor: showCursor,
87
+//    imageDelegate: imageDelegate,
88
+//    child: null,
89
+//  );
90 90
 }
91 91
 
92 92
 RenderEditableProxyBox createParagraph(ZefyrRenderContext context) {

+ 1
- 1
packages/zefyr/test/widgets/editor_test.dart Dosyayı Görüntüle

@@ -25,7 +25,7 @@ void main() {
25 25
       await editor.tapEditor();
26 26
       // TODO: figure out why this extra pump is needed here
27 27
       await tester.pumpAndSettle();
28
-      EditableRichText p = tester.widget(find.byType(EditableRichText).first);
28
+      ZefyrRichText p = tester.widget(find.byType(ZefyrRichText).first);
29 29
       expect(p.text.children.first.style.color, Colors.red);
30 30
     });
31 31
 

+ 4
- 4
packages/zefyr/test/widgets/rich_text_test.dart Dosyayı Görüntüle

@@ -9,7 +9,7 @@ import 'package:zefyr/src/widgets/rich_text.dart';
9 9
 import 'package:zefyr/zefyr.dart';
10 10
 
11 11
 void main() {
12
-  group('$EditableRichText', () {
12
+  group('$ZefyrRichText', () {
13 13
     final doc = new NotusDocument();
14 14
     doc.insert(0, 'This House Is A Circus');
15 15
     final text = new TextSpan(text: 'This House Is A Circus');
@@ -18,7 +18,7 @@ void main() {
18 18
     setUp(() {
19 19
       widget = new Directionality(
20 20
         textDirection: TextDirection.ltr,
21
-        child: new EditableRichText(
21
+        child: new ZefyrRichText(
22 22
           node: doc.root.children.first,
23 23
           text: text,
24 24
         ),
@@ -27,8 +27,8 @@ void main() {
27 27
 
28 28
     testWidgets('initialize', (tester) async {
29 29
       await tester.pumpWidget(widget);
30
-      EditableRichText result =
31
-          tester.firstWidget(find.byType(EditableRichText));
30
+      ZefyrRichText result =
31
+          tester.firstWidget(find.byType(ZefyrRichText));
32 32
       expect(result, isNotNull);
33 33
       expect(result.text.text, 'This House Is A Circus');
34 34
     });

+ 4
- 4
packages/zefyr/test/widgets/selection_test.dart Dosyayı Görüntüle

@@ -14,8 +14,8 @@ void main() {
14 14
       final editor = new EditorSandBox(tester: tester);
15 15
       await editor.tapEditor();
16 16
 
17
-      RenderEditableParagraph renderObject =
18
-          tester.firstRenderObject(find.byType(EditableRichText));
17
+      RenderZefyrParagraph renderObject =
18
+          tester.firstRenderObject(find.byType(ZefyrRichText));
19 19
       var offset = renderObject.localToGlobal(Offset.zero);
20 20
       offset += Offset(5.0, 5.0);
21 21
       await tester.tapAt(offset);
@@ -42,8 +42,8 @@ void main() {
42 42
       await tester.pumpAndSettle();
43 43
       expect(editor.controller.selection.extentOffset, 10);
44 44
 
45
-      RenderEditableParagraph renderObject =
46
-          tester.firstRenderObject(find.byType(EditableRichText));
45
+      RenderZefyrParagraph renderObject =
46
+          tester.firstRenderObject(find.byType(ZefyrRichText));
47 47
       var offset = renderObject.localToGlobal(Offset.zero);
48 48
       offset += Offset(-5.0, 5.0);
49 49
       await tester.tapAt(offset);