|
@@ -44,6 +44,12 @@ class ZefyrController extends ChangeNotifier {
|
44
|
44
|
/// Source of the last text or selection change.
|
45
|
45
|
ChangeSource get lastChangeSource => _lastChangeSource;
|
46
|
46
|
|
|
47
|
+ /// Store any styles attribute that got toggled by the tap of a button
|
|
48
|
+ /// and that has not been applied yet.
|
|
49
|
+ /// It gets reseted after each format action within the [document].
|
|
50
|
+ NotusStyle get toggledStyles => _toggledStyles;
|
|
51
|
+ NotusStyle _toggledStyles = new NotusStyle();
|
|
52
|
+
|
47
|
53
|
/// Updates selection with specified [value].
|
48
|
54
|
///
|
49
|
55
|
/// [value] and [source] cannot be `null`.
|
|
@@ -104,6 +110,9 @@ class ZefyrController extends ChangeNotifier {
|
104
|
110
|
/// Resulting change is registered as produced by user action, e.g.
|
105
|
111
|
/// using [ChangeSource.local].
|
106
|
112
|
///
|
|
113
|
+ /// It also applies the toggledStyle if needed. And then it resets it
|
|
114
|
+ /// in any cases as we don't want to keep it except on inserts.
|
|
115
|
+ ///
|
107
|
116
|
/// Optionally updates selection if provided.
|
108
|
117
|
void replaceText(int index, int length, String text,
|
109
|
118
|
{TextSelection selection}) {
|
|
@@ -111,8 +120,23 @@ class ZefyrController extends ChangeNotifier {
|
111
|
120
|
|
112
|
121
|
if (length > 0 || text.isNotEmpty) {
|
113
|
122
|
delta = document.replace(index, length, text);
|
|
123
|
+ // If the delta is a classical insert operation and we have toggled
|
|
124
|
+ // some style, then we apply it to our document.
|
|
125
|
+ if (delta != null &&
|
|
126
|
+ toggledStyles.isNotEmpty &&
|
|
127
|
+ delta.length == 2 &&
|
|
128
|
+ delta[1].isInsert) {
|
|
129
|
+ // Apply it.
|
|
130
|
+ Delta retainDelta = new Delta()
|
|
131
|
+ ..retain(index)
|
|
132
|
+ ..retain(1, toggledStyles.toJson());
|
|
133
|
+ document.compose(retainDelta, ChangeSource.local);
|
|
134
|
+ }
|
114
|
135
|
}
|
115
|
136
|
|
|
137
|
+ // Always reset it after any user action, even if it has not been applied.
|
|
138
|
+ _toggledStyles = new NotusStyle();
|
|
139
|
+
|
116
|
140
|
if (selection != null) {
|
117
|
141
|
if (delta == null) {
|
118
|
142
|
_updateSelectionSilent(selection, source: ChangeSource.local);
|
|
@@ -140,6 +164,14 @@ class ZefyrController extends ChangeNotifier {
|
140
|
164
|
void formatText(int index, int length, NotusAttribute attribute) {
|
141
|
165
|
final change = document.format(index, length, attribute);
|
142
|
166
|
_lastChangeSource = ChangeSource.local;
|
|
167
|
+
|
|
168
|
+ if (length == 0 &&
|
|
169
|
+ (attribute.key == NotusAttribute.bold.key ||
|
|
170
|
+ attribute.key == NotusAttribute.italic.key)) {
|
|
171
|
+ // Add the attribute to our toggledStyle. It will be used later upon insertion.
|
|
172
|
+ _toggledStyles = toggledStyles.put(attribute);
|
|
173
|
+ }
|
|
174
|
+
|
143
|
175
|
// Transform selection against the composed change and give priority to
|
144
|
176
|
// the change. This is needed in cases when format operation actually
|
145
|
177
|
// inserts data into the document (e.g. embeds).
|
|
@@ -160,10 +192,18 @@ class ZefyrController extends ChangeNotifier {
|
160
|
192
|
formatText(index, length, attribute);
|
161
|
193
|
}
|
162
|
194
|
|
|
195
|
+ /// Returns style of specified text range.
|
|
196
|
+ ///
|
|
197
|
+ /// If nothing is selected but we've toggled an attribute,
|
|
198
|
+ /// we also merge those in our style before returning.
|
163
|
199
|
NotusStyle getSelectionStyle() {
|
164
|
200
|
int start = _selection.start;
|
165
|
201
|
int length = _selection.end - start;
|
166
|
|
- return _document.collectStyle(start, length);
|
|
202
|
+ var lineStyle = _document.collectStyle(start, length);
|
|
203
|
+
|
|
204
|
+ lineStyle = lineStyle.mergeAll(toggledStyles);
|
|
205
|
+
|
|
206
|
+ return lineStyle;
|
167
|
207
|
}
|
168
|
208
|
|
169
|
209
|
TextEditingValue get plainTextEditingValue {
|