I\'ve got a simple, single-column, view-based NSTableView with items in it that can be dragged to reorder them. During drag and drop, I\'d like to make it so that a gap for the
I feel bizarre for doing this, but there's an extremely thorough answer in the queue here that appears to have been deleted by its author. In it, they provided the correct links to a working solution, which I feel need to be presented as an answer for someone else to take and run with, inclusive of them if they desire to do so.
From the documentation for NSTableView, the following caveats are tucked away for row animation effects:
Row Animation Effects
Optional constant that specifies that the tableview will use a fade for row or column removal. The effect can be combined with any NSTableViewAnimationOptions constant.
enum { NSTableViewAnimationEffectFade = 0x1, NSTableViewAnimationEffectGap = 0x2, };
Constants:
...
NSTableViewAnimationEffectGap
Creates a gap for newly inserted rows. This is useful for drag and drop animations that animate to a newly opened gap and should be used in the delegate method tableView:acceptDrop:row:dropOperation:.
Going through the example code from Apple, I find this:
- (void)_performInsertWithDragInfo:(id )info parentNode:(NSTreeNode *)parentNode childIndex:(NSInteger)childIndex {
// NSOutlineView's root is nil
id outlineParentItem = parentNode == _rootTreeNode ? nil : parentNode;
NSMutableArray *childNodeArray = [parentNode mutableChildNodes];
NSInteger outlineColumnIndex = [[_outlineView tableColumns] indexOfObject:[_outlineView outlineTableColumn]];
// Enumerate all items dropped on us and create new model objects for them
NSArray *classes = [NSArray arrayWithObject:[SimpleNodeData class]];
__block NSInteger insertionIndex = childIndex;
[info enumerateDraggingItemsWithOptions:0 forView:_outlineView classes:classes searchOptions:nil usingBlock:^(NSDraggingItem *draggingItem, NSInteger index, BOOL *stop) {
SimpleNodeData *newNodeData = (SimpleNodeData *)draggingItem.item;
// Wrap the model object in a tree node
NSTreeNode *treeNode = [NSTreeNode treeNodeWithRepresentedObject:newNodeData];
// Add it to the model
[childNodeArray insertObject:treeNode atIndex:insertionIndex];
[_outlineView insertItemsAtIndexes:[NSIndexSet indexSetWithIndex:insertionIndex] inParent:outlineParentItem withAnimation:NSTableViewAnimationEffectGap];
// Update the final frame of the dragging item
NSInteger row = [_outlineView rowForItem:treeNode];
draggingItem.draggingFrame = [_outlineView frameOfCellAtColumn:outlineColumnIndex row:row];
// Insert all children one after another
insertionIndex++;
}];
}
I'm unsure if it's really this simple, but it's at least worth inspection and outright refutal if it doesn't meet your needs.
Edit: see this answer's comments for the steps followed to the right solution. The OP has posted a more complete answer, which should be referred to by anyone looking for solutions to the same problem.