From 239eec74dc6f91cc6b7d74b2a10befeefdabbfea Mon Sep 17 00:00:00 2001 From: qmathe Date: Sat, 16 Jan 2010 14:45:13 +0000 Subject: [PATCH] Finished to implement the NSTable/OutlineView sort descriptor support. More changes are needed to get proper sorting support (e.g. visual feedback). git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@29293 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 23 ++++++ Headers/AppKit/NSOutlineView.h | 8 +++ Headers/AppKit/NSTableView.h | 7 ++ Source/NSOutlineView.m | 18 +++++ Source/NSTableHeaderView.m | 15 ++-- Source/NSTableView.m | 127 ++++++++++++++++++++++++++++++--- 6 files changed, 177 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 524e2d5de..a036b15c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2010-01-16 Quentin Mathe + + Finished to implement the NSTable/OutlineView sort descriptor support. + More changes are needed to get proper sorting support (e.g. visual + feedback). + * Headers/NSTableView.h: + Added _sortDescriptors ivar. + (-tableView:sortDescriptorsDidChange:): Declared. + * Source/NSTableView.m + (-_clickTableColumn:, -_didChangeSortDescriptors:): Added. + (-_initDefaults, -dealloc): Modified to initialize/release + _sortDescriptors ivar. + (-initWithCoder:, -encodeWithCoder:): Modified to support archiving + the sort descriptors. + (-setSortSelectors:, -sortSelectors): Implemented. + * Source/NSTableHeaderView.m (-mouseDown:): Modified to now call + -_clickTableColumn which prepares the sort descriptors among other + things. -_didClickTableColumn: will be called by -_clickTableColumn:. + * Headers/NSOutlineView.h (-outlineView:sortDescriptorsDidChange:, + -outlineView:didClickTableColumn:): Declared. + * Source/NSOutlineView.m (-_didClickTableColumn:, + -_didChangeSortDescriptors:): Added overriden NSTableView methods. + 2010-01-15 German Arias * Source/NSImage.m: Changes to fix bug #28580. diff --git a/Headers/AppKit/NSOutlineView.h b/Headers/AppKit/NSOutlineView.h index 6a22be483..549d73a41 100644 --- a/Headers/AppKit/NSOutlineView.h +++ b/Headers/AppKit/NSOutlineView.h @@ -264,6 +264,14 @@ willDisplayOutlineCell: (id)cell * the selection is allowed and NO, if not. */ - (BOOL) selectionShouldChangeInOutlineView: (NSOutlineView *)outlineView; + +#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) +- (void) outlineView: (NSOutlineView *)outlineView + sortDescriptorsDidChange: (NSArray *)oldSortDescriptors; +- (void) outlineView: (NSOutlineView *)outlineView + didClickTableColumn: (NSTableColumn *)aTableColumn; +#endif + @end #endif /* _GNUstep_H_NSOutlineView */ diff --git a/Headers/AppKit/NSTableView.h b/Headers/AppKit/NSTableView.h index 487edc70a..f892db7d0 100644 --- a/Headers/AppKit/NSTableView.h +++ b/Headers/AppKit/NSTableView.h @@ -104,6 +104,7 @@ typedef enum _NSTableViewColumnAutoresizingStyle BOOL _autosaveTableColumns; NSString *_autosaveName; BOOL _verticalMotionDrag; + NSArray *_sortDescriptors; /* * Ivars Acting as Cache @@ -318,8 +319,10 @@ typedef enum _NSTableViewColumnAutoresizingStyle #endif /* sorting */ +#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) - (void) setSortDescriptors: (NSArray *)array; - (NSArray *) sortDescriptors; +#endif @end /* interface of NSTableView */ @@ -375,12 +378,16 @@ APPKIT_EXPORT NSString *NSTableViewSelectionIsChangingNotification; @interface NSObject (NSTableViewDelegate) - (BOOL) selectionShouldChangeInTableView: (NSTableView *)aTableView; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) +- (void) tableView: (NSTableView*)tableView + sortDescriptorsDidChange: (NSArray *)oldSortDescriptors; - (void) tableView: (NSTableView*)tableView didClickTableColumn: (NSTableColumn *)tableColumn; - (void) tableView: (NSTableView*)tableView didDragTableColumn: (NSTableColumn *)tableColumn; - (void) tableView: (NSTableView*)tableView mouseDownInHeaderOfTableColumn: (NSTableColumn *)tableColumn; +#endif - (BOOL)tableView: (NSTableView *)aTableView shouldEditTableColumn: (NSTableColumn *)aTableColumn row: (int)rowIndex; diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index bee0d7775..2e53ec79b 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -1663,6 +1663,24 @@ Also returns the child index relative to this parent. */ return YES; } +- (void) _didChangeSortDescriptors: (NSArray *)oldSortDescriptors +{ + if ([_delegate + respondsToSelector: @selector(outlineView:sortDescriptorsDidChange:)]) + { + [_delegate outlineView: self sortDescriptorsDidChange: oldSortDescriptors]; + } +} + +- (void) _didClickTableColumn: (NSTableColumn *)tc +{ + if ([_delegate + respondsToSelector: @selector(outlineView:didClickTableColumn:)]) + { + [_delegate outlineView: self didClickTableColumn: tc]; + } +} + - (BOOL) _shouldEditTableColumn: (NSTableColumn *)tableColumn row: (int) rowIndex { diff --git a/Source/NSTableHeaderView.m b/Source/NSTableHeaderView.m index ebbb3cf8a..f460d8b3c 100644 --- a/Source/NSTableHeaderView.m +++ b/Source/NSTableHeaderView.m @@ -55,7 +55,7 @@ width: (float)width; - (float *) _columnOrigins; - (void) _mouseDownInHeaderOfTableColumn: (NSTableColumn *)tc; -- (void) _didClickTableColumn: (NSTableColumn *)tc; +- (void) _clickTableColumn: (NSTableColumn *)tc; @end @implementation NSTableHeaderView @@ -753,11 +753,8 @@ if (mouseDragged == NO) { - [_tableView _selectColumn: columnIndex - modifiers: modifiers]; - - [_tableView _didClickTableColumn: - currentColumn]; + [_tableView _selectColumn: columnIndex modifiers: modifiers]; + [_tableView _clickTableColumn: currentColumn]; [self setNeedsDisplay: YES];; } @@ -842,10 +839,8 @@ } else { - [_tableView _selectColumn: columnIndex - modifiers: modifiers]; - [_tableView _didClickTableColumn: - currentColumn]; + [_tableView _selectColumn: columnIndex modifiers: modifiers]; + [_tableView _clickTableColumn: currentColumn]; [self setNeedsDisplay: YES]; /* diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 9df976846..e76504e78 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,8 @@ typedef struct _tableViewFlags - (BOOL) _shouldSelectRow: (int)rowIndex; - (BOOL) _shouldSelectionChange; +- (void) _didChangeSortDescriptors: (NSArray *)oldSortDescriptors; +- (void) _didClickTableColumn: (NSTableColumn *)tc; - (BOOL) _shouldEditTableColumn: (NSTableColumn *)tableColumn row: (int) rowIndex; - (void) _willDisplayCell: (NSCell*)cell @@ -1991,6 +1994,7 @@ static void computeNewSelection _draggingSourceOperationMaskForLocal = NSDragOperationCopy | NSDragOperationLink | NSDragOperationGeneric | NSDragOperationPrivate; _draggingSourceOperationMaskForRemote = NSDragOperationNone; + ASSIGN(_sortDescriptors, [NSArray array]); } - (id) initWithFrame: (NSRect)frameRect @@ -2021,6 +2025,7 @@ static void computeNewSelection RELEASE (_tableColumns); RELEASE (_selectedColumns); RELEASE (_selectedRows); + RELEASE (_sortDescriptors); TEST_RELEASE (_headerView); TEST_RELEASE (_cornerView); if (_autosaveTableColumns == YES) @@ -5650,6 +5655,11 @@ This method is deprecated, use -columnIndexesInRect:. */ [aCoder encodeObject: _cornerView forKey: @"NSCornerView"]; } + if ([[self sortDescriptors] count] > 0) + { + [aCoder encodeObject: _sortDescriptors forKey: @"NSSortDescriptors"]; + } + tableViewFlags.columnSelection = [self allowsColumnSelection]; tableViewFlags.multipleSelection = [self allowsMultipleSelection]; tableViewFlags.emptySelection = [self allowsEmptySelection]; @@ -5710,6 +5720,7 @@ This method is deprecated, use -columnIndexesInRect:. */ ASSIGN(_gridColor, [NSColor gridColor]); ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]); ASSIGN(_tableColumns, [NSMutableArray array]); + ASSIGN(_sortDescriptors, [NSArray array]); if ([aDecoder containsValueForKey: @"NSDataSource"]) { @@ -5784,6 +5795,11 @@ This method is deprecated, use -columnIndexesInRect:. */ [self setHeaderView: [aDecoder decodeObjectForKey: @"NSHeaderView"]]; } + if ([aDecoder containsValueForKey: @"NSSortDescriptors"]) + { + ASSIGN(_sortDescriptors, [aDecoder decodeObjectForKey: @"NSSortDescriptors"]); + } + if ([aDecoder containsValueForKey: @"NSTvFlags"]) { unsigned long flags = [aDecoder decodeIntForKey: @"NSTvFlags"]; @@ -5797,7 +5813,7 @@ This method is deprecated, use -columnIndexesInRect:. */ [self setAllowsColumnResizing: tableViewFlags.columnResizing]; [self setAllowsColumnReordering: tableViewFlags.columnOrdering]; } - + // get the table columns... columns = [aDecoder decodeObjectForKey: @"NSTableColumns"]; e = [columns objectEnumerator]; @@ -5941,15 +5957,40 @@ This method is deprecated, use -columnIndexesInRect:. */ } } -- (void) _didClickTableColumn: (NSTableColumn *)tc +- (void) _clickTableColumn: (NSTableColumn *)tc { - if ([_delegate - respondsToSelector: - @selector(tableView:didClickTableColumn:)]) + NSSortDescriptor *oldMainSortDescriptor = nil; + NSSortDescriptor *newMainSortDescriptor = [tc sortDescriptorPrototype]; + NSMutableArray *newSortDescriptors = + [NSMutableArray arrayWithArray: [self sortDescriptors]]; + NSEnumerator *e = [newSortDescriptors objectEnumerator]; + NSSortDescriptor *descriptor = nil; + NSMutableArray *outdatedDescriptors = [NSMutableArray array]; + + if ([[self sortDescriptors] count] > 0) { - [_delegate tableView: self - didClickTableColumn: tc]; + oldMainSortDescriptor = [[self sortDescriptors] objectAtIndex: 0]; } + + /* Remove every main descriptor equivalents (normally only one) */ + while ((descriptor = [e nextObject]) != nil) + { + if ([[descriptor key] isEqual: [newMainSortDescriptor key]]) + [outdatedDescriptors addObject: descriptor]; + } + + /* Invert the sort direction when the same column header is clicked twice */ + if ([[newMainSortDescriptor key] isEqual: [oldMainSortDescriptor key]]) + { + newMainSortDescriptor = [newMainSortDescriptor reversedSortDescriptor]; + } + + [newSortDescriptors removeObjectsInArray: outdatedDescriptors]; + [newSortDescriptors insertObject: newMainSortDescriptor atIndex: 0]; + + [self setSortDescriptors: newSortDescriptors]; + + [self _didClickTableColumn: tc]; } - (void) _editNextCellAfterRow: (int) row @@ -6513,15 +6554,59 @@ This method is deprecated, use -columnIndexesInRect:. */ /* * sorting */ -- (void) setSortDescriptors: (NSArray *)array + +/** 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 +-sortDescriptors and override them with -setSortDescriptors:.
+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, +so you shouldn't need to call it usually. + +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 { - // FIXME + NSArray *oldSortDescriptors = [self sortDescriptors]; + NSArray *newSortDescriptors = nil; + + /* To replicate precisely the Cocoa behavior */ + if (sortDescriptors == nil) + { + newSortDescriptors = [NSArray array]; + } + else + { + /* _sortDescriptors must remain immutable since -sortDescriptors doesn't + return a defensive copy */ + newSortDescriptors = [NSArray arrayWithArray: sortDescriptors]; + } + + if ([newSortDescriptors isEqual: oldSortDescriptors]) + return; + + RETAIN(oldSortDescriptors); + + ASSIGN(_sortDescriptors, newSortDescriptors); + [self _didChangeSortDescriptors: oldSortDescriptors]; + + RELEASE(oldSortDescriptors); } +/** Returns the current sort descriptors, usually updated every time a click +happens on a table column header. + +By default, returns an empty array. + +For a more detailed explanation, -setSortDescriptors:. */ - (NSArray *)sortDescriptors { - // FIXME - return nil; + return _sortDescriptors; } /* @@ -6616,6 +6701,26 @@ This method is deprecated, use -columnIndexesInRect:. */ return YES; } +- (void) _didChangeSortDescriptors: (NSArray *)oldSortDescriptors +{ + if ([_delegate + respondsToSelector: @selector(tableView:sortDescriptorsDidChange:)]) + { + [_delegate tableView: self sortDescriptorsDidChange: oldSortDescriptors]; + } +} + +- (void) _didClickTableColumn: (NSTableColumn *)tc +{ + if ([_delegate + respondsToSelector: + @selector(tableView:didClickTableColumn:)]) + { + [_delegate tableView: self + didClickTableColumn: tc]; + } +} + - (BOOL) _shouldEditTableColumn: (NSTableColumn *)tableColumn row: (int) rowIndex {