View Full Version : nstreecontroller rearrangeobjects bug?

Jun 30, 2009, 12:02 PM
Hi folks

I have my own NSTreeController and NSOutlineView subclass, with a coredata backend. I can drag and drop objects around and each object knows it position.

When I change something (add/remove/drag&drop) the position is correctly updated, but the view is not. [myTreeController rearrangeobjects] is called, but only the top group (with parent == nil) is automatically rearranged. All the subgroups are not.

My question is this. Did I overlook something, or is this a bug with NSTreeController? Does this problem sound familiar to you? NSTreeController has had a lot of bugs in the past, from what I can tell. Running 10.5.7 on intel.

thanks for reading

Aug 14, 2009, 12:23 PM
I am trying to fix this bug once more, but with no luck so far. Maybe one of you sees the problem?

The bug is this. Adding a new node to a folder, when one of the nodes of that folder is selected, will add a new node to the tree with the correct value for the position. However, in the NSOutlineView the node is not correctly positioned in the tree.

-(id) addManagedObject:(NSString *) entityName {
// First get selected object, then add new object. this returns the correct user selection!
id parent = ([[self selectedObjects] count] > 0) ? [[self selectedObjects] objectAtIndex:0] : nil;

int position = def_newNodePosition;
if (parent && ![parent isFolder]) { //parent is a node itself, use its parent instead. rootnode = nil and a folder <if (![parent isFolder])> is true for rootnode
position = [[parent valueForKey:@"position"] intValue] + def_incrementNodePosition;
parent = [parent parent];
return [self addManagedObject:entityName toParent:parent atPosition:position];

-(id) addManagedObject:(NSString *) entityName toParent:(id) parent atPosition:(int) position {
id newNode = [NSEntityDescription insertNewObjectForEntityForName:entityName
inManagedObjectContext:[self managedObjectContext]]; //Add a new node into the tree.
[newNode setParent:parent];
[newNode setValue:[NSNumber numberWithInt:position]
[self resetPositionsFor:parent];
[[self managedObjectContext] processPendingChanges]; //to speed up display of new node
return newNode;

#pragma mark (re)order data
-(void) resetPositionsFor:(id)node {
if (node) {
[node resetPositions];
} else {
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Group"
inManagedObjectContext:[self managedObjectContext]];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
[request setIncludesSubentities:YES];
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"parent == nil"]];
[request setPredicate:pred];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"position"
[request setSortDescriptors:[NSArray arrayWithObject:sort]];
NSError *error = nil;
NSArray *ordered = [[self managedObjectContext] executeFetchRequest:request
[request release];
//reset position of children
for (int i = 0; i < [ordered count]; i++) {
id item = [ordered objectAtIndex:i];
[item setValue:[NSNumber numberWithInt:i*def_positioninterval]
[item resetPositions]; //reset positions of childrenchildren of this child
[sort release];

//re-order and reload
[self rearrangeObjects];
[myOutlineView reloadData];