manual item enabling
Kurt,toggle quoted messageShow quoted text
The menu key equivalents are pulled out before -keyDown: is called. You can override that event in -performKeyEquivalent:, a methof of NSResponder (and therefore views, etc). You can probably call your menu update method and then call super to handle the key equivalent.
I recall the menu update mechanism from TCL very well, and I don’t think it’s a terrible way to do it, but certainly it’s a little different in Cocoa. You might find that converting your code to use -validateMenuItem: is not as bad as you’d think though, it’s broadly similar to the TCL way, just you get each menu item passed in turn, rather than the whole menu. But the code in that method deals with all of the menu items applicable to the receiving object, just like the TCL way does, and then punts any others to the next responder.
On 25 Nov 2019, at 8:28 am, Kurt Bigler via Cocoa-dev <cocoa-dev@...> wrote:
Hi Kurt, re-reading the documentation on basic event handling might help:
particularly “The Path of Key Events”, and “Handling Key Equivalents"
Note that I mentioned NSResponder. Both NSApplication and NSView both subclass NSResponder, so there are two very different objects that receive events. I was thinking about this in terms of NSView, but NSApplication does things a little differently.
but if keyDown is what calls performKeyEquivalent, then how could performKeyEquivalent help
NSApplication’s -sendEvent: calls -performKeyEquivalent: but AFAICS, no -keyDown: method ever calls it - it’s always handled before that is called.
It’s still a little unclear to me why the standard approach that Cocoa takes to menu updating can’t be used here. In both the key equivalent case and the click on the menu case, the responder chain is asked to -validateMenuItem: for as many menu items as needed (I would expect this to be just one for a key equivalent), and you just return YES or NO to indicate the enable state of the item. But that validation method is free to examine any other property of the menu item, so if there is some legacy there of command numbers or whatever, the validation method can use it. The validation method can also change the text of a menu item.
Now I recall that in TCL, the whole menu structure (per menu? I forget now) was passed to the responder chain so it was less granular than Cocoa, so the update mechanism would enable a whole bunch of items at once. Is my understanding correct that you’d rather port that code more or less “as is”? In which case possibly the menu delegate approach is going to be more appropriate than validating individual items.
But I would suggest that handling individual items is not so very different - it’s the same concept, just broken down a little more so that you deal with one item at a time. In fact your code is generally written so that that multiple-calling situation is irrelevant. The same validation method handles ALL the cases pertaining to the current responder object, just as the TCL update method does. It’s just that the Cocoa method is called multiple times, but only one case applies, and the TCL method is called only once, but multiple cases apply. The difference between the two is actually minor. In the cocoa case, you just need to add an additional if() per item that checks that the passed item is actually the one you want.
so for example, in the TCL case, you’d have had code that was equivalent to:
- (void) updateMenu:(CMenu*) menu
menu.items[kNewItem].enable = YES;
menu.items[kOpenItem].enable = YES;
menu.items[kQuitItem].enable = YES;
and in Cocoa, you change that to:
- (BOOL) validateMenuItem:(NSMenuItem*) item
if( item.command == kNewItem )
if( item.command == kOpenItem )
if( item.command == kQuitItem )
return [nextResponder validateMenuItem:item];
Note this is just conceptual code - there is no method on NSMenuItem called -command. So you’d have to deal with that difference, or use the menu item's -action property instead, which is the usual way.
So in my view, you’re overthinking this. Just let Cocoa do its thing and adapt the validation to suit rather than try to stick with your TCL approach and adapt the event handling to suit.
Of course I don’t have your code in front of me, so this may be off base.