diff --git a/Sources/CodeEditSourceEditor/Controller/TextViewController+Highlighter.swift b/Sources/CodeEditSourceEditor/Controller/TextViewController+Highlighter.swift index ff8855f8b..db9beaec9 100644 --- a/Sources/CodeEditSourceEditor/Controller/TextViewController+Highlighter.swift +++ b/Sources/CodeEditSourceEditor/Controller/TextViewController+Highlighter.swift @@ -17,6 +17,7 @@ extension TextViewController { let highlighter = Highlighter( textView: textView, + minimapView: minimapView, providers: highlightProviders, attributeProvider: self, language: language diff --git a/Sources/CodeEditSourceEditor/Highlighting/Highlighter.swift b/Sources/CodeEditSourceEditor/Highlighting/Highlighter.swift index ff5c61224..884415bf0 100644 --- a/Sources/CodeEditSourceEditor/Highlighting/Highlighter.swift +++ b/Sources/CodeEditSourceEditor/Highlighting/Highlighter.swift @@ -85,6 +85,7 @@ class Highlighter: NSObject { init( textView: TextView, + minimapView: MinimapView?, providers: [HighlightProviding], attributeProvider: ThemeAttributesProviding, language: CodeLanguage @@ -93,7 +94,7 @@ class Highlighter: NSObject { self.textView = textView self.attributeProvider = attributeProvider - self.visibleRangeProvider = VisibleRangeProvider(textView: textView) + self.visibleRangeProvider = VisibleRangeProvider(textView: textView, minimapView: minimapView) let providerIds = providers.indices.map({ $0 }) self.styleContainer = StyledRangeContainer(documentLength: textView.length, providers: providerIds) @@ -244,7 +245,7 @@ extension Highlighter: NSTextStorageDelegate { visibleRangeProvider.visibleSet.insert(range: editedRange) } - visibleRangeProvider.updateVisibleSet(textView: textView) + visibleRangeProvider.visibleTextChanged() let providerRange = NSRange(location: editedRange.location, length: editedRange.length - delta) highlightProviders.forEach { $0.storageDidUpdate(range: providerRange, delta: delta) } diff --git a/Sources/CodeEditSourceEditor/Highlighting/VisibleRangeProvider.swift b/Sources/CodeEditSourceEditor/Highlighting/VisibleRangeProvider.swift index cc7938215..bf98a83f5 100644 --- a/Sources/CodeEditSourceEditor/Highlighting/VisibleRangeProvider.swift +++ b/Sources/CodeEditSourceEditor/Highlighting/VisibleRangeProvider.swift @@ -18,6 +18,7 @@ protocol VisibleRangeProviderDelegate: AnyObject { @MainActor class VisibleRangeProvider { private weak var textView: TextView? + private weak var minimapView: MinimapView? weak var delegate: VisibleRangeProviderDelegate? var documentRange: NSRange { @@ -29,56 +30,44 @@ class VisibleRangeProvider { return IndexSet(integersIn: textView?.visibleTextRange ?? NSRange()) }() - init(textView: TextView) { + init(textView: TextView, minimapView: MinimapView?) { self.textView = textView + self.minimapView = minimapView if let scrollView = textView.enclosingScrollView { NotificationCenter.default.addObserver( self, - selector: #selector(visibleTextChanged(_:)), + selector: #selector(visibleTextChanged), name: NSView.frameDidChangeNotification, object: scrollView ) NotificationCenter.default.addObserver( self, - selector: #selector(visibleTextChanged(_:)), + selector: #selector(visibleTextChanged), name: NSView.boundsDidChangeNotification, object: scrollView.contentView ) - } else { - NotificationCenter.default.addObserver( - self, - selector: #selector(visibleTextChanged(_:)), - name: NSView.frameDidChangeNotification, - object: textView - ) } - } - func updateVisibleSet(textView: TextView) { - if let newVisibleRange = textView.visibleTextRange { - visibleSet = IndexSet(integersIn: newVisibleRange) - } + NotificationCenter.default.addObserver( + self, + selector: #selector(visibleTextChanged), + name: NSView.frameDidChangeNotification, + object: textView + ) } /// Updates the view to highlight newly visible text when the textview is scrolled or bounds change. - @objc func visibleTextChanged(_ notification: Notification) { - let textView: TextView - if let clipView = notification.object as? NSClipView, - let documentView = clipView.enclosingScrollView?.documentView as? TextView { - textView = documentView - } else if let scrollView = notification.object as? NSScrollView, - let documentView = scrollView.documentView as? TextView { - textView = documentView - } else if let documentView = notification.object as? TextView { - textView = documentView - } else { + @objc func visibleTextChanged() { + guard let textViewVisibleRange = textView?.visibleTextRange else { return } - - updateVisibleSet(textView: textView) - + var visibleSet = IndexSet(integersIn: textViewVisibleRange) + if !(minimapView?.isHidden ?? true), let minimapVisibleRange = minimapView?.visibleTextRange { + visibleSet.formUnion(IndexSet(integersIn: minimapVisibleRange)) + } + self.visibleSet = visibleSet delegate?.visibleSetDidUpdate(visibleSet) } diff --git a/Tests/CodeEditSourceEditorTests/Highlighting/HighlightProviderStateTest.swift b/Tests/CodeEditSourceEditorTests/Highlighting/HighlightProviderStateTest.swift index e730e16de..61334cd14 100644 --- a/Tests/CodeEditSourceEditorTests/Highlighting/HighlightProviderStateTest.swift +++ b/Tests/CodeEditSourceEditorTests/Highlighting/HighlightProviderStateTest.swift @@ -30,7 +30,7 @@ final class HighlightProviderStateTest: XCTestCase { override func setUp() async throws { try await super.setUp() textView = Mock.textView() - rangeProvider = MockVisibleRangeProvider(textView: textView) + rangeProvider = MockVisibleRangeProvider(textView: textView, minimapView: nil) delegate = EmptyHighlightProviderStateDelegate() } diff --git a/Tests/CodeEditSourceEditorTests/Highlighting/VisibleRangeProviderTests.swift b/Tests/CodeEditSourceEditorTests/Highlighting/VisibleRangeProviderTests.swift index e75098d85..1fa5df4f8 100644 --- a/Tests/CodeEditSourceEditorTests/Highlighting/VisibleRangeProviderTests.swift +++ b/Tests/CodeEditSourceEditorTests/Highlighting/VisibleRangeProviderTests.swift @@ -8,7 +8,7 @@ final class VisibleRangeProviderTests: XCTestCase { textView.string = Array(repeating: "\n", count: 400).joined() textView.layout() - let rangeProvider = VisibleRangeProvider(textView: textView) + let rangeProvider = VisibleRangeProvider(textView: textView, minimapView: nil) let originalSet = rangeProvider.visibleSet scrollView.contentView.scroll(to: NSPoint(x: 0, y: 250)) @@ -25,7 +25,7 @@ final class VisibleRangeProviderTests: XCTestCase { textView.string = Array(repeating: "\n", count: 400).joined() textView.layout() - let rangeProvider = VisibleRangeProvider(textView: textView) + let rangeProvider = VisibleRangeProvider(textView: textView, minimapView: nil) let originalSet = rangeProvider.visibleSet scrollView.setFrameSize(NSSize(width: 250, height: 450)) @@ -46,7 +46,7 @@ final class VisibleRangeProviderTests: XCTestCase { textView.string = Array(repeating: "\n", count: 400).joined() textView.layout() - let rangeProvider = VisibleRangeProvider(textView: textView) + let rangeProvider = VisibleRangeProvider(textView: textView, minimapView: nil) let originalSet = rangeProvider.visibleSet textView.setFrameSize(NSSize(width: 350, height: 450)) diff --git a/Tests/CodeEditSourceEditorTests/Mock.swift b/Tests/CodeEditSourceEditorTests/Mock.swift index 5e1140286..1eb96c0c4 100644 --- a/Tests/CodeEditSourceEditorTests/Mock.swift +++ b/Tests/CodeEditSourceEditorTests/Mock.swift @@ -129,6 +129,7 @@ enum Mock { ) -> Highlighter { Highlighter( textView: textView, + minimapView: nil, providers: highlightProviders, attributeProvider: attributeProvider, language: language