|
@@ -13,7 +13,7 @@ import 'editable_box.dart';
|
13
|
13
|
import 'editable_text.dart';
|
14
|
14
|
import 'editor.dart';
|
15
|
15
|
|
16
|
|
-RenderEditableBox _getRenderParagraph(HitTestResult result) {
|
|
16
|
+RenderEditableBox _getEditableBox(HitTestResult result) {
|
17
|
17
|
for (var entry in result.path) {
|
18
|
18
|
if (entry.target is RenderEditableBox) {
|
19
|
19
|
return entry.target;
|
|
@@ -213,13 +213,12 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
|
213
|
213
|
HitTestResult result = new HitTestResult();
|
214
|
214
|
WidgetsBinding.instance.hitTest(result, globalPoint);
|
215
|
215
|
|
216
|
|
- final paragraph = _getRenderParagraph(result);
|
217
|
|
- if (paragraph == null) return;
|
|
216
|
+ final box = _getEditableBox(result);
|
|
217
|
+ if (box == null) return;
|
218
|
218
|
|
219
|
|
- final localPoint = paragraph.globalToLocal(globalPoint);
|
220
|
|
- final position = paragraph.getPositionForOffset(localPoint);
|
221
|
|
- final selection = new TextSelection.collapsed(
|
222
|
|
- offset: paragraph.node.documentOffset + position.offset);
|
|
219
|
+ final localPoint = box.globalToLocal(globalPoint);
|
|
220
|
+ final position = box.getPositionForOffset(localPoint);
|
|
221
|
+ final selection = new TextSelection.collapsed(offset: position.offset);
|
223
|
222
|
if (_didCaretTap && _selection == selection) {
|
224
|
223
|
_didCaretTap = false;
|
225
|
224
|
hideToolbar();
|
|
@@ -235,16 +234,16 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
|
235
|
234
|
_longPressPosition = null;
|
236
|
235
|
HitTestResult result = new HitTestResult();
|
237
|
236
|
WidgetsBinding.instance.hitTest(result, globalPoint);
|
238
|
|
- final paragraph = _getRenderParagraph(result);
|
239
|
|
- if (paragraph == null) {
|
|
237
|
+ final box = _getEditableBox(result);
|
|
238
|
+ if (box == null) {
|
240
|
239
|
return;
|
241
|
240
|
}
|
242
|
|
- final localPoint = paragraph.globalToLocal(globalPoint);
|
243
|
|
- final position = paragraph.getPositionForOffset(localPoint);
|
244
|
|
- final word = paragraph.getWordBoundary(position);
|
|
241
|
+ final localPoint = box.globalToLocal(globalPoint);
|
|
242
|
+ final position = box.getPositionForOffset(localPoint);
|
|
243
|
+ final word = box.getWordBoundary(position);
|
245
|
244
|
final selection = new TextSelection(
|
246
|
|
- baseOffset: paragraph.node.documentOffset + word.start,
|
247
|
|
- extentOffset: paragraph.node.documentOffset + word.end,
|
|
245
|
+ baseOffset: word.start,
|
|
246
|
+ extentOffset: word.end,
|
248
|
247
|
);
|
249
|
248
|
widget.controller.updateSelection(selection, source: ChangeSource.local);
|
250
|
249
|
}
|
|
@@ -290,10 +289,8 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
|
290
|
289
|
assert(localSelection != null);
|
291
|
290
|
|
292
|
291
|
final boxes = block.getEndpointsForSelection(selection);
|
293
|
|
- if (boxes.isEmpty) {
|
294
|
|
- print('Got empty boxes for selection ${selection}');
|
295
|
|
- return null;
|
296
|
|
- }
|
|
292
|
+ assert(boxes.isNotEmpty, 'Got empty boxes for selection ${selection}');
|
|
293
|
+
|
297
|
294
|
final box = isBaseHandle ? boxes.first : boxes.last;
|
298
|
295
|
final dx = isBaseHandle ? box.start : box.end;
|
299
|
296
|
return new Offset(dx, box.bottom);
|
|
@@ -369,18 +366,16 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> {
|
369
|
366
|
final globalPoint = _dragPosition;
|
370
|
367
|
final editor = ZefyrEditor.of(context);
|
371
|
368
|
final editable = ZefyrEditableText.of(context);
|
372
|
|
- final paragraph =
|
373
|
|
- editable.renderContext.boxForGlobalPoint(globalPoint);
|
|
369
|
+ final paragraph = editable.renderContext.boxForGlobalPoint(globalPoint);
|
374
|
370
|
if (paragraph == null) {
|
375
|
371
|
return;
|
376
|
372
|
}
|
377
|
373
|
|
378
|
374
|
final localPoint = paragraph.globalToLocal(globalPoint);
|
379
|
375
|
final position = paragraph.getPositionForOffset(localPoint);
|
380
|
|
- final documentOffset = paragraph.node.documentOffset + position.offset;
|
381
|
376
|
final newSelection = selection.copyWith(
|
382
|
|
- baseOffset: isBaseHandle ? documentOffset : selection.baseOffset,
|
383
|
|
- extentOffset: isBaseHandle ? selection.extentOffset : documentOffset,
|
|
377
|
+ baseOffset: isBaseHandle ? position.offset : selection.baseOffset,
|
|
378
|
+ extentOffset: isBaseHandle ? selection.extentOffset : position.offset,
|
384
|
379
|
);
|
385
|
380
|
if (newSelection.baseOffset >= newSelection.extentOffset) {
|
386
|
381
|
// Don't allow reversed or collapsed selection.
|
|
@@ -413,6 +408,7 @@ class _SelectionToolbar extends StatefulWidget {
|
413
|
408
|
|
414
|
409
|
class _SelectionToolbarState extends State<_SelectionToolbar> {
|
415
|
410
|
ZefyrEditableTextScope get editable => widget.editable;
|
|
411
|
+ TextSelection get selection => widget.delegate.textEditingValue.selection;
|
416
|
412
|
|
417
|
413
|
@override
|
418
|
414
|
Widget build(BuildContext context) {
|
|
@@ -420,13 +416,13 @@ class _SelectionToolbarState extends State<_SelectionToolbar> {
|
420
|
416
|
}
|
421
|
417
|
|
422
|
418
|
Widget _buildToolbar(BuildContext context) {
|
423
|
|
- final base = editable.selection.baseOffset;
|
|
419
|
+ final base = selection.baseOffset;
|
|
420
|
+ // TODO: Editable is not refreshed and may contain stale renderContext instance.
|
424
|
421
|
final block = editable.renderContext.boxForTextOffset(base);
|
425
|
422
|
if (block == null) {
|
426
|
423
|
return Container();
|
427
|
424
|
}
|
428
|
|
-
|
429
|
|
- final boxes = block.getEndpointsForSelection(editable.selection);
|
|
425
|
+ final boxes = block.getEndpointsForSelection(selection);
|
430
|
426
|
|
431
|
427
|
// Find the horizontal midpoint, just above the selected text.
|
432
|
428
|
final Offset midpoint = new Offset(
|