0

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)
  }
}
mistercake
  • 692
  • 5
  • 14

1 Answers1

0

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 and previousKeyView? This should provide the directionality you need, but also might interact better with the system overall (ie Accessibility) than just via keydowns.

Mattie
  • 2,868
  • 2
  • 25
  • 40
  • 1
    I don't understand your proposed solution. What would I return in the getters of these properties? The view itself? Also, what would the setters do? – mistercake Nov 24 '18 at 18:54
  • It's my mistake. I didn't look closely enough at these APIs before making the suggestion. While there might still be something to the idea of hooking into the next key view mechanism of NSView/NSWindow itself, these particular properties won't get you want you need. – Mattie Nov 27 '18 at 20:35