Browse Source

Merge pull request #76 from memspace/cursor-color

Allow customizing cursor color
Anatoly Pulyaevskiy 6 years ago
parent
commit
aa422567fa
No account linked to committer's email address

+ 2
- 1
packages/zefyr/CHANGELOG.md View File

1
-## Unreleased
1
+## 0.3.1
2
 
2
 
3
 - Fixed autofocus not being triggered when set to `true` for the first time.
3
 - Fixed autofocus not being triggered when set to `true` for the first time.
4
+- Allow customizing cursor color via ZefyrTheme.
4
 
5
 
5
 ## 0.3.0
6
 ## 0.3.0
6
 
7
 

+ 1
- 0
packages/zefyr/example/lib/src/full_page.dart View File

43
   @override
43
   @override
44
   Widget build(BuildContext context) {
44
   Widget build(BuildContext context) {
45
     final theme = new ZefyrThemeData(
45
     final theme = new ZefyrThemeData(
46
+      cursorColor: Colors.blue,
46
       toolbarTheme: ZefyrToolbarTheme.fallback(context).copyWith(
47
       toolbarTheme: ZefyrToolbarTheme.fallback(context).copyWith(
47
         color: Colors.grey.shade800,
48
         color: Colors.grey.shade800,
48
         toggleColor: Colors.grey.shade900,
49
         toggleColor: Colors.grey.shade900,

+ 14
- 2
packages/zefyr/lib/src/widgets/caret.dart View File

5
 
5
 
6
 import 'package:flutter/material.dart';
6
 import 'package:flutter/material.dart';
7
 
7
 
8
-class CaretPainter {
8
+/// Helper class responsible for cursor layout and painting.
9
+class CursorPainter {
9
   static const double _kCaretHeightOffset = 2.0; // pixels
10
   static const double _kCaretHeightOffset = 2.0; // pixels
10
   static const double _kCaretWidth = 1.0; // pixels
11
   static const double _kCaretWidth = 1.0; // pixels
11
 
12
 
14
         0.0, 0.0, _kCaretWidth, lineHeight - _kCaretHeightOffset);
15
         0.0, 0.0, _kCaretWidth, lineHeight - _kCaretHeightOffset);
15
   }
16
   }
16
 
17
 
18
+  CursorPainter(Color color)
19
+      : assert(color != null),
20
+        _color = color;
21
+
17
   Rect _prototype;
22
   Rect _prototype;
18
 
23
 
19
   Rect get prototype => _prototype;
24
   Rect get prototype => _prototype;
20
 
25
 
26
+  Color _color;
27
+  Color get color => _color;
28
+  set color(Color value) {
29
+    assert(value != null);
30
+    _color = value;
31
+  }
32
+
21
   void layout(double lineHeight) {
33
   void layout(double lineHeight) {
22
     _prototype = buildPrototype(lineHeight);
34
     _prototype = buildPrototype(lineHeight);
23
   }
35
   }
24
 
36
 
25
   void paint(Canvas canvas, Offset offset) {
37
   void paint(Canvas canvas, Offset offset) {
26
-    final Paint paint = new Paint()..color = Colors.black;
38
+    final Paint paint = new Paint()..color = _color;
27
     final Rect caretRect = _prototype.shift(offset);
39
     final Rect caretRect = _prototype.shift(offset);
28
     canvas.drawRect(caretRect, paint);
40
     canvas.drawRect(caretRect, paint);
29
   }
41
   }

+ 3
- 0
packages/zefyr/lib/src/widgets/common.dart View File

65
         showCursor: editable.showCursor,
65
         showCursor: editable.showCursor,
66
         selection: editable.selection,
66
         selection: editable.selection,
67
         selectionColor: theme.selectionColor,
67
         selectionColor: theme.selectionColor,
68
+        cursorColor: theme.cursorColor,
68
       );
69
       );
69
     }
70
     }
70
 
71
 
153
         showCursor: editable.showCursor,
154
         showCursor: editable.showCursor,
154
         selection: editable.selection,
155
         selection: editable.selection,
155
         selectionColor: theme.selectionColor,
