I have a custom view that has multiple components that can receive the focus, similar to NSDatePicker
in the textFieldAndStepper
style. If it gets the focus the first component is focused. You can then tab through the components. If you hit tab while the last component has the focus, the next view in the window gets the focus. When you use backtab (shift + tab) it goes in the other direction. How would I do that?
I currently move the focus along the components in the keyDown
event, and I override becomeFirstResponder
and resignFirstResponder
to switch on or switch off the focus when the user tabs beyond the last component or backtabs beyond the first component.
However in becomeFirstResponder
I cannot tell how the view got the focus. It could have been a tab or a backtab or a mouse click.
How do I get this information in becomeFirstResponder
, or is there another way to solve this problem.
Note that I don't want to introduce subviews, for various reasons.
Here is the code I have so far:
private var selectedComponent: Int?
override public var acceptsFirstResponder: Bool {
get { return true }
}
override public func becomeFirstResponder() -> Bool {
selectedComponent = 0
needsDisplay = true
return true
}
override public func resignFirstResponder() -> Bool {
selectedComponent = nil
needsDisplay = true
return true
}
override public func keyDown(with event: NSEvent) {
guard let selectedComponent = selectedComponent else {
self.nextResponder?.keyDown(with: event)
return
}
guard let specialKey = event.specialKey else {
self.nextResponder?.keyDown(with: event)
return
}
if specialKey == NSEvent.SpecialKey.tab && selectedComponent < componentFormats.count - 1 {
self.selectedComponent = selectedComponent + 1
needsDisplay = true
} else if specialKey == NSEvent.SpecialKey.backTab && selectedComponent > 0 {
self.selectedComponent = selectedComponent - 1
needsDisplay = true
} else {
self.nextResponder?.keyDown(with: event)
}
}
It sounds like you do have your problem sorted out now. But, I was thinking, would it be possible to get the same effect by overriding NSView's
nextKeyView
andpreviousKeyView
? This should provide the directionality you need, but also might interact better with the system overall (ie Accessibility) than just via keydowns.