NSBrowser....conditionally suppress right-click menu

How can I conditionally suppress NSBrowser's contextual menu?


I only want to show a menu, if the right click is on selected row... but when you set the menu property on NSBrowser, it shows it when you right click anywhere on NSBrowser.


I tried to use the menuNeedsUpdate: delegate method and check the selected rows in a column...if there's none... set the browser's menu to nil, but it's too late at that point. Would be cool if there were delegate methods for this.


Is there any other way besides hiding all the menu items?

Try overriding -menuForEvent:.

menuForEvent: doesn't get called on my NSBrowser subclass.

I guess menuForEvent: must get called on a subview of NSBrowser, and it must eat it. There doesn't seem to be a clean way to handle this. I can override menuForEvent: on a NSMatrix subclass, if I set a custom matrix class..though that API is deprecated.


What I want to do, is when a user right-clicks, and no column/row is selected, I want nothing to happen (no menu to show). I can be a bit hacky by using validateMenuItem: and hiding everything in there. Doing this isn't great either, because I can right click in a different column than the selected column and the menu will show...since I don't have the NSEvent to check the location of the click against, it seems that I have to add another layer of nasty code by converting the current cursor's position. None of this feels clean.


Edit: Seems that I can set the menu property on each cell in browser:willDisplayCell:atRow:column:


Far as handling right clicks in blank areas and showing an alternative menu depening on what that column is representing, still pretty quirky. Wish there was just a delegate method that allowed me to dynamically change the menu for a given column/row.

You can try overriding -menu (the getter for the menu property) and logging [NSThread callStackSymbols] to see where it's called from. It may even be enough to return nil from that when you don't want a contextual menu to show, although, when you're just investigating, you would call through to super and return what that returns.

Yeah, the getter for menu gets called from the addColumn method. It seems that everytime NSBrowser adds a column, it sets the menu for that column (whatever view it uses for the column) to be its menu. The main view used to create each column, far as I can tell is private API.


What I'm going to try is:

1) Setting the menu directly for each cell.

2), Setting a different menu for the browser.

3) Take hack-ish measures to validate the browser's menu to block it from being shown by hiding all the menu items when necessary.


If there is a more elegant way to this, I'd love to know.

NSBrowser....conditionally suppress right-click menu
 
 
Q