156
         selectionColor: theme.selectionColor,
157
+        cursorColor: theme.cursorColor,
156
       );
158
       );
157
     } else if (embed.type == EmbedType.image) {
159
     } else if (embed.type == EmbedType.image) {
158
       return new EditableBox(
160
       return new EditableBox(
163
         showCursor: editable.showCursor,
165
         showCursor: editable.showCursor,
164
         selection: editable.selection,
166
         selection: editable.selection,
165
         selectionColor: theme.selectionColor,
167
         selectionColor: theme.selectionColor,
168
+        cursorColor: theme.cursorColor,
166
       );
169
       );
167
     } else {
170
     } else {
168
       throw new UnimplementedError('Unimplemented embed type ${embed.type}');
171
       throw new UnimplementedError('Unimplemented embed type ${embed.type}');

+ 21
- 8
packages/zefyr/lib/src/widgets/editable_box.dart View File

20
     @required this.showCursor,
20
     @required this.showCursor,
21
     @required this.selection,
21
     @required this.selection,
22
     @required this.selectionColor,
22
     @required this.selectionColor,
23
+    @required this.cursorColor,
23
   }) : super(child: child);
24
   }) : super(child: child);
24
 
25
 
25
   final ContainerNode node;
26
   final ContainerNode node;
28
   final ValueNotifier<bool> showCursor;
29
   final ValueNotifier<bool> showCursor;
29
   final TextSelection selection;
30
   final TextSelection selection;
30
   final Color selectionColor;
31
   final Color selectionColor;
32
+  final Color cursorColor;
31
 
33
 
32
   @override
34
   @override
33
   RenderEditableProxyBox createRenderObject(BuildContext context) {
35
   RenderEditableProxyBox createRenderObject(BuildContext context) {
38
       showCursor: showCursor,
40
       showCursor: showCursor,
39
       selection: selection,
41
       selection: selection,
40
       selectionColor: selectionColor,
42
       selectionColor: selectionColor,
43
+      cursorColor: cursorColor,
41
     );
44
     );
42
   }
45
   }
43
 
46
 
50
       ..renderContext = renderContext
53
       ..renderContext = renderContext
51
       ..showCursor = showCursor
54
       ..showCursor = showCursor
52
       ..selection = selection
55
       ..selection = selection
53
-      ..selectionColor = selectionColor;
56
+      ..selectionColor = selectionColor
57
+      ..cursorColor = cursorColor;
54
   }
58
   }
55
 }
59
 }
56
 
60
 
67
     @required ValueNotifier<bool> showCursor,
71
     @required ValueNotifier<bool> showCursor,
68
     @required TextSelection selection,
72
     @required TextSelection selection,
69
     @required Color selectionColor,
73
     @required Color selectionColor,
74
+    @required Color cursorColor,
70
   })  : _node = node,
75
   })  : _node = node,
71
         _layerLink = layerLink,
76
         _layerLink = layerLink,
72
         _renderContext = renderContext,
77
         _renderContext = renderContext,
75
         _selectionColor = selectionColor,
80
         _selectionColor = selectionColor,
76
         super() {
81
         super() {
77
     this.child = child;
82
     this.child = child;
83
+    _cursorPainter = CursorPainter(cursorColor);
84
+  }
85
+
86
+  CursorPainter _cursorPainter;
87
+
88
+  set cursorColor(Color value) {
89
+    if (_cursorPainter.color != value) {
90
+      _cursorPainter.color = value;
91
+      markNeedsPaint();
92
+    }
78
   }
93
   }
79
 
94
 
80
   bool _isDirty = true;
95
   bool _isDirty = true;
171
   @mustCallSuper
186
   @mustCallSuper
172
   void performLayout() {
187
   void performLayout() {
173
     super.performLayout();
188
     super.performLayout();
174
-    _caretPainter.layout(preferredLineHeight);
189
+    _cursorPainter.layout(preferredLineHeight);
175
     // Indicate to render context that this object can be used by other
190
     // Indicate to render context that this object can be used by other
176
     // layers (selection overlay, for instance).
191
     // layers (selection overlay, for instance).
177
     _isDirty = false;
192
     _isDirty = false;
196
       paintSelection(context, offset, selection, selectionColor);
211
       paintSelection(context, offset, selection, selectionColor);
197
     }
212
     }
