4

I'm writing a small menubar application for OS X Yosemite. When clicking on the menubar icon, a popover appears with a number of recessed buttons. Like so: enter image description here

As you can see, the "d4" button is focused, even though the d20 is selected by default. Clicking on any other button does not change the focus from the "d4" button. The only way to move the focus ring is via the Tab key.

Here is my code from the popover view controller:

import Cocoa

class DiceRollerViewController: NSViewController {

    var result: Int = 0

    var currentNumberOfSides = 20

    @IBOutlet weak var rollButton: NSButton!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func sidesButtonSelected(sender: NSButton?) {
        for view in self.view.subviews as [NSView] {
            if let btn = view as? NSButton {
                if btn.tag == 1 {
                    if btn != sender {
                        btn.state = 0
                    }
                    else {
                        btn.state = 1
                    }
                }
            }
        }
    }

    @IBAction func rollDice(sender: AnyObject?) {
        willChangeValueForKey("result")
        result = DiceRoller.rollDice(numberOfRolls: 1, numberOfSides: 20)
        didChangeValueForKey("result")
    }

}

And the relevant AppDelegate code:

func showPopover(sender: AnyObject?) {
        if let button = statusItem.button {
            popover.showRelativeToRect(button.bounds, ofView: button, preferredEdge: NSRectEdge.MinY)
        }
    }

To summarize, I'm trying to get rid of the focus ring that appears automatically when clicking on the popover. However, I don't want to remove the ability to focus via tab for accessibility reasons.

pkamb
  • 33,281
  • 23
  • 160
  • 191
camden
  • 1,908
  • 19
  • 18

1 Answers1

15

Try overriding viewWillAppear() to make the "Roll!" button the first responder by doing:

if theRollButton.acceptsFirstResponder {
    self.view.window.makeFirstResponder(theRollButton)
}
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Unfortunately this fails because the Roll button is within a popover, not a window. When I unwrap `window` the program crashes because `window` is nil. – camden Aug 06 '15 at 23:41
  • Curious. I'm pretty certain there must be a window there under the hood. For example, the window is what manages the first responder (focus). Way too much code would be dependent on there being a window for things to work without one. Maybe try `viewDidAppear()`. – Ken Thomases Aug 07 '15 at 03:23
  • Ah, perfect. For the record I misread your original answer so I put the if statement in `viewDidLoad()`. Whoops! Both work, actually. Thanks so much. :) – camden Aug 07 '15 at 04:15