Move Layout Updates to NSTextStorage Delegate #82
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Detailed Changes
TextLayoutManager
a text storage delegate.TextLayoutManager
to use the text storage methods to update internal state.TextLayoutManager
's layout transaction capabilities.replaceCharacters
to reflect the new layout manager requirements.CATransaction
, now that method ordering is slightly different, macOS might calllayout
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
rects(in:)
to ensure it doesn't invalidate layout information.Discussion
This change untangles the text layout updating from text view code. Right now the hierarchy looks like this:
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:
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
Checklist
Screenshots