198
     if (isCaretVisible) {
213
     if (isCaretVisible) {
199
-      _paintCaret(context, offset);
214
+      _paintCursor(context, offset);
200
     }
215
     }
201
   }
216
   }
202
 
217
 
203
-  final CaretPainter _caretPainter = new CaretPainter();
204
-
205
-  void _paintCaret(PaintingContext context, Offset offset) {
218
+  void _paintCursor(PaintingContext context, Offset offset) {
206
     Offset caretOffset =
219
     Offset caretOffset =
207
-        getOffsetForCaret(_selection.extent, _caretPainter.prototype);
208
-    _caretPainter.paint(context.canvas, caretOffset + offset);
220
+        getOffsetForCaret(_selection.extent, _cursorPainter.prototype);
221
+    _cursorPainter.paint(context.canvas, caretOffset + offset);
209
   }
222
   }
210
 
223
 
211
   @override
224
   @override

+ 1
- 1
packages/zefyr/lib/src/widgets/rich_text.dart View File

127
   List<ui.TextBox> getEndpointsForSelection(TextSelection selection) {
127
   List<ui.TextBox> getEndpointsForSelection(TextSelection selection) {
128
     TextSelection local = getLocalSelection(selection);
128
     TextSelection local = getLocalSelection(selection);
129
     if (local.isCollapsed) {
129
     if (local.isCollapsed) {
130
-      final caret = CaretPainter.buildPrototype(preferredLineHeight);
130
+      final caret = CursorPainter.buildPrototype(preferredLineHeight);
131
       final offset = getOffsetForCaret(local.extent, caret);
131
       final offset = getOffsetForCaret(local.extent, caret);
132
       return [
132
       return [
133
         new ui.TextBox.fromLTRBD(
133
         new ui.TextBox.fromLTRBD(

+ 6
- 0
packages/zefyr/lib/src/widgets/theme.dart View File

60
   final HeadingTheme headingTheme;
60
   final HeadingTheme headingTheme;
61
   final BlockTheme blockTheme;
61
   final BlockTheme blockTheme;
62
   final Color selectionColor;
62
   final Color selectionColor;
63
+  final Color cursorColor;
63
 
64
 
64
   /// Size of indentation for blocks.
65
   /// Size of indentation for blocks.
65
   final double indentSize;
66
   final double indentSize;
88
       headingTheme: new HeadingTheme.fallback(),
89
       headingTheme: new HeadingTheme.fallback(),
89
       blockTheme: new BlockTheme.fallback(),
90
       blockTheme: new BlockTheme.fallback(),
90
       selectionColor: Colors.lightBlueAccent.shade100,
91
       selectionColor: Colors.lightBlueAccent.shade100,
92
+      cursorColor: Colors.black,
91
       indentSize: 16.0,
93
       indentSize: 16.0,
92
       toolbarTheme: new ZefyrToolbarTheme.fallback(context),
94
       toolbarTheme: new ZefyrToolbarTheme.fallback(context),
93
     );
95
     );
101
     this.headingTheme,
103
     this.headingTheme,
102
     this.blockTheme,
104
     this.blockTheme,
103
     this.selectionColor,
105
     this.selectionColor,
106
+    this.cursorColor,
104
     this.indentSize,
107
     this.indentSize,
105
     this.toolbarTheme,
108
     this.toolbarTheme,
106
   });
109
   });
114
     HeadingTheme headingTheme,
117
     HeadingTheme headingTheme,
115
     BlockTheme blockTheme,
118
     BlockTheme blockTheme,
116
     Color selectionColor,
119
     Color selectionColor,
120
+    Color cursorColor,
117
     double indentSize,
121
     double indentSize,
118
     ZefyrToolbarTheme toolbarTheme,
122
     ZefyrToolbarTheme toolbarTheme,
119
   }) {
123
   }) {
125
       headingTheme: headingTheme ?? this.headingTheme,
129
       headingTheme: headingTheme ?? this.headingTheme,
126
       blockTheme: blockTheme ?? this.blockTheme,
130
       blockTheme: blockTheme ?? this.blockTheme,
127
       selectionColor: selectionColor ?? this.selectionColor,
131
       selectionColor: selectionColor ?? this.selectionColor,
132
+      cursorColor: cursorColor ?? this.cursorColor,
128
       indentSize: indentSize ?? this.indentSize,
133
       indentSize: indentSize ?? this.indentSize,
129
       toolbarTheme: toolbarTheme ?? this.toolbarTheme,
134
       toolbarTheme: toolbarTheme ?? this.toolbarTheme,
130
     );
