FROM : Jonathan Dann
DATE : Sun May 18 22:33:41 2008
On 18 May 2008, at 20:57, Charles Srstka wrote:
> Lately, I've been trying to update my stodgy old ways and try to
> incorporate some of the new technologies Cocoa has picked up over
> the years when starting new projects (my main app has had to be
> compatible with older OS X versions, so I haven't had much
> opportunity to jump into the world of bindings prior to now). One of
> these is NSTreeController. Unfortunately, I'm having a bit of
> trouble using figuring out how to do what I want with it.
>
> 1. The order of the objects in my (non-Core Data) data model is
> sometimes important, so rather than using the tree controller to add
> objects, I have been adding them manually by calling the appropriate
> -insertObject:in<key>atIndex: methods. Okay, that works pretty well,
> and the objects show up in the NSOutlineView. However, I'd like to
> select the objects after I insert them. Now, I know where these
> objects are in the model, but since the order of the objects in the
> outline view might be different due to the user clicking on one
> column header or another to sort, and since the index paths sent to
> the tree controller's -setSelectedIndexPaths: method seem to be
> based on the interface, not the model, I don't know exactly where
> these objects are in order to select them. NSTreeController appears
> to have no -indexPathForObject: method or anything similar - does
> anyone know a way around this?
>
> 1a. At first I thought that since I am making a sibling to the
> currently selected object, I could just get the parent's index path
> via [[treeController selectionIndexPath]
> indexPathByRemovingLastIndex], then get the node at that index path
> and iterate through its -childNodes until I find the one whose -
> representedObject is the correct model object, but there doesn't
> seem to be any way to get NSTreeController to give the node (or the
> model object, for that matter) for an index path. Does anyone else
> find this a little bizarre
To have an indexPathForObject method you need this:
- (NSArray *)rootNodes;
{
return [[self arrangedObjects] childNodes];
}
// this is a depth-first search
- (NSArray *)flattenedNodes;
{
NSMutableArray *mutableArray = [NSMutableArray array];
for (NSTreeNode *node in [self rootNodes]) {
[mutableArray addObject:node];
if (![[node valueForKey:[self leafKeyPath]] boolValue])
[mutableArray addObjectsFromArray:[node valueForKey:@"descendants"]];
}
return [[mutableArray copy] autorelease];
}
- (NSTreeNode *)treeNodeForObject:(id)object;
{
NSTreeNode *treeNode = nil;
for (NSTreeNode *node in [self flattenedNodes]) {
if ([node representedObject] == object) {
treeNode = node;
break;
}
}
return treeNode;
}
- (NSIndexPath *)indexPathToObject:(id)object;
{
return [[self treeNodeForObject:object] indexPath];
}
They're all separate methods as I have quite a few extensions on
NSTreeController!
>
> 2. Okay, so I've got my objects displaying in an NSOutlineView, and
> now I'd like to add a search feature. Rather than eliminating the
> options that don't match, what I want to do is find the object,
> expand all its ancestors in the outline view so it's visible, and
> select it. Finding the model object is easy, and doing the rest
> *would* be easy enough if I weren't using NSTreeController - just
> climb the family tree, use -rowForItem: for each, expand it, and
> then use -rowForItem: to get the object and select it. Of course,
> with NSTreeController we have all these NSTreeNode objects instead
> of the actual objects themselves in the outline view, so -
> rowForItem: won't work. Is there any way to find the rows for the
> various nodes in the family tree of an object without resorting to
> just iterating through every row in the outline view? Any way to get
> the tree node for a given model object?
Now you have a treeNode for object you can as the NSOutlineView to
expand that item (the NSTreeNode) using -expandItem:
Ive recently written two posts on NSTreeController, the first is non-
Core Data the second is with core data but the sample project has a
load of extensions that let you do what you want to do. They're at
http://jonathandann.wordpress.com/2008/04/06/using-nstreecontroller/
and
http://jonathandann.wordpress.com/2008/05/13/nstreecontroller-and-core-data-sorted/
Hope this helps
Jon
DATE : Sun May 18 22:33:41 2008
On 18 May 2008, at 20:57, Charles Srstka wrote:
> Lately, I've been trying to update my stodgy old ways and try to
> incorporate some of the new technologies Cocoa has picked up over
> the years when starting new projects (my main app has had to be
> compatible with older OS X versions, so I haven't had much
> opportunity to jump into the world of bindings prior to now). One of
> these is NSTreeController. Unfortunately, I'm having a bit of
> trouble using figuring out how to do what I want with it.
>
> 1. The order of the objects in my (non-Core Data) data model is
> sometimes important, so rather than using the tree controller to add
> objects, I have been adding them manually by calling the appropriate
> -insertObject:in<key>atIndex: methods. Okay, that works pretty well,
> and the objects show up in the NSOutlineView. However, I'd like to
> select the objects after I insert them. Now, I know where these
> objects are in the model, but since the order of the objects in the
> outline view might be different due to the user clicking on one
> column header or another to sort, and since the index paths sent to
> the tree controller's -setSelectedIndexPaths: method seem to be
> based on the interface, not the model, I don't know exactly where
> these objects are in order to select them. NSTreeController appears
> to have no -indexPathForObject: method or anything similar - does
> anyone know a way around this?
>
> 1a. At first I thought that since I am making a sibling to the
> currently selected object, I could just get the parent's index path
> via [[treeController selectionIndexPath]
> indexPathByRemovingLastIndex], then get the node at that index path
> and iterate through its -childNodes until I find the one whose -
> representedObject is the correct model object, but there doesn't
> seem to be any way to get NSTreeController to give the node (or the
> model object, for that matter) for an index path. Does anyone else
> find this a little bizarre
To have an indexPathForObject method you need this:
- (NSArray *)rootNodes;
{
return [[self arrangedObjects] childNodes];
}
// this is a depth-first search
- (NSArray *)flattenedNodes;
{
NSMutableArray *mutableArray = [NSMutableArray array];
for (NSTreeNode *node in [self rootNodes]) {
[mutableArray addObject:node];
if (![[node valueForKey:[self leafKeyPath]] boolValue])
[mutableArray addObjectsFromArray:[node valueForKey:@"descendants"]];
}
return [[mutableArray copy] autorelease];
}
- (NSTreeNode *)treeNodeForObject:(id)object;
{
NSTreeNode *treeNode = nil;
for (NSTreeNode *node in [self flattenedNodes]) {
if ([node representedObject] == object) {
treeNode = node;
break;
}
}
return treeNode;
}
- (NSIndexPath *)indexPathToObject:(id)object;
{
return [[self treeNodeForObject:object] indexPath];
}
They're all separate methods as I have quite a few extensions on
NSTreeController!
>
> 2. Okay, so I've got my objects displaying in an NSOutlineView, and
> now I'd like to add a search feature. Rather than eliminating the
> options that don't match, what I want to do is find the object,
> expand all its ancestors in the outline view so it's visible, and
> select it. Finding the model object is easy, and doing the rest
> *would* be easy enough if I weren't using NSTreeController - just
> climb the family tree, use -rowForItem: for each, expand it, and
> then use -rowForItem: to get the object and select it. Of course,
> with NSTreeController we have all these NSTreeNode objects instead
> of the actual objects themselves in the outline view, so -
> rowForItem: won't work. Is there any way to find the rows for the
> various nodes in the family tree of an object without resorting to
> just iterating through every row in the outline view? Any way to get
> the tree node for a given model object?
Now you have a treeNode for object you can as the NSOutlineView to
expand that item (the NSTreeNode) using -expandItem:
Ive recently written two posts on NSTreeController, the first is non-
Core Data the second is with core data but the sample project has a
load of extensions that let you do what you want to do. They're at
http://jonathandann.wordpress.com/2008/04/06/using-nstreecontroller/
and
http://jonathandann.wordpress.com/2008/05/13/nstreecontroller-and-core-data-sorted/
Hope this helps
Jon
| Related mails | Author | Date |
|---|---|---|
| Charles Srstka | May 18, 21:57 | |
| Jonathan Dann | May 18, 22:33 | |
| Charles Srstka | May 18, 22:57 | |
| Jonathan Dann | May 19, 00:47 | |
| Charles Srstka | May 19, 00:57 | |
| Jonathan Dann | May 19, 01:44 | |
| Charles Srstka | May 19, 01:51 |






Cocoa mail archive

