Reputation: 2146
I'm looking for a way to get right-clicked row index from NSTableView
but I can't find any delegate methods or class attributes for it. Any suggestion is appreciated.
Upvotes: 17
Views: 8282
Reputation: 2334
I had the same question but I also needed a solution that would work with multiple selected rows (because when multiple rows are selected and you right-click on one of them, NSTableView highlights all of them). Here's the property I added for this in a subclass of NSTableView:
var rightClickRowIndexes: IndexSet {
if clickedRow >= 0 {
return selectedRowIndexes.contains(clickedRow) ? selectedRowIndexes : IndexSet(integer: clickedRow)
} else {
return IndexSet()
}
}
Upvotes: 0
Reputation: 86035
If you want to get clicked row index on menu opening, the answer is NSTableView.clickedRow
. Anyway this property is available only in specific moments, and usually just -1
.
When is this index to be available? That's in NSMenuDelegate.menuWillOpen
method. So you conform the delegate and implement the method on your class, and access the clickedRow
property. It's done.
final class FileNavigatorViewController: NSViewController, NSMenuDelegate {
let ov = NSOutlineView() // Assumed you setup this properly.
let ctxm = NSMenu()
override func viewDidLoad() {
super.viewDidLoad()
ov.menu = ctxm
ctxm.delegate = self
}
func menuWillOpen(_ menu: NSMenu) {
print(outlineView.clickedRow)
}
}
Clicked row index is available until you click an item in the menu. So this also works.
final class FileNavigatorViewController: NSViewController {
let ov = NSOutlineView() // Assumed you setup this properly.
let ctxm = NSMenu()
let item1 = NSMenuItem()
override func viewDidLoad() {
super.viewDidLoad()
ov.menu = ctxm
ov.addItem(item1)
ov.target = self
ov.action = #selector(onClickItem1(_:))
}
@objc
func onClickItem1(_: NSObject?) {
print(outlineView.clickedRow)
}
}
I tested this on macOS Sierra (10.12.5).
Starting from OS X 10.11, Apple finally added a method to access clickedRow
easily. Just subclass NSTableView
and override this method and you'll get the clickedRow
as far as I experienced.
func willOpenMenu(menu: NSMenu, withEvent event: NSEvent)
This needs subclassing, but anyway, the cleanest and simplest way to access clickedRow
.
Also, there's a pairing method.
func didCloseMenu(menu: NSMenu, withEvent event: NSEvent?)
Upvotes: 7
Reputation: 18805
Just select row on right-click by implementing menuForEvent:
in NSTableView
subclass:
@implementation MyTableView
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
{
int row = [self rowAtPoint:[self convertPoint:theEvent.locationInWindow fromView:nil]];
if (row == -1)
return nil;
if (row != self.selectedRow)
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
return self.menu;
}
@end
Upvotes: 3
Reputation: 2792
Use the NSTableView method - (NSInteger)clickedRow
to get the index of the last clicked row. The returned NSInteger will be the index of the right clicked row.
You do not need to subclass NSTableView
for this solution. clickedRow
is also available on NSOutlineView
.
Upvotes: 23
Reputation: 18333
While I haven't done this, I am pretty sure you can by overriding NSView
's - (NSMenu*)menuForEvent:(NSEvent*)theEvent
. The example in this link does a point conversion to determine the index.
-(NSMenu*)menuForEvent:(NSEvent*)theEvent
{
NSPoint mousePoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
int row = [self rowAtPoint:mousePoint];
// Produce the menu here or perform an action like selection of the row.
}
Upvotes: 11