NSOutlineView Drag And Drop NSTreeController
NSOutlineView Drag And Drop NSTreeController
- Subject: NSOutlineView Drag And Drop NSTreeController
- From: Arved von Brasch <email@hidden>
- Date: Thu, 25 May 2006 23:17:13 +1000
Hello Cocoa Dev List,
I've worked around many of the NSTreeController problems I'd
encountered previously in a different situation. I did this by
subclassing NSTreeController and rewriting many of the routines that
were causing me grief, as well as making use of the sample code in
DragAndDropOutlineEdit. I now have drag and drop working quite
well. I have noticed some unusual behaviour that I can't seem to
find a way to work around. My NSOutlineView supports drag and drop
ordering (similar to http://allusions.sourceforge.net/articles/
treeDragPart2.php) and NSURL drags from other applications. Drag and
drop ordering works great (at least I haven't found any bugs).
Accepting URL causes strange behaviour:
My NSOutlineView will not update its display every second time a URL
is dragged onto the root node (ie, no parent) when the application is
in the background. I have tried reloadData and reloadItem.
ReloadItem actually causes the drag to be only partially successful,
with the following errors:
*** Assertion failure in -[AGURLDragOutlineView
reloadItem:reloadChildren:], TableView.subproj/NSOutlineView.m:1058
*** Canceling drag because exception
'NSInternalInconsistencyException' (reason 'Invalid parameter not
satisfying: item') was raised during a dragging session
In the situation where the error is thrown, the reload item is nil.
The documentation doesn't mention not passing in nil.
AGURLDragOutlineView is my NSOutlineView subclass, that redefines
dragImageForRowsWithIndexes:tableColumns:event:offset: to have a nice
drag image.
I am using a CoreData backing store, but I don't think that's the
problem. The part I can't understand is why it only happens every
second drag. Here is the relevant code from acceptDrop: in my
NSTreeController subclass / OutlineView DataSource. reorderNode: is
a routine that normalises the "order" attributes of each child object
to be factors of 10. setSelectedObjects is modified from Wil
Shipley's NSTreeController's category.
NSManagedObject *draggedDownloadLink // Set in writeItems if this is
a local drag
if ([info draggingSource] == nil) {
draggedDownloadLink = [NSEntityDescription
insertNewObjectForEntityForName: @"AGDownloadLink"
inManagedObjectContext: [self managedObjectContext]];
NSURL *url = [NSURL URLFromPasteboard: [info draggingPasteboard]];
[draggedDownloadLink setValue: [url absoluteString] forKey:
@"address"];
if (parentItem == nil) {
if (index == NSOutlineViewDropOnItemIndex) {
// Sort Descriptors are not by order (attach to end of order list)
unsigned int count = [[self arrangedObjects] count];
[draggedDownloadLink setValue: [NSNumber numberWithInt: count *
10] forKey: @"order"];
[self insertObject: draggedDownloadLink
atArrangedObjectIndexPath: [NSIndexPath indexPathWithIndex: count]];
}
else {
// Sorting by order
[draggedDownloadLink setValue: [NSNumber numberWithInt: (index *
10) - 5] forKey: @"order"];
[self insertObject: draggedDownloadLink
atArrangedObjectIndexPath: [NSIndexPath indexPathWithIndex: index]];
[self reorderNode: nil];
}
}
else {
[draggedDownloadLink setValue: parentItem forKey: @"parent"];
[draggedDownloadLink setValue: [parentItem valueForKey: @"name"]
forKey: @"name"];
if (index == NSOutlineViewDropOnItemIndex) {
// Sort Descriptors are not by order (attach to end of order list)
unsigned int count = [[self outlineItemForObject: parentItem]
count];
[draggedDownloadLink setValue: [NSNumber numberWithInt: count *
10] forKey: @"order"];
[self insertObject: draggedDownloadLink
atArrangedObjectIndexPath: [[self arrangedIndexPathForObject:
parentItem] indexPathByAddingIndex: count]];
}
else {
// Sorting by order
[draggedDownloadLink setValue: [NSNumber numberWithInt: (index *
10) - 5] forKey: @"order"];
[self insertObject: draggedDownloadLink
atArrangedObjectIndexPath: [[self arrangedIndexPathForObject:
parentItem] indexPathByAddingIndex: index]];
[self reorderNode: parentItem];
}
}
[self rearrangeObjects];
[self setSelectedObjects: [NSArray arrayWithObject:
draggedDownloadLink]];
//[ov reloadData];
}
Any ideas on why this display problem only strikes every second drag
when the application isn't front most? Is there another way to force
the NSOutlineView to redisplay the renegade item?
Cheers,
Arved von Brasch
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden