Search code examples
objective-cswiftmacoscocoanstableview

Preventing contextual menu showing on specific cell in a view based NSTableView


Is there any way of preventing a contextual menu (and the associated selection "ring" around the cell view) being shown when right-clicking on a specific cell in a view-based NSTableView ?

I'm not talking about disabling the right-click action on ALL the cells, but only on specific ones.

I've obviously tried all the delegate methods dealing with selection changes but none works because the selectedRow property is not changing, only the clickedRow does. So basically I'm looking for something equivalent to

func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool 

but for the clicked row not the selected row.

Note: the questions is about NSTableView on macOS and not the UITableViewon iOS.


Solution

  • I've found a way to do what I wanted, although looks like a little to involved for something that should be simpler. So I welcome any simpler solution.

    It can be done by subclassing NSTableView :

    class MyTableView : NSTableView {
    
        override func menu(for event: NSEvent) -> NSMenu? {
            let clickedPoint = self.convert(event.locationInWindow, from: nil)
            let row = self.row(at: clickedPoint)
    
            // no contextual menu for the last row
            return row == self.numberOfRows - 1 ? nil : super.menu(for: event)
        }
    } 
    

    This example prevents the contextual menu to be shown for the last row, but a more generic solution could be implemented by adding a delegate with a method to return the menu for each cell.