3

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?

Dropbox Popover Table WIth Highlighted Cell

Lucas Derraugh
  • 6,929
  • 3
  • 27
  • 43
mixtly87
  • 1,675
  • 15
  • 32

2 Answers2

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:

mouseover detection in NSTableView's NSCell?

AJ Venturella
  • 4,742
  • 4
  • 33
  • 62