diff --git a/ChangeLog b/ChangeLog index 12f91c28a..917e1c964 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2002-03-27 Gregory John Casamento + + * Source/NSOutlineView.m make more efficient for large sets of + items + * Headers/gnustep/gui/NSOutlineView.h Added new ivar to cache + item level information. + 2002-03-26 Pierre-Yves Rivaille * Source/NSBundleAdditions.m diff --git a/Headers/gnustep/gui/NSOutlineView.h b/Headers/gnustep/gui/NSOutlineView.h index b1c7e4f83..ccfc5d5c3 100644 --- a/Headers/gnustep/gui/NSOutlineView.h +++ b/Headers/gnustep/gui/NSOutlineView.h @@ -39,6 +39,7 @@ NSMutableDictionary *_itemDict; NSMutableArray *_items; NSMutableArray *_expandedItems; + NSMutableDictionary *_levelOfItems; BOOL _autoResizesOutlineColumn; BOOL _indentationMarkerFollowsCell; BOOL _autosaveExpandedItems; diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index e3b943d4b..9bdcad343 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -89,82 +89,8 @@ static NSImage *unexpandable = nil; - (void) _autoloadTableColumns; - (void) _openItem: (id)item; - (void) _closeItem: (id)item; -- (NSDictionary *) _itemDictionary; @end -// static functions -static void _loadDictionary(NSOutlineView *outline, - id startitem, - NSMutableDictionary *allItems) -{ - int num = [[outline dataSource] outlineView: outline - numberOfChildrenOfItem: startitem]; - int i = 0; - id sitem = startitem; - - if((num > 0) && !([allItems objectForKey: startitem])) - { - if(sitem == nil) - { - sitem = [NSNull null]; - } - - [allItems setObject: [NSMutableArray array] - forKey: sitem]; - - } - - for(i = 0; i < num; i++) - { - id anitem = [[outline dataSource] outlineView: outline - child: i - ofItem: startitem]; - id anarray = [allItems objectForKey: sitem]; - - [anarray addObject: anitem]; - _loadDictionary(outline, anitem, allItems); - } -} - -static int _levelForItem(NSDictionary *outlineDict, - id startitem, - id searchitem, - int level, - BOOL *found) -{ - id sitem = startitem; - int num = 0; - int i = 0; - int finallevel = 0; - - if(sitem == nil) - sitem = [NSNull null]; - - // get the count for the array... - num = [[outlineDict objectForKey: sitem] count]; - - if(*found == YES) - { - return level; - } - - if(searchitem == startitem) - { - *found = YES; - return level; - } - - for(i = 0; i < num; i++) - { - id anitem = [[outlineDict objectForKey: sitem] objectAtIndex: i]; - - finallevel = _levelForItem(outlineDict, anitem, searchitem, level + 1, found); - if(*found) break; - } - - return finallevel; -} - @implementation NSOutlineView // Initialize the class when it is loaded @@ -194,11 +120,13 @@ static int _levelForItem(NSDictionary *outlineDict, _itemDict = [NSMutableDictionary dictionary]; _items = [NSMutableArray array]; _expandedItems = [NSMutableArray array]; + _levelOfItems = [NSMutableDictionary dictionary]; // Retain items RETAIN(_items); RETAIN(_expandedItems); RETAIN(_itemDict); + RETAIN(_levelOfItems); return self; } @@ -240,6 +168,42 @@ static int _levelForItem(NSDictionary *outlineDict, } } +- (void) _loadDictionaryStartingWith: (id) startitem + atLevel: (int) level +{ + int num = [_dataSource outlineView: self + numberOfChildrenOfItem: startitem]; + int i = 0; + id sitem = startitem; + + if(num > 0) + { + if(sitem == nil) + { + sitem = [NSNull null]; + } + + [_itemDict setObject: [NSMutableArray array] + forKey: sitem]; + + } + + [_levelOfItems setObject: [NSNumber numberWithInt: level] + forKey: sitem]; + + for(i = 0; i < num; i++) + { + id anitem = [_dataSource outlineView: self + child: i + ofItem: startitem]; + id anarray = [_itemDict objectForKey: sitem]; + + [anarray addObject: anitem]; + [self _loadDictionaryStartingWith: anitem + atLevel: level + 1]; + } +} + - (void)_closeItem: (id)item { int numchildren = 0; @@ -257,7 +221,6 @@ static int _levelForItem(NSDictionary *outlineDict, // For the close method it doesn't matter what order they are // removed in. - for(i=0; i < numchildren; i++) { id child = [removeAll objectAtIndex: i]; @@ -503,8 +466,7 @@ static int _levelForItem(NSDictionary *outlineDict, { if(item != nil) { - BOOL found = NO; - return _levelForItem(_itemDict, nil, item, -1, &found); + return [[_levelOfItems objectForKey: item] intValue]; } return -1; @@ -583,7 +545,8 @@ static int _levelForItem(NSDictionary *outlineDict, if(reloadChildren && haschildren) // expand all { NSMutableDictionary *allChildren = [NSMutableDictionary dictionary]; - _loadDictionary(self, item, allChildren); + [self _loadDictionaryStartingWith: item + atLevel: [self levelForItem: item]]; [_itemDict addEntriesFromDictionary: allChildren]; // release the old array @@ -635,7 +598,7 @@ static int _levelForItem(NSDictionary *outlineDict, - (void) noteNumberOfRowsChanged { _numberOfRows = [_items count]; - + /* If we are selecting rows, we have to check that we have no selected rows below the new end of the table */ if (!_selectingColumns) @@ -764,13 +727,19 @@ static int _levelForItem(NSDictionary *outlineDict, RELEASE(_itemDict); } + if(_levelOfItems != nil) + { + RELEASE(_levelOfItems); + } + // create a new empty one _items = RETAIN([NSMutableArray array]); - _itemDict = RETAIN([NSMutableDictionary dictionary]); + _itemDict = RETAIN([NSMutableDictionary dictionary]); + _levelOfItems = RETAIN([NSMutableDictionary dictionary]); // reload all the open items... - _loadDictionary(self, nil, _itemDict); - // NSLog(@"Dictionary = %@",_itemDict); + [self _loadDictionaryStartingWith: nil + atLevel: -1]; [self _openItem: nil]; [super reloadData]; } @@ -897,6 +866,11 @@ static int _levelForItem(NSDictionary *outlineDict, /* Using columnAtPoint: here would make it called twice per row per drawn rect - so we avoid it and do it natively */ + if(rowIndex >= _numberOfRows) + { + return; + } + /* Determine starting column as fast as possible */ x_pos = NSMinX (aRect); i = 0;