Browser setPath: fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@15929 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2003-02-11 06:43:05 +00:00
parent 79318156a7
commit f4c376b01e
2 changed files with 135 additions and 64 deletions

View file

@ -1,3 +1,9 @@
2003-02-10 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSBrowser.m: Rewrote and documented the ([-setPath:]) method
to fix the distinction between absolute and relative paths and to
improve performance somewhat.
2003-02-10 15:14 Alexander Malmberg <alexander@malmberg.org> 2003-02-10 15:14 Alexander Malmberg <alexander@malmberg.org>
Based on patches from Jeff Teunissen: Based on patches from Jeff Teunissen:

View file

@ -477,114 +477,178 @@ static NSTextFieldCell *titleCell;
return [self pathToColumn: _lastColumnLoaded + 1]; return [self pathToColumn: _lastColumnLoaded + 1];
} }
/** Parses path and selects corresponding items in the NSBrowser columns. */ /**
* <p>Parses path and selects corresponding items in the NSBrowser columns.
* </p>
* <p>This is the primary mechanism for programmatically updating the
* selection of a browser. It should result in the browser cells
* corresponding to the components being selected, and the
* browser columns up to the end of path (and just beyond if the
* last selected cell's [NSBrowserCell-isLeaf] returns YES).<br />
* It does <em>not</em> result in the browsers action being sent to its
* target, just in a change to the browser selection and display.
* </p>
* <p>If path begins with the -pathSeparator then it is taken to be absolute
* and the first component in it is expected to denote a cell in column
* zero. Otherwise it is taken to be relative to the currently selected
* column.
* </p>
* <p>Empty components (ie where a -pathSeparator occurs immediately
* after another or at the end of path) are simply ignored.
* </p>
* <p>The receivers delegate is asked to select each cell in turn
* using the -browser:selectCellWithString:inColumn: method (if it
* implements it). If this call to the delegate returns NO then
* the attempt to set the path fails.<br />
* If the delegate does not implement the method, the browser attempts
* to locate and select the cell itsself, and the method fails if it
* is unable to locate the cell by matching its [NSCell-stringValue] with
* the component of the path.
* </p>
* <p>The method returns YES if path contains no components or if a cell
* corresponding to the path was found. Otherwise it returns NO.
* </p>
*/
- (BOOL) setPath: (NSString *)path - (BOOL) setPath: (NSString *)path
{ {
NSArray *subStrings; NSArray *subStrings;
NSString *aStr;
unsigned numberOfSubStrings; unsigned numberOfSubStrings;
unsigned i, j; unsigned i, j;
int column = 0; int column = _lastColumnLoaded;
BOOL found = YES; BOOL useDelegate = NO;
// If that's all, return. if ([_browserDelegate respondsToSelector:
if (path == nil) @selector(browser:selectCellWithString:inColumn:)])
{ {
[self setNeedsDisplay: YES]; useDelegate = YES;
return YES;
} }
// Otherwise, decompose the path. /*
* Decompose the path.
*/
subStrings = [path componentsSeparatedByString: _pathSeparator]; subStrings = [path componentsSeparatedByString: _pathSeparator];
numberOfSubStrings = [subStrings count]; numberOfSubStrings = [subStrings count];
i = [subStrings indexOfObject: @""];
// Ignore a trailing void component. if (i != NSNotFound)
if (numberOfSubStrings > 0
&& [[subStrings objectAtIndex: 0] isEqualToString: @""])
{ {
numberOfSubStrings--; NSMutableArray *subs = AUTORELEASE([subStrings mutableCopy]);
if (numberOfSubStrings) /*
* If there is a leading empty component, the path began with a
* separator and is therefore absolute. Otherwise it begins from
* the currently selected column.
*/
if (i == 0 && column > 0)
{ {
NSRange theRange; column = 0;
theRange.location = 1;
theRange.length = numberOfSubStrings;
subStrings = [subStrings subarrayWithRange: theRange];
} }
[self loadColumnZero]; [subs removeObject: @""];
subStrings = subs;
numberOfSubStrings = [subStrings count];
/*
* Optimisation. If there are columns loaded, it may be that the
* specified path is already partially selected. If this is the
* case, we can avoid redrawing those columns.
*/
if (column == 0)
{
for (i = 0; i <= _lastColumnLoaded && numberOfSubStrings > 0; i++)
{
NSString *c = [[self selectedCellInColumn: i] stringValue];
if ([c isEqualToString: [subs objectAtIndex: 0]])
{
[subs removeObjectAtIndex: 0];
numberOfSubStrings--;
column++;
}
}
}
} }
column = _lastColumnLoaded; /*
* Ensure that our starting column is loaded.
*/
if (column < 0) if (column < 0)
{ {
column = 0; column = 0;
[self loadColumnZero];
}
else
{
[self setLastColumn: column];
} }
// cycle thru str's array created from path // cycle thru str's array created from path
for (i = 0; i < numberOfSubStrings; i++) for (i = 0; i < numberOfSubStrings; i++)
{ {
NSBrowserColumn *bc = [_browserColumns objectAtIndex: column + i]; NSString *aStr = [subStrings objectAtIndex: i];
NSBrowserColumn *bc = [_browserColumns objectAtIndex: column];
NSMatrix *matrix = [bc columnMatrix]; NSMatrix *matrix = [bc columnMatrix];
NSArray *cells = [matrix cells];
unsigned numOfRows = [cells count];
NSBrowserCell *selectedCell = nil; NSBrowserCell *selectedCell = nil;
BOOL found = NO;
aStr = [subStrings objectAtIndex: i];
if (![aStr isEqualToString: @""]) if (useDelegate == YES)
{ {
found = NO; if ([_browserDelegate browser: self
selectCellWithString: aStr
inColumn: column])
{
found = YES;
selectedCell = [matrix selectedCell];
}
}
else
{
NSArray *cells = [matrix cells];
unsigned numOfRows = [cells count];
// find the cell in the browser matrix which is equal to aStr // find the cell in the browser matrix which is equal to aStr
for (j = 0; j < numOfRows; j++) for (j = 0; j < numOfRows; j++)
{ {
NSString *cellString;
selectedCell = [cells objectAtIndex: j]; selectedCell = [cells objectAtIndex: j];
cellString = [selectedCell stringValue];
if ([cellString isEqualToString: aStr]) if ([[selectedCell stringValue] isEqualToString: aStr])
{ {
if ([_browserDelegate respondsToSelector: [matrix selectCellAtRow: j column: 0];
@selector(browser:selectCellWithString:inColumn:)]) found = YES;
{
if ([_browserDelegate browser: self
selectCellWithString: [selectedCell stringValue]
inColumn: column+i])
{
found = YES;
}
}
else
{
[matrix selectCellAtRow: j column: 0];
found = YES;
}
break; break;
} }
} }
// if unable to find a cell whose title matches aStr return NO
if (found == NO)
{
NSDebugLLog (@"NSBrowser",
@"unable to find cell '%@' in column %d\n",
aStr, column + i);
break;
}
// if the cell is a leaf, we are finished setting the path
if ([selectedCell isLeaf])
break;
// else, it is not a leaf: add a column to the browser for it
[self addColumn];
} }
// if unable to find a cell whose title matches aStr return NO
if (found == NO)
{
NSDebugLLog (@"NSBrowser",
@"unable to find cell '%@' in column %d\n",
aStr, column);
break;
}
// if the cell is a leaf, we are finished setting the path
if ([selectedCell isLeaf])
{
break;
}
// else, it is not a leaf: get a column in the browser for it
[self addColumn];
column++;
} }
[self setNeedsDisplay: YES]; [self setNeedsDisplay: YES];
return found; if (i == numberOfSubStrings)
{
return YES;
}
else
{
return NO;
}
} }
/** Returns a string representing the path from the first column up to, /** Returns a string representing the path from the first column up to,
@ -821,6 +885,7 @@ static NSTextFieldCell *titleCell;
} }
_lastColumnLoaded = column; _lastColumnLoaded = column;
// Unloads columns. // Unloads columns.
count = [_browserColumns count]; count = [_browserColumns count];
num = [self numberOfVisibleColumns]; num = [self numberOfVisibleColumns];