From b1d0ecc21ba2a8801b116b858f52e9e67c8ca920 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 19 Jul 2024 12:04:24 -0400 Subject: [PATCH 01/16] Add new 10.6 delegate methods to NSBrowserDelegate --- Headers/AppKit/NSBrowser.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Headers/AppKit/NSBrowser.h b/Headers/AppKit/NSBrowser.h index bfea1dfed..abadeb7c5 100644 --- a/Headers/AppKit/NSBrowser.h +++ b/Headers/AppKit/NSBrowser.h @@ -42,6 +42,7 @@ @class NSEvent; @class NSMatrix; @class NSScroller; +@class NSViewController; //@class NSBox; #if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) @@ -355,6 +356,29 @@ canDragRowsWithIndexes: (NSIndexSet *)rowIndexes inColumn: (NSInteger)column withEvent: (NSEvent *)event; #endif +#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) +- (id) browser: (NSBrowser *)browser + child: (NSInteger)index + ofItem: (id)item; +- (BOOL) browser: (NSBrowser *)browser + isLeafItem: (id)item; +- (BOOL) browser: (NSBrowser *)browser + shouldEditItem: (id)item; +- (id) browser: (NSBrowser *)browser + objectValueForItem: (id)item; +- (id) browser: (NSBrowser *)browser + setObjectValue: (id)object + forItem: (id)item; +- (id) rootItemForBrowser: (NSBrowser *)browser; +- (NSViewController *) browser: (NSBrowser *)browser + previewViewControllerForLeafItem: (id)item; +- (NSViewController *) browser: (NSBrowser *)browser + headerViewControllerForItem: (id)item; +- (void) browser: (NSBrowser *)browser + didChangeLastColumn: (NSInteger)oldLastColumn + toColumn: (NSInteger)column; +#endif + @end #if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) From 1df45b788e887bd3f490a09f423248d8c24c3a4d Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 20 Jul 2024 12:11:47 -0400 Subject: [PATCH 02/16] Initial changes to start loading each column based on items --- Headers/AppKit/NSBrowser.h | 5 + Source/NSBrowser.m | 1444 ++++++++++++++++++------------------ 2 files changed, 744 insertions(+), 705 deletions(-) diff --git a/Headers/AppKit/NSBrowser.h b/Headers/AppKit/NSBrowser.h index abadeb7c5..c715c82a2 100644 --- a/Headers/AppKit/NSBrowser.h +++ b/Headers/AppKit/NSBrowser.h @@ -100,6 +100,9 @@ APPKIT_EXPORT_CLASS int _lastVisibleColumn; NSString *_columnsAutosaveName; NSBrowserColumnResizingType _columnResizing; + + BOOL _itemBasedDelegate; + id _lastItemLoaded; } // @@ -357,6 +360,8 @@ canDragRowsWithIndexes: (NSIndexSet *)rowIndexes withEvent: (NSEvent *)event; #endif #if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) +- (NSInteger) browser: (NSBrowser *)browser + numberOfChildrenOfItem: (id)item; - (id) browser: (NSBrowser *)browser child: (NSInteger)index ofItem: (id)item; diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index bb6e6d2c1..e2c355121 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -29,8 +29,8 @@ 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. */ @@ -165,7 +165,7 @@ static BOOL browserUseBezels; else { int dummy = 0; - + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_isLoaded]; [aCoder encodeObject: _columnScrollView]; [aCoder encodeObject: _columnMatrix]; @@ -173,7 +173,7 @@ static BOOL browserUseBezels; [aCoder encodeObject: _columnTitle]; } } - + - (id) initWithCoder: (NSCoder *)aDecoder { if ([aDecoder allowsKeyedCoding]) @@ -186,14 +186,14 @@ static BOOL browserUseBezels; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_isLoaded]; _columnScrollView = [aDecoder decodeObject]; if (_columnScrollView) - RETAIN(_columnScrollView); + RETAIN(_columnScrollView); _columnMatrix = [aDecoder decodeObject]; if (_columnMatrix) - RETAIN(_columnMatrix); + RETAIN(_columnMatrix); [aDecoder decodeValueOfObjCType: @encode(int) at: &dummy]; _columnTitle = [aDecoder decodeObject]; if (_columnTitle) - RETAIN(_columnTitle); + RETAIN(_columnTitle); } return self; } @@ -224,8 +224,8 @@ static BOOL browserUseBezels; withFrame: theRect]; } -- (void) _drawBorderAndBackgroundWithFrame: (NSRect)cellFrame - inView: (NSView*)controlView +- (void) _drawBorderAndBackgroundWithFrame: (NSRect)cellFrame + inView: (NSView*)controlView { [[GSTheme theme] drawBrowserHeaderCell: self withFrame: cellFrame @@ -245,6 +245,7 @@ static BOOL browserUseBezels; @interface NSBrowser (Private) - (NSString *) _getTitleOfColumn: (NSInteger)column; - (void) _performLoadOfColumn: (NSInteger)column; +- (void) _performLoadOfItem: (id)item; - (void) _remapColumnSubviews: (BOOL)flag; - (void) _setColumnTitlesNeedDisplay; - (NSBorderType) _resolvedBorderType; @@ -256,7 +257,7 @@ static BOOL browserUseBezels; // @implementation NSBrowser -/**

Returns the NSBrowserCell class (regardless of whether a +/**

Returns the NSBrowserCell class (regardless of whether a -setCellClass: message has been sent to a particular instance). This method is not meant to be used by applications.

See Also: -setCellClass:

*/ @@ -287,7 +288,7 @@ static BOOL browserUseBezels; } /**

Sets the NSCell instance copied to display items in the columns of - NSBrowser.

See Also: -cellPrototype

+ NSBrowser.

See Also: -cellPrototype

*/ - (void) setCellPrototype: (NSCell *)aCell { @@ -295,7 +296,7 @@ static BOOL browserUseBezels; } /**

Returns the class of NSMatrix used in the NSBrowser's columns.

-

See Also: -setMatrixClass:

+

See Also: -setMatrixClass:

*/ - (Class) matrixClass { @@ -303,7 +304,7 @@ static BOOL browserUseBezels; } /**

Sets the matrix class (NSMatrix or an NSMatrix subclass) used in the - NSBrowser's columns.

See Also: -matrixClass

+ NSBrowser's columns.

See Also: -matrixClass

*/ - (void) setMatrixClass: (Class)classId { @@ -328,7 +329,7 @@ static BOOL browserUseBezels; { return nil; } - + if (!(matrix = [self matrixInColumn: i])) { return nil; @@ -337,9 +338,9 @@ static BOOL browserUseBezels; return [matrix selectedCell]; } -/**

Returns the last (lowest) NSCell that's selected in column. +/**

Returns the last (lowest) NSCell that's selected in column. Returns nil if no cell is selected

-

See Also: -selectedCell -selectedCells

+

See Also: -selectedCell -selectedCells

*/ - (id) selectedCellInColumn: (NSInteger)column { @@ -354,7 +355,7 @@ static BOOL browserUseBezels; } /**

Returns a NSArray of selected cells in the rightmost column. Returns - nil if no cell is selected.

See Also: -selectedCell + nil if no cell is selected.

See Also: -selectedCell -selectedCellInColumn: [NSMatrix selectedCells]

*/ - (NSArray *) selectedCells @@ -367,7 +368,7 @@ static BOOL browserUseBezels; { return nil; } - + if (!(matrix = [self matrixInColumn: i])) { return nil; @@ -407,15 +408,15 @@ static BOOL browserUseBezels; return [matrix selectedRow]; } -/**

Selects the cell at index row in the column identified by - index column. If the delegate method +/**

Selects the cell at index row in the column identified by + index column. If the delegate method -browser:selectRow:inColumn: is implemented, this is its responsability to select the cell. This method adds a NSBrowser column if needed - and deselects other selections if the browser does not allows multiple - selection.

See Also: -loadedCellAtRow:column: + and deselects other selections if the browser does not allows multiple + selection.

See Also: -loadedCellAtRow:column: -browser:selectRow:inColumn: [NSMatrix-selectCellAtRow:column:]

*/ -- (void) selectRow: (NSInteger)row inColumn: (NSInteger)column +- (void) selectRow: (NSInteger)row inColumn: (NSInteger)column { NSMatrix *matrix; id cell; @@ -432,18 +433,18 @@ static BOOL browserUseBezels; } [self setLastColumn: column]; - + if (_allowsMultipleSelection == NO) { [matrix deselectAllCells]; } if ([_browserDelegate respondsToSelector: - @selector(browser:selectRow:inColumn:)]) + @selector(browser:selectRow:inColumn:)]) { didSelect = [_browserDelegate browser: self - selectRow: row - inColumn: column]; + selectRow: row + inColumn: column]; } else { @@ -451,8 +452,8 @@ static BOOL browserUseBezels; didSelect = YES; } - if (didSelect && (![cell respondsToSelector: @selector(isLeaf)] - || ([(NSBrowserCell*)cell isLeaf] == NO))) + if (didSelect && (![cell respondsToSelector: @selector(isLeaf)] + || ([(NSBrowserCell*)cell isLeaf] == NO))) { [self addColumn]; } @@ -469,14 +470,14 @@ static BOOL browserUseBezels; if (selectedColumn > -1) { NSUInteger rowIndexes[selectedColumn + 1]; - - for (columnNumber = 0; columnNumber <= selectedColumn; columnNumber++) - { - rowIndexes[columnNumber] = [self selectedRowInColumn: columnNumber]; - } - return [[NSIndexPath alloc] initWithIndexes: rowIndexes - length: selectedColumn + 1]; + for (columnNumber = 0; columnNumber <= selectedColumn; columnNumber++) + { + rowIndexes[columnNumber] = [self selectedRowInColumn: columnNumber]; + } + + return [[NSIndexPath alloc] initWithIndexes: rowIndexes + length: selectedColumn + 1]; } return nil; @@ -499,15 +500,15 @@ static BOOL browserUseBezels; // FIXME: There should be a more efficent way to the the selected row numbers if (!(matrix = [self matrixInColumn: selectedColumn])) - { - return nil; - } + { + return nil; + } selectedCells = [matrix selectedCells]; if (selectedCells == nil) - { - return nil; - } + { + return nil; + } count = [selectedCells count]; NSInteger seletedRows[count]; @@ -516,46 +517,46 @@ static BOOL browserUseBezels; int i = 0; while ((cell = [enumerator nextObject]) != nil) - { - NSInteger row; - NSInteger column; + { + NSInteger row; + NSInteger column; - [matrix getRow: &row - column: &column - ofCell: cell]; - seletedRows[i++] = row; - } + [matrix getRow: &row + column: &column + ofCell: cell]; + seletedRows[i++] = row; + } if (selectedColumn > 0) - { - NSIndexPath *indexPath; - NSUInteger rowIndexes[selectedColumn]; - NSInteger columnNumber = 0; - - for (columnNumber = 0; columnNumber < selectedColumn; columnNumber++) - { - rowIndexes[columnNumber] = [self selectedRowInColumn: columnNumber]; - } - - indexPath = [[NSIndexPath alloc] initWithIndexes: rowIndexes - length: selectedColumn]; - - for (i = 0; i < count; i++) - { - [paths addObject: [indexPath indexPathByAddingIndex: seletedRows[i]]]; - } - } - if (selectedColumn == 0) - { - NSIndexPath *indexPath; + { + NSIndexPath *indexPath; + NSUInteger rowIndexes[selectedColumn]; + NSInteger columnNumber = 0; - for (i = 0; i < count; i++) - { - indexPath = [[NSIndexPath alloc] initWithIndex: seletedRows[i]]; - [paths addObject: indexPath]; - RELEASE(indexPath); - } - } + for (columnNumber = 0; columnNumber < selectedColumn; columnNumber++) + { + rowIndexes[columnNumber] = [self selectedRowInColumn: columnNumber]; + } + + indexPath = [[NSIndexPath alloc] initWithIndexes: rowIndexes + length: selectedColumn]; + + for (i = 0; i < count; i++) + { + [paths addObject: [indexPath indexPathByAddingIndex: seletedRows[i]]]; + } + } + if (selectedColumn == 0) + { + NSIndexPath *indexPath; + + for (i = 0; i < count; i++) + { + indexPath = [[NSIndexPath alloc] initWithIndex: seletedRows[i]]; + [paths addObject: indexPath]; + RELEASE(indexPath); + } + } return paths; } @@ -588,12 +589,12 @@ static BOOL browserUseBezels; } } -/** Loads if necessary and returns the NSCell at row in column. +/** Loads if necessary and returns the NSCell at row in column. if you change this code, you may want to look at the __performLoadOfColumn: - method in which the following code is integrated (for speed) + method in which the following code is integrated (for speed) */ - (id) loadedCellAtRow: (NSInteger)row - column: (NSInteger)column + column: (NSInteger)column { NSMatrix *matrix; NSCell *cell; @@ -610,27 +611,27 @@ static BOOL browserUseBezels; } // Load if not already loaded - if (![cell respondsToSelector: @selector(isLoaded)] + if (![cell respondsToSelector: @selector(isLoaded)] || [(NSBrowserCell*)cell isLoaded]) { return cell; } else { - if (_passiveDelegate || [_browserDelegate respondsToSelector: - @selector(browser:willDisplayCell:atRow:column:)]) - { - [_browserDelegate browser: self willDisplayCell: cell - atRow: row column: column]; - } + if (_passiveDelegate || [_browserDelegate respondsToSelector: + @selector(browser:willDisplayCell:atRow:column:)]) + { + [_browserDelegate browser: self willDisplayCell: cell + atRow: row column: column]; + } [(NSBrowserCell*)cell setLoaded: YES]; } return cell; } -/**

Returns the matrix located in the column identified by index - column. Returns nil if the matrix does not exists

+/**

Returns the matrix located in the column identified by index + column. Returns nil if the matrix does not exists

*/ - (NSMatrix *) matrixInColumn: (NSInteger)column { @@ -642,7 +643,7 @@ static BOOL browserUseBezels; } browserColumn = [_browserColumns objectAtIndex: column]; - + if ((browserColumn == nil) || !(browserColumn->_isLoaded)) { return nil; @@ -723,7 +724,7 @@ static BOOL browserUseBezels; subStrings = [[path componentsSeparatedByString: _pathSeparator] mutableCopy]; [subStrings removeObject: @""]; numberOfSubStrings = [subStrings count]; - + if ([path hasPrefix: _pathSeparator]) { NSUInteger i; @@ -739,20 +740,20 @@ static BOOL browserUseBezels; * case, we can avoid redrawing those columns. */ for (i = 0; i <= _lastColumnLoaded; i++) - { - if ((i < numberOfSubStrings) && - [[[self selectedCellInColumn: i] stringValue] - isEqualToString: [subStrings objectAtIndex: i]]) - { - column = i; - } - else - { - // Actually it's always called at 0 column, when string is "/" - [[self matrixInColumn: i] deselectAllCells]; - break; - } - } + { + if ((i < numberOfSubStrings) && + [[[self selectedCellInColumn: i] stringValue] + isEqualToString: [subStrings objectAtIndex: i]]) + { + column = i; + } + else + { + // Actually it's always called at 0 column, when string is "/" + [[self matrixInColumn: i] deselectAllCells]; + break; + } + } [self setLastColumn: column]; indexOfSubStrings = column; @@ -773,53 +774,53 @@ static BOOL browserUseBezels; BOOL found = NO; if (useDelegate == YES) - { - if ([_browserDelegate browser: self - selectCellWithString: aStr - inColumn: column]) - { - found = YES; - selectedCell = [matrix selectedCell]; - } - } + { + if ([_browserDelegate browser: self + selectCellWithString: aStr + inColumn: column]) + { + found = YES; + selectedCell = [matrix selectedCell]; + } + } else - { - NSInteger numOfRows = [matrix numberOfRows]; - NSInteger row; + { + NSInteger numOfRows = [matrix numberOfRows]; + NSInteger row; - // find the cell in the browser matrix which is equal to aStr - for (row = 0; row < numOfRows; row++) - { - selectedCell = [matrix cellAtRow: row column: 0]; + // find the cell in the browser matrix which is equal to aStr + for (row = 0; row < numOfRows; row++) + { + selectedCell = [matrix cellAtRow: row column: 0]; - if ([[selectedCell stringValue] isEqualToString: aStr]) - { - [matrix selectCellAtRow: row column: 0]; - found = YES; - break; - } - } - } + if ([[selectedCell stringValue] isEqualToString: aStr]) + { + [matrix selectCellAtRow: row column: 0]; + found = YES; + break; + } + } + } if (found) - { - indexOfSubStrings++; - } + { + indexOfSubStrings++; + } else - { - // if unable to find a cell whose title matches aStr return NO - NSDebugLLog (@"NSBrowser", - @"unable to find cell '%@' in column %d\n", - aStr, (int)column); - break; - } + { + // if unable to find a cell whose title matches aStr return NO + NSDebugLLog (@"NSBrowser", + @"unable to find cell '%@' in column %d\n", + aStr, (int)column); + break; + } // if the cell is a leaf, we are finished setting the path if ([selectedCell isLeaf]) - { - break; - } - + { + break; + } + // else, it is not a leaf: get a column in the browser for it [self addColumn]; column++; @@ -846,7 +847,7 @@ static BOOL browserUseBezels; NSMutableString *separator = [_pathSeparator mutableCopy]; NSString *string; NSInteger i; - + /* * Cannot go past the number of loaded columns */ @@ -860,22 +861,22 @@ static BOOL browserUseBezels; id cell = [self selectedCellInColumn: i]; if (i != 0) - { - [separator appendString: _pathSeparator]; - } + { + [separator appendString: _pathSeparator]; + } string = [cell stringValue]; - + if (string == nil) - { - /* This should happen only when c == nil, in which case it - doesn't make sense to go with the path */ - break; - } + { + /* This should happen only when c == nil, in which case it + doesn't make sense to go with the path */ + break; + } else - { - [separator appendString: string]; - } + { + [separator appendString: string]; + } } /* * We actually return a mutable string, but that's ok since a mutable @@ -904,7 +905,7 @@ static BOOL browserUseBezels; /* - * Manipulating columns + * Manipulating columns */ - (NSBrowserColumn *) _createColumn { @@ -919,7 +920,7 @@ static BOOL browserUseBezels; [sc setHasHorizontalScroller: NO]; [sc setHasVerticalScroller: YES]; [sc setBorderType: [self _resolvedBorderType]]; - + [bc setColumnScrollView: sc]; [self addSubview: sc]; RELEASE(sc); @@ -951,7 +952,15 @@ static BOOL browserUseBezels; i = 0; } - [self _performLoadOfColumn: i]; + if (_itemBasedDelegate == YES) + { + [self _performLoadOfItem: _lastItemLoaded]; + } + else + { + [self _performLoadOfColumn: i]; + } + [self setLastColumn: i]; _isLoaded = YES; @@ -1028,7 +1037,7 @@ static BOOL browserUseBezels; [sc setNeedsDisplay: YES]; } -/**

Returns the column number in which matrix is located. +/**

Returns the column number in which matrix is located. Returns -1 if matrix is not found.

*/ - (NSInteger) columnOfMatrix: (NSMatrix *)matrix @@ -1040,7 +1049,7 @@ static BOOL browserUseBezels; for (i = 0; i < count; ++i) { if (matrix == [self matrixInColumn: i]) - return i; + return i; } // Not found @@ -1056,11 +1065,11 @@ static BOOL browserUseBezels; for (i = _lastColumnLoaded; i >= 0; i--) { if (!(matrix = [self matrixInColumn: i])) - continue; + continue; if ([matrix selectedCell]) - return i; + return i; } - + return -1; } @@ -1085,7 +1094,7 @@ static BOOL browserUseBezels; { return; } - + if (column < 0) { column = -1; @@ -1103,25 +1112,25 @@ static BOOL browserUseBezels; sc = [bc columnScrollView]; if ([bc isLoaded]) - { - // Make the column appear empty by removing the matrix - if (sc) - { - [sc setDocumentView: nil]; - } - [bc setIsLoaded: NO]; - [self setTitle: nil ofColumn: i]; - } + { + // Make the column appear empty by removing the matrix + if (sc) + { + [sc setDocumentView: nil]; + } + [bc setIsLoaded: NO]; + [self setTitle: nil ofColumn: i]; + } if (!_reusesColumns && i > _lastVisibleColumn) - { - [sc removeFromSuperview]; - [_browserColumns removeObject: bc]; - count--; - i--; - } + { + [sc removeFromSuperview]; + [_browserColumns removeObject: bc]; + count--; + i--; + } } - + [self scrollColumnToVisible:column]; } @@ -1149,15 +1158,15 @@ static BOOL browserUseBezels; return _lastVisibleColumn; } -/** Invokes delegate method -browser:isColumnValid: for visible columns. +/** Invokes delegate method -browser:isColumnValid: for visible columns. */ - (void) validateVisibleColumns { NSInteger i; // If delegate doesn't care, just return - if (![_browserDelegate respondsToSelector: - @selector(browser:isColumnValid:)]) + if (![_browserDelegate respondsToSelector: + @selector(browser:isColumnValid:)]) { return; } @@ -1168,9 +1177,9 @@ static BOOL browserUseBezels; // Ask delegate if the column is valid and if not // then reload the column if (![_browserDelegate browser: self isColumnValid: i]) - { - [self reloadColumn: i]; - } + { + [self reloadColumn: i]; + } } } @@ -1212,10 +1221,10 @@ static BOOL browserUseBezels; { return; } - + // Get the previously selected cells selectedCells = [[matrix selectedCells] copy]; - + // Perform the data load [self _performLoadOfColumn: column]; // set last column loaded @@ -1229,9 +1238,9 @@ static BOOL browserUseBezels; NSInteger sRow, sColumn; if ([matrix getRow: &sRow column: &sColumn ofCell: cell]) - { - [matrix selectCellAtRow: sRow column: sColumn]; - } + { + [matrix selectCellAtRow: sRow column: sColumn]; + } } RELEASE(selectedCells); } @@ -1243,7 +1252,7 @@ static BOOL browserUseBezels; /**

Returns whether the user can select branch items when multiple selection is enabled. By default YES.

-

See Also: -setAllowsBranchSelection:

+

See Also: -setAllowsBranchSelection:

*/ - (BOOL) allowsBranchSelection { @@ -1251,7 +1260,7 @@ static BOOL browserUseBezels; } /**

Sets whether the user can select branch items when multiple selection - is enabled. By default YES.

See Also: -allowsBranchSelection

+ is enabled. By default YES.

See Also: -allowsBranchSelection

*/ - (void) setAllowsBranchSelection: (BOOL)flag { @@ -1259,7 +1268,7 @@ static BOOL browserUseBezels; } /**

Returns whether there can be nothing selected. By default YES.

-

See Also: -setAllowsEmptySelection:

+

See Also: -setAllowsEmptySelection:

*/ - (BOOL) allowsEmptySelection { @@ -1277,14 +1286,14 @@ static BOOL browserUseBezels; _allowsEmptySelection = flag; for (i = 0; i <= _lastColumnLoaded; i++) - { - [[self matrixInColumn: i] setAllowsEmptySelection: flag]; - } + { + [[self matrixInColumn: i] setAllowsEmptySelection: flag]; + } } } /**

Returns whether the user can select multiple items. By default YES.

-

See Also: -allowsMultipleSelection

+

See Also: -allowsMultipleSelection

*/ - (BOOL) allowsMultipleSelection { @@ -1292,7 +1301,7 @@ static BOOL browserUseBezels; } /**

Sets whether the user can select multiple items. By default YES.

-

See Also: -allowsMultipleSelection

+

See Also: -allowsMultipleSelection

*/ - (void) setAllowsMultipleSelection: (BOOL)flag { @@ -1303,17 +1312,17 @@ static BOOL browserUseBezels; _allowsMultipleSelection = flag; if (flag) - { - mode = NSListModeMatrix; - } + { + mode = NSListModeMatrix; + } else - { - mode = NSRadioModeMatrix; - } + { + mode = NSRadioModeMatrix; + } for (i = 0; i <= _lastColumnLoaded; i++) - { - [[self matrixInColumn: i] setMode: mode]; - } + { + [[self matrixInColumn: i] setMode: mode]; + } } } @@ -1324,7 +1333,7 @@ static BOOL browserUseBezels; /**

Returns YES if NSMatrix objects aren't freed when their columns are unloaded. By default a NSBrowser does not reuses their columns.

-

See Also: -setReusesColumns: [NSMatrix-renewRows:columns:]

+

See Also: -setReusesColumns: [NSMatrix-renewRows:columns:]

*/ - (BOOL) reusesColumns { @@ -1332,8 +1341,8 @@ static BOOL browserUseBezels; } /**

If flag is YES, prevents NSMatrix objects from being freed when - their columns are unloaded, so they can be reused. By default a NSBrowser - does not reuses their columns.

See Also: -reusesColumns + their columns are unloaded, so they can be reused. By default a NSBrowser + does not reuses their columns.

See Also: -reusesColumns [NSMatrix-renewRows:columns:]

*/ - (void) setReusesColumns: (BOOL)flag @@ -1342,16 +1351,16 @@ static BOOL browserUseBezels; } /**

Returns the maximum number of visible columns. By default a NSBrowser - has 3 visible columns.

See Also: -setMaxVisibleColumns:

+ has 3 visible columns.

See Also: -setMaxVisibleColumns:

*/ - (NSInteger) maxVisibleColumns { return _maxVisibleColumns; } -/**

Sets the maximum number of columns displayed and adjusts the various +/**

Sets the maximum number of columns displayed and adjusts the various subviews. By default a NSBrowser has 3 visible columns.

-

See Also: -maxVisibleColumns

+

See Also: -maxVisibleColumns

*/ - (void) setMaxVisibleColumns: (NSInteger)columnCount { @@ -1364,7 +1373,7 @@ static BOOL browserUseBezels; [self tile]; } -/**

Returns the minimum column width in pixels.

+/**

Returns the minimum column width in pixels.

See Also: -setMinColumnWidth:

*/ - (CGFloat) minColumnWidth @@ -1392,7 +1401,7 @@ static BOOL browserUseBezels; [self tile]; } -/**

Returns whether columns are separated by bezeled borders. By default a +/**

Returns whether columns are separated by bezeled borders. By default a NSBrowser has separate columns.

See Also: -setSeparatesColumns:

*/ - (BOOL) separatesColumns @@ -1400,7 +1409,7 @@ static BOOL browserUseBezels; return _separatesColumns; } -/**

Sets whether to separate columns with bezeled borders and marks self for +/**

Sets whether to separate columns with bezeled borders and marks self for display. Does nothing if the NSBrowser is titled. By default a NSBrowser has separate columns.

See Also: -separatesColumns -isTitled

*/ @@ -1481,7 +1490,7 @@ static BOOL browserUseBezels; } -/**

Returns YES if the title of a column is set to the string value of +/**

Returns YES if the title of a column is set to the string value of the selected NSCell in the previous column. By default YES

See Also: -setTakesTitleFromPreviousColumn: -selectedCellInColumn:

*/ @@ -1491,7 +1500,7 @@ static BOOL browserUseBezels; } /**

Sets whether the title of a column is set to the string value of the - selected NSCell in the previous column and marks self for display. By + selected NSCell in the previous column and marks self for display. By default YES

See Also: -takesTitleFromPreviousColumn -selectedCellInColumn:

*/ @@ -1527,16 +1536,16 @@ static BOOL browserUseBezels; } - (BOOL) canDragRowsWithIndexes: (NSIndexSet *)rowIndexes - inColumn: (NSInteger)columnIndex - withEvent: (NSEvent *)dragEvent + inColumn: (NSInteger)columnIndex + withEvent: (NSEvent *)dragEvent { - if ([_browserDelegate respondsToSelector: - @selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)]) + if ([_browserDelegate respondsToSelector: + @selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)]) { return [_browserDelegate browser: self - canDragRowsWithIndexes: rowIndexes - inColumn: columnIndex - withEvent: dragEvent]; + canDragRowsWithIndexes: rowIndexes + inColumn: columnIndex + withEvent: dragEvent]; } else { @@ -1560,24 +1569,24 @@ static BOOL browserUseBezels; return browserColumn->_columnTitle; } -/**

Sets the title of the column at index column to +/**

Sets the title of the column at index column to aString and marks the title for dispaly if the NSBrowser can diplay titles or if the column column is visible.

See Also: -isTitled -titleFrameOfColumn: -titleHeight

*/ - (void) setTitle: (NSString *)aString - ofColumn: (NSInteger)column + ofColumn: (NSInteger)column { NSBrowserColumn *bc; bc = [_browserColumns objectAtIndex: column]; [bc setColumnTitle: aString]; - + // If column is not visible then nothing to redisplay if (!_isTitled || !NSBR_COLUMN_IS_VISIBLE(column)) return; - + [self setNeedsDisplayInRect: [self titleFrameOfColumn: column]]; } @@ -1592,13 +1601,13 @@ static BOOL browserUseBezels; /**

Sets whether columns display titles and marks self for display. Does nothing if the NSBrowser hasn't separates columns. By default a NSBrowser displays titles.

-

See Also: -isTitled -separatesColumns

+

See Also: -isTitled -separatesColumns

*/ - (void) setTitled: (BOOL)flag { if (_isTitled == flag || !_separatesColumns) return; - + _isTitled = flag; [self tile]; [self setNeedsDisplay: YES]; @@ -1606,19 +1615,19 @@ static BOOL browserUseBezels; /** */ -- (void) drawTitleOfColumn: (NSInteger)column - inRect: (NSRect)aRect +- (void) drawTitleOfColumn: (NSInteger)column + inRect: (NSRect)aRect { - [self drawTitle: [self titleOfColumn: column] - inRect: aRect - ofColumn: column]; + [self drawTitle: [self titleOfColumn: column] + inRect: aRect + ofColumn: column]; } /** Draws the title for the column at index column within the rectangle defined by aRect. */ - (void) drawTitle: (NSString *)title - inRect: (NSRect)aRect - ofColumn: (NSInteger)column + inRect: (NSRect)aRect + ofColumn: (NSInteger)column { if (!_isTitled || !NSBR_COLUMN_IS_VISIBLE(column)) return; @@ -1657,25 +1666,25 @@ static BOOL browserUseBezels; // Calculate origin if (_separatesColumns) - { - rect.origin.x = nbColumn * (_columnSize.width + browserColumnSeparation); - } + { + rect.origin.x = nbColumn * (_columnSize.width + browserColumnSeparation); + } else - { - rect.origin.x = nbColumn * _columnSize.width; - } + { + rect.origin.x = nbColumn * _columnSize.width; + } rect.origin.y = _frame.size.height - titleHeight; - + // Calculate size if (column == _lastVisibleColumn) - { - rect.size.width = _frame.size.width - rect.origin.x; - } + { + rect.size.width = _frame.size.width - rect.origin.x; + } else - { - rect.size.width = _columnSize.width; - } + { + rect.size.width = _columnSize.width; + } rect.size.height = titleHeight; @@ -1697,14 +1706,14 @@ static BOOL browserUseBezels; if (_lastVisibleColumn < column) { [self scrollColumnsRightBy: (column - _lastVisibleColumn)]; - } + } else if (_firstVisibleColumn > column) { [self scrollColumnsLeftBy: (_firstVisibleColumn - column)]; - } + } } -/**

Scrolls columns left by shiftAmount columns.

+/**

Scrolls columns left by shiftAmount columns.

See Also: -scrollColumnsRightBy: -scrollColumnToVisible:

*/ - (void) scrollColumnsLeftBy: (NSInteger)shiftAmount @@ -1735,7 +1744,7 @@ static BOOL browserUseBezels; // Notify the delegate if ([_browserDelegate respondsToSelector: @selector(browserDidScroll:)]) - [_browserDelegate browserDidScroll: self]; + [_browserDelegate browserDidScroll: self]; } /**

Scrolls columns right by shiftAmount columns.

@@ -1796,7 +1805,7 @@ static BOOL browserUseBezels; [_horizontalScroller setFloatValue: fv knobProportion: prop]; } -/** Scrolls columns left or right based on an NSScroller. +/** Scrolls columns left or right based on an NSScroller. */ - (void) scrollViaScroller: (NSScroller *)sender { @@ -1804,36 +1813,36 @@ static BOOL browserUseBezels; if ([sender class] != [NSScroller class]) return; - + hit = [sender hitPart]; - + switch (hit) { // Scroll to the left case NSScrollerDecrementLine: case NSScrollerDecrementPage: - [self scrollColumnsLeftBy: 1]; - break; - + [self scrollColumnsLeftBy: 1]; + break; + // Scroll to the right case NSScrollerIncrementLine: case NSScrollerIncrementPage: - [self scrollColumnsRightBy: 1]; - break; - + [self scrollColumnsRightBy: 1]; + break; + // The knob or knob slot case NSScrollerKnob: case NSScrollerKnobSlot: - { - float f = [sender floatValue]; + { + float f = [sender floatValue]; + + [self scrollColumnToVisible: GSRoundTowardsInfinity(f * _lastColumnLoaded)]; + } + break; - [self scrollColumnToVisible: GSRoundTowardsInfinity(f * _lastColumnLoaded)]; - } - break; - // NSScrollerNoPart ??? default: - break; + break; } } @@ -1842,7 +1851,7 @@ static BOOL browserUseBezels; NSMatrix *matrix = [self matrixInColumn: column]; [matrix scrollCellToVisibleAtRow: row - column: 1]; + column: 1]; } /* @@ -1851,7 +1860,7 @@ static BOOL browserUseBezels; /**

Returns whether an NSScroller is used to scroll horizontally. By default a NSBrowser has a horizontal scroller.

See Also: - -setHasHorizontalScroller:

+ -setHasHorizontalScroller:

*/ - (BOOL) hasHorizontalScroller { @@ -1870,9 +1879,9 @@ static BOOL browserUseBezels; { _hasHorizontalScroller = flag; if (!flag) - [_horizontalScroller removeFromSuperview]; + [_horizontalScroller removeFromSuperview]; else - [self addSubview: _horizontalScroller]; + [self addSubview: _horizontalScroller]; [self tile]; [self setNeedsDisplay: YES]; } @@ -1911,7 +1920,7 @@ static BOOL browserUseBezels; /**

Sets whether pressing an arrow key will cause the action message to be sent (in addition to causing scrolling). By default YES.

-

See Also: -sendsActionOnArrowKeys -setAcceptsArrowKeys: +

See Also: -sendsActionOnArrowKeys -setAcceptsArrowKeys: [NSControl-setAction:] [NSControl-action]

*/ - (void) setSendsActionOnArrowKeys: (BOOL)flag @@ -1959,9 +1968,9 @@ static BOOL browserUseBezels; else if (!_separatesColumns && browserUseBezels) { if (column == _firstVisibleColumn) - rect.origin.x += 2; + rect.origin.x += 2; else - rect.origin.x += (n + 2); + rect.origin.x += (n + 2); } // Adjust for horizontal scroller @@ -1970,15 +1979,15 @@ static BOOL browserUseBezels; if (_hasHorizontalScroller) { if (_separatesColumns) - rect.origin.y = (scrollerWidth - 1) + (2 * bezelBorderSize.height) + + rect.origin.y = (scrollerWidth - 1) + (2 * bezelBorderSize.height) + browserVerticalPadding; else rect.origin.y = scrollerWidth + bezelBorderSize.width; } else if (!_separatesColumns) - { - rect.origin.y += bezelBorderSize.width; - } + { + rect.origin.y += bezelBorderSize.width; + } } else { @@ -1990,10 +1999,10 @@ static BOOL browserUseBezels; if (column == _lastVisibleColumn) { if (_separatesColumns) - rect.size.width = _frame.size.width - rect.origin.x; - else - rect.size.width = _frame.size.width - - (rect.origin.x + bezelBorderSize.width); + rect.size.width = _frame.size.width - rect.origin.x; + else + rect.size.width = _frame.size.width - + (rect.origin.x + bezelBorderSize.width); // FIXME: Assumes left-side scrollers if ([[GSTheme theme] scrollViewScrollersOverlapBorders]) @@ -2059,7 +2068,7 @@ static BOOL browserUseBezels; bezelBorderSize = [[GSTheme theme] sizeForBorderType: NSBezelBorder]; _columnSize.height = _frame.size.height; - + // Titles (there is no real frames to resize) if (_isTitled) { @@ -2073,16 +2082,16 @@ static BOOL browserUseBezels; _scrollerRect.origin.x = bezelBorderSize.width; _scrollerRect.origin.y = bezelBorderSize.height - scrollerHightReduction; - _scrollerRect.size.width = (_frame.size.width - - (2 * bezelBorderSize.width)); + _scrollerRect.size.width = (_frame.size.width - + (2 * bezelBorderSize.width)); _scrollerRect.size.height = scrollerWidth; - + if (_separatesColumns) - _columnSize.height -= (scrollerWidth - scrollerHightReduction) + - (2 * bezelBorderSize.height) + browserVerticalPadding; + _columnSize.height -= (scrollerWidth - scrollerHightReduction) + + (2 * bezelBorderSize.height) + browserVerticalPadding; else - _columnSize.height -= scrollerWidth + (2 * bezelBorderSize.height); - + _columnSize.height -= scrollerWidth + (2 * bezelBorderSize.height); + // "Bottom corner" box if (!browserUseBezels && !useBottomCorner) { @@ -2099,20 +2108,20 @@ static BOOL browserUseBezels; } if (!NSEqualRects(_scrollerRect, [_horizontalScroller frame])) - { - [_horizontalScroller setFrame: _scrollerRect]; - } + { + [_horizontalScroller setFrame: _scrollerRect]; + } } else { _scrollerRect = NSZeroRect; if (!_separatesColumns) - _columnSize.height -= 2 * bezelBorderSize.width; + _columnSize.height -= 2 * bezelBorderSize.width; } if (_columnSize.height < 0) _columnSize.height = 0; - + num = _lastVisibleColumn - _firstVisibleColumn + 1; // Column count @@ -2121,14 +2130,14 @@ static BOOL browserUseBezels; CGFloat colWidth = _minColumnWidth + scrollerWidth; if (_separatesColumns) - colWidth += browserColumnSeparation; + colWidth += browserColumnSeparation; if (_frame.size.width > colWidth) - { - columnCount = (int)(_frame.size.width / colWidth); - } + { + columnCount = (int)(_frame.size.width / colWidth); + } else - columnCount = 1; + columnCount = 1; } else columnCount = num; @@ -2140,18 +2149,18 @@ static BOOL browserUseBezels; if (columnCount != num) { if (num > 0) - delta = columnCount - num; + delta = columnCount - num; else - delta = columnCount - 1; + delta = columnCount - 1; if ((delta > 0) && (_lastVisibleColumn <= _lastColumnLoaded)) - { - _firstVisibleColumn = (_firstVisibleColumn - delta > 0) ? - _firstVisibleColumn - delta : 0; - } + { + _firstVisibleColumn = (_firstVisibleColumn - delta > 0) ? + _firstVisibleColumn - delta : 0; + } for (i = [_browserColumns count]; i < columnCount; i++) - [self _createColumn]; + [self _createColumn]; _lastVisibleColumn = _firstVisibleColumn + columnCount - 1; } @@ -2160,8 +2169,8 @@ static BOOL browserUseBezels; if (_separatesColumns) frameWidth = _frame.size.width - ((columnCount - 1) * browserColumnSeparation); else - frameWidth = _frame.size.width - ((columnCount - 1) + - (2 * bezelBorderSize.width)); + frameWidth = _frame.size.width - ((columnCount - 1) + + (2 * bezelBorderSize.width)); _columnSize.width = (int)(frameWidth / (CGFloat)columnCount); @@ -2177,38 +2186,38 @@ static BOOL browserUseBezels; bc = [_browserColumns objectAtIndex: i]; if (!(sc = [bc columnScrollView])) - { - NSLog(@"NSBrowser error, sc != [bc columnScrollView]"); - return; - } + { + NSLog(@"NSBrowser error, sc != [bc columnScrollView]"); + return; + } [sc setBorderType: [self _resolvedBorderType]]; [sc setFrame: [self frameOfColumn: i]]; matrix = [bc columnMatrix]; - + // Adjust matrix to fit in scrollview if column has been loaded if (matrix && [bc isLoaded]) - { - NSSize cs, ms; - - cs = [sc contentSize]; - ms = [matrix cellSize]; - ms.width = cs.width; - [matrix setCellSize: ms]; - [sc setDocumentView: matrix]; - } + { + NSSize cs, ms; + + cs = [sc contentSize]; + ms = [matrix cellSize]; + ms.width = cs.width; + [matrix setCellSize: ms]; + [sc setDocumentView: matrix]; + } } if (columnCount != num) { [self updateScroller]; [self _remapColumnSubviews: YES]; - // [self _setColumnTitlesNeedDisplay]; + // [self _setColumnTitlesNeedDisplay]; [self setNeedsDisplay: YES]; } } -/** Override from NSControl. Don't do anything to change the size of the +/** Override from NSControl. Don't do anything to change the size of the browser. */ - (void) sizeToFit { @@ -2229,9 +2238,9 @@ static BOOL browserUseBezels; *

Sets the delegate of the receiver. * If not nil, the delegate must either be passive and respond to * [NSObject-browser:numberOfRowsInColumn:] or be active and respond to - * [NSObject-browser:createRowsForColumn:inMatrix:] but not both. + * [NSObject-browser:createRowsForColumn:inMatrix:] but not both. * If the delegate is active it must also respond to - * [NSObject-browser:willDisplayCell:atRow:column:]. + * [NSObject-browser:willDisplayCell:atRow:column:]. * If the delegate is not nil but does not meet these conditions, * an NSBrowserIllegalDelegateException will be raised.

*

See Also: -delegate

@@ -2242,48 +2251,61 @@ static BOOL browserUseBezels; /* Default to YES for nil delegate. */ _passiveDelegate = YES; + _itemBasedDelegate = NO; - if ([anObject respondsToSelector: - @selector(browser:numberOfRowsInColumn:)]) + if ([anObject respondsToSelector: + @selector(browser:numberOfChildrenOfItem:)]) { - flag = YES; - if (![anObject respondsToSelector: - @selector(browser:willDisplayCell:atRow:column:)]) - [NSException raise: NSBrowserIllegalDelegateException - format: @"(Passive) Delegate does not respond to %s\n", - GSNameFromSelector - (@selector(browser:willDisplayCell:atRow:column:))]; + _itemBasedDelegate = YES; } - if ([anObject respondsToSelector: - @selector(browser:createRowsForColumn:inMatrix:)]) + if ([anObject respondsToSelector: + @selector(browser:numberOfRowsInColumn:)]) + { + flag = YES; + if (![anObject respondsToSelector: + @selector(browser:willDisplayCell:atRow:column:)]) + [NSException raise: NSBrowserIllegalDelegateException + format: @"(Passive) Delegate does not respond to %s\n", + GSNameFromSelector + (@selector(browser:willDisplayCell:atRow:column:))]; + } + + if ([anObject respondsToSelector: + @selector(browser:createRowsForColumn:inMatrix:)]) { _passiveDelegate = NO; /* If flag is already set - then the delegate must respond to both methods. */ + then the delegate must respond to both methods. */ if (flag) - { - [NSException raise: NSBrowserIllegalDelegateException - format: @"Delegate responds to both %s and %s\n", - GSNameFromSelector - (@selector(browser:numberOfRowsInColumn:)), - GSNameFromSelector - (@selector(browser:createRowsForColumn:inMatrix:))]; - } + { + [NSException raise: NSBrowserIllegalDelegateException + format: @"Delegate responds to both %s and %s\n", + GSNameFromSelector + (@selector(browser:numberOfRowsInColumn:)), + GSNameFromSelector + (@selector(browser:createRowsForColumn:inMatrix:))]; + } flag = YES; } if (!flag && anObject) [NSException raise: NSBrowserIllegalDelegateException - format: @"Delegate does not respond to %s or %s\n", - GSNameFromSelector - (@selector(browser:numberOfRowsInColumn:)), - GSNameFromSelector - (@selector(browser:createRowsForColumn:inMatrix:))]; + format: @"Delegate does not respond to %s or %s\n", + GSNameFromSelector + (@selector(browser:numberOfRowsInColumn:)), + GSNameFromSelector + (@selector(browser:createRowsForColumn:inMatrix:))]; _browserDelegate = anObject; + + // Get the root object after all checks have been done, if it's item based. + if (_itemBasedDelegate) + { + _lastItemLoaded = [_browserDelegate rootItemForBrowser: self]; + } } @@ -2292,7 +2314,7 @@ static BOOL browserUseBezels; */ /**

Returns the NSBrowser's double-click action method.

-

See Also: -setDoubleAction:

+

See Also: -setDoubleAction:

*/ - (SEL) doubleAction { @@ -2300,14 +2322,14 @@ static BOOL browserUseBezels; } /**

Sets the NSBrowser's double-click action to aSelector.

-

See Also: -doubleAction

+

See Also: -doubleAction

*/ - (void) setDoubleAction: (SEL)aSelector { _doubleAction = aSelector; } -/** Sends the action message to the target. Returns YES upon success, +/** Sends the action message to the target. Returns YES upon success, NO if no target for the message could be found. */ - (BOOL) sendAction { @@ -2337,7 +2359,7 @@ static BOOL browserUseBezels; // If the matrix isn't ours then just return if (column < 0 || column > _lastColumnLoaded) return; - + array = [sender selectedCells]; aCount = [array count]; if (aCount == 0) @@ -2349,9 +2371,9 @@ static BOOL browserUseBezels; while ((cell = [enumerator nextObject])) { if (_allowsBranchSelection == NO && [cell isLeaf] == NO) - { - [selectedCells removeObject: cell]; - } + { + [selectedCells removeObject: cell]; + } } if ([selectedCells count] == 0 && [sender selectedCell] != nil) @@ -2371,7 +2393,7 @@ static BOOL browserUseBezels; [sender deselectAllCells]; enumerator = [selectedCells objectEnumerator]; while ((cell = [enumerator nextObject])) - [sender selectCell: cell]; + [sender selectCell: cell]; [sender setAutoscroll: autoscroll]; } @@ -2383,9 +2405,9 @@ static BOOL browserUseBezels; // If the cell is not a leaf we need to load a column if (![cell isLeaf]) - { - [self addColumn]; - } + { + [self addColumn]; + } [sender scrollCellToVisibleAtRow: [sender selectedRow] column: 0]; } @@ -2441,13 +2463,13 @@ static BOOL browserUseBezels; // Initial version [self setVersion: 1]; - + /* Create the shared titleCell if it hasn't been created already. */ if (!titleCell) - { - titleCell = [GSBrowserTitleCell new]; - } - + { + titleCell = [GSBrowserTitleCell new]; + } + [self _themeDidActivate: nil]; } } @@ -2469,7 +2491,7 @@ static BOOL browserUseBezels; // Class setting _browserCellPrototype = [[[NSBrowser cellClass] alloc] init]; _browserMatrixClass = [NSMatrix class]; - + // Default values _pathSeparator = @"/"; _allowsBranchSelection = YES; @@ -2489,7 +2511,7 @@ static BOOL browserUseBezels; _sendsActionOnAlphaNumericalKeys = YES; _browserDelegate = nil; _passiveDelegate = YES; - _doubleAction = NULL; + _doubleAction = NULL; // FIXME: Seems a bit wrong to look at the current theme here bs = NSZeroSize; if (browserUseBezels) @@ -2519,6 +2541,10 @@ static BOOL browserUseBezels; _maxVisibleColumns = 3; [self _createColumn]; + // Item based delegate, 10.6+ + _itemBasedDelegate = NO; + _lastItemLoaded = nil; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_themeDidActivate:) @@ -2579,7 +2605,7 @@ static BOOL browserUseBezels; /* - * Events handling + * Events handling */ - (void) drawRect: (NSRect)rect @@ -2613,26 +2639,26 @@ static BOOL browserUseBezels; matrix = (NSMatrix *)[_window firstResponder]; selectedColumn = [self columnOfMatrix:matrix]; if (selectedColumn == -1) - { - selectedColumn = [self selectedColumn]; - matrix = [self matrixInColumn: selectedColumn]; - } + { + selectedColumn = [self selectedColumn]; + matrix = [self matrixInColumn: selectedColumn]; + } if (selectedColumn > 0) - { - [matrix deselectAllCells]; - [matrix scrollCellToVisibleAtRow:0 column:0]; - [self setLastColumn: selectedColumn]; + { + [matrix deselectAllCells]; + [matrix scrollCellToVisibleAtRow:0 column:0]; + [self setLastColumn: selectedColumn]; - selectedColumn--; - [self scrollColumnToVisible: selectedColumn]; - matrix = [self matrixInColumn: selectedColumn]; - [_window makeFirstResponder: matrix]; + selectedColumn--; + [self scrollColumnToVisible: selectedColumn]; + matrix = [self matrixInColumn: selectedColumn]; + [_window makeFirstResponder: matrix]; - if (_sendsActionOnArrowKeys == YES) - { - [super sendAction: _action to: _target]; - } - } + if (_sendsActionOnArrowKeys == YES) + { + [super sendAction: _action to: _target]; + } + } } } @@ -2646,47 +2672,47 @@ static BOOL browserUseBezels; matrix = (NSMatrix *)[_window firstResponder]; selectedColumn = [self columnOfMatrix:matrix]; if (selectedColumn == -1) - { - selectedColumn = [self selectedColumn]; - matrix = [self matrixInColumn: selectedColumn]; - } + { + selectedColumn = [self selectedColumn]; + matrix = [self matrixInColumn: selectedColumn]; + } if (selectedColumn == -1) - { - matrix = [self matrixInColumn: 0]; + { + matrix = [self matrixInColumn: 0]; - if ([[matrix cells] count]) - { - [matrix selectCellAtRow: 0 column: 0]; - } - } + if ([[matrix cells] count]) + { + [matrix selectCellAtRow: 0 column: 0]; + } + } else - { - // if there is one selected cell and it is a leaf, move right - // (column is already loaded) - if (![[matrix selectedCell] isLeaf] - && [[matrix selectedCells] count] == 1) - { - selectedColumn++; - matrix = [self matrixInColumn: selectedColumn]; - if ([[matrix cells] count] && [matrix selectedCell] == nil) - { - [matrix selectCellAtRow: 0 column: 0]; - } - // if selected cell is a leaf, we need to add a column - if (![[matrix selectedCell] isLeaf] - && [[matrix selectedCells] count] == 1) - { - [self addColumn]; - } - } - } + { + // if there is one selected cell and it is a leaf, move right + // (column is already loaded) + if (![[matrix selectedCell] isLeaf] + && [[matrix selectedCells] count] == 1) + { + selectedColumn++; + matrix = [self matrixInColumn: selectedColumn]; + if ([[matrix cells] count] && [matrix selectedCell] == nil) + { + [matrix selectCellAtRow: 0 column: 0]; + } + // if selected cell is a leaf, we need to add a column + if (![[matrix selectedCell] isLeaf] + && [[matrix selectedCells] count] == 1) + { + [self addColumn]; + } + } + } [_window makeFirstResponder: matrix]; if (_sendsActionOnArrowKeys == YES) - { - [super sendAction: _action to: _target]; - } + { + [super sendAction: _action to: _target]; + } } } @@ -2703,32 +2729,32 @@ static BOOL browserUseBezels; if (_acceptsArrowKeys) { switch (character) - { - case NSUpArrowFunctionKey: - case NSDownArrowFunctionKey: - return; - case NSLeftArrowFunctionKey: - [self moveLeft:self]; - return; - case NSRightArrowFunctionKey: - [self moveRight:self]; - return; - case NSBackTabCharacter: - [_window selectKeyViewPrecedingView: self]; - return; - case NSTabCharacter: - { - if ([theEvent modifierFlags] & NSShiftKeyMask) - { - [_window selectKeyViewPrecedingView: self]; - } - else - { - [_window selectKeyViewFollowingView: self]; - } - } - return; - } + { + case NSUpArrowFunctionKey: + case NSDownArrowFunctionKey: + return; + case NSLeftArrowFunctionKey: + [self moveLeft:self]; + return; + case NSRightArrowFunctionKey: + [self moveRight:self]; + return; + case NSBackTabCharacter: + [_window selectKeyViewPrecedingView: self]; + return; + case NSTabCharacter: + { + if ([theEvent modifierFlags] & NSShiftKeyMask) + { + [_window selectKeyViewPrecedingView: self]; + } + else + { + [_window selectKeyViewFollowingView: self]; + } + } + return; + } } if (_acceptsAlphaNumericalKeys && (character < 0xF700) @@ -2744,83 +2770,83 @@ static BOOL browserUseBezels; selectedColumn = [self selectedColumn]; if (selectedColumn != -1) - { - matrix = [self matrixInColumn: selectedColumn]; - n = [matrix numberOfRows]; - s = [matrix selectedRow]; - - if (!_charBuffer) - { - _charBuffer = [characters substringToIndex: 1]; - RETAIN(_charBuffer); - } - else - { - if (([theEvent timestamp] - _lastKeyPressed < 2000.0) - && (_alphaNumericalLastColumn == selectedColumn)) - { - NSString *transition; - transition = [_charBuffer - stringByAppendingString: - [characters substringToIndex: 1]]; - RELEASE(_charBuffer); - _charBuffer = transition; - RETAIN(_charBuffer); - } - else - { - RELEASE(_charBuffer); - _charBuffer = [characters substringToIndex: 1]; - RETAIN(_charBuffer); - } - } + { + matrix = [self matrixInColumn: selectedColumn]; + n = [matrix numberOfRows]; + s = [matrix selectedRow]; - _alphaNumericalLastColumn = selectedColumn; - _lastKeyPressed = [theEvent timestamp]; - - sv = [((*lcarc)(self, lcarcSel, s, selectedColumn)) - stringValue]; + if (!_charBuffer) + { + _charBuffer = [characters substringToIndex: 1]; + RETAIN(_charBuffer); + } + else + { + if (([theEvent timestamp] - _lastKeyPressed < 2000.0) + && (_alphaNumericalLastColumn == selectedColumn)) + { + NSString *transition; + transition = [_charBuffer + stringByAppendingString: + [characters substringToIndex: 1]]; + RELEASE(_charBuffer); + _charBuffer = transition; + RETAIN(_charBuffer); + } + else + { + RELEASE(_charBuffer); + _charBuffer = [characters substringToIndex: 1]; + RETAIN(_charBuffer); + } + } - if (([sv length] > 0) - && ([sv hasPrefix: _charBuffer])) - return; + _alphaNumericalLastColumn = selectedColumn; + _lastKeyPressed = [theEvent timestamp]; - match = -1; - for (i = s + 1; i < n; i++) - { - sv = [((*lcarc)(self, lcarcSel, i, selectedColumn)) - stringValue]; - if (([sv length] > 0) - && ([sv hasPrefix: _charBuffer])) - { - match = i; - break; - } - } - if (i == n) - { - for (i = 0; i < s; i++) - { - sv = [((*lcarc)(self, lcarcSel, i, selectedColumn)) - stringValue]; - if (([sv length] > 0) - && ([sv hasPrefix: _charBuffer])) - { - match = i; - break; - } - } - } - if (match != -1) - { - [matrix deselectAllCells]; - [self selectRow: match - inColumn: selectedColumn]; - [matrix scrollCellToVisibleAtRow: match column: 0]; - [matrix performClick: self]; - return; - } - } + sv = [((*lcarc)(self, lcarcSel, s, selectedColumn)) + stringValue]; + + if (([sv length] > 0) + && ([sv hasPrefix: _charBuffer])) + return; + + match = -1; + for (i = s + 1; i < n; i++) + { + sv = [((*lcarc)(self, lcarcSel, i, selectedColumn)) + stringValue]; + if (([sv length] > 0) + && ([sv hasPrefix: _charBuffer])) + { + match = i; + break; + } + } + if (i == n) + { + for (i = 0; i < s; i++) + { + sv = [((*lcarc)(self, lcarcSel, i, selectedColumn)) + stringValue]; + if (([sv length] > 0) + && ([sv hasPrefix: _charBuffer])) + { + match = i; + break; + } + } + } + if (match != -1) + { + [matrix deselectAllCells]; + [self selectRow: match + inColumn: selectedColumn]; + [matrix scrollCellToVisibleAtRow: match column: 0]; + [matrix performClick: self]; + return; + } + } _lastKeyPressed = 0.; } @@ -2870,9 +2896,9 @@ static BOOL browserUseBezels; [aCoder encodeInt: _columnResizing forKey: @"NSColumnResizingType"]; //[aCoder encodeInt: prefWidth forKey: @"NSPreferedColumnWidth"]; if (nil != [self columnsAutosaveName]) - { - [aCoder encodeObject: [self columnsAutosaveName] forKey: @"NSColumnsAutosaveName"]; - } + { + [aCoder encodeObject: [self columnsAutosaveName] forKey: @"NSColumnsAutosaveName"]; + } } else { @@ -2880,7 +2906,7 @@ static BOOL browserUseBezels; [aCoder encodeObject: nil]; [aCoder encodeObject:_browserCellPrototype]; [aCoder encodeObject: NSStringFromClass (_browserMatrixClass)]; - + [aCoder encodeObject:_pathSeparator]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_isLoaded]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_allowsBranchSelection]; @@ -2892,32 +2918,32 @@ static BOOL browserUseBezels; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_separatesColumns]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_takesTitleFromPreviousColumn]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_isTitled]; - - + + [aCoder encodeObject:_horizontalScroller]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_hasHorizontalScroller]; [aCoder encodeRect: _scrollerRect]; [aCoder encodeSize: _columnSize]; - + [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_acceptsArrowKeys]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_sendsActionOnArrowKeys]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_acceptsAlphaNumericalKeys]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_sendsActionOnAlphaNumericalKeys]; - + [aCoder encodeConditionalObject:_browserDelegate]; - + [aCoder encodeValueOfObjCType: @encode(SEL) at: &_doubleAction]; [aCoder encodeConditionalObject: _target]; [aCoder encodeValueOfObjCType: @encode(SEL) at: &_action]; - + [aCoder encodeObject: _browserColumns]; - + // Just encode the number of columns and the first visible // and rebuild the browser columns on the decoding side { - int colCount = [_browserColumns count]; - [aCoder encodeValueOfObjCType: @encode(int) at: &colCount]; - [aCoder encodeValueOfObjCType: @encode(int) at: &_firstVisibleColumn]; + int colCount = [_browserColumns count]; + [aCoder encodeValueOfObjCType: @encode(int) at: &colCount]; + [aCoder encodeValueOfObjCType: @encode(int) at: &_firstVisibleColumn]; } } } @@ -2932,11 +2958,11 @@ static BOOL browserUseBezels; NSString *sep = [aDecoder decodeObjectForKey: @"NSPathSeparator"]; long flags; NSSize bs; - + // Class setting _browserCellPrototype = [[[NSBrowser cellClass] alloc] init]; _browserMatrixClass = [NSMatrix class]; - + // Default values _pathSeparator = @"/"; _allowsBranchSelection = YES; @@ -2956,15 +2982,19 @@ static BOOL browserUseBezels; _sendsActionOnAlphaNumericalKeys = YES; _browserDelegate = nil; _passiveDelegate = YES; - _doubleAction = NULL; + _doubleAction = NULL; // FIXME: Seems a bit wrong to look at the current theme here bs = NSZeroSize; if (browserUseBezels) bs = [[GSTheme theme] sizeForBorderType: NSBezelBorder]; _minColumnWidth = scrollerWidth + (2 * bs.width); if (_minColumnWidth < 100.0) - _minColumnWidth = 100.0; - + _minColumnWidth = 100.0; + + // Item based delegate, 10.6+ + _itemBasedDelegate = NO; + _lastItemLoaded = nil; + // Horizontal scroller _scrollerRect.origin.x = bs.width; _scrollerRect.origin.y = bs.height; @@ -2975,76 +3005,76 @@ static BOOL browserUseBezels; [_horizontalScroller setAction: @selector(scrollViaScroller:)]; [self addSubview: _horizontalScroller]; _skipUpdateScroller = NO; - + // Columns _browserColumns = [[NSMutableArray alloc] init]; - + // Create a single column _lastColumnLoaded = -1; _firstVisibleColumn = 0; _lastVisibleColumn = 0; _maxVisibleColumns = 3; [self _createColumn]; - // end // - + // end // + [self setCellPrototype: proto]; [self setPathSeparator: sep]; [self setTitle: title ofColumn: 0]; if ([aDecoder containsValueForKey: @"NSBrFlags"]) - { - flags = [aDecoder decodeIntForKey: @"NSBrFlags"]; + { + flags = [aDecoder decodeIntForKey: @"NSBrFlags"]; - [self setHasHorizontalScroller: ((flags & 0x10000) == 0x10000)]; - [self setAllowsEmptySelection: !((flags & 0x20000) == 0x20000)]; - [self setSendsActionOnArrowKeys: ((flags & 0x40000) == 0x40000)]; - [self setAcceptsArrowKeys: ((flags & 0x100000) == 0x100000)]; - [self setSeparatesColumns: ((flags & 0x4000000) == 0x4000000)]; - [self setTakesTitleFromPreviousColumn: ((flags & 0x8000000) == 0x8000000)]; - [self setTitled: ((flags & 0x10000000) == 0x10000000)]; - [self setReusesColumns: ((flags & 0x20000000) == 0x20000000)]; - [self setAllowsBranchSelection: ((flags & 0x40000000) == 0x40000000)]; - [self setAllowsMultipleSelection: ((flags & 0x80000000) == 0x80000000)]; - } + [self setHasHorizontalScroller: ((flags & 0x10000) == 0x10000)]; + [self setAllowsEmptySelection: !((flags & 0x20000) == 0x20000)]; + [self setSendsActionOnArrowKeys: ((flags & 0x40000) == 0x40000)]; + [self setAcceptsArrowKeys: ((flags & 0x100000) == 0x100000)]; + [self setSeparatesColumns: ((flags & 0x4000000) == 0x4000000)]; + [self setTakesTitleFromPreviousColumn: ((flags & 0x8000000) == 0x8000000)]; + [self setTitled: ((flags & 0x10000000) == 0x10000000)]; + [self setReusesColumns: ((flags & 0x20000000) == 0x20000000)]; + [self setAllowsBranchSelection: ((flags & 0x40000000) == 0x40000000)]; + [self setAllowsMultipleSelection: ((flags & 0x80000000) == 0x80000000)]; + } if ([aDecoder containsValueForKey: @"NSNumberOfVisibleColumns"]) - { - [self setMaxVisibleColumns: [aDecoder decodeIntForKey: - @"NSNumberOfVisibleColumns"]]; - } + { + [self setMaxVisibleColumns: [aDecoder decodeIntForKey: + @"NSNumberOfVisibleColumns"]]; + } if ([aDecoder containsValueForKey: @"NSMinColumnWidth"]) - { - [self setMinColumnWidth: [aDecoder decodeIntForKey: @"NSMinColumnWidth"]]; - } + { + [self setMinColumnWidth: [aDecoder decodeIntForKey: @"NSMinColumnWidth"]]; + } if ([aDecoder containsValueForKey: @"NSColumnResizingType"]) - { - [self setColumnResizingType: [aDecoder decodeIntForKey: @"NSColumnResizingType"]]; - } + { + [self setColumnResizingType: [aDecoder decodeIntForKey: @"NSColumnResizingType"]]; + } if ([aDecoder containsValueForKey: @"NSPreferedColumnWidth"]) - { - //int prefWidth = [aDecoder decodeIntForKey: @"NSPreferedColumnWidth"]; - } + { + //int prefWidth = [aDecoder decodeIntForKey: @"NSPreferedColumnWidth"]; + } if ([aDecoder containsValueForKey: @"NSColumnsAutosaveName"]) - { - [self setColumnsAutosaveName: [aDecoder decodeObjectForKey: - @"NSColumnsAutosaveName"]]; - } + { + [self setColumnsAutosaveName: [aDecoder decodeObjectForKey: + @"NSColumnsAutosaveName"]]; + } } else { int colCount; - + // Here to keep compatibility with old version [aDecoder decodeObject]; _browserCellPrototype = RETAIN([aDecoder decodeObject]); _browserMatrixClass = NSClassFromString ((NSString *)[aDecoder decodeObject]); - + [self setPathSeparator: [aDecoder decodeObject]]; - + [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_isLoaded]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsBranchSelection]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsEmptySelection]; @@ -3055,7 +3085,7 @@ static BOOL browserUseBezels; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_separatesColumns]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_takesTitleFromPreviousColumn]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_isTitled]; - + //NSBox *_horizontalScrollerBox; _horizontalScroller = RETAIN([aDecoder decodeObject]); [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_hasHorizontalScroller]; @@ -3064,9 +3094,9 @@ static BOOL browserUseBezels; _skipUpdateScroller = NO; /* - _horizontalScroller = [[NSScroller alloc] initWithFrame: _scrollerRect]; - [_horizontalScroller setTarget: self]; - [_horizontalScroller setAction: @selector(scrollViaScroller:)]; + _horizontalScroller = [[NSScroller alloc] initWithFrame: _scrollerRect]; + [_horizontalScroller setTarget: self]; + [_horizontalScroller setAction: @selector(scrollViaScroller:)]; */ [self setHasHorizontalScroller: _hasHorizontalScroller]; @@ -3080,27 +3110,27 @@ static BOOL browserUseBezels; _browserDelegate = [aDecoder decodeObject]; if (_browserDelegate != nil) - [self setDelegate:_browserDelegate]; + [self setDelegate:_browserDelegate]; else - _passiveDelegate = YES; - + _passiveDelegate = YES; + [aDecoder decodeValueOfObjCType: @encode(SEL) at: &_doubleAction]; _target = [aDecoder decodeObject]; [aDecoder decodeValueOfObjCType: @encode(SEL) at: &_action]; - + // Do the minimal thing to initiate the browser... /* - _lastColumnLoaded = -1; - _firstVisibleColumn = 0; - _lastVisibleColumn = 0; - [self _createColumn]; + _lastColumnLoaded = -1; + _firstVisibleColumn = 0; + _lastVisibleColumn = 0; + [self _createColumn]; */ _browserColumns = RETAIN([aDecoder decodeObject]); // ..and rebuild any existing browser columns [aDecoder decodeValueOfObjCType: @encode(int) at: &colCount]; [aDecoder decodeValueOfObjCType: @encode(int) at: &_firstVisibleColumn]; } - + // Display even if there isn't any column _isLoaded = NO; [self tile]; @@ -3147,14 +3177,14 @@ static BOOL browserUseBezels; _acceptsAlphaNumericalKeys = flag; } -/** Returns NO if pressing an arrow key only scrolls the browser, YES if +/** Returns NO if pressing an arrow key only scrolls the browser, YES if it also sends the action message specified by setAction:. */ - (BOOL) sendsActionOnAlphaNumericalKeys { return _sendsActionOnAlphaNumericalKeys; } -/** Sets whether pressing an arrow key will cause the action message +/** Sets whether pressing an arrow key will cause the action message to be sent (in addition to causing scrolling). */ - (void) setSendsActionOnAlphaNumericalKeys: (BOOL)flag { @@ -3187,13 +3217,13 @@ static BOOL browserUseBezels; sc = [bc columnScrollView]; if (!firstResponder && [bc columnMatrix] == [_window firstResponder]) - { - firstResponder = [bc columnMatrix]; - } + { + firstResponder = [bc columnMatrix]; + } if (sc) - { - [sc removeFromSuperviewWithoutNeedingDisplay]; - } + { + [sc removeFromSuperviewWithoutNeedingDisplay]; + } } if (_firstVisibleColumn > _lastVisibleColumn) @@ -3205,49 +3235,53 @@ static BOOL browserUseBezels; if (fromFirst) { for (i = _firstVisibleColumn; i <= _lastVisibleColumn; i++) - { - bc = [_browserColumns objectAtIndex: i]; - sc = [bc columnScrollView]; - [self addSubview: sc]; + { + bc = [_browserColumns objectAtIndex: i]; + sc = [bc columnScrollView]; + [self addSubview: sc]; - if ([bc isLoaded] && [bc columnMatrix] == firstResponder) - { - [_window makeFirstResponder: firstResponder]; - setFirstResponder = YES; - } - } + if ([bc isLoaded] && [bc columnMatrix] == firstResponder) + { + [_window makeFirstResponder: firstResponder]; + setFirstResponder = YES; + } + } if (firstResponder && setFirstResponder == NO) - { - [_window makeFirstResponder: - [[_browserColumns objectAtIndex: _firstVisibleColumn] - columnMatrix]]; - } + { + [_window makeFirstResponder: + [[_browserColumns objectAtIndex: _firstVisibleColumn] + columnMatrix]]; + } } else { for (i = _lastVisibleColumn; i >= _firstVisibleColumn; i--) - { - bc = [_browserColumns objectAtIndex: i]; - sc = [bc columnScrollView]; - [self addSubview: sc]; + { + bc = [_browserColumns objectAtIndex: i]; + sc = [bc columnScrollView]; + [self addSubview: sc]; - if ([bc isLoaded] && [bc columnMatrix] == firstResponder) - { - [_window makeFirstResponder: firstResponder]; - setFirstResponder = YES; - } - } + if ([bc isLoaded] && [bc columnMatrix] == firstResponder) + { + [_window makeFirstResponder: firstResponder]; + setFirstResponder = YES; + } + } if (firstResponder && setFirstResponder == NO) - { - [_window makeFirstResponder: - [[_browserColumns objectAtIndex: _lastVisibleColumn] - columnMatrix]]; - } + { + [_window makeFirstResponder: + [[_browserColumns objectAtIndex: _lastVisibleColumn] + columnMatrix]]; + } } } +- (void) _performLoadOfItem: (id)item +{ +} + /* Loads column 'column' (asking the delegate). */ - (void) _performLoadOfColumn: (NSInteger)column { @@ -3281,9 +3315,9 @@ static BOOL browserUseBezels; // Mark all the cells as unloaded for (i = 0; i < rows; i++) - { - [[matrix cellAtRow: i column: 0] setLoaded: NO]; - } + { + [[matrix cellAtRow: i column: 0] setLoaded: NO]; + } } else { @@ -3292,11 +3326,11 @@ static BOOL browserUseBezels; // create a new col matrix matrix = [[_browserMatrixClass alloc] - initWithFrame: matrixRect - mode: NSListModeMatrix - prototype: _browserCellPrototype - numberOfRows: rows - numberOfColumns: cols]; + initWithFrame: matrixRect + mode: NSListModeMatrix + prototype: _browserCellPrototype + numberOfRows: rows + numberOfColumns: cols]; [matrix setIntercellSpacing: matrixIntercellSpace]; [matrix setAllowsEmptySelection: _allowsEmptySelection]; [matrix setAutoscroll: YES]; @@ -3306,13 +3340,13 @@ static BOOL browserUseBezels; [matrix setDrawsBackground: YES]; if (!_allowsMultipleSelection) - { - [matrix setMode: NSRadioModeMatrix]; - } + { + [matrix setMode: NSRadioModeMatrix]; + } [matrix setTarget: self]; [matrix setAction: @selector(doClick:)]; [matrix setDoubleAction: @selector(doDoubleClick:)]; - + // set new col matrix and release old [bc setColumnMatrix: matrix]; RELEASE (matrix); @@ -3328,46 +3362,46 @@ static BOOL browserUseBezels; IMP imp1 = [_browserDelegate methodForSelector: sel1]; SEL sel2 = @selector(cellAtRow:column:); IMP imp2 = [matrix methodForSelector: sel2]; - + for (i = 0; i < rows; i++) - { - aCell = (*imp2)(matrix, sel2, i, 0); - if (![aCell isLoaded]) - { - (*imp1)(_browserDelegate, sel1, self, aCell, i, - column); - [aCell setLoaded: YES]; - } - } + { + aCell = (*imp2)(matrix, sel2, i, 0); + if (![aCell isLoaded]) + { + (*imp1)(_browserDelegate, sel1, self, aCell, i, + column); + [aCell setLoaded: YES]; + } + } } else { // Tell the delegate to create the rows [_browserDelegate browser: self - createRowsForColumn: column - inMatrix: matrix]; + createRowsForColumn: column + inMatrix: matrix]; } [bc setIsLoaded: YES]; - + if (column > _lastColumnLoaded) { _lastColumnLoaded = column; } - /* Determine the height of a cell in the matrix, and set that as the + /* Determine the height of a cell in the matrix, and set that as the cellSize of the matrix. */ { NSSize cs, ms; - NSBrowserCell *b = [matrix cellAtRow: 0 column: 0]; + NSBrowserCell *b = [matrix cellAtRow: 0 column: 0]; if (b != nil) { - ms = [b cellSize]; + ms = [b cellSize]; } else { - ms = [matrix cellSize]; + ms = [matrix cellSize]; } cs = [sc contentSize]; ms.width = cs.width; @@ -3384,68 +3418,68 @@ static BOOL browserUseBezels; - (NSString *) _getTitleOfColumn: (NSInteger)column { // Ask the delegate for the column title - if ([_browserDelegate respondsToSelector: - @selector(browser:titleOfColumn:)]) + if ([_browserDelegate respondsToSelector: + @selector(browser:titleOfColumn:)]) { return [_browserDelegate browser: self titleOfColumn: column]; } - + // Check if we take title from previous column if (_takesTitleFromPreviousColumn) { id c; - + // If first column then use the path separator if (column == 0) - { - return _pathSeparator; - } - + { + return _pathSeparator; + } + // Get the selected cell // Use its string value as the title // Only if it is not a leaf if (_allowsMultipleSelection == NO) - { - c = [self selectedCellInColumn: column - 1]; - } + { + c = [self selectedCellInColumn: column - 1]; + } else - { - NSMatrix *matrix; - NSArray *selectedCells; + { + NSMatrix *matrix; + NSArray *selectedCells; - if (!(matrix = [self matrixInColumn: column - 1])) - return @""; + if (!(matrix = [self matrixInColumn: column - 1])) + return @""; - selectedCells = [matrix selectedCells]; + selectedCells = [matrix selectedCells]; - if ([selectedCells count] == 1) - { - c = [selectedCells objectAtIndex:0]; - } - else - { - return @""; - } - } + if ([selectedCells count] == 1) + { + c = [selectedCells objectAtIndex:0]; + } + else + { + return @""; + } + } if ([c isLeaf]) - { - return @""; - } + { + return @""; + } else - { - NSString *value = [c stringValue]; + { + NSString *value = [c stringValue]; - if (value != nil) - { - return value; - } - else - { - return @""; - } - } + if (value != nil) + { + return value; + } + else + { + return @""; + } + } } return @""; } From a1dd317d29c5f4faaad276cbdc9c99c49c0f9a26 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Mon, 22 Jul 2024 18:48:54 -0400 Subject: [PATCH 03/16] Add delegate calls to method _performLoadOfItem:forColumn: --- Source/NSBrowser.m | 215 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 167 insertions(+), 48 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index e2c355121..dab7ef867 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -245,7 +245,7 @@ static BOOL browserUseBezels; @interface NSBrowser (Private) - (NSString *) _getTitleOfColumn: (NSInteger)column; - (void) _performLoadOfColumn: (NSInteger)column; -- (void) _performLoadOfItem: (id)item; +- (void) _performLoadOfItem: (id)item forColumn: (NSInteger)column; - (void) _remapColumnSubviews: (BOOL)flag; - (void) _setColumnTitlesNeedDisplay; - (NSBorderType) _resolvedBorderType; @@ -954,7 +954,7 @@ static BOOL browserUseBezels; if (_itemBasedDelegate == YES) { - [self _performLoadOfItem: _lastItemLoaded]; + [self _performLoadOfItem: _lastItemLoaded forColumn: i]; } else { @@ -2257,55 +2257,55 @@ static BOOL browserUseBezels; @selector(browser:numberOfChildrenOfItem:)]) { _itemBasedDelegate = YES; - } - if ([anObject respondsToSelector: - @selector(browser:numberOfRowsInColumn:)]) - { - flag = YES; - if (![anObject respondsToSelector: - @selector(browser:willDisplayCell:atRow:column:)]) - [NSException raise: NSBrowserIllegalDelegateException - format: @"(Passive) Delegate does not respond to %s\n", - GSNameFromSelector - (@selector(browser:willDisplayCell:atRow:column:))]; - } - - if ([anObject respondsToSelector: - @selector(browser:createRowsForColumn:inMatrix:)]) - { - _passiveDelegate = NO; - - /* If flag is already set - then the delegate must respond to both methods. */ - if (flag) - { - [NSException raise: NSBrowserIllegalDelegateException - format: @"Delegate responds to both %s and %s\n", - GSNameFromSelector - (@selector(browser:numberOfRowsInColumn:)), - GSNameFromSelector - (@selector(browser:createRowsForColumn:inMatrix:))]; - } - - flag = YES; - } - - if (!flag && anObject) - [NSException raise: NSBrowserIllegalDelegateException - format: @"Delegate does not respond to %s or %s\n", - GSNameFromSelector - (@selector(browser:numberOfRowsInColumn:)), - GSNameFromSelector - (@selector(browser:createRowsForColumn:inMatrix:))]; - - _browserDelegate = anObject; - - // Get the root object after all checks have been done, if it's item based. - if (_itemBasedDelegate) - { + // Get the root object after all checks have been done, if it's item based. _lastItemLoaded = [_browserDelegate rootItemForBrowser: self]; } + else + { + if ([anObject respondsToSelector: + @selector(browser:numberOfRowsInColumn:)]) + { + flag = YES; + if (![anObject respondsToSelector: + @selector(browser:willDisplayCell:atRow:column:)]) + [NSException raise: NSBrowserIllegalDelegateException + format: @"(Passive) Delegate does not respond to %s\n", + GSNameFromSelector + (@selector(browser:willDisplayCell:atRow:column:))]; + } + + if ([anObject respondsToSelector: + @selector(browser:createRowsForColumn:inMatrix:)]) + { + _passiveDelegate = NO; + + /* If flag is already set + then the delegate must respond to both methods. */ + if (flag) + { + [NSException raise: NSBrowserIllegalDelegateException + format: @"Delegate responds to both %s and %s\n", + GSNameFromSelector + (@selector(browser:numberOfRowsInColumn:)), + GSNameFromSelector + (@selector(browser:createRowsForColumn:inMatrix:))]; + } + + flag = YES; + } + + if (!flag && anObject) + [NSException raise: NSBrowserIllegalDelegateException + format: @"Delegate does not respond to %s or %s\n", + GSNameFromSelector + (@selector(browser:numberOfRowsInColumn:)), + GSNameFromSelector + (@selector(browser:createRowsForColumn:inMatrix:))]; + } + + _browserDelegate = anObject; + NSLog(@"_browserDelegate = %@", _browserDelegate); } @@ -3279,7 +3279,126 @@ static BOOL browserUseBezels; } - (void) _performLoadOfItem: (id)item + forColumn: (NSInteger)column { + NSBrowserColumn *bc; + NSScrollView *sc; + NSMatrix *matrix; + NSInteger i, rows, cols; + + // Ask the delegate for the number of rows + rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; + cols = 1; + + bc = [_browserColumns objectAtIndex: column]; + + if (!(sc = [bc columnScrollView])) + return; + + matrix = [bc columnMatrix]; + + if (_reusesColumns && matrix) + { + [matrix renewRows: rows columns: cols]; + + // Mark all the cells as unloaded + for (i = 0; i < rows; i++) + { + [[matrix cellAtRow: i column: 0] setLoaded: NO]; + } + } + else + { + NSRect matrixRect = {{0, 0}, {100, 100}}; + NSSize matrixIntercellSpace = {0, 0}; + + // create a new col matrix + matrix = [[_browserMatrixClass alloc] + initWithFrame: matrixRect + mode: NSListModeMatrix + prototype: _browserCellPrototype + numberOfRows: rows + numberOfColumns: cols]; + [matrix setIntercellSpacing: matrixIntercellSpace]; + [matrix setAllowsEmptySelection: _allowsEmptySelection]; + [matrix setAutoscroll: YES]; + + // Set up background colors. + [matrix setBackgroundColor: [self backgroundColor]]; + [matrix setDrawsBackground: YES]; + + if (!_allowsMultipleSelection) + { + [matrix setMode: NSRadioModeMatrix]; + } + [matrix setTarget: self]; + [matrix setAction: @selector(doClick:)]; + [matrix setDoubleAction: @selector(doDoubleClick:)]; + + // set new col matrix and release old + [bc setColumnMatrix: matrix]; + RELEASE (matrix); + } + [sc setDocumentView: matrix]; + + // Loading for item based delegate + { + // Now loop through the cells and load each one + id aCell = nil; + + for (i = 0; i < rows; i++) + { + aCell = [matrix cellAtRow: i column: 0]; + if (![aCell isLoaded]) + { + BOOL leaf = YES; + id val = nil; + id child = nil; + + child = [_browserDelegate browser: self child: i ofItem: _lastItemLoaded]; + leaf = [_browserDelegate browser: self isLeafItem: child]; + val = [_browserDelegate browser: self objectValueForItem: child]; + [aCell setLeaf: leaf]; + [aCell setStringValue: val]; + [aCell setLoaded: YES]; + + _lastItemLoaded = child; + } + } + } + + [bc setIsLoaded: YES]; + + if (column > _lastColumnLoaded) + { + _lastColumnLoaded = column; + } + + /* Determine the height of a cell in the matrix, and set that as the + cellSize of the matrix. */ + { + NSSize cs, ms; + NSBrowserCell *b = [matrix cellAtRow: 0 column: 0]; + + if (b != nil) + { + ms = [b cellSize]; + } + else + { + ms = [matrix cellSize]; + } + + cs = [sc contentSize]; + ms.width = cs.width; + [matrix setCellSize: ms]; + } + + // Get the title even when untitled, as this may change later. + [self setTitle: [self _getTitleOfColumn: column] ofColumn: column]; + + // Mark for redisplay + [self displayColumn: column]; } /* Loads column 'column' (asking the delegate). */ From ffdf8fb6daf47966649557565af9df802a7e4ced Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 23 Jul 2024 13:08:35 -0400 Subject: [PATCH 04/16] Partially correct implementation --- Source/NSBrowser.m | 58 ++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index dab7ef867..bc136b037 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -3281,15 +3281,14 @@ static BOOL browserUseBezels; - (void) _performLoadOfItem: (id)item forColumn: (NSInteger)column { - NSBrowserColumn *bc; - NSScrollView *sc; - NSMatrix *matrix; - NSInteger i, rows, cols; - - // Ask the delegate for the number of rows - rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; - cols = 1; + NSBrowserColumn *bc = nil; + NSScrollView *sc = nil; + NSMatrix *matrix = nil; + NSInteger i = 0, rows = 0, cols = 1; + id child = nil; + // Ask the delegate for the number of rows for a given item... + rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; bc = [_browserColumns objectAtIndex: column]; if (!(sc = [bc columnScrollView])) @@ -3341,37 +3340,30 @@ static BOOL browserUseBezels; } [sc setDocumentView: matrix]; - // Loading for item based delegate - { - // Now loop through the cells and load each one - id aCell = nil; - - for (i = 0; i < rows; i++) - { - aCell = [matrix cellAtRow: i column: 0]; - if (![aCell isLoaded]) - { - BOOL leaf = YES; - id val = nil; - id child = nil; - - child = [_browserDelegate browser: self child: i ofItem: _lastItemLoaded]; - leaf = [_browserDelegate browser: self isLeafItem: child]; - val = [_browserDelegate browser: self objectValueForItem: child]; - [aCell setLeaf: leaf]; - [aCell setStringValue: val]; - [aCell setLoaded: YES]; - - _lastItemLoaded = child; - } - } - } + // Iterate over the rows... + for (i = 0; i < rows; i++) + { + id aCell = [matrix cellAtRow: i column: 0]; + if (![aCell isLoaded]) + { + BOOL leaf = YES; + id val = nil; + + child = [_browserDelegate browser: self child: i ofItem: _lastItemLoaded]; + leaf = [_browserDelegate browser: self isLeafItem: child]; + val = [_browserDelegate browser: self objectValueForItem: child]; + [aCell setLeaf: leaf]; + [aCell setStringValue: val]; + [aCell setLoaded: YES]; + } + } [bc setIsLoaded: YES]; if (column > _lastColumnLoaded) { _lastColumnLoaded = column; + _lastItemLoaded = child; } /* Determine the height of a cell in the matrix, and set that as the From f5decac3bae25baf62a67a349460baf985200a3a Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 24 Jul 2024 11:28:51 -0400 Subject: [PATCH 05/16] Add code to reset column if the delegate is item-based --- Source/NSBrowser.m | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index bc136b037..8298d67a4 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -1226,7 +1226,21 @@ static BOOL browserUseBezels; selectedCells = [[matrix selectedCells] copy]; // Perform the data load - [self _performLoadOfColumn: column]; + if (_itemBasedDelegate == YES) + { + if (column == 0) + { + _lastItemLoaded = [_browserDelegate rootItemForBrowser: self]; + } + + [self _performLoadOfItem: _lastItemLoaded + forColumn: column]; + } + else + { + [self _performLoadOfColumn: column]; + } + // set last column loaded [self setLastColumn: column]; @@ -2305,7 +2319,6 @@ static BOOL browserUseBezels; } _browserDelegate = anObject; - NSLog(@"_browserDelegate = %@", _browserDelegate); } From 782321e063fd1780ff57bb5e534f5c568ea61609 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 25 Jul 2024 08:12:49 -0400 Subject: [PATCH 06/16] Consolidate _performLoad methods, get the last item selected --- Headers/AppKit/NSBrowser.h | 4 +- Source/NSBrowser.m | 221 ++++++++++++------------------------- 2 files changed, 70 insertions(+), 155 deletions(-) diff --git a/Headers/AppKit/NSBrowser.h b/Headers/AppKit/NSBrowser.h index c715c82a2..30a4a2c60 100644 --- a/Headers/AppKit/NSBrowser.h +++ b/Headers/AppKit/NSBrowser.h @@ -37,13 +37,13 @@ @class NSArray; @class NSIndexPath; @class NSIndexSet; +@class NSMutableDictionary; @class NSCell; @class NSEvent; @class NSMatrix; @class NSScroller; @class NSViewController; -//@class NSBox; #if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) enum _NSBrowserColumnResizingType @@ -63,7 +63,6 @@ APPKIT_EXPORT_CLASS Class _browserMatrixClass; NSString *_pathSeparator; - //NSBox *_horizontalScrollerBox; NSScroller *_horizontalScroller; NSTimeInterval _lastKeyPressed; NSString *_charBuffer; @@ -102,7 +101,6 @@ APPKIT_EXPORT_CLASS NSBrowserColumnResizingType _columnResizing; BOOL _itemBasedDelegate; - id _lastItemLoaded; } // diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index 8298d67a4..dc3aca274 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -14,7 +14,10 @@ Date: September 2000 Author: Fred Kiefer Date: September 2002 - + Author: Gregory Casamento + Date: July 2024 + Note: Added support for 10.6+ delegate methods. + This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or @@ -34,14 +37,17 @@ Boston, MA 02110-1301, USA. */ -#include // (float)rintf(float x) +#include #import "config.h" + #import #import +#import #import #import #import #import + #import "AppKit/NSBrowser.h" #import "AppKit/NSBrowserCell.h" #import "AppKit/AppKitExceptions.h" @@ -56,8 +62,8 @@ #import "AppKit/NSEvent.h" #import "AppKit/NSWindow.h" #import "AppKit/NSBezierPath.h" -#import "GNUstepGUI/GSTheme.h" +#import "GNUstepGUI/GSTheme.h" #import "GSGuiPrivate.h" /* Cache */ @@ -245,7 +251,6 @@ static BOOL browserUseBezels; @interface NSBrowser (Private) - (NSString *) _getTitleOfColumn: (NSInteger)column; - (void) _performLoadOfColumn: (NSInteger)column; -- (void) _performLoadOfItem: (id)item forColumn: (NSInteger)column; - (void) _remapColumnSubviews: (BOOL)flag; - (void) _setColumnTitlesNeedDisplay; - (NSBorderType) _resolvedBorderType; @@ -952,15 +957,7 @@ static BOOL browserUseBezels; i = 0; } - if (_itemBasedDelegate == YES) - { - [self _performLoadOfItem: _lastItemLoaded forColumn: i]; - } - else - { - [self _performLoadOfColumn: i]; - } - + [self _performLoadOfColumn: i]; [self setLastColumn: i]; _isLoaded = YES; @@ -1226,20 +1223,7 @@ static BOOL browserUseBezels; selectedCells = [[matrix selectedCells] copy]; // Perform the data load - if (_itemBasedDelegate == YES) - { - if (column == 0) - { - _lastItemLoaded = [_browserDelegate rootItemForBrowser: self]; - } - - [self _performLoadOfItem: _lastItemLoaded - forColumn: column]; - } - else - { - [self _performLoadOfColumn: column]; - } + [self _performLoadOfColumn: column]; // set last column loaded [self setLastColumn: column]; @@ -2271,9 +2255,6 @@ static BOOL browserUseBezels; @selector(browser:numberOfChildrenOfItem:)]) { _itemBasedDelegate = YES; - - // Get the root object after all checks have been done, if it's item based. - _lastItemLoaded = [_browserDelegate rootItemForBrowser: self]; } else { @@ -2556,8 +2537,7 @@ static BOOL browserUseBezels; // Item based delegate, 10.6+ _itemBasedDelegate = NO; - _lastItemLoaded = nil; - + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_themeDidActivate:) @@ -2581,7 +2561,7 @@ static BOOL browserUseBezels; RELEASE(_horizontalScroller); RELEASE(_browserColumns); TEST_RELEASE(_charBuffer); - + [super dealloc]; } @@ -3006,7 +2986,6 @@ static BOOL browserUseBezels; // Item based delegate, 10.6+ _itemBasedDelegate = NO; - _lastItemLoaded = nil; // Horizontal scroller _scrollerRect.origin.x = bs.width; @@ -3291,121 +3270,6 @@ static BOOL browserUseBezels; } } -- (void) _performLoadOfItem: (id)item - forColumn: (NSInteger)column -{ - NSBrowserColumn *bc = nil; - NSScrollView *sc = nil; - NSMatrix *matrix = nil; - NSInteger i = 0, rows = 0, cols = 1; - id child = nil; - - // Ask the delegate for the number of rows for a given item... - rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; - bc = [_browserColumns objectAtIndex: column]; - - if (!(sc = [bc columnScrollView])) - return; - - matrix = [bc columnMatrix]; - - if (_reusesColumns && matrix) - { - [matrix renewRows: rows columns: cols]; - - // Mark all the cells as unloaded - for (i = 0; i < rows; i++) - { - [[matrix cellAtRow: i column: 0] setLoaded: NO]; - } - } - else - { - NSRect matrixRect = {{0, 0}, {100, 100}}; - NSSize matrixIntercellSpace = {0, 0}; - - // create a new col matrix - matrix = [[_browserMatrixClass alloc] - initWithFrame: matrixRect - mode: NSListModeMatrix - prototype: _browserCellPrototype - numberOfRows: rows - numberOfColumns: cols]; - [matrix setIntercellSpacing: matrixIntercellSpace]; - [matrix setAllowsEmptySelection: _allowsEmptySelection]; - [matrix setAutoscroll: YES]; - - // Set up background colors. - [matrix setBackgroundColor: [self backgroundColor]]; - [matrix setDrawsBackground: YES]; - - if (!_allowsMultipleSelection) - { - [matrix setMode: NSRadioModeMatrix]; - } - [matrix setTarget: self]; - [matrix setAction: @selector(doClick:)]; - [matrix setDoubleAction: @selector(doDoubleClick:)]; - - // set new col matrix and release old - [bc setColumnMatrix: matrix]; - RELEASE (matrix); - } - [sc setDocumentView: matrix]; - - // Iterate over the rows... - for (i = 0; i < rows; i++) - { - id aCell = [matrix cellAtRow: i column: 0]; - if (![aCell isLoaded]) - { - BOOL leaf = YES; - id val = nil; - - child = [_browserDelegate browser: self child: i ofItem: _lastItemLoaded]; - leaf = [_browserDelegate browser: self isLeafItem: child]; - val = [_browserDelegate browser: self objectValueForItem: child]; - [aCell setLeaf: leaf]; - [aCell setStringValue: val]; - [aCell setLoaded: YES]; - } - } - - [bc setIsLoaded: YES]; - - if (column > _lastColumnLoaded) - { - _lastColumnLoaded = column; - _lastItemLoaded = child; - } - - /* Determine the height of a cell in the matrix, and set that as the - cellSize of the matrix. */ - { - NSSize cs, ms; - NSBrowserCell *b = [matrix cellAtRow: 0 column: 0]; - - if (b != nil) - { - ms = [b cellSize]; - } - else - { - ms = [matrix cellSize]; - } - - cs = [sc contentSize]; - ms.width = cs.width; - [matrix setCellSize: ms]; - } - - // Get the title even when untitled, as this may change later. - [self setTitle: [self _getTitleOfColumn: column] ofColumn: column]; - - // Mark for redisplay - [self displayColumn: column]; -} - /* Loads column 'column' (asking the delegate). */ - (void) _performLoadOfColumn: (NSInteger)column { @@ -3413,8 +3277,41 @@ static BOOL browserUseBezels; NSScrollView *sc; NSMatrix *matrix; NSInteger i, rows, cols; + id child = nil; + id item = nil; + + if (_itemBasedDelegate) + { + if (column == 0) + { + item = [_browserDelegate rootItemForBrowser: self]; + } + else + { + NSInteger col = column > 1 ? column - 1 : column; - if (_passiveDelegate) + bc = [_browserColumns objectAtIndex: col]; + if (bc != nil) + { + matrix = [bc columnMatrix]; + if (matrix != nil) + { + NSArray *selectedCells = [matrix selectedCells]; + if (selectedCells != nil && [selectedCells count] > 0) + { + id cell = [selectedCells objectAtIndex: 0]; + + item = [cell objectValue]; + } + } + } + } + + // Ask the delegate for the number of rows for a given item... + rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; + cols = 1; + } + else if (_passiveDelegate) { // Ask the delegate for the number of rows rows = [_browserDelegate browser: self numberOfRowsInColumn: column]; @@ -3477,8 +3374,28 @@ static BOOL browserUseBezels; } [sc setDocumentView: matrix]; - // Loading is different based upon passive/active delegate - if (_passiveDelegate) + // Loading is different based upon item/passive/active delegate + if (_itemBasedDelegate) + { + // Iterate over the children for the item.... + for (i = 0; i < rows; i++) + { + id aCell = [matrix cellAtRow: i column: 0]; + if (![aCell isLoaded]) + { + BOOL leaf = YES; + id val = nil; + + child = [_browserDelegate browser: self child: i ofItem: item]; + leaf = [_browserDelegate browser: self isLeafItem: child]; + val = [_browserDelegate browser: self objectValueForItem: child]; + [aCell setLeaf: leaf]; + [aCell setObjectValue: val]; + [aCell setLoaded: YES]; + } + } + } + else if (_passiveDelegate) { // Now loop through the cells and load each one id aCell; From ab737b81d5463f64017054df0d445de8718ef31b Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 25 Jul 2024 08:23:06 -0400 Subject: [PATCH 07/16] Get the previous column when loading a column in item-based mode in _performLoadOfColumn --- Source/NSBrowser.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index dc3aca274..ae51806b5 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -3288,7 +3288,7 @@ static BOOL browserUseBezels; } else { - NSInteger col = column > 1 ? column - 1 : column; + NSInteger col = column > 0 ? column - 1 : column; bc = [_browserColumns objectAtIndex: col]; if (bc != nil) From 3ae1a4b41d63a70088d2530edbb6fcc7e87e23af Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 25 Jul 2024 08:39:21 -0400 Subject: [PATCH 08/16] Minor whitespace cleanup --- Source/NSBrowser.m | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index ae51806b5..303bbbc2e 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -17,7 +17,7 @@ Author: Gregory Casamento Date: July 2024 Note: Added support for 10.6+ delegate methods. - + This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or @@ -2269,12 +2269,12 @@ static BOOL browserUseBezels; GSNameFromSelector (@selector(browser:willDisplayCell:atRow:column:))]; } - + if ([anObject respondsToSelector: @selector(browser:createRowsForColumn:inMatrix:)]) { _passiveDelegate = NO; - + /* If flag is already set then the delegate must respond to both methods. */ if (flag) @@ -2286,10 +2286,10 @@ static BOOL browserUseBezels; GSNameFromSelector (@selector(browser:createRowsForColumn:inMatrix:))]; } - + flag = YES; } - + if (!flag && anObject) [NSException raise: NSBrowserIllegalDelegateException format: @"Delegate does not respond to %s or %s\n", @@ -2537,7 +2537,7 @@ static BOOL browserUseBezels; // Item based delegate, 10.6+ _itemBasedDelegate = NO; - + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_themeDidActivate:) @@ -2561,7 +2561,7 @@ static BOOL browserUseBezels; RELEASE(_horizontalScroller); RELEASE(_browserColumns); TEST_RELEASE(_charBuffer); - + [super dealloc]; } @@ -3279,7 +3279,7 @@ static BOOL browserUseBezels; NSInteger i, rows, cols; id child = nil; id item = nil; - + if (_itemBasedDelegate) { if (column == 0) @@ -3300,13 +3300,13 @@ static BOOL browserUseBezels; if (selectedCells != nil && [selectedCells count] > 0) { id cell = [selectedCells objectAtIndex: 0]; - + item = [cell objectValue]; } } } } - + // Ask the delegate for the number of rows for a given item... rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; cols = 1; @@ -3385,7 +3385,7 @@ static BOOL browserUseBezels; { BOOL leaf = YES; id val = nil; - + child = [_browserDelegate browser: self child: i ofItem: item]; leaf = [_browserDelegate browser: self isLeafItem: child]; val = [_browserDelegate browser: self objectValueForItem: child]; From b77c7052e6709872da8c45938f300de9691e536c Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Thu, 25 Jul 2024 10:18:59 -0400 Subject: [PATCH 09/16] Update changelog with NSBrowser change details --- ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index ae6603ce0..943cab4e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2024-07-25 Gregory John Casamento + + * Headers/AppKit/NSBrowser.h: Add declarations for + 10.6 delegate methods for item-based browsers. + * Source/NSBrowser.m: Add support for 10.6 item-based + delegate methods. + 2024-06-28 Gregory John Casamento * Headers/AppKit/AppKit.h: Add NSMenuToolbarItem.h From 71304617b2179cff5be6a7a0c9a00027018e1eec Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 26 Jul 2024 10:56:52 -0400 Subject: [PATCH 10/16] Move logic for finding the item for a given column to a private method, call method to get a view controller from the delegate --- Source/NSBrowser.m | 89 ++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index 303bbbc2e..2b3bdd986 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -48,26 +48,27 @@ #import #import +#import "AppKit/AppKitExceptions.h" +#import "AppKit/NSBezierPath.h" #import "AppKit/NSBrowser.h" #import "AppKit/NSBrowserCell.h" -#import "AppKit/AppKitExceptions.h" -#import "AppKit/NSScroller.h" #import "AppKit/NSCell.h" #import "AppKit/NSColor.h" #import "AppKit/NSFont.h" -#import "AppKit/NSScrollView.h" #import "AppKit/NSGraphics.h" #import "AppKit/NSMatrix.h" +#import "AppKit/NSScroller.h" +#import "AppKit/NSScrollView.h" #import "AppKit/NSTableHeaderCell.h" #import "AppKit/NSEvent.h" +#import "AppKit/NSViewController.h" #import "AppKit/NSWindow.h" -#import "AppKit/NSBezierPath.h" #import "GNUstepGUI/GSTheme.h" #import "GSGuiPrivate.h" /* Cache */ -static CGFloat scrollerWidth; // == [NSScroller scrollerWidth] +static CGFloat scrollerWidth; static NSTextFieldCell *titleCell; static CGFloat browserColumnSeparation; static CGFloat browserVerticalPadding; @@ -251,6 +252,7 @@ static BOOL browserUseBezels; @interface NSBrowser (Private) - (NSString *) _getTitleOfColumn: (NSInteger)column; - (void) _performLoadOfColumn: (NSInteger)column; +- (id) _itemForColumn: (NSInteger)column; - (void) _remapColumnSubviews: (BOOL)flag; - (void) _setColumnTitlesNeedDisplay; - (NSBorderType) _resolvedBorderType; @@ -1627,13 +1629,26 @@ static BOOL browserUseBezels; inRect: (NSRect)aRect ofColumn: (NSInteger)column { + NSViewController *vc = nil; + NSView *cv = nil; + if (!_isTitled || !NSBR_COLUMN_IS_VISIBLE(column)) return; -// [titleCell setControlView: self]; + if (_itemBasedDelegate == YES) + { + SEL sel = @selector(browser:headerViewControllerForItem:); + if ([_browserDelegate respondsToSelector: sel]) + { + id item = [self _itemForColumn: column]; + vc = [_browserDelegate browser: self headerViewControllerForItem: item]; + cv = [vc view]; + } + } + [titleCell setStringValue: title]; [titleCell drawWithFrame: aRect inView: self]; - [titleCell setControlView: nil]; + [titleCell setControlView: cv]; } /**

Returns the height of column titles. The Nextish look returns 21.

@@ -3270,6 +3285,41 @@ static BOOL browserUseBezels; } } +- (id) _itemForColumn: (NSInteger)column +{ + id item = nil; + + if (column == 0) + { + item = [_browserDelegate rootItemForBrowser: self]; + } + else + { + NSInteger col = column > 0 ? column - 1 : column; + NSBrowserColumn *bc; + + bc = [_browserColumns objectAtIndex: col]; + if (bc != nil) + { + NSMatrix *matrix; + + matrix = [bc columnMatrix]; + if (matrix != nil) + { + NSArray *selectedCells = [matrix selectedCells]; + if (selectedCells != nil && [selectedCells count] > 0) + { + id cell = [selectedCells objectAtIndex: 0]; + + item = [cell objectValue]; + } + } + } + } + + return item; +} + /* Loads column 'column' (asking the delegate). */ - (void) _performLoadOfColumn: (NSInteger)column { @@ -3282,30 +3332,7 @@ static BOOL browserUseBezels; if (_itemBasedDelegate) { - if (column == 0) - { - item = [_browserDelegate rootItemForBrowser: self]; - } - else - { - NSInteger col = column > 0 ? column - 1 : column; - - bc = [_browserColumns objectAtIndex: col]; - if (bc != nil) - { - matrix = [bc columnMatrix]; - if (matrix != nil) - { - NSArray *selectedCells = [matrix selectedCells]; - if (selectedCells != nil && [selectedCells count] > 0) - { - id cell = [selectedCells objectAtIndex: 0]; - - item = [cell objectValue]; - } - } - } - } + item = [self _itemForColumn: column]; // Ask the delegate for the number of rows for a given item... rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; From 9712490625f7d2042f31d459d01de193d0f39bc0 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 26 Jul 2024 21:24:21 -0400 Subject: [PATCH 11/16] Minor cleanup --- Source/NSBrowser.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index 2b3bdd986..58b72d5b0 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -1629,7 +1629,6 @@ static BOOL browserUseBezels; inRect: (NSRect)aRect ofColumn: (NSInteger)column { - NSViewController *vc = nil; NSView *cv = nil; if (!_isTitled || !NSBR_COLUMN_IS_VISIBLE(column)) @@ -1641,6 +1640,7 @@ static BOOL browserUseBezels; if ([_browserDelegate respondsToSelector: sel]) { id item = [self _itemForColumn: column]; + NSViewController *vc = nil; vc = [_browserDelegate browser: self headerViewControllerForItem: item]; cv = [vc view]; } From 1d266d7a9bf0a20d07d8f2ea71b502167636c80f Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 13:49:24 -0400 Subject: [PATCH 12/16] Add back informational comments --- Source/NSBrowser.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index 58b72d5b0..b3c356eb9 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -37,7 +37,7 @@ Boston, MA 02110-1301, USA. */ -#include +#include // (float)rintf(float x} #import "config.h" #import @@ -68,7 +68,7 @@ #import "GSGuiPrivate.h" /* Cache */ -static CGFloat scrollerWidth; +static CGFloat scrollerWidth; // == [NSScroller scrollerWidth]; static NSTextFieldCell *titleCell; static CGFloat browserColumnSeparation; static CGFloat browserVerticalPadding; From ddc47652ecf24ab4f3735651d1fd091de8b500f0 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 16:46:04 -0400 Subject: [PATCH 13/16] Fix indentation, per discussion with @fredkiefer --- Headers/AppKit/NSBrowser.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Headers/AppKit/NSBrowser.h b/Headers/AppKit/NSBrowser.h index 30a4a2c60..cdebc4ba7 100644 --- a/Headers/AppKit/NSBrowser.h +++ b/Headers/AppKit/NSBrowser.h @@ -359,7 +359,7 @@ canDragRowsWithIndexes: (NSIndexSet *)rowIndexes #endif #if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) - (NSInteger) browser: (NSBrowser *)browser - numberOfChildrenOfItem: (id)item; +numberOfChildrenOfItem: (id)item; - (id) browser: (NSBrowser *)browser child: (NSInteger)index ofItem: (id)item; @@ -368,17 +368,17 @@ canDragRowsWithIndexes: (NSIndexSet *)rowIndexes - (BOOL) browser: (NSBrowser *)browser shouldEditItem: (id)item; - (id) browser: (NSBrowser *)browser - objectValueForItem: (id)item; +objectValueForItem: (id)item; - (id) browser: (NSBrowser *)browser - setObjectValue: (id)object +setObjectValue: (id)object forItem: (id)item; - (id) rootItemForBrowser: (NSBrowser *)browser; - (NSViewController *) browser: (NSBrowser *)browser - previewViewControllerForLeafItem: (id)item; +previewViewControllerForLeafItem: (id)item; - (NSViewController *) browser: (NSBrowser *)browser - headerViewControllerForItem: (id)item; + headerViewControllerForItem: (id)item; - (void) browser: (NSBrowser *)browser - didChangeLastColumn: (NSInteger)oldLastColumn +didChangeLastColumn: (NSInteger)oldLastColumn toColumn: (NSInteger)column; #endif From 4e95021973156a0a103625799cd4e2467c19ee5b Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 16:59:05 -0400 Subject: [PATCH 14/16] Update to simplify code per discussion with @fredkiefer --- Source/NSBrowser.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index b3c356eb9..d5b83c233 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -3295,7 +3295,7 @@ static BOOL browserUseBezels; } else { - NSInteger col = column > 0 ? column - 1 : column; + NSInteger col = column - 1; NSBrowserColumn *bc; bc = [_browserColumns objectAtIndex: col]; From 7b78d9b64ebd90f2de5fa54d19bdc620ec996417 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 27 Jul 2024 17:19:16 -0400 Subject: [PATCH 15/16] Check for methods for an item-based delegate, per discussion with @fredkiefer --- Source/NSBrowser.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index d5b83c233..bc608750a 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -2267,8 +2267,13 @@ static BOOL browserUseBezels; _itemBasedDelegate = NO; if ([anObject respondsToSelector: - @selector(browser:numberOfChildrenOfItem:)]) + @selector(browser:numberOfChildrenOfItem:)] + && [anObject respondsToSelector: + @selector(browser:child:ofItem:)] + && [anObject respondsToSelector: + @selector(browser:isLeafItem:)]) { + _passiveDelegate = NO; _itemBasedDelegate = YES; } else From 4813800ac8c84ff0b2a6224e51c98a48251ad1b2 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 18 Aug 2024 21:04:22 -0400 Subject: [PATCH 16/16] Final fixes per discussion with @fredkiefer --- Headers/AppKit/NSBrowser.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Headers/AppKit/NSBrowser.h b/Headers/AppKit/NSBrowser.h index cdebc4ba7..06257b217 100644 --- a/Headers/AppKit/NSBrowser.h +++ b/Headers/AppKit/NSBrowser.h @@ -37,7 +37,6 @@ @class NSArray; @class NSIndexPath; @class NSIndexSet; -@class NSMutableDictionary; @class NSCell; @class NSEvent;