1

I'm implementing drag and drop in a table view, and the problem I'm having is that the drag image is always based on the column where the drag started, but I want to use the image from the first column.

I looked at Apple's TableViewPlayground sample, where the "Complex OutlineView Window" does what I want, but I can't figure out what I'm doing different in terms of setting up the drag.

I put together a simple example at https://github.com/Uncommon/TableTest - if you drag from the second column where it says "stuff", then it looks like you're dragging the word "stuff". What I want is to have the drag image always come from the first column (with the icon and name) regardless of which column you drag from.

In my data source I implement tableView(tableView:,pasteboardWriterForRow:) to enable dragging, but that doesn't include information about what column the drag started in. What am I missing from the example app to make this work?

Uncommon
  • 3,323
  • 2
  • 18
  • 36

3 Answers3

4

The accepted answer didn't work for me. Instead, I had to implement the following optional function in NSTableViewDataSource:

func tableView(_ tableView: NSTableView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forRowIndexes rowIndexes: IndexSet) {
        // Or whatever cell you want as the drag image
        let cell = tableView.view(atColumn: 0, row: rowIndexes.first!, makeIfNecessary: false) as? NSTableCellView
        session.enumerateDraggingItems(options: .concurrent, for: nil, classes: [NSPasteboardItem.self], searchOptions: [:]) {(draggingItem, idx, stop) in
            if let cell = cell {
                let rect = cell.bounds
                let drag = session.draggingLocation
                // You can customize the image starting point and size here
                draggingItem.setDraggingFrame(NSRect(x: drag.x, y: drag.y, width: rect.width, height: rect.height), contents: cell.draggingImageComponents)
                draggingItem.imageComponentsProvider = {
                    return cell.draggingImageComponents
                }
            }
        }
    }

Credit goes to this answer for providing much of this solution.

alanbi
  • 171
  • 1
  • 8
1

In response to why dragImageForRows(with:tableColumns:event:offset:) didn't work:

From the Apple documentation:

Note: To support multi-item drags, it is highly recommended to implement the delegate method tableView:pasteboardWriterForRow: instead. Using that method will cause this method to not be called.

S Jensen
  • 17
  • 5
0

NSTableView drags the column where the drag started, NSOutlineView drags the outline column. If you want to change the image, subclass NSTableView and override dragImageForRows(with:tableColumns:event:offset:).

Willeke
  • 14,578
  • 4
  • 19
  • 47
  • Thanks! I should have trie an outline view in my test. I just assumed they were the same in this respect. – Uncommon Dec 18 '17 at 15:54