From bfb33156cf261313de738717fc3a9d38f3b71335 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 19 Jun 2024 01:46:27 -0400 Subject: [PATCH 01/72] Move code over from old branch, startint new branch since NSOutlineView was refactored --- Headers/AppKit/NSTreeController.h | 296 +++++++++++++++++++++++--- Source/GSBindingHelpers.h | 1 + Source/GSXib5KeyedUnarchiver.m | 3 + Source/NSKeyValueBinding.m | 5 + Source/NSOutlineView.m | 117 +++++++---- Source/NSTreeController.m | 336 +++++++++++++++++++++++------- 6 files changed, 611 insertions(+), 147 deletions(-) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index ccbd70378d..d6d1c439f2 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -1,4 +1,4 @@ -/* +/* NSTreeController.h The tree controller class. @@ -7,7 +7,7 @@ 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 @@ -22,10 +22,10 @@ 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, + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ +*/ #ifndef _GNUstep_H_NSTreeController #define _GNUstep_H_NSTreeController @@ -47,61 +47,301 @@ APPKIT_EXPORT_CLASS NSString *_countKeyPath; NSString *_leafKeyPath; NSArray *_sortDescriptors; + NSArray *_arranged_objects; + NSMutableArray *_selection_index_paths; + BOOL _alwaysUsesMultipleValuesMarker; BOOL _avoidsEmptySelection; BOOL _preservesSelection; BOOL _selectsInsertedObjects; + BOOL _canAddChild; + BOOL _canInsert; + BOOL _canInsertChild; } -- (BOOL) addSelectionIndexPaths: (NSArray*)indexPaths; +/** + * Adds the objects in the indexPaths array to the current selection. + */ +- (BOOL) addSelectionIndexPaths: (NSArray *)indexPaths; + +/** + * BOOL that indicates if the controller returns the multiple values marker when + * multiple objects have been selected. + */ - (BOOL) alwaysUsesMultipleValuesMarker; + +/** + * If YES, requires the content array to maintain a selection. + */ - (BOOL) avoidsEmptySelection; -- (BOOL) canAddChid; + +/** + * If YES, a child can be added. + */ +- (BOOL) canAddChild; + +/** + * If YES, an object can be inserted. + */ - (BOOL) canInsert; + +/** + * If YES, a child can be inserted. + */ - (BOOL) canInsertChild; -- (BOOL) preservesSelection; + +/** + * If YES, then preserve the current selection when the content changes. + */ +- (BOOL) preservesSelection; + +/** + * If YES, then when an object is inserted it is added to the selection. + */ - (BOOL) selectsInsertedObjects; -- (BOOL) setSelectionIndexPath: (NSIndexPath*)indexPath; -- (BOOL) setSelectionIndexPaths: (NSArray*)indexPaths; + +/** + * Makes indexPath the current selection. + */ +- (BOOL) setSelectionIndexPath: (NSIndexPath *)indexPath; + +/** + * Makes the array indexPaths the current selections. + */ +- (BOOL) setSelectionIndexPaths: (NSArray *)indexPaths; + +/** + * All objects managed by this tree controller. + */ - (id) arrangedObjects; -- (id) content; + +/** + * An NSArray containing all selected objects. + */ - (NSArray*) selectedObjects; + +/** + * The index path of the first selected object. + */ - (NSIndexPath*) selectionIndexPath; + +/** + * An array containing all of the currently selected objects. + */ - (NSArray*) selectionIndexPaths; + +/** + * An array containing sort descriptors used to arrange content. + */ - (NSArray*) sortDescriptors; + +/** + * Key path for children of the node. This key must be key value + * compliant. + */ - (NSString*) childrenKeyPath; + +/** + * Key value path for the flag which gives the count for the children + * of this node. The path indicated her must be key-value compliant. + */ - (NSString*) countKeyPath; + +/** + * Key value path for the flag which determins that this is a leaf. + * The path indicated her must be key-value compliant. + */ - (NSString*) leafKeyPath; + +/** + * Adds a child to the current selection using the newObject method. + */ - (void) addChild: (id)sender; + +/** + * Adds a new objeect to the tree usin the newObject method. + */ - (void) add: (id)sender; + +/** + * Inserts a child using the newObject method. This method + * will fail if canInsertChild returns NO. + */ - (void) insertChild: (id)sender; -- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)indexPath; -- (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*)indexPaths; + +/** + * Inserts and object using the newObject method at the specified indexPath. + */ +- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)indexPath; + +/** + * Inserts objects into arranged objects at the specified indexPaths. These arrays are + * expected to be parallel and have the same number of objects. + */ +- (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths; + +/** + * Insert an object created by newObject into arranged objects. + */ +- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)indexPath; + +/** + * Inserts objects into arranged objects at the specified indexPaths. These arrays are + * expected to be parallel and have the same number of objects. + */ +- (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths; + +/** + * Insert an object created by newObject into arranged objects. + */ - (void) insert: (id)sender; + +/** + * Causes the controller to re-sort and rearrange the objects. This method + * should be called if anything has been done that affects the list of objects + * in the controller. + */ - (void) rearrangeObjects; -- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath; -- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths; -- (void) removeSelectionIndexPaths: (NSArray*)indexPaths; + +/** + * Removes object at the specified indexPath. + */ +- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath *)indexPath; + +/** + * Removes objects at the specified indexPaths. + */ +- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray *)indexPaths; + +/** + * Removes selection of objects at the specified indexPaths. + */ +- (void) removeSelectionIndexPaths: (NSArray *)indexPaths; + +/** + * Remove the currently selected object + */ +- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath *)indexPath; + +/** + * Removes objects at the specified indexPaths. + */ +- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray *)indexPaths; + +/** + * Removes selection of objects at the specified indexPaths. + */ +- (void) removeSelectionIndexPaths: (NSArray *)indexPaths; + +/** + * Remove the currently selected object + */ - (void) remove: (id)sender; + +/** + * Sets the flag to always use multiple values marker. + */ - (void) setAlwaysUsesMultipleValuesMarker: (BOOL)flag; + +/** + * Sets the flag to avoid empty selection. + */ - (void) setAvoidsEmptySelection: (BOOL)flag; -- (void) setChildrenKeyPath: (NSString*)path; -- (void) setContent: (id)content; -- (void) setCountKeyPath: (NSString*)path; -- (void) setLeafPathKey: (NSString*)key; + +/** + * Sets the children key path. This needs to be key-value compliant. + */ +- (void) setChildrenKeyPath: (NSString *)path; + +/** + * Sets the count key path. This needs to be key-value compliant. + */ +- (void) setCountKeyPath: (NSString *)path; + +/** + * Sets leaf key path. This value needs to be key-value compliant. + */ +- (void) setLeafKeyPath: (NSString *)key; + +/** + * Sets the preserves selection flag. + */ - (void) setPreservesSelection: (BOOL)flag; + +/** + * Sets the flag that determines if objects inserted are automatically + * selected. + */ - (void) setSelectsInsertedObjects: (BOOL)flag; -- (void) setSortDescriptors: (NSArray*)descriptors; + +/** + * Sets the array of sort descriptors used when building arrangedObjects. + */ +- (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; +/** + * children key path for the given NSTreeNode. + */ +- (NSString*) childrenKeyPathForNode: (NSTreeNode *)node; + +/** + * count key path for the given NSTreeNode. + */ +- (NSString*) countKeyPathForNode: (NSTreeNode *)node; + +/** + * leaf key path for the given NSTreeNode. + */ +- (NSString*) leafKeyPathForNode: (NSTreeNode *)node; + +/** + * Moves node to given indexPath + */ +- (void) moveNode: (NSTreeNode *)node toIndexPath: (NSIndexPath *)indexPath; + +/** + * Move nodes to position at startingIndexPath + */ +- (void) moveNodes: (NSArray *)nodes toIndexPath: (NSIndexPath *)startingIndexPath; + +/** + * Array containing all selected nodes + */ +- (void) setSortDescriptors: (NSArray *)descriptors; + +/** + * children key path for the given NSTreeNode. + */ +- (NSString*) childrenKeyPathForNode: (NSTreeNode *)node; + +/** + * count key path for the given NSTreeNode. + */ +- (NSString*) countKeyPathForNode: (NSTreeNode *)node; + +/** + * leaf key path for the given NSTreeNode. + */ +- (NSString*) leafKeyPathForNode: (NSTreeNode *)node; + +/** + * Moves node to given indexPath + */ +- (void) moveNode: (NSTreeNode *)node toIndexPath: (NSIndexPath *)indexPath; + +/** + * Move nodes to position at startingIndexPath + */ +- (void) moveNodes: (NSArray *)nodes toIndexPath: (NSIndexPath *)startingIndexPath; + +/** + * Array containing all selected nodes + */ - (NSArray*) selectedNodes; -#endif +#endif // 10_5 + @end -#endif +#endif // if OS_API_VERSION... #endif /* _GNUstep_H_NSTreeController */ diff --git a/Source/GSBindingHelpers.h b/Source/GSBindingHelpers.h index 47bdb0f66f..7d74001ad4 100644 --- a/Source/GSBindingHelpers.h +++ b/Source/GSBindingHelpers.h @@ -64,6 +64,7 @@ - (void) reverseSetValueFor: (NSString *)binding; - (id) destinationValue; - (id) sourceValueFor: (NSString *)binding; +- (id) observedObject; /* Transforms the value with a value transformer, if specified and available, * and takes care of any placeholders diff --git a/Source/GSXib5KeyedUnarchiver.m b/Source/GSXib5KeyedUnarchiver.m index 80b75bfaaa..75c64ba267 100644 --- a/Source/GSXib5KeyedUnarchiver.m +++ b/Source/GSXib5KeyedUnarchiver.m @@ -330,6 +330,9 @@ + (void) initialize @"shadow", @"NSViewShadow", @"blurRadius", @"NSShadowBlurRadius", @"color", @"NSShadowColor", + @"childrenKeyPath", @"NSTreeContentChildrenKey", // NSTreeController + @"countKeyPath", @"NSTreeContentCountKey", + @"leafKeyPath", @"NSTreeContentLeafKey", nil]; RETAIN(XmlKeyMapTable); diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index d5b9e2769f..12306c7935 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -321,6 +321,11 @@ - (void)dealloc [super dealloc]; } +- (id) observedObject +{ + return [info objectForKey: NSObservedObjectKey]; +} + - (id) destinationValue { id newValue; diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 2bf286070f..59ebc96261 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -54,16 +54,20 @@ #import "AppKit/NSEvent.h" #import "AppKit/NSGraphics.h" #import "AppKit/NSImage.h" +#import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSOutlineView.h" #import "AppKit/NSScroller.h" #import "AppKit/NSTableColumn.h" #import "AppKit/NSTableHeaderView.h" #import "AppKit/NSText.h" #import "AppKit/NSTextFieldCell.h" +#import "AppKit/NSTreeController.h" #import "AppKit/NSWindow.h" #import "GNUstepGUI/GSTheme.h" +#import "GSBindingHelpers.h" #import "GSGuiPrivate.h" + #include static NSMapTableKeyCallBacks keyCallBacks; @@ -170,6 +174,11 @@ + (void) initialize unexpandable = [[NSImage alloc] initWithSize: [expanded size]]; #endif autoExpanded = [NSMutableSet new]; + + // Bindings.. + [self exposeBinding: NSContentBinding]; + [self exposeBinding: NSSelectionIndexesBinding]; + [self exposeBinding: NSSortDescriptorsBinding]; } } @@ -700,18 +709,25 @@ - (BOOL)shouldCollapseAutoExpandedItemsForDeposited: (BOOL)deposited */ - (void) setDataSource: (id)anObject { + GSKeyValueBinding *theBinding; + #define CHECK_REQUIRED_METHOD(selector_name) \ if (anObject && ![anObject respondsToSelector: @selector(selector_name)]) \ [NSException raise: NSInternalInconsistencyException \ format: @"data source does not respond to %@", @#selector_name] - CHECK_REQUIRED_METHOD(outlineView:child:ofItem:); - CHECK_REQUIRED_METHOD(outlineView:isItemExpandable:); - CHECK_REQUIRED_METHOD(outlineView:numberOfChildrenOfItem:); - - // This method is @optional in NSOutlineViewDataSource as of macOS10.0 - // CHECK_REQUIRED_METHOD(outlineView:objectValueForTableColumn:byItem:); + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + if (theBinding == nil) + { + CHECK_REQUIRED_METHOD(outlineView:child:ofItem:); + CHECK_REQUIRED_METHOD(outlineView:isItemExpandable:); + CHECK_REQUIRED_METHOD(outlineView:numberOfChildrenOfItem:); + // This method is @optional in NSOutlineViewDataSource as of macOS10.0 + // CHECK_REQUIRED_METHOD(outlineView:objectValueForTableColumn:byItem:); + } + // Is the data source editable? _dataSource_editable = [anObject respondsToSelector: @selector(outlineView:setObjectValue:forTableColumn:byItem:)]; @@ -1814,9 +1830,9 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb row: (NSInteger) index { id result = nil; - + if ([_dataSource respondsToSelector: - @selector(outlineView:objectValueForTableColumn:byItem:)]) + @selector(outlineView:objectValueForTableColumn:byItem:)]) { id item = [self itemAtRow: index]; @@ -1953,43 +1969,68 @@ - (BOOL) _isItemLoaded: (id)item - (void) _loadDictionaryStartingWith: (id) startitem atLevel: (NSInteger) level { + GSKeyValueBinding *theBinding; NSInteger num = 0; NSInteger i = 0; id sitem = (startitem == nil) ? (id)[NSNull null] : (id)startitem; - NSMutableArray *anarray = nil; - - /* Check to see if item is expandable and expanded before getting the number - * of items. For macos compatibility the topmost item (startitem==nil) - * is always considered expandable and must not be checked. - * We must load the item only if expanded, otherwise an outline view is not - * usable with a big tree structure. For example, an outline view to browse - * file system would try to traverse every file/directory on -reloadData. - */ - if ((startitem == nil - || [_dataSource outlineView: self isItemExpandable: startitem]) - && [self isItemExpanded: startitem]) - { - num = [_dataSource outlineView: self - numberOfChildrenOfItem: startitem]; - } + NSMutableArray *anarray = nil; - if (num > 0) + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + if (theBinding != nil) { - anarray = [NSMutableArray array]; - NSMapInsert(_itemDict, sitem, anarray); + /* Implement logic to build the internal data structure here using + * bindings... + */ + id observedObject = [theBinding observedObject]; + + if ([observedObject isKindOfClass: [NSTreeController class]]) + { + NSTreeController *tc = (NSTreeController *)observedObject; + NSString *leafKeyPath = [tc leafKeyPath]; + NSString *childrenKeyPath = [tc childrenKeyPath]; + NSString *countKeyPath = [tc countKeyPath]; + + NSLog(@"leafKeyPath = %@", leafKeyPath); + NSLog(@"childrenKeyPath = %@", childrenKeyPath); + NSLog(@"countKeyPath = %@", countKeyPath); + } } - - NSMapInsert(_levelOfItems, sitem, [NSNumber numberWithInteger: level]); - - for (i = 0; i < num; i++) + else { - id anitem = [_dataSource outlineView: self - child: i - ofItem: startitem]; - - [anarray addObject: anitem]; - [self _loadDictionaryStartingWith: anitem - atLevel: level + 1]; + /* Check to see if item is expandable and expanded before getting the number + * of items. For macos compatibility the topmost item (startitem==nil) + * is always considered expandable and must not be checked. + * We must load the item only if expanded, otherwise an outline view is not + * usable with a big tree structure. For example, an outline view to browse + * file system would try to traverse every file/directory on -reloadData. + */ + if ((startitem == nil + || [_dataSource outlineView: self isItemExpandable: startitem]) + && [self isItemExpanded: startitem]) + { + num = [_dataSource outlineView: self + numberOfChildrenOfItem: startitem]; + } + + if (num > 0) + { + anarray = [NSMutableArray array]; + NSMapInsert(_itemDict, sitem, anarray); + } + + NSMapInsert(_levelOfItems, sitem, [NSNumber numberWithInteger: level]); + + for (i = 0; i < num; i++) + { + id anitem = [_dataSource outlineView: self + child: i + ofItem: startitem]; + + [anarray addObject: anitem]; + [self _loadDictionaryStartingWith: anitem + atLevel: level + 1]; + } } } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 9cd1ad9bd7..cb3dee6ab1 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -1,5 +1,5 @@ -/* - NSTreeController.h + /* + NSTreeController.m The tree controller class. @@ -7,35 +7,7 @@ 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 @@ -50,26 +22,62 @@ 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, + 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 #import -#import -#import +#import "AppKit/NSKeyValueBinding.h" +#import "AppKit/NSTreeController.h" + +#import "GSBindingHelpers.h" +#import "GSFastEnumeration.h" @implementation NSTreeController ++ (void) initialize +{ + if (self == [NSTreeController class]) + { + [self exposeBinding: NSContentArrayBinding]; + [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] + triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; + } +} + - (id) initWithContent: (id)content { + NSLog(@"Content = %@", content); if ((self = [super initWithContent: content]) != nil) { + _childrenKeyPath = nil; + _countKeyPath = nil; + _leafKeyPath = nil; + _sortDescriptors = nil; + _selection_index_paths = [[NSMutableArray alloc] init]; + + _canInsert = YES; + _canInsertChild = YES; + _canAddChild = YES; } + + return self; +} + +- (id) init +{ + NSMutableArray *array = [[NSMutableArray alloc] init]; + + self = [self initWithContent: array]; + RELEASE(array); return self; } @@ -80,10 +88,11 @@ - (void) dealloc RELEASE(_countKeyPath); RELEASE(_leafKeyPath); RELEASE(_sortDescriptors); + RELEASE(_arranged_objects); [super dealloc]; } -- (BOOL) addSelectionIndexPaths: (NSArray*)indexPaths +- (BOOL) addSelectionIndexPaths: (NSArray *)indexPaths { // FIXME return NO; @@ -99,22 +108,19 @@ - (BOOL) avoidsEmptySelection return _avoidsEmptySelection; } -- (BOOL) canAddChid +- (BOOL) canAddChild { - // FIXME - return NO; + return _canAddChild; } - (BOOL) canInsert { - // FIXME - return NO; + return _canInsert; } - (BOOL) canInsertChild { - // FIXME - return NO; + return _canInsertChild; } - (BOOL) preservesSelection @@ -127,31 +133,57 @@ - (BOOL) selectsInsertedObjects return _selectsInsertedObjects; } -- (BOOL) setSelectionIndexPath: (NSIndexPath*)indexPath +- (BOOL) setSelectionIndexPath: (NSIndexPath *)indexPath { - // FIXME - return NO; + BOOL f = [self commitEditing]; + + if (YES == f) + { + [_selection_index_paths addObject: indexPath]; + } + + return f; } -- (BOOL) setSelectionIndexPaths: (NSArray*)indexPaths +- (BOOL) setSelectionIndexPaths: (NSArray *)indexPaths { - // FIXME - return NO; + BOOL f = [self commitEditing]; + + if (YES == f) + { + NSMutableArray *mutable_index_paths = [NSMutableArray arrayWithArray: indexPaths]; + ASSIGN(_selection_index_paths, mutable_index_paths); + } + + return f; +} + +- (NSArray*) arrangeObjects: (NSArray*)obj +{ + NSArray *temp = obj; + return [temp sortedArrayUsingDescriptors: _sortDescriptors]; } - (id) arrangedObjects { - // FIXME - return nil; + if (_arranged_objects == nil) + { + [self rearrangeObjects]; + } + return _arranged_objects; } -- (id) content +- (void) rearrangeObjects { - // FIXME - return [super content]; + NSLog(@"---- rearrangeObjects"); + [self willChangeValueForKey: @"arrangedObjects"]; + DESTROY(_arranged_objects); + _arranged_objects = [[GSObservableArray alloc] + initWithArray: [self arrangeObjects: _content]]; + [self didChangeValueForKey: @"arrangedObjects"]; } -- (NSArray*) selectedObjects +- (NSArray *) selectedObjects { // FIXME return [super selectedObjects]; @@ -189,15 +221,34 @@ - (NSString*) leafKeyPath return _leafKeyPath; } -- (void) addChild: (id)sender +- (void) add: (id)sender { - // FIXME + if ([self canAddChild]) + { + id new = [self newObject]; + + [self addChild: new]; + RELEASE(new); + } } -- (void) add: (id)sender +- (void) addChild: (id)obj { - // FIXME - [super add: sender]; + GSKeyValueBinding *theBinding; + + [self setContent: obj]; + theBinding = [GSKeyValueBinding getBinding: NSContentObjectBinding + forObject: self]; + if (theBinding != nil) + [theBinding reverseSetValueFor: @"content"]; +} + +- (void) remove: (id)sender +{ + if ([self canRemove]) + { + [self removeObject: [self content]]; + } } - (void) insertChild: (id)sender @@ -220,11 +271,6 @@ - (void) insert: (id)sender // FIXME } -- (void) rearrangeObjects -{ - // FIXME -} - - (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath { // FIXME @@ -240,12 +286,6 @@ - (void) removeSelectionIndexPaths: (NSArray*)indexPaths // FIXME } -- (void) remove: (id)sender -{ - // FIXME - [super remove: sender]; -} - - (void) setAlwaysUsesMultipleValuesMarker: (BOOL)flag { _alwaysUsesMultipleValuesMarker = flag; @@ -263,8 +303,8 @@ - (void) setChildrenKeyPath: (NSString*)path - (void) setContent: (id)content { - // FIXME [super setContent: content]; + [self rearrangeObjects]; } - (void) setCountKeyPath: (NSString*)path @@ -272,7 +312,7 @@ - (void) setCountKeyPath: (NSString*)path ASSIGN(_countKeyPath, path); } -- (void) setLeafPathKey: (NSString*)key +- (void) setLeafKeyPath: (NSString*)key { ASSIGN(_leafKeyPath, key); } @@ -294,20 +334,17 @@ - (void) setSortDescriptors: (NSArray*)descriptors - (NSString*) childrenKeyPathForNode: (NSTreeNode*)node { - // FIXME - return nil; + return _childrenKeyPath; } - (NSString*) countKeyPathForNode: (NSTreeNode*)node { - // FIXME - return nil; + return _countKeyPath; } - (NSString*) leafKeyPathForNode: (NSTreeNode*)node { - // FIXME - return nil; + return _leafKeyPath; } - (void) moveNode: (NSTreeNode*)node toIndexPath: (NSIndexPath*)indexPath @@ -326,19 +363,156 @@ - (NSArray*) selectedNodes return nil; } + +- (void) bind: (NSString *)binding + toObject: (id)anObject + withKeyPath: (NSString *)keyPath + options: (NSDictionary *)options +{ + if ([binding isEqual: NSContentArrayBinding]) + { + GSKeyValueBinding *kvb; + + [self unbind: binding]; + kvb = [[GSKeyValueBinding alloc] initWithBinding: @"content" + withName: binding + toObject: anObject + withKeyPath: keyPath + options: options + fromObject: self]; + // The binding will be retained in the binding table + RELEASE(kvb); + } + else + { + [super bind: binding + toObject: anObject + withKeyPath: keyPath + options: options]; + } +} + - (id) initWithCoder: (NSCoder*)coder { + self = [super initWithCoder: coder]; + + if (self != nil) + { + if ([coder allowsKeyedCoding]) + { + // These names do not stick to convention. Usually it would be + // NS* or NSTreeController* so they must be overriden in + // GSXib5KeyedUnarchver. + if ([coder containsValueForKey: @"NSTreeContentChildrenKey"]) + { + [self setChildrenKeyPath: + [coder decodeObjectForKey: @"NSTreeContentChildrenKey"]]; + } + if ([coder containsValueForKey: @"NSTreeContentCountKey"]) + { + [self setCountKeyPath: + [coder decodeObjectForKey: @"NSTreeContentCountKey"]]; + } + if ([coder containsValueForKey: @"NSTreeContentLeafKey"]) + { + [self setLeafKeyPath: + [coder decodeObjectForKey: @"NSTreeContentLeafKey"]]; + } + + // Since we don't inherit from NSArrayController these are decoded here + // as well. + if ([coder containsValueForKey: @"NSAvoidsEmptySelection"]) + { + [self setAvoidsEmptySelection: + [coder decodeBoolForKey: @"NSAvoidsEmptySelection"]]; + } + if ([coder containsValueForKey: @"NSPreservesSelection"]) + { + [self setPreservesSelection: + [coder decodeBoolForKey: @"NSPreservesSelection"]]; + } + if ([coder containsValueForKey: @"NSSelectsInsertedObjects"]) + { + [self setSelectsInsertedObjects: + [coder decodeBoolForKey: @"NSSelectsInsertedObjects"]]; + } + } + } + else + { + id obj = nil; + BOOL f = NO; + + obj = [coder decodeObject]; + [self setChildrenKeyPath: obj]; + obj = [coder decodeObject]; + [self setCountKeyPath: obj]; + obj = [coder decodeObject]; + [self setLeafKeyPath: obj]; + + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + [self setAvoidsEmptySelection: f]; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + [self setPreservesSelection: f]; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + [self setSelectsInsertedObjects: f]; + } + return self; } - (void) encodeWithCoder: (NSCoder*)coder { - // Do nothing... + [super encodeWithCoder: coder]; + if ([coder allowsKeyedCoding]) + { + [coder encodeObject: _childrenKeyPath + forKey: @"NSTreeContentChildrenKey"]; + [coder encodeObject: _countKeyPath + forKey: @"NSTreeContentCountKey"]; + [coder encodeObject: _leafKeyPath + forKey: @"NSTreeContentLeafKey"]; + + + [coder encodeBool: _avoidsEmptySelection + forKey: @"NSAvoidsEmptySelection"]; + [coder encodeBool: _preservesSelection + forKey: @"NSPreservesSelection"]; + [coder encodeBool: _selectsInsertedObjects + forKey: @"NSSelectsInsertedObjects"]; + } + else + { + id obj = nil; + BOOL f = NO; + + obj = [self childrenKeyPath]; + [coder encodeObject: obj]; + obj = [self countKeyPath]; + [coder encodeObject: obj]; + obj = [self leafKeyPath]; + [coder encodeObject: obj]; + + f = [self avoidsEmptySelection]; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + f = [self preservesSelection]; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + f = [self selectsInsertedObjects]; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + } } - (id) copyWithZone: (NSZone*)zone { - return [self retain]; + NSData *data = [NSArchiver archivedDataWithRootObject: self]; + id result = [NSUnarchiver unarchiveObjectWithData: data]; + return result; } @end From 1d296134911dac03731637c4ccf3a7b68b68f1ae Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 19 Jun 2024 03:28:39 -0400 Subject: [PATCH 02/72] Progress, thusfar... --- Source/NSOutlineView.m | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 59ebc96261..e81ea3c972 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1994,6 +1994,35 @@ - (void) _loadDictionaryStartingWith: (id) startitem NSLog(@"leafKeyPath = %@", leafKeyPath); NSLog(@"childrenKeyPath = %@", childrenKeyPath); NSLog(@"countKeyPath = %@", countKeyPath); + + if (startitem == nil) + { + NSArray *items = (NSArray *)[theBinding destinationValue]; + NSLog(@"items = %@", items); + + num = [items count]; + } + + if (num > 0) + { + anarray = [NSMutableArray array]; + NSMapInsert(_itemDict, sitem, anarray); + } + + NSMapInsert(_levelOfItems, sitem, [NSNumber numberWithInteger: level]); + + /* + for (i = 0; i < num; i++) + { + id anitem = [_dataSource outlineView: self + child: i + ofItem: startitem]; + + [anarray addObject: anitem]; + [self _loadDictionaryStartingWith: anitem + atLevel: level + 1]; + } + */ } } else From f7afc331eb0767e5b8e746056ebd9f9462f8bbf1 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Mon, 24 Jun 2024 08:50:22 -0400 Subject: [PATCH 03/72] Interim changes before refactor of NSTreeController --- Headers/AppKit/NSTreeController.h | 4 ++-- Headers/AppKit/NSTreeNode.h | 1 + Source/GSBindingHelpers.h | 1 + Source/NSKeyValueBinding.m | 19 ++++++++++++++++ Source/NSNibBindingConnector.m | 1 + Source/NSOutlineView.m | 36 +++++++++++++++++++++---------- Source/NSTreeController.m | 8 +++++-- 7 files changed, 55 insertions(+), 15 deletions(-) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index d6d1c439f2..f3bfce3179 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -47,7 +47,7 @@ APPKIT_EXPORT_CLASS NSString *_countKeyPath; NSString *_leafKeyPath; NSArray *_sortDescriptors; - NSArray *_arranged_objects; + NSTreeNode *_arranged_objects; NSMutableArray *_selection_index_paths; BOOL _alwaysUsesMultipleValuesMarker; @@ -113,7 +113,7 @@ APPKIT_EXPORT_CLASS /** * All objects managed by this tree controller. */ -- (id) arrangedObjects; +- (NSTreeNode *) arrangedObjects; /** * An NSArray containing all selected objects. diff --git a/Headers/AppKit/NSTreeNode.h b/Headers/AppKit/NSTreeNode.h index 5fdce914d1..4f57f685ca 100644 --- a/Headers/AppKit/NSTreeNode.h +++ b/Headers/AppKit/NSTreeNode.h @@ -26,6 +26,7 @@ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #ifndef _GNUstep_H_NSTreeNode #define _GNUstep_H_NSTreeNode diff --git a/Source/GSBindingHelpers.h b/Source/GSBindingHelpers.h index 7d74001ad4..4e3a3917d7 100644 --- a/Source/GSBindingHelpers.h +++ b/Source/GSBindingHelpers.h @@ -44,6 +44,7 @@ BOOL inReverseSet; } ++ (void) _printObjectTable; + (void) exposeBinding: (NSString *)binding forClass: (Class)clazz; + (NSArray *) exposedBindingsForClass: (Class)clazz; + (GSKeyValueBinding *) getBinding: (NSString *)binding diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index 12306c7935..a00a3111fe 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -141,6 +141,21 @@ void GSBindingInvokeAction(NSString *targetKey, NSString *argumentKey, @implementation GSKeyValueBinding ++ (void) _printObjectTable +{ + NSArray *keys = NSAllMapTableKeys(objectTable); + id k = nil; + NSEnumerator *en = [keys objectEnumerator]; + + NSLog(@"==== objectTable contents ===="); + while ((k = [en nextObject]) != nil) + { + id v = NSMapGet(objectTable, k); + NSLog(@"k = %@, v = %@", k, v); + } + NSLog(@"END: objectTable contents ===="); +} + + (void) initialize { if (self == [GSKeyValueBinding class]) @@ -192,8 +207,12 @@ + (GSKeyValueBinding *) getBinding: (NSString *)binding if (!objectTable) return nil; + // NSLog(@"+++ called with %@, %@", binding, anObject); + // [self _printObjectTable]; + [bindingLock lock]; bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)anObject); + // NSLog(@"+++ Bindings found for %@ => %@", anObject, bindings); if (bindings != nil) { theBinding = (GSKeyValueBinding*)[bindings objectForKey: binding]; diff --git a/Source/NSNibBindingConnector.m b/Source/NSNibBindingConnector.m index 4444d056d5..a354005e3b 100644 --- a/Source/NSNibBindingConnector.m +++ b/Source/NSNibBindingConnector.m @@ -158,6 +158,7 @@ - (id) initWithCoder: (NSCoder*)aDecoder if ([aDecoder containsValueForKey: @"NSBinding"]) { ASSIGN(_binding, [aDecoder decodeObjectForKey: @"NSBinding"]); + NSLog(@"_binding = %@", _binding); } if ([aDecoder containsValueForKey: @"NSKeyPath"]) { diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index e81ea3c972..4bcb74600a 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -177,6 +177,7 @@ + (void) initialize // Bindings.. [self exposeBinding: NSContentBinding]; + // [self exposeBinding: NSContentArrayBinding]; [self exposeBinding: NSSelectionIndexesBinding]; [self exposeBinding: NSSortDescriptorsBinding]; } @@ -1830,15 +1831,27 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb row: (NSInteger) index { id result = nil; - - if ([_dataSource respondsToSelector: - @selector(outlineView:objectValueForTableColumn:byItem:)]) - { - id item = [self itemAtRow: index]; - result = [_dataSource outlineView: self - objectValueForTableColumn: tb - byItem: item]; + // If we have content binding the data source is used only + // like a delegate + GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: tb]; + if (theBinding != nil) + { + NSLog(@"theBinding = %@", theBinding); + result = [_items objectAtIndex: index]; + } + else + { + if ([_dataSource respondsToSelector: + @selector(outlineView:objectValueForTableColumn:byItem:)]) + { + id item = [self itemAtRow: index]; + + result = [_dataSource outlineView: self + objectValueForTableColumn: tb + byItem: item]; + } } return result; @@ -1991,9 +2004,9 @@ - (void) _loadDictionaryStartingWith: (id) startitem NSString *childrenKeyPath = [tc childrenKeyPath]; NSString *countKeyPath = [tc countKeyPath]; - NSLog(@"leafKeyPath = %@", leafKeyPath); - NSLog(@"childrenKeyPath = %@", childrenKeyPath); - NSLog(@"countKeyPath = %@", countKeyPath); + // NSLog(@"leafKeyPath = %@", leafKeyPath); + // NSLog(@"childrenKeyPath = %@", childrenKeyPath); + // NSLog(@"countKeyPath = %@", countKeyPath); if (startitem == nil) { @@ -2094,6 +2107,7 @@ - (void)_openItem: (id)item id object; id sitem = (item == nil) ? (id)[NSNull null] : (id)item; + // NSLog(@"openItem: %@", item); // open the item... if (item != nil) { diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index cb3dee6ab1..00f921072a 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -37,6 +37,7 @@ #import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSTreeController.h" +#import "AppKit/NSTreeNode.h" #import "GSBindingHelpers.h" #import "GSFastEnumeration.h" @@ -47,7 +48,8 @@ + (void) initialize { if (self == [NSTreeController class]) { - [self exposeBinding: NSContentArrayBinding]; + // [self exposeBinding: NSContentArrayBinding]; + [self exposeBinding: NSContentBinding]; [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; } @@ -164,7 +166,7 @@ - (NSArray*) arrangeObjects: (NSArray*)obj return [temp sortedArrayUsingDescriptors: _sortDescriptors]; } -- (id) arrangedObjects +- (NSTreeNode *) arrangedObjects { if (_arranged_objects == nil) { @@ -178,8 +180,10 @@ - (void) rearrangeObjects NSLog(@"---- rearrangeObjects"); [self willChangeValueForKey: @"arrangedObjects"]; DESTROY(_arranged_objects); + NSLog(@"-- _content = %@", _content); _arranged_objects = [[GSObservableArray alloc] initWithArray: [self arrangeObjects: _content]]; + NSLog(@"-- _arranged_objects = %@", _arranged_objects); [self didChangeValueForKey: @"arrangedObjects"]; } From 3dfcdf65701fa3d806ccf5481fc09967ff0c4f88 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 25 Jun 2024 17:11:57 -0400 Subject: [PATCH 04/72] Update loading mechanism and add new proxy class for tree node --- Source/GNUmakefile | 1 + Source/GSControllerTreeProxy.h | 52 +++++++++++++++++++++++++++++ Source/GSControllerTreeProxy.m | 61 ++++++++++++++++++++++++++++++++++ Source/NSOutlineView.m | 50 +++++++++++++++------------- Source/NSTreeController.m | 18 ++++++---- Source/NSTreeNode.m | 6 ++++ 6 files changed, 158 insertions(+), 30 deletions(-) create mode 100644 Source/GSControllerTreeProxy.h create mode 100644 Source/GSControllerTreeProxy.m diff --git a/Source/GNUmakefile b/Source/GNUmakefile index 5e1409a101..0943221c4b 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -303,6 +303,7 @@ NSWindowController.m \ NSWorkspace.m \ GSAnimator.m \ GSAutocompleteWindow.m \ +GSControllerTreeProxy.m \ GSDisplayServer.m \ GSHelpManagerPanel.m \ GSInfoPanel.m \ diff --git a/Source/GSControllerTreeProxy.h b/Source/GSControllerTreeProxy.h new file mode 100644 index 0000000000..67fceae047 --- /dev/null +++ b/Source/GSControllerTreeProxy.h @@ -0,0 +1,52 @@ +/* Definition of class GSControllerTreeProxy + Copyright (C) 2024 Free Software Foundation, Inc. + + By: Gregory John Casamento + Date: 24-06-2024 + + This file is part of the GNUstep 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.1 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; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110 USA. +*/ + +#ifndef _GSControllerTreeProxy_h_GNUSTEP_GUI_INCLUDE +#define _GSControllerTreeProxy_h_GNUSTEP_GUI_INCLUDE + +#import "AppKit/NSTreeNode.h" + +@class NSTreeController; + +#if defined(__cplusplus) +extern "C" { +#endif + +@interface GSControllerTreeProxy : NSTreeNode +{ + NSTreeController *_controller; +} + +- (instancetype) initWithRepresentedObject: (id)representedObject + withController: (id)controller; +- (NSUInteger) count; + +@end + +#if defined(__cplusplus) +} +#endif + +#endif /* _GSControllerTreeProxy_h_GNUSTEP_GUI_INCLUDE */ + diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m new file mode 100644 index 0000000000..2531febb66 --- /dev/null +++ b/Source/GSControllerTreeProxy.m @@ -0,0 +1,61 @@ +/* Implementation of class GSControllerTreeProxy + Copyright (C) 2024 Free Software Foundation, Inc. + + By: Gregory John Casamento + Date: 24-06-2024 + + This file is part of the GNUstep 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.1 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; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110 USA. +*/ + +#import +#import +#import + +#import "AppKit/NSTreeController.h" + +#import "GSControllerTreeProxy.h" +#import "GSBindingHelpers.h" + +@implementation GSControllerTreeProxy + +- (instancetype) initWithRepresentedObject: (id)representedObject + withController: (id)controller +{ + self = [super initWithRepresentedObject: representedObject]; + if (self != nil) + { + ASSIGN(_controller, controller); + } + return self; +} + +- (NSUInteger) count +{ + NSDictionary *ro = [self representedObject]; + NSArray *children = [ro objectForKey: @"children"]; + + return [children count]; +} + +- (id) value +{ + return nil; +} + +@end + diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 4bcb74600a..db5d131c1a 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1834,7 +1834,7 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb // If we have content binding the data source is used only // like a delegate - GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSContentBinding + GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSValueBinding forObject: tb]; if (theBinding != nil) { @@ -1982,7 +1982,7 @@ - (BOOL) _isItemLoaded: (id)item - (void) _loadDictionaryStartingWith: (id) startitem atLevel: (NSInteger) level { - GSKeyValueBinding *theBinding; + GSKeyValueBinding *theBinding = nil; NSInteger num = 0; NSInteger i = 0; id sitem = (startitem == nil) ? (id)[NSNull null] : (id)startitem; @@ -1992,50 +1992,52 @@ - (void) _loadDictionaryStartingWith: (id) startitem forObject: self]; if (theBinding != nil) { + id observedObject = [theBinding observedObject]; + NSTreeController *tc = (NSTreeController *)observedObject; + NSArray *children = nil; + // NSString *leafKeyPath = [tc leafKeyPath]; + /* Implement logic to build the internal data structure here using * bindings... */ - id observedObject = [theBinding observedObject]; - + if ([observedObject isKindOfClass: [NSTreeController class]]) { - NSTreeController *tc = (NSTreeController *)observedObject; - NSString *leafKeyPath = [tc leafKeyPath]; - NSString *childrenKeyPath = [tc childrenKeyPath]; - NSString *countKeyPath = [tc countKeyPath]; - - // NSLog(@"leafKeyPath = %@", leafKeyPath); - // NSLog(@"childrenKeyPath = %@", childrenKeyPath); - // NSLog(@"countKeyPath = %@", countKeyPath); - if (startitem == nil) { - NSArray *items = (NSArray *)[theBinding destinationValue]; - NSLog(@"items = %@", items); + NSTreeNode *node = (NSTreeNode *)[theBinding destinationValue]; + NSDictionary *representedObject = [node representedObject]; + + children = [representedObject objectForKey: @"children"]; + num = [children count]; + } + else + { + NSString *childrenKeyPath = [tc childrenKeyPath]; + NSString *countKeyPath = [tc countKeyPath]; + NSNumber *n = [sitem valueForKeyPath: countKeyPath]; - num = [items count]; + num = [n integerValue]; + children = [sitem valueForKeyPath: childrenKeyPath]; } if (num > 0) { - anarray = [NSMutableArray array]; + anarray = [NSMutableArray arrayWithCapacity: num]; NSMapInsert(_itemDict, sitem, anarray); } NSMapInsert(_levelOfItems, sitem, [NSNumber numberWithInteger: level]); - /* for (i = 0; i < num; i++) { - id anitem = [_dataSource outlineView: self - child: i - ofItem: startitem]; - + id anitem = [children objectAtIndex: i]; + + NSLog(@"anitem = %@, level = %d", anitem, level); [anarray addObject: anitem]; [self _loadDictionaryStartingWith: anitem atLevel: level + 1]; } - */ } } else @@ -2057,7 +2059,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem if (num > 0) { - anarray = [NSMutableArray array]; + anarray = [NSMutableArray arrayWithCapacity: num]; NSMapInsert(_itemDict, sitem, anarray); } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 00f921072a..1106f88dda 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -29,6 +29,7 @@ #import #import +#import #import #import #import @@ -41,6 +42,7 @@ #import "GSBindingHelpers.h" #import "GSFastEnumeration.h" +#import "GSControllerTreeProxy.h" @implementation NSTreeController @@ -48,7 +50,7 @@ + (void) initialize { if (self == [NSTreeController class]) { - // [self exposeBinding: NSContentArrayBinding]; + [self exposeBinding: NSContentArrayBinding]; [self exposeBinding: NSContentBinding]; [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; @@ -177,13 +179,17 @@ - (NSTreeNode *) arrangedObjects - (void) rearrangeObjects { - NSLog(@"---- rearrangeObjects"); [self willChangeValueForKey: @"arrangedObjects"]; DESTROY(_arranged_objects); - NSLog(@"-- _content = %@", _content); - _arranged_objects = [[GSObservableArray alloc] - initWithArray: [self arrangeObjects: _content]]; - NSLog(@"-- _arranged_objects = %@", _arranged_objects); + + if ([_content isKindOfClass: [NSArray class]]) + { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject: _content + forKey: @"children"]; + _arranged_objects = [[GSControllerTreeProxy alloc] initWithRepresentedObject: dictionary + withController: self]; + } + [self didChangeValueForKey: @"arrangedObjects"]; } diff --git a/Source/NSTreeNode.m b/Source/NSTreeNode.m index 2d80fcdd2b..967eb96d03 100644 --- a/Source/NSTreeNode.m +++ b/Source/NSTreeNode.m @@ -248,4 +248,10 @@ - (void) sortWithSortDescriptors: (NSArray*)sortDescs recursively: (BOOL)flag } } +- (NSString *) description +{ + return [NSString stringWithFormat: @"<%@> _representedObject = %@, _childNode = %@, _parentNode = %@", + [super description], _representedObject, _childNodes, _parentNode]; +} + @end From 340b95c9fa1bbe3b7e314fa9c5f4e887db14e6a1 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 25 Jun 2024 19:43:12 -0400 Subject: [PATCH 05/72] Limit the items we grab from the binding. Check if item is expanded, etc --- Source/NSOutlineView.m | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index db5d131c1a..7bc33fa9d4 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1995,12 +1995,10 @@ - (void) _loadDictionaryStartingWith: (id) startitem id observedObject = [theBinding observedObject]; NSTreeController *tc = (NSTreeController *)observedObject; NSArray *children = nil; - // NSString *leafKeyPath = [tc leafKeyPath]; - + /* Implement logic to build the internal data structure here using * bindings... - */ - + */ if ([observedObject isKindOfClass: [NSTreeController class]]) { if (startitem == nil) @@ -2015,10 +2013,17 @@ - (void) _loadDictionaryStartingWith: (id) startitem { NSString *childrenKeyPath = [tc childrenKeyPath]; NSString *countKeyPath = [tc countKeyPath]; - NSNumber *n = [sitem valueForKeyPath: countKeyPath]; + NSNumber *countValue = [sitem valueForKeyPath: countKeyPath]; + NSString *leafKeyPath = [tc leafKeyPath]; + NSNumber *leafValue = [sitem valueForKeyPath: leafKeyPath]; + BOOL leaf = [leafValue boolValue]; - num = [n integerValue]; - children = [sitem valueForKeyPath: childrenKeyPath]; + if (leaf == NO + && [self isItemExpanded: startitem]) + { + num = [countValue integerValue]; + children = [sitem valueForKeyPath: childrenKeyPath]; + } } if (num > 0) @@ -2033,7 +2038,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem { id anitem = [children objectAtIndex: i]; - NSLog(@"anitem = %@, level = %d", anitem, level); + NSLog(@"-- anitem = %@, level = %ld", anitem, level); [anarray addObject: anitem]; [self _loadDictionaryStartingWith: anitem atLevel: level + 1]; @@ -2070,7 +2075,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem id anitem = [_dataSource outlineView: self child: i ofItem: startitem]; - + NSLog(@"++ anitem = %@, level = %ld", anitem, level); [anarray addObject: anitem]; [self _loadDictionaryStartingWith: anitem atLevel: level + 1]; From fb2f605e18a02e354a41e21906db17f602e6a263 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 26 Jun 2024 18:17:21 -0400 Subject: [PATCH 06/72] Update drawing code to handle binding, add NSString private method to helpers, remove debugging code from binding connector and outline --- Source/GSBindingHelpers.h | 4 ++++ Source/GSThemeDrawing.m | 17 ++++++++++++----- Source/NSKeyValueBinding.m | 34 ++++++++++++++++++++++++++++++++++ Source/NSNibBindingConnector.m | 1 - Source/NSOutlineView.m | 24 +++++++++++++++++------- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/Source/GSBindingHelpers.h b/Source/GSBindingHelpers.h index 4e3a3917d7..e56546fb94 100644 --- a/Source/GSBindingHelpers.h +++ b/Source/GSBindingHelpers.h @@ -87,4 +87,8 @@ } @end +@interface NSString (PrivatePathExtension) +- (NSString *) stringByRemovingFirstKeyPath; +@end + #endif //_GS_BINDING_HELPER_H diff --git a/Source/GSThemeDrawing.m b/Source/GSThemeDrawing.m index 8c817a21a5..085782b518 100644 --- a/Source/GSThemeDrawing.m +++ b/Source/GSThemeDrawing.m @@ -44,6 +44,7 @@ #import "AppKit/NSGraphics.h" #import "AppKit/NSImage.h" #import "AppKit/NSImageView.h" +#import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSMenuView.h" #import "AppKit/NSMenuItemCell.h" #import "AppKit/NSOutlineView.h" @@ -70,6 +71,7 @@ #import "GNUstepGUI/GSToolbarView.h" #import "GNUstepGUI/GSTitleView.h" +#import "GSBindingHelpers.h" /* a border width of 5 gives a reasonable compromise between Cocoa metrics and looking good */ /* 7.0 gives us the NeXT Look (which is 8 pix wide including the shadow) */ @@ -3284,7 +3286,7 @@ - (void) drawTableViewRect: (NSRect)aRect { endingRow = numberOfRows - 1; } - // NSLog(@"drawRect : %d-%d", startingRow, endingRow); + // NSLog(@"drawRect : %d-%d", startingRow, endingRow); { SEL sel = @selector(drawRow:clipRect:); void (*imp)(id, SEL, NSInteger, NSRect); @@ -3408,6 +3410,7 @@ - (void) drawTableViewRow: (NSInteger)rowIndex { const BOOL columnSelected = [tableView isColumnSelected: i]; const BOOL cellSelected = (rowSelected || columnSelected); + tb = [tableColumns objectAtIndex: i]; cell = [tb dataCellForRow: rowIndex]; [tableView _willDisplayCell: cell @@ -3531,8 +3534,12 @@ - (void) drawOutlineViewRow: (NSInteger)rowIndex NSInteger i; id dataSource = [outlineView dataSource]; NSTableColumn *outlineTableColumn = [outlineView outlineTableColumn]; + GSKeyValueBinding *theBinding = nil; - if (dataSource == nil) + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: outlineView]; + + if (dataSource == nil && theBinding == nil) { return; } @@ -3566,9 +3573,9 @@ - (void) drawOutlineViewRow: (NSInteger)rowIndex } else { - [cell setObjectValue: [dataSource outlineView: outlineView - objectValueForTableColumn: tb - byItem: item]]; + id value = [outlineView _objectValueForTableColumn: tb + row: rowIndex]; + [cell setObjectValue: value]; } drawingRect = [outlineView frameOfCellAtColumn: i diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index a00a3111fe..d95fa35ce0 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -122,6 +122,40 @@ - (void) unbind: (NSString *)binding @end +@implementation NSString (PrivatePathExtension) + +- (NSString *) stringByRemovingFirstKeyPath +{ + NSArray *components = [self componentsSeparatedByString: @"."]; + NSString *result = @""; + NSEnumerator *en = [components objectEnumerator]; + NSString *component = nil; + NSUInteger i = 0; + + if ([components count] == 1) + { + return self; + } + + while ((component = [en nextObject]) != nil) + { + if (i > 0) + { + result = [result stringByAppendingString: component]; + if ([[components lastObject] isEqual: component] == NO) + { + result = [result stringByAppendingString: @"."]; + } + } + + i++; + } + + return result; +} + +@end + static NSRecursiveLock *bindingLock = nil; static NSMapTable *classTable = NULL; //available bindings static NSMapTable *objectTable = NULL; //bound bindings diff --git a/Source/NSNibBindingConnector.m b/Source/NSNibBindingConnector.m index a354005e3b..4444d056d5 100644 --- a/Source/NSNibBindingConnector.m +++ b/Source/NSNibBindingConnector.m @@ -158,7 +158,6 @@ - (id) initWithCoder: (NSCoder*)aDecoder if ([aDecoder containsValueForKey: @"NSBinding"]) { ASSIGN(_binding, [aDecoder decodeObjectForKey: @"NSBinding"]); - NSLog(@"_binding = %@", _binding); } if ([aDecoder containsValueForKey: @"NSKeyPath"]) { diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 7bc33fa9d4..b1124b1b64 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1834,12 +1834,19 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb // If we have content binding the data source is used only // like a delegate - GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSValueBinding - forObject: tb]; - if (theBinding != nil) + // GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSValueBinding + // forObject: tb]; + NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding forObject: tb]; + if (info != nil) { - NSLog(@"theBinding = %@", theBinding); - result = [_items objectAtIndex: index]; + id theItem = [_items objectAtIndex: index]; + NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; + NSString *keyPath = [ikp stringByRemovingFirstKeyPath]; + + // NSLog(@"info = %@, ikp = %@, keyPath = %@", info, ikp, keyPath); + + result = [theItem valueForKeyPath: keyPath]; + // NSLog(@"result = %@", result); } else { @@ -2038,7 +2045,6 @@ - (void) _loadDictionaryStartingWith: (id) startitem { id anitem = [children objectAtIndex: i]; - NSLog(@"-- anitem = %@, level = %ld", anitem, level); [anarray addObject: anitem]; [self _loadDictionaryStartingWith: anitem atLevel: level + 1]; @@ -2075,7 +2081,6 @@ - (void) _loadDictionaryStartingWith: (id) startitem id anitem = [_dataSource outlineView: self child: i ofItem: startitem]; - NSLog(@"++ anitem = %@, level = %ld", anitem, level); [anarray addObject: anitem]; [self _loadDictionaryStartingWith: anitem atLevel: level + 1]; @@ -2358,4 +2363,9 @@ - (void) _autoCollapse [autoExpanded removeAllObjects]; } +- (void) awakeFromNib +{ + [self reloadData]; +} + @end From 930e3b6c0f719e06631a8b09c9e639d4a2863778 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 27 Jun 2024 05:37:01 -0400 Subject: [PATCH 07/72] Update isExpandable: to be used either in the case where we have a dataSource or if we have a binding, also use it in the loadItem... method so the logic for this is in ONE place --- Source/NSOutlineView.m | 86 ++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index b1124b1b64..23b7d19985 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -450,11 +450,57 @@ - (CGFloat) indentationPerLevel */ - (BOOL) isExpandable: (id)item { - if (item == nil) + BOOL result = NO; + GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + if (theBinding != nil) { - return NO; + BOOL leaf = YES; + id observedObject = [theBinding observedObject]; + NSTreeController *tc = (NSTreeController *)observedObject; + NSString *leafKeyPath = [tc leafKeyPath]; + + if (leafKeyPath == nil) + { + NSString *countKeyPath = [tc countKeyPath]; + + if (countKeyPath == nil) + { + NSString *childrenKeyPath = [tc childrenKeyPath]; + + if (childrenKeyPath == nil) + { + result = NO; + } + else + { + id children = [item valueForKeyPath: childrenKeyPath]; + + leaf = ([children count] > 0); + } + } + else + { + NSNumber *countValue = [item valueForKeyPath: countKeyPath]; + + leaf = ([countValue integerValue] > 0); + } + } + else + { + NSNumber *leafValue = [item valueForKeyPath: leafKeyPath]; + + leaf = [leafValue boolValue]; + } + + result = !leaf; // if item is a leaf, it's not expandable... + } + else if (item != nil) + { + result = [_dataSource outlineView: self isItemExpandable: item]; } - return [_dataSource outlineView: self isItemExpandable: item]; + + return result; } /** @@ -1834,8 +1880,6 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb // If we have content binding the data source is used only // like a delegate - // GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSValueBinding - // forObject: tb]; NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding forObject: tb]; if (info != nil) { @@ -1843,10 +1887,10 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; NSString *keyPath = [ikp stringByRemovingFirstKeyPath]; - // NSLog(@"info = %@, ikp = %@, keyPath = %@", info, ikp, keyPath); - + // Here we are getting the last part of the keyPath since elsewhere in this class + // we are recursively storing the contents of arrangedObjects (for example) to + // display it as an outline in _loadDictionaryStartingWith:atLevel:. result = [theItem valueForKeyPath: keyPath]; - // NSLog(@"result = %@", result); } else { @@ -2013,21 +2057,25 @@ - (void) _loadDictionaryStartingWith: (id) startitem NSTreeNode *node = (NSTreeNode *)[theBinding destinationValue]; NSDictionary *representedObject = [node representedObject]; + /* Per the documentation 10.4/5+ uses NSTreeNode as the return value for + * the contents of this tree node consists of a dictionary with a single + * key of "children". This is per the tests for this at + * https://github.com/gcasa/NSTreeController_test. Specifically it returns + * _NSControllerTreeProxy. The equivalent of that class in GNUstep is + * GSTreeControllerProxy. + */ children = [representedObject objectForKey: @"children"]; num = [children count]; } else { - NSString *childrenKeyPath = [tc childrenKeyPath]; - NSString *countKeyPath = [tc countKeyPath]; - NSNumber *countValue = [sitem valueForKeyPath: countKeyPath]; - NSString *leafKeyPath = [tc leafKeyPath]; - NSNumber *leafValue = [sitem valueForKeyPath: leafKeyPath]; - BOOL leaf = [leafValue boolValue]; - - if (leaf == NO + if ([self isExpandable: startitem] // leaf == NO && [self isItemExpanded: startitem]) { + NSString *childrenKeyPath = [tc childrenKeyPath]; + NSString *countKeyPath = [tc countKeyPath]; + NSNumber *countValue = [sitem valueForKeyPath: countKeyPath]; + num = [countValue integerValue]; children = [sitem valueForKeyPath: childrenKeyPath]; } @@ -2060,9 +2108,9 @@ - (void) _loadDictionaryStartingWith: (id) startitem * usable with a big tree structure. For example, an outline view to browse * file system would try to traverse every file/directory on -reloadData. */ - if ((startitem == nil - || [_dataSource outlineView: self isItemExpandable: startitem]) - && [self isItemExpanded: startitem]) + if (startitem == nil + || ([self isExpandable: startitem] // [_dataSource outlineView: self isItemExpandable: startitem]) + && [self isItemExpanded: startitem])) { num = [_dataSource outlineView: self numberOfChildrenOfItem: startitem]; From 6b808f2d24072c2faa589b59a4548693dd9a7545 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 27 Jun 2024 05:54:06 -0400 Subject: [PATCH 08/72] Whitespace cleanup, remove unneeded methods, remove NSLogs --- Source/GSBindingHelpers.h | 1 - Source/GSThemeDrawing.m | 2 +- Source/NSKeyValueBinding.m | 17 +---------------- Source/NSOutlineView.m | 28 ++++++++++++++-------------- 4 files changed, 16 insertions(+), 32 deletions(-) diff --git a/Source/GSBindingHelpers.h b/Source/GSBindingHelpers.h index e56546fb94..781b38d8f8 100644 --- a/Source/GSBindingHelpers.h +++ b/Source/GSBindingHelpers.h @@ -44,7 +44,6 @@ BOOL inReverseSet; } -+ (void) _printObjectTable; + (void) exposeBinding: (NSString *)binding forClass: (Class)clazz; + (NSArray *) exposedBindingsForClass: (Class)clazz; + (GSKeyValueBinding *) getBinding: (NSString *)binding diff --git a/Source/GSThemeDrawing.m b/Source/GSThemeDrawing.m index 085782b518..64d4e4bd9b 100644 --- a/Source/GSThemeDrawing.m +++ b/Source/GSThemeDrawing.m @@ -3286,7 +3286,7 @@ - (void) drawTableViewRect: (NSRect)aRect { endingRow = numberOfRows - 1; } - // NSLog(@"drawRect : %d-%d", startingRow, endingRow); + // NSLog(@"drawRect : %ld-%ld", startingRow, endingRow); { SEL sel = @selector(drawRow:clipRect:); void (*imp)(id, SEL, NSInteger, NSRect); diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index d95fa35ce0..d5afd257b4 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -136,7 +136,7 @@ - (NSString *) stringByRemovingFirstKeyPath { return self; } - + while ((component = [en nextObject]) != nil) { if (i > 0) @@ -175,21 +175,6 @@ void GSBindingInvokeAction(NSString *targetKey, NSString *argumentKey, @implementation GSKeyValueBinding -+ (void) _printObjectTable -{ - NSArray *keys = NSAllMapTableKeys(objectTable); - id k = nil; - NSEnumerator *en = [keys objectEnumerator]; - - NSLog(@"==== objectTable contents ===="); - while ((k = [en nextObject]) != nil) - { - id v = NSMapGet(objectTable, k); - NSLog(@"k = %@, v = %@", k, v); - } - NSLog(@"END: objectTable contents ===="); -} - + (void) initialize { if (self == [GSKeyValueBinding class]) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 23b7d19985..3dbd0afaec 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -451,7 +451,7 @@ - (CGFloat) indentationPerLevel - (BOOL) isExpandable: (id)item { BOOL result = NO; - GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSContentBinding + GSKeyValueBinding *theBinding = [GSKeyValueBinding getBinding: NSContentBinding forObject: self]; if (theBinding != nil) { @@ -492,14 +492,14 @@ - (BOOL) isExpandable: (id)item leaf = [leafValue boolValue]; } - + result = !leaf; // if item is a leaf, it's not expandable... } else if (item != nil) { result = [_dataSource outlineView: self isItemExpandable: item]; } - + return result; } @@ -757,7 +757,7 @@ - (BOOL)shouldCollapseAutoExpandedItemsForDeposited: (BOOL)deposited - (void) setDataSource: (id)anObject { GSKeyValueBinding *theBinding; - + #define CHECK_REQUIRED_METHOD(selector_name) \ if (anObject && ![anObject respondsToSelector: @selector(selector_name)]) \ [NSException raise: NSInternalInconsistencyException \ @@ -774,7 +774,7 @@ - (void) setDataSource: (id)anObject // This method is @optional in NSOutlineViewDataSource as of macOS10.0 // CHECK_REQUIRED_METHOD(outlineView:objectValueForTableColumn:byItem:); } - + // Is the data source editable? _dataSource_editable = [anObject respondsToSelector: @selector(outlineView:setObjectValue:forTableColumn:byItem:)]; @@ -1898,7 +1898,7 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb @selector(outlineView:objectValueForTableColumn:byItem:)]) { id item = [self itemAtRow: index]; - + result = [_dataSource outlineView: self objectValueForTableColumn: tb byItem: item]; @@ -2037,9 +2037,9 @@ - (void) _loadDictionaryStartingWith: (id) startitem NSInteger num = 0; NSInteger i = 0; id sitem = (startitem == nil) ? (id)[NSNull null] : (id)startitem; - NSMutableArray *anarray = nil; + NSMutableArray *anarray = nil; - theBinding = [GSKeyValueBinding getBinding: NSContentBinding + theBinding = [GSKeyValueBinding getBinding: NSContentBinding forObject: self]; if (theBinding != nil) { @@ -2049,7 +2049,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem /* Implement logic to build the internal data structure here using * bindings... - */ + */ if ([observedObject isKindOfClass: [NSTreeController class]]) { if (startitem == nil) @@ -2086,7 +2086,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem anarray = [NSMutableArray arrayWithCapacity: num]; NSMapInsert(_itemDict, sitem, anarray); } - + NSMapInsert(_levelOfItems, sitem, [NSNumber numberWithInteger: level]); for (i = 0; i < num; i++) @@ -2115,15 +2115,15 @@ - (void) _loadDictionaryStartingWith: (id) startitem num = [_dataSource outlineView: self numberOfChildrenOfItem: startitem]; } - + if (num > 0) { anarray = [NSMutableArray arrayWithCapacity: num]; NSMapInsert(_itemDict, sitem, anarray); } - + NSMapInsert(_levelOfItems, sitem, [NSNumber numberWithInteger: level]); - + for (i = 0; i < num; i++) { id anitem = [_dataSource outlineView: self @@ -2370,7 +2370,7 @@ - (NSView *) viewAtColumn: (NSInteger)column row: (NSInteger)row makeIfNecessary drawingRect: drawingRect rowIndex: row]; } - + if (view == nil && flag == YES) { From 0f4e1711d02e3f7acbab8c72fe28a3530afc9597 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 27 Jun 2024 06:12:07 -0400 Subject: [PATCH 09/72] Update changelog --- ChangeLog | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 38b0ee6244..35004fcc87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2024-06-27 Gregory John Casamento + + * Headers/AppKit/NSTreeController.h: Update header + * Headers/AppKit/NSTreeNode.h: Update header + * Source/GNUmakefile: Add new class + * Source/GSBindingHelpers.h: Add NSString category + * Source/GSControllerTreeProxy.[hm]: Proxy class + for NSTreeController, a subclass of NSTreeNode. + * Source/GSThemeDrawing.m: Optimize code a bit and + add changes for binfings. + * Source/GSXib5KeyedUnarchiver.m: Add support for new keys + on NSTreeController. + * Source/NSKeyValueBinding.m: Add new methods to + GSKeyValueBinding + * Source/NSOutlineView.m: Add support for bindings. + * Source/NSTreeController.m: Implement new methods. + * Source/NSTreeNode.m: Implement new methods + 2024-06-07 Gregory John Casamento * Headers/Additions/GNUstepGUI/GSTheme.h: Add new methods From 647076cb8ae926843a6250c505c6347dd8e5febd Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 28 Jun 2024 08:39:39 -0400 Subject: [PATCH 10/72] Update copyWithZone: method, provide simple implementation of addSelectionIndexPaths: --- Source/NSTreeController.m | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 1106f88dda..c33d40bbb8 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -3,10 +3,10 @@ The tree controller class. - Copyright (C) 2012 Free Software Foundation, Inc. + Copyright (C) 2012, 2024 Free Software Foundation, Inc. Author: Gregory Casamento - Date: 2012 + Date: 2012, 2024 This file is part of the GNUstep GUI Library. @@ -98,8 +98,14 @@ - (void) dealloc - (BOOL) addSelectionIndexPaths: (NSArray *)indexPaths { - // FIXME - return NO; + BOOL f = [self commitEditing]; + + if (YES == f) + { + [_selection_index_paths addObjectsFromArray: indexPaths]; + } + + return f; } - (BOOL) alwaysUsesMultipleValuesMarker @@ -520,9 +526,20 @@ - (void) encodeWithCoder: (NSCoder*)coder - (id) copyWithZone: (NSZone*)zone { - NSData *data = [NSArchiver archivedDataWithRootObject: self]; - id result = [NSUnarchiver unarchiveObjectWithData: data]; - return result; + id copy = [[NSTreeController allocWithZone: zone] initWithContent: [self content]]; + + if (copy != nil) + { + [copy setChildrenKeyPath: [self childrenKeyPath]]; + [copy setCountKeyPath: [self countKeyPath]]; + [copy setLeafKeyPath: [self leafKeyPath]]; + + [copy setAvoidsEmptySelection: [self avoidsEmptySelection]]; + [copy setPreservesSelection: [self preservesSelection]]; + [copy setSelectsInsertedObjects: [self selectsInsertedObjects]]; + } + + return copy; } @end From 786b48dd1bb8195de5f4c8c9f618e463cd6c8f71 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 28 Jun 2024 09:45:41 -0400 Subject: [PATCH 11/72] Remove unneeded method --- Source/NSTreeController.m | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index c33d40bbb8..ba18e2948d 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -168,12 +168,6 @@ - (BOOL) setSelectionIndexPaths: (NSArray *)indexPaths return f; } -- (NSArray*) arrangeObjects: (NSArray*)obj -{ - NSArray *temp = obj; - return [temp sortedArrayUsingDescriptors: _sortDescriptors]; -} - - (NSTreeNode *) arrangedObjects { if (_arranged_objects == nil) From aa4f9b5dbf26a889f6efc24916022865de13cc93 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 29 Jun 2024 21:48:27 -0400 Subject: [PATCH 12/72] Remove NSString category per discussion with @fredkiefer --- Source/GSBindingHelpers.h | 4 ---- Source/NSKeyValueBinding.m | 34 ---------------------------------- Source/NSOutlineView.m | 32 +++++++++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/Source/GSBindingHelpers.h b/Source/GSBindingHelpers.h index 781b38d8f8..7d74001ad4 100644 --- a/Source/GSBindingHelpers.h +++ b/Source/GSBindingHelpers.h @@ -86,8 +86,4 @@ } @end -@interface NSString (PrivatePathExtension) -- (NSString *) stringByRemovingFirstKeyPath; -@end - #endif //_GS_BINDING_HELPER_H diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index d5afd257b4..2c93b64961 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -122,40 +122,6 @@ - (void) unbind: (NSString *)binding @end -@implementation NSString (PrivatePathExtension) - -- (NSString *) stringByRemovingFirstKeyPath -{ - NSArray *components = [self componentsSeparatedByString: @"."]; - NSString *result = @""; - NSEnumerator *en = [components objectEnumerator]; - NSString *component = nil; - NSUInteger i = 0; - - if ([components count] == 1) - { - return self; - } - - while ((component = [en nextObject]) != nil) - { - if (i > 0) - { - result = [result stringByAppendingString: component]; - if ([[components lastObject] isEqual: component] == NO) - { - result = [result stringByAppendingString: @"."]; - } - } - - i++; - } - - return result; -} - -@end - static NSRecursiveLock *bindingLock = nil; static NSMapTable *classTable = NULL; //available bindings static NSMapTable *objectTable = NULL; //bound bindings diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 3dbd0afaec..322bcf8011 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1873,6 +1873,36 @@ - (BOOL) _isDraggingSource @selector(outlineView:writeItems:toPasteboard:)]; } +- (NSString *) _stringByRemovingFirstKeyPath: (NSString *)path +{ + NSArray *components = [path componentsSeparatedByString: @"."]; + NSString *result = @""; + NSEnumerator *en = [components objectEnumerator]; + NSString *component = nil; + NSUInteger i = 0; + + if ([components count] == 1) + { + return path; + } + + while ((component = [en nextObject]) != nil) + { + if (i > 0) + { + result = [result stringByAppendingString: component]; + if ([[components lastObject] isEqual: component] == NO) + { + result = [result stringByAppendingString: @"."]; + } + } + + i++; + } + + return result; +} + - (id) _objectValueForTableColumn: (NSTableColumn *)tb row: (NSInteger) index { @@ -1885,7 +1915,7 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb { id theItem = [_items objectAtIndex: index]; NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; - NSString *keyPath = [ikp stringByRemovingFirstKeyPath]; + NSString *keyPath = [self _stringByRemovingFirstKeyPath: ikp]; // Here we are getting the last part of the keyPath since elsewhere in this class // we are recursively storing the contents of arrangedObjects (for example) to From ff97a5bbe2178011e1d4c479399e4ed8635203a4 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 29 Jun 2024 22:06:09 -0400 Subject: [PATCH 13/72] Remove private method entirely, per discussion with @fredkiefer --- Source/NSOutlineView.m | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 322bcf8011..323f122330 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1873,36 +1873,6 @@ - (BOOL) _isDraggingSource @selector(outlineView:writeItems:toPasteboard:)]; } -- (NSString *) _stringByRemovingFirstKeyPath: (NSString *)path -{ - NSArray *components = [path componentsSeparatedByString: @"."]; - NSString *result = @""; - NSEnumerator *en = [components objectEnumerator]; - NSString *component = nil; - NSUInteger i = 0; - - if ([components count] == 1) - { - return path; - } - - while ((component = [en nextObject]) != nil) - { - if (i > 0) - { - result = [result stringByAppendingString: component]; - if ([[components lastObject] isEqual: component] == NO) - { - result = [result stringByAppendingString: @"."]; - } - } - - i++; - } - - return result; -} - - (id) _objectValueForTableColumn: (NSTableColumn *)tb row: (NSInteger) index { @@ -1915,7 +1885,8 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb { id theItem = [_items objectAtIndex: index]; NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; - NSString *keyPath = [self _stringByRemovingFirstKeyPath: ikp]; + NSUInteger location = [ikp rangeOfString: @"."].location; + NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); // Here we are getting the last part of the keyPath since elsewhere in this class // we are recursively storing the contents of arrangedObjects (for example) to From 6b2bddab4cc4ada86f18ee613eeb4976302d1e39 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 30 Jun 2024 21:58:37 -0400 Subject: [PATCH 14/72] Add code to determine if a node has children and the number if the count key is not specified --- Source/NSOutlineView.m | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 323f122330..cb29d11ef6 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -2070,15 +2070,30 @@ - (void) _loadDictionaryStartingWith: (id) startitem } else { + /* Per the documentation in NSTreeController, we can determine everything + * from whether there are children present on a given node. See + * the documentation for NSTreeController for more info. + */ if ([self isExpandable: startitem] // leaf == NO && [self isItemExpanded: startitem]) { NSString *childrenKeyPath = [tc childrenKeyPath]; - NSString *countKeyPath = [tc countKeyPath]; - NSNumber *countValue = [sitem valueForKeyPath: countKeyPath]; - num = [countValue integerValue]; - children = [sitem valueForKeyPath: childrenKeyPath]; + if (childrenKeyPath != nil) + { + NSString *countKeyPath = [tc countKeyPath]; + + children = [sitem valueForKeyPath: childrenKeyPath]; + if (countKeyPath == nil) + { + num = [children count]; // get the count directly... + } + else + { + NSNumber *countValue = [sitem valueForKeyPath: countKeyPath]; + num = [countValue integerValue]; + } + } } } From 860e1863dac1d8f596252c936c8407a43881fe5f Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 30 Jun 2024 22:07:54 -0400 Subject: [PATCH 15/72] Minor correction to spelling --- Source/NSOutlineView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index cb29d11ef6..a64e14f006 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -2063,7 +2063,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem * key of "children". This is per the tests for this at * https://github.com/gcasa/NSTreeController_test. Specifically it returns * _NSControllerTreeProxy. The equivalent of that class in GNUstep is - * GSTreeControllerProxy. + * GSControllerTreeProxy. */ children = [representedObject objectForKey: @"children"]; num = [children count]; From ba9c12ddf817d4270e14a0374e425e0a4f8d6daf Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 30 Jun 2024 22:21:04 -0400 Subject: [PATCH 16/72] Improve documentation regarding 'object' mode and key specification --- Headers/AppKit/NSTreeController.h | 32 ++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index f3bfce3179..f1affc03fe 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -143,56 +143,79 @@ APPKIT_EXPORT_CLASS /** * Key value path for the flag which gives the count for the children - * of this node. The path indicated her must be key-value compliant. + * of this node. The path indicated here must be key-value compliant. + * If count is enabled, then add:, addChild:, remove:, removeChild: + * and insert: are disabled. This key path is option since it can + * be determined by the array of children retuned by the + * childKeyPath. The mode the tree controller is in when this is + * not specified is called "object" mode. */ - (NSString*) countKeyPath; /** * Key value path for the flag which determins that this is a leaf. - * The path indicated her must be key-value compliant. + * The path indicated here must be key-value compliant. This + * key path is optional as it can be determined by the children + * returned by the childrenKeyPath. */ - (NSString*) leafKeyPath; /** * Adds a child to the current selection using the newObject method. + * If the tree controller is in "object" mode, then newObject is called + * to add a new node. */ - (void) addChild: (id)sender; /** * Adds a new objeect to the tree usin the newObject method. + * If the tree controller is in "object" mode, then newObject is called + * to add a new node. */ - (void) add: (id)sender; /** * Inserts a child using the newObject method. This method * will fail if canInsertChild returns NO. + * If the tree controller is in "object" mode, then newObject is called + * to add a new node. */ - (void) insertChild: (id)sender; /** * Inserts and object using the newObject method at the specified indexPath. + * If the tree controller is in "object" mode, then newObject is called + * to add a new node. */ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)indexPath; /** * Inserts objects into arranged objects at the specified indexPaths. These arrays are * expected to be parallel and have the same number of objects. + * This method will only function if the tree controller is in + * "object" mode. */ - (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths; /** * Insert an object created by newObject into arranged objects. + * This method will only function if the tree controller is in + * "object" mode. */ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)indexPath; /** * Inserts objects into arranged objects at the specified indexPaths. These arrays are * expected to be parallel and have the same number of objects. + * This method will only function if the tree controller is in + * "object" mode. */ - (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths; /** * Insert an object created by newObject into arranged objects. + * This method will only function if the tree controller is in + * "object" mode. */ - (void) insert: (id)sender; @@ -205,6 +228,8 @@ APPKIT_EXPORT_CLASS /** * Removes object at the specified indexPath. + * This method will only function if the tree controller is in + * "object" mode. */ - (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath *)indexPath; @@ -234,7 +259,8 @@ APPKIT_EXPORT_CLASS - (void) removeSelectionIndexPaths: (NSArray *)indexPaths; /** - * Remove the currently selected object + * Remove the currently selected object. This method will only + * function if the tree controller is in "object" mode. */ - (void) remove: (id)sender; From ebf6bdb8d2f547c1a7f54f92ec05c37c0b32845d Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 2 Jul 2024 04:05:53 -0400 Subject: [PATCH 17/72] Update add method, fix white space issue, remove duplicate methods --- Headers/AppKit/NSTreeController.h | 31 +++------------- Source/GSControllerTreeProxy.h | 5 ++- Source/GSControllerTreeProxy.m | 18 +++++++-- Source/NSObjectController.m | 11 +++++- Source/NSTreeController.m | 61 +++++++++++++++++++------------ 5 files changed, 72 insertions(+), 54 deletions(-) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index f1affc03fe..137258ee8c 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -281,6 +281,9 @@ APPKIT_EXPORT_CLASS /** * Sets the count key path. This needs to be key-value compliant. + * Setting this key path will disable add:, addChild:, remove:, + * removeChild:, and insert: methods. If this is not specified, + * the tree controller is in "object" mode. */ - (void) setCountKeyPath: (NSString *)path; @@ -332,35 +335,11 @@ APPKIT_EXPORT_CLASS - (void) moveNodes: (NSArray *)nodes toIndexPath: (NSIndexPath *)startingIndexPath; /** - * Array containing all selected nodes + * Set the descriptors by which the content of this tree controller + * is sorted. */ - (void) setSortDescriptors: (NSArray *)descriptors; -/** - * children key path for the given NSTreeNode. - */ -- (NSString*) childrenKeyPathForNode: (NSTreeNode *)node; - -/** - * count key path for the given NSTreeNode. - */ -- (NSString*) countKeyPathForNode: (NSTreeNode *)node; - -/** - * leaf key path for the given NSTreeNode. - */ -- (NSString*) leafKeyPathForNode: (NSTreeNode *)node; - -/** - * Moves node to given indexPath - */ -- (void) moveNode: (NSTreeNode *)node toIndexPath: (NSIndexPath *)indexPath; - -/** - * Move nodes to position at startingIndexPath - */ -- (void) moveNodes: (NSArray *)nodes toIndexPath: (NSIndexPath *)startingIndexPath; - /** * Array containing all selected nodes */ diff --git a/Source/GSControllerTreeProxy.h b/Source/GSControllerTreeProxy.h index 67fceae047..0114b2c3b6 100644 --- a/Source/GSControllerTreeProxy.h +++ b/Source/GSControllerTreeProxy.h @@ -38,10 +38,13 @@ extern "C" { NSTreeController *_controller; } ++ (NSMutableDictionary *) dictionaryWithChildren: (NSMutableArray *)children; + - (instancetype) initWithRepresentedObject: (id)representedObject withController: (id)controller; - (NSUInteger) count; - + +- (NSMutableArray *) childNodes; @end #if defined(__cplusplus) diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index 2531febb66..eac6757abe 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -33,6 +33,13 @@ @implementation GSControllerTreeProxy ++ (NSMutableDictionary *) dictionaryWithChildren: (NSMutableArray *)children +{ + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject: children + forKey: @"children"]; + return dictionary; +} + - (instancetype) initWithRepresentedObject: (id)representedObject withController: (id)controller { @@ -46,12 +53,17 @@ - (instancetype) initWithRepresentedObject: (id)representedObject - (NSUInteger) count { - NSDictionary *ro = [self representedObject]; - NSArray *children = [ro objectForKey: @"children"]; - + NSArray *children = [[self representedObject] objectForKey: @"children"]; return [children count]; } +- (NSMutableArray *) childNodes +{ + NSDictionary *ro = [self representedObject]; + NSMutableArray *children = [ro objectForKey: @"children"]; + return children; +} + - (id) value { return nil; diff --git a/Source/NSObjectController.m b/Source/NSObjectController.m index db9331ea2f..71f00d7855 100644 --- a/Source/NSObjectController.m +++ b/Source/NSObjectController.m @@ -99,6 +99,8 @@ + (void) initialize { if (self == [NSObjectController class]) { + [self setVersion: 1]; + [self exposeBinding: NSContentObjectBinding]; [self setKeys: [NSArray arrayWithObject: @"editable"] triggerChangeNotificationsForDependentKey: @"canAdd"]; @@ -155,11 +157,13 @@ - (void) encodeWithCoder: (NSCoder *)coder [coder encodeValueOfObjCType: @encode(BOOL) at: &_is_editable]; [coder encodeValueOfObjCType: @encode(BOOL) at: &_automatically_prepares_content]; [coder encodeConditionalObject: _managed_proxy]; + [coder encodeObject: NSStringFromClass([self objectClass])]; } } - (id) initWithCoder: (NSCoder *)coder -{ +{ + int version = [coder versionForClassName: @"NSObjectController"]; if ((self = [super initWithCoder: coder]) != nil) { if ([self automaticallyPreparesContent]) @@ -190,6 +194,11 @@ - (id) initWithCoder: (NSCoder *)coder [coder decodeValueOfObjCType: @encode(BOOL) at: &_is_editable]; [coder decodeValueOfObjCType: @encode(BOOL) at: &_automatically_prepares_content]; ASSIGN(_managed_proxy, [coder decodeObject]); + if (version > 0) + { + NSString *className = [coder decodeObject]; + [self setObjectClass: NSClassFromString(className)]; + } } } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index ba18e2948d..bf08de43f5 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -57,20 +57,27 @@ + (void) initialize } } +- (void) _initDefaults +{ + _childrenKeyPath = nil; + _countKeyPath = nil; + _leafKeyPath = nil; + _sortDescriptors = nil; + _selection_index_paths = [[NSMutableArray alloc] init]; + + _canInsert = YES; + _canInsertChild = YES; + _canAddChild = YES; + + [self setObjectClass: [NSMutableDictionary class]]; +} + - (id) initWithContent: (id)content { NSLog(@"Content = %@", content); if ((self = [super initWithContent: content]) != nil) { - _childrenKeyPath = nil; - _countKeyPath = nil; - _leafKeyPath = nil; - _sortDescriptors = nil; - _selection_index_paths = [[NSMutableArray alloc] init]; - - _canInsert = YES; - _canInsertChild = YES; - _canAddChild = YES; + [self _initDefaults]; } return self; @@ -184,8 +191,7 @@ - (void) rearrangeObjects if ([_content isKindOfClass: [NSArray class]]) { - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject: _content - forKey: @"children"]; + NSMutableDictionary *dictionary = [GSControllerTreeProxy dictionaryWithChildren: _content]; _arranged_objects = [[GSControllerTreeProxy alloc] initWithRepresentedObject: dictionary withController: self]; } @@ -233,29 +239,37 @@ - (NSString*) leafKeyPath - (void) add: (id)sender { - if ([self canAddChild]) + if ([self canAddChild] + && [self countKeyPath] == nil) { - id new = [self newObject]; + id newObject = [self newObject]; - [self addChild: new]; - RELEASE(new); + if (newObject != nil) + { + NSMutableArray *newContent = [NSMutableArray arrayWithArray: [self content]]; + GSControllerTreeProxy *node = [[GSControllerTreeProxy alloc] + initWithRepresentedObject: newObject + withController: self]; + + [newContent addObject: node]; + [self setContent: newContent]; + RELEASE(newObject); + } } } - (void) addChild: (id)obj { - GSKeyValueBinding *theBinding; - - [self setContent: obj]; - theBinding = [GSKeyValueBinding getBinding: NSContentObjectBinding - forObject: self]; - if (theBinding != nil) - [theBinding reverseSetValueFor: @"content"]; + if ([self canAddChild] + && [self countKeyPath] == nil) + { + } } - (void) remove: (id)sender { - if ([self canRemove]) + if ([self canRemove] + && [self countKeyPath] == nil) { [self removeObject: [self content]]; } @@ -408,6 +422,7 @@ - (id) initWithCoder: (NSCoder*)coder if (self != nil) { + [self _initDefaults]; // set up default values... if ([coder allowsKeyedCoding]) { // These names do not stick to convention. Usually it would be From 7aee7f66670f07481aace77b2f917af9085947fc Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 3 Jul 2024 04:08:43 -0400 Subject: [PATCH 18/72] Use ...ForNode: methods so that the path is dependent on the kind of node --- Source/NSOutlineView.m | 10 +++++----- Source/NSTreeController.m | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index a64e14f006..4c5628b8e4 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -458,15 +458,15 @@ - (BOOL) isExpandable: (id)item BOOL leaf = YES; id observedObject = [theBinding observedObject]; NSTreeController *tc = (NSTreeController *)observedObject; - NSString *leafKeyPath = [tc leafKeyPath]; + NSString *leafKeyPath = [tc leafKeyPathForNode: item]; if (leafKeyPath == nil) { - NSString *countKeyPath = [tc countKeyPath]; + NSString *countKeyPath = [tc countKeyPathForNode: item]; if (countKeyPath == nil) { - NSString *childrenKeyPath = [tc childrenKeyPath]; + NSString *childrenKeyPath = [tc childrenKeyPathForNode: item]; if (childrenKeyPath == nil) { @@ -2077,11 +2077,11 @@ - (void) _loadDictionaryStartingWith: (id) startitem if ([self isExpandable: startitem] // leaf == NO && [self isItemExpanded: startitem]) { - NSString *childrenKeyPath = [tc childrenKeyPath]; + NSString *childrenKeyPath = [tc childrenKeyPathForNode: startitem]; if (childrenKeyPath != nil) { - NSString *countKeyPath = [tc countKeyPath]; + NSString *countKeyPath = [tc countKeyPathForNode: startitem]; children = [sitem valueForKeyPath: childrenKeyPath]; if (countKeyPath == nil) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index bf08de43f5..18d9247c03 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -263,6 +263,19 @@ - (void) addChild: (id)obj if ([self canAddChild] && [self countKeyPath] == nil) { + id newObject = [self newObject]; + + if (newObject != nil) + { + NSMutableArray *newContent = [NSMutableArray arrayWithArray: [self content]]; + GSControllerTreeProxy *node = [[GSControllerTreeProxy alloc] + initWithRepresentedObject: newObject + withController: self]; + + [newContent addObject: node]; + [self setContent: newContent]; + RELEASE(newObject); + } } } From 90d94fea225857bdf7c14c301c76696c22ce002b Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 5 Jul 2024 01:40:51 -0400 Subject: [PATCH 19/72] Add unbind call to dealloc methods, add children method to proxy class, cleanup --- Source/GSControllerTreeProxy.h | 2 +- Source/GSControllerTreeProxy.m | 2 +- Source/NSOutlineView.m | 21 ++++++++++++++------- Source/NSTableView.m | 2 ++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Source/GSControllerTreeProxy.h b/Source/GSControllerTreeProxy.h index 0114b2c3b6..54c3ca61d2 100644 --- a/Source/GSControllerTreeProxy.h +++ b/Source/GSControllerTreeProxy.h @@ -44,7 +44,7 @@ extern "C" { withController: (id)controller; - (NSUInteger) count; -- (NSMutableArray *) childNodes; +- (NSMutableArray *) children; @end #if defined(__cplusplus) diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index eac6757abe..e2b12fe864 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -57,7 +57,7 @@ - (NSUInteger) count return [children count]; } -- (NSMutableArray *) childNodes +- (NSMutableArray *) children { NSDictionary *ro = [self representedObject]; NSMutableArray *children = [ro objectForKey: @"children"]; diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 4c5628b8e4..6d2f1d760e 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -204,6 +204,8 @@ - (id) initWithFrame: (NSRect)frame - (void) dealloc { + [GSKeyValueBinding unbindAllForObject: self]; + RELEASE(_items); RELEASE(_expandedItems); @@ -773,12 +775,18 @@ - (void) setDataSource: (id)anObject // This method is @optional in NSOutlineViewDataSource as of macOS10.0 // CHECK_REQUIRED_METHOD(outlineView:objectValueForTableColumn:byItem:); - } - - // Is the data source editable? - _dataSource_editable = [anObject respondsToSelector: - @selector(outlineView:setObjectValue:forTableColumn:byItem:)]; + // Is the data source editable? + _dataSource_editable = [anObject respondsToSelector: + @selector(outlineView:setObjectValue:forTableColumn:byItem:)]; + } + else + { + /* Based on testing on macOS, this should default to YES if there is a binding... + */ + _dataSource_editable = YES; + } + /* We do *not* retain the dataSource, it's like a delegate */ _dataSource = anObject; [self tile]; @@ -2056,7 +2064,6 @@ - (void) _loadDictionaryStartingWith: (id) startitem if (startitem == nil) { NSTreeNode *node = (NSTreeNode *)[theBinding destinationValue]; - NSDictionary *representedObject = [node representedObject]; /* Per the documentation 10.4/5+ uses NSTreeNode as the return value for * the contents of this tree node consists of a dictionary with a single @@ -2065,7 +2072,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem * _NSControllerTreeProxy. The equivalent of that class in GNUstep is * GSControllerTreeProxy. */ - children = [representedObject objectForKey: @"children"]; + children = [node children]; num = [children count]; } else diff --git a/Source/NSTableView.m b/Source/NSTableView.m index abf8c4f1da..94593bb618 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -2083,6 +2083,8 @@ - (void) dealloc { [self abortEditing]; + [GSKeyValueBinding unbindAllForObject: self]; + RELEASE (_gridColor); RELEASE (_backgroundColor); RELEASE (_tableColumns); From 8fbcbdb38078e5c794f4cbe79c1bfa52834f35e0 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 5 Jul 2024 01:57:09 -0400 Subject: [PATCH 20/72] Changes to allow editing --- Source/NSOutlineView.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 6d2f1d760e..d4b65d9157 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -2056,6 +2056,13 @@ - (void) _loadDictionaryStartingWith: (id) startitem NSTreeController *tc = (NSTreeController *)observedObject; NSArray *children = nil; + /* If there is a binding present, then allow it to be editable + * by default as editability of cells is determined in the + * NSTableColumn class based on the binding there for the + * editable property as defined in IB. + */ + _dataSource_editable = YES; + /* Implement logic to build the internal data structure here using * bindings... */ From 23bcb99166efbda4313902c364b7c0a986babfe2 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 6 Jul 2024 22:02:10 -0400 Subject: [PATCH 21/72] Initial changes to NSBrowser for NSTreeController/binding integration --- Source/NSBrowser.m | 12 +++++++++++- Source/NSOutlineView.m | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index bb6e6d2c1d..fb3b5801ad 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -49,6 +49,7 @@ #import "AppKit/NSCell.h" #import "AppKit/NSColor.h" #import "AppKit/NSFont.h" +#import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSScrollView.h" #import "AppKit/NSGraphics.h" #import "AppKit/NSMatrix.h" @@ -56,9 +57,10 @@ #import "AppKit/NSEvent.h" #import "AppKit/NSWindow.h" #import "AppKit/NSBezierPath.h" -#import "GNUstepGUI/GSTheme.h" +#import "GNUstepGUI/GSTheme.h" #import "GSGuiPrivate.h" +#import "GSBindingHelpers.h" /* Cache */ static CGFloat scrollerWidth; // == [NSScroller scrollerWidth] @@ -2448,6 +2450,12 @@ + (void) initialize titleCell = [GSBrowserTitleCell new]; } + // Bindings.. + [self exposeBinding: NSContentBinding]; + [self exposeBinding: NSContentValuesBinding]; + [self exposeBinding: NSSelectionIndexesBinding]; + [self exposeBinding: NSSortDescriptorsBinding]; + [self _themeDidActivate: nil]; } } @@ -2530,6 +2538,8 @@ - (id) initWithFrame: (NSRect)rect - (void) dealloc { + [GSKeyValueBinding unbindAllForObject: self]; + [[NSNotificationCenter defaultCenter] removeObserver: self]; if ([titleCell controlView] == self) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index d4b65d9157..8457591277 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -177,7 +177,7 @@ + (void) initialize // Bindings.. [self exposeBinding: NSContentBinding]; - // [self exposeBinding: NSContentArrayBinding]; + [self exposeBinding: NSContentArrayBinding]; [self exposeBinding: NSSelectionIndexesBinding]; [self exposeBinding: NSSortDescriptorsBinding]; } From 435ccfb2c732764664f808e3c211c2d4e099852f Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 6 Jul 2024 23:03:31 -0400 Subject: [PATCH 22/72] Add value/setValue: --- Source/GSControllerTreeProxy.h | 5 +++++ Source/GSControllerTreeProxy.m | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Source/GSControllerTreeProxy.h b/Source/GSControllerTreeProxy.h index 54c3ca61d2..208214295c 100644 --- a/Source/GSControllerTreeProxy.h +++ b/Source/GSControllerTreeProxy.h @@ -45,6 +45,11 @@ extern "C" { - (NSUInteger) count; - (NSMutableArray *) children; + +- (id) value; + +- (void) setValue: (id)value; + @end #if defined(__cplusplus) diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index e2b12fe864..f5f20dc7d1 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -66,7 +66,13 @@ - (NSMutableArray *) children - (id) value { - return nil; + return [_representedObject objectForKey: @"value"]; +} + +- (void) setValue: (id)value +{ + [_representedObject setObject: value + forKey: @"value"]; } @end From fdb35eb86958a469f127992803f38ef8df1bac77 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 6 Jul 2024 23:06:26 -0400 Subject: [PATCH 23/72] Add value/setValue: --- Source/NSOutlineView.m | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 8457591277..add9f017c6 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -2139,7 +2139,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem * file system would try to traverse every file/directory on -reloadData. */ if (startitem == nil - || ([self isExpandable: startitem] // [_dataSource outlineView: self isItemExpandable: startitem]) + || ([self isExpandable: startitem] && [self isItemExpanded: startitem])) { num = [_dataSource outlineView: self @@ -2441,9 +2441,4 @@ - (void) _autoCollapse [autoExpanded removeAllObjects]; } -- (void) awakeFromNib -{ - [self reloadData]; -} - @end From 060b27a854f7b740d7fe63bef092c19cd13696bd Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 6 Jul 2024 23:44:31 -0400 Subject: [PATCH 24/72] Update _setObjectValue:... --- Source/NSOutlineView.m | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index add9f017c6..d2554d3329 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1921,15 +1921,32 @@ - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index { - if ([_dataSource respondsToSelector: - @selector(outlineView:setObjectValue:forTableColumn:byItem:)]) + // If we have content binding the data source is used only + // like a delegate + NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding forObject: tb]; + if (info != nil) { - id item = [self itemAtRow: index]; + id theItem = [_items objectAtIndex: index]; + NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; + NSUInteger location = [ikp rangeOfString: @"."].location; + NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); - [_dataSource outlineView: self - setObjectValue: value - forTableColumn: tb - byItem: item]; + // Set the value on the keyPath. + [theItem setValue: value + forKeyPath: keyPath]; + } + else + { + if ([_dataSource respondsToSelector: + @selector(outlineView:setObjectValue:forTableColumn:byItem:)]) + { + id item = [self itemAtRow: index]; + + [_dataSource outlineView: self + setObjectValue: value + forTableColumn: tb + byItem: item]; + } } } From aa86a96c552219f56ca70cbe49cbfc9193c91a0a Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 10 Jul 2024 06:31:55 -0400 Subject: [PATCH 25/72] Update to use NSObservedKeyPathKey instead of string, add code to _setObjectValue:... in NSTableView to set the value when we have a binding --- Source/NSOutlineView.m | 4 ++-- Source/NSTableView.m | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index d2554d3329..1298bb32b5 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1892,7 +1892,7 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb if (info != nil) { id theItem = [_items objectAtIndex: index]; - NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; + NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; NSUInteger location = [ikp rangeOfString: @"."].location; NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); @@ -1927,7 +1927,7 @@ - (void) _setObjectValue: (id)value if (info != nil) { id theItem = [_items objectAtIndex: index]; - NSString *ikp = [info objectForKey: @"NSObservedKeyPath"]; + NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; NSUInteger location = [ikp rangeOfString: @"."].location; NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 94593bb618..0df4e1e3f3 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6883,8 +6883,21 @@ - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index { - if ([_dataSource respondsToSelector: - @selector(tableView:setObjectValue:forTableColumn:row:)]) + GSKeyValueBinding *theBinding; + + theBinding = [GSKeyValueBinding getBinding: NSValueBinding + forObject: tb]; + if (theBinding != nil) + { + NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding + forObject: tb]; + id obj = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + NSString *keyPath = [info objectForKey: NSObservedKeyPathKey]; + [obj setValue: value forKeyPath: keyPath]; + } + else if ([_dataSource respondsToSelector: + @selector(tableView:setObjectValue:forTableColumn:row:)]) { [_dataSource tableView: self setObjectValue: value From 8da3d0afb70e70e1a58b85129b80a19347cf3997 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 10 Jul 2024 07:06:08 -0400 Subject: [PATCH 26/72] Update to use NSObservedKeyPathKey instead of string, add code to _setObjectValue:... in NSTableView to set the value when we have a binding --- Source/NSTableView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 0df4e1e3f3..a74e9acd62 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6878,7 +6878,7 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb return result; } - + - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index From bbbe9d00b4b79779dbe36529914a3ae66bcf3968 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 11 Jul 2024 12:18:52 -0400 Subject: [PATCH 27/72] Update _setObjectValue:... to update items in arrangedObjects when there is a binding --- Source/NSTableColumn.m | 10 + Source/NSTableView.m | 2061 ++++++++++++++++++++-------------------- 2 files changed, 1054 insertions(+), 1017 deletions(-) diff --git a/Source/NSTableColumn.m b/Source/NSTableColumn.m index ff99499eed..fd358b1f33 100644 --- a/Source/NSTableColumn.m +++ b/Source/NSTableColumn.m @@ -97,6 +97,7 @@ + (void) initialize [self setVersion: 4]; [self exposeBinding: NSValueBinding]; [self exposeBinding: NSEnabledBinding]; + [self exposeBinding: NSEditableBinding]; } } @@ -661,6 +662,10 @@ - (void) setValue: (id)anObject forKey: (NSString*)aKey { // FIXME } + else if ([aKey isEqual: NSEditableBinding]) + { + // FIXME + } else { [super setValue: anObject forKey: aKey]; @@ -678,6 +683,11 @@ - (id) valueForKey: (NSString*)aKey // FIXME return [NSNumber numberWithBool: YES]; } + else if ([aKey isEqual: NSEditableBinding]) + { + // FIXME + return [NSNumber numberWithBool: YES]; + } else { return [super valueForKey: aKey]; diff --git a/Source/NSTableView.m b/Source/NSTableView.m index a74e9acd62..38b868a00a 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -4,7 +4,7 @@ Author: Nicola Pero Date: March 2000, June 2000, August 2000, September 2000 - + Author: Pierre-Yves Rivaille Date: August 2001, January 2002 @@ -25,10 +25,10 @@ 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, + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ +*/ #import #import @@ -47,6 +47,7 @@ #import "AppKit/NSTableView.h" #import "AppKit/NSApplication.h" +#import "AppKit/NSArrayController.h" #import "AppKit/NSCell.h" #import "AppKit/NSClipView.h" #import "AppKit/NSColor.h" @@ -88,7 +89,7 @@ static NSDragOperation currentDragOperation; /* - * Nib compatibility struct. This structure is used to + * Nib compatibility struct. This structure is used to * pull the attributes out of the nib that we need to fill * in the flags. */ @@ -155,9 +156,9 @@ - (void)_setObjectValue: (id)value row: (NSInteger)index; - (BOOL) _isEditableColumn: (NSInteger)columnIndex - row: (NSInteger)rowIndex; + row: (NSInteger)rowIndex; - (BOOL) _isCellSelectableColumn: (NSInteger)columnIndex - row: (NSInteger)rowIndex; + row: (NSInteger)rowIndex; - (BOOL) _isCellEditableColumn: (NSInteger)columnIndex row: (NSInteger)rowIndex; - (NSInteger) _numRows; @@ -209,9 +210,9 @@ void quick_sort_internal(columnSorting *data, int p, int r) while (1) { j--; - for (; + for (; (data[j].width > x) - || ((data[j].width == x) + || ((data[j].width == x) && (data[j].isMax == YES) && (y == NO)); j--) @@ -220,7 +221,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) i++; for (; (data[i].width < x) - || ((data[i].width == x) + || ((data[i].width == x) && (data[i].isMax == NO) && (y == YES)); i++) @@ -243,8 +244,8 @@ void quick_sort_internal(columnSorting *data, int p, int r) } } -/* - * Now some auxiliary functions used to manage real-time user selections. +/* + * Now some auxiliary functions used to manage real-time user selections. * */ @@ -260,12 +261,12 @@ void quick_sort_internal(columnSorting *data, int p, int r) { if (!(selectionMode & ALLOWS_MULTIPLE)) { - if ((selectionMode & SHIFT_DOWN) && - (selectionMode & ALLOWS_EMPTY) && + if ((selectionMode & SHIFT_DOWN) && + (selectionMode & ALLOWS_EMPTY) && !(selectionMode & ADDING_ROW)) // we will unselect the selected row // ic, sc : ok - { + { NSUInteger count = [_selectedRows count]; if ((count == 0) && (_oldRow == -1)) @@ -283,18 +284,18 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (_currentRow != _originalRow) { if (*_selectedRow == _originalRow) - { + { // we are already selected, don't do anything } else - { + { //begin checking code if (count > 0) { NSLog(@"There should not be any row selected"); } //end checking code - + if ([tv _selectRow: _originalRow]) { [tv _postSelectionIsChangingNotification]; @@ -304,31 +305,31 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (_currentRow == _originalRow) { if (count == 0) - { + { // the row is already deselected // nothing to do ! } else - { + { [tv _unselectRow: _originalRow]; [tv _postSelectionIsChangingNotification]; } } } - else //(!(selectionMode & ALLOWS_MULTIPLE) && - //(!(selectionMode & SHIFT_DOWN) || + else //(!(selectionMode & ALLOWS_MULTIPLE) && + //(!(selectionMode & SHIFT_DOWN) || //!(selectionMode & ALLOWS_EMPTY) || //(selectionMode & ADDING_ROW))) // we'll be selecting exactly one row // ic, sc : ok - { + { NSUInteger count = [_selectedRows count]; - + if ([tv _shouldSelectRow: _currentRow] == NO) { return; } - + if ((count != 1) || (_oldRow == -1)) { // this is the first call that goes thru shouldSelectRow @@ -337,20 +338,20 @@ void quick_sort_internal(columnSorting *data, int p, int r) [tv _unselectAllRows]; [_selectedRows addIndex: _currentRow]; *_selectedRow = _currentRow; - + if (notified == YES) - { + { [tv setNeedsDisplayInRect: [tv rectOfRow: _currentRow]]; } else - { + { if (count > 1) { notified = YES; } } if (notified == YES) - { + { [tv _postSelectionIsChangingNotification]; } } @@ -361,18 +362,18 @@ void quick_sort_internal(columnSorting *data, int p, int r) //begin checking code if (![_selectedRows containsIndex: *_selectedRow]) - { + { NSLog(@"*_selectedRow is not the only selected row!"); } //end checking code - + if (*_selectedRow == _currentRow) - { + { // currentRow is already selecteed return; } else - { + { [tv _unselectRow: *_selectedRow]; // CHANGE: This does a check more [tv _selectRow: _currentRow]; @@ -425,7 +426,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } } else // new multiple selection, after first pass - { + { NSInteger oldDiff, newDiff, i; oldDiff = _oldRow - _originalRow; newDiff = _currentRow - _originalRow; @@ -463,9 +464,9 @@ void quick_sort_internal(columnSorting *data, int p, int r) // leave it selected continue; } - + if ([tv _unselectRow: i]) - { + { notified = YES; } } @@ -549,7 +550,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff <= 0 && newDiff >= 0) { BOOL notified = NO; - + // we're reducing the selection { for (i = _oldRow; i < _originalRow; i++) @@ -560,7 +561,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) // leave it selected continue; } - + if ([tv _unselectRow: i]) { notified = YES; @@ -569,7 +570,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow + 1; i <= _currentRow; i++) - { + { if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { @@ -602,14 +603,14 @@ void quick_sort_internal(columnSorting *data, int p, int r) // we're reducing the selection for (i = _oldRow; i > _originalRow; i--) - { + { if ([_oldSelectedRows containsIndex: i]) { // this row was in the old selection // leave it selected continue; } - + if ([tv _unselectRow: i]) { notified = YES; @@ -617,7 +618,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow - 1; i >= _currentRow; i--) - { + { if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { @@ -661,7 +662,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) NSInteger diff, i; NSUInteger count = [_selectedRows count]; BOOL notified = NO; - diff = _currentRow - _originalRow; + diff = _currentRow - _originalRow; if (count > 0) { @@ -697,7 +698,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } } else // new multiple selection, after first pass - { + { NSInteger oldDiff, newDiff, i; oldDiff = _oldRow - _originalRow; newDiff = _currentRow - _originalRow; @@ -761,7 +762,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) { notified = YES; } - } + } if (notified == YES) { [tv _postSelectionIsChangingNotification]; @@ -801,10 +802,10 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff <= 0 && newDiff >= 0) { BOOL notified = NO; - + // we're reducing the selection for (i = _oldRow; i < _originalRow; i++) - { + { if ([tv _unselectRow: i]) { notified = YES; @@ -812,7 +813,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow + 1; i <= _currentRow; i++) - { + { if ([tv _selectRow: i]) { notified = YES; @@ -843,7 +844,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) // we're reducing the selection for (i = _oldRow; i > _originalRow; i--) - { + { if ([tv _unselectRow: i]) { notified = YES; @@ -851,7 +852,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow - 1; i >= _currentRow; i--) - { + { if ([tv _selectRow: i]) { notified = YES; @@ -882,7 +883,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) && ((selectionMode & SHIFT_DOWN) == 0) && ((selectionMode & ALLOWS_EMPTY) == 0) && (selectionMode & ADDING_ROW)) - // the following case can be assimilated to the + // the following case can be assimilated to the // one before, although it will lead to an // extra redraw // TODO: solve this issue @@ -906,38 +907,38 @@ void quick_sort_internal(columnSorting *data, int p, int r) NSUInteger count = [_selectedRows count]; BOOL notified = NO; diff = _currentRow - _originalRow; - + if (count > 0) { notified = YES; } - + [tv _unselectAllRows]; - + if (diff >= 0) { for (i = _originalRow; i <= _currentRow; i++) { if ([tv _selectRow: i]) - { + { notified = YES; } - } + } } else { for (i = _originalRow; i >= _currentRow; i--) { if ([tv _selectRow: i]) - { + { notified = YES; } - } + } + } + if (notified == YES) + { + [tv _postSelectionIsChangingNotification]; } - if (notified == YES) - { - [tv _postSelectionIsChangingNotification]; - } } else { @@ -947,12 +948,12 @@ void quick_sort_internal(columnSorting *data, int p, int r) NSInteger diff, i; BOOL notified = NO; diff = _currentRow - _originalRow; - + if (diff >= 0) { for (i = _originalRow; i <= _currentRow; i++) { - if ([_selectedRows containsIndex: i] || + if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { *_selectedRow = i; @@ -965,7 +966,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) // this case does happen (sometimes) for (i = _originalRow; i >= _currentRow; i--) { - if ([_selectedRows containsIndex: i] || + if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { *_selectedRow = i; @@ -996,7 +997,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) for (i = _oldRow + 1; i <= _currentRow; i++) { if ([tv _selectRow: i]) - { + { notified = YES; } } @@ -1012,20 +1013,20 @@ void quick_sort_internal(columnSorting *data, int p, int r) for (i = _oldRow; i > _currentRow; i--) { if ([tv _unselectRow: i]) - { + { notified = YES; } } if (*_selectedRow == -1) { NSUInteger last = [_selectedRows lastIndex]; - + if (last == NSNotFound) - { + { *_selectedRow = -1; } else - { + { *_selectedRow = last; } } @@ -1045,10 +1046,10 @@ void quick_sort_internal(columnSorting *data, int p, int r) for (i = _oldRow - 1; i >= _currentRow; i--) { if ([tv _selectRow: i]) - { + { notified = YES; } - } + } if (notified == YES) { [tv _postSelectionIsChangingNotification]; @@ -1062,7 +1063,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) for (i = _oldRow; i < _currentRow; i++) { if ([tv _unselectRow: i]) - { + { notified = YES; } } @@ -1089,10 +1090,10 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff <= 0 && newDiff >= 0) { BOOL notified = NO; - + // we're reducing the selection for (i = _oldRow; i < _originalRow; i++) - { + { if ([tv _unselectRow: i]) { notified = YES; @@ -1100,7 +1101,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow + 1; i <= _currentRow; i++) - { + { if ([tv _selectRow: i]) { notified = YES; @@ -1131,7 +1132,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) // we're reducing the selection for (i = _oldRow; i > _originalRow; i--) - { + { if ([tv _unselectRow: i]) { notified = YES; @@ -1139,7 +1140,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow - 1; i >= _currentRow; i--) - { + { if ([tv _selectRow: i]) { notified = YES; @@ -1166,7 +1167,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } } else - // as the originalRow is not selection, + // as the originalRow is not selection, // we are adding to the old selection { // this code is copied from another case @@ -1183,7 +1184,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) BOOL notified = NO; for (i = _oldRow + 1; i <= _currentRow; i++) { - if ([_selectedRows containsIndex: i] || + if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { *_selectedRow = i; @@ -1208,9 +1209,9 @@ void quick_sort_internal(columnSorting *data, int p, int r) // leave it selected continue; } - + if ([tv _unselectRow: i]) - { + { notified = YES; } } @@ -1220,11 +1221,11 @@ void quick_sort_internal(columnSorting *data, int p, int r) NSUInteger last = [_selectedRows lastIndex]; if (last == NSNotFound) - { + { *_selectedRow = -1; } else - { + { *_selectedRow = last; } } @@ -1242,7 +1243,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) BOOL notified = NO; for (i = _oldRow - 1; i >= _currentRow; i--) { - if ([_selectedRows containsIndex: i] || + if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { *_selectedRow = i; @@ -1269,7 +1270,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) continue; } if ([tv _unselectRow: i]) - { + { notified = YES; } } @@ -1295,10 +1296,10 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff <= 0 && newDiff >= 0) { BOOL notified = NO; - + // we're reducing the selection for (i = _oldRow; i < _originalRow; i++) - { + { if ([_oldSelectedRows containsIndex: i]) { // this row was in the old selection @@ -1312,7 +1313,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } // then we're extending it for (i = _originalRow + 1; i <= _currentRow; i++) - { + { if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { @@ -1324,7 +1325,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { *_selectedRow = -1; @@ -1345,14 +1346,14 @@ void quick_sort_internal(columnSorting *data, int p, int r) // we're reducing the selection for (i = _oldRow; i > _originalRow; i--) - { + { if ([_oldSelectedRows containsIndex: i]) { // this row was in the old selection // leave it selected continue; } - + if ([tv _unselectRow: i]) { notified = YES; @@ -1361,7 +1362,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) // then we're extending it for (i = _originalRow - 1; i >= _currentRow; i--) - { + { if ([_selectedRows containsIndex: i] || [tv _selectRow: i]) { @@ -1401,7 +1402,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) NSInteger diff, i; BOOL notified = NO; - diff = _currentRow - _originalRow; + diff = _currentRow - _originalRow; if (diff >= 0) { @@ -1415,7 +1416,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { *_selectedRow = -1; @@ -1439,7 +1440,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { *_selectedRow = -1; @@ -1456,7 +1457,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } } else // new multiple antiselection, after first pass - { + { NSInteger oldDiff, newDiff, i; oldDiff = _oldRow - _originalRow; @@ -1478,7 +1479,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { *_selectedRow = -1; @@ -1534,13 +1535,13 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) - { + { *_selectedRow = -1; } else - { + { *_selectedRow = first; } } @@ -1578,7 +1579,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff <= 0 && newDiff >= 0) { BOOL notified = NO; - + // we're reducing the selection { for (i = _oldRow; i < _originalRow; i++) @@ -1609,7 +1610,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { *_selectedRow = -1; @@ -1628,7 +1629,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff >= 0 && newDiff <= 0) { BOOL notified = NO; - + // we're reducing the selection { for (i = _oldRow; i > _originalRow; i--) @@ -1659,7 +1660,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { *_selectedRow = -1; @@ -1688,7 +1689,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) NSInteger diff, i; NSUInteger count = [_selectedRows count]; BOOL notified = NO; - diff = _currentRow - _originalRow; + diff = _currentRow - _originalRow; if (diff >= 0) { @@ -1703,7 +1704,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { NSLog(@"error!"); @@ -1729,7 +1730,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { NSLog(@"error!"); @@ -1747,7 +1748,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) } } else // new multiple antiselection, after first pass - { + { NSInteger oldDiff, newDiff, i; NSUInteger count = [_selectedRows count]; oldDiff = _oldRow - _originalRow; @@ -1761,7 +1762,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) for (i = _oldRow + 1; i <= _currentRow; i++) { if ((count > 1) && [tv _unselectRow: i]) - { + { notified = YES; count--; } @@ -1770,14 +1771,14 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) - { + { NSLog(@"error!"); *_selectedRow = -1; } else - { + { *_selectedRow = first; } } @@ -1819,7 +1820,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) for (i = _oldRow - 1; i >= _currentRow; i--) { if ((count > 1) && [tv _unselectRow: i]) - { + { notified = YES; count--; } @@ -1828,14 +1829,14 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) - { + { NSLog(@"error!"); *_selectedRow = -1; } else - { + { *_selectedRow = first; } } @@ -1873,7 +1874,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff <= 0 && newDiff >= 0) { BOOL notified = NO; - + // we're reducing the selection { for (i = _oldRow; i < _originalRow; i++) @@ -1904,7 +1905,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { NSLog(@"error!"); @@ -1924,7 +1925,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) else if (oldDiff >= 0 && newDiff <= 0) { BOOL notified = NO; - + // we're reducing the selection { for (i = _oldRow; i > _originalRow; i--) @@ -1955,7 +1956,7 @@ void quick_sort_internal(columnSorting *data, int p, int r) if (*_selectedRow == -1) { NSUInteger first = [_selectedRows firstIndex]; - + if (first == NSNotFound) { NSLog(@"error!"); @@ -2006,7 +2007,7 @@ - (void) _autoloadTableColumns; @end -@implementation NSTableView +@implementation NSTableView + (void) initialize { @@ -2022,7 +2023,7 @@ + (void) initialize } /* - * Initializing/Releasing + * Initializing/Releasing */ - (void) _initDefaults @@ -2048,7 +2049,7 @@ - (void) _initDefaults _selectedColumn = -1; _selectedRow = -1; _highlightedTableColumn = nil; - _draggingSourceOperationMaskForLocal = NSDragOperationCopy + _draggingSourceOperationMaskForLocal = NSDragOperationCopy | NSDragOperationLink | NSDragOperationGeneric | NSDragOperationPrivate; _draggingSourceOperationMaskForRemote = NSDragOperationNone; ASSIGN(_sortDescriptors, [NSArray array]); @@ -2067,8 +2068,8 @@ - (id) initWithFrame: (NSRect)frameRect return self; [self _initDefaults]; - ASSIGN(_gridColor, [NSColor gridColor]); - ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]); + ASSIGN(_gridColor, [NSColor gridColor]); + ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]); ASSIGN(_tableColumns, [NSMutableArray array]); _headerView = [NSTableHeaderView new]; @@ -2100,7 +2101,7 @@ - (void) dealloc TEST_RELEASE (_cornerView); if (_autosaveTableColumns == YES) { - [nc removeObserver: self + [nc removeObserver: self name: NSTableViewColumnDidResizeNotification object: self]; } @@ -2123,7 +2124,7 @@ - (BOOL) isFlipped } /* - * Table Dimensions + * Table Dimensions */ - (NSInteger) numberOfColumns @@ -2136,8 +2137,8 @@ - (NSInteger) numberOfRows return [self _numRows]; } -/* - * Columns +/* + * Columns */ - (void) addTableColumn: (NSTableColumn *)aColumn @@ -2150,10 +2151,10 @@ - (void) addTableColumn: (NSTableColumn *)aColumn _columnOrigins = NSZoneRealloc (NSDefaultMallocZone (), _columnOrigins, (sizeof (CGFloat)) * _numberOfColumns); } - else + else { _columnOrigins = NSZoneMalloc (NSDefaultMallocZone (), sizeof (CGFloat)); - } + } [self tile]; } @@ -2189,16 +2190,16 @@ - (void) removeTableColumn: (NSTableColumn *)aColumn _columnOrigins = NSZoneRealloc (NSDefaultMallocZone (), _columnOrigins, (sizeof (CGFloat)) * _numberOfColumns); } - else + else { NSZoneFree (NSDefaultMallocZone (), _columnOrigins); - } + } [self tile]; } - (void) moveColumn: (NSInteger)columnIndex toColumn: (NSInteger)newIndex { - /* The range of columns which need to be shifted, + /* The range of columns which need to be shifted, extremes included */ NSInteger minRange, maxRange; /* Amount of shift for these columns */ @@ -2237,7 +2238,7 @@ - (void) moveColumn: (NSInteger)columnIndex toColumn: (NSInteger)newIndex { _selectedColumn = newIndex; } - else if ((_selectedColumn >= minRange) && (_selectedColumn <= maxRange)) + else if ((_selectedColumn >= minRange) && (_selectedColumn <= maxRange)) { _selectedColumn += shift; } @@ -2258,7 +2259,7 @@ - (void) moveColumn: (NSInteger)columnIndex toColumn: (NSInteger)newIndex { _editedColumn = newIndex; } - else if ((_editedColumn >= minRange) && (_editedColumn <= maxRange)) + else if ((_editedColumn >= minRange) && (_editedColumn <= maxRange)) { _editedColumn += shift; } @@ -2282,14 +2283,14 @@ - (void) moveColumn: (NSInteger)columnIndex toColumn: (NSInteger)newIndex /* Post notification */ [self _postColumnDidMoveNotificationWithOldIndex: columnIndex - newIndex: newIndex]; + newIndex: newIndex]; [self _autosaveTableColumns]; } - (NSArray *) tableColumns { - return AUTORELEASE ([_tableColumns mutableCopyWithZone: + return AUTORELEASE ([_tableColumns mutableCopyWithZone: NSDefaultMallocZone ()]); } @@ -2298,15 +2299,15 @@ - (NSInteger) columnWithIdentifier: (id)identifier NSEnumerator *enumerator = [_tableColumns objectEnumerator]; NSTableColumn *tb; NSInteger return_value = 0; - + while ((tb = [enumerator nextObject]) != nil) { // Also handle a nil identifier. - if ((identifier == [tb identifier]) || - [[tb identifier] isEqual: identifier]) - return return_value; + if ((identifier == [tb identifier]) || + [[tb identifier] isEqual: identifier]) + return return_value; else - return_value++; + return_value++; } return -1; } @@ -2317,12 +2318,12 @@ - (NSTableColumn *) tableColumnWithIdentifier:(id)anObject if (indexOfColumn == -1) return nil; - else + else return [_tableColumns objectAtIndex: indexOfColumn]; } -/* - * Data Source +/* + * Data Source */ - (id) dataSource @@ -2340,28 +2341,35 @@ - (void) setDataSource: (id)anObject // If we have content binding the data source is used only // like a delegate - theBinding = [GSKeyValueBinding getBinding: NSContentBinding - forObject: self]; + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; if (theBinding == nil) - { - if (anObject && [anObject respondsToSelector: sel_a] == NO) - { - [NSException - raise: NSInternalInconsistencyException - format: @"Data Source doesn't respond to numberOfRowsInTableView:"]; - } - - if (anObject && [anObject respondsToSelector: sel_b] == NO) - { - /* This method isn't required. - [NSException raise: NSInternalInconsistencyException - format: @"Data Source doesn't respond to " - @"tableView:objectValueForTableColumn:row:"]; - */ - } - } - - _dataSource_editable = [anObject respondsToSelector: sel_c]; + { + if (anObject && [anObject respondsToSelector: sel_a] == NO) + { + [NSException + raise: NSInternalInconsistencyException + format: @"Data Source doesn't respond to numberOfRowsInTableView:"]; + } + + if (anObject && [anObject respondsToSelector: sel_b] == NO) + { + /* This method isn't required. + [NSException raise: NSInternalInconsistencyException + format: @"Data Source doesn't respond to " + @"tableView:objectValueForTableColumn:row:"]; + */ + } + + _dataSource_editable = [anObject respondsToSelector: sel_c]; + } + else + { + /* Based on testing on macOS, this should default to YES if there is a binding... + */ + _dataSource_editable = YES; + } + /* We do *not* retain the dataSource, it's like a delegate */ _dataSource = anObject; @@ -2370,8 +2378,8 @@ - (void) setDataSource: (id)anObject [self reloadData]; } -/* - * Loading data +/* + * Loading data */ - (void) reloadData @@ -2382,13 +2390,13 @@ - (void) reloadData [_pathsToViews removeAllObjects]; [_rowViews removeAllObjects]; } - + [self noteNumberOfRowsChanged]; [self setNeedsDisplay: YES]; } -/* - * Target-action +/* + * Target-action */ - (void) setAction: (SEL)aSelector @@ -2439,15 +2447,15 @@ - (void) _sendDoubleActionForColumn: (NSInteger)columnIndex { _clickedColumn = columnIndex; _clickedRow = -1; - [self sendAction: _doubleAction to: _target]; + [self sendAction: _doubleAction to: _target]; } /* - * And this when it gets a simple click which turns out to be for + * And this when it gets a simple click which turns out to be for * selecting/deselecting a column. - * We don't support subtracting a column from the selection (Cocoa doesn't + * We don't support subtracting a column from the selection (Cocoa doesn't * either). - * However we support adding a distinct column with the control key (unlike + * However we support adding a distinct column with the control key (unlike * Cocoa where the user can only make column range selection). */ - (void) _selectColumn: (NSInteger)columnIndex @@ -2458,7 +2466,7 @@ - (void) _selectColumn: (NSInteger)columnIndex && _allowsMultipleSelection && [oldIndexes count] > 0); BOOL addSingle = ((modifiers & NSControlKeyMask) && _allowsMultipleSelection); - BOOL shouldSelect = ([self _shouldSelectionChange] + BOOL shouldSelect = ([self _shouldSelectionChange] && [self _shouldSelectTableColumn: [_tableColumns objectAtIndex: columnIndex]]); NSIndexSet *newIndexes = [NSIndexSet indexSetWithIndex: columnIndex]; @@ -2474,7 +2482,7 @@ - (void) _selectColumn: (NSInteger)columnIndex /* Single select has priority over range select when both modifiers are pressed */ if (addSingle) - { + { [self selectColumnIndexes: newIndexes byExtendingSelection: YES]; } else if (addRange) @@ -2483,19 +2491,19 @@ - (void) _selectColumn: (NSInteger)columnIndex NSUInteger lastIndex = [oldIndexes lastIndex]; NSRange range; - /* We extend the selection to the left or the right of the last selected - column. */ + /* We extend the selection to the left or the right of the last selected + column. */ if (columnIndex > [self selectedColumn]) - { - lastIndex = columnIndex; - } + { + lastIndex = columnIndex; + } else - { - firstIndex = columnIndex; - } + { + firstIndex = columnIndex; + } range = NSMakeRange(firstIndex, lastIndex - firstIndex + 1); - newIndexes = [NSIndexSet indexSetWithIndexesInRange: range]; + newIndexes = [NSIndexSet indexSetWithIndexesInRange: range]; [self selectColumnIndexes: newIndexes byExtendingSelection: YES]; } else @@ -2506,8 +2514,8 @@ - (void) _selectColumn: (NSInteger)columnIndex /* - *Configuration - */ + *Configuration + */ - (void) setAllowsColumnReordering: (BOOL)flag { @@ -2559,8 +2567,8 @@ - (BOOL) allowsColumnSelection return _allowsColumnSelection; } -/* - * Drawing Attributes +/* + * Drawing Attributes */ - (void) setIntercellSpacing: (NSSize)aSize @@ -2628,7 +2636,7 @@ - (NSTableViewSelectionHighlightStyle) selectionHighlightStyle /* * Selecting Columns and Rows */ -- (void) selectColumn: (NSInteger)columnIndex +- (void) selectColumn: (NSInteger)columnIndex byExtendingSelection: (BOOL)flag { if (columnIndex < 0 || columnIndex > _numberOfColumns) @@ -2653,9 +2661,9 @@ - (void) selectColumn: (NSInteger)columnIndex { [self validateEditing]; [self abortEditing]; - } + } return; - } + } /* If _numberOfColumns == 1, we can skip trying to deselect the only column - because we have been called to select it. */ @@ -2669,7 +2677,7 @@ - (void) selectColumn: (NSInteger)columnIndex if (_allowsMultipleSelection == NO) { [NSException raise: NSInternalInconsistencyException - format: @"Can not extend selection in table view when multiple selection is disabled"]; + format: @"Can not extend selection in table view when multiple selection is disabled"]; } } @@ -2680,7 +2688,7 @@ - (void) selectColumn: (NSInteger)columnIndex [self abortEditing]; } - /* Now select the column and post notification only if needed */ + /* Now select the column and post notification only if needed */ if ([_selectedColumns containsIndex: columnIndex] == NO) { [_selectedColumns addIndex: columnIndex]; @@ -2689,7 +2697,7 @@ - (void) selectColumn: (NSInteger)columnIndex [self setNeedsDisplayInRect: [self rectOfColumn: columnIndex]]; if (_headerView) { - [_headerView setNeedsDisplayInRect: + [_headerView setNeedsDisplayInRect: [_headerView headerRectOfColumn: columnIndex]]; } [self _postSelectionDidChangeNotification]; @@ -2737,7 +2745,7 @@ - (void) selectRow: (NSInteger)rowIndex /* reset the _clickedRow for keyboard navigation */ _clickedRow = rowIndex; return; - } + } /* If _numberOfRows == 1, we can skip trying to deselect the only row - because we have been called to select it. */ @@ -2751,7 +2759,7 @@ - (void) selectRow: (NSInteger)rowIndex if (_allowsMultipleSelection == NO) { [NSException raise: NSInternalInconsistencyException - format: @"Can not extend selection in table view when multiple selection is disabled"]; + format: @"Can not extend selection in table view when multiple selection is disabled"]; } } @@ -2760,12 +2768,12 @@ - (void) selectRow: (NSInteger)rowIndex { [self validateEditing]; [self abortEditing]; - } + } /* * Now select the row and post notification only if needed * also update the _clickedRow for keyboard navigation. - */ + */ if ([self _selectUnselectedRow: rowIndex]) { _clickedRow = rowIndex; @@ -2783,7 +2791,7 @@ - (void) selectColumnIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL) BOOL empty = ([indexes firstIndex] == NSNotFound); BOOL changed = NO; NSUInteger col; - + if (!_selectingColumns) { _selectingColumns = YES; @@ -2799,7 +2807,7 @@ - (void) selectColumnIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL) [self validateEditing]; [self abortEditing]; } - + if (extend == NO) { /* If the current selection is the one we want, just ends editing @@ -2807,7 +2815,7 @@ - (void) selectColumnIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL) * a NSTableViewSelectionDidChangeNotification. * This behaviour is required by the specifications */ if ([_selectedColumns isEqual: indexes]) - { + { if (!empty) { _selectedColumn = [indexes lastIndex]; @@ -2822,31 +2830,31 @@ - (void) selectColumnIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL) if (!empty) { if ([indexes lastIndex] >= _numberOfColumns) - { - // Cocoa returns in this case... - NSDebugLLog(@"NSTableView", @"Column index %lu out of table in selectColumn", - [indexes lastIndex]); - return; + { + // Cocoa returns in this case... + NSDebugLLog(@"NSTableView", @"Column index %lu out of table in selectColumn", + [indexes lastIndex]); + return; } - /* This check is not fully correct, as both sets may contain just + /* This check is not fully correct, as both sets may contain just the same entry, but works according to the old specification. */ - if (_allowsMultipleSelection == NO && + if (_allowsMultipleSelection == NO && [_selectedColumns count] + [indexes count] > 1) - { + { [NSException raise: NSInternalInconsistencyException - format: @"Can not set multiple selection in table view when multiple selection is disabled"]; + format: @"Can not set multiple selection in table view when multiple selection is disabled"]; } col = [indexes firstIndex]; while (col != NSNotFound) - { + { if (![_selectedColumns containsIndex: col]) { [self setNeedsDisplayInRect: [self rectOfColumn: col]]; if (_headerView) - { - [_headerView setNeedsDisplayInRect: + { + [_headerView setNeedsDisplayInRect: [_headerView headerRectOfColumn: col]]; } changed = YES; @@ -2868,7 +2876,7 @@ - (void) selectRowIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL)ext BOOL empty = ([indexes firstIndex] == NSNotFound); BOOL changed = NO; NSUInteger row; - + if (_selectingColumns) { _selectingColumns = NO; @@ -2884,7 +2892,7 @@ - (void) selectRowIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL)ext [self validateEditing]; [self abortEditing]; } - + if (extend == NO) { /* If the current selection is the one we want, just ends editing @@ -2892,7 +2900,7 @@ - (void) selectRowIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL)ext * a NSTableViewSelectionDidChangeNotification. * This behaviour is required by the specifications */ if ([_selectedRows isEqual: indexes]) - { + { if (!empty) { _selectedRow = [indexes lastIndex]; @@ -2907,23 +2915,23 @@ - (void) selectRowIndexes: (NSIndexSet *)indexes byExtendingSelection: (BOOL)ext if (!empty) { if ([indexes lastIndex] >= _numberOfRows) - { + { [NSException raise: NSInvalidArgumentException - format: @"Row index out of table in selectRow"]; + format: @"Row index out of table in selectRow"]; } - /* This check is not fully correct, as both sets may contain just + /* This check is not fully correct, as both sets may contain just the same entry, but works according to the old specification. */ - if (_allowsMultipleSelection == NO && + if (_allowsMultipleSelection == NO && [_selectedRows count] + [indexes count] > 1) - { + { [NSException raise: NSInternalInconsistencyException - format: @"Can not set multiple selection in table view when multiple selection is disabled"]; + format: @"Can not set multiple selection in table view when multiple selection is disabled"]; } row = [indexes firstIndex]; while (row != NSNotFound) - { + { if (![_selectedRows containsIndex: row]) { [self setNeedsDisplayInRect: [self rectOfRow: row]]; @@ -2966,7 +2974,7 @@ - (void) deselectColumn: (NSInteger)columnIndex [self validateEditing]; [self abortEditing]; } - + _selectingColumns = YES; [_selectedColumns removeIndex: columnIndex]; @@ -2977,34 +2985,34 @@ - (void) deselectColumn: (NSInteger)columnIndex NSUInteger greater = [_selectedColumns indexGreaterThanIndex: columnIndex]; if (less == NSNotFound) - { + { if (greater == NSNotFound) { _selectedColumn = -1; } else { - _selectedColumn = greater; - } + _selectedColumn = greater; + } } else if (greater == NSNotFound) - { + { _selectedColumn = less; } else if (columnIndex - less > greater - columnIndex) - { - _selectedColumn = greater; + { + _selectedColumn = greater; } - else - { + else + { _selectedColumn = less; } } - + [self setNeedsDisplayInRect: [self rectOfColumn: columnIndex]]; if (_headerView) { - [_headerView setNeedsDisplayInRect: + [_headerView setNeedsDisplayInRect: [_headerView headerRectOfColumn: columnIndex]]; } @@ -3034,26 +3042,26 @@ - (void) deselectRow: (NSInteger)rowIndex NSUInteger greater = [_selectedRows indexGreaterThanIndex: rowIndex]; if (less == NSNotFound) - { + { if (greater == NSNotFound) { _selectedRow = -1; } else { - _selectedRow = greater; - } + _selectedRow = greater; + } } else if (greater == NSNotFound) - { + { _selectedRow = less; } else if (rowIndex - less > greater - rowIndex) - { - _selectedRow = greater; + { + _selectedRow = greater; } - else - { + else + { _selectedRow = less; } } @@ -3136,8 +3144,8 @@ - (void) selectAll: (id) sender } { - NSInteger row; - + NSInteger row; + for (row = 0; row < _numberOfRows; row++) { if ([self _shouldSelectRow: row] == NO) @@ -3151,7 +3159,7 @@ - (void) selectAll: (id) sender { [self validateEditing]; [self abortEditing]; - } + } /* Do the real selection */ if (_selectingColumns == YES) @@ -3164,7 +3172,7 @@ - (void) selectAll: (id) sender [_selectedRows removeAllIndexes]; [_selectedRows addIndexesInRange: NSMakeRange(0, _numberOfRows)]; } - + [self setNeedsDisplay: YES]; [self _postSelectionDidChangeNotification]; } @@ -3178,13 +3186,13 @@ - (void) deselectAll: (id) sender { return; } - + if (_textObject != nil) { [self validateEditing]; [self abortEditing]; } - + if (([_selectedColumns count] > 0) || ([_selectedRows count] > 0)) { [_selectedColumns removeAllIndexes]; @@ -3203,8 +3211,8 @@ - (void) deselectAll: (id) sender } } -/* - * Grid Drawing attributes +/* + * Grid Drawing attributes */ - (void) setDrawsGrid: (BOOL)flag @@ -3247,10 +3255,10 @@ - (NSCell *) preparedCellAtColumn: (NSInteger)columnIndex row: (NSInteger)rowInd NSCell *cell = nil; if (_viewBased == NO) - { + { NSTableColumn *tb = [_tableColumns objectAtIndex: columnIndex]; - if ([_delegate respondsToSelector: + if ([_delegate respondsToSelector: @selector(tableView:dataCellForTableColumn:row:)]) { cell = [_delegate tableView: self dataCellForTableColumn: tb @@ -3261,21 +3269,21 @@ - (NSCell *) preparedCellAtColumn: (NSInteger)columnIndex row: (NSInteger)rowInd cell = [tb dataCellForRow: rowIndex]; } } - + return cell; } -/* - * Editing Cells +/* + * Editing Cells */ - (BOOL) abortEditing -{ +{ if (_textObject) { [_editedCell endEditing: _textObject]; DESTROY(_editedCell); - [self setNeedsDisplayInRect: + [self setNeedsDisplayInRect: [self frameOfCellAtColumn: _editedColumn row: _editedRow]]; _editedRow = -1; _editedColumn = -1; @@ -3302,80 +3310,87 @@ - (void) validateEditing NSString *string; id newObjectValue = nil; BOOL validatedOK = YES; + GSKeyValueBinding *theBinding = nil; // Avoid potential recursive sequences... _isValidating = YES; - + formatter = [_editedCell formatter]; string = AUTORELEASE([[_textObject text] copy]); if (formatter != nil) - { - NSString *error; - - if ([formatter getObjectValue: &newObjectValue - forString: string - errorDescription: &error] == YES) - { - [_editedCell setObjectValue: newObjectValue]; - - if (_dataSource_editable) - { - NSTableColumn *tb; - - tb = [_tableColumns objectAtIndex: _editedColumn]; - - [self _setObjectValue: newObjectValue - forTableColumn: tb - row: _editedRow]; - } - - _isValidating = NO; - return; - } - else - { - SEL sel = @selector(control:didFailToFormatString:errorDescription:); - - if ([_delegate respondsToSelector: sel]) - { - validatedOK = [_delegate control: self - didFailToFormatString: string - errorDescription: error]; - } - // Allow an empty string to fall through - else if (![string isEqualToString: @""]) - { - validatedOK = NO; - } - } - } + { + NSString *error; + + if ([formatter getObjectValue: &newObjectValue + forString: string + errorDescription: &error] == YES) + { + NSTableColumn *tb; + + [_editedCell setObjectValue: newObjectValue]; + tb = [_tableColumns objectAtIndex: _editedColumn]; + + theBinding = [GSKeyValueBinding getBinding: NSValueBinding + forObject: tb]; + + if (_dataSource_editable + || theBinding != nil) + { + [self _setObjectValue: newObjectValue + forTableColumn: tb + row: _editedRow]; + } + + _isValidating = NO; + return; + } + else + { + SEL sel = @selector(control:didFailToFormatString:errorDescription:); + + if ([_delegate respondsToSelector: sel]) + { + validatedOK = [_delegate control: self + didFailToFormatString: string + errorDescription: error]; + } + // Allow an empty string to fall through + else if (![string isEqualToString: @""]) + { + validatedOK = NO; + } + } + } if (validatedOK) - { - [_editedCell setStringValue: string]; - - if (_dataSource_editable) - { - NSTableColumn *tb; - - tb = [_tableColumns objectAtIndex: _editedColumn]; - - [self _setObjectValue: string // newObjectValue - forTableColumn: tb - row: _editedRow]; - } - } + { + NSTableColumn *tb; + + [_editedCell setStringValue: string]; + tb = [_tableColumns objectAtIndex: _editedColumn]; + + theBinding = [GSKeyValueBinding getBinding: NSValueBinding + forObject: tb]; + + if (_dataSource_editable + || theBinding != nil) + { + [self _setObjectValue: string // newObjectValue + forTableColumn: tb + row: _editedRow]; + } + } // Avoid potential recursive sequences... _isValidating = NO; } } -- (void) editColumn: (NSInteger) columnIndex - row: (NSInteger) rowIndex - withEvent: (NSEvent *) theEvent - select: (BOOL) flag +- (void) editColumn: (NSInteger) columnIndex + row: (NSInteger) rowIndex + withEvent: (NSEvent *) theEvent + select: (BOOL) flag { NSText *t; NSTableColumn *tb; @@ -3388,13 +3403,13 @@ - (void) editColumn: (NSInteger) columnIndex format:@"Attempted to edit unselected row"]; } - if (rowIndex < 0 || rowIndex >= _numberOfRows + if (rowIndex < 0 || rowIndex >= _numberOfRows || columnIndex < 0 || columnIndex >= _numberOfColumns) { [NSException raise: NSInvalidArgumentException format: @"Row/column out of index in edit"]; } - + [self scrollRowToVisible: rowIndex]; [self scrollColumnToVisible: columnIndex]; @@ -3415,7 +3430,7 @@ - (void) editColumn: (NSInteger) columnIndex return; } } - + _editedRow = rowIndex; _editedColumn = columnIndex; @@ -3426,7 +3441,7 @@ - (void) editColumn: (NSInteger) columnIndex tb = [_tableColumns objectAtIndex: columnIndex]; [_editedCell setObjectValue: [self _objectValueForTableColumn: tb row: rowIndex]]; - + // But of course the delegate can mess it up if it wants [self _willDisplayCell: _editedCell forTableColumn: tb @@ -3470,12 +3485,12 @@ before the actual editing is started (otherwise you easily end up delegate: self event: theEvent]; } - return; + return; } - (NSInteger) editedRow { - return _editedRow; + return _editedRow; } - (NSInteger) editedColumn @@ -3485,29 +3500,29 @@ - (NSInteger) editedColumn static inline NSTimeInterval computePeriod(NSPoint mouseLocationWin, - CGFloat minYVisible, - CGFloat maxYVisible) + CGFloat minYVisible, + CGFloat maxYVisible) { - /* We have three zones of speed. + /* We have three zones of speed. 0 - 50 pixels: period 0.2 50 - 100 pixels: period 0.1 100 - 150 pixels: period 0.01 */ CGFloat distance = 0; - - if (mouseLocationWin.y < minYVisible) + + if (mouseLocationWin.y < minYVisible) { - distance = minYVisible - mouseLocationWin.y; + distance = minYVisible - mouseLocationWin.y; } else if (mouseLocationWin.y > maxYVisible) { distance = mouseLocationWin.y - maxYVisible; } - + if (distance < 50) return 0.2; else if (distance < 100) return 0.1; - else + else return 0.01; } @@ -3519,25 +3534,25 @@ - (void) _trackCellAtColumn: (NSInteger) columnIndex { return; } - + /* we should copy the cell here, as we do on editing. otherwise validation on a cell being edited could cause the cell we are selecting to get it's objectValue */ NSCell *cell = [[self preparedCellAtColumn: columnIndex row: rowIndex] copy]; NSTableColumn *tb = [_tableColumns objectAtIndex: columnIndex]; id originalValue = RETAIN([self _objectValueForTableColumn: tb - row: rowIndex]); - [cell setObjectValue: originalValue]; + row: rowIndex]); + [cell setObjectValue: originalValue]; NSRect cellFrame = [self frameOfCellAtColumn: columnIndex - row: rowIndex]; + row: rowIndex]; [cell setHighlighted: YES]; [self setNeedsDisplayInRect: cellFrame]; /* give delegate a chance to i.e set target */ [self _willDisplayCell: cell forTableColumn: tb - row: rowIndex]; - - if ([cell trackMouse: theEvent + row: rowIndex]; + + if ([cell trackMouse: theEvent inRect: cellFrame ofView: self untilMouseUp: [[cell class] @@ -3548,13 +3563,13 @@ - (void) _trackCellAtColumn: (NSInteger) columnIndex /* don't check editability that only pertains to editColumn:... */ if (originalValue != newValue && ![originalValue isEqual: newValue]) - { - [self _setObjectValue: newValue + { + [self _setObjectValue: newValue forTableColumn: tb row: rowIndex]; } } - RELEASE(originalValue); + RELEASE(originalValue); [cell setHighlighted: NO]; [self setNeedsDisplayInRect: cellFrame]; RELEASE(cell); @@ -3563,8 +3578,8 @@ - (void) _trackCellAtColumn: (NSInteger) columnIndex - (BOOL) _startDragOperationWithEvent: (NSEvent *) theEvent { NSPasteboard *pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; - NSPoint startPoint = [self convertPoint: [theEvent locationInWindow] - fromView: nil]; + NSPoint startPoint = [self convertPoint: [theEvent locationInWindow] + fromView: nil]; if ([self canDragRowsWithIndexes: _selectedRows atPoint: startPoint] && [self _writeRows: _selectedRows toPasteboard: pboard]) @@ -3576,9 +3591,9 @@ - (BOOL) _startDragOperationWithEvent: (NSEvent *) theEvent NSArray *cols = nil; dragImage = [self dragImageForRowsWithIndexes: _selectedRows - tableColumns: cols - event: theEvent - offset: &p]; + tableColumns: cols + event: theEvent + offset: &p]; /* * Store image offset in s ... the returned @@ -3599,14 +3614,14 @@ - (BOOL) _startDragOperationWithEvent: (NSEvent *) theEvent p = startPoint; p.x += s.width; p.y += s.height; - + [self dragImage: dragImage at: p offset: NSMakeSize(0, 0) event: theEvent pasteboard: pboard - source: self + source: self slideBack: YES]; return YES; } @@ -3627,56 +3642,56 @@ - (void) mouseDown: (NSEvent *)theEvent // Pathological case -- ignore mouse down if ((_numberOfRows == 0) || (_numberOfColumns == 0)) { - return; + return; } - + /* Stop editing if any */ if (_textObject != nil) { - if (_editedCell != nil - && [_editedCell isEntryAcceptable:[_textObject text]] == NO) - { - NSBeep(); - return; - } + if (_editedCell != nil + && [_editedCell isEntryAcceptable:[_textObject text]] == NO) + { + NSBeep(); + return; + } [self validateEditing]; [self abortEditing]; - } + } // Determine row and column which were clicked location = [self convertPoint: initialLocation fromView: nil]; _clickedRow = [self rowAtPoint: location]; _clickedColumn = [self columnAtPoint: location]; - + if ([theEvent type] == NSLeftMouseDown && clickCount > 1) { // Double-click event if (![self isRowSelected: _clickedRow]) - { + { return; } if (![self _isCellSelectableColumn: _clickedColumn row: _clickedRow]) - { + { // Send double-action but don't edit [self _trackCellAtColumn: _clickedColumn - row: _clickedRow - withEvent: theEvent]; + row: _clickedRow + withEvent: theEvent]; if (_clickedRow != -1) [self sendAction: _doubleAction to: _target]; } else if (clickCount == 2) // if < 2, dont want to abort editing - { + { // It is OK to edit column. Go on, do it. - [self editColumn: _clickedColumn + [self editColumn: _clickedColumn row: _clickedRow withEvent: theEvent select: YES]; } } - else + else { #define COMPUTE_NEW_SELECTION do { \ if (originalRow == -1) \ @@ -3699,9 +3714,9 @@ - (void) mouseDown: (NSEvent *)theEvent // Selection NSUInteger modifiers = [theEvent modifierFlags]; - NSUInteger eventMask = (NSLeftMouseUpMask + NSUInteger eventMask = (NSLeftMouseUpMask | NSLeftMouseDownMask - | NSLeftMouseDraggedMask + | NSLeftMouseDraggedMask | NSPeriodicMask); unsigned selectionMode = 0; NSPoint mouseLocationWin; @@ -3735,12 +3750,12 @@ - (void) mouseDown: (NSEvent *)theEvent { selectionMode |= ALLOWS_EMPTY; } - + if (modifiers & NSShiftKeyMask) { selectionMode |= SHIFT_DOWN; } - + if (![_selectedRows containsIndex: _clickedRow]) { selectionMode |= ADDING_ROW; @@ -3756,7 +3771,7 @@ - (void) mouseDown: (NSEvent *)theEvent selectionMode |= ADDING_ROW; } } - + // is the delegate ok for a new selection ? if ([self _shouldSelectionChange] == NO) { @@ -3779,15 +3794,15 @@ - (void) mouseDown: (NSEvent *)theEvent */ CREATE_AUTORELEASE_POOL(arp); NSEventType eventType = [lastEvent type]; - - mouseLocationWin = [lastEvent locationInWindow]; - mouseLocationView = [self convertPoint: mouseLocationWin + + mouseLocationWin = [lastEvent locationInWindow]; + mouseLocationView = [self convertPoint: mouseLocationWin fromView: nil]; - + switch (eventType) { case NSLeftMouseUp: - if ((mouseLocationWin.y > minYVisible) + if ((mouseLocationWin.y > minYVisible) && (mouseLocationWin.y < maxYVisible)) { // mouse up within table @@ -3799,19 +3814,19 @@ - (void) mouseDown: (NSEvent *)theEvent mouseLocationView.x = _bounds.origin.x; oldRow = currentRow; currentRow = [self rowAtPoint: mouseLocationView]; - + if (oldRow != currentRow) { COMPUTE_NEW_SELECTION; } - + if (!didTrackCell && currentRow == _clickedRow) { /* * a dragging operation is still possible so * selections were never dragged, * and a drag operation was never attempted. - * the cell was clicked, + * the cell was clicked, * track the cell with the old mouseDown event * then it will get the current event mouseUp. */ @@ -3831,7 +3846,7 @@ - (void) mouseDown: (NSEvent *)theEvent case NSLeftMouseDown: case NSLeftMouseDragged: if (fabs(mouseLocationWin.x - initialLocation.x) > 1 - || fabs(mouseLocationWin.y - initialLocation.y) > 1) + || fabs(mouseLocationWin.y - initialLocation.y) > 1) { mouseMoved = YES; } @@ -3839,19 +3854,19 @@ - (void) mouseDown: (NSEvent *)theEvent if (dragOperationPossible == YES) { if ([_selectedRows containsIndex:_clickedRow] == NO - || (_verticalMotionDrag == NO - && fabs(mouseLocationWin.y - initialLocation.y) > 2)) + || (_verticalMotionDrag == NO + && fabs(mouseLocationWin.y - initialLocation.y) > 2)) { dragOperationPossible = NO; } - else if ((fabs(mouseLocationWin.x - initialLocation.x) >= 4) - || (_verticalMotionDrag - && fabs(mouseLocationWin.y - initialLocation.y) >= 4)) + else if ((fabs(mouseLocationWin.x - initialLocation.x) >= 4) + || (_verticalMotionDrag + && fabs(mouseLocationWin.y - initialLocation.y) >= 4)) { if ([self _startDragOperationWithEvent: theEvent]) { - RELEASE(oldSelectedRows); - IF_NO_GC(DESTROY(arp)); + RELEASE(oldSelectedRows); + IF_NO_GC(DESTROY(arp)); return; } else @@ -3860,7 +3875,7 @@ - (void) mouseDown: (NSEvent *)theEvent } } } - else if ((mouseLocationWin.y > minYVisible) + else if ((mouseLocationWin.y > minYVisible) && (mouseLocationWin.y < maxYVisible)) { // mouse dragged within table @@ -3877,25 +3892,25 @@ - (void) mouseDown: (NSEvent *)theEvent { COMPUTE_NEW_SELECTION; } - + if (eventType == NSLeftMouseDown) { /* * Can never get here from a dragging source * so they need to track in mouse up. */ - NSCell *cell = [self preparedCellAtColumn: _clickedColumn + NSCell *cell = [self preparedCellAtColumn: _clickedColumn row: _clickedRow]; - + [self _trackCellAtColumn: _clickedColumn row: _clickedRow withEvent: theEvent]; didTrackCell = YES; - + if ([[cell class] prefersTrackingUntilMouseUp]) { /* the mouse could have gone up outside of the cell - * avoid selecting the row under mouse cursor */ + * avoid selecting the row under mouse cursor */ sendAction = YES; done = YES; } @@ -3911,13 +3926,13 @@ - (void) mouseDown: (NSEvent *)theEvent else { // Mouse dragged out of the table - NSTimeInterval period = computePeriod(mouseLocationWin, - minYVisible, + NSTimeInterval period = computePeriod(mouseLocationWin, + minYVisible, maxYVisible); if (startedPeriodicEvents == YES) { - /* Check - if the mouse did not change zone, + /* Check - if the mouse did not change zone, we do nothing */ if (period == oldPeriod) break; @@ -3929,7 +3944,7 @@ - (void) mouseDown: (NSEvent *)theEvent [NSEvent startPeriodicEventsAfterDelay: 0 withPeriod: oldPeriod]; startedPeriodicEvents = YES; - if (mouseLocationWin.y <= minYVisible) + if (mouseLocationWin.y <= minYVisible) mouseBelowView = YES; else mouseBelowView = NO; @@ -3968,7 +3983,7 @@ - (void) mouseDown: (NSEvent *)theEvent default: break; } - + if (done == NO) { /* in certain cases we are working with events that have already @@ -3976,11 +3991,11 @@ - (void) mouseDown: (NSEvent *)theEvent * getNextEvent is set to NO, use the current event. */ if (getNextEvent == YES) - { - lastEvent = [NSApp nextEventMatchingMask: eventMask + { + lastEvent = [NSApp nextEventMatchingMask: eventMask untilDate: distantFuture - inMode: NSEventTrackingRunLoopMode - dequeue: YES]; + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; } else { @@ -3998,11 +4013,11 @@ - (void) mouseDown: (NSEvent *)theEvent { [self _postSelectionDidChangeNotification]; } - + RELEASE(oldSelectedRows); if (!mouseMoved) - sendAction = YES; + sendAction = YES; /* If this was a simple click (ie. no dragging), we send our action. */ if (sendAction) @@ -4018,7 +4033,7 @@ - (void) mouseDown: (NSEvent *)theEvent [self sendAction: _action to: _target]; } } - + _clickedRow = _selectedRow; } @@ -4032,7 +4047,7 @@ - (void) mouseDown: (NSEvent *)theEvent } \ } static BOOL selectContiguousRegion(NSTableView *self, - NSIndexSet *_selectedRows, + NSIndexSet *_selectedRows, NSInteger originalRow, NSInteger oldRow, NSInteger currentRow) @@ -4049,7 +4064,7 @@ static BOOL selectContiguousRegion(NSTableView *self, } /* - * check if the old row is not between the current row and the original row + * check if the old row is not between the current row and the original row * and not the original or current rows */ if (((!((oldRow < currentRow @@ -4062,18 +4077,18 @@ static BOOL selectContiguousRegion(NSTableView *self, || oldRow == originalRow)))) { CHECK_CHANGING(notified); - [self _unselectRow: oldRow]; + [self _unselectRow: oldRow]; } - /* - * there is an off by one here it could be on either end of the loop + /* + * there is an off by one here it could be on either end of the loop * but its either oldRow or currentRow so above we select the currentRow * and possibly unselect the oldRow, one of the two will then - * be selected or deselected again in in this loop + * be selected or deselected again in in this loop */ for (row = first; row < last; row++) { - + /* check if the old row is between the current row and the original row */ if ((row < currentRow && row > originalRow @@ -4100,13 +4115,13 @@ static BOOL selectContiguousRegion(NSTableView *self, { if ([_selectedRows containsIndex: row]) { - CHECK_CHANGING(notified); + CHECK_CHANGING(notified); [self _unselectRow: row]; } } } return notified; -} +} - (void) keyDown: (NSEvent *)theEvent { @@ -4123,13 +4138,13 @@ - (void) keyDown: (NSEvent *)theEvent NSInteger visRows; NSUInteger i; BOOL gotMovementKey = NO; - + // will not contain partial rows. - visRows = visRect.size.height / [self rowHeight]; + visRows = visRect.size.height / [self rowHeight]; - // _clickedRow is stored between calls as the first selected row + // _clickedRow is stored between calls as the first selected row // when doing multiple selection, so the selection may grow and shrink. - + /* * do a contiguous selection on shift */ @@ -4141,7 +4156,7 @@ - (void) keyDown: (NSEvent *)theEvent oldRow = _selectedRow; } } - + /* just scroll don't modify any selection */ if (modifiers & NSControlKeyMask) { @@ -4153,12 +4168,12 @@ - (void) keyDown: (NSEvent *)theEvent unichar c = [characters characterAtIndex: i]; switch (c) - { + { case NSUpArrowFunctionKey: gotMovementKey = YES; - if (modifySelection == NO) + if (modifySelection == NO) { - noModPoint.x = visRect.origin.x; + noModPoint.x = visRect.origin.x; noModPoint.y = NSMinY(visRect) - rowHeight; } else @@ -4168,25 +4183,25 @@ - (void) keyDown: (NSEvent *)theEvent break; case NSDownArrowFunctionKey: gotMovementKey = YES; - if (modifySelection == NO) + if (modifySelection == NO) { - noModPoint.x = visRect.origin.x; + noModPoint.x = visRect.origin.x; noModPoint.y = NSMinY(visRect) + rowHeight; } else { - currentRow++; + currentRow++; } break; case NSPageDownFunctionKey: gotMovementKey = YES; - if (modifySelection == NO) + if (modifySelection == NO) { - noModPoint.x = visRect.origin.x; + noModPoint.x = visRect.origin.x; noModPoint.y = NSMinY(visRect) + (rowHeight * visRows) - rowHeight; } else - { + { currentRow += visRows; } break; @@ -4194,12 +4209,12 @@ - (void) keyDown: (NSEvent *)theEvent gotMovementKey = YES; if (modifySelection == NO) { - noModPoint.x = visRect.origin.x; + noModPoint.x = visRect.origin.x; noModPoint.y = NSMinY(visRect) - (rowHeight * visRows) + rowHeight; } - else + else { - currentRow -= visRows; + currentRow -= visRows; } break; case NSHomeFunctionKey: @@ -4211,7 +4226,7 @@ - (void) keyDown: (NSEvent *)theEvent } else { - currentRow = 0; + currentRow = 0; } break; case NSEndFunctionKey: @@ -4228,9 +4243,9 @@ - (void) keyDown: (NSEvent *)theEvent break; default: break; - } + } } - + /* * if scrolled off the bottom or top the selection. * the modifiers might have changed so recompute the selection. @@ -4249,90 +4264,90 @@ - (void) keyDown: (NSEvent *)theEvent { currentRow = _numberOfRows - 1; } - + if (_numberOfRows) { if (modifySelection) - { + { BOOL notified = NO; - [self _setSelectingColumns: NO]; - - if (originalRow == -1) - { + [self _setSelectingColumns: NO]; + + if (originalRow == -1) + { /* we're not extending any selection */ - originalRow = currentRow; - _clickedRow = currentRow; + originalRow = currentRow; + _clickedRow = currentRow; } - if (_clickedRow == -1) - { + if (_clickedRow == -1) + { /* user must have hit a key with no selected rows */ - _clickedRow = currentRow; + _clickedRow = currentRow; } - + if ((!(modifiers & NSShiftKeyMask && _allowsMultipleSelection))) { NSUInteger first = [_selectedRows firstIndex]; NSUInteger last = [_selectedRows lastIndex]; if ((first == last && first == currentRow) == 0) - { + { CHECK_CHANGING(notified) [self _unselectAllRows]; [self _selectRow: currentRow]; - _selectedRow = currentRow; + _selectedRow = currentRow; } } else - { + { notified = selectContiguousRegion(self, _selectedRows, - originalRow, oldRow, currentRow); + originalRow, oldRow, currentRow); _selectedRow = currentRow; } - + if (notified) - { - [self _postSelectionDidChangeNotification]; + { + [self _postSelectionDidChangeNotification]; } - + [self scrollRowToVisible: currentRow]; [self displayIfNeeded]; - } + } else - { + { noModPoint = [self convertPoint: noModPoint - toView: _super_view]; - noModPoint = + toView: _super_view]; + noModPoint = [(NSClipView *)_super_view constrainScrollPoint: noModPoint]; [(NSClipView *)_super_view scrollToPoint: noModPoint]; } } } -/* - * Auxiliary Components +/* + * Auxiliary Components */ - (void) setHeaderView: (NSTableHeaderView*)aHeaderView { - + if ([_headerView respondsToSelector:@selector(setTableView:)]) [_headerView setTableView: nil]; - + ASSIGN (_headerView, aHeaderView); - + if ([_headerView respondsToSelector:@selector(setTableView:)]) [_headerView setTableView: self]; - + [self tile]; // resizes corner and header views, then displays - + if (_super_view != nil) { id ssv = [_super_view superview]; if ([ssv isKindOfClass: [NSScrollView class]]) - [ssv tile]; // draws any border type over corner and header views - } + [ssv tile]; // draws any border type over corner and header views + } } - (NSTableHeaderView*) headerView @@ -4348,7 +4363,7 @@ - (void) setCornerView: (NSView*)aView { id ssv = [_super_view superview]; if ([ssv isKindOfClass: [NSScrollView class]]) - [ssv tile]; // draws any border type over corner and header views + [ssv tile]; // draws any border type over corner and header views } } @@ -4357,8 +4372,8 @@ - (NSView*) cornerView return _cornerView; } -/* - * Layout +/* + * Layout */ - (NSRect) rectOfColumn: (NSInteger)columnIndex @@ -4411,11 +4426,11 @@ - (NSIndexSet *) columnIndexesInRect: (NSRect)aRect NSTableColumn *tableColumn = [_tableColumns objectAtIndex: i]; if ([tableColumn isHidden]) - [indexes removeIndex: i]; + [indexes removeIndex: i]; } return indexes; -} +} /** Returns the index range of the table columns which intersects the given rect. @@ -4429,7 +4444,7 @@ - (NSRange) columnsInRect: (NSRect)aRect NSRange range; range.location = [self columnAtPoint: aRect.origin]; - range.length = [self columnAtPoint: + range.length = [self columnAtPoint: NSMakePoint (NSMaxX (aRect), _bounds.origin.y)]; range.length -= range.location; range.length += 1; @@ -4442,14 +4457,14 @@ - (NSRange) rowsInRect: (NSRect)aRect NSInteger lastRowInRect; range.location = [self rowAtPoint: aRect.origin]; - lastRowInRect = [self rowAtPoint: + lastRowInRect = [self rowAtPoint: NSMakePoint (_bounds.origin.x, NSMaxY (aRect))]; - + if (lastRowInRect == -1) { lastRowInRect = _numberOfRows - 1; } - + range.length = lastRowInRect; range.length -= range.location; range.length += 1; @@ -4465,7 +4480,7 @@ - (NSInteger) columnAtPoint: (NSPoint)aPoint else { NSInteger i = 0; - + while ((i < _numberOfColumns) && (aPoint.x >= _columnOrigins[i])) { i++; @@ -4500,17 +4515,17 @@ - (NSInteger) rowAtPoint: (NSPoint)aPoint } } -- (NSRect) frameOfCellAtColumn: (NSInteger)columnIndex +- (NSRect) frameOfCellAtColumn: (NSInteger)columnIndex row: (NSInteger)rowIndex { NSRect frameRect; - if ((columnIndex < 0) + if ((columnIndex < 0) || (rowIndex < 0) || (columnIndex > (_numberOfColumns - 1)) || (rowIndex > (_numberOfRows - 1))) return NSZeroRect; - + frameRect.origin.y = _bounds.origin.y + (rowIndex * _rowHeight); frameRect.origin.y += _intercellSpacing.height / 2; frameRect.size.height = _rowHeight - _intercellSpacing.height; @@ -4530,7 +4545,7 @@ - (NSRect) frameOfCellAtColumn: (NSInteger)columnIndex // Safety check if (frameRect.size.width < 0) frameRect.size.width = 0; - + return frameRect; } @@ -4565,10 +4580,10 @@ - (void) sizeLastColumnToFit lastColumn = [_tableColumns objectAtIndex: (_numberOfColumns - 1)]; if ([lastColumn isResizable] == NO) - { - return; - } - excess_width = NSMaxX([self convertRect: [_super_view bounds] + { + return; + } + excess_width = NSMaxX([self convertRect: [_super_view bounds] fromView: _super_view]) - NSMaxX(_bounds); last_column_width = [lastColumn width] + excess_width; // This will automatically retile the table @@ -4584,15 +4599,15 @@ - (void) setFrame: (NSRect)frameRect { CGFloat rowsHeight = ((_numberOfRows * _rowHeight) + 1); NSRect docRect = [(NSClipView *)_super_view documentVisibleRect]; - + if (rowsHeight < docRect.size.height) { tmpRect.size.height = docRect.size.height; } - else - { + else + { tmpRect.size.height = rowsHeight; - } + } // TODO width? } [super setFrame: tmpRect]; @@ -4601,20 +4616,20 @@ - (void) setFrame: (NSRect)frameRect - (void) setFrameSize: (NSSize)frameSize { NSSize tmpSize = frameSize; - + if ([_super_view respondsToSelector: @selector(documentVisibleRect)]) { CGFloat rowsHeight = ((_numberOfRows * _rowHeight) + 1); NSRect docRect = [(NSClipView *)_super_view documentVisibleRect]; - + if (rowsHeight < docRect.size.height) { tmpSize.height = docRect.size.height; } else - { - tmpSize.height = rowsHeight; - } + { + tmpSize.height = rowsHeight; + } // TODO width? } [super setFrameSize: tmpSize]; @@ -4646,7 +4661,7 @@ - (void) sizeToFit return; columnInfo = NSZoneMalloc(NSDefaultMallocZone(), - sizeof(columnSorting) * 2 + sizeof(columnSorting) * 2 * _numberOfColumns); currentWidth = NSZoneMalloc(NSDefaultMallocZone(), sizeof(CGFloat) * _numberOfColumns); @@ -4657,7 +4672,7 @@ - (void) sizeToFit isResizable = NSZoneMalloc(NSDefaultMallocZone(), sizeof(BOOL) * _numberOfColumns); - remainingWidth = NSMaxX([self convertRect: [_super_view bounds] + remainingWidth = NSMaxX([self convertRect: [_super_view bounds] fromView: _super_view]); /* @@ -4673,7 +4688,7 @@ - (void) sizeToFit { minWidth[i] = [tb minWidth]; maxWidth[i] = [tb maxWidth]; - + if (minWidth[i] < 0) minWidth[i] = 0; if (minWidth[i] > maxWidth[i]) @@ -4685,7 +4700,7 @@ - (void) sizeToFit columnInfo[i * 2].isMax = 0; currentWidth[i] = minWidth[i]; remainingWidth -= minWidth[i]; - + columnInfo[i * 2 + 1].width = maxWidth[i]; columnInfo[i * 2 + 1].isMax = 1; } @@ -4696,35 +4711,35 @@ - (void) sizeToFit columnInfo[i * 2].isMax = 0; currentWidth[i] = minWidth[i]; remainingWidth -= minWidth[i]; - + maxWidth[i] = minWidth[i]; columnInfo[i * 2 + 1].width = maxWidth[i]; columnInfo[i * 2 + 1].isMax = 1; } - } + } // sort the info we have quick_sort_internal(columnInfo, 0, 2 * _numberOfColumns - 1); previousPoint = columnInfo[0].width; numberOfCurrentColumns = 1; - + if (remainingWidth >= 0.) { for (i = 1; i < 2 * _numberOfColumns; i++) { nextPoint = columnInfo[i].width; - - if (numberOfCurrentColumns > 0 && + + if (numberOfCurrentColumns > 0 && (nextPoint - previousPoint) > 0.) { NSInteger verification = 0; - + if ((nextPoint - previousPoint) * numberOfCurrentColumns <= remainingWidth) { toAddToCurrentColumns = nextPoint - previousPoint; - remainingWidth -= + remainingWidth -= (nextPoint - previousPoint) * numberOfCurrentColumns; for (j = 0; j < _numberOfColumns; j++) @@ -4754,7 +4769,7 @@ - (void) sizeToFit && maxWidth[j] >= nextPoint) { currentWidth[j] += quotient; - if (remainder > 0 + if (remainder > 0 && maxWidth[j] >= currentWidth[j] + 1) { remainder--; @@ -4770,14 +4785,14 @@ - (void) sizeToFit if (minWidth[j] <= previousPoint && maxWidth[j] >= nextPoint) { - if (remainder > 0 + if (remainder > 0 && maxWidth[j] >= currentWidth[j] + 1) { remainder--; currentWidth[j]++; } } - + } } if (remainder > 0) @@ -4786,20 +4801,20 @@ - (void) sizeToFit else remainingWidth = 0.; } - - + + } else if (numberOfCurrentColumns < 0) { NSLog(@"[NSTableView sizeToFit]: unexpected error"); } - + if (columnInfo[i].isMax) numberOfCurrentColumns--; else numberOfCurrentColumns++; previousPoint = nextPoint; - + if (remainingWidth == 0.) { break; @@ -4852,18 +4867,18 @@ - (void) sizeToFit enumerator = [_tableColumns objectEnumerator]; while ((tb = [enumerator nextObject]) != nil) { - // Compute min width of column + // Compute min width of column width = [[tb headerCell] cellSize].width; for (row = 0; row < _numberOfRows; row++) { - cell = [self preparedCellAtColumn: [_tableColumns indexOfObject: tb] - row: row]; + cell = [self preparedCellAtColumn: [_tableColumns indexOfObject: tb] + row: row]; [cell setObjectValue: [_dataSource tableView: self objectValueForTableColumn: tb - row: row]]; + row: row]]; [self _willDisplayCell: cell - forTableColumn: tb - row: row]; + forTableColumn: tb + row: row]; candidate_width = [cell cellSize].width; if (_drawsGrid) @@ -4876,22 +4891,22 @@ - (void) sizeToFit } width += _intercellSpacing.width; [tb setWidth: width]; - // It is necessary to ask the column for the width, since it might have + // It is necessary to ask the column for the width, since it might have // been changed by the column to constrain it to a min or max width table_width += [tb width]; } // Second Step - // If superview (clipview) is bigger than that, divide remaining space + // If superview (clipview) is bigger than that, divide remaining space // between all columns if ((_super_view != nil) && (_numberOfColumns > 0)) { float excess_width; - excess_width = NSMaxX ([self convertRect: [_super_view bounds] + excess_width = NSMaxX ([self convertRect: [_super_view bounds] fromView: _super_view]); excess_width -= table_width; - // Since we resized each column at its minimum width, + // Since we resized each column at its minimum width, // it's useless to try shrinking more: we can't if (excess_width <= 0) { @@ -4920,79 +4935,79 @@ - (void) noteNumberOfRowsChanged NSRect newFrame; _numberOfRows = [self _numRows]; - + /* If we are selecting rows, we have to check that we have no selected rows below the new end of the table */ if (!_selectingColumns) { NSUInteger row = [_selectedRows lastIndex]; - + if (row == NSNotFound) - { - if (!_allowsEmptySelection) - { - /* We shouldn't allow empty selection - try - selecting the last row */ - NSInteger lastRow = _numberOfRows - 1; - - if (lastRow > -1) - { - [self _postSelectionIsChangingNotification]; - [_selectedRows addIndex: lastRow]; - _selectedRow = lastRow; - [self _postSelectionDidChangeNotification]; - } - else - { - /* problem - there are no rows at all */ - _selectedRow = -1; - } - } - } + { + if (!_allowsEmptySelection) + { + /* We shouldn't allow empty selection - try + selecting the last row */ + NSInteger lastRow = _numberOfRows - 1; + + if (lastRow > -1) + { + [self _postSelectionIsChangingNotification]; + [_selectedRows addIndex: lastRow]; + _selectedRow = lastRow; + [self _postSelectionDidChangeNotification]; + } + else + { + /* problem - there are no rows at all */ + _selectedRow = -1; + } + } + } /* Check that all selected rows are in the new range of rows */ else if (row >= _numberOfRows) - { - [_selectedRows removeIndexesInRange: - NSMakeRange(_numberOfRows, row + 1 - _numberOfRows)]; - if (_selectedRow >= _numberOfRows) - { - row = [_selectedRows lastIndex]; - [self _postSelectionIsChangingNotification]; - - if (row != NSNotFound) - { - _selectedRow = row; - } - else - { - /* Argh - all selected rows were outside the table */ - if (_allowsEmptySelection) - { - _selectedRow = -1; - } - else - { - /* We shouldn't allow empty selection - try - selecting the last row */ - NSInteger lastRow = _numberOfRows - 1; - - if (lastRow > -1) - { - [_selectedRows addIndex: lastRow]; - _selectedRow = lastRow; - } - else - { - /* problem - there are no rows at all */ - _selectedRow = -1; - } - } - } - [self _postSelectionDidChangeNotification]; - } - } - } - + { + [_selectedRows removeIndexesInRange: + NSMakeRange(_numberOfRows, row + 1 - _numberOfRows)]; + if (_selectedRow >= _numberOfRows) + { + row = [_selectedRows lastIndex]; + [self _postSelectionIsChangingNotification]; + + if (row != NSNotFound) + { + _selectedRow = row; + } + else + { + /* Argh - all selected rows were outside the table */ + if (_allowsEmptySelection) + { + _selectedRow = -1; + } + else + { + /* We shouldn't allow empty selection - try + selecting the last row */ + NSInteger lastRow = _numberOfRows - 1; + + if (lastRow > -1) + { + [_selectedRows addIndex: lastRow]; + _selectedRow = lastRow; + } + else + { + /* problem - there are no rows at all */ + _selectedRow = -1; + } + } + } + [self _postSelectionDidChangeNotification]; + } + } + } + newFrame = _frame; newFrame.size.height = (_numberOfRows * _rowHeight) + 1; if (NO == NSEqualRects(newFrame, NSUnionRect(newFrame, _frame))) @@ -5007,11 +5022,11 @@ - (void) noteNumberOfRowsChanged { NSRect superviewBounds; // Get this *after* [self setFrame:] superviewBounds = [_super_view bounds]; - if ((superviewBounds.origin.x <= _frame.origin.x) - && (NSMaxY(superviewBounds) >= NSMaxY(_frame))) - { - [self setNeedsDisplay: YES]; - } + if ((superviewBounds.origin.x <= _frame.origin.x) + && (NSMaxY(superviewBounds) >= NSMaxY(_frame))) + { + [self setNeedsDisplay: YES]; + } } } @@ -5027,7 +5042,7 @@ - (void) tile { NSInteger i; CGFloat width; - + _columnOrigins[0] = _bounds.origin.x; width = [[_tableColumns objectAtIndex: 0] width]; table_width += width; @@ -5048,31 +5063,31 @@ - (void) tile CGFloat innerBorderWidth = [[NSUserDefaults standardUserDefaults] boolForKey: @"GSScrollViewNoInnerBorder"] ? 0.0 : 1.0; - [_headerView setFrameSize: + [_headerView setFrameSize: NSMakeSize (_frame.size.width, [_headerView frame].size.height)]; - [_cornerView setFrameSize: + [_cornerView setFrameSize: NSMakeSize ([NSScroller scrollerWidth] + innerBorderWidth, [_headerView frame].size.height)]; [_headerView setNeedsDisplay: YES]; [_cornerView setNeedsDisplay: YES]; - } + } } -/* - * Drawing +/* + * Drawing */ - (void) _calculatedStartingColumn: (NSInteger *)startingColumn endingColumn: (NSInteger *)endingColumn inClipRect: (NSRect)clipRect - + { CGFloat x_pos = 0.0; NSInteger i = 0; NSInteger numberOfColumns = [self numberOfColumns]; CGFloat *columnOrigins = [self _columnOrigins]; - - /* Using columnAtPoint: here would make it called twice per row per drawn + + /* Using columnAtPoint: here would make it called twice per row per drawn rect - so we avoid it and do it natively */ /* Determine starting column as fast as possible */ @@ -5104,11 +5119,11 @@ - (void) _drawCellViewRow: (NSInteger)rowIndex clipRect: (NSRect)clipRect { NSInteger numberOfRows = [self numberOfRows]; - NSInteger startingColumn; + NSInteger startingColumn; NSInteger endingColumn; NSInteger columnIndex; id dataSource = [self dataSource]; - + // If we have no data source, there is nothing to do... if (dataSource == nil) { @@ -5120,20 +5135,20 @@ - (void) _drawCellViewRow: (NSInteger)rowIndex { return; } - + [self _calculatedStartingColumn: &startingColumn endingColumn: &endingColumn inClipRect: clipRect]; - + /* Draw the row between startingColumn and endingColumn */ for (columnIndex = startingColumn; columnIndex <= endingColumn; columnIndex++) { id rowView = [self rowViewAtRow: rowIndex - makeIfNecessary: YES]; + makeIfNecessary: YES]; NSView *view = [self viewAtColumn: columnIndex row: rowIndex makeIfNecessary: YES]; - + // If the view is already part of the table, don't re-add it... if (rowView != nil && [[self subviews] containsObject: rowView] == NO) @@ -5144,23 +5159,23 @@ - (void) _drawCellViewRow: (NSInteger)rowIndex CGFloat y = cellFrame.origin.y; CGFloat w = [self frame].size.width; CGFloat h = [self rowHeight]; - + NSRect rvFrame = NSMakeRect(x, y, w, h); NSAutoresizingMaskOptions options = NSViewWidthSizable | NSViewMinYMargin; - + [self addSubview: rowView]; [rowView setAutoresizingMask: options]; [rowView setFrame: rvFrame]; } - + // Create the view if needed... if (view != nil && [[rowView subviews] containsObject: view] == NO) { // Add the view to the row... [rowView addSubview: view]; - + // Place the view... NSRect newRect = [view frame]; newRect.origin.y = 0.0; @@ -5220,8 +5235,8 @@ - (BOOL) isOpaque return YES; } -/* - * Scrolling +/* + * Scrolling */ - (void) scrollRowToVisible: (NSInteger)rowIndex @@ -5230,14 +5245,14 @@ - (void) scrollRowToVisible: (NSInteger)rowIndex { NSRect rowRect = [self rectOfRow: rowIndex]; NSRect visibleRect = [self visibleRect]; - - // If the row is over the top, or it is partially visible + + // If the row is over the top, or it is partially visible // on top, - if ((rowRect.origin.y < visibleRect.origin.y)) + if ((rowRect.origin.y < visibleRect.origin.y)) { // Then make it visible on top - NSPoint newOrigin; - + NSPoint newOrigin; + newOrigin.x = visibleRect.origin.x; newOrigin.y = rowRect.origin.y; newOrigin = [self convertPoint: newOrigin toView: _super_view]; @@ -5249,8 +5264,8 @@ - (void) scrollRowToVisible: (NSInteger)rowIndex if (NSMaxY (rowRect) > NSMaxY (visibleRect)) { // Then make it visible on bottom - NSPoint newOrigin; - + NSPoint newOrigin; + newOrigin.x = visibleRect.origin.x; newOrigin.y = visibleRect.origin.y; newOrigin.y += NSMaxY (rowRect) - NSMaxY (visibleRect); @@ -5269,13 +5284,13 @@ - (void) scrollColumnToVisible: (NSInteger)columnIndex NSRect visibleRect = [self visibleRect]; CGFloat diff; - // If the row is out on the left, or it is partially visible + // If the row is out on the left, or it is partially visible // on the left - if ((columnRect.origin.x < visibleRect.origin.x)) + if ((columnRect.origin.x < visibleRect.origin.x)) { // Then make it visible on the left - NSPoint newOrigin; - + NSPoint newOrigin; + newOrigin.x = columnRect.origin.x; newOrigin.y = visibleRect.origin.y; newOrigin = [self convertPoint: newOrigin toView: _super_view]; @@ -5301,8 +5316,8 @@ - (void) scrollColumnToVisible: (NSInteger)columnIndex } -/* - * Text delegate methods +/* + * Text delegate methods */ - (void) textDidBeginEditing: (NSNotification *)aNotification @@ -5313,7 +5328,7 @@ - (void) textDidBeginEditing: (NSNotification *)aNotification - (void) textDidChange: (NSNotification *)aNotification { // MacOS-X asks us to inform the cell if possible. - if ((_editedCell != nil) && [_editedCell respondsToSelector: + if ((_editedCell != nil) && [_editedCell respondsToSelector: @selector(textDidChange:)]) [_editedCell textDidChange: aNotification]; @@ -5379,20 +5394,20 @@ - (BOOL) textShouldEndEditing: (NSText*)textObject NSBeep (); return NO; } - + return YES; } - if ([_delegate respondsToSelector: + if ([_delegate respondsToSelector: @selector(control:isValidObject:)] == YES) { NSFormatter *formatter; id newObjectValue; - + formatter = [_editedCell formatter]; - - if ([formatter getObjectValue: &newObjectValue - forString: [_textObject text] + + if ([formatter getObjectValue: &newObjectValue + forString: [_textObject text] errorDescription: NULL] == YES) { if ([_delegate control: self @@ -5404,8 +5419,8 @@ - (BOOL) textShouldEndEditing: (NSText*)textObject return [_editedCell isEntryAcceptable: [textObject text]]; } -/* - * Persistence +/* + * Persistence */ - (NSString *) autosaveName @@ -5435,32 +5450,32 @@ - (void) setAutosaveTableColumns: (BOOL)flag if (flag) { [self _autoloadTableColumns]; - [nc addObserver: self - selector: @selector(_autosaveTableColumns) + [nc addObserver: self + selector: @selector(_autosaveTableColumns) name: NSTableViewColumnDidResizeNotification object: self]; } else { - [nc removeObserver: self + [nc removeObserver: self name: NSTableViewColumnDidResizeNotification - object: self]; + object: self]; } } -/* - * Delegate +/* + * Delegate */ - (void) setDelegate: (id)anObject { const SEL sel = @selector(tableView:willDisplayCell:forTableColumn:row:); const SEL vbsel = @selector(tableView:viewForTableColumn:row:); - + if (_delegate) [nc removeObserver: _delegate name: nil object: self]; _delegate = anObject; - + #define SET_DELEGATE_NOTIFICATION(notif_name) \ if ([_delegate respondsToSelector: @selector(tableView##notif_name:)]) \ [nc addObserver: _delegate \ @@ -5471,7 +5486,7 @@ - (void) setDelegate: (id)anObject SET_DELEGATE_NOTIFICATION(ColumnDidResize); SET_DELEGATE_NOTIFICATION(SelectionDidChange); SET_DELEGATE_NOTIFICATION(SelectionIsChanging); - + /* Cache */ _del_responds = [_delegate respondsToSelector: sel]; @@ -5530,8 +5545,8 @@ - (void) setHighlightedTableColumn: (NSTableColumn *)aTableColumn /* dragging rows */ - (NSImage*) dragImageForRows: (NSArray*)dragRows - event: (NSEvent*)dragEvent - dragImageOffset: (NSPoint*)dragImageOffset + event: (NSEvent*)dragEvent + dragImageOffset: (NSPoint*)dragImageOffset { // FIXME NSImage *dragImage = [[NSImage alloc] @@ -5541,24 +5556,24 @@ - (NSImage*) dragImageForRows: (NSArray*)dragRows } - (NSImage *) dragImageForRowsWithIndexes: (NSIndexSet*)rows - tableColumns: (NSArray*)cols - event: (NSEvent*)event - offset: (NSPoint*)offset + tableColumns: (NSArray*)cols + event: (NSEvent*)event + offset: (NSPoint*)offset { // FIXME NSArray *rowArray; rowArray = [self _indexSetToArray: rows]; - return [self dragImageForRows: rowArray - event: event - dragImageOffset: offset]; + return [self dragImageForRows: rowArray + event: event + dragImageOffset: offset]; } - (void) setDropRow: (NSInteger)row dropOperation: (NSTableViewDropOperation)operation { - if (row < -1 || row > _numberOfRows - || (operation == NSTableViewDropOn && row == _numberOfRows)) + if (row < -1 || row > _numberOfRows + || (operation == NSTableViewDropOn && row == _numberOfRows)) { currentDropRow = -1; currentDropOperation = NSTableViewDropOn; @@ -5583,11 +5598,11 @@ - (BOOL) verticalMotionCanBeginDrag - (NSArray*) namesOfPromisedFilesDroppedAtDestination: (NSURL *)dropDestination { if ([_dataSource respondsToSelector: - @selector(tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes:)]) + @selector(tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes:)]) { return [_dataSource tableView: self - namesOfPromisedFilesDroppedAtDestination: dropDestination - forDraggedRowsWithIndexes: _selectedRows]; + namesOfPromisedFilesDroppedAtDestination: dropDestination + forDraggedRowsWithIndexes: _selectedRows]; } else { @@ -5603,13 +5618,13 @@ - (void) encodeWithCoder: (NSCoder*)aCoder { if ([aCoder allowsKeyedCoding]) { - unsigned int vFlags = 0; + unsigned int vFlags = 0; NSSize intercellSpacing = [self intercellSpacing]; GSTableViewFlags tableViewFlags; // make sure the corner view is properly encoded... [super encodeWithCoder: aCoder]; - + if ([self dataSource]) { [aCoder encodeObject: [self dataSource] forKey: @"NSDataSource"]; @@ -5639,28 +5654,28 @@ - (void) encodeWithCoder: (NSCoder*)aCoder [aCoder encodeObject: [self tableColumns] forKey: @"NSTableColumns"]; if (_headerView) - { - [aCoder encodeObject: _headerView forKey: @"NSHeaderView"]; - } + { + [aCoder encodeObject: _headerView forKey: @"NSHeaderView"]; + } if (_cornerView) - { - [aCoder encodeObject: _cornerView forKey: @"NSCornerView"]; - } + { + [aCoder encodeObject: _cornerView forKey: @"NSCornerView"]; + } if ([[self sortDescriptors] count] > 0) - { - [aCoder encodeObject: _sortDescriptors forKey: @"NSSortDescriptors"]; - } + { + [aCoder encodeObject: _sortDescriptors forKey: @"NSSortDescriptors"]; + } tableViewFlags.columnSelection = [self allowsColumnSelection]; tableViewFlags.multipleSelection = [self allowsMultipleSelection]; tableViewFlags.emptySelection = [self allowsEmptySelection]; - tableViewFlags.drawsGrid = [self drawsGrid]; + tableViewFlags.drawsGrid = [self drawsGrid]; tableViewFlags.columnResizing = [self allowsColumnResizing]; tableViewFlags.columnOrdering = [self allowsColumnReordering]; tableViewFlags.columnAutosave = [self autosaveTableColumns]; tableViewFlags.alternatingRowBackgroundColors = [self usesAlternatingRowBackgroundColors]; - + memcpy((void *)&vFlags,(void *)&tableViewFlags,sizeof(unsigned int)); // encode.. @@ -5688,13 +5703,13 @@ - (void) encodeWithCoder: (NSCoder*)aCoder [aCoder encodeValueOfObjCType: @encode(int) at: &number]; number = _numberOfColumns; [aCoder encodeValueOfObjCType: @encode(int) at: &number]; - + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_drawsGrid]; rowHeight = _rowHeight; [aCoder encodeValueOfObjCType: @encode(float) at: &rowHeight]; [aCoder encodeValueOfObjCType: @encode(SEL) at: &_doubleAction]; [aCoder encodeSize: _intercellSpacing]; - + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_allowsMultipleSelection]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_allowsEmptySelection]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_allowsColumnSelection]; @@ -5722,22 +5737,22 @@ - (id) initWithCoder: (NSCoder*)aDecoder // assign defaults, so that there's color in case none is specified [self _initDefaults]; - ASSIGN(_gridColor, [NSColor gridColor]); - ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]); + ASSIGN(_gridColor, [NSColor gridColor]); + ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]); ASSIGN(_tableColumns, [NSMutableArray array]); ASSIGN(_sortDescriptors, [NSArray array]); // // Check for nil on some of these, since they are usually set // in NSIBOutletConnector objects we don't want to override - // that setting unless they're directly encoded with the - // object. - // + // that setting unless they're directly encoded with the + // object. + // // I'm not sure why IB encodes nil values for these, but // the behaviour here should match that on Mac OS X. // if ([aDecoder containsValueForKey: @"NSDataSource"]) - { + { id obj = [aDecoder decodeObjectForKey: @"NSDataSource"]; if(obj != nil) { @@ -5745,7 +5760,7 @@ - (id) initWithCoder: (NSCoder*)aDecoder } } if ([aDecoder containsValueForKey: @"NSDelegate"]) - { + { id obj = [aDecoder decodeObjectForKey: @"NSDelegate"]; if(obj != nil) { @@ -5753,7 +5768,7 @@ - (id) initWithCoder: (NSCoder*)aDecoder } } if ([aDecoder containsValueForKey: @"NSTarget"]) - { + { id obj = [aDecoder decodeObjectForKey: @"NSTarget"]; if(obj != nil) { @@ -5761,16 +5776,16 @@ - (id) initWithCoder: (NSCoder*)aDecoder } } if ([aDecoder containsValueForKey: @"NSAction"]) - { - NSString *action = [aDecoder decodeObjectForKey: @"NSAction"]; + { + NSString *action = [aDecoder decodeObjectForKey: @"NSAction"]; if(action != nil) { [self setAction: NSSelectorFromString(action)]; } } if ([aDecoder containsValueForKey: @"NSDoubleAction"]) - { - NSString *action = [aDecoder decodeObjectForKey: @"NSDoubleAction"]; + { + NSString *action = [aDecoder decodeObjectForKey: @"NSDoubleAction"]; if(action != nil) { [self setDoubleAction: NSSelectorFromString(action)]; @@ -5778,80 +5793,80 @@ - (id) initWithCoder: (NSCoder*)aDecoder } if ([aDecoder containsValueForKey: @"NSBackgroundColor"]) - { - [self setBackgroundColor: [aDecoder decodeObjectForKey: @"NSBackgroundColor"]]; - } + { + [self setBackgroundColor: [aDecoder decodeObjectForKey: @"NSBackgroundColor"]]; + } if ([aDecoder containsValueForKey: @"NSGridColor"]) - { - [self setGridColor: [aDecoder decodeObjectForKey: @"NSGridColor"]]; - } + { + [self setGridColor: [aDecoder decodeObjectForKey: @"NSGridColor"]]; + } intercellSpacing = [self intercellSpacing]; if ([aDecoder containsValueForKey: @"NSIntercellSpacingHeight"]) - { - intercellSpacing.height = [aDecoder decodeFloatForKey: @"NSIntercellSpacingHeight"]; - } + { + intercellSpacing.height = [aDecoder decodeFloatForKey: @"NSIntercellSpacingHeight"]; + } if ([aDecoder containsValueForKey: @"NSIntercellSpacingWidth"]) - { - intercellSpacing.width = [aDecoder decodeFloatForKey: @"NSIntercellSpacingWidth"]; - } + { + intercellSpacing.width = [aDecoder decodeFloatForKey: @"NSIntercellSpacingWidth"]; + } [self setIntercellSpacing: intercellSpacing]; if ([aDecoder containsValueForKey: @"NSDraggingSourceMaskForLocal"]) - { - [self setDraggingSourceOperationMask: - [aDecoder decodeIntForKey: @"NSDraggingSourceMaskForLocal"] - forLocal: YES]; - } + { + [self setDraggingSourceOperationMask: + [aDecoder decodeIntForKey: @"NSDraggingSourceMaskForLocal"] + forLocal: YES]; + } if ([aDecoder containsValueForKey: @"NSDraggingSourceMaskForNonLocal"]) - { - [self setDraggingSourceOperationMask: - [aDecoder decodeIntForKey: @"NSDraggingSourceMaskForNonLocal"] - forLocal: NO]; - } + { + [self setDraggingSourceOperationMask: + [aDecoder decodeIntForKey: @"NSDraggingSourceMaskForNonLocal"] + forLocal: NO]; + } if ([aDecoder containsValueForKey: @"NSRowHeight"]) - { - [self setRowHeight: [aDecoder decodeFloatForKey: @"NSRowHeight"]]; - } + { + [self setRowHeight: [aDecoder decodeFloatForKey: @"NSRowHeight"]]; + } if ([aDecoder containsValueForKey: @"NSCornerView"]) - { + { NSView *aView = [aDecoder decodeObjectForKey: @"NSCornerView"]; - [self setCornerView: aView]; + [self setCornerView: aView]; [aView setHidden: NO]; - } + } else - { - _cornerView = [GSTableCornerView new]; - } + { + _cornerView = [GSTableCornerView new]; + } if ([aDecoder containsValueForKey: @"NSHeaderView"]) - { - [self setHeaderView: [aDecoder decodeObjectForKey: @"NSHeaderView"]]; - } + { + [self setHeaderView: [aDecoder decodeObjectForKey: @"NSHeaderView"]]; + } if ([aDecoder containsValueForKey: @"NSSortDescriptors"]) - { - ASSIGN(_sortDescriptors, [aDecoder decodeObjectForKey: @"NSSortDescriptors"]); - } + { + ASSIGN(_sortDescriptors, [aDecoder decodeObjectForKey: @"NSSortDescriptors"]); + } if ([aDecoder containsValueForKey: @"NSTvFlags"]) - { - unsigned int flags = [aDecoder decodeIntForKey: @"NSTvFlags"]; - GSTableViewFlags tableViewFlags; - memcpy((void *)&tableViewFlags,(void *)&flags,sizeof(struct _tableViewFlags)); - - [self setAllowsColumnSelection: tableViewFlags.columnSelection]; - [self setAllowsMultipleSelection: tableViewFlags.multipleSelection]; - [self setAllowsEmptySelection: tableViewFlags.emptySelection]; - [self setDrawsGrid: tableViewFlags.drawsGrid]; - [self setAllowsColumnResizing: tableViewFlags.columnResizing]; - [self setAllowsColumnReordering: tableViewFlags.columnOrdering]; - [self setAutosaveTableColumns: tableViewFlags.columnAutosave]; - [self setUsesAlternatingRowBackgroundColors: tableViewFlags.alternatingRowBackgroundColors]; - } - + { + unsigned int flags = [aDecoder decodeIntForKey: @"NSTvFlags"]; + GSTableViewFlags tableViewFlags; + memcpy((void *)&tableViewFlags,(void *)&flags,sizeof(struct _tableViewFlags)); + + [self setAllowsColumnSelection: tableViewFlags.columnSelection]; + [self setAllowsMultipleSelection: tableViewFlags.multipleSelection]; + [self setAllowsEmptySelection: tableViewFlags.emptySelection]; + [self setDrawsGrid: tableViewFlags.drawsGrid]; + [self setAllowsColumnResizing: tableViewFlags.columnResizing]; + [self setAllowsColumnReordering: tableViewFlags.columnOrdering]; + [self setAutosaveTableColumns: tableViewFlags.columnAutosave]; + [self setUsesAlternatingRowBackgroundColors: tableViewFlags.alternatingRowBackgroundColors]; + } + if ([aDecoder containsValueForKey: @"NSViewBased"]) { _viewBased = [aDecoder decodeBoolForKey: @"NSViewBased"]; @@ -5861,18 +5876,18 @@ - (id) initWithCoder: (NSCoder*)aDecoder columns = [aDecoder decodeObjectForKey: @"NSTableColumns"]; e = [columns objectEnumerator]; while ((col = [e nextObject]) != nil) - { - /* Will initialize -[NSTableColumn tableView], _numberOfColumns and - allocate _columnsOrigins */ - [self addTableColumn: col]; - } + { + /* Will initialize -[NSTableColumn tableView], _numberOfColumns and + allocate _columnsOrigins */ + [self addTableColumn: col]; + } [self tile]; /* Initialize _columnOrigins */ } else { - int version = [aDecoder versionForClassName: - @"NSTableView"]; + int version = [aDecoder versionForClassName: + @"NSTableView"]; id aDelegate; float rowHeight; int number; @@ -5890,7 +5905,7 @@ - (id) initWithCoder: (NSCoder*)aDecoder [self setDelegate: aDelegate]; [_headerView setTableView: self]; [_tableColumns makeObjectsPerformSelector: @selector(setTableView:) - withObject: self]; + withObject: self]; [aDecoder decodeValueOfObjCType: @encode(int) at: &number]; _numberOfRows = number; @@ -5901,26 +5916,26 @@ - (id) initWithCoder: (NSCoder*)aDecoder _rowHeight = rowHeight; [aDecoder decodeValueOfObjCType: @encode(SEL) at: &_doubleAction]; _intercellSpacing = [aDecoder decodeSize]; - + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsMultipleSelection]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsEmptySelection]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsColumnSelection]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsColumnResizing]; if (version >= 3) - { - [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsColumnReordering]; - } + { + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsColumnReordering]; + } if (version >= 2) - { - [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_autoresizesAllColumnsToFit]; - } - + { + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_autoresizesAllColumnsToFit]; + } + if (version >= 4) - { - [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_verticalMotionDrag]; - } + { + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_verticalMotionDrag]; + } if (version >= 5) { @@ -5929,17 +5944,17 @@ - (id) initWithCoder: (NSCoder*)aDecoder if (version >= 6) { - [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_viewBased]; + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_viewBased]; } - + if (_numberOfColumns > 0) - { - _columnOrigins = NSZoneMalloc (NSDefaultMallocZone (), - sizeof(CGFloat) * _numberOfColumns); - } + { + _columnOrigins = NSZoneMalloc (NSDefaultMallocZone (), + sizeof(CGFloat) * _numberOfColumns); + } [self tile]; /* Initialize _columnOrigins */ } - + return self; } @@ -6003,7 +6018,7 @@ - (CGFloat *) _columnOrigins - (void) _mouseDownInHeaderOfTableColumn: (NSTableColumn *)tc { - if ([_delegate + if ([_delegate respondsToSelector: @selector(tableView:mouseDownInHeaderOfTableColumn:)]) { @@ -6016,7 +6031,7 @@ - (void) _clickTableColumn: (NSTableColumn *)tc { NSSortDescriptor *oldMainSortDescriptor = nil; NSSortDescriptor *newMainSortDescriptor = [tc sortDescriptorPrototype]; - NSMutableArray *newSortDescriptors = + NSMutableArray *newSortDescriptors = [NSMutableArray arrayWithArray: [self sortDescriptors]]; NSEnumerator *e = [newSortDescriptors objectEnumerator]; NSSortDescriptor *descriptor = nil; @@ -6031,7 +6046,7 @@ - (void) _clickTableColumn: (NSTableColumn *)tc while ((descriptor = [e nextObject]) != nil) { if ([[descriptor key] isEqual: [newMainSortDescriptor key]]) - [outdatedDescriptors addObject: descriptor]; + [outdatedDescriptors addObject: descriptor]; } /* Invert the sort direction when the same column header is clicked twice */ @@ -6061,46 +6076,46 @@ - (void) _editNextCellAfterRow: (NSInteger) row byExtendingSelection: NO]; if ([self _isCellEditableColumn: column row:row]) - { - [self editColumn: column - row: row - withEvent: nil - select: YES]; - } + { + [self editColumn: column + row: row + withEvent: nil + select: YES]; + } } } -(BOOL) _editNextEditableCellAfterRow: (NSInteger)row - column: (NSInteger)column + column: (NSInteger)column { NSInteger i, j; - + if (row > -1) { // First look for cells in the same row for (j = column + 1; j < _numberOfColumns; j++) - { - if ([self _isCellEditableColumn: j row: row]) - { - [self editColumn: j row: row withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: row]) + { + [self editColumn: j row: row withEvent: nil select: YES]; + return YES; + } + } } // Otherwise, make the big cycle. for (i = row + 1; i < _numberOfRows; i++) { for (j = 0; j < _numberOfColumns; j++) - { - if ([self _isCellEditableColumn: j row: i]) - { - // Need to select row to be able to edit it. - [self selectRow: i byExtendingSelection: NO]; - [self editColumn: j row: i withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: i]) + { + // Need to select row to be able to edit it. + [self selectRow: i byExtendingSelection: NO]; + [self editColumn: j row: i withEvent: nil select: YES]; + return YES; + } + } } // Should we loop around or not? @@ -6109,15 +6124,15 @@ -(BOOL) _editNextEditableCellAfterRow: (NSInteger)row for (i = 0; i < row; i++) { for (j = 0; j < _numberOfColumns; j++) - { - if ([self _isCellEditableColumn: j row: i]) - { - // Need to select row to be able to edit it. - [self selectRow: i byExtendingSelection: NO]; - [self editColumn: j row: i withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: i]) + { + // Need to select row to be able to edit it. + [self selectRow: i byExtendingSelection: NO]; + [self editColumn: j row: i withEvent: nil select: YES]; + return YES; + } + } } // Still nothing? Look at the beginning of the current row @@ -6125,13 +6140,13 @@ -(BOOL) _editNextEditableCellAfterRow: (NSInteger)row { // First look for cells in the same row for (j = 0; j < column; j++) - { - if ([self _isCellEditableColumn: j row: row]) - { - [self editColumn: j row: row withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: row]) + { + [self editColumn: j row: row withEvent: nil select: YES]; + return YES; + } + } } #endif @@ -6147,28 +6162,28 @@ -(BOOL) _editPreviousEditableCellBeforeRow: (NSInteger)row { // First look for cells in the same row for (j = column - 1; j > -1; j--) - { - if ([self _isCellEditableColumn: j row: row]) - { - [self editColumn: j row: row withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: row]) + { + [self editColumn: j row: row withEvent: nil select: YES]; + return YES; + } + } } // Otherwise, make the big cycle. for (i = row - 1; i > -1; i--) { for (j = _numberOfColumns - 1; j > -1; j--) - { - if ([self _isCellEditableColumn: j row: i]) - { - // Need to select row to be able to edit it. - [self selectRow: i byExtendingSelection: NO]; - [self editColumn: j row: i withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: i]) + { + // Need to select row to be able to edit it. + [self selectRow: i byExtendingSelection: NO]; + [self editColumn: j row: i withEvent: nil select: YES]; + return YES; + } + } } // Should we loop around or not? @@ -6177,15 +6192,15 @@ -(BOOL) _editPreviousEditableCellBeforeRow: (NSInteger)row for (i = _numberOfRows - 1; i > row; i--) { for (j = _numberOfColumns - 1; j > -1; j--) - { - if ([self _isCellEditableColumn: j row: i]) - { - // Need to select row to be able to edit it. - [self selectRow: i byExtendingSelection: NO]; - [self editColumn: j row: i withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: i]) + { + // Need to select row to be able to edit it. + [self selectRow: i byExtendingSelection: NO]; + [self editColumn: j row: i withEvent: nil select: YES]; + return YES; + } + } } // Still nothing? Look at the end of the current row @@ -6193,13 +6208,13 @@ -(BOOL) _editPreviousEditableCellBeforeRow: (NSInteger)row { // First look for cells in the same row for (j = _numberOfColumns - 1; j > column; j++) - { - if ([self _isCellEditableColumn: j row: row]) - { - [self editColumn: j row: row withEvent: nil select: YES]; - return YES; - } - } + { + if ([self _isCellEditableColumn: j row: row]) + { + [self editColumn: j row: row withEvent: nil select: YES]; + return YES; + } + } } #endif @@ -6208,7 +6223,7 @@ -(BOOL) _editPreviousEditableCellBeforeRow: (NSInteger)row - (void) _autosaveTableColumns { - if (_autosaveTableColumns && _autosaveName != nil) + if (_autosaveTableColumns && _autosaveName != nil) { NSUserDefaults *defaults; NSString *tableKey; @@ -6217,24 +6232,24 @@ - (void) _autosaveTableColumns id en; defaults = [NSUserDefaults standardUserDefaults]; - tableKey = [NSString stringWithFormat: @"NSTableView Columns %@", + tableKey = [NSString stringWithFormat: @"NSTableView Columns %@", _autosaveName]; config = [NSMutableDictionary new]; - + en = [[self tableColumns] objectEnumerator]; while ((column = [en nextObject]) != nil) { NSArray *array; NSNumber *width, *identNum; id ident; - + width = [NSNumber numberWithInt: [column width]]; ident = [column identifier]; - identNum = [NSNumber numberWithInt: [self columnWithIdentifier: + identNum = [NSNumber numberWithInt: [self columnWithIdentifier: ident]]; - array = [NSArray arrayWithObjects: width, identNum, nil]; - [config setObject: array forKey: ident]; - } + array = [NSArray arrayWithObjects: width, identNum, nil]; + [config setObject: array forKey: ident]; + } [defaults setObject: config forKey: tableKey]; [defaults synchronize]; RELEASE (config); @@ -6243,27 +6258,27 @@ - (void) _autosaveTableColumns - (void) _autoloadTableColumns { - if (_autosaveTableColumns && _autosaveName != nil) - { + if (_autosaveTableColumns && _autosaveName != nil) + { NSUserDefaults *defaults; NSDictionary *config; NSString *tableKey; defaults = [NSUserDefaults standardUserDefaults]; - tableKey = [NSString stringWithFormat: @"NSTableView Columns %@", + tableKey = [NSString stringWithFormat: @"NSTableView Columns %@", _autosaveName]; config = [defaults objectForKey: tableKey]; - if (config != nil) + if (config != nil) { NSEnumerator *en = [[config allKeys] objectEnumerator]; NSString *colKey; - NSArray *colDesc; + NSArray *colDesc; NSTableColumn *col; - - while ((colKey = [en nextObject]) != nil) + + while ((colKey = [en nextObject]) != nil) { col = [self tableColumnWithIdentifier: colKey]; - + if (col != nil) { colDesc = [config objectForKey: colKey]; @@ -6280,22 +6295,22 @@ - (void) superviewFrameChanged: (NSNotification*)aNotification { if (_autoresizesAllColumnsToFit == YES) { - CGFloat visible_width = [self convertRect: [_super_view bounds] + CGFloat visible_width = [self convertRect: [_super_view bounds] fromView: _super_view].size.width; CGFloat table_width = 0; if (_numberOfColumns > 0) - { - table_width = - _columnOrigins[_numberOfColumns - 1] + - [[_tableColumns objectAtIndex: _numberOfColumns - 1] width]; - } - + { + table_width = + _columnOrigins[_numberOfColumns - 1] + + [[_tableColumns objectAtIndex: _numberOfColumns - 1] width]; + } + /* NSLog(@"columnOrigins[0] %f", _columnOrigins[0]); - NSLog(@"superview.bounds %@", + NSLog(@"superview.bounds %@", NSStringFromRect([_super_view bounds])); - NSLog(@"superview.frame %@", + NSLog(@"superview.frame %@", NSStringFromRect([_super_view frame])); NSLog(@"table_width %f", table_width); NSLog(@"width %f", visible_width); @@ -6326,22 +6341,22 @@ - (void) superviewFrameChanged: (NSNotification*)aNotification } else { - CGFloat visible_width = [self convertRect: [_super_view bounds] + CGFloat visible_width = [self convertRect: [_super_view bounds] fromView: _super_view].size.width; CGFloat table_width = 0; if (_numberOfColumns > 0) - { - table_width = - _columnOrigins[_numberOfColumns - 1] + - [[_tableColumns objectAtIndex: _numberOfColumns - 1] width]; - } - + { + table_width = + _columnOrigins[_numberOfColumns - 1] + + [[_tableColumns objectAtIndex: _numberOfColumns - 1] width]; + } + /* NSLog(@"columnOrigins[0] %f", _columnOrigins[0]); - NSLog(@"superview.bounds %@", + NSLog(@"superview.bounds %@", NSStringFromRect([_super_view bounds])); - NSLog(@"superview.frame %@", + NSLog(@"superview.frame %@", NSStringFromRect([_super_view frame])); NSLog(@"table_width %f", table_width); NSLog(@"width %f", visible_width); @@ -6387,7 +6402,7 @@ - (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL)isLocal } - (void) setDraggingSourceOperationMask: (NSDragOperation)mask - forLocal: (BOOL)isLocal + forLocal: (BOOL)isLocal { if (isLocal) { @@ -6450,7 +6465,7 @@ - (void) _drawDropIndicator } else { - newRect = NSMakeRect([self visibleRect].origin.x, + newRect = NSMakeRect([self visibleRect].origin.x, currentDropRow * _rowHeight - 1, [self visibleRect].size.width, 3); @@ -6461,7 +6476,7 @@ - (void) _drawDropIndicator else { newRect = [self frameOfCellAtColumn: 0 - row: currentDropRow]; + row: currentDropRow]; newRect.origin.x = _bounds.origin.x; newRect.size.width = _bounds.size.width + 2; newRect.origin.x -= _intercellSpacing.height / 2; @@ -6489,9 +6504,9 @@ - (void) _drawDropIndicator [self unlockFocus]; } -/* This is a crude method of scrolling the view while dragging so the user can -drag to any cell even if it's not visible. Unfortunately we don't receive -events when the drag is outside the view, so the pointer must still be in the +/* This is a crude method of scrolling the view while dragging so the user can +drag to any cell even if it's not visible. Unfortunately we don't receive +events when the drag is outside the view, so the pointer must still be in the view to drag. */ - (void) _scrollRowAtPointToVisible: (NSPoint)p { @@ -6501,13 +6516,13 @@ - (void) _scrollRowAtPointToVisible: (NSPoint)p { currentRow = [self rowAtPoint: p] - 1; if (currentRow > 0) - [self scrollRowToVisible: currentRow]; + [self scrollRowToVisible: currentRow]; } else if (p.y > NSMaxY([self visibleRect]) - 3) { currentRow = [self rowAtPoint: p] + 1; if (currentRow < _numberOfRows) - [self scrollRowToVisible: currentRow]; + [self scrollRowToVisible: currentRow]; } } @@ -6517,13 +6532,13 @@ - (NSInteger) _computedRowAtPoint: (NSPoint)p } - (void) _setDropOperationAndRow: (NSInteger)row - usingPositionInRow: (NSInteger)positionInRow - atPoint: (NSPoint)p + usingPositionInRow: (NSInteger)positionInRow + atPoint: (NSPoint)p { NSParameterAssert(row > -1); - BOOL isPositionInsideMiddleQuartersOfRow = + BOOL isPositionInsideMiddleQuartersOfRow = (positionInRow > _rowHeight / 4 && positionInRow <= (3 * _rowHeight) / 4); - BOOL isDropOn = (row > _numberOfRows || isPositionInsideMiddleQuartersOfRow); + BOOL isDropOn = (row > _numberOfRows || isPositionInsideMiddleQuartersOfRow); [self setDropRow: (isDropOn ? [self _computedRowAtPoint: p] : row) dropOperation: (isDropOn ? NSTableViewDropOn : NSTableViewDropAbove)]; @@ -6560,28 +6575,28 @@ - (NSDragOperation) draggingUpdated: (id ) sender /* Remember current drop target */ currentDragOperation = dragOperation; lastQuarterPosition = quarterPosition; - - /* The user can retarget this default drop using -setDropRow:dropOperation: + + /* The user can retarget this default drop using -setDropRow:dropOperation: in -tableView:validateDrop:proposedRow:proposedDropOperation:. */ - [self _setDropOperationAndRow: row - usingPositionInRow: positionInRow - atPoint: p]; + [self _setDropOperationAndRow: row + usingPositionInRow: positionInRow + atPoint: p]; - if ([_dataSource respondsToSelector: + if ([_dataSource respondsToSelector: @selector(tableView:validateDrop:proposedRow:proposedDropOperation:)]) { currentDragOperation = [_dataSource tableView: self - validateDrop: sender - proposedRow: currentDropRow - proposedDropOperation: currentDropOperation]; + validateDrop: sender + proposedRow: currentDropRow + proposedDropOperation: currentDropOperation]; } - - /* -setDropRow:dropOperation: can changes both currentDropRow and - currentDropOperation. Whether we have to redraw the drop indicator depends + + /* -setDropRow:dropOperation: can changes both currentDropRow and + currentDropOperation. Whether we have to redraw the drop indicator depends on this change. */ if (currentDropRow != oldDropRow || currentDropOperation != oldDropOperation) { - [self _drawDropIndicator]; + [self _drawDropIndicator]; oldDropRow = (currentDropRow > -1 ? currentDropRow : _numberOfRows); oldDropOperation = currentDropOperation; } @@ -6614,30 +6629,30 @@ - (void) concludeDragOperation:(id )sender { } -- (BOOL) canDragRowsWithIndexes: (NSIndexSet *)indexes - atPoint: (NSPoint)point +- (BOOL) canDragRowsWithIndexes: (NSIndexSet *)indexes + atPoint: (NSPoint)point { return YES; } -/* - * sorting +/* + * sorting */ -/** Sets the sort descriptors used to sort the rows and delegates the sorting +/** Sets the sort descriptors used to sort the rows and delegates the sorting to -tableView:didChangeSortDescriptors or -outlineView:didChangeSortDescriptors: in NSOutlineView. -The delegate methods can retrieve the new sort descriptors with +The delegate methods can retrieve the new sort descriptors with -sortDescriptors and override them with -setSortDescriptors:.
-The first object in the new sort descriptor array is the sort descriptor +The first object in the new sort descriptor array is the sort descriptor prototype returned by the table column whose header was the last clicked. See -[NSTableColumn sortDescriptorPrototype]. - -This method is called automatically when you click on a table column header, + +This method is called automatically when you click on a table column header, so you shouldn't need to call it usually. -Take note the sort descriptors are encoded by the keyed archiving (rarely used +Take note the sort descriptors are encoded by the keyed archiving (rarely used since neither IB or Gorm support to set these directly). */ - (void) setSortDescriptors: (NSArray *)sortDescriptors { @@ -6651,8 +6666,8 @@ - (void) setSortDescriptors: (NSArray *)sortDescriptors } else { - /* _sortDescriptors must remain immutable since -sortDescriptors doesn't - return a defensive copy */ + /* _sortDescriptors must remain immutable since -sortDescriptors doesn't + return a defensive copy */ newSortDescriptors = [NSArray arrayWithArray: sortDescriptors]; } @@ -6667,7 +6682,7 @@ - (void) setSortDescriptors: (NSArray *)sortDescriptors RELEASE(oldSortDescriptors); } -/** Returns the current sort descriptors, usually updated every time a click +/** Returns the current sort descriptors, usually updated every time a click happens on a table column header. By default, returns an empty array. @@ -6707,7 +6722,7 @@ - (void) _postColumnDidMoveNotificationWithOldIndex: (NSInteger) oldIndex { [nc postNotificationName: NSTableViewColumnDidMoveNotification object: self - userInfo: [NSDictionary + userInfo: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger: newIndex], @"NSNewColumn", @@ -6718,20 +6733,20 @@ - (void) _postColumnDidMoveNotificationWithOldIndex: (NSInteger) oldIndex - (void) _postColumnDidResizeNotificationWithOldWidth: (float) oldWidth { - [nc postNotificationName: + [nc postNotificationName: NSTableViewColumnDidResizeNotification object: self - userInfo: [NSDictionary + userInfo: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat: oldWidth], - @"NSOldWidth", + @"NSOldWidth", nil]]; } - (BOOL) _shouldSelectTableColumn: (NSTableColumn *)tableColumn { - if ([_delegate respondsToSelector: - @selector (tableView:shouldSelectTableColumn:)] == YES) + if ([_delegate respondsToSelector: + @selector (tableView:shouldSelectTableColumn:)] == YES) { if ([_delegate tableView: self shouldSelectTableColumn: tableColumn] == NO) { @@ -6744,35 +6759,35 @@ - (BOOL) _shouldSelectTableColumn: (NSTableColumn *)tableColumn - (BOOL) _shouldSelectRow: (NSInteger)rowIndex { - if ([_delegate respondsToSelector: - @selector (tableView:shouldSelectRow:)] == YES) + if ([_delegate respondsToSelector: + @selector (tableView:shouldSelectRow:)] == YES) { if ([_delegate tableView: self shouldSelectRow: rowIndex] == NO) { return NO; } } - + return YES; } - (BOOL) _shouldSelectionChange { - if ([_delegate respondsToSelector: - @selector (selectionShouldChangeInTableView:)] == YES) + if ([_delegate respondsToSelector: + @selector (selectionShouldChangeInTableView:)] == YES) { if ([_delegate selectionShouldChangeInTableView: self] == NO) { return NO; } } - + return YES; } - (void) _didChangeSortDescriptors: (NSArray *)oldSortDescriptors { - if ([_dataSource + if ([_dataSource respondsToSelector: @selector(tableView:sortDescriptorsDidChange:)]) { [_dataSource tableView: self sortDescriptorsDidChange: oldSortDescriptors]; @@ -6781,7 +6796,7 @@ - (void) _didChangeSortDescriptors: (NSArray *)oldSortDescriptors - (void) _didClickTableColumn: (NSTableColumn *)tc { - if ([_delegate + if ([_delegate respondsToSelector: @selector(tableView:didClickTableColumn:)]) { @@ -6793,7 +6808,7 @@ - (void) _didClickTableColumn: (NSTableColumn *)tc - (BOOL) _shouldEditTableColumn: (NSTableColumn *)tableColumn row: (NSInteger) rowIndex { - if ([_delegate respondsToSelector: + if ([_delegate respondsToSelector: @selector(tableView:shouldEditTableColumn:row:)]) { return [_delegate tableView: self shouldEditTableColumn: tableColumn @@ -6804,16 +6819,16 @@ - (BOOL) _shouldEditTableColumn: (NSTableColumn *)tableColumn } - (BOOL) _isEditableColumn: (NSInteger) columnIndex - row: (NSInteger) rowIndex + row: (NSInteger) rowIndex { NSTableColumn *tableColumn = [_tableColumns objectAtIndex: columnIndex]; return [tableColumn isEditable] && [self _shouldEditTableColumn: tableColumn - row: rowIndex]; + row: rowIndex]; } - (BOOL) _isCellSelectableColumn: (NSInteger) columnIndex - row: (NSInteger) rowIndex + row: (NSInteger) rowIndex { if (![self _isEditableColumn: columnIndex row: rowIndex]) { @@ -6848,11 +6863,11 @@ - (void) _willDisplayCell: (NSCell*)cell { if (_del_responds) { - [_delegate tableView: self - willDisplayCell: cell - forTableColumn: tb + [_delegate tableView: self + willDisplayCell: cell + forTableColumn: tb row: index]; - } + } } - (id) _objectValueForTableColumn: (NSTableColumn *)tb @@ -6861,12 +6876,12 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb id result = nil; GSKeyValueBinding *theBinding; - theBinding = [GSKeyValueBinding getBinding: NSValueBinding + theBinding = [GSKeyValueBinding getBinding: NSValueBinding forObject: tb]; if (theBinding != nil) { - return [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; } else if ([_dataSource respondsToSelector: @selector(tableView:objectValueForTableColumn:row:)]) @@ -6875,26 +6890,38 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb objectValueForTableColumn: tb row: index]; } - + return result; } - + - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index { GSKeyValueBinding *theBinding; - theBinding = [GSKeyValueBinding getBinding: NSValueBinding + theBinding = [GSKeyValueBinding getBinding: NSValueBinding forObject: tb]; if (theBinding != nil) { - NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding - forObject: tb]; - id obj = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - NSString *keyPath = [info objectForKey: NSObservedKeyPathKey]; - [obj setValue: value forKeyPath: keyPath]; + NSArray *items = [[theBinding observedObject] arrangedObjects]; + if (items != nil) + { + NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding + forObject: tb]; + if (info != nil) + { + NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; + NSUInteger location = [ikp rangeOfString: @"."].location; + NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); + id obj = [items objectAtIndex: index]; + + if (obj != nil) + { + [obj setValue: value forKeyPath: keyPath]; + } + } + } } else if ([_dataSource respondsToSelector: @selector(tableView:setObjectValue:forTableColumn:row:)]) @@ -6907,7 +6934,7 @@ - (void) _setObjectValue: (id)value } /* Quasi private method called on self from -noteNumberOfRowsChanged - * implemented in NSTableView and subclasses + * implemented in NSTableView and subclasses * by default returns the DataSource's -numberOfRowsInTableView: */ - (NSInteger) _numRows @@ -6916,8 +6943,8 @@ - (NSInteger) _numRows // If we have content binding the data source is used only // like a delegate - theBinding = [GSKeyValueBinding getBinding: NSContentBinding - forObject: self]; + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; if (theBinding != nil) { return [(NSArray *)[theBinding destinationValue] count]; @@ -6933,11 +6960,11 @@ - (NSInteger) _numRows GSKeyValueBinding *theBinding; theBinding = [GSKeyValueBinding getBinding: NSValueBinding - forObject: tb]; + forObject: tb]; if (theBinding != nil) - { - return [[theBinding destinationValue] count]; - } + { + return [[theBinding destinationValue] count]; + } // FIXME return 0; @@ -6951,9 +6978,9 @@ - (NSInteger) _numRows - (BOOL) _isDraggingSource { return [_dataSource respondsToSelector: - @selector(tableView:writeRows:toPasteboard:)] + @selector(tableView:writeRows:toPasteboard:)] || [_dataSource respondsToSelector: - @selector(tableView:writeRowsWithIndexes:toPasteboard:)]; + @selector(tableView:writeRowsWithIndexes:toPasteboard:)]; } - (BOOL) _writeRows: (NSIndexSet *)rows @@ -6963,24 +6990,24 @@ - (BOOL) _writeRows: (NSIndexSet *)rows @selector(tableView:writeRowsWithIndexes:toPasteboard:)] == YES) { return [_dataSource tableView: self - writeRowsWithIndexes: rows - toPasteboard: pboard]; + writeRowsWithIndexes: rows + toPasteboard: pboard]; } else if ([_dataSource respondsToSelector: - @selector(tableView:writeRows:toPasteboard:)] == YES) + @selector(tableView:writeRows:toPasteboard:)] == YES) { NSArray *rowArray; rowArray = [self _indexSetToArray: rows]; return [_dataSource tableView: self - writeRows: rowArray - toPasteboard: pboard]; + writeRows: rowArray + toPasteboard: pboard]; } return NO; } - (void) reloadDataForRowIndexes: (NSIndexSet*)rowIndexes - columnIndexes: (NSIndexSet*)columnIndexes + columnIndexes: (NSIndexSet*)columnIndexes { [self reloadData]; } @@ -6995,11 +7022,11 @@ - (void) endUpdates if (_beginEndUpdates > 0) { if (--_beginEndUpdates == 0) - { - // Process batched inserts/removes.... - // Just reload table for now until we get inserts/removes working... - [self reloadData]; - } + { + // Process batched inserts/removes.... + // Just reload table for now until we get inserts/removes working... + [self reloadData]; + } } } @@ -7010,12 +7037,12 @@ - (NSInteger) columnForView: (NSView*)view } - (void) insertRowsAtIndexes: (NSIndexSet*)indexes - withAnimation: (NSTableViewAnimationOptions)animationOptions + withAnimation: (NSTableViewAnimationOptions)animationOptions { } - (void) removeRowsAtIndexes: (NSIndexSet*)indexes - withAnimation: (NSTableViewAnimationOptions)animationOptions + withAnimation: (NSTableViewAnimationOptions)animationOptions { } @@ -7048,7 +7075,7 @@ - (NSView *) makeViewWithIdentifier: (NSUserInterfaceItemIdentifier)identifier o { NSEnumerator *en = [tlo objectEnumerator]; id v = nil; - + while ((v = [en nextObject]) != nil) { if ([v isKindOfClass: [NSView class]]) @@ -7064,7 +7091,7 @@ - (NSView *) makeViewWithIdentifier: (NSUserInterfaceItemIdentifier)identifier o } } } - + return view; } @@ -7072,7 +7099,7 @@ - (id) _prototypeCellViewFromTableColumn: (NSTableColumn *)tb { NSArray *protoCellViews = [tb _prototypeCellViews]; id view = nil; - + // it seems there is always one prototype... if ([protoCellViews count] > 0) { @@ -7090,7 +7117,7 @@ - (NSTableRowView *) rowViewAtRow: (NSInteger)row makeIfNecessary: (BOOL)flag if (_viewBased == YES) { NSNumber *aRow = [NSNumber numberWithInteger: row]; - + rv = [_rowViews objectForKey: aRow]; if (rv == nil) { @@ -7103,14 +7130,14 @@ - (NSTableRowView *) rowViewAtRow: (NSInteger)row makeIfNecessary: (BOOL)flag if (rv == nil) { rv = AUTORELEASE([[NSTableRowView alloc] init]); - } + } } - + [_rowViews setObject: rv forKey: aRow]; } } - + return rv; } @@ -7122,7 +7149,7 @@ - (NSView *) viewAtColumn: (NSInteger)column row: (NSInteger)row makeIfNecessary NSView *view = [self _renderedViewForPath: path]; NSRect drawingRect = [self frameOfCellAtColumn: column row: row]; - + // If the view has been stored use it, if not // then grab it. if (view == nil @@ -7138,7 +7165,7 @@ - (NSView *) viewAtColumn: (NSInteger)column row: (NSInteger)row makeIfNecessary { view = [self _prototypeCellViewFromTableColumn: tb]; } - + [self _setRenderedView: view forPath: path]; } @@ -7193,7 +7220,7 @@ - (void) _setSelectingColumns: (BOOL)flag { if (flag == _selectingColumns) return; - + if (flag == NO) { [self _unselectAllColumns]; @@ -7210,15 +7237,15 @@ - (NSArray *) _indexSetToArray: (NSIndexSet*)indexSet { NSMutableArray *array = [NSMutableArray array]; NSUInteger index = [indexSet firstIndex]; - + while (index != NSNotFound) { NSNumber *num = [NSNumber numberWithUnsignedInteger: index]; - [array addObject: num]; + [array addObject: num]; index = [indexSet indexGreaterThanIndex: index]; - } - + } + return array; } @@ -7233,7 +7260,7 @@ - (BOOL) _selectRow: (NSInteger)rowIndex { return NO; } - + [self setNeedsDisplayInRect: [self rectOfRow: rowIndex]]; [_selectedRows addIndex: rowIndex]; _selectedRow = rowIndex; @@ -7246,7 +7273,7 @@ - (BOOL) _selectUnselectedRow: (NSInteger)rowIndex { return NO; } - + [self setNeedsDisplayInRect: [self rectOfRow: rowIndex]]; [_selectedRows addIndex: rowIndex]; _selectedRow = rowIndex; @@ -7275,7 +7302,7 @@ - (void) _unselectAllRows { /* Compute rect to redraw to clear the old row selection */ NSUInteger row = [_selectedRows firstIndex]; - + while (row != NSNotFound) { [self setNeedsDisplayInRect: [self rectOfRow: row]]; @@ -7294,19 +7321,19 @@ - (void) _unselectAllColumns { /* Compute rect to redraw to clear the old column selection */ NSUInteger column = [_selectedColumns firstIndex]; - + while (column != NSNotFound) { [self setNeedsDisplayInRect: [self rectOfColumn: column]]; if (_headerView) - { - [_headerView setNeedsDisplayInRect: + { + [_headerView setNeedsDisplayInRect: [_headerView headerRectOfColumn: column]]; } column = [_selectedColumns indexGreaterThanIndex: column]; - } + } [_selectedColumns removeAllIndexes]; - _selectedColumn = -1; + _selectedColumn = -1; } - (void) setValue: (id)anObject forKey: (NSString*)aKey @@ -7320,29 +7347,29 @@ - (void) setValue: (id)anObject forKey: (NSString*)aKey else if ([aKey isEqual: NSSelectionIndexesBinding]) { if (_selectingColumns) - { - if (nil == anObject) - { - [self _unselectAllColumns]; - } - else - { - return [self selectColumnIndexes: anObject - byExtendingSelection: NO]; - } - } + { + if (nil == anObject) + { + [self _unselectAllColumns]; + } + else + { + return [self selectColumnIndexes: anObject + byExtendingSelection: NO]; + } + } else - { - if (nil == anObject) - { - [self _unselectAllRows]; - } - else - { - return [self selectRowIndexes: anObject - byExtendingSelection: NO]; - } - } + { + if (nil == anObject) + { + [self _unselectAllRows]; + } + else + { + return [self selectRowIndexes: anObject + byExtendingSelection: NO]; + } + } } else { @@ -7359,13 +7386,13 @@ - (id) valueForKey: (NSString*)aKey else if ([aKey isEqual: NSSelectionIndexesBinding]) { if (_selectingColumns) - { - return [self selectedColumnIndexes]; - } + { + return [self selectedColumnIndexes]; + } else - { - return [self selectedRowIndexes]; - } + { + return [self selectedRowIndexes]; + } } else { From 90b3913a1ffa6bb290df05b4ab583653979f5a3c Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 12 Jul 2024 06:22:56 -0400 Subject: [PATCH 28/72] Add implementation for methods that add nodes at a given indexPath or set of indexPaths --- Headers/AppKit/NSTreeController.h | 10 ++--- Source/GSControllerTreeProxy.m | 12 ++++++ Source/NSTreeController.m | 66 ++++++++++++++++++++----------- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index 137258ee8c..0568d9f9db 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -165,14 +165,14 @@ APPKIT_EXPORT_CLASS * If the tree controller is in "object" mode, then newObject is called * to add a new node. */ -- (void) addChild: (id)sender; +- (IBAction) addChild: (id)sender; /** * Adds a new objeect to the tree usin the newObject method. * If the tree controller is in "object" mode, then newObject is called * to add a new node. */ -- (void) add: (id)sender; +- (IBAction) add: (id)sender; /** * Inserts a child using the newObject method. This method @@ -180,7 +180,7 @@ APPKIT_EXPORT_CLASS * If the tree controller is in "object" mode, then newObject is called * to add a new node. */ -- (void) insertChild: (id)sender; +- (IBAction) insertChild: (id)sender; /** * Inserts and object using the newObject method at the specified indexPath. @@ -217,7 +217,7 @@ APPKIT_EXPORT_CLASS * This method will only function if the tree controller is in * "object" mode. */ -- (void) insert: (id)sender; +- (IBAction) insert: (id)sender; /** * Causes the controller to re-sort and rearrange the objects. This method @@ -262,7 +262,7 @@ APPKIT_EXPORT_CLASS * Remove the currently selected object. This method will only * function if the tree controller is in "object" mode. */ -- (void) remove: (id)sender; +- (IBAction) remove: (id)sender; /** * Sets the flag to always use multiple values marker. diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index f5f20dc7d1..59ccbb818f 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -57,6 +57,7 @@ - (NSUInteger) count return [children count]; } +// This is here so that when the path is specified as "children" it responds - (NSMutableArray *) children { NSDictionary *ro = [self representedObject]; @@ -75,5 +76,16 @@ - (void) setValue: (id)value forKey: @"value"]; } +// These return the value in the cases where the parent class method is called... +- (NSArray *) childNodes +{ + return [self children]; +} + +- (NSArray *) mutableChildNodes +{ + return [self children]; +} + @end diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 18d9247c03..c162b63d7c 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -32,6 +32,7 @@ #import #import #import +#import #import #import #import @@ -237,7 +238,7 @@ - (NSString*) leafKeyPath return _leafKeyPath; } -- (void) add: (id)sender +- (IBAction) add: (id)sender { if ([self canAddChild] && [self countKeyPath] == nil) @@ -258,28 +259,13 @@ - (void) add: (id)sender } } -- (void) addChild: (id)obj +- (IBAction) addChild: (id)sender { - if ([self canAddChild] - && [self countKeyPath] == nil) - { - id newObject = [self newObject]; - - if (newObject != nil) - { - NSMutableArray *newContent = [NSMutableArray arrayWithArray: [self content]]; - GSControllerTreeProxy *node = [[GSControllerTreeProxy alloc] - initWithRepresentedObject: newObject - withController: self]; - - [newContent addObject: node]; - [self setContent: newContent]; - RELEASE(newObject); - } - } + // FIXME + [self add: sender]; } -- (void) remove: (id)sender +- (IBAction) remove: (id)sender { if ([self canRemove] && [self countKeyPath] == nil) @@ -288,24 +274,56 @@ - (void) remove: (id)sender } } -- (void) insertChild: (id)sender +- (IBAction) insertChild: (id)sender { // FIXME + [self add: sender]; } - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)indexPath { - // FIXME + NSUInteger length = [indexPath length]; + NSUInteger pos = 0; + NSMutableArray *children = [_arranged_objects mutableChildNodes]; + NSUInteger lastIndex = 0; + + for (pos = 0; pos < length - 1; pos++) + { + NSUInteger i = [indexPath indexAtPosition: pos]; + id node = [children objectAtIndex: i]; + + children = [node valueForKeyPath: _childrenKeyPath]; + } + + lastIndex = [indexPath indexAtPosition: length - 1]; + [children insertObject: object atIndex: lastIndex]; } - (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*)indexPaths { - // FIXME + if ([objects count] != [indexPaths count]) + { + return; + } + else + { + NSUInteger i = 0; + + FOR_IN(id, object, objects) + { + NSIndexPath *indexPath = [indexPaths objectAtIndex: i]; + + [self insertObject: object atArrangedObjectIndexPath: indexPath]; + i++; + } + END_FOR_IN(objects); + } } -- (void) insert: (id)sender +- (IBAction) insert: (id)sender { // FIXME + [self add: sender]; } - (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath From e6f86a5a9ea228bcf550722f95d32d70c810fafc Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 12 Jul 2024 06:35:31 -0400 Subject: [PATCH 29/72] Add NSNibDeclarations.h to the header to correct compilation error --- Headers/AppKit/NSTreeController.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index 0568d9f9db..762ab9d6cf 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -34,6 +34,7 @@ #if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST) #import +#import @class NSString; @class NSArray; From 9b481f10b37bb014ccb1cfc8310c9bef0400208d Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 12 Jul 2024 08:11:23 -0400 Subject: [PATCH 30/72] Correctly refresh after adding an item at an index path --- Source/NSTreeController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index c162b63d7c..610aae465c 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -297,6 +297,7 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)index lastIndex = [indexPath indexAtPosition: length - 1]; [children insertObject: object atIndex: lastIndex]; + [self rearrangeObjects]; } - (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*)indexPaths From 4ddce03859ee056ead232240e8ab7d4161302182 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 12 Jul 2024 08:49:52 -0400 Subject: [PATCH 31/72] Add removeObjects... methods --- Source/NSTreeController.m | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 610aae465c..35ffb7b556 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -90,7 +90,7 @@ - (id) init self = [self initWithContent: array]; RELEASE(array); - + return self; } @@ -159,7 +159,7 @@ - (BOOL) setSelectionIndexPath: (NSIndexPath *)indexPath { [_selection_index_paths addObject: indexPath]; } - + return f; } @@ -172,7 +172,7 @@ - (BOOL) setSelectionIndexPaths: (NSArray *)indexPaths NSMutableArray *mutable_index_paths = [NSMutableArray arrayWithArray: indexPaths]; ASSIGN(_selection_index_paths, mutable_index_paths); } - + return f; } @@ -196,7 +196,7 @@ - (void) rearrangeObjects _arranged_objects = [[GSControllerTreeProxy alloc] initWithRepresentedObject: dictionary withController: self]; } - + [self didChangeValueForKey: @"arrangedObjects"]; } @@ -286,12 +286,12 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)index NSUInteger pos = 0; NSMutableArray *children = [_arranged_objects mutableChildNodes]; NSUInteger lastIndex = 0; - + for (pos = 0; pos < length - 1; pos++) { NSUInteger i = [indexPath indexAtPosition: pos]; id node = [children objectAtIndex: i]; - + children = [node valueForKeyPath: _childrenKeyPath]; } @@ -309,7 +309,7 @@ - (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*) else { NSUInteger i = 0; - + FOR_IN(id, object, objects) { NSIndexPath *indexPath = [indexPaths objectAtIndex: i]; @@ -329,12 +329,31 @@ - (IBAction) insert: (id)sender - (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath { - // FIXME + NSUInteger length = [indexPath length]; + NSUInteger pos = 0; + NSMutableArray *children = [_arranged_objects mutableChildNodes]; + NSUInteger lastIndex = 0; + + for (pos = 0; pos < length - 1; pos++) + { + NSUInteger i = [indexPath indexAtPosition: pos]; + id node = [children objectAtIndex: i]; + + children = [node valueForKeyPath: _childrenKeyPath]; + } + + lastIndex = [indexPath indexAtPosition: length - 1]; + [children removeObjectAtIndex: lastIndex]; + [self rearrangeObjects]; } - (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths { - // FIXME + FOR_IN(NSIndexPath*, indexPath, indexPaths) + { + [self removeObjectAtArrangedObjectIndexPath: indexPath]; + } + END_FOR_IN(indexPaths); } - (void) removeSelectionIndexPaths: (NSArray*)indexPaths @@ -579,7 +598,7 @@ - (id) copyWithZone: (NSZone*)zone [copy setPreservesSelection: [self preservesSelection]]; [copy setSelectsInsertedObjects: [self selectsInsertedObjects]]; } - + return copy; } From 2ba9843537b3263851a472fded88cfd2727bffe1 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 12 Jul 2024 09:42:26 -0400 Subject: [PATCH 32/72] Add removeSelectionIndexPaths: --- Source/NSTreeController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 35ffb7b556..ff167380e1 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -359,6 +359,7 @@ - (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths - (void) removeSelectionIndexPaths: (NSArray*)indexPaths { // FIXME + [self removeObjectsAtArrangedObjectIndexPaths: indexPaths]; } - (void) setAlwaysUsesMultipleValuesMarker: (BOOL)flag From f253f3fa0e5ae9bd14ea09847fa41019a2d2a376 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 12 Jul 2024 10:39:47 -0400 Subject: [PATCH 33/72] Formatting fixes.. add space before * in return value --- Headers/AppKit/NSTreeController.h | 22 +++++++------- Source/NSTreeController.m | 48 +++++++++++++++---------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Headers/AppKit/NSTreeController.h b/Headers/AppKit/NSTreeController.h index 762ab9d6cf..e381666355 100644 --- a/Headers/AppKit/NSTreeController.h +++ b/Headers/AppKit/NSTreeController.h @@ -119,28 +119,28 @@ APPKIT_EXPORT_CLASS /** * An NSArray containing all selected objects. */ -- (NSArray*) selectedObjects; +- (NSArray *) selectedObjects; /** * The index path of the first selected object. */ -- (NSIndexPath*) selectionIndexPath; +- (NSIndexPath *) selectionIndexPath; /** * An array containing all of the currently selected objects. */ -- (NSArray*) selectionIndexPaths; +- (NSArray *) selectionIndexPaths; /** * An array containing sort descriptors used to arrange content. */ -- (NSArray*) sortDescriptors; +- (NSArray *) sortDescriptors; /** * Key path for children of the node. This key must be key value * compliant. */ -- (NSString*) childrenKeyPath; +- (NSString *) childrenKeyPath; /** * Key value path for the flag which gives the count for the children @@ -151,7 +151,7 @@ APPKIT_EXPORT_CLASS * childKeyPath. The mode the tree controller is in when this is * not specified is called "object" mode. */ -- (NSString*) countKeyPath; +- (NSString *) countKeyPath; /** * Key value path for the flag which determins that this is a leaf. @@ -159,7 +159,7 @@ APPKIT_EXPORT_CLASS * key path is optional as it can be determined by the children * returned by the childrenKeyPath. */ -- (NSString*) leafKeyPath; +- (NSString *) leafKeyPath; /** * Adds a child to the current selection using the newObject method. @@ -313,17 +313,17 @@ APPKIT_EXPORT_CLASS /** * children key path for the given NSTreeNode. */ -- (NSString*) childrenKeyPathForNode: (NSTreeNode *)node; +- (NSString *) childrenKeyPathForNode: (NSTreeNode *)node; /** * count key path for the given NSTreeNode. */ -- (NSString*) countKeyPathForNode: (NSTreeNode *)node; +- (NSString *) countKeyPathForNode: (NSTreeNode *)node; /** * leaf key path for the given NSTreeNode. */ -- (NSString*) leafKeyPathForNode: (NSTreeNode *)node; +- (NSString *) leafKeyPathForNode: (NSTreeNode *)node; /** * Moves node to given indexPath @@ -344,7 +344,7 @@ APPKIT_EXPORT_CLASS /** * Array containing all selected nodes */ -- (NSArray*) selectedNodes; +- (NSArray *) selectedNodes; #endif // 10_5 @end diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index ff167380e1..ab01243afd 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -206,34 +206,34 @@ - (NSArray *) selectedObjects return [super selectedObjects]; } -- (NSIndexPath*) selectionIndexPath +- (NSIndexPath *) selectionIndexPath { // FIXME return nil; } -- (NSArray*) selectionIndexPaths +- (NSArray *) selectionIndexPaths { // FIXME return nil; } -- (NSArray*) sortDescriptors +- (NSArray *) sortDescriptors { return _sortDescriptors; } -- (NSString*) childrenKeyPath +- (NSString *) childrenKeyPath { return _childrenKeyPath; } -- (NSString*) countKeyPath +- (NSString *) countKeyPath { return _countKeyPath;; } -- (NSString*) leafKeyPath +- (NSString *) leafKeyPath { return _leafKeyPath; } @@ -280,7 +280,7 @@ - (IBAction) insertChild: (id)sender [self add: sender]; } -- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)indexPath +- (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)indexPath { NSUInteger length = [indexPath length]; NSUInteger pos = 0; @@ -300,7 +300,7 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath*)index [self rearrangeObjects]; } -- (void) insertObjects: (NSArray*)objects atArrangedObjectIndexPaths: (NSArray*)indexPaths +- (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths { if ([objects count] != [indexPaths count]) { @@ -327,7 +327,7 @@ - (IBAction) insert: (id)sender [self add: sender]; } -- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath +- (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath *)indexPath { NSUInteger length = [indexPath length]; NSUInteger pos = 0; @@ -347,7 +347,7 @@ - (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath*)indexPath [self rearrangeObjects]; } -- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths +- (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray *)indexPaths { FOR_IN(NSIndexPath*, indexPath, indexPaths) { @@ -356,7 +356,7 @@ - (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray*)indexPaths END_FOR_IN(indexPaths); } -- (void) removeSelectionIndexPaths: (NSArray*)indexPaths +- (void) removeSelectionIndexPaths: (NSArray *)indexPaths { // FIXME [self removeObjectsAtArrangedObjectIndexPaths: indexPaths]; @@ -372,7 +372,7 @@ - (void) setAvoidsEmptySelection: (BOOL)flag _avoidsEmptySelection = flag; } -- (void) setChildrenKeyPath: (NSString*)path +- (void) setChildrenKeyPath: (NSString *)path { ASSIGN(_childrenKeyPath, path); } @@ -383,12 +383,12 @@ - (void) setContent: (id)content [self rearrangeObjects]; } -- (void) setCountKeyPath: (NSString*)path +- (void) setCountKeyPath: (NSString *)path { ASSIGN(_countKeyPath, path); } -- (void) setLeafKeyPath: (NSString*)key +- (void) setLeafKeyPath: (NSString *)key { ASSIGN(_leafKeyPath, key); } @@ -403,37 +403,37 @@ - (void) setSelectsInsertedObjects: (BOOL)flag _selectsInsertedObjects = flag; } -- (void) setSortDescriptors: (NSArray*)descriptors +- (void) setSortDescriptors: (NSArray *)descriptors { ASSIGN(_sortDescriptors, descriptors); } -- (NSString*) childrenKeyPathForNode: (NSTreeNode*)node +- (NSString *) childrenKeyPathForNode: (NSTreeNode *)node { return _childrenKeyPath; } -- (NSString*) countKeyPathForNode: (NSTreeNode*)node +- (NSString *) countKeyPathForNode: (NSTreeNode *)node { return _countKeyPath; } -- (NSString*) leafKeyPathForNode: (NSTreeNode*)node +- (NSString *) leafKeyPathForNode: (NSTreeNode *)node { return _leafKeyPath; } -- (void) moveNode: (NSTreeNode*)node toIndexPath: (NSIndexPath*)indexPath +- (void) moveNode: (NSTreeNode *)node toIndexPath: (NSIndexPath *)indexPath { // FIXME } -- (void) moveNodes: (NSArray*)nodes toIndexPath: (NSIndexPath*)startingIndexPath +- (void) moveNodes: (NSArray *)nodes toIndexPath: (NSIndexPath *)startingIndexPath { // FIXME } -- (NSArray*) selectedNodes +- (NSArray *) selectedNodes { // FIXME return nil; @@ -468,7 +468,7 @@ - (void) bind: (NSString *)binding } } -- (id) initWithCoder: (NSCoder*)coder +- (id) initWithCoder: (NSCoder *)coder { self = [super initWithCoder: coder]; @@ -541,7 +541,7 @@ - (id) initWithCoder: (NSCoder*)coder return self; } -- (void) encodeWithCoder: (NSCoder*)coder +- (void) encodeWithCoder: (NSCoder *)coder { [super encodeWithCoder: coder]; if ([coder allowsKeyedCoding]) @@ -585,7 +585,7 @@ - (void) encodeWithCoder: (NSCoder*)coder } } -- (id) copyWithZone: (NSZone*)zone +- (id) copyWithZone: (NSZone *)zone { id copy = [[NSTreeController allocWithZone: zone] initWithContent: [self content]]; From 45c0368602350f067b0ebf15460dff93ab6c562f Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 14 Jul 2024 15:14:07 -0400 Subject: [PATCH 34/72] Add code to get the value of the NSEditableBinding --- Source/NSOutlineView.m | 15 +++++++++++++++ Source/NSTableView.m | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 1298bb32b5..a1842439c6 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1841,6 +1841,21 @@ - (void) _willDisplayCell: (NSCell*)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index { + GSKeyValueBinding *theBinding; + + theBinding = [GSKeyValueBinding getBinding: NSEditableBinding + forObject: tb]; + if (theBinding != nil) + { + id result = nil; + BOOL flag = NO; + + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + flag = [result boolValue]; + [cell setEditable: flag]; + } + if (_del_responds) { id item = [self itemAtRow: index]; diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 38b868a00a..24c76c8103 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6861,6 +6861,21 @@ - (void) _willDisplayCell: (NSCell*)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index { + GSKeyValueBinding *theBinding; + + theBinding = [GSKeyValueBinding getBinding: NSEditableBinding + forObject: tb]; + if (theBinding != nil) + { + id result = nil; + BOOL flag = NO; + + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + flag = [result boolValue]; + [cell setEditable: flag]; + } + if (_del_responds) { [_delegate tableView: self From ca4fe0e07848963bf9c12e3a8d64994da75fd148 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 14 Jul 2024 15:40:47 -0400 Subject: [PATCH 35/72] Add code to get the value of the NSEnabledBinding --- Source/NSOutlineView.m | 15 ++++++++++++++- Source/NSTableView.m | 13 +++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index a1842439c6..cb88195135 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1855,7 +1855,20 @@ - (void) _willDisplayCell: (NSCell*)cell flag = [result boolValue]; [cell setEditable: flag]; } - + + theBinding = [GSKeyValueBinding getBinding: NSEnabledBinding + forObject: tb]; + if (theBinding != nil) + { + id result = nil; + BOOL flag = NO; + + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + flag = [result boolValue]; + [cell setEnabled: flag]; + } + if (_del_responds) { id item = [self itemAtRow: index]; diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 24c76c8103..91bb6f8457 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6875,6 +6875,19 @@ - (void) _willDisplayCell: (NSCell*)cell flag = [result boolValue]; [cell setEditable: flag]; } + + theBinding = [GSKeyValueBinding getBinding: NSEnabledBinding + forObject: tb]; + if (theBinding != nil) + { + id result = nil; + BOOL flag = NO; + + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + flag = [result boolValue]; + [cell setEnabled: flag]; + } if (_del_responds) { From 766a358fb7a0c084df0f0e72aa6bf34935002a37 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 14 Jul 2024 16:00:18 -0400 Subject: [PATCH 36/72] Move code to handle enabled/editable bindings to a common method in the parent class --- Source/NSOutlineView.m | 35 +++++++---------------------------- Source/NSTableView.m | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index cb88195135..8bf2a6adec 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -145,6 +145,9 @@ - (void) _setRenderedView: (NSView *)view forPath: (NSIndexPath *)path; - (id) _prototypeCellViewFromTableColumn: (NSTableColumn *)tb; - (void) _drawCellViewRow: (NSInteger)rowIndex clipRect: (NSRect)clipRect; +- (void) _applyBindingsToCell: (NSCell *)cell + forTableColumn: (NSTableColumn *)tb + row: (NSInteger)index; @end @implementation NSOutlineView @@ -1837,37 +1840,13 @@ - (BOOL) _shouldEditTableColumn: (NSTableColumn *)tableColumn return YES; } -- (void) _willDisplayCell: (NSCell*)cell +- (void) _willDisplayCell: (NSCell *)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index { - GSKeyValueBinding *theBinding; - - theBinding = [GSKeyValueBinding getBinding: NSEditableBinding - forObject: tb]; - if (theBinding != nil) - { - id result = nil; - BOOL flag = NO; - - result = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - flag = [result boolValue]; - [cell setEditable: flag]; - } - - theBinding = [GSKeyValueBinding getBinding: NSEnabledBinding - forObject: tb]; - if (theBinding != nil) - { - id result = nil; - BOOL flag = NO; - - result = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - flag = [result boolValue]; - [cell setEnabled: flag]; - } + [self _applyBindingsToCell: cell + forTableColumn: tb + row: index]; if (_del_responds) { diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 91bb6f8457..c9be64d2b9 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6857,9 +6857,9 @@ - (BOOL) _isCellEditableColumn: (NSInteger) columnIndex } } -- (void) _willDisplayCell: (NSCell*)cell - forTableColumn: (NSTableColumn *)tb - row: (NSInteger)index +- (void) _applyBindingsToCell: (NSCell *)cell + forTableColumn: (NSTableColumn *)tb + row: (NSInteger)index { GSKeyValueBinding *theBinding; @@ -6887,7 +6887,16 @@ - (void) _willDisplayCell: (NSCell*)cell objectAtIndex: index]; flag = [result boolValue]; [cell setEnabled: flag]; - } + } +} + +- (void) _willDisplayCell: (NSCell*)cell + forTableColumn: (NSTableColumn *)tb + row: (NSInteger)index +{ + [self _applyBindingsToCell: cell + forTableColumn: tb + row: index]; if (_del_responds) { From 74e0c1950362774fb66b25659445081da6603888 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Mon, 15 Jul 2024 06:50:20 -0400 Subject: [PATCH 37/72] Add bindigns to NSTableColumn and handle font bindings in _applyBindingsToCell:... method --- Source/NSTableColumn.m | 3 +++ Source/NSTableView.m | 49 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Source/NSTableColumn.m b/Source/NSTableColumn.m index fd358b1f33..018489d97a 100644 --- a/Source/NSTableColumn.m +++ b/Source/NSTableColumn.m @@ -98,6 +98,9 @@ + (void) initialize [self exposeBinding: NSValueBinding]; [self exposeBinding: NSEnabledBinding]; [self exposeBinding: NSEditableBinding]; + [self exposeBinding: NSFontBinding]; + [self exposeBinding: NSFontNameBinding]; + [self exposeBinding: NSFontSizeBinding]; } } diff --git a/Source/NSTableView.m b/Source/NSTableView.m index c9be64d2b9..af51575996 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6861,8 +6861,9 @@ - (void) _applyBindingsToCell: (NSCell *)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index { - GSKeyValueBinding *theBinding; - + GSKeyValueBinding *theBinding = nil; + NSFont *font = nil; + theBinding = [GSKeyValueBinding getBinding: NSEditableBinding forObject: tb]; if (theBinding != nil) @@ -6887,7 +6888,49 @@ - (void) _applyBindingsToCell: (NSCell *)cell objectAtIndex: index]; flag = [result boolValue]; [cell setEnabled: flag]; - } + } + + // Font bindings... + theBinding = [GSKeyValueBinding getBinding: NSFontBinding + forObject: tb]; + if (theBinding != nil) + { + font = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + } + else + { + NSString *fontName = nil; + CGFloat fontSize = 0.0; + + theBinding = [GSKeyValueBinding getBinding: NSFontNameBinding + forObject: tb]; + if (theBinding != nil) + { + fontName = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + } + + if (fontName != nil) + { + theBinding = [GSKeyValueBinding getBinding: NSFontSizeBinding + forObject: tb]; + if (theBinding != nil) + { + id num = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + fontSize = [num doubleValue]; + } + + font = [NSFont fontWithName: fontName + size: fontSize]; + } + } + + if (font != nil) + { + [cell setFont: font]; + } } - (void) _willDisplayCell: (NSCell*)cell From c39095cd617e1db5de3b43ffaaacc4fa154b1e95 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Mon, 15 Jul 2024 07:06:49 -0400 Subject: [PATCH 38/72] Add comment/documentation --- Source/NSTableView.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/NSTableView.m b/Source/NSTableView.m index af51575996..e6a1bf63f7 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6890,7 +6890,11 @@ - (void) _applyBindingsToCell: (NSCell *)cell [cell setEnabled: flag]; } - // Font bindings... + /* Font bindings... According to Apple documentation, if the + * font binding is available, then name, size, and other + * font related bindings are ignored. Otherwise they are + * used + */ theBinding = [GSKeyValueBinding getBinding: NSFontBinding forObject: tb]; if (theBinding != nil) From c68c4595843618aeb2591548720ad2b774a15b80 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 16 Jul 2024 18:03:30 -0400 Subject: [PATCH 39/72] Add code to set selection indexes on the controller --- Source/NSArrayController.m | 1 + Source/NSTableView.m | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Source/NSArrayController.m b/Source/NSArrayController.m index 80e3aaaf40..b1dfce2f25 100644 --- a/Source/NSArrayController.m +++ b/Source/NSArrayController.m @@ -147,6 +147,7 @@ + (void) initialize if (self == [NSArrayController class]) { [self exposeBinding: NSContentArrayBinding]; + [self exposeBinding: NSSelectionIndexesBinding]; [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; } diff --git a/Source/NSTableView.m b/Source/NSTableView.m index e6a1bf63f7..f9e03c80ed 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6713,6 +6713,26 @@ - (void) _postSelectionIsChangingNotification - (void) _postSelectionDidChangeNotification { + NSTableColumn *tb = [_tableColumns objectAtIndex: 0]; + GSKeyValueBinding *theBinding; + + theBinding = [GSKeyValueBinding getBinding: NSValueBinding + forObject: tb]; + + // If there is a binding, send the indexes back + if (theBinding != nil) + { + id observedObject = [theBinding observedObject]; + + // Set the selection indexes on the controller... + theBinding = [GSKeyValueBinding getBinding: NSSelectionIndexesBinding + forObject: observedObject]; + if (theBinding != nil) + { + [theBinding reverseSetValue: _selectedRows]; + } + } + [nc postNotificationName: NSTableViewSelectionDidChangeNotification object: self]; } From cd41f301a887a8d0db947a5c0118931cdc456cf6 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 19 Jul 2024 08:04:13 -0400 Subject: [PATCH 40/72] Add selection logic for computing indexPaths --- Headers/AppKit/NSKeyValueBinding.h | 1 + Headers/AppKit/NSOutlineView.h | 2 +- Source/NSOutlineView.m | 67 +++++++++++++++++++++++++++--- Source/NSTreeController.m | 1 + Source/externs.m | 1 + 5 files changed, 66 insertions(+), 6 deletions(-) diff --git a/Headers/AppKit/NSKeyValueBinding.h b/Headers/AppKit/NSKeyValueBinding.h index 4563357246..445867e06a 100644 --- a/Headers/AppKit/NSKeyValueBinding.h +++ b/Headers/AppKit/NSKeyValueBinding.h @@ -126,6 +126,7 @@ APPKIT_EXPORT NSString *NSSelectedObjectBinding; APPKIT_EXPORT NSString *NSSelectedTagBinding; APPKIT_EXPORT NSString *NSSelectedValueBinding; APPKIT_EXPORT NSString *NSSelectionIndexesBinding; +APPKIT_EXPORT NSString *NSSelectionIndexPathsBinding; APPKIT_EXPORT NSString *NSSortDescriptorsBinding; APPKIT_EXPORT NSString *NSTextColorBinding; APPKIT_EXPORT NSString *NSTitleBinding; diff --git a/Headers/AppKit/NSOutlineView.h b/Headers/AppKit/NSOutlineView.h index 7dc6ec15f7..81fbcd7700 100644 --- a/Headers/AppKit/NSOutlineView.h +++ b/Headers/AppKit/NSOutlineView.h @@ -44,7 +44,7 @@ APPKIT_EXPORT_CLASS NSMapTable *_itemDict; NSMutableArray *_items; NSMutableArray *_expandedItems; - NSMutableArray *_selectedItems; /* No longer in use */ + NSMutableArray *_selectedIndexPaths; NSMapTable *_levelOfItems; BOOL _autoResizesOutlineColumn; BOOL _indentationMarkerFollowsCell; diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 8bf2a6adec..7bee06e860 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -62,6 +62,7 @@ #import "AppKit/NSText.h" #import "AppKit/NSTextFieldCell.h" #import "AppKit/NSTreeController.h" +#import "AppKit/NSTreeNode.h" #import "AppKit/NSWindow.h" #import "GNUstepGUI/GSTheme.h" @@ -211,6 +212,7 @@ - (void) dealloc RELEASE(_items); RELEASE(_expandedItems); + RELEASE(_selectedIndexPaths); NSFreeMapTable(_itemDict); NSFreeMapTable(_levelOfItems); @@ -1716,6 +1718,38 @@ before the actual editing is started (otherwise you easily end up @end /* implementation of NSOutlineView */ @implementation NSOutlineView (NotificationRequestMethods) + +- (void) _indexPathsFromSelectedRows +{ + NSUInteger index = [_selectedRows firstIndex]; + NSUInteger count = 0; + + [_selectedIndexPaths removeAllObjects]; + while (index != NSNotFound) + { + id item = [_items objectAtIndex: index]; + + if ([item respondsToSelector: @selector(indexPath)]) + { + NSIndexPath *path = [item indexPath]; + + [_selectedIndexPaths addObject: path]; + count++; + } + + index = [_selectedRows indexGreaterThanIndex: index]; + } + + // According to tests and observation, if none of the + // objects respond to indexPath, then we need return the + // root object + if (count == 0) + { + NSIndexPath *path = [NSIndexPath indexPathWithIndex: 0]; + [_selectedIndexPaths addObject: path]; + } +} + /* * (NotificationRequestMethods) */ @@ -1725,12 +1759,34 @@ - (void) _postSelectionIsChangingNotification NSOutlineViewSelectionIsChangingNotification object: self]; } + - (void) _postSelectionDidChangeNotification { - [nc postNotificationName: - NSOutlineViewSelectionDidChangeNotification - object: self]; + NSTableColumn *tb = [_tableColumns objectAtIndex: 0]; + GSKeyValueBinding *theBinding; + + theBinding = [GSKeyValueBinding getBinding: NSValueBinding + forObject: tb]; + + // If there is a binding, send the indexes back + if (theBinding != nil) + { + id observedObject = [theBinding observedObject]; + + // Set the selection indexes on the controller... + theBinding = [GSKeyValueBinding getBinding: NSSelectionIndexPathsBinding + forObject: observedObject]; + if (theBinding != nil) + { + [self _indexPathsFromSelectedRows]; + [theBinding reverseSetValue: _selectedIndexPaths]; + } + } + + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; } + - (void) _postColumnDidMoveNotificationWithOldIndex: (NSInteger) oldIndex newIndex: (NSInteger) newIndex { @@ -1776,7 +1832,7 @@ - (BOOL) _shouldSelectTableColumn: (NSTableColumn *)tableColumn - (BOOL) _shouldSelectRow: (NSInteger)rowIndex { id item = [self itemAtRow: rowIndex]; - + if ([_delegate respondsToSelector: @selector (outlineView:shouldSelectItem:)] == YES) { @@ -1973,6 +2029,7 @@ - (void) _initOutlineDefaults 64); _items = [[NSMutableArray alloc] init]; _expandedItems = [[NSMutableArray alloc] init]; + _selectedIndexPaths = [[NSMutableArray alloc] init]; _levelOfItems = NSCreateMapTable(keyCallBacks, NSObjectMapValueCallBacks, 64); @@ -2103,7 +2160,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem * _NSControllerTreeProxy. The equivalent of that class in GNUstep is * GSControllerTreeProxy. */ - children = [node children]; + children = [node mutableChildNodes]; num = [children count]; } else diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index ab01243afd..00e241cbdf 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -53,6 +53,7 @@ + (void) initialize { [self exposeBinding: NSContentArrayBinding]; [self exposeBinding: NSContentBinding]; + [self exposeBinding: NSSelectionIndexPathsBinding]; [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; } diff --git a/Source/externs.m b/Source/externs.m index c4464829f7..fa0cc71b6e 100644 --- a/Source/externs.m +++ b/Source/externs.m @@ -711,6 +711,7 @@ APPKIT_DECLARE NSString *NSSelectedTagBinding = @"selectedTag"; APPKIT_DECLARE NSString *NSSelectedValueBinding = @"selectedValue"; APPKIT_DECLARE NSString *NSSelectionIndexesBinding = @"selectionIndexes"; +APPKIT_DECLARE NSString *NSSelectionIndexPathsBinding = @"selectionIndexPaths"; APPKIT_DECLARE NSString *NSSortDescriptorsBinding = @"sortDescriptors"; APPKIT_DECLARE NSString *NSTextColorBinding = @"textColor"; APPKIT_DECLARE NSString *NSTitleBinding = @"title"; From dc78b112910d710fbfb7a545d527efcb63b28e3c Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 19 Jul 2024 10:14:18 -0400 Subject: [PATCH 41/72] Add code to handle insertion methods that are based on selection --- Source/NSTreeController.m | 121 +++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 00e241cbdf..acb2dc7cd7 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -201,22 +201,51 @@ - (void) rearrangeObjects [self didChangeValueForKey: @"arrangedObjects"]; } +- (id) _objectAtIndexPath: (NSIndexPath *)indexPath +{ + NSUInteger length = [indexPath length]; + NSUInteger pos = 0; + NSMutableArray *children = [_arranged_objects mutableChildNodes]; + NSUInteger lastIndex = 0; + id obj = nil; + + for (pos = 0; pos < length - 1; pos++) + { + NSUInteger i = [indexPath indexAtPosition: pos]; + id node = [children objectAtIndex: i]; + + children = [node valueForKeyPath: _childrenKeyPath]; + } + + lastIndex = [indexPath indexAtPosition: length - 1]; + obj = [children objectAtIndex: lastIndex]; + + return obj; +} + - (NSArray *) selectedObjects { - // FIXME - return [super selectedObjects]; + NSMutableArray *selectedObjects = [NSMutableArray array]; + NSEnumerator *en = [_selection_index_paths objectEnumerator]; + NSIndexPath *path = nil; + + while ((path = [en nextObject]) != nil) + { + id obj = [self _objectAtIndexPath: path]; + [selectedObjects addObject: obj]; + } + + return selectedObjects; } - (NSIndexPath *) selectionIndexPath { - // FIXME - return nil; + return [_selection_index_paths objectAtIndex: 0]; } - (NSArray *) selectionIndexPaths { - // FIXME - return nil; + return _selection_index_paths; } - (NSArray *) sortDescriptors @@ -254,6 +283,7 @@ - (IBAction) add: (id)sender withController: self]; [newContent addObject: node]; + [self setContent: newContent]; RELEASE(newObject); } @@ -262,8 +292,10 @@ - (IBAction) add: (id)sender - (IBAction) addChild: (id)sender { - // FIXME - [self add: sender]; + NSIndexPath *p = [self selectionIndexPath]; + id newObject = [self newObject]; + + [self insertObject: newObject atArrangedObjectIndexPath: p]; } - (IBAction) remove: (id)sender @@ -277,55 +309,61 @@ - (IBAction) remove: (id)sender - (IBAction) insertChild: (id)sender { - // FIXME - [self add: sender]; + [self addChild: sender]; } - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)indexPath { - NSUInteger length = [indexPath length]; - NSUInteger pos = 0; - NSMutableArray *children = [_arranged_objects mutableChildNodes]; - NSUInteger lastIndex = 0; - - for (pos = 0; pos < length - 1; pos++) + if ([self canAddChild] + && [self countKeyPath] == nil) { - NSUInteger i = [indexPath indexAtPosition: pos]; - id node = [children objectAtIndex: i]; - - children = [node valueForKeyPath: _childrenKeyPath]; + NSUInteger length = [indexPath length]; + NSUInteger pos = 0; + NSMutableArray *children = [_arranged_objects mutableChildNodes]; + NSUInteger lastIndex = 0; + + for (pos = 0; pos < length - 1; pos++) + { + NSUInteger i = [indexPath indexAtPosition: pos]; + id node = [children objectAtIndex: i]; + + children = [node valueForKeyPath: _childrenKeyPath]; + } + + lastIndex = [indexPath indexAtPosition: length - 1]; + [children insertObject: object atIndex: lastIndex]; + [self rearrangeObjects]; } - - lastIndex = [indexPath indexAtPosition: length - 1]; - [children insertObject: object atIndex: lastIndex]; - [self rearrangeObjects]; } - (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray *)indexPaths { - if ([objects count] != [indexPaths count]) - { - return; - } - else - { - NSUInteger i = 0; - - FOR_IN(id, object, objects) + if ([self canAddChild] + && [self countKeyPath] == nil) + { + if ([objects count] != [indexPaths count]) { - NSIndexPath *indexPath = [indexPaths objectAtIndex: i]; - - [self insertObject: object atArrangedObjectIndexPath: indexPath]; - i++; + return; + } + else + { + NSUInteger i = 0; + + FOR_IN(id, object, objects) + { + NSIndexPath *indexPath = [indexPaths objectAtIndex: i]; + + [self insertObject: object atArrangedObjectIndexPath: indexPath]; + i++; + } + END_FOR_IN(objects); } - END_FOR_IN(objects); } } - (IBAction) insert: (id)sender { - // FIXME - [self add: sender]; + [self addChild: sender]; } - (void) removeObjectAtArrangedObjectIndexPath: (NSIndexPath *)indexPath @@ -359,7 +397,6 @@ - (void) removeObjectsAtArrangedObjectIndexPaths: (NSArray *)indexPaths - (void) removeSelectionIndexPaths: (NSArray *)indexPaths { - // FIXME [self removeObjectsAtArrangedObjectIndexPaths: indexPaths]; } @@ -437,7 +474,7 @@ - (void) moveNodes: (NSArray *)nodes toIndexPath: (NSIndexPath *)startingIndexPa - (NSArray *) selectedNodes { // FIXME - return nil; + return [self selectedObjects]; } From d22d839b0c0cf015e907ace6b431aa5a15d6ad30 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 19 Jul 2024 11:12:24 -0400 Subject: [PATCH 42/72] Correct minor formatting issues --- Source/NSOutlineView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 7bee06e860..d360309a98 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1832,7 +1832,7 @@ - (BOOL) _shouldSelectTableColumn: (NSTableColumn *)tableColumn - (BOOL) _shouldSelectRow: (NSInteger)rowIndex { id item = [self itemAtRow: rowIndex]; - + if ([_delegate respondsToSelector: @selector (outlineView:shouldSelectItem:)] == YES) { From f55d937ab24b911acb7dfda4e4ce9576aeaf50f0 Mon Sep 17 00:00:00 2001 From: Gregory Casamento Date: Sat, 20 Jul 2024 12:27:00 -0400 Subject: [PATCH 43/72] Update NSTreeController.m Remove NSLog from initWithContent: --- Source/NSTreeController.m | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index acb2dc7cd7..5cfa774fd2 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -76,7 +76,6 @@ - (void) _initDefaults - (id) initWithContent: (id)content { - NSLog(@"Content = %@", content); if ((self = [super initWithContent: content]) != nil) { [self _initDefaults]; From 3d59afd2c9f473ae0d18f77290e1b4cc2db55898 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 17:37:04 -0400 Subject: [PATCH 44/72] Improvements, per discussion with @fredkiefer --- Source/NSKeyValueBinding.m | 7 +++---- Source/NSOutlineView.m | 1 - Source/NSTableView.m | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index 2c93b64961..15a2615a5c 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -192,12 +192,11 @@ + (GSKeyValueBinding *) getBinding: (NSString *)binding if (!objectTable) return nil; - // NSLog(@"+++ called with %@, %@", binding, anObject); - // [self _printObjectTable]; - + NSDebugLog(@"+++ called with %@, %@", binding, anObject); [bindingLock lock]; bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)anObject); - // NSLog(@"+++ Bindings found for %@ => %@", anObject, bindings); + + NSDebugLog(@"+++ Bindings found for %@ => %@", anObject, bindings); if (bindings != nil) { theBinding = (GSKeyValueBinding*)[bindings objectForKey: binding]; diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index d360309a98..21b2fe03a2 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -2278,7 +2278,6 @@ - (void)_openItem: (id)item id object; id sitem = (item == nil) ? (id)[NSNull null] : (id)item; - // NSLog(@"openItem: %@", item); // open the item... if (item != nil) { diff --git a/Source/NSTableView.m b/Source/NSTableView.m index f9e03c80ed..1a31800bdb 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -3310,7 +3310,6 @@ - (void) validateEditing NSString *string; id newObjectValue = nil; BOOL validatedOK = YES; - GSKeyValueBinding *theBinding = nil; // Avoid potential recursive sequences... _isValidating = YES; @@ -3327,6 +3326,7 @@ - (void) validateEditing errorDescription: &error] == YES) { NSTableColumn *tb; + GSKeyValueBinding *theBinding = nil; [_editedCell setObjectValue: newObjectValue]; tb = [_tableColumns objectAtIndex: _editedColumn]; @@ -3366,6 +3366,7 @@ - (void) validateEditing if (validatedOK) { NSTableColumn *tb; + GSKeyValueBinding *theBinding = nil; [_editedCell setStringValue: string]; tb = [_tableColumns objectAtIndex: _editedColumn]; From abfc782a6cfa85f8691524951db9f66ee077358f Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 18:29:00 -0400 Subject: [PATCH 45/72] Move check for dataSource or binding into NSOutlineView before calling method to draw the row per discussion with @fredkiefer --- Source/GSThemeDrawing.m | 9 --------- Source/NSOutlineView.m | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/GSThemeDrawing.m b/Source/GSThemeDrawing.m index 64d4e4bd9b..e8d08a5185 100644 --- a/Source/GSThemeDrawing.m +++ b/Source/GSThemeDrawing.m @@ -3534,15 +3534,6 @@ - (void) drawOutlineViewRow: (NSInteger)rowIndex NSInteger i; id dataSource = [outlineView dataSource]; NSTableColumn *outlineTableColumn = [outlineView outlineTableColumn]; - GSKeyValueBinding *theBinding = nil; - - theBinding = [GSKeyValueBinding getBinding: NSContentBinding - forObject: outlineView]; - - if (dataSource == nil && theBinding == nil) - { - return; - } /* Using columnAtPoint: here would make it called twice per row per drawn rect - so we avoid it and do it natively */ diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 21b2fe03a2..a47f9a9a06 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1032,6 +1032,16 @@ - (void)keyDown: (NSEvent*)event */ - (void) drawRow: (NSInteger)rowIndex clipRect: (NSRect)aRect { + GSKeyValueBinding *theBinding = nil; + + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + + if (_dataSource == nil && theBinding == nil) + { + return; + } + if (_viewBased) { [self _drawCellViewRow: rowIndex From 6f2c542b468e22454bfee313bc2ad0db2cb5aaab Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 18:51:59 -0400 Subject: [PATCH 46/72] Move handling of dictionary creation into GSControllerTreeProxy class, per discussion with @fredkiefer --- Source/GSControllerTreeProxy.h | 5 +++-- Source/GSControllerTreeProxy.m | 14 ++++++++------ Source/NSTreeController.m | 14 ++++++++------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Source/GSControllerTreeProxy.h b/Source/GSControllerTreeProxy.h index 208214295c..149bbe9570 100644 --- a/Source/GSControllerTreeProxy.h +++ b/Source/GSControllerTreeProxy.h @@ -40,8 +40,9 @@ extern "C" { + (NSMutableDictionary *) dictionaryWithChildren: (NSMutableArray *)children; -- (instancetype) initWithRepresentedObject: (id)representedObject - withController: (id)controller; +- (instancetype) initWithContent: (id)content + withController: (id)controller; + - (NSUInteger) count; - (NSMutableArray *) children; diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index 59ccbb818f..8822d56ef4 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -35,19 +35,21 @@ @implementation GSControllerTreeProxy + (NSMutableDictionary *) dictionaryWithChildren: (NSMutableArray *)children { - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject: children - forKey: @"children"]; - return dictionary; + return [NSMutableDictionary dictionaryWithObject: children + forKey: @"children"]; } -- (instancetype) initWithRepresentedObject: (id)representedObject - withController: (id)controller +- (instancetype) initWithContent: (id)content + withController: (id)controller { - self = [super initWithRepresentedObject: representedObject]; + self = [super initWithRepresentedObject: + [GSControllerTreeProxy + dictionaryWithChildren: content]]; if (self != nil) { ASSIGN(_controller, controller); } + return self; } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 5cfa774fd2..533d87c4e0 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -192,9 +192,8 @@ - (void) rearrangeObjects if ([_content isKindOfClass: [NSArray class]]) { - NSMutableDictionary *dictionary = [GSControllerTreeProxy dictionaryWithChildren: _content]; - _arranged_objects = [[GSControllerTreeProxy alloc] initWithRepresentedObject: dictionary - withController: self]; + _arranged_objects = [[GSControllerTreeProxy alloc] initWithContent: _content + withController: self]; } [self didChangeValueForKey: @"arrangedObjects"]; @@ -278,8 +277,8 @@ - (IBAction) add: (id)sender { NSMutableArray *newContent = [NSMutableArray arrayWithArray: [self content]]; GSControllerTreeProxy *node = [[GSControllerTreeProxy alloc] - initWithRepresentedObject: newObject - withController: self]; + initWithContent: newObject + withController: self]; [newContent addObject: node]; @@ -294,7 +293,10 @@ - (IBAction) addChild: (id)sender NSIndexPath *p = [self selectionIndexPath]; id newObject = [self newObject]; - [self insertObject: newObject atArrangedObjectIndexPath: p]; + if (p != nil) + { + [self insertObject: newObject atArrangedObjectIndexPath: p]; + } } - (IBAction) remove: (id)sender From 52eef305b03cfaca6987cd55aeef4c86fb1c4a65 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 19:46:51 -0400 Subject: [PATCH 47/72] Use FOR_IN instead of while loop --- Source/NSTreeController.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 533d87c4e0..63937b6f9c 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -224,15 +224,14 @@ - (id) _objectAtIndexPath: (NSIndexPath *)indexPath - (NSArray *) selectedObjects { NSMutableArray *selectedObjects = [NSMutableArray array]; - NSEnumerator *en = [_selection_index_paths objectEnumerator]; - NSIndexPath *path = nil; - while ((path = [en nextObject]) != nil) + FOR_IN(NSIndexPath*, path, _selection_index_paths) { id obj = [self _objectAtIndexPath: path]; [selectedObjects addObject: obj]; } - + END_FOR_IN(_selection_index_paths); + return selectedObjects; } From ad758041023c3e8cda8283d50a427e5011378d37 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 28 Jul 2024 20:49:18 -0400 Subject: [PATCH 48/72] Remove method, minor cleanup, per discussion with @fredkiefer --- Source/GSControllerTreeProxy.h | 2 -- Source/GSControllerTreeProxy.m | 15 ++++++--------- Source/NSOutlineView.m | 4 ++++ Source/NSTreeController.m | 2 +- Source/NSTreeNode.m | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Source/GSControllerTreeProxy.h b/Source/GSControllerTreeProxy.h index 149bbe9570..a6632f5a80 100644 --- a/Source/GSControllerTreeProxy.h +++ b/Source/GSControllerTreeProxy.h @@ -38,8 +38,6 @@ extern "C" { NSTreeController *_controller; } -+ (NSMutableDictionary *) dictionaryWithChildren: (NSMutableArray *)children; - - (instancetype) initWithContent: (id)content withController: (id)controller; diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index 8822d56ef4..656fdbe985 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -33,18 +33,15 @@ @implementation GSControllerTreeProxy -+ (NSMutableDictionary *) dictionaryWithChildren: (NSMutableArray *)children -{ - return [NSMutableDictionary dictionaryWithObject: children - forKey: @"children"]; -} - - (instancetype) initWithContent: (id)content withController: (id)controller { - self = [super initWithRepresentedObject: - [GSControllerTreeProxy - dictionaryWithChildren: content]]; + NSMutableDictionary *dict = + [NSMutableDictionary dictionaryWithObject: + [NSMutableArray arrayWithArray: children] + forKey: @"children"]; + + self = [super initWithRepresentedObject: dict]; if (self != nil) { ASSIGN(_controller, controller); diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index a47f9a9a06..b6f6414d55 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1789,6 +1789,10 @@ - (void) _postSelectionDidChangeNotification if (theBinding != nil) { [self _indexPathsFromSelectedRows]; + if ([observedObject respondsToSelector: @selector(setSelectionIndexPaths:)]) + { + [observedObject setSelectionIndexPaths: _selectedIndexPaths]; + } [theBinding reverseSetValue: _selectedIndexPaths]; } } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 63937b6f9c..495fead756 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -231,7 +231,7 @@ - (NSArray *) selectedObjects [selectedObjects addObject: obj]; } END_FOR_IN(_selection_index_paths); - + return selectedObjects; } diff --git a/Source/NSTreeNode.m b/Source/NSTreeNode.m index 967eb96d03..822c33a696 100644 --- a/Source/NSTreeNode.m +++ b/Source/NSTreeNode.m @@ -32,7 +32,7 @@ #import #import -#import +#import "AppKit/NSTreeNode.h" @interface NSTreeNode (Private) - (NSMutableArray*) _childNodes; From 8935a2d2daabfc97937a417a2b798e4be4df1e3d Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 28 Jul 2024 21:05:22 -0400 Subject: [PATCH 49/72] Fix compilation issue --- Source/GSControllerTreeProxy.m | 2 +- Source/NSTreeController.m | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index 656fdbe985..a3b714d209 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -38,7 +38,7 @@ - (instancetype) initWithContent: (id)content { NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject: - [NSMutableArray arrayWithArray: children] + [NSMutableArray arrayWithArray: content] forKey: @"children"]; self = [super initWithRepresentedObject: dict]; diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 495fead756..29204465d4 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -332,6 +332,8 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde lastIndex = [indexPath indexAtPosition: length - 1]; [children insertObject: object atIndex: lastIndex]; + + NSLog(@"children = %@, class = %@", children, [children className]); [self rearrangeObjects]; } } From fbee6dce81a5fce652173955d3a1212ac4a77891 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 2 Aug 2024 11:20:58 -0400 Subject: [PATCH 50/72] If no indexPaths are found, return the root --- Source/NSOutlineView.m | 22 +++++++++++++++++++--- Source/NSTreeController.m | 21 +++++++++++++++++++-- Source/NSTreeNode.m | 6 +++++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index b6f6414d55..2ca20e1327 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -151,6 +151,18 @@ - (void) _applyBindingsToCell: (NSCell *)cell row: (NSInteger)index; @end +@interface NSTreeNode (Private_NSOutlineView) +- (void) _setParentNode: (NSTreeNode*)parentNode; +@end + +@implementation NSTreeNode (Private_NSOutlineView) + +- (void) _setParentNode: (NSTreeNode*)parentNode +{ + _parentNode = parentNode; +} + +@end @implementation NSOutlineView // Initialize the class when it is loaded @@ -1755,7 +1767,7 @@ - (void) _indexPathsFromSelectedRows // root object if (count == 0) { - NSIndexPath *path = [NSIndexPath indexPathWithIndex: 0]; + NSIndexPath *path = [NSIndexPath indexPathWithIndex: 1]; [_selectedIndexPaths addObject: path]; } } @@ -1796,7 +1808,7 @@ - (void) _postSelectionDidChangeNotification [theBinding reverseSetValue: _selectedIndexPaths]; } } - + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification object: self]; } @@ -2183,7 +2195,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem * from whether there are children present on a given node. See * the documentation for NSTreeController for more info. */ - if ([self isExpandable: startitem] // leaf == NO + if ([self isExpandable: startitem] && [self isItemExpanded: startitem]) { NSString *childrenKeyPath = [tc childrenKeyPathForNode: startitem]; @@ -2218,6 +2230,10 @@ - (void) _loadDictionaryStartingWith: (id) startitem { id anitem = [children objectAtIndex: i]; + if ([anitem respondsToSelector: @selector(_setParentNode:)]) + { + [anitem _setParentNode: startitem]; + } [anarray addObject: anitem]; [self _loadDictionaryStartingWith: anitem atLevel: level + 1]; diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 29204465d4..f76ea4c3c4 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -34,9 +34,11 @@ #import #import #import +#import #import #import +#import "AppKit/NSOutlineView.h" #import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSTreeController.h" #import "AppKit/NSTreeNode.h" @@ -45,6 +47,21 @@ #import "GSFastEnumeration.h" #import "GSControllerTreeProxy.h" +@interface NSOutlineView (__NSTreeController_private__) + +- (NSArray *) _selectedIndexPaths; + +@end + +@implementation NSOutlineView (__NSTreeController_private__) + +- (NSArray *) _selectedIndexPaths +{ + return _selectedIndexPaths; +} + +@end + @implementation NSTreeController + (void) initialize @@ -101,6 +118,7 @@ - (void) dealloc RELEASE(_leafKeyPath); RELEASE(_sortDescriptors); RELEASE(_arranged_objects); + [super dealloc]; } @@ -321,7 +339,7 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde NSUInteger pos = 0; NSMutableArray *children = [_arranged_objects mutableChildNodes]; NSUInteger lastIndex = 0; - + for (pos = 0; pos < length - 1; pos++) { NSUInteger i = [indexPath indexAtPosition: pos]; @@ -333,7 +351,6 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde lastIndex = [indexPath indexAtPosition: length - 1]; [children insertObject: object atIndex: lastIndex]; - NSLog(@"children = %@, class = %@", children, [children className]); [self rearrangeObjects]; } } diff --git a/Source/NSTreeNode.m b/Source/NSTreeNode.m index 822c33a696..0f14597bf6 100644 --- a/Source/NSTreeNode.m +++ b/Source/NSTreeNode.m @@ -47,6 +47,7 @@ - (NSMutableArray*) _childNodes - (void) _setParentNode: (NSTreeNode*)parentNode { + NSLog(@"parentNode = %@", parentNode); _parentNode = parentNode; } @@ -154,12 +155,13 @@ - (NSTreeNode*) descendantNodeAtIndexPath: (NSIndexPath*)path - (NSIndexPath*) indexPath { + NSLog(@"In %@", NSStringFromSelector(_cmd)); if (_parentNode != nil) { NSIndexPath *path; NSUInteger index; - index = [_parentNode->_childNodes indexOfObject: self]; + index = [[_parentNode childNodes] indexOfObject: self]; path = [_parentNode indexPath]; if (path != nil) { @@ -169,6 +171,8 @@ - (NSIndexPath*) indexPath { return [NSIndexPath indexPathWithIndex: index]; } + + NSLog(@"index = %ld", index); } else { From 1a8f0fa8e65178055eb57997c679ee347d0ec9c6 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 14:31:51 -0400 Subject: [PATCH 51/72] First cut at recursive method to find NSIndexPath for non NSTreeNode items --- Source/NSOutlineView.m | 73 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 2ca20e1327..571c7b5914 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -67,6 +67,7 @@ #import "GNUstepGUI/GSTheme.h" #import "GSBindingHelpers.h" +#import "GSFastEnumeration.h" #import "GSGuiPrivate.h" #include @@ -1741,35 +1742,87 @@ before the actual editing is started (otherwise you easily end up @implementation NSOutlineView (NotificationRequestMethods) +- (void) _buildIndexPathStartingWithItem: (id)startitem + matchingItem: (id)item + intoPath: (NSIndexPath **)path +{ + id sitem = (startitem == nil) ? + (id)[NSNull null] : (id)startitem; + NSArray *children = NSMapGet(_itemDict, sitem); + NSUInteger index = 0; + + // If the item is 0 it is the root, so add it... + if(startitem == nil) + { + *path = [NSIndexPath indexPathWithIndex: 0]; + } + + // Iterate over the children to find the item... + FOR_IN(id, child, children) + { + if (item == child) + { + break; + } + + index++; + [self _buildIndexPathStartingWithItem: child + matchingItem: item + intoPath: path]; + + *path = [*path indexPathByAddingIndex: index]; + } + END_FOR_IN(children); +} + +- (NSIndexPath *) _indexPathForItem: (id)item +{ + NSIndexPath *path = nil; + + [self _buildIndexPathStartingWithItem: nil + matchingItem: item + intoPath: &path]; + + return path; +} + - (void) _indexPathsFromSelectedRows { NSUInteger index = [_selectedRows firstIndex]; - NSUInteger count = 0; - + + // Regenerate the array... [_selectedIndexPaths removeAllObjects]; while (index != NSNotFound) { id item = [_items objectAtIndex: index]; + NSIndexPath *path = nil; if ([item respondsToSelector: @selector(indexPath)]) { - NSIndexPath *path = [item indexPath]; - - [_selectedIndexPaths addObject: path]; - count++; + path = [item indexPath]; + } + else + { + path = [self _indexPathForItem: item]; } + NSLog(@"*** path = %@", path); + [_selectedIndexPaths addObject: path]; + index = [_selectedRows indexGreaterThanIndex: index]; } - + // According to tests and observation, if none of the - // objects respond to indexPath, then we need return the - // root object - if (count == 0) + // objects respond to and we can't get the indices from + // the above calculation, then we need return the + // root object. + /* + if ([_selectedIndexPaths count] == 0) { NSIndexPath *path = [NSIndexPath indexPathWithIndex: 1]; [_selectedIndexPaths addObject: path]; } + */ } /* From 27718ee7943445549580a11f31fb5e6255f8942d Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 15:05:44 -0400 Subject: [PATCH 52/72] Slightly better attempt at getting the index path --- Source/NSOutlineView.m | 57 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 571c7b5914..3483e458d2 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1742,48 +1742,47 @@ before the actual editing is started (otherwise you easily end up @implementation NSOutlineView (NotificationRequestMethods) -- (void) _buildIndexPathStartingWithItem: (id)startitem - matchingItem: (id)item - intoPath: (NSIndexPath **)path +- (NSIndexPath *) _findIndexPathForItem: (id)item + parentItem: (id)pItem { - id sitem = (startitem == nil) ? - (id)[NSNull null] : (id)startitem; - NSArray *children = NSMapGet(_itemDict, sitem); - NSUInteger index = 0; + id parentItem = (pItem == nil) ? (id)[NSNull null] : (id)pItem; + NSArray *children = NSMapGet(_itemDict, parentItem); + NSInteger childCount = [children count]; - // If the item is 0 it is the root, so add it... - if(startitem == nil) + if (item == pItem) { - *path = [NSIndexPath indexPathWithIndex: 0]; + return [NSIndexPath indexPathWithIndex: 0]; } - // Iterate over the children to find the item... - FOR_IN(id, child, children) + for (NSInteger index = 0; index < childCount; index++) { - if (item == child) + id childItem = [children objectAtIndex: index]; + + if (childItem == item) { - break; + return [NSIndexPath indexPathWithIndex: index]; + } + else + { + NSIndexPath *foundPath = [self _findIndexPathForItem: item + parentItem: childItem]; + + if (foundPath != nil) + { + return [foundPath indexPathByAddingIndex: index]; + } } - - index++; - [self _buildIndexPathStartingWithItem: child - matchingItem: item - intoPath: path]; - - *path = [*path indexPathByAddingIndex: index]; } - END_FOR_IN(children); + + return nil; } - (NSIndexPath *) _indexPathForItem: (id)item { - NSIndexPath *path = nil; - - [self _buildIndexPathStartingWithItem: nil - matchingItem: item - intoPath: &path]; - - return path; + id rootItem = [self itemAtRow: 0]; + NSLog(@"rootItem = %@", rootItem); + return [self _findIndexPathForItem: item + parentItem: rootItem]; } - (void) _indexPathsFromSelectedRows From 8059cdadd09310f2410aac7570e83ee73244daea Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 20:05:23 -0400 Subject: [PATCH 53/72] Slight improvements --- Source/NSOutlineView.m | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 3483e458d2..3fd05771f7 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1749,11 +1749,6 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item NSArray *children = NSMapGet(_itemDict, parentItem); NSInteger childCount = [children count]; - if (item == pItem) - { - return [NSIndexPath indexPathWithIndex: 0]; - } - for (NSInteger index = 0; index < childCount; index++) { id childItem = [children objectAtIndex: index]; @@ -1779,8 +1774,7 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item - (NSIndexPath *) _indexPathForItem: (id)item { - id rootItem = [self itemAtRow: 0]; - NSLog(@"rootItem = %@", rootItem); + id rootItem = nil; return [self _findIndexPathForItem: item parentItem: rootItem]; } @@ -1805,7 +1799,6 @@ - (void) _indexPathsFromSelectedRows path = [self _indexPathForItem: item]; } - NSLog(@"*** path = %@", path); [_selectedIndexPaths addObject: path]; index = [_selectedRows indexGreaterThanIndex: index]; From 13f86ebfa901361897c43f923f57ad2a7b8db553 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 20:48:09 -0400 Subject: [PATCH 54/72] Add child index, add category that properly prepends the index to the NSIndexPath --- Source/NSOutlineView.m | 30 +++++++++++++++++++++++++++++- Source/NSTreeController.m | 2 +- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 3fd05771f7..d005851e13 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1740,6 +1740,34 @@ before the actual editing is started (otherwise you easily end up @end /* implementation of NSOutlineView */ +@interface NSIndexPath (__NSOutlineView__Prepend__) + +- (NSIndexPath *) _indexPathByPrependingIndex: (NSUInteger)index; + +@end + +@implementation NSIndexPath (__NSOutlineView__Prepend__) + +- (NSIndexPath *) _indexPathByPrependingIndex: (NSUInteger)index +{ + NSIndexPath *newPath = [NSIndexPath indexPathWithIndex: index]; + NSUInteger length = [self length]; + NSUInteger indexes[length + 1]; + NSUInteger i = 0; + + [self getIndexes: indexes]; + + // Iterate over existing indexes... + for (i = 0; i < length; i++) + { + newPath = [newPath indexPathByAddingIndex: indexes[i]]; + } + + return newPath; +} + +@end + @implementation NSOutlineView (NotificationRequestMethods) - (NSIndexPath *) _findIndexPathForItem: (id)item @@ -1764,7 +1792,7 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item if (foundPath != nil) { - return [foundPath indexPathByAddingIndex: index]; + return [foundPath _indexPathByPrependingIndex: index]; } } } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index f76ea4c3c4..4bb0310be4 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -349,7 +349,7 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde } lastIndex = [indexPath indexAtPosition: length - 1]; - [children insertObject: object atIndex: lastIndex]; + [children insertObject: object atIndex: lastIndex + 1]; [self rearrangeObjects]; } From 300a84c493161c8bb0edfec633879cd02b22d577 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 21:02:33 -0400 Subject: [PATCH 55/72] Improve adding a child, also do whitespace-cleanup --- Source/NSOutlineView.m | 22 +++++++++++----------- Source/NSTreeController.m | 24 ++++++++++++++---------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index d005851e13..f3aa747536 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -222,7 +222,7 @@ - (id) initWithFrame: (NSRect)frame - (void) dealloc { [GSKeyValueBinding unbindAllForObject: self]; - + RELEASE(_items); RELEASE(_expandedItems); RELEASE(_selectedIndexPaths); @@ -804,7 +804,7 @@ - (void) setDataSource: (id)anObject */ _dataSource_editable = YES; } - + /* We do *not* retain the dataSource, it's like a delegate */ _dataSource = anObject; [self tile]; @@ -1047,14 +1047,14 @@ - (void) drawRow: (NSInteger)rowIndex clipRect: (NSRect)aRect { GSKeyValueBinding *theBinding = nil; - theBinding = [GSKeyValueBinding getBinding: NSContentBinding + theBinding = [GSKeyValueBinding getBinding: NSContentBinding forObject: self]; - + if (_dataSource == nil && theBinding == nil) { return; } - + if (_viewBased) { [self _drawCellViewRow: rowIndex @@ -1754,7 +1754,7 @@ - (NSIndexPath *) _indexPathByPrependingIndex: (NSUInteger)index NSUInteger length = [self length]; NSUInteger indexes[length + 1]; NSUInteger i = 0; - + [self getIndexes: indexes]; // Iterate over existing indexes... @@ -1780,7 +1780,7 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item for (NSInteger index = 0; index < childCount; index++) { id childItem = [children objectAtIndex: index]; - + if (childItem == item) { return [NSIndexPath indexPathWithIndex: index]; @@ -1831,7 +1831,7 @@ - (void) _indexPathsFromSelectedRows index = [_selectedRows indexGreaterThanIndex: index]; } - + // According to tests and observation, if none of the // objects respond to and we can't get the indices from // the above calculation, then we need return the @@ -1859,7 +1859,7 @@ - (void) _postSelectionDidChangeNotification { NSTableColumn *tb = [_tableColumns objectAtIndex: 0]; GSKeyValueBinding *theBinding; - + theBinding = [GSKeyValueBinding getBinding: NSValueBinding forObject: tb]; @@ -2103,7 +2103,7 @@ - (void) _setObjectValue: (id)value @selector(outlineView:setObjectValue:forTableColumn:byItem:)]) { id item = [self itemAtRow: index]; - + [_dataSource outlineView: self setObjectValue: value forTableColumn: tb @@ -2286,7 +2286,7 @@ - (void) _loadDictionaryStartingWith: (id) startitem { NSNumber *countValue = [sitem valueForKeyPath: countKeyPath]; num = [countValue integerValue]; - } + } } } } diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 4bb0310be4..60ca67114a 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -224,7 +224,7 @@ - (id) _objectAtIndexPath: (NSIndexPath *)indexPath NSMutableArray *children = [_arranged_objects mutableChildNodes]; NSUInteger lastIndex = 0; id obj = nil; - + for (pos = 0; pos < length - 1; pos++) { NSUInteger i = [indexPath indexAtPosition: pos]; @@ -335,21 +335,25 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde if ([self canAddChild] && [self countKeyPath] == nil) { - NSUInteger length = [indexPath length]; + NSUInteger length = [indexPath length] - 1; NSUInteger pos = 0; NSMutableArray *children = [_arranged_objects mutableChildNodes]; NSUInteger lastIndex = 0; - for (pos = 0; pos < length - 1; pos++) + for (pos = 0; pos < length; pos++) { NSUInteger i = [indexPath indexAtPosition: pos]; id node = [children objectAtIndex: i]; - + children = [node valueForKeyPath: _childrenKeyPath]; } - - lastIndex = [indexPath indexAtPosition: length - 1]; - [children insertObject: object atIndex: lastIndex + 1]; + + lastIndex = [indexPath indexAtPosition: length]; + + id child = [children objectAtIndex: lastIndex]; + + children = [child valueForKeyPath: _childrenKeyPath]; + [children addObject: object]; [self rearrangeObjects]; } @@ -359,7 +363,7 @@ - (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray { if ([self canAddChild] && [self countKeyPath] == nil) - { + { if ([objects count] != [indexPaths count]) { return; @@ -367,11 +371,11 @@ - (void) insertObjects: (NSArray *)objects atArrangedObjectIndexPaths: (NSArray else { NSUInteger i = 0; - + FOR_IN(id, object, objects) { NSIndexPath *indexPath = [indexPaths objectAtIndex: i]; - + [self insertObject: object atArrangedObjectIndexPath: indexPath]; i++; } From a1b9dc546e2ced501aca5415120aaabe271d27fa Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 21:40:04 -0400 Subject: [PATCH 56/72] Eliminate category, move logic for prepend inline --- Source/NSOutlineView.m | 43 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index f3aa747536..9f78561e3b 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1740,34 +1740,6 @@ before the actual editing is started (otherwise you easily end up @end /* implementation of NSOutlineView */ -@interface NSIndexPath (__NSOutlineView__Prepend__) - -- (NSIndexPath *) _indexPathByPrependingIndex: (NSUInteger)index; - -@end - -@implementation NSIndexPath (__NSOutlineView__Prepend__) - -- (NSIndexPath *) _indexPathByPrependingIndex: (NSUInteger)index -{ - NSIndexPath *newPath = [NSIndexPath indexPathWithIndex: index]; - NSUInteger length = [self length]; - NSUInteger indexes[length + 1]; - NSUInteger i = 0; - - [self getIndexes: indexes]; - - // Iterate over existing indexes... - for (i = 0; i < length; i++) - { - newPath = [newPath indexPathByAddingIndex: indexes[i]]; - } - - return newPath; -} - -@end - @implementation NSOutlineView (NotificationRequestMethods) - (NSIndexPath *) _findIndexPathForItem: (id)item @@ -1792,7 +1764,20 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item if (foundPath != nil) { - return [foundPath _indexPathByPrependingIndex: index]; + NSIndexPath *newPath = [NSIndexPath indexPathWithIndex: index]; + NSUInteger length = [foundPath length]; + NSUInteger indexes[length + 1]; + NSUInteger i = 0; + + [foundPath getIndexes: indexes]; + + // Iterate over existing indexes... + for (i = 0; i < length; i++) + { + newPath = [newPath indexPathByAddingIndex: indexes[i]]; + } + + return newPath; } } } From d694efc941371330fff082e484fb8cd528af576b Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 3 Aug 2024 21:44:02 -0400 Subject: [PATCH 57/72] Fix compilation error --- Source/NSOutlineView.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 9f78561e3b..d598ddb682 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1748,8 +1748,9 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item id parentItem = (pItem == nil) ? (id)[NSNull null] : (id)pItem; NSArray *children = NSMapGet(_itemDict, parentItem); NSInteger childCount = [children count]; - - for (NSInteger index = 0; index < childCount; index++) + NSInteger index = 0; + + for (index = 0; index < childCount; index++) { id childItem = [children objectAtIndex: index]; From 21d0bc906ec0606f4f6363cf6c052f9cfb6d650a Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 4 Aug 2024 18:44:01 -0400 Subject: [PATCH 58/72] Fix issues pointed out by @fredkiefer --- ChangeLog | 2 +- Source/GSControllerTreeProxy.m | 2 +- Source/NSControl.m | 1 + Source/NSKeyValueBinding.m | 4 ++-- Source/NSTableView.m | 2 -- Source/NSTreeNode.m | 1 - 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a17774bdb..037f43ae58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,7 @@ * Source/GSControllerTreeProxy.[hm]: Proxy class for NSTreeController, a subclass of NSTreeNode. * Source/GSThemeDrawing.m: Optimize code a bit and - add changes for binfings. + add changes for bindings. * Source/GSXib5KeyedUnarchiver.m: Add support for new keys on NSTreeController. * Source/NSKeyValueBinding.m: Add new methods to diff --git a/Source/GSControllerTreeProxy.m b/Source/GSControllerTreeProxy.m index a3b714d209..715a6525a0 100644 --- a/Source/GSControllerTreeProxy.m +++ b/Source/GSControllerTreeProxy.m @@ -81,7 +81,7 @@ - (NSArray *) childNodes return [self children]; } -- (NSArray *) mutableChildNodes +- (NSMutableArray *) mutableChildNodes { return [self children]; } diff --git a/Source/NSControl.m b/Source/NSControl.m index c9fab9404f..f05f6e3402 100644 --- a/Source/NSControl.m +++ b/Source/NSControl.m @@ -122,6 +122,7 @@ - (id) initWithFrame: (NSRect)frameRect - (void) dealloc { + [GSKeyValueBinding unbindAllForObject: self]; RELEASE(_cell); [super dealloc]; } diff --git a/Source/NSKeyValueBinding.m b/Source/NSKeyValueBinding.m index 15a2615a5c..bfc9d76766 100644 --- a/Source/NSKeyValueBinding.m +++ b/Source/NSKeyValueBinding.m @@ -192,11 +192,11 @@ + (GSKeyValueBinding *) getBinding: (NSString *)binding if (!objectTable) return nil; - NSDebugLog(@"+++ called with %@, %@", binding, anObject); + NSDebugLLog(@"NSBinding", @"+++ called with %@, %@", binding, anObject); [bindingLock lock]; bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)anObject); - NSDebugLog(@"+++ Bindings found for %@ => %@", anObject, bindings); + NSDebugLLog(@"NSBinding", @"+++ Bindings found for %@ => %@", anObject, bindings); if (bindings != nil) { theBinding = (GSKeyValueBinding*)[bindings objectForKey: binding]; diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 1a31800bdb..e6a8e59615 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -2084,8 +2084,6 @@ - (void) dealloc { [self abortEditing]; - [GSKeyValueBinding unbindAllForObject: self]; - RELEASE (_gridColor); RELEASE (_backgroundColor); RELEASE (_tableColumns); diff --git a/Source/NSTreeNode.m b/Source/NSTreeNode.m index 0f14597bf6..9e38d98b53 100644 --- a/Source/NSTreeNode.m +++ b/Source/NSTreeNode.m @@ -47,7 +47,6 @@ - (NSMutableArray*) _childNodes - (void) _setParentNode: (NSTreeNode*)parentNode { - NSLog(@"parentNode = %@", parentNode); _parentNode = parentNode; } From d8c4c1401838c6a3d10b681ecfd73eaf5d73d69c Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 7 Aug 2024 22:55:14 -0400 Subject: [PATCH 59/72] Move _applyBindingsToCell:atRow: to NSTableColumn --- Source/NSOutlineView.m | 11 +++--- Source/NSTableColumn.m | 85 ++++++++++++++++++++++++++++++++++++++-- Source/NSTableView.m | 88 ++---------------------------------------- 3 files changed, 92 insertions(+), 92 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index d598ddb682..83b52accfe 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -147,9 +147,11 @@ - (void) _setRenderedView: (NSView *)view forPath: (NSIndexPath *)path; - (id) _prototypeCellViewFromTableColumn: (NSTableColumn *)tb; - (void) _drawCellViewRow: (NSInteger)rowIndex clipRect: (NSRect)clipRect; +@end + +@interface NSTableColumn (Private) - (void) _applyBindingsToCell: (NSCell *)cell - forTableColumn: (NSTableColumn *)tb - row: (NSInteger)index; + atRow: (NSInteger)index; @end @interface NSTreeNode (Private_NSOutlineView) @@ -1985,9 +1987,8 @@ - (void) _willDisplayCell: (NSCell *)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index { - [self _applyBindingsToCell: cell - forTableColumn: tb - row: index]; + [tb _applyBindingsToCell: cell + atRow: index]; if (_del_responds) { diff --git a/Source/NSTableColumn.m b/Source/NSTableColumn.m index 018489d97a..ca27713324 100644 --- a/Source/NSTableColumn.m +++ b/Source/NSTableColumn.m @@ -654,6 +654,85 @@ - (NSString *) title return [_headerCell stringValue]; } +- (void) _applyBindingsToCell: (NSCell *)cell + atRow: (NSInteger)index +{ + GSKeyValueBinding *theBinding = nil; + NSFont *font = nil; + + theBinding = [GSKeyValueBinding getBinding: NSEditableBinding + forObject: self]; + if (theBinding != nil) + { + id result = nil; + BOOL flag = NO; + + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + flag = [result boolValue]; + [cell setEditable: flag]; + } + + theBinding = [GSKeyValueBinding getBinding: NSEnabledBinding + forObject: self]; + if (theBinding != nil) + { + id result = nil; + BOOL flag = NO; + + result = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + flag = [result boolValue]; + [cell setEnabled: flag]; + } + + /* Font bindings... According to Apple documentation, if the + * font binding is available, then name, size, and other + * font related bindings are ignored. Otherwise they are + * used + */ + theBinding = [GSKeyValueBinding getBinding: NSFontBinding + forObject: self]; + if (theBinding != nil) + { + font = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + } + else + { + NSString *fontName = nil; + CGFloat fontSize = 0.0; + + theBinding = [GSKeyValueBinding getBinding: NSFontNameBinding + forObject: self]; + if (theBinding != nil) + { + fontName = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + } + + if (fontName != nil) + { + theBinding = [GSKeyValueBinding getBinding: NSFontSizeBinding + forObject: self]; + if (theBinding != nil) + { + id num = [(NSArray *)[theBinding destinationValue] + objectAtIndex: index]; + fontSize = [num doubleValue]; + } + + font = [NSFont fontWithName: fontName + size: fontSize]; + } + } + + if (font != nil) + { + [cell setFont: font]; + } +} + - (void) setValue: (id)anObject forKey: (NSString*)aKey { if ([aKey isEqual: NSValueBinding]) @@ -667,7 +746,8 @@ - (void) setValue: (id)anObject forKey: (NSString*)aKey } else if ([aKey isEqual: NSEditableBinding]) { - // FIXME + NSNumber *v = [anObject valueForKey: NSEditableBinding]; + _is_editable = [v boolValue]; } else { @@ -688,8 +768,7 @@ - (id) valueForKey: (NSString*)aKey } else if ([aKey isEqual: NSEditableBinding]) { - // FIXME - return [NSNumber numberWithBool: YES]; + return [NSNumber numberWithBool: _is_editable]; } else { diff --git a/Source/NSTableView.m b/Source/NSTableView.m index e6a8e59615..68cf4b7381 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -183,6 +183,8 @@ - (BOOL) _startDragOperationWithEvent:(NSEvent *)theEvent; @interface NSTableColumn (Private) - (NSArray *) _prototypeCellViews; +- (void) _applyBindingsToCell: (NSCell *)cell + atRow: (NSInteger)index; @end /* @@ -6875,94 +6877,12 @@ - (BOOL) _isCellEditableColumn: (NSInteger) columnIndex return [cell isEditable]; } } - -- (void) _applyBindingsToCell: (NSCell *)cell - forTableColumn: (NSTableColumn *)tb - row: (NSInteger)index -{ - GSKeyValueBinding *theBinding = nil; - NSFont *font = nil; - - theBinding = [GSKeyValueBinding getBinding: NSEditableBinding - forObject: tb]; - if (theBinding != nil) - { - id result = nil; - BOOL flag = NO; - - result = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - flag = [result boolValue]; - [cell setEditable: flag]; - } - - theBinding = [GSKeyValueBinding getBinding: NSEnabledBinding - forObject: tb]; - if (theBinding != nil) - { - id result = nil; - BOOL flag = NO; - - result = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - flag = [result boolValue]; - [cell setEnabled: flag]; - } - - /* Font bindings... According to Apple documentation, if the - * font binding is available, then name, size, and other - * font related bindings are ignored. Otherwise they are - * used - */ - theBinding = [GSKeyValueBinding getBinding: NSFontBinding - forObject: tb]; - if (theBinding != nil) - { - font = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - } - else - { - NSString *fontName = nil; - CGFloat fontSize = 0.0; - - theBinding = [GSKeyValueBinding getBinding: NSFontNameBinding - forObject: tb]; - if (theBinding != nil) - { - fontName = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - } - - if (fontName != nil) - { - theBinding = [GSKeyValueBinding getBinding: NSFontSizeBinding - forObject: tb]; - if (theBinding != nil) - { - id num = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - fontSize = [num doubleValue]; - } - - font = [NSFont fontWithName: fontName - size: fontSize]; - } - } - - if (font != nil) - { - [cell setFont: font]; - } -} - - (void) _willDisplayCell: (NSCell*)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index { - [self _applyBindingsToCell: cell - forTableColumn: tb - row: index]; + [tb _applyBindingsToCell: cell + atRow: index]; if (_del_responds) { From 0ab960e6fc7077f4aa7d15886519a3ad336d6331 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 8 Aug 2024 17:44:04 -0400 Subject: [PATCH 60/72] Remove uneeded outside iteration and get the lastIndex more efficiently, also cleanup NSLog per @fredkiefer --- Source/NSTreeController.m | 8 +------- Source/NSTreeNode.m | 3 --- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 60ca67114a..e470f5309d 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -335,10 +335,9 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde if ([self canAddChild] && [self countKeyPath] == nil) { - NSUInteger length = [indexPath length] - 1; + NSUInteger length = [indexPath length]; NSUInteger pos = 0; NSMutableArray *children = [_arranged_objects mutableChildNodes]; - NSUInteger lastIndex = 0; for (pos = 0; pos < length; pos++) { @@ -348,11 +347,6 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde children = [node valueForKeyPath: _childrenKeyPath]; } - lastIndex = [indexPath indexAtPosition: length]; - - id child = [children objectAtIndex: lastIndex]; - - children = [child valueForKeyPath: _childrenKeyPath]; [children addObject: object]; [self rearrangeObjects]; diff --git a/Source/NSTreeNode.m b/Source/NSTreeNode.m index 9e38d98b53..12f20ff6d3 100644 --- a/Source/NSTreeNode.m +++ b/Source/NSTreeNode.m @@ -154,7 +154,6 @@ - (NSTreeNode*) descendantNodeAtIndexPath: (NSIndexPath*)path - (NSIndexPath*) indexPath { - NSLog(@"In %@", NSStringFromSelector(_cmd)); if (_parentNode != nil) { NSIndexPath *path; @@ -170,8 +169,6 @@ - (NSIndexPath*) indexPath { return [NSIndexPath indexPathWithIndex: index]; } - - NSLog(@"index = %ld", index); } else { From 854af0901e4f5fc733cbbdc5fd006bcef990c35c Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 8 Aug 2024 17:48:16 -0400 Subject: [PATCH 61/72] Cleanup of unused or commented out methods --- Source/NSOutlineView.m | 12 ------ Source/NSTableView.m | 81 --------------------------------------- Source/NSTreeController.m | 15 -------- 3 files changed, 108 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 83b52accfe..db63296d20 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1819,18 +1819,6 @@ - (void) _indexPathsFromSelectedRows index = [_selectedRows indexGreaterThanIndex: index]; } - - // According to tests and observation, if none of the - // objects respond to and we can't get the indices from - // the above calculation, then we need return the - // root object. - /* - if ([_selectedIndexPaths count] == 0) - { - NSIndexPath *path = [NSIndexPath indexPathWithIndex: 1]; - [_selectedIndexPaths addObject: path]; - } - */ } /* diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 68cf4b7381..33a9d86430 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -4849,87 +4849,6 @@ - (void) sizeToFit [self tile]; } -/* -- (void) sizeToFit -{ - NSCell *cell; - NSEnumerator *enumerator; - NSTableColumn *tb; - float table_width; - float width; - float candidate_width; - int row; - - _tilingDisabled = YES; - - // First Step - // Resize Each Column to its Minimum Width - table_width = _bounds.origin.x; - enumerator = [_tableColumns objectEnumerator]; - while ((tb = [enumerator nextObject]) != nil) - { - // Compute min width of column - width = [[tb headerCell] cellSize].width; - for (row = 0; row < _numberOfRows; row++) - { - cell = [self preparedCellAtColumn: [_tableColumns indexOfObject: tb] - row: row]; - [cell setObjectValue: [_dataSource tableView: self - objectValueForTableColumn: tb - row: row]]; - [self _willDisplayCell: cell - forTableColumn: tb - row: row]; - candidate_width = [cell cellSize].width; - - if (_drawsGrid) - candidate_width += 4; - - if (candidate_width > width) - { - width = candidate_width; - } - } - width += _intercellSpacing.width; - [tb setWidth: width]; - // It is necessary to ask the column for the width, since it might have - // been changed by the column to constrain it to a min or max width - table_width += [tb width]; - } - - // Second Step - // If superview (clipview) is bigger than that, divide remaining space - // between all columns - if ((_super_view != nil) && (_numberOfColumns > 0)) - { - float excess_width; - - excess_width = NSMaxX ([self convertRect: [_super_view bounds] - fromView: _super_view]); - excess_width -= table_width; - // Since we resized each column at its minimum width, - // it's useless to try shrinking more: we can't - if (excess_width <= 0) - { - _tilingDisabled = NO; - [self tile]; - NSLog(@"exiting sizeToFit"); - return; - } - excess_width = excess_width / _numberOfColumns; - - enumerator = [_tableColumns objectEnumerator]; - while ((tb = [enumerator nextObject]) != nil) - { - [tb setWidth: ([tb width] + excess_width)]; - } - } - - _tilingDisabled = NO; - [self tile]; - NSLog(@"exiting sizeToFit"); -} -*/ - (void) noteNumberOfRowsChanged { diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index e470f5309d..23e65a66e5 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -47,21 +47,6 @@ #import "GSFastEnumeration.h" #import "GSControllerTreeProxy.h" -@interface NSOutlineView (__NSTreeController_private__) - -- (NSArray *) _selectedIndexPaths; - -@end - -@implementation NSOutlineView (__NSTreeController_private__) - -- (NSArray *) _selectedIndexPaths -{ - return _selectedIndexPaths; -} - -@end - @implementation NSTreeController + (void) initialize From 5d9e49a2ff8a9bf6291926a74b6208332eaebabd Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 8 Aug 2024 18:20:00 -0400 Subject: [PATCH 62/72] Remove both instances where we get properties from the binding where it is not needed during the loading process, per discussion with @fredkiefer --- Source/NSTableView.m | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 33a9d86430..86b978520c 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -3326,16 +3326,11 @@ - (void) validateEditing errorDescription: &error] == YES) { NSTableColumn *tb; - GSKeyValueBinding *theBinding = nil; [_editedCell setObjectValue: newObjectValue]; tb = [_tableColumns objectAtIndex: _editedColumn]; - theBinding = [GSKeyValueBinding getBinding: NSValueBinding - forObject: tb]; - - if (_dataSource_editable - || theBinding != nil) + if (_dataSource_editable) { [self _setObjectValue: newObjectValue forTableColumn: tb @@ -3366,18 +3361,13 @@ - (void) validateEditing if (validatedOK) { NSTableColumn *tb; - GSKeyValueBinding *theBinding = nil; [_editedCell setStringValue: string]; tb = [_tableColumns objectAtIndex: _editedColumn]; - theBinding = [GSKeyValueBinding getBinding: NSValueBinding - forObject: tb]; - - if (_dataSource_editable - || theBinding != nil) + if (_dataSource_editable) { - [self _setObjectValue: string // newObjectValue + [self _setObjectValue: string forTableColumn: tb row: _editedRow]; } From 6474e53fb636b6860d25c0e892fe139a34c072ef Mon Sep 17 00:00:00 2001 From: Gregory Casamento Date: Fri, 9 Aug 2024 02:28:29 -0400 Subject: [PATCH 63/72] Update NSOutlineView.m - remove unbind per discussion with @fredkiefer --- Source/NSOutlineView.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index db63296d20..5d9379d4b8 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -223,8 +223,6 @@ - (id) initWithFrame: (NSRect)frame - (void) dealloc { - [GSKeyValueBinding unbindAllForObject: self]; - RELEASE(_items); RELEASE(_expandedItems); RELEASE(_selectedIndexPaths); From 118eb26a5f75165fbc8c5ae13e39be8999b284e0 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 11 Aug 2024 16:40:37 -0400 Subject: [PATCH 64/72] Fix issues mentioned by @fredkiefer --- Source/NSTableColumn.m | 14 +------------- Source/NSTableView.m | 1 + 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/Source/NSTableColumn.m b/Source/NSTableColumn.m index ca27713324..a469282275 100644 --- a/Source/NSTableColumn.m +++ b/Source/NSTableColumn.m @@ -660,19 +660,7 @@ - (void) _applyBindingsToCell: (NSCell *)cell GSKeyValueBinding *theBinding = nil; NSFont *font = nil; - theBinding = [GSKeyValueBinding getBinding: NSEditableBinding - forObject: self]; - if (theBinding != nil) - { - id result = nil; - BOOL flag = NO; - - result = [(NSArray *)[theBinding destinationValue] - objectAtIndex: index]; - flag = [result boolValue]; - [cell setEditable: flag]; - } - + [cell setEditable: _is_editable]; theBinding = [GSKeyValueBinding getBinding: NSEnabledBinding forObject: self]; if (theBinding != nil) diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 86b978520c..5a72916db0 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6786,6 +6786,7 @@ - (BOOL) _isCellEditableColumn: (NSInteger) columnIndex return [cell isEditable]; } } + - (void) _willDisplayCell: (NSCell*)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index From ddf6546c3779f8433f42cc0702f48c2b559ab1f1 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 11 Aug 2024 17:06:49 -0400 Subject: [PATCH 65/72] Release selection_index_paths in -dealloc method, per discussion with @fredkiefer --- Source/NSTreeController.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 23e65a66e5..27d45775df 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -103,7 +103,8 @@ - (void) dealloc RELEASE(_leafKeyPath); RELEASE(_sortDescriptors); RELEASE(_arranged_objects); - + RELEASE(_selection_index_paths); + [super dealloc]; } From fbc0cd160b6d2b455393beafc35039bfce6b87f6 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Mon, 12 Aug 2024 14:44:13 -0400 Subject: [PATCH 66/72] Fix issues mentioned by @fredkiefer as well as some addiutional cleanup --- Source/NSTreeController.m | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index 27d45775df..f1b18bac02 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -271,24 +271,9 @@ - (NSString *) leafKeyPath - (IBAction) add: (id)sender { - if ([self canAddChild] - && [self countKeyPath] == nil) - { - id newObject = [self newObject]; - - if (newObject != nil) - { - NSMutableArray *newContent = [NSMutableArray arrayWithArray: [self content]]; - GSControllerTreeProxy *node = [[GSControllerTreeProxy alloc] - initWithContent: newObject - withController: self]; - - [newContent addObject: node]; - - [self setContent: newContent]; - RELEASE(newObject); - } - } + NSIndexPath *p = [NSIndexPath indexPathWithIndex: 0]; + id newObject = [self newObject]; + [self insertObject: newObject atArrangedObjectIndexPath: p]; } - (IBAction) addChild: (id)sender @@ -299,6 +284,7 @@ - (IBAction) addChild: (id)sender if (p != nil) { [self insertObject: newObject atArrangedObjectIndexPath: p]; + RELEASE(newObject); } } @@ -307,7 +293,11 @@ - (IBAction) remove: (id)sender if ([self canRemove] && [self countKeyPath] == nil) { - [self removeObject: [self content]]; + if ([_selection_index_paths count] > 0) + { + NSIndexPath *p = [_selection_index_paths objectAtIndex: 0]; + [self removeObjectAtArrangedObjectIndexPath: p]; + } } } @@ -325,7 +315,7 @@ - (void) insertObject: (id)object atArrangedObjectIndexPath: (NSIndexPath *)inde NSUInteger pos = 0; NSMutableArray *children = [_arranged_objects mutableChildNodes]; - for (pos = 0; pos < length; pos++) + for (pos = 0; pos < length - 1; pos++) { NSUInteger i = [indexPath indexAtPosition: pos]; id node = [children objectAtIndex: i]; From 5befed5855d91e02ba11d31ffb65fed9a60c73f5 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 18 Aug 2024 17:25:47 -0400 Subject: [PATCH 67/72] Fix a number of issues pointed out by @fredkiefer --- Headers/AppKit/NSOutlineView.h | 1 - Source/GSThemeDrawing.m | 1 - Source/NSOutlineView.m | 21 ++++++++++----------- Source/NSTreeController.m | 18 ++++++++++++------ 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Headers/AppKit/NSOutlineView.h b/Headers/AppKit/NSOutlineView.h index 81fbcd7700..fe0b1b9667 100644 --- a/Headers/AppKit/NSOutlineView.h +++ b/Headers/AppKit/NSOutlineView.h @@ -44,7 +44,6 @@ APPKIT_EXPORT_CLASS NSMapTable *_itemDict; NSMutableArray *_items; NSMutableArray *_expandedItems; - NSMutableArray *_selectedIndexPaths; NSMapTable *_levelOfItems; BOOL _autoResizesOutlineColumn; BOOL _indentationMarkerFollowsCell; diff --git a/Source/GSThemeDrawing.m b/Source/GSThemeDrawing.m index e8d08a5185..6c7006742d 100644 --- a/Source/GSThemeDrawing.m +++ b/Source/GSThemeDrawing.m @@ -3532,7 +3532,6 @@ - (void) drawOutlineViewRow: (NSInteger)rowIndex NSInteger endingColumn; NSRect drawingRect; NSInteger i; - id dataSource = [outlineView dataSource]; NSTableColumn *outlineTableColumn = [outlineView outlineTableColumn]; /* Using columnAtPoint: here would make it called twice per row per drawn diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 5d9379d4b8..feb12cfb78 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -225,7 +225,6 @@ - (void) dealloc { RELEASE(_items); RELEASE(_expandedItems); - RELEASE(_selectedIndexPaths); NSFreeMapTable(_itemDict); NSFreeMapTable(_levelOfItems); @@ -1788,17 +1787,16 @@ - (NSIndexPath *) _findIndexPathForItem: (id)item - (NSIndexPath *) _indexPathForItem: (id)item { - id rootItem = nil; return [self _findIndexPathForItem: item - parentItem: rootItem]; + parentItem: nil]; } -- (void) _indexPathsFromSelectedRows +- (NSArray *) _indexPathsFromSelectedRows { NSUInteger index = [_selectedRows firstIndex]; - + NSMutableArray *result = [[NSMutableArray alloc] init]; + // Regenerate the array... - [_selectedIndexPaths removeAllObjects]; while (index != NSNotFound) { id item = [_items objectAtIndex: index]; @@ -1813,10 +1811,12 @@ - (void) _indexPathsFromSelectedRows path = [self _indexPathForItem: item]; } - [_selectedIndexPaths addObject: path]; + [result addObject: path]; index = [_selectedRows indexGreaterThanIndex: index]; } + + return result; } /* @@ -1847,12 +1847,12 @@ - (void) _postSelectionDidChangeNotification forObject: observedObject]; if (theBinding != nil) { - [self _indexPathsFromSelectedRows]; + NSArray *paths = [self _indexPathsFromSelectedRows]; if ([observedObject respondsToSelector: @selector(setSelectionIndexPaths:)]) { - [observedObject setSelectionIndexPaths: _selectedIndexPaths]; + [observedObject setSelectionIndexPaths: paths]; } - [theBinding reverseSetValue: _selectedIndexPaths]; + [theBinding reverseSetValue: paths]; } } @@ -2101,7 +2101,6 @@ - (void) _initOutlineDefaults 64); _items = [[NSMutableArray alloc] init]; _expandedItems = [[NSMutableArray alloc] init]; - _selectedIndexPaths = [[NSMutableArray alloc] init]; _levelOfItems = NSCreateMapTable(keyCallBacks, NSObjectMapValueCallBacks, 64); diff --git a/Source/NSTreeController.m b/Source/NSTreeController.m index f1b18bac02..13247ff466 100644 --- a/Source/NSTreeController.m +++ b/Source/NSTreeController.m @@ -161,7 +161,8 @@ - (BOOL) setSelectionIndexPath: (NSIndexPath *)indexPath if (YES == f) { - [_selection_index_paths addObject: indexPath]; + NSMutableArray *mutable_index_paths = [NSMutableArray arrayWithObject: indexPath]; + ASSIGN(_selection_index_paths, mutable_index_paths); } return f; @@ -241,17 +242,21 @@ - (NSArray *) selectedObjects - (NSIndexPath *) selectionIndexPath { - return [_selection_index_paths objectAtIndex: 0]; + if ([_selection_index_paths count] > 0) + { + return [_selection_index_paths objectAtIndex: 0]; + } + return nil; } - (NSArray *) selectionIndexPaths { - return _selection_index_paths; + return [_selection_index_paths copy]; } - (NSArray *) sortDescriptors { - return _sortDescriptors; + return [_sortDescriptors copy]; } - (NSString *) childrenKeyPath @@ -261,7 +266,7 @@ - (NSString *) childrenKeyPath - (NSString *) countKeyPath { - return _countKeyPath;; + return _countKeyPath; } - (NSString *) leafKeyPath @@ -274,6 +279,7 @@ - (IBAction) add: (id)sender NSIndexPath *p = [NSIndexPath indexPathWithIndex: 0]; id newObject = [self newObject]; [self insertObject: newObject atArrangedObjectIndexPath: p]; + RELEASE(newObject); } - (IBAction) addChild: (id)sender @@ -295,7 +301,7 @@ - (IBAction) remove: (id)sender { if ([_selection_index_paths count] > 0) { - NSIndexPath *p = [_selection_index_paths objectAtIndex: 0]; + NSIndexPath *p = [self selectionIndexPath]; [self removeObjectAtArrangedObjectIndexPath: p]; } } From 27d57fe5eb2f2284fabd8d78e74a8126fedd2f25 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 20 Aug 2024 22:53:31 -0400 Subject: [PATCH 68/72] Add method _keyPathForValueBinding to encapsulate the code for getting the path --- Source/NSOutlineView.m | 14 +++----------- Source/NSTableColumn.m | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index feb12cfb78..d4a4cf61b2 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -152,6 +152,7 @@ - (void) _drawCellViewRow: (NSInteger)rowIndex @interface NSTableColumn (Private) - (void) _applyBindingsToCell: (NSCell *)cell atRow: (NSInteger)index; +- (NSString *) _keyPathForValueBinding; @end @interface NSTreeNode (Private_NSOutlineView) @@ -2020,20 +2021,11 @@ - (id) _objectValueForTableColumn: (NSTableColumn *)tb row: (NSInteger) index { id result = nil; + NSString *keyPath = [tb _keyPathForValueBinding]; - // If we have content binding the data source is used only - // like a delegate - NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding forObject: tb]; - if (info != nil) + if (keyPath != nil) { id theItem = [_items objectAtIndex: index]; - NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; - NSUInteger location = [ikp rangeOfString: @"."].location; - NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); - - // Here we are getting the last part of the keyPath since elsewhere in this class - // we are recursively storing the contents of arrangedObjects (for example) to - // display it as an outline in _loadDictionaryStartingWith:atLevel:. result = [theItem valueForKeyPath: keyPath]; } else diff --git a/Source/NSTableColumn.m b/Source/NSTableColumn.m index a469282275..b1aaff63f0 100644 --- a/Source/NSTableColumn.m +++ b/Source/NSTableColumn.m @@ -654,6 +654,22 @@ - (NSString *) title return [_headerCell stringValue]; } +- (NSString *) _keyPathForValueBinding +{ + NSString *keyPath = nil; + NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding + forObject: self]; + if (info != nil) + { + NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; + NSUInteger location = [ikp rangeOfString: @"."].location; + + keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); + } + + return keyPath; +} + - (void) _applyBindingsToCell: (NSCell *)cell atRow: (NSInteger)index { From 1a188b7eb71f758387d85f105d22b5fbc3805185 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 20 Aug 2024 22:56:18 -0400 Subject: [PATCH 69/72] Add method _keyPathForValueBinding in _setObjectValue for Outline view --- Source/NSOutlineView.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index d4a4cf61b2..ff915c9e6b 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -2048,15 +2048,13 @@ - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index { + NSString *keyPath = [tb _keyPathForValueBinding]; + // If we have content binding the data source is used only // like a delegate - NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding forObject: tb]; - if (info != nil) + if (keyPath != nil) { id theItem = [_items objectAtIndex: index]; - NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; - NSUInteger location = [ikp rangeOfString: @"."].location; - NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); // Set the value on the keyPath. [theItem setValue: value From 068684d6d3690886001feee066d605b1bdc90a23 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 20 Aug 2024 23:00:16 -0400 Subject: [PATCH 70/72] Add method _keyPathForValueBinding in _setObjectValue for table view --- Source/NSTableView.m | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 5a72916db0..169a0a758a 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -185,6 +185,7 @@ @interface NSTableColumn (Private) - (NSArray *) _prototypeCellViews; - (void) _applyBindingsToCell: (NSCell *)cell atRow: (NSInteger)index; +- (NSString *) _keyPathForValueBinding; @end /* @@ -6831,28 +6832,17 @@ - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index { - GSKeyValueBinding *theBinding; - - theBinding = [GSKeyValueBinding getBinding: NSValueBinding - forObject: tb]; - if (theBinding != nil) + NSString *keyPath = [tb _keyPathForValueBinding]; + if (keyPath != nil) { NSArray *items = [[theBinding observedObject] arrangedObjects]; if (items != nil) { - NSDictionary *info = [GSKeyValueBinding infoForBinding: NSValueBinding - forObject: tb]; - if (info != nil) - { - NSString *ikp = [info objectForKey: NSObservedKeyPathKey]; - NSUInteger location = [ikp rangeOfString: @"."].location; - NSString *keyPath = (location == NSNotFound ? ikp : [ikp substringFromIndex: location + 1]); - id obj = [items objectAtIndex: index]; + id obj = [items objectAtIndex: index]; - if (obj != nil) - { - [obj setValue: value forKeyPath: keyPath]; - } + if (obj != nil) + { + [obj setValue: value forKeyPath: keyPath]; } } } From 8ed8754b2ae5874f8722033734eef2b238829c78 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 20 Aug 2024 23:43:30 -0400 Subject: [PATCH 71/72] Correction compile error --- Source/NSTableView.m | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 169a0a758a..82f5ed0649 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -6832,17 +6832,24 @@ - (void) _setObjectValue: (id)value forTableColumn: (NSTableColumn *)tb row: (NSInteger) index { - NSString *keyPath = [tb _keyPathForValueBinding]; - if (keyPath != nil) + GSKeyValueBinding *theBinding; + + theBinding = [GSKeyValueBinding getBinding: NSValueBinding + forObject: tb]; + if (theBinding != nil) { NSArray *items = [[theBinding observedObject] arrangedObjects]; if (items != nil) { - id obj = [items objectAtIndex: index]; - - if (obj != nil) + NSString *keyPath = [tb _keyPathForValueBinding]; + if (keyPath != nil) { - [obj setValue: value forKeyPath: keyPath]; + id obj = [items objectAtIndex: index]; + + if (obj != nil) + { + [obj setValue: value forKeyPath: keyPath]; + } } } } From e1f3109c94750042cd81d8e10facea623c380161 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 21 Aug 2024 00:12:03 -0400 Subject: [PATCH 72/72] Fix issues with setting editable property on NSTableColumn and call _keyPathForValueBinding --- Source/NSTableColumn.m | 6 ++++-- Source/NSTableView.m | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/NSTableColumn.m b/Source/NSTableColumn.m index b1aaff63f0..5e8418e090 100644 --- a/Source/NSTableColumn.m +++ b/Source/NSTableColumn.m @@ -750,8 +750,10 @@ - (void) setValue: (id)anObject forKey: (NSString*)aKey } else if ([aKey isEqual: NSEditableBinding]) { - NSNumber *v = [anObject valueForKey: NSEditableBinding]; - _is_editable = [v boolValue]; + if ([anObject isKindOfClass: [NSNumber class]]) + { + _is_editable = [anObject boolValue]; + } } else { diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 82f5ed0649..eae550bf3d 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -2062,6 +2062,7 @@ - (void) _initDefaults _registeredNibs = [[NSMutableDictionary alloc] init]; _registeredViews = [[NSMutableDictionary alloc] init]; _rowViews = [[NSMutableDictionary alloc] init]; + _dataSource_editable = YES; } - (id) initWithFrame: (NSRect)frameRect @@ -6838,14 +6839,13 @@ - (void) _setObjectValue: (id)value forObject: tb]; if (theBinding != nil) { - NSArray *items = [[theBinding observedObject] arrangedObjects]; - if (items != nil) + NSString *keyPath = [tb _keyPathForValueBinding]; + if (keyPath != nil) { - NSString *keyPath = [tb _keyPathForValueBinding]; - if (keyPath != nil) + NSArray *items = [[theBinding observedObject] arrangedObjects]; + if (items != nil) { id obj = [items objectAtIndex: index]; - if (obj != nil) { [obj setValue: value forKeyPath: keyPath];