Skip to content

Commit 84505b4

Browse files
Update Text Container Width Correctly (#177)
1 parent 77e51db commit 84505b4

File tree

4 files changed

+101
-36
lines changed

4 files changed

+101
-36
lines changed

Sources/CodeEditTextView/CEScrollView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import STTextView
1010

1111
class CEScrollView: NSScrollView {
1212

13+
override open var contentSize: NSSize {
14+
var proposedSize = super.contentSize
15+
proposedSize.width -= verticalRulerView?.requiredThickness ?? 0.0
16+
return proposedSize
17+
}
18+
1319
override func mouseDown(with event: NSEvent) {
1420

1521
if let textView = self.documentView as? STTextView,
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// STTextViewController+Highlighter.swift
3+
//
4+
//
5+
// Created by Khan Winter on 4/21/23.
6+
//
7+
8+
import AppKit
9+
import SwiftTreeSitter
10+
11+
extension STTextViewController {
12+
/// Configures the `Highlighter` object
13+
internal func setUpHighlighter() {
14+
self.highlighter = Highlighter(
15+
textView: textView,
16+
highlightProvider: highlightProvider,
17+
theme: theme,
18+
attributeProvider: self,
19+
language: language
20+
)
21+
}
22+
23+
/// Sets the highlight provider and re-highlights all text. This method should be used sparingly.
24+
internal func setHighlightProvider(_ highlightProvider: HighlightProviding? = nil) {
25+
var provider: HighlightProviding?
26+
27+
if let highlightProvider = highlightProvider {
28+
provider = highlightProvider
29+
} else {
30+
let textProvider: ResolvingQueryCursor.TextProvider = { [weak self] range, _ -> String? in
31+
return self?.textView.textContentStorage.textStorage?.mutableString.substring(with: range)
32+
}
33+
34+
provider = TreeSitterClient(codeLanguage: language, textProvider: textProvider)
35+
}
36+
37+
if let provider = provider {
38+
self.highlightProvider = provider
39+
highlighter?.setHighlightProvider(provider)
40+
}
41+
}
42+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// STTextViewController+TextContainer.swift
3+
//
4+
//
5+
// Created by Khan Winter on 4/21/23.
6+
//
7+
8+
import AppKit
9+
import STTextView
10+
11+
extension STTextViewController {
12+
/// Update the text view's text container if needed.
13+
///
14+
/// Effectively updates the container to reflect the `wrapLines` setting, and to reflect any updates to the ruler,
15+
/// scroll view, or window frames.
16+
internal func updateTextContainerWidthIfNeeded() {
17+
let previousTrackingSetting = textView.widthTracksTextView
18+
textView.widthTracksTextView = wrapLines
19+
if wrapLines {
20+
var proposedSize = ((view as? NSScrollView)?.contentSize ?? .zero)
21+
proposedSize.height = .greatestFiniteMagnitude
22+
23+
if textView.textContainer.size != proposedSize || textView.frame.size != proposedSize {
24+
textView.textContainer.size = proposedSize
25+
textView.setFrameSize(proposedSize)
26+
}
27+
} else {
28+
var proposedSize = textView.frame.size
29+
proposedSize.width = ((view as? NSScrollView)?.contentSize ?? .zero).width
30+
if previousTrackingSetting != wrapLines {
31+
textView.textContainer.size = CGSize(
32+
width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude
33+
)
34+
textView.setFrameSize(proposedSize)
35+
textView.textLayoutManager.textViewportLayoutController.layoutViewport()
36+
}
37+
}
38+
}
39+
}

Sources/CodeEditTextView/Controller/STTextViewController.swift

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import AppKit
99
import SwiftUI
1010
import Combine
1111
import STTextView
12-
import SwiftTreeSitter
1312
import CodeEditLanguages
1413
import TextFormation
1514

@@ -97,7 +96,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
9796
internal var highlighter: Highlighter?
9897

9998
/// The provided highlight provider.
100-
private var highlightProvider: HighlightProviding?
99+
internal var highlightProvider: HighlightProviding?
101100

102101
// MARK: Init
103102

@@ -183,7 +182,6 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
183182
textView.selectedLineHighlightColor = theme.lineHighlight
184183
textView.string = self.text.wrappedValue
185184
textView.isEditable = self.isEditable
186-
textView.widthTracksTextView = self.wrapLines
187185
textView.highlightSelectedLine = true
188186
textView.allowsUndo = true
189187
textView.setupMenus()
@@ -223,6 +221,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
223221
queue: .main) { [weak self] _ in
224222
guard let self = self else { return }
225223
(self.view as? NSScrollView)?.contentView.contentInsets.bottom = self.bottomContentInsets
224+
self.updateTextContainerWidthIfNeeded()
226225
}
227226

228227
NotificationCenter.default.addObserver(
@@ -232,10 +231,19 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
232231
) { [weak self] _ in
233232
self?.updateCursorPosition()
234233
}
234+
235+
NotificationCenter.default.addObserver(
236+
forName: NSView.frameDidChangeNotification,
237+
object: (self.view as? NSScrollView)?.verticalRulerView,
238+
queue: .main
239+
) { [weak self] _ in
240+
self?.updateTextContainerWidthIfNeeded()
241+
}
235242
}
236243

237-
public override func viewDidAppear() {
238-
super.viewDidAppear()
244+
public override func viewWillAppear() {
245+
super.viewWillAppear()
246+
updateTextContainerWidthIfNeeded()
239247
}
240248

241249
public func textViewDidChangeText(_ notification: Notification) {
@@ -299,6 +307,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
299307
}
300308

301309
highlighter?.invalidate()
310+
updateTextContainerWidthIfNeeded()
302311
}
303312

304313
/// Gets all attributes for the given capture including the line height, background color, and text color.
@@ -324,37 +333,6 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
324333
((self.lineHeight) - font.lineHeight) / 2
325334
}
326335

327-
// MARK: - Highlighting
328-
329-
/// Configures the `Highlighter` object
330-
private func setUpHighlighter() {
331-
self.highlighter = Highlighter(textView: textView,
332-
highlightProvider: highlightProvider,
333-
theme: theme,
334-
attributeProvider: self,
335-
language: language)
336-
}
337-
338-
/// Sets the highlight provider and re-highlights all text. This method should be used sparingly.
339-
public func setHighlightProvider(_ highlightProvider: HighlightProviding? = nil) {
340-
var provider: HighlightProviding?
341-
342-
if let highlightProvider = highlightProvider {
343-
provider = highlightProvider
344-
} else {
345-
let textProvider: ResolvingQueryCursor.TextProvider = { [weak self] range, _ -> String? in
346-
return self?.textView.textContentStorage.textStorage?.mutableString.substring(with: range)
347-
}
348-
349-
provider = TreeSitterClient(codeLanguage: language, textProvider: textProvider)
350-
}
351-
352-
if let provider = provider {
353-
self.highlightProvider = provider
354-
highlighter?.setHighlightProvider(provider)
355-
}
356-
}
357-
358336
// MARK: Selectors
359337

360338
override public func keyDown(with event: NSEvent) {

0 commit comments

Comments
 (0)