Commit 5114e0d
authored
Move Layout Updates to NSTextStorage Delegate (#82)
### Description
**Detailed Changes**
- Makes `TextLayoutManager` a text storage delegate.
- Updates `TextLayoutManager` to use the text storage methods to update internal state.
- Remove `TextLayoutManager`'s layout transaction capabilities.
- Updates `replaceCharacters` to reflect the new layout manager requirements.
- Moves layout back into a `CATransaction`, now that method ordering is slightly different, macOS might call `layout` on the text view while we're laying out text. Doing that in a transaction ensures that doesn't happen and layout is atomic.
**Tests**
- Adds tests to the layout manager to ensure modifications are kept valid.
- Adds tests for `rects(in:)` to ensure it doesn't invalidate layout information.
- Adds a test ensuring editing text contents in a text view delegate callback doesn't break layout.
### Discussion
This change untangles the text layout updating from text view code. Right now the hierarchy looks like this:
```
(Update occurs)
TextView -> Text Layout Update
-> Text Storage Update
```
This isn't great, because it means anything that modifies the text outside of the text view *must* remember to update layout, selection, send notifications, and do it all in the right order. I'd like to move it to this hierarchy:
```
(Update occurs)
TextView -> Text Storage Update -> Text Layout Update
```
This way any component can modify the text storage, and that will be reflected in the layout manager. There's a myriad of small bugs in our editor right now that are effected by this.
One key result of this change is the ability to correctly modify text in textView delegate callbacks. Right now, if the text is updated in a callback, it can lead to a recursive layout call to the text layout manager. This leads to bad internal state, and bugs where entire sections of text disappear entirely.
This also comes with a performance boost. Since NSTextStorage automatically coagulates text changes, we'll perform less layout passes for each edit, and components can make use of the text storage's transaction capabilities to only cause layout after all edits have been applied in a transaction.
> [!NOTE]
> This change cannot be applied to the selection manager, the selection manager needs much more fine-grained information about edits than the layout manager to correctly update itself.
> @hi2gage and I have also discussed some modifications to the selection API, since keeping it in sync with the text storage makes less sense than the layout manager.
### Related Issues
* Could be related to CodeEditApp/CodeEditSourceEditor#196
### Checklist
- [x] Add Tests
- [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md)
- [x] The issues this PR addresses are related to each other
- [x] My changes generate no new warnings
- [x] My code builds and runs on my machine
- [x] My changes are all related to the related issue above
- [x] I documented my code
### Screenshots1 parent d5ef35f commit 5114e0d
File tree
12 files changed
+267
-102
lines changed- Sources/CodeEditTextView
- TextLayoutManager
- TextSelectionManager
- TextView
- Utils
- Tests/CodeEditTextViewTests
12 files changed
+267
-102
lines changedLines changed: 56 additions & 38 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| 14 | + | |
14 | 15 | | |
15 | | - | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
| 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 | + | |
22 | 55 | | |
23 | | - | |
| 56 | + | |
24 | 57 | | |
25 | 58 | | |
26 | 59 | | |
| |||
38 | 71 | | |
39 | 72 | | |
40 | 73 | | |
| 74 | + | |
41 | 75 | | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
42 | 80 | | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
50 | 87 | | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
58 | 91 | | |
59 | | - | |
60 | 92 | | |
61 | 93 | | |
62 | 94 | | |
| |||
65 | 97 | | |
66 | 98 | | |
67 | 99 | | |
68 | | - | |
| 100 | + | |
69 | 101 | | |
70 | 102 | | |
71 | 103 | | |
| |||
96 | 128 | | |
97 | 129 | | |
98 | 130 | | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | 131 | | |
Lines changed: 7 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
121 | 121 | | |
122 | 122 | | |
123 | 123 | | |
124 | | - | |
| 124 | + | |
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
| |||
165 | 165 | | |
166 | 166 | | |
167 | 167 | | |
168 | | - | |
| 168 | + | |
| 169 | + | |
169 | 170 | | |
170 | 171 | | |
171 | 172 | | |
| |||
190 | 191 | | |
191 | 192 | | |
192 | 193 | | |
| 194 | + | |
193 | 195 | | |
194 | 196 | | |
195 | 197 | | |
| |||
239 | 241 | | |
240 | 242 | | |
241 | 243 | | |
| 244 | + | |
| 245 | + | |
242 | 246 | | |
243 | 247 | | |
244 | 248 | | |
| |||
286 | 290 | | |
287 | 291 | | |
288 | 292 | | |
289 | | - | |
| 293 | + | |
290 | 294 | | |
291 | 295 | | |
292 | 296 | | |
| |||
Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 4 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
13 | | - | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
Lines changed: 13 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
199 | 199 | | |
200 | 200 | | |
201 | 201 | | |
202 | | - | |
203 | | - | |
204 | 202 | | |
205 | 203 | | |
206 | 204 | | |
| |||
209 | 207 | | |
210 | 208 | | |
211 | 209 | | |
| 210 | + | |
| 211 | + | |
212 | 212 | | |
213 | 213 | | |
214 | 214 | | |
| |||
217 | 217 | | |
218 | 218 | | |
219 | 219 | | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
220 | 225 | | |
221 | 226 | | |
222 | 227 | | |
| 228 | + | |
223 | 229 | | |
224 | 230 | | |
225 | 231 | | |
| |||
265 | 271 | | |
266 | 272 | | |
267 | 273 | | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
268 | 279 | | |
269 | 280 | | |
270 | 281 | | |
271 | 282 | | |
272 | 283 | | |
273 | 284 | | |
274 | | - | |
275 | | - | |
276 | | - | |
277 | | - | |
278 | 285 | | |
279 | 286 | | |
280 | 287 | | |
| |||
Lines changed: 6 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| 89 | + | |
| 90 | + | |
89 | 91 | | |
90 | 92 | | |
91 | 93 | | |
| |||
99 | 101 | | |
100 | 102 | | |
101 | 103 | | |
102 | | - | |
103 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
104 | 109 | | |
105 | 110 | | |
106 | 111 | | |
| |||
Lines changed: 0 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | 19 | | |
21 | 20 | | |
22 | 21 | | |
| |||
25 | 24 | | |
26 | 25 | | |
27 | 26 | | |
28 | | - | |
29 | 27 | | |
30 | 28 | | |
31 | 29 | | |
| |||
39 | 37 | | |
40 | 38 | | |
41 | 39 | | |
42 | | - | |
43 | 40 | | |
44 | 41 | | |
45 | 42 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
62 | 61 | | |
63 | 62 | | |
64 | 63 | | |
| |||
339 | 338 | | |
340 | 339 | | |
341 | 340 | | |
| 341 | + | |
342 | 342 | | |
343 | 343 | | |
344 | 344 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
| 182 | + | |
186 | 183 | | |
187 | 184 | | |
188 | 185 | | |
189 | 186 | | |
190 | 187 | | |
191 | 188 | | |
192 | 189 | | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
| 190 | + | |
197 | 191 | | |
198 | 192 | | |
199 | 193 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
0 commit comments