From c1d41e382e29be1dc8583e44d73844da6519b8df Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 14 Feb 2023 14:56:49 -0600 Subject: [PATCH 1/4] Add content insets parameter --- .../CodeEditTextView/CodeEditTextView.swift | 12 ++++++++-- .../STTextViewController.swift | 23 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Sources/CodeEditTextView/CodeEditTextView.swift b/Sources/CodeEditTextView/CodeEditTextView.swift index de434ed20..be81e3f4c 100644 --- a/Sources/CodeEditTextView/CodeEditTextView.swift +++ b/Sources/CodeEditTextView/CodeEditTextView.swift @@ -25,6 +25,9 @@ public struct CodeEditTextView: NSViewControllerRepresentable { /// - editorOverscroll: The percentage for overscroll, between 0-1 (default: `0.0`) /// - highlightProvider: A class you provide to perform syntax highlighting. Leave this as `nil` to use the /// built-in `TreeSitterClient` highlighter. + /// - contentInsets: Insets to use to offset the content in the enclosing scroll view. Leave as `nil` to let the + /// scroll view automatically adjust content insets. + /// **NOTE**: Left insets currently do not work and will be set to 0. This is a known bug. public init( _ text: Binding, language: CodeLanguage, @@ -36,7 +39,8 @@ public struct CodeEditTextView: NSViewControllerRepresentable { editorOverscroll: Binding = .constant(0.0), cursorPosition: Published<(Int, Int)>.Publisher? = nil, useThemeBackground: Bool = true, - highlightProvider: HighlightProviding? = nil + highlightProvider: HighlightProviding? = nil, + contentInsets: NSEdgeInsets? = nil ) { self._text = text self.language = language @@ -49,6 +53,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable { self._editorOverscroll = editorOverscroll self.cursorPosition = cursorPosition self.highlightProvider = highlightProvider + self.contentInsets = contentInsets } @Binding private var text: String @@ -62,6 +67,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable { private var cursorPosition: Published<(Int, Int)>.Publisher? private var useThemeBackground: Bool private var highlightProvider: HighlightProviding? + private var contentInsets: NSEdgeInsets? public typealias NSViewControllerType = STTextViewController @@ -76,7 +82,8 @@ public struct CodeEditTextView: NSViewControllerRepresentable { cursorPosition: cursorPosition, editorOverscroll: editorOverscroll, useThemeBackground: useThemeBackground, - highlightProvider: highlightProvider + highlightProvider: highlightProvider, + contentInsets: contentInsets ) controller.lineHeightMultiple = lineHeight return controller @@ -89,6 +96,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable { controller.useThemeBackground = useThemeBackground controller.lineHeightMultiple = lineHeight controller.editorOverscroll = editorOverscroll + controller.contentInsets = contentInsets // Updating the language and theme needlessly can cause highlights to be re-calculated. if controller.language.id != language.id { diff --git a/Sources/CodeEditTextView/STTextViewController.swift b/Sources/CodeEditTextView/STTextViewController.swift index 7e87347e9..9e24366ff 100644 --- a/Sources/CodeEditTextView/STTextViewController.swift +++ b/Sources/CodeEditTextView/STTextViewController.swift @@ -55,6 +55,9 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt /// Filters used when applying edits.. internal var textFilters: [TextFormation.Filter] = [] + /// Optional insets to offset the text view in the scroll view by. + public var contentInsets: NSEdgeInsets? + // MARK: - Highlighting internal var highlighter: Highlighter? @@ -77,7 +80,8 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt cursorPosition: Published<(Int, Int)>.Publisher? = nil, editorOverscroll: Double, useThemeBackground: Bool, - highlightProvider: HighlightProviding? = nil + highlightProvider: HighlightProviding? = nil, + contentInsets: NSEdgeInsets? ) { self.text = text self.language = language @@ -89,6 +93,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt self.editorOverscroll = editorOverscroll self.useThemeBackground = useThemeBackground self.highlightProvider = highlightProvider + self.contentInsets = contentInsets super.init(nibName: nil, bundle: nil) } @@ -98,6 +103,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt // MARK: VC Lifecycle + // swiftlint:disable function_body_length public override func loadView() { textView = STTextView() @@ -106,6 +112,10 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt scrollView.hasVerticalScroller = true scrollView.documentView = textView scrollView.drawsBackground = useThemeBackground + scrollView.automaticallyAdjustsContentInsets = contentInsets == nil + if let contentInsets = contentInsets { + scrollView.contentInsets = contentInsets + } rulerView = STLineNumberRulerView(textView: textView, scrollView: scrollView) rulerView.backgroundColor = useThemeBackground ? theme.background : .clear @@ -218,9 +228,14 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt rulerView?.separatorColor = theme.invisibles rulerView?.baselineOffset = baselineOffset - (view as? NSScrollView)?.drawsBackground = useThemeBackground - (view as? NSScrollView)?.backgroundColor = useThemeBackground ? theme.background : .clear - (view as? NSScrollView)?.contentView.contentInsets.bottom = bottomContentInsets + if let view = view as? NSScrollView { + view.drawsBackground = useThemeBackground + view.backgroundColor = useThemeBackground ? theme.background : .clear + if let contentInsets = contentInsets { + view.contentInsets = contentInsets + } + view.contentView.contentInsets.bottom = bottomContentInsets + (contentInsets?.bottom ?? 0) + } setStandardAttributes() } From 71af944e043255c9afb55462b82b0f5e1a5a0656 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 14 Feb 2023 15:09:24 -0600 Subject: [PATCH 2/4] Update STTextView & remove warning --- Package.swift | 2 +- Sources/CodeEditTextView/CodeEditTextView.swift | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 5c1ae4da6..5b7c530ae 100644 --- a/Package.swift +++ b/Package.swift @@ -15,7 +15,7 @@ let package = Package( dependencies: [ .package( url: "https://github.com/krzyzanowskim/STTextView.git", - exact: "0.4.0" + from: "0.4.1" ), .package( url: "https://github.com/CodeEditApp/CodeEditLanguages.git", diff --git a/Sources/CodeEditTextView/CodeEditTextView.swift b/Sources/CodeEditTextView/CodeEditTextView.swift index be81e3f4c..2ff103072 100644 --- a/Sources/CodeEditTextView/CodeEditTextView.swift +++ b/Sources/CodeEditTextView/CodeEditTextView.swift @@ -27,7 +27,6 @@ public struct CodeEditTextView: NSViewControllerRepresentable { /// built-in `TreeSitterClient` highlighter. /// - contentInsets: Insets to use to offset the content in the enclosing scroll view. Leave as `nil` to let the /// scroll view automatically adjust content insets. - /// **NOTE**: Left insets currently do not work and will be set to 0. This is a known bug. public init( _ text: Binding, language: CodeLanguage, From dc9e70532944446e9a5b415528dcd7dc40ae544a Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 14 Feb 2023 15:18:27 -0600 Subject: [PATCH 3/4] Fix failing test case --- Sources/CodeEditTextView/STTextViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CodeEditTextView/STTextViewController.swift b/Sources/CodeEditTextView/STTextViewController.swift index 9e24366ff..2632fd401 100644 --- a/Sources/CodeEditTextView/STTextViewController.swift +++ b/Sources/CodeEditTextView/STTextViewController.swift @@ -81,7 +81,7 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt editorOverscroll: Double, useThemeBackground: Bool, highlightProvider: HighlightProviding? = nil, - contentInsets: NSEdgeInsets? + contentInsets: NSEdgeInsets? = nil ) { self.text = text self.language = language From dbc93c38d48e48eeee8271fc04554f1bd5a3e038 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 14 Feb 2023 19:59:33 -0600 Subject: [PATCH 4/4] Added tests, fixed names --- .../STTextViewController.swift | 10 ++-- .../STTextViewControllerTests.swift | 46 +++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/Sources/CodeEditTextView/STTextViewController.swift b/Sources/CodeEditTextView/STTextViewController.swift index 2632fd401..92a149952 100644 --- a/Sources/CodeEditTextView/STTextViewController.swift +++ b/Sources/CodeEditTextView/STTextViewController.swift @@ -228,13 +228,13 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt rulerView?.separatorColor = theme.invisibles rulerView?.baselineOffset = baselineOffset - if let view = view as? NSScrollView { - view.drawsBackground = useThemeBackground - view.backgroundColor = useThemeBackground ? theme.background : .clear + if let scrollView = view as? NSScrollView { + scrollView.drawsBackground = useThemeBackground + scrollView.backgroundColor = useThemeBackground ? theme.background : .clear if let contentInsets = contentInsets { - view.contentInsets = contentInsets + scrollView.contentInsets = contentInsets } - view.contentView.contentInsets.bottom = bottomContentInsets + (contentInsets?.bottom ?? 0) + scrollView.contentInsets.bottom = bottomContentInsets + (contentInsets?.bottom ?? 0) } setStandardAttributes() diff --git a/Tests/CodeEditTextViewTests/STTextViewControllerTests.swift b/Tests/CodeEditTextViewTests/STTextViewControllerTests.swift index b866d270c..b170b46f1 100644 --- a/Tests/CodeEditTextViewTests/STTextViewControllerTests.swift +++ b/Tests/CodeEditTextViewTests/STTextViewControllerTests.swift @@ -70,6 +70,10 @@ final class STTextViewControllerTests: XCTestCase { width: 100, height: 100) + controller.editorOverscroll = 0 + controller.contentInsets = nil + controller.reloadUI() + // editorOverscroll: 0 XCTAssertEqual(scrollView.contentView.contentInsets.bottom, 0) @@ -86,6 +90,48 @@ final class STTextViewControllerTests: XCTestCase { XCTAssertEqual(scrollView.contentView.contentInsets.bottom, 87.0) } + func test_editorInsets() throws { + let scrollView = try XCTUnwrap(controller.view as? NSScrollView) + scrollView.frame = .init(x: .zero, + y: .zero, + width: 100, + height: 100) + + func assertInsetsEqual(_ lhs: NSEdgeInsets, _ rhs: NSEdgeInsets) throws { + XCTAssertEqual(lhs.top, rhs.top) + XCTAssertEqual(lhs.right, rhs.right) + XCTAssertEqual(lhs.bottom, rhs.bottom) + XCTAssertEqual(lhs.left, rhs.left) + } + + controller.editorOverscroll = 0 + controller.contentInsets = nil + controller.reloadUI() + + // contentInsets: 0 + try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)) + + // contentInsets: 16 + controller.contentInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) + controller.reloadUI() + + try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)) + + // contentInsets: different + controller.contentInsets = NSEdgeInsets(top: 32.5, left: 12.3, bottom: 20, right: 1) + controller.reloadUI() + + try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 32.5, left: 12.3, bottom: 20, right: 1)) + + // contentInsets: 16 + // editorOverscroll: 0.5 + controller.contentInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) + controller.editorOverscroll = 0.5 + controller.reloadUI() + + try assertInsetsEqual(scrollView.contentInsets, NSEdgeInsets(top: 16, left: 16, bottom: 16 + 50, right: 16)) + } + func test_editorOverScroll_ZeroCondition() throws { let scrollView = try XCTUnwrap(controller.view as? NSScrollView) scrollView.frame = .zero