From 275c7ff8d5e8fb8ec09107eff8aea0bc54c787e8 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 23 Feb 2002 16:37:17 +0000 Subject: [PATCH] Adding NSOutlineView changes so far so that everyone can see the progress which has been made. GJC git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@12704 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 9 + Headers/gnustep/gui/AppKit.h | 1 + Headers/gnustep/gui/NSOutlineView.h | 66 +- Source/NSOutlineView.m | 1657 ++++++++++++++++++++++++++- Source/externs.m | 10 + 5 files changed, 1699 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index 90e910144..7b5bfa8ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Sat Feb 23 11:28:32 2002 Gregory Casamento + * Headers/gnustep/gui/AppKit.h: Added NSOutlineView header + * Headers/gnustep/gui/NSOutlineView.h: Added additional ivars and + corrected methods for delegate and data source. + * Source/NSOutlineView.m: Added lots of new code to handle the + outline view. + * Source/externs.m: Added definitions for notifications. + Sat Feb 23 12:20:28 2002 Nicola Pero Patch by Alexander Malmberg - @@ -57,6 +65,7 @@ Fri Feb 22 18:22:48 2002 Nicola Pero * Source/NSApplication.m ([-terminate:]): Use an autorelease pool. +>>>>>>> 1.1360 Thu Feb 21 23:29:50 2002 Nicola Pero * Headers/gnustep/gui/NSWindow.h (_originalResponder): Ivar removed. diff --git a/Headers/gnustep/gui/AppKit.h b/Headers/gnustep/gui/AppKit.h index 7ab84863a..2a5404859 100644 --- a/Headers/gnustep/gui/AppKit.h +++ b/Headers/gnustep/gui/AppKit.h @@ -139,6 +139,7 @@ #ifndef STRICT_OPENSTEP #include #include +#include #include #include #include diff --git a/Headers/gnustep/gui/NSOutlineView.h b/Headers/gnustep/gui/NSOutlineView.h index 23fa0a9c9..e2e580737 100644 --- a/Headers/gnustep/gui/NSOutlineView.h +++ b/Headers/gnustep/gui/NSOutlineView.h @@ -31,11 +31,16 @@ #include +@class NSMutableArray; +@class NSString; + @interface NSOutlineView : NSTableView { + NSMutableArray *_items; + NSMutableArray *_expandedItems; BOOL _resize; BOOL _followsCell; - BOOL _autosave; + BOOL _autosaveExpandedItems; float _indentLevel; NSTableColumn *_outlineTableColumn; BOOL _shouldCollapse; @@ -67,7 +72,7 @@ - (void)setOutlineTableColumn: (NSTableColumn *)outlineTableColumn; - (BOOL)shouldCollapseAutoExpandedItemsForDeposited: (BOOL)deposited; -@end /* interface of NSTableView */ +@end /* interface of NSOutlineView */ /* * Informal protocol NSOutlineViewDataSource @@ -78,19 +83,23 @@ item: (id)item childIndex: (int)index; +// required method - (id)outlineView: (NSOutlineView *)outlineView child: (int)index - ofItem:(id)item; + ofItem: (id)item; +// required method - (BOOL)outlineView: (NSOutlineView *)outlineView isItemExpandable: (id)item; - (id)outlineView: (NSOutlineView *)outlineView itemForPersistentObject:(id)object; +// required method - (int)outlineView: (NSOutlineView *)outlineView numberOfChildrenOfItem: (id)item; +// required method - (id)outlineView: (NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; @@ -99,12 +108,14 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn persistentObjectForItem: (id)item; - (void)outlineView: (NSOutlineView *)outlineView - setObjectView: (id)object - forTableColumn: (NSTableColumn *)tableColumn; + setObjectValue: (id)object + forTableColumn: (NSTableColumn *)tableColumn + byItem: (id)item; - (NSDragOperation)outlineView: (NSOutlineView*)outlineView validateDrop: (id )info - proposedItem: (id)item proposedChildIndex:(int)index; + proposedItem: (id)item + proposedChildIndex: (int)index; - (BOOL)outlineView: (NSOutlineView *)outlineView writeItems: (NSArray*)items @@ -125,29 +136,44 @@ APPKIT_EXPORT NSString *NSOutlineViewSelectionDidChangeNotification; APPKIT_EXPORT NSString *NSOutlineViewSelectionIsChangingNotification; APPKIT_EXPORT NSString *NSOutlineViewItemDidExpandNotification; APPKIT_EXPORT NSString *NSOutlineViewItemDidCollapseNotification; +APPKIT_EXPORT NSString *NSOutlineViewItemWillExpandNotification; +APPKIT_EXPORT NSString *NSOutlineViewItemWillCollapseNotification; /* * Methods Implemented by the Delegate */ @interface NSObject (NSOutlineViewDelegate) - -- (BOOL) outlineView: (NSOutlineView *)aOutlineView -shouldEditTableColumn: (NSTableColumn *)aTableColumn - row: (int)rowIndex; -- (BOOL) outlineView: (NSOutlineView *)aOutlineView - shouldSelectRow: (int)rowIndex; -- (BOOL) outlineView: (NSOutlineView *)aOutlineView -shouldSelectTableColumn: (NSTableColumn *)aTableColumn; -- (void) outlineView: (NSOutlineView *)aOutlineView - willDisplayCell: (id)aCell - forTableColumn: (NSTableColumn *)aTableColumn - row: (int)rowIndex; +// notification methods - (void) outlineViewColumnDidMove: (NSNotification *)aNotification; - (void) outlineViewColumnDidResize: (NSNotification *)aNotification; +- (void) outlineViewItemDidCollapse: (NSNotification *)aNotification; +- (void) outlineViewItemDidExpand: (NSNotification *)aNotification; +- (void) outlineViewItemWillCollapse: (NSNotification *)aNotification; +- (void) outlineViewItemWillExpand: (NSNotification *)aNotification; - (void) outlineViewSelectionDidChange: (NSNotification *)aNotification; - (void) outlineViewSelectionIsChanging: (NSNotification *)aNotification; -- (void) outlineViewItemDidExpand: (NSNotification *)aNotification; -- (void) outlineViewItemDidCollapse: (NSNotification *)aNotification; + +// delegate methods +- (BOOL) outlineView: (NSOutlineView *)outlineView + shouldCollapseItem: (id)item; +- (BOOL) outlineView: (NSOutlineView *)outlineView +shouldEditTableColumn: (NSTableColumn *)tableColumn + item: (id)item; +- (BOOL) outlineView: (NSOutlineView *)outlineView + shouldExpandItem: (id)item; +- (BOOL) outlineView: (NSOutlineView *)outlineView + shouldSelectItem: (id)item; +- (BOOL) outlineView: (NSOutlineView *)outlineView +shouldSelectTableColumn: (NSTableColumn *)tableColumn; +- (BOOL) outlineView: (NSOutlineView *)outlineView + willDisplayCell: (id)cell + forTableColumn: (NSTableColumn *)tableColumn + item: (id)item; +- (BOOL) outlineView: (NSOutlineView *)outlineView +willDisplayOutlineCell: (id)cell + forTableColumn: (NSTableColumn *)tableColumn + item: (id)item; +- (BOOL) selectionShouldChangeInOutlineView: (NSOutlineView *)outlineView; @end #endif /* _GNUstep_H_NSOutlineView */ diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index e2606f1e9..33527215b 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -25,20 +25,224 @@ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +static NSNotificationCenter *nc = nil; +static const int current_version = 1; + +// Cache the arrow images... +static NSImage *rightArrow = nil; +static NSImage *downArrow = nil; + +// +// Forward declarations for functions used by both the NSTableView class +// and NSOutlineView. +// +/* The selection arrays are stored so that the selected columns/rows + are always in ascending order. The following function is used + whenever a new column/row is added to the array, to keep the + columns/rows in the correct order. */ +static +void _insertNumberInSelectionArray (NSMutableArray *array, + NSNumber *num) +{ + int i, count; + + count = [array count]; + + for (i = 0; i < count; i++) + { + NSNumber *number; + + number = [array objectAtIndex: i]; + if ([number compare: num] == NSOrderedDescending) + break; + } + [array insertObject: num atIndex: i]; +} + +/* + * Now some auxiliary functions used to manage real-time user selections. + * + */ + +static void +_selectItemsInRange (NSOutlineView *ov, id delegate, + int startRow, int endRow, int clickedRow) +{ + int i; + int tmp; + int shift = 1; + + /* Switch rows if in the wrong order */ + if (startRow > endRow) + { + tmp = startRow; + startRow = endRow; + endRow = tmp; + shift = 0; + } + + for (i = startRow + shift; i < endRow + shift; i++) + { + if (i != clickedRow) + { + if (delegate != nil) + { + id item = [ov itemAtRow: i]; + if ([delegate outlineView: ov shouldSelectItem: item] == NO) + continue; + } + + [ov selectRow: i byExtendingSelection: YES]; + [ov setNeedsDisplayInRect: [ov rectOfRow: i]]; + } + } +} + +static void +_deselectItemsInRange (NSOutlineView *ov, int startRow, int endRow, + int clickedRow) +{ + int i; + int tmp; + int shift = 1; + + if (startRow > endRow) + { + tmp = startRow; + startRow = endRow; + endRow = tmp; + shift = 0; + } + + for (i = startRow + shift; i < endRow + shift; i++) + { + if (i != clickedRow) + { + [ov deselectRow: i]; + [ov setNeedsDisplayInRect: [ov rectOfRow: i]]; + } + } +} + +/* + * The following function can work on columns or rows; + * passing the correct select/deselect function switches between one + * and the other. Currently used only for rows, anyway. + */ + +static void +_selectionChange (NSOutlineView *ov, id delegate, int numberOfRows, + int clickedRow, + int oldSelectedRow, int newSelectedRow, + void (*deselectFunction)(NSOutlineView *, int, int, int), + void (*selectFunction)(NSOutlineView *, id, int, int, int)) +{ + int newDistance; + int oldDistance; + + if (oldSelectedRow == newSelectedRow) + return; + + /* Change coordinates - distance from the center of selection */ + oldDistance = oldSelectedRow - clickedRow; + newDistance = newSelectedRow - clickedRow; + + /* If they have different signs, then we decompose it into + two problems with the same sign */ + if ((oldDistance * newDistance) < 0) + { + _selectionChange (ov, delegate, numberOfRows, clickedRow, + oldSelectedRow, clickedRow, deselectFunction, + selectFunction); + _selectionChange (ov, delegate, numberOfRows, clickedRow, clickedRow, + newSelectedRow, deselectFunction, selectFunction); + return; + } + + /* Otherwise, take the modulus of the distances */ + if (oldDistance < 0) + oldDistance = -oldDistance; + + if (newDistance < 0) + newDistance = -newDistance; + + /* If the new selection is more wide, we need to select */ + if (newDistance > oldDistance) + { + selectFunction (ov, delegate, oldSelectedRow, newSelectedRow, + clickedRow); + } + else /* Otherwise to deselect */ + { + deselectFunction (ov, newSelectedRow, oldSelectedRow, clickedRow); + } +} + +// These methods are defined in NSTableView. +@interface NSOutlineView (TableViewInternalPrivate) +- (void) _setSelectingColumns: (BOOL)flag; +- (BOOL) _editNextEditableCellAfterRow: (int)row + column: (int)column; +- (BOOL) _editPreviousEditableCellBeforeRow: (int)row + column: (int)column; +- (void) _autosaveTableColumns; +- (void) _autoloadTableColumns; +- (void) _openItem: (id)item; +- (void) _closeItem: (id)item; +@end @implementation NSOutlineView -// Instance methods -- (id)init +// Initialize the class when it is loaded ++ (void) initialize { - [super init]; + if (self == [NSOutlineView class]) + { + [self setVersion: current_version]; + nc = [NSNotificationCenter defaultCenter]; + rightArrow = [NSImage imageNamed: @"common_ArrowRight.tiff"]; + downArrow = [NSImage imageNamed: @"common_ArrowDown.tiff"]; + NSLog(@"%@ %@",rightArrow, downArrow); + } +} + +// Instance methods +- (id)initWithFrame: (NSRect)frame +{ + [super initWithFrame: frame]; + + NSLog(@"Intializing NSOutlineView"); + _resize = NO; _followsCell = NO; - _autosave = NO; + _autosaveExpandedItems = NO; _indentLevel = 0.0; _outlineTableColumn = nil; _shouldCollapse = NO; + _items = [NSMutableArray array]; + _expandedItems = [NSMutableArray array]; + + // Retain items + RETAIN(_items); + RETAIN(_expandedItems); return self; } @@ -50,27 +254,223 @@ - (BOOL)autosaveExpandedItems { - return _autosave; + return _autosaveExpandedItems; +} + +- (void)_closeItem: (id)item +{ + int numchildren = [_dataSource outlineView: self + numberOfChildrenOfItem: item]; + int i = 0; + + NSLog(@"closing: %@"); + // close the item... + if(item == nil) + { + [_expandedItems removeObject: @"root"]; + } + else + { + [_expandedItems removeObject: item]; + } + + // For the close method it doesn't matter what order they are + // removed in. + for(i=0;i 0; i--) + { + id child = [_dataSource outlineView: self + child: i + ofItem: item]; + NSLog(@"In here...."); + NSLog(@"child = %@",child); + [_items insertObject: child atIndex: insertionPoint]; + // [self setNeedsDisplayInRect: [self rectOfRow: [self rowForItem: child]]]; + NSLog(@"_items = %@",_items); + } } - (void)collapseItem: (id)item { - // Nothing yet... + [self collapseItem: item collapseChildren: NO]; } - (void)collapseItem: (id)item collapseChildren: (BOOL)collapseChildren { - // Nothing yet... + const SEL shouldSelector = @selector(outlineView:shouldCollapseItem:); + BOOL canCollapse = YES; + + if([_delegate respondsToSelector: shouldSelector]) + { + canCollapse = [_delegate outlineView: self shouldCollapseItem: item]; + } + + if([self isExpandable: item] && [self isItemExpanded: item] && canCollapse) + { + NSMutableDictionary *infoDict = [NSDictionary dictionary]; + [infoDict setObject: item forKey: @"NSObject"]; + + // Send out the notification to let observers know that this is about + // to occur. + [nc postNotificationName: NSOutlineViewItemWillCollapseNotification + object: self + userInfo: infoDict]; + + // collapse... + [self _closeItem: item]; + + // Send out the notification to let observers know that this has + // occured. + [nc postNotificationName: NSOutlineViewItemDidCollapseNotification + object: self + userInfo: infoDict]; + + + if(collapseChildren) // collapse all + { + int numchild = [_dataSource outlineView: self + numberOfChildrenOfItem: item]; + int index = 0; + for(index = 0;index < numchild;index++) + { + id child = [_dataSource outlineView: self + child: index + ofItem: item]; + NSMutableDictionary *infoDict = [NSDictionary dictionary]; + [infoDict setObject: child forKey: @"NSObject"]; + + // Send out the notification to let observers know + // that this is about to occur. + [nc postNotificationName: NSOutlineViewItemWillCollapseNotification + object: self + userInfo: infoDict]; + + if([self isItemExpanded: child]) + { + [self _closeItem: child]; + } + + // Send out the notification to let observers know that + // this is about to occur. + [nc postNotificationName: NSOutlineViewItemDidCollapseNotification + object: self + userInfo: infoDict]; + + + } + } + } + [self reloadData]; } - (void)expandItem: (id)item { - // Nothing yet... + [self expandItem: item expandChildren: NO]; } - (void)expandItem:(id)item expandChildren:(BOOL)expandChildren { - // Nothing yet... + const SEL shouldExpandSelector = @selector(outlineView:shouldExpandItem:); + BOOL canExpand = YES; + + if([_delegate respondsToSelector: shouldExpandSelector]) + { + canExpand = [_delegate outlineView: self shouldExpandItem: item]; + } + + if([self isExpandable: item] && ![self isItemExpanded: item] && canExpand) + { + NSMutableDictionary *infoDict = [NSDictionary dictionary]; + + [infoDict setObject: item forKey: @"NSObject"]; + + // Send out the notification to let observers know that this is about + // to occur. + [nc postNotificationName: NSOutlineViewItemWillExpandNotification + object: self + userInfo: infoDict]; + + // insert the root element, if necessary otherwise insert the + // actual object. + [self _openItem: item]; + + // Send out the notification to let observers know that this has + // occured. + [nc postNotificationName: NSOutlineViewItemDidExpandNotification + object: self + userInfo: infoDict]; + + if(expandChildren) // expand all + { + int numchild = [_dataSource outlineView: self + numberOfChildrenOfItem: item]; + int index = 0; + for(index = 0;index < numchild;index++) + { + id child = [_dataSource outlineView: self + child: index + ofItem: item]; + // Send out the notification to let observers know that this has + // occured. + [nc postNotificationName: NSOutlineViewItemWillExpandNotification + object: self + userInfo: infoDict]; + + if(![self isItemExpanded: child]) + { + [self _openItem: child]; + } + + // Send out the notification to let observers know that this has + // occured. + [nc postNotificationName: NSOutlineViewItemDidExpandNotification + object: self + userInfo: infoDict]; + + } + } + } + [self reloadData]; } - (BOOL)indentationMarkerFollowsCell @@ -85,31 +485,43 @@ - (BOOL)isExpandable: (id)item { - // Nothing yet... - return NO; + return [_dataSource outlineView: self isItemExpandable: item]; } - (BOOL)isItemExpanded: (id)item { - // Nothing yet... - return NO; + id object = item; + + // if the object to be expanded is nil, then the root + // object is being queried. We need to check for a + // placeholder. + if(object == nil) + { + object = @"root"; + } + + // Check the array to determine if it is expanded. + return([_expandedItems containsObject: object]); } - (id)itemAtRow: (int)row { - // Nothing yet... - return nil; + NSLog(@"itemAtRow %d",row); + return [_items objectAtIndex: row]; } - (int)levelForItem: (id)item { - // Nothing yet... - return -1; + if(item == nil) + { + return -1; + } + + return 0; } - (int)levelForRow: (int)row { - // Nothing yet... return -1; } @@ -120,7 +532,7 @@ - (void)reloadItem: (id)item { - // Nothing yet... + [self reloadItem: item reloadChildren: YES]; } - (void)reloadItem: (id)item reloadChildren: (BOOL)reloadChildren @@ -130,8 +542,7 @@ - (int)rowForItem: (id)item { - // Nothing yet... - return -1; + return [_items indexOfObject: item]; } - (void)setAutoresizesOutlineColumn: (BOOL)resize @@ -141,7 +552,7 @@ - (void)setAutosaveExpandedItems: (BOOL)flag { - _autosave = flag; + _autosaveExpandedItems = flag; } - (void)setDropItem:(id)item dropChildIndex: (int)index @@ -169,5 +580,1203 @@ return _shouldCollapse; } -@end /* implementation of NSTableView */ +- (void) noteNumberOfRowsChanged +{ + _numberOfRows = [_items count]; + NSLog(@"_numberOfRows = %d", _numberOfRows); + + /* If we are selecting rows, we have to check that we have no + selected rows below the new end of the table */ + if (!_selectingColumns) + { + int i, count = [_selectedRows count]; + int row = -1; + + /* Check that all selected rows are in the new range of rows */ + for (i = 0; i < count; i++) + { + row = [[_selectedRows objectAtIndex: i] intValue]; + + if (row >= _numberOfRows) + { + break; + } + } + + if (i < count && row > -1) + { + /* Some of them are outside the table ! - Remove them */ + for (; i < count; i++) + { + [_selectedRows removeLastObject]; + } + /* Now if the _selectedRow is outside the table, reset it to be + the last selected row (if any) */ + if (_selectedRow >= _numberOfRows) + { + if ([_selectedRows count] > 0) + { + _selectedRow = [[_selectedRows lastObject] intValue]; + } + 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 */ + int lastRow = _numberOfRows - 1; + + if (lastRow > -1) + { + [_selectedRows addObject: + [NSNumber numberWithInt: lastRow]]; + _selectedRow = lastRow; + } + else + { + /* problem - there are no rows at all */ + _selectedRow = -1; + } + } + } + } + } + } + + [self setFrame: NSMakeRect (_frame.origin.x, + _frame.origin.y, + _frame.size.width, + (_numberOfRows * _rowHeight) + 1)]; + + /* If we are shorter in height than the enclosing clipview, we + should redraw us now. */ + if (_super_view != nil) + { + 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]; + } + } +} + +- (void) setDataSource: (id)anObject +{ + NSArray *requiredMethods = + [NSArray arrayWithObjects: @"outlineView:child:ofItem:", + @"outlineView:isItemExpandable:", + @"outlineView:numberOfChildrenOfItem:", + @"outlineView:objectValueForTableColumn:byItem:", + nil]; + NSEnumerator *en = [requiredMethods objectEnumerator]; + NSString *selectorName = nil; + + // Is the data source editable? + _dataSource_editable = [anObject respondsToSelector: + @selector(outlineView:setObjectValue:forTableColumn:byItem:)]; + + while((selectorName = [en nextObject]) != nil) + { + SEL sel = NSSelectorFromString(selectorName); + if ([anObject respondsToSelector: sel] == NO) + { + [NSException + raise: NSInternalInconsistencyException + format: @"Data Source doesn't respond to %@", + selectorName]; + } + } + + /* We do *not* retain the dataSource, it's like a delegate */ + _dataSource = anObject; + [self tile]; + [self reloadData]; +} + +- (void) reloadData +{ + if([_items count] == 0) + { + [self _openItem: nil]; + } + [super reloadData]; +} + +- (void) setDelegate: (id)anObject +{ + SEL sel; + + if (_delegate) + [nc removeObserver: _delegate name: nil object: self]; + _delegate = anObject; + +#define SET_DELEGATE_NOTIFICATION(notif_name) \ + if ([_delegate respondsToSelector: @selector(outlineView##notif_name:)]) \ + [nc addObserver: _delegate \ + selector: @selector(outlineView##notif_name:) \ + name: NSOutlineView##notif_name##Notification object: self] + + SET_DELEGATE_NOTIFICATION(ColumnDidMove); + SET_DELEGATE_NOTIFICATION(ColumnDidResize); + SET_DELEGATE_NOTIFICATION(SelectionDidChange); + SET_DELEGATE_NOTIFICATION(SelectionIsChanging); + SET_DELEGATE_NOTIFICATION(ItemDidExpand); + SET_DELEGATE_NOTIFICATION(ItemDidCollapse); + SET_DELEGATE_NOTIFICATION(ItemWillExpand); + SET_DELEGATE_NOTIFICATION(ItemWillCollapse); + + /* Cache */ + sel = @selector(outlineView:willDisplayCell:forTableColumn:row:); + sel = @selector(outlineView:setObjectValue:forTableColumn:row:); +} + +- (void) encodeWithCoder: (NSCoder*)aCoder +{ + [super encodeWithCoder: aCoder]; + + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_resize]; + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_followsCell]; + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_autosaveExpandedItems]; + [aCoder encodeValueOfObjCType: @encode(float) at: &_indentLevel]; + [aCoder encodeConditionalObject: _outlineTableColumn]; + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_shouldCollapse]; +} + +- (id) initWithCoder: (NSCoder *)aDecoder +{ + // Since we only have one version.... + self = [super initWithCoder: aDecoder]; + + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_resize]; + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_followsCell]; + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_autosaveExpandedItems]; + [aDecoder decodeValueOfObjCType: @encode(float) at: &_indentLevel]; + _outlineTableColumn = [aDecoder decodeObject]; + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_shouldCollapse]; + + return self; +} + +- (void) moveColumn: (int)columnIndex toColumn: (int)newIndex +{ + /* The range of columns which need to be shifted, + extremes included */ + int minRange, maxRange; + /* Amount of shift for these columns */ + int shift; + /* Dummy variables for the loop */ + int i, count, column; + NSDictionary *dict; + + if ((columnIndex < 0) || (columnIndex > (_numberOfColumns - 1))) + { + NSLog (@"Attempt to move column outside table"); + return; + } + if ((newIndex < 0) || (newIndex > (_numberOfColumns - 1))) + { + NSLog (@"Attempt to move column to outside table"); + return; + } + + if (columnIndex == newIndex) + return; + + if (columnIndex > newIndex) + { + minRange = newIndex; + maxRange = columnIndex - 1; + shift = +1; + } + else // columnIndex < newIndex + { + minRange = columnIndex + 1; + maxRange = newIndex; + shift = -1; + } + + /* Rearrange selection */ + if (_selectedColumn == columnIndex) + { + _selectedColumn = newIndex; + } + else if ((_selectedColumn >= minRange) && (_selectedColumn <= maxRange)) + { + _selectedColumn += shift; + } + + count = [_selectedColumns count]; + for (i = 0; i < count; i++) + { + column = [[_selectedColumns objectAtIndex: i] intValue]; + + if (column == columnIndex) + { + [_selectedColumns replaceObjectAtIndex: i + withObject: [NSNumber numberWithInt: newIndex]]; + continue; + } + + if ((column >= minRange) && (column <= maxRange)) + { + column += shift; + [_selectedColumns replaceObjectAtIndex: i + withObject: [NSNumber numberWithInt: column]]; + continue; + } + + if ((column > columnIndex) && (column > newIndex)) + { + break; + } + } + /* Now really move the column */ + if (columnIndex < newIndex) + { + [_tableColumns insertObject: [_tableColumns objectAtIndex: columnIndex] + atIndex: newIndex + 1]; + [_tableColumns removeObjectAtIndex: columnIndex]; + } + else + { + [_tableColumns insertObject: [_tableColumns objectAtIndex: columnIndex] + atIndex: newIndex]; + [_tableColumns removeObjectAtIndex: columnIndex + 1]; + } + /* Tile */ + [self tile]; + + /* Post notification */ + dict =[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: columnIndex], @"NSOldColumn", + [NSNumber numberWithInt: newIndex], @"NSNewColumn", nil]; + [nc postNotificationName: NSOutlineViewColumnDidMoveNotification + object: self + userInfo: dict]; + + [self _autosaveTableColumns]; +} + +/* + * Selecting Columns and Rows + */ +- (void) selectColumn: (int)columnIndex + byExtendingSelection: (BOOL)flag +{ + NSNumber *num = [NSNumber numberWithInt: columnIndex]; + + if (columnIndex < 0 || columnIndex > _numberOfColumns) + { + [NSException raise: NSInvalidArgumentException + format: @"Column index out of table in selectColumn"]; + } + + _selectingColumns = YES; + + if (flag == NO) + { + /* If the current selection is the one we want, just ends editing + * This is not just a speed up, it prevents us from sending + * a NSOutlineViewSelectionDidChangeNotification. + * This behaviour is required by the specifications */ + if ([_selectedColumns count] == 1 + && [_selectedColumns containsObject: num] == YES) + { + /* Stop editing if any */ + if (_textObject != nil) + { + [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. */ + if (_numberOfColumns > 1) + { + [_selectedColumns removeAllObjects]; + _selectedColumn = -1; + } + } + else // flag == YES + { + if (_allowsMultipleSelection == NO) + { + [NSException raise: NSInternalInconsistencyException + format: @"Can not extend selection in table view when multiple selection is disabled"]; + } + } + + /* Stop editing if any */ + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + + /* Now select the column and post notification only if needed */ + if ([_selectedColumns containsObject: num] == NO) + { + _insertNumberInSelectionArray (_selectedColumns, num); + _selectedColumn = columnIndex; + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; + } + else /* Otherwise simply change the last selected column */ + { + _selectedColumn = columnIndex; + } +} + +- (void) selectRow: (int)rowIndex +byExtendingSelection: (BOOL)flag +{ + NSNumber *num = [NSNumber numberWithInt: rowIndex]; + + if (rowIndex < 0 || rowIndex > _numberOfRows) + { + [NSException raise: NSInvalidArgumentException + format: @"Row index out of table in selectRow"]; + } + + _selectingColumns = NO; + + if (flag == NO) + { + /* If the current selection is the one we want, just ends editing + * This is not just a speed up, it prevents us from sending + * a NSOutlineViewSelectionDidChangeNotification. + * This behaviour is required by the specifications */ + if ([_selectedRows count] == 1 + && [_selectedRows containsObject: num] == YES) + { + /* Stop editing if any */ + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + return; + } + + /* If _numberOfRows == 1, we can skip trying to deselect the + only row - because we have been called to select it. */ + if (_numberOfRows > 1) + { + [_selectedRows removeAllObjects]; + _selectedRow = -1; + } + } + else // flag == YES + { + if (_allowsMultipleSelection == NO) + { + [NSException raise: NSInternalInconsistencyException + format: @"Can not extend selection in table view when multiple selection is disabled"]; + } + } + + /* Stop editing if any */ + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + + /* Now select the row and post notification only if needed */ + if ([_selectedRows containsObject: num] == NO) + { + _insertNumberInSelectionArray (_selectedRows, num); + _selectedRow = rowIndex; + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; + } + else /* Otherwise simply change the last selected row */ + { + _selectedRow = rowIndex; + } +} + +- (void) deselectColumn: (int)columnIndex +{ + NSNumber *num = [NSNumber numberWithInt: columnIndex]; + + if ([_selectedColumns containsObject: num] == NO) + { + return; + } + + /* Now by internal consistency we assume columnIndex is in fact a + valid column index, since it was the index of a selected column */ + + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + + _selectingColumns = YES; + + [_selectedColumns removeObject: num]; + + if (_selectedColumn == columnIndex) + { + int i, count = [_selectedColumns count]; + int nearestColumn = -1; + int nearestColumnDistance = _numberOfColumns; + int column, distance; + for (i = 0; i < count; i++) + { + column = [[_selectedColumns objectAtIndex: i] intValue]; + + distance = column - columnIndex; + if (distance < 0) + { + distance = -distance; + } + + if (distance < nearestColumnDistance) + { + nearestColumn = column; + } + } + _selectedColumn = nearestColumn; + } + + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; +} + +- (void) deselectRow: (int)rowIndex +{ + NSNumber *num = [NSNumber numberWithInt: rowIndex]; + + if ([_selectedRows containsObject: num] == NO) + { + return; + } + + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + + _selectingColumns = NO; + + [_selectedRows removeObject: num]; + + if (_selectedRow == rowIndex) + { + int i, count = [_selectedRows count]; + int nearestRow = -1; + int nearestRowDistance = _numberOfRows; + int row, distance; + for (i = 0; i < count; i++) + { + row = [[_selectedRows objectAtIndex: i] intValue]; + + distance = row - rowIndex; + if (distance < 0) + { + distance = -distance; + } + + if (distance < nearestRowDistance) + { + nearestRow = row; + } + } + _selectedRow = nearestRow; + } + + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; +} + +- (void) selectAll: (id) sender +{ + SEL selector; + + if (_allowsMultipleSelection == NO) + return; + + /* Ask the delegate if we can select all columns or rows */ + if (_selectingColumns == YES) + { + if ([_selectedColumns count] == _numberOfColumns) + { + // Nothing to do ! + return; + } + + selector = @selector (outlineView:shouldSelectTableColumn:); + + if ([_delegate respondsToSelector: selector] == YES) + { + NSEnumerator *enumerator = [_tableColumns objectEnumerator]; + NSTableColumn *tb; + while ((tb = [enumerator nextObject]) != nil) + { + if ([_delegate outlineView: self + shouldSelectTableColumn: tb] == NO) + { + return; + } + } + } + } + else // selecting rows + { + if ([_selectedRows count] == _numberOfRows) + { + // Nothing to do ! + return; + } + + selector = @selector (outlineView:shouldSelectRow:); + + if ([_delegate respondsToSelector: selector] == YES) + { + int row; + + for (row = 0; row < _numberOfRows; row++) + { + id item = [self itemAtRow: row]; + if ([_delegate outlineView: self shouldSelectItem: item] == NO) + return; + } + } + } + + /* Stop editing if any */ + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + + /* Do the real selection */ + if (_selectingColumns == YES) + { + int column; + + [_selectedColumns removeAllObjects]; + for (column = 0; column < _numberOfColumns; column++) + { + NSNumber *num = [NSNumber numberWithInt: column]; + [_selectedColumns addObject: num]; + } + } + else // selecting rows + { + int row; + + [_selectedRows removeAllObjects]; + for (row = 0; row < _numberOfRows; row++) + { + NSNumber *num = [NSNumber numberWithInt: row]; + [_selectedRows addObject: num]; + } + } + + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; +} + +- (void) deselectAll: (id) sender +{ + SEL selector; + + if (_allowsEmptySelection == NO) + return; + + selector = @selector (selectionShouldChangeInOutlineView:); + if ([_delegate respondsToSelector: selector] == YES) + { + if ([_delegate selectionShouldChangeInOutlineView: self] == NO) + { + return; + } + } + + if (_textObject != nil) + { + [self validateEditing]; + [self abortEditing]; + } + + if (([_selectedColumns count] > 0) || ([_selectedRows count] > 0)) + { + [_selectedColumns removeAllObjects]; + [_selectedRows removeAllObjects]; + [nc postNotificationName: NSOutlineViewSelectionDidChangeNotification + object: self]; + } + + _selectedColumn = -1; + _selectedRow = -1; + _selectingColumns = NO; +} + +- (void) mouseDown: (NSEvent *)theEvent +{ + NSPoint location = [theEvent locationInWindow]; + NSTableColumn *tb; + int clickCount; + BOOL shouldEdit; + + // + // Pathological case -- ignore mouse down + // + if ((_numberOfRows == 0) || (_numberOfColumns == 0)) + { + [super mouseDown: theEvent]; + return; + } + + clickCount = [theEvent clickCount]; + + if (clickCount > 2) + return; + + // Determine row and column which were clicked + location = [self convertPoint: location fromView: nil]; + _clickedRow = [self rowAtPoint: location]; + _clickedColumn = [self columnAtPoint: location]; + + NSLog(@"location (%f,%f)",location.x,location.y); + + // Selection + if (clickCount == 1) + { + SEL selector; + unsigned int modifiers; + modifiers = [theEvent modifierFlags]; + + /* Unselect a selected row if the shift key is pressed */ + if ([self isRowSelected: _clickedRow] == YES + && (modifiers & NSShiftKeyMask)) + { + if (([_selectedRows count] == 1) && (_allowsEmptySelection == NO)) + return; + + selector = @selector (selectionShouldChangeInOutlineView:); + if ([_delegate respondsToSelector: selector] == YES) + { + if ([_delegate selectionShouldChangeInOutlineView: self] == NO) + { + return; + } + } + + if (_selectingColumns == YES) + { + [self _setSelectingColumns: NO]; + } + + [self deselectRow: _clickedRow]; + [self setNeedsDisplayInRect: [self rectOfRow: _clickedRow]]; + return; + } + else // row is not selected + { + BOOL newSelection; + + if ((modifiers & (NSShiftKeyMask | NSAlternateKeyMask)) + && _allowsMultipleSelection) + newSelection = NO; + else + newSelection = YES; + + selector = @selector (selectionShouldChangeInOutlineView:); + if ([_delegate respondsToSelector: selector] == YES) + { + if ([_delegate selectionShouldChangeInOutlineView: self] == NO) + { + return; + } + } + + selector = @selector (outlineView:shouldSelectRow:); + if ([_delegate respondsToSelector: selector] == YES) + { + id clickedItem = [self itemAtRow: _clickedRow]; + if ([_delegate outlineView: self + shouldSelectItem: clickedItem] == NO) + { + return; + } + } + + if (_selectingColumns == YES) + { + [self _setSelectingColumns: NO]; + } + + if (newSelection == YES) + { + /* No shift or alternate key pressed: clear the old selection */ + + /* Compute rect to redraw to clear the old selection */ + int row, i, count = [_selectedRows count]; + + for (i = 0; i < count; i++) + { + row = [[_selectedRows objectAtIndex: i] intValue]; + [self setNeedsDisplayInRect: [self rectOfRow: row]]; + } + + /* Draw the new selection */ + [self selectRow: _clickedRow byExtendingSelection: NO]; + [self setNeedsDisplayInRect: [self rectOfRow: _clickedRow]]; + } + else /* Simply add to the old selection */ + { + [self selectRow: _clickedRow byExtendingSelection: YES]; + [self setNeedsDisplayInRect: [self rectOfRow: _clickedRow]]; + } + + if (_allowsMultipleSelection == NO) + { + return; + } + + /* else, we track the mouse to allow extending selection to + areas by dragging the mouse */ + + /* Draw immediately because we are going to enter an event + loop to track the mouse */ + [_window flushWindow]; + + /* We track the cursor and highlight according to the cursor + position. When the cursor gets out (up or down) of the + table, we start periodic events and scroll periodically + the table enlarging or reducing selection. */ + { + BOOL startedPeriodicEvents = NO; + unsigned int eventMask = (NSLeftMouseUpMask + | NSLeftMouseDraggedMask + | NSPeriodicMask); + NSEvent *lastEvent; + BOOL done = NO; + NSPoint mouseLocationWin; + NSDate *distantFuture = [NSDate distantFuture]; + int lastSelectedRow = _clickedRow; + NSRect visibleRect = [self convertRect: [self visibleRect] + toView: nil]; + float minYVisible = NSMinY (visibleRect); + float maxYVisible = NSMaxY (visibleRect); + BOOL delegateTakesPart; + BOOL mouseUp = NO; + /* We have three zones of speed. + 0 - 50 pixels: period 0.2 + 50 - 100 pixels: period 0.1 + 100 - 150 pixels: period 0.01 */ + float oldPeriod = 0; + inline float computePeriod () + { + float distance = 0; + + if (mouseLocationWin.y < minYVisible) + { + 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 + return 0.01; + } + + selector = @selector (outlineView:shouldSelectRow:); + delegateTakesPart = [_delegate respondsToSelector: selector]; + + while (done != YES) + { + lastEvent = [NSApp nextEventMatchingMask: eventMask + untilDate: distantFuture + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + + switch ([lastEvent type]) + { + case NSLeftMouseUp: + done = YES; + break; + case NSLeftMouseDragged: + mouseLocationWin = [lastEvent locationInWindow]; + if ((mouseLocationWin.y > minYVisible) + && (mouseLocationWin.y < maxYVisible)) + { + NSPoint mouseLocationView; + int rowAtPoint; + + if (startedPeriodicEvents == YES) + { + [NSEvent stopPeriodicEvents]; + startedPeriodicEvents = NO; + } + mouseLocationView = [self convertPoint: + mouseLocationWin + fromView: nil]; + mouseLocationView.x = _bounds.origin.x; + rowAtPoint = [self rowAtPoint: mouseLocationView]; + + if (delegateTakesPart == YES) + { + _selectionChange (self, _delegate, + _numberOfRows, _clickedRow, + lastSelectedRow, rowAtPoint, + _deselectItemsInRange, + _selectItemsInRange); + } + else + { + _selectionChange (self, nil, + _numberOfRows, _clickedRow, + lastSelectedRow, rowAtPoint, + _deselectItemsInRange, + _selectItemsInRange); + } + lastSelectedRow = rowAtPoint; + [_window flushWindow]; + [nc postNotificationName: + NSOutlineViewSelectionIsChangingNotification + object: self]; + } + else /* Mouse dragged out of the table */ + { + if (startedPeriodicEvents == YES) + { + /* Check - if the mouse did not change zone, + we do nothing */ + if (computePeriod () == oldPeriod) + break; + + [NSEvent stopPeriodicEvents]; + } + /* Start periodic events */ + oldPeriod = computePeriod (); + + [NSEvent startPeriodicEventsAfterDelay: 0 + withPeriod: oldPeriod]; + startedPeriodicEvents = YES; + if (mouseLocationWin.y <= minYVisible) + mouseUp = NO; + else + mouseUp = YES; + } + break; + case NSPeriodic: + if (mouseUp == NO) // mouse below the table + { + if (lastSelectedRow < _clickedRow) + { + [self deselectRow: lastSelectedRow]; + [self setNeedsDisplayInRect: + [self rectOfRow: lastSelectedRow]]; + [self scrollRowToVisible: lastSelectedRow]; + [_window flushWindow]; + lastSelectedRow++; + } + else + { + if ((lastSelectedRow + 1) < _numberOfRows) + { + id item = nil; + + lastSelectedRow++; + item = [self itemAtRow: lastSelectedRow]; + if ((delegateTakesPart == YES) && + ([_delegate + outlineView: self + shouldSelectItem: item] + == NO)) + { + break; + } + [self selectRow: lastSelectedRow + byExtendingSelection: YES]; + [self setNeedsDisplayInRect: + [self rectOfRow: lastSelectedRow]]; + [self scrollRowToVisible: lastSelectedRow]; + [_window flushWindow]; + } + } + } + else /* mouse above the table */ + { + if (lastSelectedRow <= _clickedRow) + { + if ((lastSelectedRow - 1) >= 0) + { + id item = nil; + + lastSelectedRow--; + item = [self itemAtRow: lastSelectedRow]; + if ((delegateTakesPart == YES) && + ([_delegate + outlineView: self + shouldSelectItem: item] + == NO)) + { + break; + } + [self selectRow: lastSelectedRow + byExtendingSelection: YES]; + [self setNeedsDisplayInRect: + [self rectOfRow: lastSelectedRow]]; + [self scrollRowToVisible: lastSelectedRow]; + [_window flushWindow]; + } + } + else + { + [self deselectRow: lastSelectedRow]; + [self setNeedsDisplayInRect: + [self rectOfRow: lastSelectedRow]]; + [self scrollRowToVisible: lastSelectedRow]; + [_window flushWindow]; + lastSelectedRow--; + } + } + [nc postNotificationName: + NSOutlineViewSelectionIsChangingNotification + object: self]; + break; + default: + break; + } + + } + + if (startedPeriodicEvents == YES) + [NSEvent stopPeriodicEvents]; + + [nc postNotificationName: + NSOutlineViewSelectionDidChangeNotification + object: self]; + + return; + } + } + } + + // Double-click events + + if ([self isRowSelected: _clickedRow] == NO) + return; + + tb = [_tableColumns objectAtIndex: _clickedColumn]; + + shouldEdit = YES; + + if ([tb isEditable] == NO) + { + shouldEdit = NO; + } + else if ([_delegate respondsToSelector: + @selector(outlineView:shouldEditTableColumn:item:)]) + { + id clickedItem = [self itemAtRow: _clickedRow]; + if ([_delegate outlineView: self shouldEditTableColumn: tb + item: clickedItem] == NO) + { + shouldEdit = NO; + } + } + + if (shouldEdit == NO) + { + // Send double-action but don't edit + [self sendAction: _doubleAction to: _target]; + return; + } + + // It is OK to edit column. Go on, do it. + [self editColumn: _clickedColumn row: _clickedRow + withEvent: theEvent select: NO]; +} + +/* + * Drawing + */ + +- (void)drawRow: (int)rowIndex clipRect: (NSRect)aRect +{ + int startingColumn; + int endingColumn; + NSTableColumn *tb; + NSRect drawingRect; + NSCell *cell; + NSCell *imageCell = nil; + NSRect imageRect; + int i; + float x_pos; + id item; + + NSLog(@"In the drawing code..."); + if (_dataSource == nil) + { + return; + } + + /* 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 */ + x_pos = NSMinX (aRect); + i = 0; + while ((x_pos > _columnOrigins[i]) && (i < _numberOfColumns)) + { + i++; + } + startingColumn = (i - 1); + + if (startingColumn == -1) + startingColumn = 0; + + /* Determine ending column as fast as possible */ + x_pos = NSMaxX (aRect); + // Nota Bene: we do *not* reset i + while ((x_pos > _columnOrigins[i]) && (i < _numberOfColumns)) + { + i++; + } + endingColumn = (i - 1); + + if (endingColumn == -1) + endingColumn = _numberOfColumns - 1; + + /* Draw the row between startingColumn and endingColumn */ + for (i = startingColumn; i <= endingColumn; i++) + { + if (i != _editedColumn || rowIndex != _editedRow) + { + id item = [self itemAtRow: rowIndex]; + + tb = [_tableColumns objectAtIndex: i]; + cell = [tb dataCellForRow: rowIndex]; + + if (_del_responds) + { + [_delegate outlineView: self + willDisplayCell: cell + forTableColumn: tb + item: item]; + } + + // item = [self itemAtRow: rowIndex]; + [cell setObjectValue: [_dataSource outlineView: self + objectValueForTableColumn: tb + byItem: item]]; + drawingRect = [self frameOfCellAtColumn: i + row: rowIndex]; + NSLog(@"Drawing rect (%f, %f, %f, %f)", + drawingRect.origin.x, + drawingRect.origin.y, + drawingRect.size.width, + drawingRect.size.height); + + if(tb == _outlineTableColumn) + { + NSLog(@"outlineColumn: %@", item); + imageCell = [[NSCell alloc] initImageCell: rightArrow]; + imageRect.origin.x = drawingRect.origin.x; + imageRect.origin.y = drawingRect.origin.y; + imageRect.size.width = [rightArrow size].width; + imageRect.size.height = [rightArrow size].height; + [imageCell drawWithFrame: imageRect inView: self]; + + // reformat drawing rect, so that there is no overlap + drawingRect.origin.x += [rightArrow size].width + 1; + drawingRect.size.width -= [rightArrow size].width + 1; + } + + [cell drawWithFrame: drawingRect inView: self]; + + } + } +} + +/* +- (void) tile +{ + float table_width = 0; + float table_height; + + NSLog(@"In NSOutlineView's tile method *********"); + if (_tilingDisabled == YES) + { + NSLog(@"NO TILING!!"); + return; + } + + if (_numberOfColumns > 0) + { + int i; + float width; + float offset = 0.0; + + if([_tableColumns objectAtIndex: 0] == _outlineTableColumn) + { + offset = 10.0; + } + + _columnOrigins[0] = _bounds.origin.x; // + offset; + width = [[_tableColumns objectAtIndex: 0] width] + offset; + table_width += width; + + for (i = 1; i < _numberOfColumns; i++) + { + id column = [_tableColumns objectAtIndex: i]; + float coloffset = 0.0; + + // When determining where each column begins, we need to make + // sure that the outline column is taken into account + if (column == _outlineTableColumn) + { + coloffset = 10.0; // width of image. + } + + _columnOrigins[i] = _columnOrigins[i - 1] + width + coloffset; + width = [column width]; + table_width += width; + } + } + + // + 1 for the last grid line + table_height = (_numberOfRows * _rowHeight) + 1; + [self setFrameSize: NSMakeSize (table_width, table_height)]; + [self setNeedsDisplay: YES]; + + if (_headerView != nil) + { + [_headerView setFrameSize: + NSMakeSize (_frame.size.width, + [_headerView frame].size.height)]; + [_cornerView setFrameSize: + NSMakeSize ([NSScroller scrollerWidth] + 1, + [_headerView frame].size.height)]; + [_headerView setNeedsDisplay: YES]; + [_cornerView setNeedsDisplay: YES]; + } +} +*/ +@end /* implementation of NSOutlineView */ diff --git a/Source/externs.m b/Source/externs.m index b02627b02..d1763f811 100644 --- a/Source/externs.m +++ b/Source/externs.m @@ -342,6 +342,16 @@ NSString *NSTableViewColumnDidMoveNotification = @"TableViewColumnDidMove"; NSString *NSTableViewColumnDidResizeNotification = @"TableViewColumnDidResize"; NSString *NSTableViewSelectionIsChangingNotification = @"TableViewSelectionIsChanging"; +// NSOutlineView notifications +NSString *NSOutlineViewSelectionDidChangeNotification = @"OutlineViewSelectionDidChange"; +NSString *NSOutlineViewColumnDidMoveNotification = @"OutlineViewColumnDidMove"; +NSString *NSOutlineViewColumnDidResizeNotification = @"OutlineViewColumnDidResize"; +NSString *NSOutlineViewSelectionIsChangingNotification = @"OutlineViewSelectionIsChanging"; +NSString *NSOutlineViewItemDidExpandNotification = @"OutlineViewItemDidExpand"; +NSString *NSOutlineViewItemDidCollapseNotification = @"OutlineViewItemDidCollapse"; +NSString *NSOutlineViewItemWillExpandNotification = @"OutlineViewItemWillExpand"; +NSString *NSOutlineViewItemWillCollapseNotification = @"OutlineViewItemWillCollapse"; + // NSWindow notifications NSString *NSWindowDidBecomeKeyNotification = @"WindowDidBecomeKey"; NSString *NSWindowDidBecomeMainNotification = @"WindowDidBecomeMain";