< Previous PageNext Page > Hide TOC

Displaying a Contextual Menu

The Application Kit interprets right-mouse-down events and left-mouse-down events modified by the Control key as commands to display a contextual menu for the clicked view. Your view subclasses have several alternative approaches for displaying a contextual menu. If the view’s menu is to remain unchanged regardless of context, you can do one of three simple procedures:

After you complete any of these procedures, the Application Kit displays the contextual menu whenever the user left-Control-clicks or right-clicks the view. Note that the Application Kit automatically also validates the menu items of contextual menus, unless you request it not to.

However, you might want the view’s contextual menu to change based on where the mouse click occurs in the view or on the current state of the view; you may want to add, delete, enable, or disable menu items or change some item attributes to reflect the current context. There is more than one way to accomplish this, but a good approach is to override the defaultMenu and menuForEvent: methods of NSView. In the former method implementation, create and return an NSMenu object that is the “base” contextual menu, suitable for most contexts. Be sure to create menu items for the menu that have all necessary attributes (including action selector and possibly target object). Listing 1 shows how you might do this.

Listing 1  Returning the default menu

+ (NSMenu *)defaultMenu {
    NSMenu *theMenu = [[[NSMenu alloc] initWithTitle:@"Contextual Menu"] autorelease];
    [theMenu insertItemWithTitle:@"Beep" action:@selector(beep:) keyEquivalent:@"" atIndex:0];
    [theMenu insertItemWithTitle:@"Honk" action:@selector(honk:) keyEquivalent:@"" atIndex:1];
    return theMenu;
}

For contextual-menu events, the Application Kit invokes the menuForEvent: method if your view subclass implements it. In your implementation of this method, test for a certain condition (event type, mouse location, view state, and so on) and if that condition holds modify and return the default menu. Otherwise, return the default menu unchanged. Listing 2 gives an example that tests for a mouse click in a certain area and returns a modified contextual menu if that test holds true.

Listing 2  Displaying a dynamically modified contextual menu

- (NSMenu *)menuForEvent:(NSEvent *)theEvent {
    NSPoint curLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
    NSRect magic_square = NSMakeRect(0.0, 0.0, 10.0, 10.0);
 
    if ([self mouse:curLoc inRect:magic_square]) {
        NSMenu *theMenu = [[self class] defaultMenu];
        [theMenu insertItemWithTitle:@"Wail" action:@selector(wail:) keyEquivalent:@"" atIndex:[theMenu numberOfItems]-1];
        return theMenu;
    }
    return [[self class] defaultMenu];
}

If you want your view to display a contextual menu in response to events other than right-mouse clicks and left-mouse-Control clicks, you can directly handle the event message in the appropriate NSResponder method. For example, if you want users to be able to left-click an image view to get a menu of export options, you would override the mouseDown: method. In your implementation of the method, create a menu and then invoke the NSMenu class method popUpContextMenu:withEvent:forView:, passing in the event object related to the mouse-down event and the view owning the contextual menu. Listing 3 illustrates this approach.

Listing 3  Displaying a contextual menu upon receiving a left-mouse event

- (void)mouseDown:(NSEvent *)theEvent {
 
    NSMenu *theMenu = [[[NSMenu alloc] initWithTitle:@"Contextual Menu"] autorelease];
    [theMenu insertItemWithTitle:@"Beep" action:@selector(beep:) keyEquivalent:@"" atIndex:0];
    [theMenu insertItemWithTitle:@"Honk" action:@selector(honk:) keyEquivalent:@"" atIndex:1];
 
    [NSMenu popUpContextMenu:theMenu withEvent:theEvent forView:self];
}

Contextual menus, including any menu you pop up with popUpContextMenu:withEvent:forView:, automatically insert menu items from any contextual menu plug-ins that the user has installed into the menu. A contextual menu plug-in, which is CFPlugIn bundle installed in a Library/Contextual Menu Items directory at the appropriate level of the system, enables applications and other forms of software to extend the list of commands found on contextual menus such as the Finder’s. The applications do not have to be running for their items to appear. If you are trying to programmatically display a menu, you might not want those items to appear. The preferred approach for programmatically displaying a non-contextual menu is to create an NSPopUpButtonCell object, set its menu, and then call send a attachPopUpWithFrame:inView: message to the pop-up button cell.

Note: For information on how to create a CFPlugIn plug-in, see Plug-ins. For information on the Carbon Menu Manager functions you must implement for a contextual menu plug-in, see Menu Manager Reference.



< Previous PageNext Page > Hide TOC


© 2001, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-06-26)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.