|
@@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart';
|
8
|
8
|
import 'package:flutter/widgets.dart';
|
9
|
9
|
import 'package:notus/notus.dart';
|
10
|
10
|
|
|
11
|
+import 'caret.dart';
|
11
|
12
|
import 'render_context.dart';
|
12
|
13
|
|
13
|
14
|
class EditableBox extends SingleChildRenderObjectWidget {
|
|
@@ -29,7 +30,7 @@ class EditableBox extends SingleChildRenderObjectWidget {
|
29
|
30
|
final Color selectionColor;
|
30
|
31
|
|
31
|
32
|
@override
|
32
|
|
- RenderObject createRenderObject(BuildContext context) {
|
|
33
|
+ RenderEditableProxyBox createRenderObject(BuildContext context) {
|
33
|
34
|
return new RenderEditableProxyBox(
|
34
|
35
|
node: node,
|
35
|
36
|
layerLink: layerLink,
|
|
@@ -39,6 +40,18 @@ class EditableBox extends SingleChildRenderObjectWidget {
|
39
|
40
|
selectionColor: selectionColor,
|
40
|
41
|
);
|
41
|
42
|
}
|
|
43
|
+
|
|
44
|
+ @override
|
|
45
|
+ void updateRenderObject(
|
|
46
|
+ BuildContext context, RenderEditableProxyBox renderObject) {
|
|
47
|
+ renderObject
|
|
48
|
+ ..node = node
|
|
49
|
+ ..layerLink = layerLink
|
|
50
|
+ ..renderContext = renderContext
|
|
51
|
+ ..showCursor = showCursor
|
|
52
|
+ ..selection = selection
|
|
53
|
+ ..selectionColor = selectionColor;
|
|
54
|
+ }
|
42
|
55
|
}
|
43
|
56
|
|
44
|
57
|
class RenderEditableProxyBox extends RenderBox
|
|
@@ -114,8 +127,6 @@ class RenderEditableProxyBox extends RenderBox
|
114
|
127
|
markNeedsPaint();
|
115
|
128
|
}
|
116
|
129
|
|
117
|
|
- double get preferredLineHeight => child.preferredLineHeight;
|
118
|
|
-
|
119
|
130
|
/// Returns `true` if current selection is collapsed, located within
|
120
|
131
|
/// this paragraph and is visible according to tick timer.
|
121
|
132
|
bool get isCaretVisible {
|
|
@@ -153,12 +164,11 @@ class RenderEditableProxyBox extends RenderBox
|
153
|
164
|
super.detach();
|
154
|
165
|
}
|
155
|
166
|
|
156
|
|
- /// Subclasses must call super as the last statement when overriding this
|
157
|
|
- /// method.
|
158
|
167
|
@override
|
159
|
168
|
@mustCallSuper
|
160
|
169
|
void performLayout() {
|
161
|
170
|
super.performLayout();
|
|
171
|
+ _caretPainter.layout(preferredLineHeight);
|
162
|
172
|
// Indicate to render context that this object can be used by other
|
163
|
173
|
// layers (selection overlay, for instance).
|
164
|
174
|
_renderContext.markDirty(this, false);
|
|
@@ -171,6 +181,30 @@ class RenderEditableProxyBox extends RenderBox
|
171
|
181
|
super.markNeedsLayout();
|
172
|
182
|
}
|
173
|
183
|
|
|
184
|
+ @override
|
|
185
|
+ void paint(PaintingContext context, Offset offset) {
|
|
186
|
+ if (selectionOrder == SelectionOrder.background && isSelectionVisible) {
|
|
187
|
+ paintSelection(context, offset, selection, selectionColor);
|
|
188
|
+ }
|
|
189
|
+ super.paint(context, offset);
|
|
190
|
+ if (selectionOrder == SelectionOrder.foreground && isSelectionVisible) {
|
|
191
|
+ paintSelection(context, offset, selection, selectionColor);
|
|
192
|
+ }
|
|
193
|
+ if (isCaretVisible) {
|
|
194
|
+ _paintCaret(context, offset);
|
|
195
|
+ }
|
|
196
|
+ }
|
|
197
|
+
|
|
198
|
+ final CaretPainter _caretPainter = new CaretPainter();
|
|
199
|
+
|
|
200
|
+ void _paintCaret(PaintingContext context, Offset offset) {
|
|
201
|
+ final TextPosition caret = new TextPosition(
|
|
202
|
+ offset: _selection.extentOffset - node.documentOffset,
|
|
203
|
+ );
|
|
204
|
+ Offset caretOffset = getOffsetForCaret(caret, _caretPainter.prototype);
|
|
205
|
+ _caretPainter.paint(context.canvas, caretOffset + offset);
|
|
206
|
+ }
|
|
207
|
+
|
174
|
208
|
@override
|
175
|
209
|
bool hitTestSelf(Offset position) => true;
|
176
|
210
|
|
|
@@ -183,6 +217,25 @@ class RenderEditableProxyBox extends RenderBox
|
183
|
217
|
return false;
|
184
|
218
|
}
|
185
|
219
|
|
|
220
|
+ //
|
|
221
|
+ // Proxy methods
|
|
222
|
+ //
|
|
223
|
+
|
|
224
|
+ @override
|
|
225
|
+ double get preferredLineHeight => child.preferredLineHeight;
|
|
226
|
+
|
|
227
|
+ @override
|
|
228
|
+ SelectionOrder get selectionOrder => child.selectionOrder;
|
|
229
|
+
|
|
230
|
+ @override
|
|
231
|
+ void paintSelection(PaintingContext context, Offset offset,
|
|
232
|
+ TextSelection selection, Color selectionColor) =>
|
|
233
|
+ child.paintSelection(context, offset, selection, selectionColor);
|
|
234
|
+
|
|
235
|
+ @override
|
|
236
|
+ Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) =>
|
|
237
|
+ child.getOffsetForCaret(position, caretPrototype);
|
|
238
|
+
|
186
|
239
|
@override
|
187
|
240
|
TextSelection getLocalSelection(TextSelection documentSelection) =>
|
188
|
241
|
child.getLocalSelection(documentSelection);
|
|
@@ -191,9 +244,8 @@ class RenderEditableProxyBox extends RenderBox
|
191
|
244
|
child.intersectsWithSelection(selection);
|
192
|
245
|
|
193
|
246
|
@override
|
194
|
|
- List<ui.TextBox> getEndpointsForSelection(TextSelection selection,
|
195
|
|
- {bool isLocal: false}) =>
|
196
|
|
- child.getEndpointsForSelection(selection, isLocal: isLocal);
|
|
247
|
+ List<ui.TextBox> getEndpointsForSelection(TextSelection selection) =>
|
|
248
|
+ child.getEndpointsForSelection(selection);
|
197
|
249
|
|
198
|
250
|
@override
|
199
|
251
|
ui.TextPosition getPositionForOffset(ui.Offset offset) =>
|
|
@@ -204,13 +256,20 @@ class RenderEditableProxyBox extends RenderBox
|
204
|
256
|
child.getWordBoundary(position);
|
205
|
257
|
}
|
206
|
258
|
|
|
259
|
+enum SelectionOrder {
|
|
260
|
+ /// Background selection is painted before primary content of editable box.
|
|
261
|
+ background,
|
|
262
|
+
|
|
263
|
+ /// Foreground selection is painted after primary content of editable box.
|
|
264
|
+ foreground,
|
|
265
|
+}
|
|
266
|
+
|
207
|
267
|
abstract class RenderEditableBox extends RenderBox {
|
208
|
268
|
Node get node;
|
209
|
269
|
double get preferredLineHeight;
|
210
|
270
|
|
211
|
271
|
TextPosition getPositionForOffset(Offset offset);
|
212
|
|
- List<ui.TextBox> getEndpointsForSelection(TextSelection selection,
|
213
|
|
- {bool isLocal: false});
|
|
272
|
+ List<ui.TextBox> getEndpointsForSelection(TextSelection selection);
|
214
|
273
|
|
215
|
274
|
/// Returns the text range of the word at the given offset. Characters not
|
216
|
275
|
/// part of a word, such as spaces, symbols, and punctuation, have word breaks
|
|
@@ -223,6 +282,14 @@ abstract class RenderEditableBox extends RenderBox {
|
223
|
282
|
/// Valid only after [layout].
|
224
|
283
|
TextRange getWordBoundary(TextPosition position);
|
225
|
284
|
|
|
285
|
+ /// Paint order of selection in this editable box.
|
|
286
|
+ SelectionOrder get selectionOrder;
|
|
287
|
+
|
|
288
|
+ void paintSelection(PaintingContext context, Offset offset,
|
|
289
|
+ TextSelection selection, Color selectionColor);
|
|
290
|
+
|
|
291
|
+ Offset getOffsetForCaret(TextPosition position, Rect caretPrototype);
|
|
292
|
+
|
226
|
293
|
/// Returns part of [documentSelection] local to this box. May return
|
227
|
294
|
/// `null`.
|
228
|
295
|
///
|