Subclassing NSControl, IBAction is not called in Swift

646 views Asked by At

I've subclassed an NSSlider that behaves differently whether the option key is pressed. In order to do that, I overrode the mouseDown func. It seems to do the job. The thing is, I've noticed the connected @IBAction in my ViewController is only triggered when the option key is unpressed (i.e. when the mouseDown method is passed to super). What am I missing in order to allow the @IBAction to perform?

Many thanks Besides the issue, improvement advices on the code are welcome... :-)

Josh

class ViewController: NSViewController {

    @IBOutlet weak var theSlider: MySlider!
    @IBAction func moveSlider(sender: NSSlider) {
        print(sender.floatValue) //works only with optionKey unpressed
    }
}

class MySlider: NSSlider { //Implemented in another source file

    @IBInspectable var multiplier: Float = 0.5
    private var modifierKeys = NSEventModifierFlags.AlternateKeyMask
    private var optionKeyPressed = false
    private var previousSliderPosition: Float = 0.0

//MARK: Init with NSCoder
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        Swift.print("init Coder called")

        self.continuous = true
        NSEvent.addLocalMonitorForEventsMatchingMask(.FlagsChangedMask) { (theEvent) -> NSEvent? in
            self.flagsChanged(theEvent)
            return theEvent
        }
    }

//MARK: Mouse tracking
    override func mouseDown(theEvent: NSEvent) {

        if optionKeyPressed {

            var keepOn = true
            previousSliderPosition = self.floatValue * Float(self.bounds.width) / Float(self.maxValue)

            while keepOn {
                if let nextEvent = self.window?.nextEventMatchingMask(Int(NSEventMask.LeftMouseUpMask.rawValue) | Int(NSEventMask.LeftMouseDraggedMask.rawValue))
                {
                    switch nextEvent.type
                    {
                    case .LeftMouseDragged:
                         let mouseInnerLocationX = Float(self.convertPoint(nextEvent.locationInWindow, fromView: self.superview).x)
                        let mouseDelta = mouseInnerLocationX - previousSliderPosition
                        let newSliderPosition = previousSliderPosition + (mouseDelta) * multiplier

                        self.floatValue = newSliderPosition * Float(self.maxValue) / Float(self.bounds.width)
                        break

                    case .LeftMouseUp:
                        keepOn = false
                        break

                    default:
                        break
                    }
                }
            }
        } else {
            super.mouseDown(theEvent)
        }
    }

//MARK: Option key handling
    override func flagsChanged(theEvent: NSEvent) {
        if (theEvent.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == NSEventModifierFlags.AlternateKeyMask.rawValue {
            optionKeyPressed = true
        } else {
            optionKeyPressed = false
        }
    }
}
1

There are 1 answers

1
rob mayoff On BEST ANSWER

If you're not calling super.mouseDown, you need to send the action yourself:

sendAction(action, to: target)

sendAction(_:to:), action and target are existing members of NSControl.