how can I customize NSToolbar context menu on OS X El Capitan? - osx-elcapitan

Is there a way to customize the context menu that pops op when right clicking on a toolbar (or the title bar of the window containing it)?
Several Apple applications (XCode, Safari, Mail and probably others seem to be able to remove or hide certain menu items), but I can't find a way to access the NSMenu.
Here's what I tried so far:
tried to get to the menu as I did on previous OS X versions (as explained here: How to customize the context menu of NSToolbar?): the returned NSMenu is nil
tried to override rightMouseDown: in the NSWindow containing the toolbar: the method is not called
tried to override menuForEvent: in the window's content view (I replaced the default content view with a custom NSView for this): the method is not called
tried to override rightMouseDown: in the window's content view (I replaced the default content view with a custom NSView for this): the method is not called
Any help would be greatly appreciated.

I actually found the answer by inspecting things in the debugger and tinkering a bit. On El Capitan, a working solution is to get the menu as such:
NSView * theContentView = myWindow.contentView;
NSMenu * theCustomizeMenu = theContentView.superview.menu;

Related

UIBarButtonItem created in Interface Builder not working - confused

I am trying to tidy up my UI by consolidating various things in a Tool Bar, and am utterly confused. I am using Interface Builder rather than constructing the controls programmatically, because my UI is fairly simple and not particularly dynamic.
What I did did so far:
Added an empty tool bar.
Dragged two previously existing and working buttons onto the tool bar. They changed their class from UIButton
to UIBarButtonItem, and the inspector now shows them as having no
Sent Actions or Referencing Outlet, but the the previous action &
outlet in the View Controller - responding to taps, setting the
label of the button - still work.
Created a new Button directly
in the tool bar. Wired up its action & outlet by ctrl-drag in the
normal way. The inspector shows the Action and Outlet for this
button as connected, which is nice, but sadly neither of them works.
Clicking the button does not invoke the action; setting the label of
the button does not cause anything to happen on the screen, even
after I tried prodding the tool bar with a setNeedsDisplay.
I'm not sure what to try next. Googling has shown me that I'm not the only person to find using UIToolBar via Interface Bulder difficult and confusing, but I haven't found a solution to my exact problem.
I don't particularly want to resort to creating my entire GUI programmatically just to tidy up a few buttons. Creating all the controls in Interface Builder outside the tool bar, getting them wired up and working, then moving them into the tool bar would presumably also work - but it would be a kludge, and would leave me still none the wiser if anything went wrong later.
Should you try using UIBarButtonItem instead of UIButton? It works for me.
i had a similar issue.
Did you created an extra UITapGestureRecognizer for root view ?
Maybe for something like > When elsewhere than UITextView clicked, resignFirstResponder for all UITextViews !
In my case, on 7.1, that extra UITapGestureRecognizer prevented transfer of event to IBAction of UIBarButtonItem which is inside an UIToolBar.
IBAction was made on Storyboard by Ctrl+Drag.
on 8.1 it was working. Not on 7.1
Read some suggestions to create an extra UIView and putting all visual elements into that extra UIView except UIToolBar

NSPanel with "Title Bar" unchecked in Interface Builder does not appear

So I thought I had covered my bases, but apparently I'm missing a key step or two.
I have an NSPanel that is displayed (makeKeyAndOrderFront:) when an NSStatusItem is pressed. Things work great, but as the NSPanel displays a title bar, the panel is also draggable. (This is undesired.)
The first screenshot shows the panel with "Title Bar" enabled in Interface Builder, in the Appearance category. (Sorry for the blur, things are still under lock and key for now.)
The only change that is made in Interface Builder is unchecking the "Title Bar" checkbox. I then save and re-run, and that's what you see in the second screenshot. While a slight shadow appears, the panel does not.
Things I've tried:
I've subclassed the NSPanel and returned YES for canBecomeKeyWindow and canBecomeMainWindow after a bit of research, but (prior to subclassing) these methods both returned NO regardless of whether I was using a Title Bar or not. So I don't think this is the issue.
I've ensured that the frame for the NSPanel is properly set. It has a good height, and the origin is set properly as well.
Edit: Forgot to Mention:
The application is a menu-bar-only application. In the screenshot below, note that an additional entry was added to Info.plist to enforce this.
I've had problems with this in the past. I was able to resolve it by first "ignoring" other apps, then making it the key window. Give it a shot and see if it works for you.
[NSApp activateIgnoringOtherApps:YES];
[[self window]makeKeyAndOrderFront:self];
Also, try setting the window level to NSPopUpMenuWindowLevel during initialization.
[[self window]setLevel:NSPopUpMenuWindowLevel];
I have also had problems with the way that nib files are loaded on Mac OS X. They're loaded "lazily", which means that they won't be initialized until they're needed. This causes a problem when you're wanting to set specifics on the window, but you can't because awakeFromNib doesn't seem to be called, due to lazy nib loading. To fix this, here's what I've done in the past. In your delegate (or wherever you initialize your window), kick the window into action by accessing the window property on the initialized class:
wc = [[blah alloc]initWithWindowNibName:NSStringFromClass([blah class])];
(void)[wc window]; //just kicks the lazy nib loading into gear
By doing so, you're forcing the nib to initialize. That way, when the user clicks the menubar icon the nib is already initialized, and awakeFromNib has already been called.
While a slight shadow appears, the panel does not.
Are you saying makeKeyAndOrderFront: on this NSPanel object doesn't display it when running your app? I just created a sample project, NSButton triggers the same type of NSPanel to display, and it works fine.. titleBar enabled or not.
http://cl.ly/3d0U3C0P3u2D0m3T1w1N

Drawing an "NSView" to a Custom-View - How? Am I taking the right approach?

I'm using Objective-C and Cocoa, whilst developing for Mac OS X - so not the iPhone/Cocoa Touch. (That said, I'd be interested if it was the same procedure for the iPhone)
I'm working on a preferences window for a simple app. I have a NSWindow with a toolbar - there are 5 different items on the toolbar, all of which need to bring up a different set of options.
So I set the NSToolbar and its items in Interface Builder, and then placed a custom view underneath the menu - taking up the rest of the window. My plan is to work out the interface too each of the NSToolbarItems options, and then draw the corresponding view on to the custom view when the specified NSToolbarItem is clicked.
I'm guessing that I simply create a NSView sub-class for each view, an empty xib in Interface Builder - set the xib to my custom NSView, code it as usual... But here's a few problems;
1 - Just how can I get the xib file to appear on the custom-view then? I have looked around and most articles don't seem to have this situation, or a situation I can relate too.
2 - When the window comes up, I want the default view to appear on the custom view. Once again, I'm guessing I just write that in the initialisation code for the NSWindow - its no big deal. It just goes back to question 1 though - how do I draw my NSView to the custom-view specified in Interface Builder?
I'd be really grateful for any help!
Cheers in advance.
So I set the NSToolbar and its items in Interface Builder, and then placed a custom view underneath the menu - taking up the rest of the window.
You can't have a menu inside of a window. You can have a pop-up button, which has a menu, but not a menu directly. Did you mean “toolbar” here?
You don't need to create a custom view for this. Make a tab view and set it to be tabless. Give it as many tab view items as you have toolbar items. In your controller, write an action method for each of the toolbar items, and in each action method, switch the active tab of the tab view.
You can activate different tabs in IB to populate them with views in IB. The active tab is saved in the nib, so make sure you set it back to the first tab before saving, so that the first tab is the one that's initially active when your app runs.
Just how can I get the xib file to appear on the custom-view then?
That question doesn't make sense.
Once again, I'm guessing I just write that in the initialisation code for the NSWindow - its no big deal.
You would only be able to do that if you have your own initialization code for the window, which you would only have if you have subclassed NSWindow. There are very few reasons to do that; unless you're making the window itself look different (not making an Aqua or HUD window), you should move that initialization code elsewhere, probably to the aforementioned controller (which should be the File's Owner of the nib).
It just goes back to question 1 though - how do I draw my NSView to the custom-view specified in Interface Builder?
A custom view in Interface Builder is a plain NSView (unless you explicitly change it to a subclass of NSView you create). However, you do not need one for anything you have described in your question.

Setting Toolbar Items of UINavigationController

In iPhone OS 3.0, you can set the toolbar items of a UINavigationController using the setToolbarItems:animated: method. However, this requires you pass in an array of UIToolbarItems. While I could programmatically create these toolbar items, I'd rather create them in Interface Builder if possible.
With this in mind, I have created a UIToolbar in "MyGreatViewController.xib" and have populated it with the wanted toolbar items. Then, in "MyGreatViewController.m", I get the items from the toolbar and pass them to setToolbarItems:animated::
- (void)viewDidLoad {
[super viewDidLoad];
[self setToolbarItems: [toolbar items]];
}
...where toolbar is an IBOutlet referring to the UIToolbar.
Is this a good approach? Is there a better way to accomplish this? Should I just create the items programmatically?
I don't know if this is documented anywhere, but I've found that in Interface Builder, if you enable the navigation controller's toolbar, you can drag bar items to your view controller, and they will automagically show up in the navigation controller's toolbar.
For example, here's what we can do (using Xcode 3.2 on Snow Leopard):
File->New Project.... Choose Navigation-based Application and create the project.
Open MainWindow.xib in Interface Builder.
Select the Navigation Controller, and in the Attributes inspector, check the "Shows Toolbar" box. This will cause a Toolbar object to appear.
Drag a Bar Button Item from the Library to the toolbar. It will appear in the toolbar. If you check the hierarchy in the NIB, you'll see that this new item is a child of the RootViewController.
It seems that any Bar Button Items added as children of the navigation item will show up in the navigation bar, and any Bar Button Items added as children of the view controller will show up in the toolbar.
(I stumbled on this by accident. If anyone can find documentation for this behavior, or any additional info, I'd like to hear about it.)
It's a perfectly acceptable way of doing it, but do bear in mind that loading xib files is quite expensive on the iPhone, and it may well be faster to create the toolbar items programatically in your viewDidLoad method.

Putting an NSPopUpButton in an NSToolbar

Having wrestled with NSPopUpButton in a previous question here I am now trying to place a NSPopUpButton inside an NSToolbar. Essentially I want to create something similar to what XCode has by default on the left hand side of it's toolbar. E.g. a pop up button with an action button next to it.
I have seen a method that show's a programmatic way of creating an NSPopUpButton and then adding it to an NSToolbar, but then I can't work out how to do all the Binding stuff that was so handy last time.
Interface Builder hasn't been very helpful, so any help gratefully received.
P.S. Could I solve this by creating a custom view (containing an NSPopUpButton with the usual bindings) and then adding the custom view to the toolbar?
It's actually pretty easy to do what you want here. In Interface Builder, switch to the tree view (the second button on the View Mode segmented control). Expand the window and the toolbar. Then, from the library, drag a popup button onto the toolbar. Interface Builder will embed a new popup button in a custom view for you automatically.
To actually put the button on the toolbar, double click on the toolbar in the window. This will bring up the customization sheet. You can drag the popup button to the desired location on the toolbar.
If you wanted to do this programmatically, you would create a custom view containing your popup button. Then, you'd need to assign it to a new outlet so you can refer to it programmatically. In the toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar method, you would create a new NSToolbarItem per usual, and call setView: to assign the custom view to the toolbar item.
Old post, but note you can also double-click the toolbar in the window and drag straight into the "Allowed Toolbar Items".
You will want to open up the toolbar view anyway so you can drag things in or out of the default toolbar items.