overlay_manager.dart
4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'gesture_detector_builder.dart';
import 'gesture_detector_builder_selectable.dart';
import 'overlay.dart';
import 'selection_manager.dart';
mixin SelectionOverlayManagerMixin<T extends StatefulWidget>
on SelectionManagerMixin<T>
implements MathSelectionGestureDetectorBuilderDelegate {
FocusNode get focusNode;
bool get hasFocus => focusNode.hasFocus;
double get preferredLineHeight;
TextSelectionControls get textSelectionControls;
DragStartBehavior get dragStartBehavior;
MathSelectionOverlay? get selectionOverlay => _selectionOverlay;
MathSelectionOverlay? _selectionOverlay;
final toolbarLayerLink = LayerLink();
final startHandleLayerLink = LayerLink();
final endHandleLayerLink = LayerLink();
bool toolbarVisible = false;
late SelectableMathSelectionGestureDetectorBuilder
_selectionGestureDetectorBuilder;
SelectableMathSelectionGestureDetectorBuilder
get selectionGestureDetectorBuilder => _selectionGestureDetectorBuilder;
@override
void initState() {
super.initState();
_selectionGestureDetectorBuilder =
SelectableMathSelectionGestureDetectorBuilder(delegate: this);
}
@override
void didUpdateWidget(T oldWidget) {
super.didUpdateWidget(oldWidget);
_selectionOverlay?.update();
}
@override
void dispose() {
_selectionOverlay?.dispose();
super.dispose();
}
/// Shows the selection toolbar at the location of the current cursor.
///
/// Returns `false` if a toolbar couldn't be shown, such as when the toolbar
/// is already shown, or when no text selection currently exists.
bool showToolbar() {
// Web is using native dom elements to enable clipboard functionality of the
// toolbar: copy, paste, select, cut. It might also provide additional
// functionality depending on the browser (such as translate). Due to this
// we should not show a Flutter toolbar for the editable text elements.
if (kIsWeb) {
return false;
}
if (_selectionOverlay == null || _selectionOverlay!.toolbarIsVisible) {
return false;
}
if (controller.selection.isCollapsed) {
return false;
}
_selectionOverlay!.showToolbar();
toolbarVisible = true;
return true;
}
@override
void hideToolbar([bool hideHandles = true]) {
toolbarVisible = false;
_selectionOverlay?.hideToolbar();
}
void hide() {
toolbarVisible = false;
_selectionOverlay?.hide();
}
bool _shouldShowSelectionHandles(SelectionChangedCause? cause) {
// When the text field is activated by something that doesn't trigger the
// selection overlay, we shouldn't show the handles either.
if (!_selectionGestureDetectorBuilder.shouldShowSelectionToolbar) {
return false;
}
if (controller.selection.isCollapsed) return false;
if (cause == SelectionChangedCause.keyboard) return false;
if (cause == SelectionChangedCause.longPress) return true;
if (controller.ast.greenRoot.capturedCursor > 1) return true;
return false;
}
void handleSelectionChanged(
TextSelection selection, SelectionChangedCause? cause,
[ExtraSelectionChangedCause? extraCause]) {
super.handleSelectionChanged(selection, cause, extraCause);
if (extraCause != ExtraSelectionChangedCause.handle) {
_selectionOverlay?.hide();
_selectionOverlay = null;
// if (textSelectionControls != null) {
_selectionOverlay = MathSelectionOverlay(
clipboardStatus: kIsWeb ? null : ClipboardStatusNotifier(),
manager: this,
toolbarLayerLink: toolbarLayerLink,
startHandleLayerLink: startHandleLayerLink,
endHandleLayerLink: endHandleLayerLink,
onSelectionHandleTapped: () {
if (!controller.selection.isCollapsed) {
toolbarVisible ? hideToolbar() : showToolbar();
}
},
selectionControls: textSelectionControls,
dragStartBehavior: dragStartBehavior,
debugRequiredFor: widget,
);
_selectionOverlay!.handlesVisible = _shouldShowSelectionHandles(cause);
if (SchedulerBinding.instance.schedulerPhase ==
SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance
.addPostFrameCallback((_) => _selectionOverlay!.showHandles());
} else {
_selectionOverlay!.showHandles();
}
// _selectionOverlay.showHandles();
// }
} else {
_selectionOverlay?.update();
}
}
}