How to programmatically add new NSToolbarItem to existing toolbar? - cocoa

I'm looking for a method called addNewItem:(NSToolbarItem *)item or something like this that lets me add a programmatically created item to my toolbar, but I haven't found any. I would like to add an item that shows a popover when the user clicks on it, like in Safari when the user downloads something.

You need to have a class that conforms to the NSToolbarDelegate protocol and have an instance of that class be the delegate of your toolbar. This delegate would, for example, implement -toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:, which returns an NSToolbarItem instance for a given identifier, potentially creating that item on demand. By doing this, you’re preparing your delegate to return a toolbar item when the toolbar asks it for the item corresponding to an identifier.
Having done that, you can programatically add a new toolbar item to the toolbar by sending -[NSToolbar insertItemWithItemIdentifier:atIndex] to the toolbar instance. The identifier string argument should match the one used in the paragraph above. If you need to remove an item, send -[NSToolbar removeItemAtIndex:] to the toolbar.
This is described with examples in the Adding and Removing Toolbar Items section of the Toolbar Programming Topics for Cocoa document.

Related

How to show NSTextView-like context menu

I want to present NSTextView-like context menu for a certain NSString object (say, "text") each time -rightMouseDown-method of my custom NSResponder-subclass get called.
Where can I obtain these items for some NSString?
UPD
Created NSTextView instance and used its -menuForEvent:-method. Some of items was disabled (like 'copy' and so on), I reset its target value to custom object with overridden selectors (like -copy: and others).
NSTextView is an NSView subclass, which provides a class method +defaultMenu. So you can ask for NSMenu * menu = [NSTextView defaultMenu]; to get your very own copy to do with as you please. You may have to walk its structure and customize individual NSMenuItem instances to adjust their target/action but most (all?) should work just fine with nil-target (sends action to first responder) and their default action.
I must admit, however, I'm not sure what you mean by "Where can I obtain these items for some NSString?" The context menu is opened from some UI control (like a text view) and sends its action (like -checkSpelling...) to some target (like the first responder; which should be something like a text view, which acts as the view for a string or attributed string) to act upon.

Different menubar in document based apps

I've a cocoa app based on NSDocument, I've two types of document.
Every document type has its own menu items, all items are defined in mainmenu.xib.
As defined in Apple UI guidelines the menu items irrelevant for a doc type are shown grayed.
I have too much menu items so I want to show only relevant items per doc type, another problem is created by the key bindings, for doc type A a particular key binding is associated to a menu item but for doc type B the same key bindind is associated to another menu item but this isn't possible because XCode detects the same key is already used and it removes (correctly) from previous item definition.
I want to create a menu similar to XCode's 'Editor' menu, it shows some items when focus is on a text window and a totally different item set when focus is on a IB file.
Are there best practices? For example splitting menus.
How can I easily create a menu similar to XCode's 'Editor' menu?
Which API cocoa gives us to do it?
You can create the separate menu(s) in the MainMenu.xib and create outlets to them from the App Controller. Then when your document gains focus (see windowDidBecomeMain (reference)), you tell the App controller to switch-out the relevant parts of the main menu.
Switching-out the parts of the main menu is done by trawling the main menu hierarchy and assigning the separate menu at the right place (i.e. [NSMenuItem setSubmenu:] (reference)). You can make this easier for yourself by setting tags, using Interface Builder, in those menu items and then using [NSMenu itemWithTag:] (reference) to find them programmatically.

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?

Multiple documents open at the same time, each with different menu item states

In a Cocoa document-based application, what's the best way to keep the menu item states in the menu bar in sync with the currently visible document?
For example, say you have a document with a ruler view that can be hidden/shown via "Show Rulers" (off state) and "Hide Rulers" (on state) menu items. The user has two documents open at the same time. He/she has hidden the rulers in one document, but not on the other. When the user moves between the documents the menu item should reflect the state for that document, not for the application as a whole.
How does one do this cleanly? I've googled around but it doesn't seem like there's a predefined "out of the box" way to do this. It would be nice if NSDocument had some sort of "didRegainFocus" type method where such logic can be added.
My actual implementation is a bit trickier since it's actually a NSViewController inside my NSDocument that deals with these particular menu items.
#interface MyDocument : NSDocument {
SomeViewController *myCustomizedTextViewController;
}
When MyDocument is the currently active document, I need methods in myCustomizedTextViewController to ensure the state of a couple of NSMenuItems in the application's main menu. One is genuinely a ruler. The other is a similar temporary setting.
Have the target of the menu items implement the validateUserInterfaceItem: method to enable/disable them. See the User Interface Validation reference for more info.

Resources