Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTableView and NSOutlineView drag-and-drop

I have an NSTableView and an NSOutlineView, both with their content provided by bindings, that I'd like to have some drag-and-drop functionality:

  • Drag rows from Table A onto a row of Outline B, where they will be copied into a data structure which the row in Outline B represents.

  • Drag a row from Outline B onto another row in Outline B, which will copy the data represented by the first row into the data represented in the second row.

I've read Apple's drag-and-drop documentation and gotten just about nowhere. It doesn't really seem to apply to what I need to do. What am I missing?

like image 360
Rich Catalano Avatar asked Mar 16 '09 05:03

Rich Catalano


3 Answers

The page you linked to is pretty clear about what you need to do. In table A's data source, implement registerForDraggedTypes: and tableView:writeRowsWithIndexes:toPasteboard: to put some private TableAPasteboardType data on the pasteboard.

In outline B's data source, implement the same two methods and put some private OutlineBPasteboardType data on the pasteboard.

Finally, implement tableView:validateDrop:proposedRow:proposedDropOperation: and tableView:acceptDrop:row:dropOperation: to check the pasteboard for either TableAPasteboardType or OutlineBPasteboardType and make the appropriate changes to your bound model, depending.

It's pretty straightforward once you just plow in and do it.

like image 147
Jim Puls Avatar answered Nov 04 '22 09:11

Jim Puls


You need a data source—AFAIK, you can't make this happen with Bindings alone.

The unfinished Adium Xtras Creator, which is under the BSD license, includes an array controller that you can set as the data source to get drag-and-drop in a Bindings-powered table view.

This requirement may not apply to NSOutlineView and NSTreeController. I haven't tried that.

like image 42
Peter Hosey Avatar answered Nov 04 '22 11:11

Peter Hosey


In MacOS 10.7 some new protocols were added to implement this.

There is a lack of documentation for tables at the moment but you can find some nice examples:

  • DragNDropOutlineView
  • SourceView
  • TableViewPlayground

For NSTableViwew the Protocol NSTableViewDataSource defines the following methods:

  • (BOOL)tableView:writeRowsWithIndexes:toPasteboard:
  • tableView:validateDrop:proposedRow:proposedDropOperation:
  • tableView:acceptDrop:row:dropOperation:

For NSOutlineView the Protocol NSOutlineViewDataSource defines the following methods:

  • (BOOL)outlineView:writeItems:toPasteboard:
  • (NSDragOperation)outlineView:validateDrop:proposedItem:proposedChildIndex:
  • (BOOL)outlineView:acceptDrop:item:childIndex:

These are the minimum requirements to implement for each view type. The use cases are quite similar.

  1. If the toPasteboard: method returns YES, the drag is started.
  2. The validateDrop: method controls which target node is allowed by updating the marker in the view
  3. Return YES for the acceptDrop: method if the drop was successful

This lead to two sub-usecases you have to manage. The first one is a drag & drop within the same view or the same operation between two views. Additionally you may distinguish between move, copy or delete operations. A nice example is how the breakpoints work with drag & drop in Xcode.

The tableView has some additional methods to customize drag & drop, but the ones I mentioned are the key methods to get it working.

like image 5
Stephan Avatar answered Nov 04 '22 09:11

Stephan