Sunday, February 26, 2006

In Cocoa, an NSMenu object can be set to allow clients to enable or disable menu items, or to have Cocoa itself enable or disable menu items based on whether or not the control that has focus (known in Cocoa as the firstResponder) can handle the action that selecting the menu item would invoke. In otherwords, if there is an object in the responder chain that can handle a cut: message, then the Cut menu item will be enabled, otherwise it will not. That is, as long as I map the menu item to that cut: action, like this:

[menuItem setAction:@selector(cut:)];

This implies the following strategy. When creating the menu item concrete implementation, check the menu item class, and if it is cut, copy, paste, or clear, do the following:

-- invoke the setAction method on the NSMenuItem object, passing the appropriate selector (as in the above code)
-- call a method on the containing item (an NSMenu) to tell it that it should handle the enabling and the disabling of menu items (presumably, this will be the Edit menu, but it may not). Otherwise, call a method to tell Cocoa we are going to handle the enabling and disabling of the menu items. Code for this step looks like the following (in my implementation, that is):

if (menuImpl) {
NSMenu *parentMenu = menuImpl->GetMenu();

if (parentMenu && !setAction) {
[parentMenu setAutoenablesItems: YES];
return PR_SUCCESS;

setAction is a flag that was set if the menu item class was one corresponding to the selectors cut:, copy:, paste:, delete:, or selectAll:. setAutoenablesItems: YES tells the menu it needs to manage the enabling and disabling of the menu item. If this is invoked on the menu, any calls made from JavaScript to enable or disable menu items in this menu will silently fail.

There is a bit of an issue regarding placing other items in a menu that uses setAutoenablesItems: in this way. There may be menu items that do not correspond to this paradigm, e.g., they have a selector that does not get handled by anyone, thus they would be perpetually disabled. The way to avoid this will be to keep all items out of menus like this. This strategy will work if the menu is restricted containing menu items corresponding to the above-mentioned selectors, as is the case with the Edit menu (at least, as I have implemented it in the sample application).


Post a Comment

<< Home