135
     );
139
       headingTheme: other.headingTheme,
144
       headingTheme: other.headingTheme,
140
       blockTheme: other.blockTheme,
145
       blockTheme: other.blockTheme,
141
       selectionColor: other.selectionColor,
146
       selectionColor: other.selectionColor,
147
+      cursorColor: other.cursorColor,
142
       indentSize: other.indentSize,
148
       indentSize: other.indentSize,
143
       toolbarTheme: other.toolbarTheme,
149
       toolbarTheme: other.toolbarTheme,
144
     );
150
     );

+ 4
- 3
packages/zefyr/test/painting/caret_painter_test.dart View File

3
 // BSD-style license that can be found in the LICENSE file.
3
 // BSD-style license that can be found in the LICENSE file.
4
 import 'dart:ui';
4
 import 'dart:ui';
5
 
5
 
6
+import 'package:flutter/material.dart';
6
 import 'package:flutter_test/flutter_test.dart';
7
 import 'package:flutter_test/flutter_test.dart';
7
 import 'package:zefyr/src/widgets/caret.dart';
8
 import 'package:zefyr/src/widgets/caret.dart';
8
 
9
 
9
 void main() {
10
 void main() {
10
-  group('$CaretPainter', () {
11
+  group('$CursorPainter', () {
11
     test('prototype is null before layout', () {
12
     test('prototype is null before layout', () {
12
-      var painter = new CaretPainter();
13
+      var painter = new CursorPainter(Colors.black);
13
       expect(painter.prototype, isNull);
14
       expect(painter.prototype, isNull);
14
     });
15
     });
15
 
16
 
16
     test('prototype is set after layout', () {
17
     test('prototype is set after layout', () {
17
-      var painter = new CaretPainter();
18
+      var painter = new CursorPainter(Colors.black);
18
       painter.layout(16.0);
19
       painter.layout(16.0);
19
       expect(painter.prototype, new Rect.fromLTWH(0.0, 0.0, 1.0, 14.0));
20
       expect(painter.prototype, new Rect.fromLTWH(0.0, 0.0, 1.0, 14.0));
20
     });
21
     });

+ 1
- 0
packages/zefyr/test/rendering/render_editable_proxy_box_test.dart View File

36
         showCursor: ValueNotifier<bool>(true),
36
         showCursor: ValueNotifier<bool>(true),
37
         selection: TextSelection.collapsed(offset: 0),
37
         selection: TextSelection.collapsed(offset: 0),
38
         selectionColor: Color(0),
38
         selectionColor: Color(0),
39
+        cursorColor: Color(0),
39
       );
40
       );
40
     });
41
     });
41
 
42
 

+ 1
- 0
packages/zefyr/test/widgets/editable_text_scope_test.dart View File

103
     showCursor: showCursor,
103
     showCursor: showCursor,
104
     selection: selection,
104
     selection: selection,
105
     selectionColor: selectionColor,
105
     selectionColor: selectionColor,
106
+    cursorColor: Color(0),
106
   );
107
   );
107
 }
108
 }

+ 1
- 0
packages/zefyr/test/widgets/render_context_test.dart View File

85
     showCursor: showCursor,
85
     showCursor: showCursor,
86
     selection: selection,
86
     selection: selection,
87
     selectionColor: selectionColor,
87
     selectionColor: selectionColor,
88
+    cursorColor: Color(0),
88
   );
89
   );
89
 }
90
 }