Opening a gap in NSTableView during drag and drop

前端 未结 4 943
误落风尘
误落风尘 2021-01-30 11:52

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

4条回答
  •  既然无缘
    2021-01-30 12:17

    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.

提交回复
热议问题