Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reorder rows in NSTableView?

I just can't seem to find a quick and easy way to simply reorder rows in an NSTableView (the OSX one, not iOS). On iOS I would use these two delegate methods:

// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    MyObject *obj = [model objectAtIndex:fromIndexPath.row];
    [model removeObject:obj]; 
    [model insertObject:obj atIndex:toIndexPath.row];
}

Is there any quick and easy way to do something similar for an NSTableView in Cocoa? So far I have only found some extensive code samples using the pasteboard, which seemed pretty much like an overkill for a simple reordering functionality to me.

like image 330
optz Avatar asked Feb 08 '23 16:02

optz


1 Answers

Thanks guys, this is what worked for me perfectly now:

//add line somewhere in your code
#define MyPrivateTableViewDataType @"MyPrivateTableViewDataType"

//add line in your viewDidLoad: method
[self.tableView registerForDraggedTypes:[NSArray arrayWithObject:MyPrivateTableViewDataType]

these data source methods can be copied to the code without any alteration:

// drag operation stuff
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard {
    // Copy the row numbers to the pasteboard.
    NSData *zNSIndexSetData = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];

    [pboard declareTypes:[NSArray arrayWithObject:MyPrivateTableViewDataType] owner:self];

    [pboard setData:zNSIndexSetData forType:MyPrivateTableViewDataType];

    return YES;
}

- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id )info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)op {
    // Add code here to validate the drop
    return NSDragOperationEvery;
}

this part needs to implement the custom model, just like in my question above:

- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id )info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation {

    NSPasteboard* pboard = [info draggingPasteboard];
    NSData* rowData = [pboard dataForType:MyPrivateTableViewDataType];
    NSIndexSet* rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:rowData];
    NSInteger dragRow = [rowIndexes firstIndex];





    if (dragRow < row) {
        [model insertObject:[model objectAtIndex:dragRow] atIndex:row];
        [model removeObjectAtIndex:dragRow];

        [aTableView noteNumberOfRowsChanged];
        [aTableView moveRowAtIndex:dragRow toIndex:row-1];

    }else {
        ModelObj *obj = [model objectAtIndex:dragRow];
        [model removeObjectAtIndex:dragRow];
        [model insertObject:obj atIndex:row];

        [aTableView noteNumberOfRowsChanged];
        [aTableView moveRowAtIndex:dragRow toIndex:row];
    }

    return YES;
}
like image 169
optz Avatar answered Feb 16 '23 02:02

optz