I'm trying to create a tray popover app with table very similar to the one Dropbox has in it's popover view. There is a table of files and when you hover mouse over a table cell, cell will highlight and show additional controls. I'm not sure if NSTableView is suitable for this at all? Does anyone have any advice?
Asked
Active
Viewed 1,663 times
2 Answers
7
This would be an ideal use of NSTableView
. Using a view-based NSTableView, you'll be easily able to create the look of those cells (views). The highlight on mouse-over should be accomplishable if you add an NSTrackingArea
to the table view (scroll view might be better) with -[NSView addTrackingArea:]
, which gives you callbacks for -mouseMoved:
events. From that method you can use the locationInWindow
property on the NSEvent, and then use NSTableView's -rowAtPoint:
call to query which row you should change to display the hover event.

Lucas Derraugh
- 6,929
- 3
- 27
- 43
-
Are you suggesting putting a single tracking area on the table view, or separate tracking areas on each cell view? – sam Sep 29 '17 at 22:12
-
1@sam Single tracking area on the entire table view. You want to avoid adding multiple tracking areas if possible. It's probably much easier to maintain with 1 tracking area anyway. – Lucas Derraugh Oct 03 '17 at 20:15
-
1@sam Might want to actually do the scroll view instead of the entire table view. Not sure if it really matters much, but it's a smaller area to track. – Lucas Derraugh Oct 04 '17 at 17:05
0
As a possible amendment here, I had to do the following to make this work:
highlightedRow: MyCustomRow?
func viewWillAppear(){
configureTableHighlight()
}
func configureTableHighlight() {
let trackingArea = NSTrackingArea(rect: scrollView.frame, options: [.mouseMoved, .activeInKeyWindow, .inVisibleRect], owner: self, userInfo: nil)
scrollView.addTrackingArea(trackingArea)
}
override func mouseMoved(with event: NSEvent) {
let pointInTableView = tableView.convert(event.locationInWindow, to: nil)
let row = tableView.row(at: pointInTableView)
if row == -1 {
highlightedRow?.highlight = false
highlightedRow = nil
return
}
guard let view = tableView.view(atColumn: 0, row: row, makeIfNecessary: false) as? MyCustomRow else {
return
}
if(highlightedRow == view){
return
}
view.highlight = true;
highlightedRow?.highlight = false
highlightedRow = view;
}
This might depend on where you add the trackingView however.
Additional reference:

AJ Venturella
- 4,742
- 4
- 33
- 62