From 36066ac5d9b35e0c60697ebf856b242e43395760 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 22 Dec 2023 15:50:28 -0600 Subject: [PATCH 1/3] Fix First Responder Issues, Custom Undo Manager --- .../TextView/TextView+Mouse.swift | 4 --- .../TextView/TextView+UndoRedo.swift | 1 + .../CodeEditTextView/TextView/TextView.swift | 36 +++++++++++++++++++ .../Utils/CEUndoManager.swift | 8 +++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/Sources/CodeEditTextView/TextView/TextView+Mouse.swift b/Sources/CodeEditTextView/TextView/TextView+Mouse.swift index 3f04ee58..789867f4 100644 --- a/Sources/CodeEditTextView/TextView/TextView+Mouse.swift +++ b/Sources/CodeEditTextView/TextView/TextView+Mouse.swift @@ -48,10 +48,6 @@ extension TextView { self?.autoscroll(with: event) } } - - if !self.isFirstResponder { - self.window?.makeFirstResponder(self) - } } override public func mouseUp(with event: NSEvent) { diff --git a/Sources/CodeEditTextView/TextView/TextView+UndoRedo.swift b/Sources/CodeEditTextView/TextView/TextView+UndoRedo.swift index 2dbc40ee..a12f1d83 100644 --- a/Sources/CodeEditTextView/TextView/TextView+UndoRedo.swift +++ b/Sources/CodeEditTextView/TextView/TextView+UndoRedo.swift @@ -10,6 +10,7 @@ import AppKit extension TextView { public func setUndoManager(_ newManager: CEUndoManager) { self._undoManager = newManager + self._undoManager?.setTextView(self) } override public var undoManager: UndoManager? { diff --git a/Sources/CodeEditTextView/TextView/TextView.swift b/Sources/CodeEditTextView/TextView/TextView.swift index 0a9383a5..07ad9d25 100644 --- a/Sources/CodeEditTextView/TextView/TextView.swift +++ b/Sources/CodeEditTextView/TextView/TextView.swift @@ -326,6 +326,16 @@ public class TextView: NSView, NSTextContent { super.canBecomeKeyView && acceptsFirstResponder && !isHiddenOrHasHiddenAncestor } + /// Sent to the window's first responder when `NSWindow.makeKey()` occurs. + @objc private func becomeKeyWindow() { + let _ = becomeFirstResponder() + } + + /// Sent to the window's first responder when `NSWindow.resignKey()` occurs. + @objc private func resignKeyWindow() { + let _ = resignFirstResponder() + } + open override var needsPanelToBecomeKey: Bool { isSelectable || isEditable } @@ -362,6 +372,23 @@ public class TextView: NSView, NSTextContent { updateFrameIfNeeded() } + // MARK: - Hit test + + /// Returns the responding view for a given point. + /// - Parameter point: The point to find. + /// - Returns: A view at the given point, if any. + override public func hitTest(_ point: NSPoint) -> NSView? { + // For our purposes, cursor and line fragment views should be transparent from the point of view of + // all other views. So, if the normal hitTest returns one of them, we return `self` instead. + let hitView = super.hitTest(point) + + if let hitView, hitView != self, + (type(of: hitView) == CursorView.self || type(of: hitView) == LineFragmentView.self) { + return self + } + return hitView + } + // MARK: - Key Down override public func keyDown(with event: NSEvent) { @@ -381,6 +408,15 @@ public class TextView: NSView, NSTextContent { // MARK: - Layout + open override class var isCompatibleWithResponsiveScrolling: Bool { + true + } + + open override func prepareContent(in rect: NSRect) { + needsLayout = true + super.prepareContent(in: rect) + } + override public func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) if isSelectable { diff --git a/Sources/CodeEditTextView/Utils/CEUndoManager.swift b/Sources/CodeEditTextView/Utils/CEUndoManager.swift index b65e033c..533a5381 100644 --- a/Sources/CodeEditTextView/Utils/CEUndoManager.swift +++ b/Sources/CodeEditTextView/Utils/CEUndoManager.swift @@ -224,4 +224,12 @@ public class CEUndoManager { public func enable() { isDisabled = false } + + // MARK: - Internal + + /// Sets a new text view to use for mutation registration, undo/redo operations. + /// - Parameter newTextView: The new text view. + func setTextView(_ newTextView: TextView) { + self.textView = newTextView + } } From 16138a5bd1387dd617a3b7763652743e354282ab Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 22 Dec 2023 18:43:44 -0600 Subject: [PATCH 2/3] SwiftLint Errors --- Sources/CodeEditTextView/TextView/TextView.swift | 8 ++++---- Sources/CodeEditTextView/Utils/CEUndoManager.swift | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/CodeEditTextView/TextView/TextView.swift b/Sources/CodeEditTextView/TextView/TextView.swift index 07ad9d25..33173413 100644 --- a/Sources/CodeEditTextView/TextView/TextView.swift +++ b/Sources/CodeEditTextView/TextView/TextView.swift @@ -328,12 +328,12 @@ public class TextView: NSView, NSTextContent { /// Sent to the window's first responder when `NSWindow.makeKey()` occurs. @objc private func becomeKeyWindow() { - let _ = becomeFirstResponder() + _ = becomeFirstResponder() } - + /// Sent to the window's first responder when `NSWindow.resignKey()` occurs. @objc private func resignKeyWindow() { - let _ = resignFirstResponder() + _ = resignFirstResponder() } open override var needsPanelToBecomeKey: Bool { @@ -373,7 +373,7 @@ public class TextView: NSView, NSTextContent { } // MARK: - Hit test - + /// Returns the responding view for a given point. /// - Parameter point: The point to find. /// - Returns: A view at the given point, if any. diff --git a/Sources/CodeEditTextView/Utils/CEUndoManager.swift b/Sources/CodeEditTextView/Utils/CEUndoManager.swift index 533a5381..4fac1720 100644 --- a/Sources/CodeEditTextView/Utils/CEUndoManager.swift +++ b/Sources/CodeEditTextView/Utils/CEUndoManager.swift @@ -226,7 +226,7 @@ public class CEUndoManager { } // MARK: - Internal - + /// Sets a new text view to use for mutation registration, undo/redo operations. /// - Parameter newTextView: The new text view. func setTextView(_ newTextView: TextView) { From 7eb429f57b03d4fcbd81b069325ad58038151134 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 22 Dec 2023 18:49:03 -0600 Subject: [PATCH 3/3] Odd SwiftLint Fix --- Sources/CodeEditTextView/TextView/TextView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CodeEditTextView/TextView/TextView.swift b/Sources/CodeEditTextView/TextView/TextView.swift index 33173413..7094a1c9 100644 --- a/Sources/CodeEditTextView/TextView/TextView.swift +++ b/Sources/CodeEditTextView/TextView/TextView.swift @@ -383,7 +383,7 @@ public class TextView: NSView, NSTextContent { let hitView = super.hitTest(point) if let hitView, hitView != self, - (type(of: hitView) == CursorView.self || type(of: hitView) == LineFragmentView.self) { + type(of: hitView) == CursorView.self || type(of: hitView) == LineFragmentView.self { return self } return hitView