Menu shortcut overrides NSTextField's normal behavior - cocoa

In my cocoa app I have a Menu to "select all" and I naturally assign "Command-A" to it.
However if I am in a text field and I press Command-A, instead of selecting all the text in the text field it calls the menu. How can I overcome this?
I have tried subclassing NSTextField to have becomeFirstResponder return true but that didn't work out.
EDIT: Select All is "mine" and is not in the Edit menu. Its "Sent Action" points at the first responder (which is a red herring). I'm not sure how Save is done (how it ends up calling my NSDocument because it also refers to First Responder).
Instead of First Responder I moved the menu's action to the App Delegate (which then tries to get the current NSDocument and do its stuff) but it is still not working.
What should I point the action at? Looks like I only have the choice between "Application", "App Delegate" and "First Responder".

Related

Editing text in field editor disables ⌘S when menu item is customized

When I bind "File > Save ⌘S" to a custom IBAction it works fine, except when I use the window's field editor to make something editable programmatically. (NSTableHeaderCells, specifically.)
When the cursor is in any NSTextField, ⌘S is still activated. That's what I want.
When the cursor is in the field editor (NSText based), ⌘S is deactivated. This only happens when I change the connection in MainMenu.nib to "First Responder > myCustomSaveMethod:".
Any ideas how to enable ⌘S-saving in the field editor in this case?
The reason this happened is that the "First Responder" is anything above the current view in the responder chain. The manually invoked field editor is inserted into the responder chain below NSWindowController. myCustomSaveMethod: is implemented in a sub-view controller which is not part of that responder chain, so the method definition isn't available to the field editor.
Moving myCustomSaveMethod: to a responder in the chain that both the table view and the field editor share (e.g. the NSWindowController) works like a charm.
¯\_(ツ)_/¯

Facing issue with internationalize MainMenu.xib for Cocoa based Mac OS X Application

I am working in a Cocoa based Mac OS X project and facing one issue with internationalize MainMenu.xib.
In the menu items, all titles are need to be internationalized programmatically. All the menu items like “cut”, ”copy”, ”paste” can be internationalized using setTitle except the undo and redo menu item title. Adding to this, after typing anything in the text fields of the project forms, the undo menu item title dynamically changed to “Undo Typing”. The same happens for “Redo” also.
I can set the titles of other menu and menuitems' title using,
[[[[NSApp mainMenu] itemAtIndex:1] submenu]setTitle:#"Edit_Test"]
for MainMenu.xib "Edit" menu and similarly,
[[[[[NSApp mainMenu] itemAtIndex:1] submenu]itemAtIndex:4]setTitle:#"Copy_Test"]
for NSMenuItem "Copy" which is in under "Edit" menu.
But If I use the same piece of code,
[[[[[NSApp mainMenu] itemAtIndex:1] submenu]itemAtIndex:0]setTitle:#"Undo_Test"]
the menuItem title still remain as "Undo"
NSUndoManager provides the methods undoMenuItemTitle and redoMenuItemTitle, but NSUndoManager does not send the -setTitle: messages to the "Undo" and "Redo" menu items.
So how can I track that dynamic change in title and make that "Undo Typing" internationalized also?
Is it possible to manually get the First responder of the MainMenu.xib and from that get the undomanager object? So that i can unbind the undo action that is currently present in the first responder with the undo menu item and perform undo operation manually or is it possible to just change the title programmatically without doing all these.
Please let me know if any one had come across this problem and resolved the issue.
Make a subclass of NSUndoManager and override the undoMenuTitleForUndoActionName: method and the redoMenuTitleForUndoActionName: method. Create instances of this subclass for each document (or managed object context, or other thing) that needs an undo manager.

NSTextFinder action on NSTextView

I'm trying to capture all the NSTextFinderClient calls on my custom NSTextView subclass.
The show action is called on my -(void)performTextFinderAction:(id)sender override, but for find next, find previous, etc. it's not called.
Any ideas?
Thanks!
Edit:
If you create a new project and drag an NSTextView from interface builder, command-g and command-shift-g (find next and find previous) don't work when the find bar is first responder.
Why is this?
I need a custom subclass of NSTextView to respond to the find bar for every event.
I searched in the Apple's TextEdit source code because with TextEdit, the standard search bar within the Text View works fine for command-G (and other shortcuts) even the search field is the first responder.
I found the solution.
Go to your nib for the main menu, and select the "Find" (and related) menu items. They should be bound to the default action called "performFindPanelAction:." Now unbind them and bind to "performTextFinderAction:" of the First Responder instead.
You may not find that action in the First Responder's action list. So you need to add it by yourself in the First Responder's attributes inspector pane.
This was meant by the document below saying
Before OS X v10.7, the default action for these menu items was performFindPanelAction:. Whenever possible which you should update your implementation to use this new action.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/#//apple_ref/occ/instm/NSResponder/performTextFinderAction:
The find bar communicates privately with the client's NSTextFinder instead of calling NSResponder's -performTextFinderAction:. This is necessary to allow find to work when something besides the client has key focus.
What are you trying to accomplish?

How do I stop my NSbutton from being selected when the app starts by default?

I created a button, and a have a little problem: When the my app launches, the button is selected. How do I disable this selection?
Example:
Caveat: This answer is incomplete: It just hides the focus ring (without preventing the selection). There's little benefit in this solution.
Set your button's focus ring type to none:
[myButton setFocusRingType:NSFocusRingTypeNone];
You can also set this option in the XIB.
First, you should know that, by default, buttons can't get focus. A user would have to have selected System Preferences > Keyboard > Shortcuts > Full Keyboard Access: All Controls. If they've done that, they may want a button to initially have focus.
Anyway, the proper way to do this is to call [theWindow makeFirstResponder:nil] sometime after showing it the first time. When to do this depends on exactly how the window gets shown. If you show it explicitly in code, then you can make the call just after that. If it's shown because its Visible at Launch flag is set in its NIB, then you'd do it after the NIB is loaded. Etc.
Something should always be first responder in a window, if anything can be. Normally, only a few controls like text fields can become first responder, but when a user has Full Keyboard Access enabled, it's normal for a button to be selected by default.
If you don't want this particular button to start selected, set the window's initialFirstResponder to another control.
I'd advise against using -[NSWindow makeFirstResponder:nil]. The window will start with nothing selected, but the button will become selected as soon as the user hits tab. This is unusual for Mac apps because there's no way to get the window back into the "nothing selected" state as a user.

How to make a keyboard shortcut to close dialog with Xcode/Interface Builder?

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.
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.)
Adding an invisible button works just fine.
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.
why don't you try this:
-(void)keyDown:(NSEvent *)theEvent{
//If the key is X or x it just closes the window
if ([theEvent.characters.uppercaseString isEqualToString:#"X"]) {
[self.window performClose:self];
}
}
or if you want to show a window you can instanciate and show it there instead of the performClose
Jasper was right about the code part. For interface builder(storyboard), there is a quick fix:
In your storyboard, hit "CMD+Shift+L" to bring up the components lib, select File Menu Item.
Add the file menu item to the Application Scene's Main Menu Node. (Remove unwanted file menus)
Now you have a keyboard shortcut to close a window.

Resources