Changing NSCursor for NSView above an NSTextView

后端 未结 3 737
借酒劲吻你
借酒劲吻你 2020-12-10 07:33

Found a similar question to mine(this), but my issues seems to be a bit more associated with view hierarchy.

I have a NSTextView, then as sibling views, several othe

3条回答
  •  爱一瞬间的悲伤
    2020-12-10 08:15

    A few important notes:

    • Be careful calling super on your mouseMoved or similar events, or the cursor might just get reset by the base class implementation.
    • Only reset your tracking area when the parent view size changes; if you try to do this by overriding layout() it's going to be happening all the time which is not great

    Here's an example class that you can just use as a base class in your storyboards.

    Swift 4 code:

    import Cocoa
    
    final class MouseTrackingTextView: NSTextView {
    
        // MARK: - Lifecycle
    
        override func awakeFromNib() {
            setupTrackingArea()
        }
    
        // MARK: - Resizing
    
        // Call this in your controller's `viewDidLayout`
        // so it only gets called when the view resizes
        func superviewResized() {
            resetTrackingArea()
        }
    
        // MARK: - Mouse Events
    
        override func resetCursorRects() {
            addCursorRect(bounds, cursor: cursorType)
        }
    
        override func mouseMoved(with event: NSEvent) {
            cursorType.set()
        }
    
        // MARK: - Private Properties
    
        private var currentTrackingArea: NSTrackingArea?
    
        private var cursorType: NSCursor {
            return isEditable ? .iBeam : .pointingHand
        }
    
        // MARK: - Private API
    
        private func setupTrackingArea() {
            let trackingArea = NSTrackingArea(rect: bounds,
                                              options: [.activeAlways, .mouseMoved],
                                              owner: self, userInfo: nil)
            currentTrackingArea = trackingArea
            addTrackingArea(trackingArea)
        }
    
        private func resetTrackingArea() {
            if let trackingArea = currentTrackingArea {
                removeTrackingArea(trackingArea)
            }
            setupTrackingArea()
        }
    
    }
    

提交回复
热议问题