Search code examples
objective-ccocoacontextmenunsoutlineviewnsmenu

Contextual menu on only certain items in a "Source List"


I have a window with a Source List (NSOutlineView). My source list has just two levels. Level one is header and level two is data. I want to have a contextual menu on some of the data cells. Not all.

First, I try to attach a menu on the table cell view who represents the data cell -> nothing happens.

Second, I attach a menu on the Outline View in IB -> the contextual menu opens on each cells (header and data). I search for stopping the opening of the menu, but I don't find anything.

Do you have some ideas ?

Thank you

OS X 10.8.2 Lion, Xcode 4.5.2, SDK 10.8


Solution

  • If you subclass NSOutlineView, you can override menuForEvent: to return a menu only if the user clicked on the correct row. Here's an example:

    - (NSMenu *)menuForEvent:(NSEvent *)event;
    {
        //The event has the mouse location in window space; convert it to our (the outline view's) space so we can find which row the user clicked on.
        NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
        NSInteger row = [self rowAtPoint:point];
    
        //If the user did not click on a row, or is not exactly one level down from the top level of hierarchy, return nil—that is, no menu.
        if ( row == -1 || [self levelForRow:row] != 1 )
            return nil;
    
        //Create and populate a menu.
        NSMenu *menu = [[NSMenu alloc] init];
        NSMenuItem *delete = [menu addItemWithTitle:NSLocalizedString( @"Delete", @"" ) action:@selector(delete:) keyEquivalent:@""];
    
        [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
    
        //Set the Delete menu item's represented object to the clicked-on item. If the user chooses this item, we'll retrieve its represented object so we know what to delete.
        [delete setRepresentedObject:[self itemAtRow:row]];
    
        return menu;
    }
    

    This assumes we're compiling with ARC, so you don't need to autorelease the menu object being created.