diff --git a/ChangeLog b/ChangeLog index 357b49a29..4fcea20f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2013-08-19 Fred Kiefer + + * Headers/AppKit/NSTreeController.h, + * Headers/AppKit/NSTreeNode.h: Add method declarations to these files. + * Headers/AppKit/AppKit.h, + * Source/GNUmakefile: Include new files. + * Source/NSObjectController.m (+initialize, -selection): Get basic + binding example working. + * Source/NSTreeController.m: Minimal implementation. + * Source/NSTreeNode.m: Full implementation of this class. + 2013-08-17 Fred Kiefer * Headers/AppKit/NSStatusBar.h, @@ -6,7 +17,7 @@ * Source/GNUmakefile: Add new class. * Headers/AppKit/NSStatusItem.h, * Source/NSStatusItem.m: - Add fill in code by Nikolaus Schaller . + Add code by Nikolaus Schaller , reformatted and simplified. 2013-08-12 Lubos Dolezel diff --git a/Headers/AppKit/AppKit.h b/Headers/AppKit/AppKit.h index ddaf9bbb2..dcbed3614 100644 --- a/Headers/AppKit/AppKit.h +++ b/Headers/AppKit/AppKit.h @@ -182,6 +182,8 @@ #import #import #import +#import +#import #import #import #import diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index a2b16f2be..0d3824d91 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -1,7 +1,7 @@ /* NSTreeController.h - Main include file for GNUstep GUI Library + The tree controller class. Copyright (C) 2012 Free Software Foundation, Inc. @@ -27,17 +27,32 @@ Boston, MA 02110-1301, USA. */ -#import - #ifndef _GNUstep_H_NSTreeController #define _GNUstep_H_NSTreeController -@interface NSTreeController : NSController +#import + +#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST) +#import + +@class NSString; +@class NSArray; +@class NSIndexPath; +@class NSTreeNode; + +@interface NSTreeController : NSObjectController { + NSString *_childrenKeyPath; + NSString *_countKeyPath; + NSString *_leafKeyPath; + NSArray *_sortDescriptors; + BOOL _alwaysUsesMultipleValuesMarker; + BOOL _avoidsEmptySelection; + BOOL _preservesSelection; + BOOL _selectsInsertedObjects; } -#if 0 // compile this out for now.... -- (BOOL) addSelectionIndexPaths:(NSArray *)indexPaths; +- (BOOL) addSelectionIndexPaths: (NSArray*)indexPaths; - (BOOL) alwaysUsesMultipleValuesMarker; - (BOOL) avoidsEmptySelection; - (BOOL) canAddChid; @@ -45,39 +60,47 @@ - (BOOL) canInsertChild; - (BOOL) preservesSelection; - (BOOL) selectsInsertedObjects; -- (BOOL) setSelectionIndexPath: (NSIndexPath *)indexPath; -- (BOOL) setSelectionIndexPaths: (NSArray *)indexPaths; +- (BOOL) setSelectionIndexPath: (NSIndexPath*)indexPath; +- (BOOL) setSelectionIndexPaths: (NSArray*)indexPaths; - (id) arrangedObjects; - (id) content; -- (NSArray *) selectedObjects; -- (NSArray *) selectionIndexPaths; -- (NSArray *) sortDescriptors; -- (NSIndexPath *) selectionIndexPath; -- (NSString *) childrenKeyPath; -- (NSString *) countKeyPath; -- (NSString *) leafKeyPath; +- (NSArray*) selectedObjects; +- (NSIndexPath*) selectionIndexPath; +- (NSArray*) selectionIndexPaths; +- (NSArray*) sortDescriptors; +- (NSString*) childrenKeyPath; +- (NSString*) countKeyPath; +- (NSString*) leafKeyPath; - (void) addChild: (id)sender; - (void) add: (id)sender; - (void) insertChild: (id)sender; -- (void) insertObject: (id)object atArrangedObjectIndexPath:(NSIndexPath *)indexPath; -- (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths; -- (void) insert:sender; +- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)indexPath; +- (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*)indexPaths; +- (void) insert: (id)sender; - (void) rearrangeObjects; -- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath *)indexPath; -- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray *)indexPaths; -- (void) removeSelectionIndexPaths: (NSArray *)indexPaths; +- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath; +- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths; +- (void) removeSelectionIndexPaths: (NSArray*)indexPaths; - (void) remove: (id)sender; -- (void) setAlwaysUsesMultipleValuesMarker:(BOOL)flag; -- (void) setAvoidsEmptySelection:(BOOL)flag; -- (void) setChildrenKeyPath:(NSString *)path; +- (void) setAlwaysUsesMultipleValuesMarker: (BOOL)flag; +- (void) setAvoidsEmptySelection: (BOOL)flag; +- (void) setChildrenKeyPath: (NSString*)path; - (void) setContent: (id)content; -- (void) setCountKeyPath: (NSString *)path; -- (void) setLeafPathKey: (NSString *)key; +- (void) setCountKeyPath: (NSString*)path; +- (void) setLeafPathKey: (NSString*)key; - (void) setPreservesSelection: (BOOL)flag; - (void) setSelectsInsertedObjects: (BOOL)flag; -- (void) setSortDescriptors: (NSArray *)descriptors; -#endif +- (void) setSortDescriptors: (NSArray*)descriptors; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) +- (NSString*) childrenKeyPathForNode: (NSTreeNode*)node; +- (NSString*) countKeyPathForNode: (NSTreeNode*)node; +- (NSString*) leafKeyPathForNode: (NSTreeNode*)node; +- (void) moveNode: (NSTreeNode*)node toIndexPath: (NSIndexPath*)indexPath; +- (void) moveNodes: (NSArray*)nodes toIndexPath: (NSIndexPath*)startingIndexPath; +- (NSArray*) selectedNodes; +#endif @end +#endif #endif /* _GNUstep_H_NSTreeController */ diff --git a/Headers/AppKit/NSTreeNode.h b/Headers/AppKit/NSTreeNode.h index e69de29bb..847b4544c 100644 --- a/Headers/AppKit/NSTreeNode.h +++ b/Headers/AppKit/NSTreeNode.h @@ -0,0 +1,61 @@ +/* + NSTreeNode.h + + The tree node class + + Copyright (C) 2013 Free Software Foundation, Inc. + + Author: Dr. H. Nikolaus Schaller + Date: 2013 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; see the file COPYING.LIB. + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _GNUstep_H_NSTreeNode +#define _GNUstep_H_NSTreeNode + +#import +#import + +@class NSArray; +@class NSIndexPath; +@class NSMutableArray; + +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) +@interface NSTreeNode : NSObject +{ + id _representedObject; + NSMutableArray *_childNodes; + NSTreeNode *_parentNode; +} + ++ (id) treeNodeWithRepresentedObject: (id)modelObject; + +- (NSArray*) childNodes; +- (NSTreeNode*) descendantNodeAtIndexPath: (NSIndexPath*)path; +- (NSIndexPath*) indexPath; +- (id) initWithRepresentedObject: (id)repObj; +- (BOOL) isLeaf; +- (NSMutableArray*) mutableChildNodes; +- (NSTreeNode*) parentNode; +- (id) representedObject; +- (void) sortWithSortDescriptors: (NSArray*)sortDescs recursively: (BOOL)flag; + +@end +#endif +#endif // _GNUstep_H_NSTreeNode diff --git a/Source/GNUmakefile b/Source/GNUmakefile index 5583daed3..fff776712 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -189,6 +189,7 @@ NSToolbarItemGroup.m \ NSTokenField.m \ NSTokenFieldCell.m \ NSTreeController.m \ +NSTreeNode.m \ NSUserDefaultsController.m \ NSView.m \ NSViewController.m \ @@ -400,6 +401,7 @@ NSToolbarItemGroup.h \ NSTokenField.h \ NSTokenFieldCell.h \ NSTreeController.h \ +NSTreeNode.h \ NSUserDefaultsController.h \ NSView.h \ NSViewController.h \ diff --git a/Source/NSObjectController.m b/Source/NSObjectController.m index 2c099f9fb..db9331ea2 100644 --- a/Source/NSObjectController.m +++ b/Source/NSObjectController.m @@ -50,9 +50,9 @@ @implementation _NSManagedProxy - (id) initWithCoder: (NSCoder *)coder { - if((self = [super init]) != nil) + if ((self = [super init]) != nil) { - if([coder allowsKeyedCoding]) + if ([coder allowsKeyedCoding]) { ASSIGN(_entity_name_key,[coder decodeObjectForKey: @"NSEntityName"]); } @@ -66,7 +66,7 @@ - (void) encodeWithCoder: (NSCoder *)coder { - if([coder allowsKeyedCoding]) + if ([coder allowsKeyedCoding]) { [coder encodeObject: _entity_name_key forKey: @"NSEntityName"]; } @@ -104,8 +104,10 @@ triggerChangeNotificationsForDependentKey: @"canAdd"]; [self setKeys: [NSArray arrayWithObject: @"editable"] triggerChangeNotificationsForDependentKey: @"canRemove"]; - [self setKeys: [NSArray arrayWithObject: @"content"] + [self setKeys: [NSArray arrayWithObjects: @"content", NSContentObjectBinding, nil] triggerChangeNotificationsForDependentKey: @"selectedObjects"]; + [self setKeys: [NSArray arrayWithObjects: @"content", NSContentObjectBinding, nil] + triggerChangeNotificationsForDependentKey: @"selection"]; } } @@ -140,7 +142,7 @@ - (void) encodeWithCoder: (NSCoder *)coder { [super encodeWithCoder: coder]; - if([coder allowsKeyedCoding]) + if ([coder allowsKeyedCoding]) { [coder encodeBool: _is_editable forKey: @"NSEditable"]; [coder encodeBool: _automatically_prepares_content forKey: @"NSAutomaticallyPreparesContent"]; @@ -158,7 +160,7 @@ - (id) initWithCoder: (NSCoder *)coder { - if((self = [super initWithCoder: coder]) != nil) + if ((self = [super initWithCoder: coder]) != nil) { if ([self automaticallyPreparesContent]) { @@ -172,7 +174,7 @@ } } - if([coder allowsKeyedCoding]) + if ([coder allowsKeyedCoding]) { _is_editable = [coder decodeBoolForKey: @"NSEditable"]; _automatically_prepares_content = [coder decodeBoolForKey: @"NSAutomaticallyPreparesContent"]; @@ -353,13 +355,13 @@ - (id) selection { // TODO - return nil; + return _content; } - (BOOL) validateMenuItem: (id )item { - SEL action = [item action]; + SEL action = [item action]; if (sel_isEqual(action, @selector(add:))) { diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index cda011198..9cd1ad9bd 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -1,18 +1,342 @@ +/* + NSTreeController.h + + The tree controller class. + + Copyright (C) 2012 Free Software Foundation, Inc. + + Author: Gregory Casamento + Date: 2012 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; see the file COPYING.LIB. + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +/* + NSTreeController.h + + The tree controller class. + + Copyright (C) 2012 Free Software Foundation, Inc. + + Author: Gregory Casamento + Date: 2012 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; see the file COPYING.LIB. + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#import +#import +#import +#import + #import +#import @implementation NSTreeController -- (id) initWithCoder: (NSCoder *)coder +- (id) initWithContent: (id)content +{ + if ((self = [super initWithContent: content]) != nil) + { + } + + return self; +} + +- (void) dealloc +{ + RELEASE(_childrenKeyPath); + RELEASE(_countKeyPath); + RELEASE(_leafKeyPath); + RELEASE(_sortDescriptors); + [super dealloc]; +} + +- (BOOL) addSelectionIndexPaths: (NSArray*)indexPaths +{ + // FIXME + return NO; +} + +- (BOOL) alwaysUsesMultipleValuesMarker +{ + return _alwaysUsesMultipleValuesMarker; +} + +- (BOOL) avoidsEmptySelection +{ + return _avoidsEmptySelection; +} + +- (BOOL) canAddChid +{ + // FIXME + return NO; +} + +- (BOOL) canInsert +{ + // FIXME + return NO; +} + +- (BOOL) canInsertChild +{ + // FIXME + return NO; +} + +- (BOOL) preservesSelection +{ + return _preservesSelection; +} + +- (BOOL) selectsInsertedObjects +{ + return _selectsInsertedObjects; +} + +- (BOOL) setSelectionIndexPath: (NSIndexPath*)indexPath +{ + // FIXME + return NO; +} + +- (BOOL) setSelectionIndexPaths: (NSArray*)indexPaths +{ + // FIXME + return NO; +} + +- (id) arrangedObjects +{ + // FIXME + return nil; +} + +- (id) content +{ + // FIXME + return [super content]; +} + +- (NSArray*) selectedObjects +{ + // FIXME + return [super selectedObjects]; +} + +- (NSIndexPath*) selectionIndexPath +{ + // FIXME + return nil; +} + +- (NSArray*) selectionIndexPaths +{ + // FIXME + return nil; +} + +- (NSArray*) sortDescriptors +{ + return _sortDescriptors; +} + +- (NSString*) childrenKeyPath +{ + return _childrenKeyPath; +} + +- (NSString*) countKeyPath +{ + return _countKeyPath;; +} + +- (NSString*) leafKeyPath +{ + return _leafKeyPath; +} + +- (void) addChild: (id)sender +{ + // FIXME +} + +- (void) add: (id)sender +{ + // FIXME + [super add: sender]; +} + +- (void) insertChild: (id)sender +{ + // FIXME +} + +- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)indexPath +{ + // FIXME +} + +- (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*)indexPaths +{ + // FIXME +} + +- (void) insert: (id)sender +{ + // FIXME +} + +- (void) rearrangeObjects +{ + // FIXME +} + +- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath +{ + // FIXME +} + +- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths +{ + // FIXME +} + +- (void) removeSelectionIndexPaths: (NSArray*)indexPaths +{ + // FIXME +} + +- (void) remove: (id)sender +{ + // FIXME + [super remove: sender]; +} + +- (void) setAlwaysUsesMultipleValuesMarker: (BOOL)flag +{ + _alwaysUsesMultipleValuesMarker = flag; +} + +- (void) setAvoidsEmptySelection: (BOOL)flag +{ + _avoidsEmptySelection = flag; +} + +- (void) setChildrenKeyPath: (NSString*)path +{ + ASSIGN(_childrenKeyPath, path); +} + +- (void) setContent: (id)content +{ + // FIXME + [super setContent: content]; +} + +- (void) setCountKeyPath: (NSString*)path +{ + ASSIGN(_countKeyPath, path); +} + +- (void) setLeafPathKey: (NSString*)key +{ + ASSIGN(_leafKeyPath, key); +} + +- (void) setPreservesSelection: (BOOL)flag +{ + _preservesSelection = flag; +} + +- (void) setSelectsInsertedObjects: (BOOL)flag +{ + _selectsInsertedObjects = flag; +} + +- (void) setSortDescriptors: (NSArray*)descriptors +{ + ASSIGN(_sortDescriptors, descriptors); +} + +- (NSString*) childrenKeyPathForNode: (NSTreeNode*)node +{ + // FIXME + return nil; +} + +- (NSString*) countKeyPathForNode: (NSTreeNode*)node +{ + // FIXME + return nil; +} + +- (NSString*) leafKeyPathForNode: (NSTreeNode*)node +{ + // FIXME + return nil; +} + +- (void) moveNode: (NSTreeNode*)node toIndexPath: (NSIndexPath*)indexPath +{ + // FIXME +} + +- (void) moveNodes: (NSArray*)nodes toIndexPath: (NSIndexPath*)startingIndexPath +{ + // FIXME +} + +- (NSArray*) selectedNodes +{ + // FIXME + return nil; +} + +- (id) initWithCoder: (NSCoder*)coder { return self; } -- (void) encodeWithCoder: (NSCoder *)coder +- (void) encodeWithCoder: (NSCoder*)coder { // Do nothing... } -- (id) copyWithZone: (NSZone *)zone +- (id) copyWithZone: (NSZone*)zone { return [self retain]; } diff --git a/Source/NSTreeNode.m b/Source/NSTreeNode.m new file mode 100644 index 000000000..2d80fcdd2 --- /dev/null +++ b/Source/NSTreeNode.m @@ -0,0 +1,251 @@ +/* + NSTreeNode.m + + The tree node class + + Copyright (C) 2013 Free Software Foundation, Inc. + + Author: Fred Kiefer + Date: 2013 + + This file is part of the GNUstep GUI Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; see the file COPYING.LIB. + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#import +#import +#import +#import + +#import + +@interface NSTreeNode (Private) +- (NSMutableArray*) _childNodes; +- (void) _setParentNode: (NSTreeNode*)parentNode; +@end + +@implementation NSTreeNode (Private) +- (NSMutableArray*) _childNodes +{ + return _childNodes; +} + +- (void) _setParentNode: (NSTreeNode*)parentNode +{ + _parentNode = parentNode; +} + +@end + + +@interface GSTreeNodeArray : NSMutableArray +{ + NSMutableArray *array; + NSTreeNode *parent; +} + +@end + +@implementation GSTreeNodeArray + +- (id) initForTreeNode: (NSTreeNode*)node +{ + ASSIGN(parent, node); + array = [parent _childNodes]; + return self; +} + +- (void) dealloc +{ + RELEASE(parent); + [super dealloc]; +} + +- (NSUInteger) count +{ + return [array count]; +} + +- (id) objectAtIndex: (NSUInteger)index +{ + return [array objectAtIndex: index]; +} + +- (void) addObject: (id)anObject +{ + [array addObject: anObject]; + [(NSTreeNode*)anObject _setParentNode: parent]; +} + +- (void) replaceObjectAtIndex: (NSUInteger)index withObject: (id)anObject +{ + id old = [array objectAtIndex: index]; + + [(NSTreeNode*)old _setParentNode: nil]; + [array replaceObjectAtIndex: index withObject: anObject]; + [(NSTreeNode*)anObject _setParentNode: parent]; +} + +- (void) insertObject: anObject atIndex: (NSUInteger)index +{ + [array insertObject: anObject atIndex: index]; + [(NSTreeNode*)anObject _setParentNode: parent]; +} + +- (void) removeObjectAtIndex: (NSUInteger)index +{ + id old = [array objectAtIndex: index]; + + [(NSTreeNode*)old _setParentNode: nil]; + [array removeObjectAtIndex: index]; +} + +@end + + +@implementation NSTreeNode + ++ (id) treeNodeWithRepresentedObject: (id)modelObject +{ + NSTreeNode *node = [[NSTreeNode alloc] initWithRepresentedObject: modelObject]; + + return AUTORELEASE(node); +} + +- (NSArray*) childNodes +{ + return [NSArray arrayWithArray: _childNodes]; +} + +- (NSTreeNode*) descendantNodeAtIndexPath: (NSIndexPath*)path +{ + NSUInteger len = [path length]; + NSUInteger i; + NSTreeNode *node = self; + + for (i = 0; i < len; i++) + { + NSUInteger index = [path indexAtPosition: i]; + + node = [node->_childNodes objectAtIndex: index]; + if (node == nil) + { + return nil; + } + } + + return node; +} + +- (NSIndexPath*) indexPath +{ + if (_parentNode != nil) + { + NSIndexPath *path; + NSUInteger index; + + index = [_parentNode->_childNodes indexOfObject: self]; + path = [_parentNode indexPath]; + if (path != nil) + { + return [path indexPathByAddingIndex: index]; + } + else + { + return [NSIndexPath indexPathWithIndex: index]; + } + } + else + { + return nil; + } +} + +- (id) initWithRepresentedObject: (id)repObj +{ + ASSIGN(_representedObject, repObj); + _childNodes = [[NSMutableArray alloc] init]; + return self; +} + +- (void) dealloc +{ + RELEASE(_representedObject); + RELEASE(_childNodes); + [super dealloc]; +} + +- (BOOL) isLeaf +{ + return [_childNodes count] == 0; +} + +- (NSMutableArray*) mutableChildNodes +{ + GSTreeNodeArray *nodeArray = [[GSTreeNodeArray alloc] initForTreeNode: self]; + + return AUTORELEASE(nodeArray); +} + +- (NSTreeNode*) parentNode +{ + return _parentNode; +} + +- (id) representedObject +{ + return _representedObject; +} + +- (void) sortWithSortDescriptors: (NSArray*)sortDescs recursively: (BOOL)flag +{ + // Sort children nodes + NSUInteger i; + NSUInteger len = [sortDescs count]; + NSMutableArray *newSortDescs = [[NSMutableArray alloc] init]; + + for (i = 0; i < len; i++) + { + NSSortDescriptor *oldDesc = [sortDescs objectAtIndex: i]; + NSString * newKey = [@"representedObject." stringByAppendingString: [oldDesc key]]; + NSSortDescriptor *newDesc = [[NSSortDescriptor alloc] + initWithKey: newKey + ascending: [oldDesc ascending] + selector: [oldDesc selector]]; + + [newSortDescs addObject: newDesc]; + RELEASE(newDesc); + } + + [_childNodes sortUsingDescriptors: newSortDescs]; + RELEASE(newSortDescs); + + if (flag) + { + // sort recursive + NSUInteger count = [_childNodes count]; + + for (i = 0; i < count; i++) + { + [[_childNodes objectAtIndex: i] sortWithSortDescriptors: sortDescs + recursively: YES]; + } + } +} + +@end