Drag and Drop Reordering of NSTableView’s Rows

×

This post was originally published in 2009
It may contain stale & outdated information. Or it may have grown more awesome with age, like the author.

I just had to re-implement drag-and-drop-reordering of Slider cells. I was lucky enough to find my post on the Cocoa-dev list – I just had to copy-paste the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#define MyPrivateTableViewDataType @"NSMutableDictionary"
 
- (void)awakeFromNib {
[table registerForDraggedTypes:[NSArray arrayWithObject:MyPrivateTableViewDataType]];
}
 
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexestoPasteboard:(NSPasteboard*)pboard{
 // Copy the row numbers to the pasteboard.
 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
 
[pboard declareTypes:[NSArray arrayWithObject:MyPrivateTableViewDataType] owner:controller];
 
 [pboard setData:data forType:MyPrivateTableViewDataType];
 return YES;
}
 
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op{
 // Add code here to validate the drop
 NSLog(@"validate Drop");
 return NSDragOperationEvery;
}
 
- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info row:(int)to dropOperation:(NSTableViewDropOperation)operation{
 
//this is the code that handles dnd ordering - my table doesn't need to accept drops from outside! Hooray!
 NSPasteboard* pboard = [info draggingPasteboard];
 NSData* rowData = [pboard dataForType:MyPrivateTableViewDataType];
 
NSIndexSet* rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:rowData];
 
 int from = [rowIndexes firstIndex];
 
NSMutableDictionary *traveller = [[controller arrangedObjects] objectAtIndex:from];
 
 [traveller retain];
   int length = [[controller arrangedObjects] count];
   NSMutableArray *replacement = [NSMutableArray new];
 
   int i;
 for (i = 0; i <= length; i++){
       if(i == to){
         if(from > to){
         [controller insertObject:traveller atArrangedObjectIndex:to];
         [controller removeObjectAtArrangedObjectIndex:from+1];
         }
         else{
             [controller insertObject:traveller atArrangedObjectIndex:to];
             [controller removeObjectAtArrangedObjectIndex:from];
         }
     }
   }
}

Posting replies to the lists helps more than just the receiver – keep in mind that source code can be lost. Time is saved when tedious sections can be copy-pasted in during rewriting!

Comments (2) | Trackback