| 
				
			 | 
			
			
				@@ -1,8 +1,10 @@ 
			 | 
		
	
		
			
			| 
				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:math' as math; 
			 | 
		
	
		
			
			| 
				4
			 | 
			
				5
			 | 
			
			
				 import 'dart:ui' as ui; 
			 | 
		
	
		
			
			| 
				5
			 | 
			
				6
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				7
			 | 
			
			
				+import 'package:flutter/gestures.dart'; 
			 | 
		
	
		
			
			| 
				6
			 | 
			
				8
			 | 
			
			
				 import 'package:flutter/material.dart'; 
			 | 
		
	
		
			
			| 
				7
			 | 
			
				9
			 | 
			
			
				 import 'package:flutter/rendering.dart'; 
			 | 
		
	
		
			
			| 
				8
			 | 
			
				10
			 | 
			
			
				 import 'package:notus/notus.dart'; 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -75,13 +77,13 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay> 
			 | 
		
	
		
			
			| 
				75
			 | 
			
				77
			 | 
			
			
				     final toolbarOpacity = _toolbarController.view; 
			 | 
		
	
		
			
			| 
				76
			 | 
			
				78
			 | 
			
			
				     _toolbar = new OverlayEntry( 
			 | 
		
	
		
			
			| 
				77
			 | 
			
				79
			 | 
			
			
				       builder: (context) => new FadeTransition( 
			 | 
		
	
		
			
			| 
				78
			 | 
			
				
			 | 
			
			
				-            opacity: toolbarOpacity, 
			 | 
		
	
		
			
			| 
				79
			 | 
			
				
			 | 
			
			
				-            child: new _SelectionToolbar( 
			 | 
		
	
		
			
			| 
				80
			 | 
			
				
			 | 
			
			
				-              scope: _editor, 
			 | 
		
	
		
			
			| 
				81
			 | 
			
				
			 | 
			
			
				-              controls: widget.controls, 
			 | 
		
	
		
			
			| 
				82
			 | 
			
				
			 | 
			
			
				-              delegate: this, 
			 | 
		
	
		
			
			| 
				83
			 | 
			
				
			 | 
			
			
				-            ), 
			 | 
		
	
		
			
			| 
				84
			 | 
			
				
			 | 
			
			
				-          ), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				80
			 | 
			
			
				+        opacity: toolbarOpacity, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				81
			 | 
			
			
				+        child: new _SelectionToolbar( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				82
			 | 
			
			
				+          scope: _editor, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				83
			 | 
			
			
				+          controls: widget.controls, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				84
			 | 
			
			
				+          delegate: this, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				85
			 | 
			
			
				+        ), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				86
			 | 
			
			
				+      ), 
			 | 
		
	
		
			
			| 
				85
			 | 
			
				87
			 | 
			
			
				     ); 
			 | 
		
	
		
			
			| 
				86
			 | 
			
				88
			 | 
			
			
				     widget.overlay.insert(_toolbar); 
			 | 
		
	
		
			
			| 
				87
			 | 
			
				89
			 | 
			
			
				     _toolbarController.forward(from: 0.0); 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -303,7 +305,8 @@ class SelectionHandleDriver extends StatefulWidget { 
			 | 
		
	
		
			
			| 
				303
			 | 
			
				305
			 | 
			
			
				       new _SelectionHandleDriverState(); 
			 | 
		
	
		
			
			| 
				304
			 | 
			
				306
			 | 
			
			
				 } 
			 | 
		
	
		
			
			| 
				305
			 | 
			
				307
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				306
			 | 
			
				
			 | 
			
			
				-class _SelectionHandleDriverState extends State<SelectionHandleDriver> { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				308
			 | 
			
			
				+class _SelectionHandleDriverState extends State<SelectionHandleDriver> 
			 | 
		
	
		
			
			| 
				
			 | 
			
				309
			 | 
			
			
				+    with SingleTickerProviderStateMixin { 
			 | 
		
	
		
			
			| 
				307
			 | 
			
				310
			 | 
			
			
				   ZefyrScope _scope; 
			 | 
		
	
		
			
			| 
				308
			 | 
			
				311
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				309
			 | 
			
				312
			 | 
			
			
				   /// Current document selection. 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -320,19 +323,18 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> { 
			 | 
		
	
		
			
			| 
				320
			 | 
			
				323
			 | 
			
			
				   int get documentOffset => 
			 | 
		
	
		
			
			| 
				321
			 | 
			
				324
			 | 
			
			
				       isBaseHandle ? selection.baseOffset : selection.extentOffset; 
			 | 
		
	
		
			
			| 
				322
			 | 
			
				325
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				323
			 | 
			
				
			 | 
			
			
				-  /// Position in pixels of this selection handle within its paragraph [block]. 
			 | 
		
	
		
			
			| 
				324
			 | 
			
				
			 | 
			
			
				-  Offset getPosition(RenderEditableBox block) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				326
			 | 
			
			
				+  List<TextSelectionPoint> getEndpointsForSelection(RenderEditableBox block) { 
			 | 
		
	
		
			
			| 
				325
			 | 
			
				327
			 | 
			
			
				     if (block == null) return null; 
			 | 
		
	
		
			
			| 
				326
			 | 
			
				328
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				327
			 | 
			
				
			 | 
			
			
				-    final localSelection = block.getLocalSelection(selection); 
			 | 
		
	
		
			
			| 
				328
			 | 
			
				
			 | 
			
			
				-    assert(localSelection != null); 
			 | 
		
	
		
			
			| 
				329
			 | 
			
				
			 | 
			
			
				- 
			 | 
		
	
		
			
			| 
				330
			 | 
			
				
			 | 
			
			
				-    final boxes = block.getEndpointsForSelection(selection); 
			 | 
		
	
		
			
			| 
				331
			 | 
			
				
			 | 
			
			
				-    assert(boxes.isNotEmpty, 'Got empty boxes for selection ${selection}'); 
			 | 
		
	
		
			
			| 
				332
			 | 
			
				
			 | 
			
			
				- 
			 | 
		
	
		
			
			| 
				333
			 | 
			
				
			 | 
			
			
				-    final box = isBaseHandle ? boxes.first : boxes.last; 
			 | 
		
	
		
			
			| 
				334
			 | 
			
				
			 | 
			
			
				-    final dx = isBaseHandle ? box.start : box.end; 
			 | 
		
	
		
			
			| 
				335
			 | 
			
				
			 | 
			
			
				-    return new Offset(dx, box.bottom); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				329
			 | 
			
			
				+    final Offset paintOffset = Offset.zero; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				330
			 | 
			
			
				+    final List<ui.TextBox> boxes = block.getEndpointsForSelection(selection); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				331
			 | 
			
			
				+    final Offset start = 
			 | 
		
	
		
			
			| 
				
			 | 
			
				332
			 | 
			
			
				+        Offset(boxes.first.start, boxes.first.bottom) + paintOffset; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				333
			 | 
			
			
				+    final Offset end = Offset(boxes.last.end, boxes.last.bottom) + paintOffset; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				334
			 | 
			
			
				+    return <TextSelectionPoint>[ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				335
			 | 
			
			
				+      TextSelectionPoint(start, boxes.first.direction), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				336
			 | 
			
			
				+      TextSelectionPoint(end, boxes.last.direction), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				337
			 | 
			
			
				+    ]; 
			 | 
		
	
		
			
			| 
				336
			 | 
			
				338
			 | 
			
			
				   } 
			 | 
		
	
		
			
			| 
				337
			 | 
			
				339
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				338
			 | 
			
				340
			 | 
			
			
				   @override 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -366,39 +368,97 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> { 
			 | 
		
	
		
			
			| 
				366
			 | 
			
				368
			 | 
			
			
				       return new Container(); 
			 | 
		
	
		
			
			| 
				367
			 | 
			
				369
			 | 
			
			
				     } 
			 | 
		
	
		
			
			| 
				368
			 | 
			
				370
			 | 
			
			
				     final block = _scope.renderContext.boxForTextOffset(documentOffset); 
			 | 
		
	
		
			
			| 
				369
			 | 
			
				
			 | 
			
			
				-    final position = getPosition(block); 
			 | 
		
	
		
			
			| 
				370
			 | 
			
				
			 | 
			
			
				-    Widget handle; 
			 | 
		
	
		
			
			| 
				371
			 | 
			
				
			 | 
			
			
				-    if (position == null) { 
			 | 
		
	
		
			
			| 
				372
			 | 
			
				
			 | 
			
			
				-      handle = new Container(); 
			 | 
		
	
		
			
			| 
				373
			 | 
			
				
			 | 
			
			
				-    } else { 
			 | 
		
	
		
			
			| 
				374
			 | 
			
				
			 | 
			
			
				-      final handleType = isBaseHandle 
			 | 
		
	
		
			
			| 
				375
			 | 
			
				
			 | 
			
			
				-          ? TextSelectionHandleType.left 
			 | 
		
	
		
			
			| 
				376
			 | 
			
				
			 | 
			
			
				-          : TextSelectionHandleType.right; 
			 | 
		
	
		
			
			| 
				377
			 | 
			
				
			 | 
			
			
				-      handle = new Positioned( 
			 | 
		
	
		
			
			| 
				378
			 | 
			
				
			 | 
			
			
				-        left: position.dx, 
			 | 
		
	
		
			
			| 
				379
			 | 
			
				
			 | 
			
			
				-        top: position.dy, 
			 | 
		
	
		
			
			| 
				380
			 | 
			
				
			 | 
			
			
				-        child: widget.controls.buildHandle( 
			 | 
		
	
		
			
			| 
				381
			 | 
			
				
			 | 
			
			
				-          context, 
			 | 
		
	
		
			
			| 
				382
			 | 
			
				
			 | 
			
			
				-          handleType, 
			 | 
		
	
		
			
			| 
				383
			 | 
			
				
			 | 
			
			
				-          block.preferredLineHeight, 
			 | 
		
	
		
			
			| 
				384
			 | 
			
				
			 | 
			
			
				-        ), 
			 | 
		
	
		
			
			| 
				385
			 | 
			
				
			 | 
			
			
				-      ); 
			 | 
		
	
		
			
			| 
				386
			 | 
			
				
			 | 
			
			
				-      handle = new CompositedTransformFollower( 
			 | 
		
	
		
			
			| 
				387
			 | 
			
				
			 | 
			
			
				-        link: block.layerLink, 
			 | 
		
	
		
			
			| 
				388
			 | 
			
				
			 | 
			
			
				-        showWhenUnlinked: false, 
			 | 
		
	
		
			
			| 
				389
			 | 
			
				
			 | 
			
			
				-        child: new Stack( 
			 | 
		
	
		
			
			| 
				390
			 | 
			
				
			 | 
			
			
				-          overflow: Overflow.visible, 
			 | 
		
	
		
			
			| 
				391
			 | 
			
				
			 | 
			
			
				-          children: <Widget>[handle], 
			 | 
		
	
		
			
			| 
				392
			 | 
			
				
			 | 
			
			
				-        ), 
			 | 
		
	
		
			
			| 
				393
			 | 
			
				
			 | 
			
			
				-      ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				371
			 | 
			
			
				+    if (block == null) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				372
			 | 
			
			
				+      // TODO: For some reason sometimes we get updates when render boxes 
			 | 
		
	
		
			
			| 
				
			 | 
			
				373
			 | 
			
			
				+      //      are in process of rebuilding so we don't have access to them here. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				374
			 | 
			
			
				+      //      As a workaround we just return empty container. There is usually 
			 | 
		
	
		
			
			| 
				
			 | 
			
				375
			 | 
			
			
				+      //      another rebuild right after which "fixes" the view. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				376
			 | 
			
			
				+      //      Example: when toolbar button is toggled changing style of current 
			 | 
		
	
		
			
			| 
				
			 | 
			
				377
			 | 
			
			
				+      //      selection. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				378
			 | 
			
			
				+      return Container(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				379
			 | 
			
			
				+    } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				380
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				381
			 | 
			
			
				+    final List<TextSelectionPoint> endpoints = getEndpointsForSelection(block); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				382
			 | 
			
			
				+    Offset point; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				383
			 | 
			
			
				+    TextSelectionHandleType type; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				384
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				385
			 | 
			
			
				+    switch (widget.position) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				386
			 | 
			
			
				+      case _SelectionHandlePosition.base: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				387
			 | 
			
			
				+        point = endpoints[0].point; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				388
			 | 
			
			
				+        type = _chooseType(endpoints[0], TextSelectionHandleType.left, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				389
			 | 
			
			
				+            TextSelectionHandleType.right); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				390
			 | 
			
			
				+        break; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				391
			 | 
			
			
				+      case _SelectionHandlePosition.extent: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				392
			 | 
			
			
				+        // [endpoints] will only contain 1 point for collapsed selections, in 
			 | 
		
	
		
			
			| 
				
			 | 
			
				393
			 | 
			
			
				+        // which case we shouldn't be building the [end] handle. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				394
			 | 
			
			
				+        assert(endpoints.length == 2); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				395
			 | 
			
			
				+        point = endpoints[1].point; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				396
			 | 
			
			
				+        type = _chooseType(endpoints[1], TextSelectionHandleType.right, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				397
			 | 
			
			
				+            TextSelectionHandleType.left); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				398
			 | 
			
			
				+        break; 
			 | 
		
	
		
			
			| 
				394
			 | 
			
				399
			 | 
			
			
				     } 
			 | 
		
	
		
			
			| 
				395
			 | 
			
				
			 | 
			
			
				-    // Always return this gesture detector even if handle is an empty container 
			 | 
		
	
		
			
			| 
				396
			 | 
			
				
			 | 
			
			
				-    // This way we prevent drag gesture from being canceled in case current 
			 | 
		
	
		
			
			| 
				397
			 | 
			
				
			 | 
			
			
				-    // position is somewhere outside of any visible paragraph block. 
			 | 
		
	
		
			
			| 
				398
			 | 
			
				
			 | 
			
			
				-    return new GestureDetector( 
			 | 
		
	
		
			
			| 
				399
			 | 
			
				
			 | 
			
			
				-      onPanStart: _handleDragStart, 
			 | 
		
	
		
			
			| 
				400
			 | 
			
				
			 | 
			
			
				-      onPanUpdate: _handleDragUpdate, 
			 | 
		
	
		
			
			| 
				401
			 | 
			
				
			 | 
			
			
				-      child: handle, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				400
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				401
			 | 
			
			
				+    final Size viewport = block.size; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				402
			 | 
			
			
				+    point = Offset( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				403
			 | 
			
			
				+      point.dx.clamp(0.0, viewport.width), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				404
			 | 
			
			
				+      point.dy.clamp(0.0, viewport.height), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				405
			 | 
			
			
				+    ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				406
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				407
			 | 
			
			
				+    final Offset handleAnchor = widget.controls.getHandleAnchor( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				408
			 | 
			
			
				+      type, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				409
			 | 
			
			
				+      block.preferredLineHeight, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				410
			 | 
			
			
				+    ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				411
			 | 
			
			
				+    final Size handleSize = widget.controls.getHandleSize( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				412
			 | 
			
			
				+      block.preferredLineHeight, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				413
			 | 
			
			
				+    ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				414
			 | 
			
			
				+    final Rect handleRect = Rect.fromLTWH( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				415
			 | 
			
			
				+      // Put handleAnchor on top of point 
			 | 
		
	
		
			
			| 
				
			 | 
			
				416
			 | 
			
			
				+      point.dx - handleAnchor.dx, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				417
			 | 
			
			
				+      point.dy - handleAnchor.dy, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				418
			 | 
			
			
				+      handleSize.width, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				419
			 | 
			
			
				+      handleSize.height, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				420
			 | 
			
			
				+    ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				421
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				422
			 | 
			
			
				+    // Make sure the GestureDetector is big enough to be easily interactive. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				423
			 | 
			
			
				+    final Rect interactiveRect = handleRect.expandToInclude( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				424
			 | 
			
			
				+      Rect.fromCircle( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				425
			 | 
			
			
				+          center: handleRect.center, radius: kMinInteractiveSize / 2), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				426
			 | 
			
			
				+    ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				427
			 | 
			
			
				+    final RelativeRect padding = RelativeRect.fromLTRB( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				428
			 | 
			
			
				+      math.max((interactiveRect.width - handleRect.width) / 2, 0), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				429
			 | 
			
			
				+      math.max((interactiveRect.height - handleRect.height) / 2, 0), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				430
			 | 
			
			
				+      math.max((interactiveRect.width - handleRect.width) / 2, 0), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				431
			 | 
			
			
				+      math.max((interactiveRect.height - handleRect.height) / 2, 0), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				432
			 | 
			
			
				+    ); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				433
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				434
			 | 
			
			
				+    return CompositedTransformFollower( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				435
			 | 
			
			
				+      link: block.layerLink, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				436
			 | 
			
			
				+      offset: interactiveRect.topLeft, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				437
			 | 
			
			
				+      showWhenUnlinked: false, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				438
			 | 
			
			
				+      child: Container( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				439
			 | 
			
			
				+        alignment: Alignment.topLeft, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				440
			 | 
			
			
				+        width: interactiveRect.width, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				441
			 | 
			
			
				+        height: interactiveRect.height, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				442
			 | 
			
			
				+        child: GestureDetector( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				443
			 | 
			
			
				+          behavior: HitTestBehavior.translucent, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				444
			 | 
			
			
				+          dragStartBehavior: DragStartBehavior.start, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				445
			 | 
			
			
				+          onPanStart: _handleDragStart, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				446
			 | 
			
			
				+          onPanUpdate: _handleDragUpdate, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				447
			 | 
			
			
				+          child: Padding( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				448
			 | 
			
			
				+            padding: EdgeInsets.only( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				449
			 | 
			
			
				+              left: padding.left, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				450
			 | 
			
			
				+              top: padding.top, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				451
			 | 
			
			
				+              right: padding.right, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				452
			 | 
			
			
				+              bottom: padding.bottom, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				453
			 | 
			
			
				+            ), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				454
			 | 
			
			
				+            child: widget.controls.buildHandle( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				455
			 | 
			
			
				+              context, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				456
			 | 
			
			
				+              type, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				457
			 | 
			
			
				+              block.preferredLineHeight, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				458
			 | 
			
			
				+            ), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				459
			 | 
			
			
				+          ), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				460
			 | 
			
			
				+        ), 
			 | 
		
	
		
			
			| 
				
			 | 
			
				461
			 | 
			
			
				+      ), 
			 | 
		
	
		
			
			| 
				402
			 | 
			
				462
			 | 
			
			
				     ); 
			 | 
		
	
		
			
			| 
				403
			 | 
			
				463
			 | 
			
			
				   } 
			 | 
		
	
		
			
			| 
				404
			 | 
			
				464
			 | 
			
			
				  
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -406,6 +466,23 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver> { 
			 | 
		
	
		
			
			| 
				406
			 | 
			
				466
			 | 
			
			
				   // Private members 
			 | 
		
	
		
			
			| 
				407
			 | 
			
				467
			 | 
			
			
				   // 
			 | 
		
	
		
			
			| 
				408
			 | 
			
				468
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				469
			 | 
			
			
				+  TextSelectionHandleType _chooseType( 
			 | 
		
	
		
			
			| 
				
			 | 
			
				470
			 | 
			
			
				+    TextSelectionPoint endpoint, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				471
			 | 
			
			
				+    TextSelectionHandleType ltrType, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				472
			 | 
			
			
				+    TextSelectionHandleType rtlType, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				473
			 | 
			
			
				+  ) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				474
			 | 
			
			
				+    if (selection.isCollapsed) return TextSelectionHandleType.collapsed; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				475
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				476
			 | 
			
			
				+    assert(endpoint.direction != null); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				477
			 | 
			
			
				+    switch (endpoint.direction) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				478
			 | 
			
			
				+      case TextDirection.ltr: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				479
			 | 
			
			
				+        return ltrType; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				480
			 | 
			
			
				+      case TextDirection.rtl: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				481
			 | 
			
			
				+        return rtlType; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				482
			 | 
			
			
				+    } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				483
			 | 
			
			
				+    return null; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				484
			 | 
			
			
				+  } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				485
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				409
			 | 
			
				486
			 | 
			
			
				   Offset _dragPosition; 
			 | 
		
	
		
			
			| 
				410
			 | 
			
				487
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				411
			 | 
			
				488
			 | 
			
			
				   void _handleScopeChange() { 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -506,8 +583,9 @@ class _SelectionToolbarState extends State<_SelectionToolbar> { 
			 | 
		
	
		
			
			| 
				506
			 | 
			
				583
			 | 
			
			
				       block.localToGlobal(Offset.zero), 
			 | 
		
	
		
			
			| 
				507
			 | 
			
				584
			 | 
			
			
				       block.localToGlobal(block.size.bottomRight(Offset.zero)), 
			 | 
		
	
		
			
			| 
				508
			 | 
			
				585
			 | 
			
			
				     ); 
			 | 
		
	
		
			
			| 
				509
			 | 
			
				
			 | 
			
			
				-    final toolbar = widget.controls.buildToolbar( 
			 | 
		
	
		
			
			| 
				510
			 | 
			
				
			 | 
			
			
				-        context, editingRegion, midpoint, endpoints, widget.delegate); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				586
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				587
			 | 
			
			
				+    final toolbar = widget.controls.buildToolbar(context, editingRegion, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				588
			 | 
			
			
				+        block.preferredLineHeight, midpoint, endpoints, widget.delegate); 
			 | 
		
	
		
			
			| 
				511
			 | 
			
				589
			 | 
			
			
				     return new CompositedTransformFollower( 
			 | 
		
	
		
			
			| 
				512
			 | 
			
				590
			 | 
			
			
				       link: block.layerLink, 
			 | 
		
	
		
			
			| 
				513
			 | 
			
				591
			 | 
			
			
				       showWhenUnlinked: false, 
			 |