views:

728

answers:

3

This seems awfully basic but here goes. If you are keyboard-oriented you get used to using Command-W to close windows all the time in OS X. I'd like to add that capability to the dialogs I am creating in Interface Builder for my program. I can see how to add a keyboard equivalent to a button action but what if I don't have a button?

Should I add an invisible button and put the shortcut on that? Seems clunky. Surely there is just some method I can override but what I've tried so far isn't working.

+1  A: 

Is the dialog an NSWindow? Because by default the File->Close menu option is set to the performClose: action of the first responder, and already wired to command-w

If the dialog isn't a window simply make your dialog first responder and implement the performClose: action.

Jason Harwig
+1  A: 

When you press Command-W, it's the exact same as choosing File -> Close from the menu bar. What Close does is send a performClose: message to the first responder. That, in turn, will check if the receiver or if the receiver's delegate implements windowShouldClose:, and the window will close if it returns YES (otherwise, it will call the close method).

So really, it depends on what type of dialog you've got here. If it's non-modal (essentially, if you can access the menu bar while it's running) and is an instance or subclass of NSWindow, then all you need to do is override the windowShouldClose: method in your dialog's delegate (or your dialog class, if you subclassed NSWindow or something) and make it return YES.

However, if the dialog is a modal dialog (you can't access the menu bar, switch windows, etc. while the dialog is running), then you can't do it this way. You could add an invisible button, but in all honesty, a modal dialog should not be closed by hitting Command-W, for that most certainly violates some Apple interface guideline out there. (Especially since, as Ande noted, it's standard practice to have Esc close/cancel a dialog.)

htw
It is an instance of NSWindow. What you suggest makes sense but when I override windowShouldClose: in the delegate that method is not called when Command-W is pressed. I tried overriding performKeyEquivalent: but that doesn't get called either. Any key I press (except Command-Q which quits the whole application) just beeps.
gauss256
That sounds like your dialog is modal—in other words, the rest of the interface is disabled while the dialog is running. In this case, you can't (and shouldn't) try to make Command-W close the dialog. You should instead add a "Cancel" button which would map to Esc and/or Command-Period. This is more in line with expected behavior and established interface guidelines.
htw
No, it's modeless. I have a few dialogs, but to pick one specific example, the About dialog. Like in Xcode itself, the About box is modeless, and I'd like to be able to dismiss it with Command-W, as in Xcode.
gauss256
A: 

Adding an invisible button works just fine.

gauss256
But is not necessary. I created a new project, ran it without doing anything to it, and was able to ⌘W its About window. If you're not able to do that, then you broke ⌘W and should fix it. Make sure the Close menu item is connected to First Responder, and not a specific window.
Peter Hosey
You're right: I had accidentally broken Command-W by mucking around with the menu. The details of the bad thing I did are not interesting but I brought it back to its original state and everything works now without the need for magic invisible buttons.
gauss256