Skip to content

Commit d83b449

Browse files
Add contentInsets Parameter (CodeEditApp#141)
# Description This PR adds a `contentInsets` parameter that lets users set an inset object for the editor. It also updates `STTextView` to be able to set the left inset correctly. When left `nil` the scroll view will use automatic insets. This also doesn't override the overscroll option, but rather adds the overscroll after the insets are applied. # Related Issues - [Discord discussion](https://canary.discord.com/channels/951544472238444645/954084547694325861/1075085722211581952) - [STTextView commit](krzyzanowskim/STTextView@06d8f33) # Screenshots Adding top and left insets: <img width="741" alt="Screenshot 2023-02-14 at 3 09 57 PM" src="https://user-images.githubusercontent.com/35942988/218863914-8869e185-cd21-45a7-a7aa-58387ea778ea.png"> Adding left and bottom insets (scroller is also inset): <img width="835" alt="Screenshot 2023-02-14 at 3 10 15 PM" src="https://user-images.githubusercontent.com/35942988/218863899-99d2b124-fc96-418a-9869-d6897a7baea4.png">
1 parent 14f82ff commit d83b449

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let package = Package(
1515
dependencies: [
1616
.package(
1717
url: "https://github.com/krzyzanowskim/STTextView.git",
18-
exact: "0.4.0"
18+
from: "0.4.1"
1919
),
2020
.package(
2121
url: "https://github.com/CodeEditApp/CodeEditLanguages.git",

Sources/CodeEditTextView/CodeEditTextView.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
2525
/// - editorOverscroll: The percentage for overscroll, between 0-1 (default: `0.0`)
2626
/// - highlightProvider: A class you provide to perform syntax highlighting. Leave this as `nil` to use the
2727
/// built-in `TreeSitterClient` highlighter.
28+
/// - contentInsets: Insets to use to offset the content in the enclosing scroll view. Leave as `nil` to let the
29+
/// scroll view automatically adjust content insets.
2830
public init(
2931
_ text: Binding<String>,
3032
language: CodeLanguage,
@@ -36,7 +38,8 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
3638
editorOverscroll: Binding<Double> = .constant(0.0),
3739
cursorPosition: Published<(Int, Int)>.Publisher? = nil,
3840
useThemeBackground: Bool = true,
39-
highlightProvider: HighlightProviding? = nil
41+
highlightProvider: HighlightProviding? = nil,
42+
contentInsets: NSEdgeInsets? = nil
4043
) {
4144
self._text = text
4245
self.language = language
@@ -49,6 +52,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
4952
self._editorOverscroll = editorOverscroll
5053
self.cursorPosition = cursorPosition
5154
self.highlightProvider = highlightProvider
55+
self.contentInsets = contentInsets
5256
}
5357

5458
@Binding private var text: String
@@ -62,6 +66,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
6266
private var cursorPosition: Published<(Int, Int)>.Publisher?
6367
private var useThemeBackground: Bool
6468
private var highlightProvider: HighlightProviding?
69+
private var contentInsets: NSEdgeInsets?
6570

6671
public typealias NSViewControllerType = STTextViewController
6772

@@ -76,7 +81,8 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
7681
cursorPosition: cursorPosition,
7782
editorOverscroll: editorOverscroll,
7883
useThemeBackground: useThemeBackground,
79-
highlightProvider: highlightProvider
84+
highlightProvider: highlightProvider,
85+
contentInsets: contentInsets
8086
)
8187
controller.lineHeightMultiple = lineHeight
8288
return controller
@@ -89,6 +95,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
8995
controller.useThemeBackground = useThemeBackground
9096
controller.lineHeightMultiple = lineHeight
9197
controller.editorOverscroll = editorOverscroll
98+
controller.contentInsets = contentInsets
9299

93100
// Updating the language and theme needlessly can cause highlights to be re-calculated.
94101
if controller.language.id != language.id {

Sources/CodeEditTextView/STTextViewController.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
5555
/// Filters used when applying edits..
5656
internal var textFilters: [TextFormation.Filter] = []
5757

58+
/// Optional insets to offset the text view in the scroll view by.
59+
public var contentInsets: NSEdgeInsets?
60+
5861
// MARK: - Highlighting
5962

6063
internal var highlighter: Highlighter?
@@ -77,7 +80,8 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
7780
cursorPosition: Published<(Int, Int)>.Publisher? = nil,
7881
editorOverscroll: Double,
7982
useThemeBackground: Bool,
80-
highlightProvider: HighlightProviding? = nil
83+
highlightProvider: HighlightProviding? = nil,
84+
contentInsets: NSEdgeInsets? = nil
8185
) {
8286
self.text = text
8387
self.language = language
@@ -89,6 +93,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
8993
self.editorOverscroll = editorOverscroll
9094
self.useThemeBackground = useThemeBackground
9195
self.highlightProvider = highlightProvider
96+
self.contentInsets = contentInsets
9297
super.init(nibName: nil, bundle: nil)
9398
}
9499

@@ -98,6 +103,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
98103

99104
// MARK: VC Lifecycle
100105

106+
// swiftlint:disable function_body_length
101107
public override func loadView() {
102108
textView = STTextView()
103109

@@ -106,6 +112,10 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
106112
scrollView.hasVerticalScroller = true
107113
scrollView.documentView = textView
108114
scrollView.drawsBackground = useThemeBackground
115+
scrollView.automaticallyAdjustsContentInsets = contentInsets == nil
116+
if let contentInsets = contentInsets {
117+
scrollView.contentInsets = contentInsets
118+
}
109119

110120
rulerView = STLineNumberRulerView(textView: textView, scrollView: scrollView)
111121
rulerView.backgroundColor = useThemeBackground ? theme.background : .clear
@@ -218,9 +228,14 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
218228
rulerView?.separatorColor = theme.invisibles
219229
rulerView?.baselineOffset = baselineOffset
220230

221-
(view as? NSScrollView)?.drawsBackground = useThemeBackground
222-
(view as? NSScrollView)?.backgroundColor = useThemeBackground ? theme.background : .clear
223-
(view as? NSScrollView)?.contentView.contentInsets.bottom = bottomContentInsets
231+
if let scrollView = view as? NSScrollView {
232+
scrollView.drawsBackground = useThemeBackground
233+
scrollView.backgroundColor = useThemeBackground ? theme.background : .clear
234+
if let contentInsets = contentInsets {
235+
scrollView.contentInsets = contentInsets
236+
}
237+
scrollView.contentInsets.bottom = bottomContentInsets + (contentInsets?.bottom ?? 0)
238+
}
224239

225240
setStandardAttributes()
226241
}

Tests/CodeEditTextViewTests/STTextViewControllerTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ final class STTextViewControllerTests: XCTestCase {
7070
width: 100,
7171
height: 100)
7272

73+
controller.editorOverscroll = 0
74+
controller.contentInsets = nil
75+
controller.reloadUI()
76+
7377
// editorOverscroll: 0
7478
XCTAssertEqual(scrollView.contentView.contentInsets.bottom, 0)
7579

@@ -86,6 +90,48 @@ final class STTextViewControllerTests: XCTestCase {
8690
XCTAssertEqual(scrollView.contentView.contentInsets.bottom, 87.0)
8791
}
8892

93+
func test_editorInsets() throws {
94+
let scrollView = try XCTUnwrap(controller.view as? NSScrollView)
95+
scrollView.frame = .init(x: .zero,
96+
y: .zero,
97+
width: 100,
98+
height: 100)
99+
100+
func assertInsetsEqual(_ lhs: NSEdgeInsets, _ rhs: NSEdgeInsets) throws {
101+
XCTAssertEqual(lhs.top, rhs.top)
102+
XCTAssertEqual(lhs.right, rhs.right)
103+
XCTAssertEqual(lhs.bottom, rhs.bottom)
104+
XCTAssertEqual(lhs.left, rhs.left)
105+
}
106+
107+
controller.editorOverscroll = 0
108+
controller.contentInsets = nil
109+
controller.reloadUI()
110+
111+
// contentInsets: 0
112+
try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0))
113+
114+
// contentInsets: 16
115+
controller.contentInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
116+
controller.reloadUI()
117+
118+
try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16))
119+
120+
// contentInsets: different
121+
controller.contentInsets = NSEdgeInsets(top: 32.5, left: 12.3, bottom: 20, right: 1)
122+
controller.reloadUI()
123+
124+
try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 32.5, left: 12.3, bottom: 20, right: 1))
125+
126+
// contentInsets: 16
127+
// editorOverscroll: 0.5
128+
controller.contentInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
129+
controller.editorOverscroll = 0.5
130+
controller.reloadUI()
131+
132+
try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 16, left: 16, bottom: 16 + 50, right: 16))
133+
}
134+
89135
func test_editorOverScroll_ZeroCondition() throws {
90136
let scrollView = try XCTUnwrap(controller.view as? NSScrollView)
91137
scrollView.frame = .zero

0 commit comments

Comments
 (0)