0

I have a table view where I would like to have a different context menu appear when right-clicking on a cell vs. when right-clicking on an area where there are no cells. I'm trying to do this using storyboards in the interface builder.

If I attach a menu to the NSTableView I can get a context menu to appear. However, if I attach a menu to the NSTableCellView I get the NSTableView's context menu rather than the menu I have attached to the NSTableCellView.

I know I could do all this via code by having one menu attached the the NSTableView and change it's contents based on the cell clicked but I believe I should be able to do this by attaching different menus to different views in the view heirachy.

Can this be done solely in interface builder?

act1292
  • 19
  • 6
  • Is `NSTableViewCell` the `NSTableCellView` or the `NSTextField`? – Willeke May 24 '22 at 23:15
  • Sorry - my bad. I was referring the the NSTableCellView - I have corrected my spelling. I have tried adding the menu to the NSTableCellView, NSTextField, and the NSTextFieldCell and none seem to show my menu. – act1292 May 25 '22 at 12:37
  • I did some poking around in the debugger and I found that the NSTableCellView's parent window has firstResponder set to the NSTableView - which would seem to explain why it's context menu is always displayed rather than the one set up in the NSTableCellView. I haven't figured out yet how to correct this. – act1292 May 25 '22 at 13:38
  • `NSTableView` overrides `hitTest:` and returns `self` instead of the clicked subview. I think the easiest solution is subclassing `NSTableView` and overriding the `menu` property. – Willeke May 25 '22 at 13:58

1 Answers1

0

As per Willeke's suggestion I sub-classed the NSTableView and added the the following code to the menu property:

- (NSMenu*) menu
{
    if (self.clickedRow == -1 || self.clickedColumn == -1) return super.menu;

    NSTableCellView *clickedCell = [self viewAtColumn:self.clickedColumn row:self.clickedRow makeIfNecessary:FALSE];
    
    if (clickedCell != nil) return clickedCell.menu;

    return self.menu;
}

With this implementation I get the behavior I was looking for.

act1292
  • 19
  • 6