From 9dc09bed613c8eb79f26789ff4bf2cf3123d28ef Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 16 Apr 2023 21:47:44 -0400 Subject: [PATCH] Move Outline drawing code to GSThemeDrawing category --- Headers/Additions/GNUstepGUI/GSTheme.h | 4 + Source/GSBindingHelpers.h | 1 + Source/GSThemeDrawing.m | 173 ++++++++++++++++++++++++- Source/NSOutlineView.m | 172 +++++------------------- Source/NSTableView.m | 5 + 5 files changed, 208 insertions(+), 147 deletions(-) diff --git a/Headers/Additions/GNUstepGUI/GSTheme.h b/Headers/Additions/GNUstepGUI/GSTheme.h index 792ffb4b6..b555a66cc 100644 --- a/Headers/Additions/GNUstepGUI/GSTheme.h +++ b/Headers/Additions/GNUstepGUI/GSTheme.h @@ -1324,6 +1324,10 @@ APPKIT_EXPORT_CLASS clipRect: (NSRect)clipRect inView: (NSView *)view; +- (void) drawOutlineViewRow: (NSInteger)rowIndex + clipRect: (NSRect)clipRect + inView: (NSView *)view; + - (void) drawBoxInClipRect: (NSRect)clipRect boxType: (NSBoxType)boxType borderType: (NSBorderType)borderType diff --git a/Source/GSBindingHelpers.h b/Source/GSBindingHelpers.h index 47bdb0f66..3d1a72fb1 100644 --- a/Source/GSBindingHelpers.h +++ b/Source/GSBindingHelpers.h @@ -62,6 +62,7 @@ - (void) setValueFor: (NSString *)binding; - (void) reverseSetValue: (id)value; - (void) reverseSetValueFor: (NSString *)binding; +- (id) observedObject; - (id) destinationValue; - (id) sourceValueFor: (NSString *)binding; diff --git a/Source/GSThemeDrawing.m b/Source/GSThemeDrawing.m index 9a411bfa6..5d281be5b 100644 --- a/Source/GSThemeDrawing.m +++ b/Source/GSThemeDrawing.m @@ -44,6 +44,7 @@ #import "AppKit/NSImage.h" #import "AppKit/NSMenuView.h" #import "AppKit/NSMenuItemCell.h" +#import "AppKit/NSOutlineView.h" #import "AppKit/NSParagraphStyle.h" #import "AppKit/NSPopUpButtonCell.h" #import "AppKit/NSProgressIndicator.h" @@ -62,6 +63,7 @@ #import "AppKit/NSPathCell.h" #import "AppKit/NSPathControl.h" #import "AppKit/NSPathComponentCell.h" + #import "GNUstepGUI/GSToolbarView.h" #import "GNUstepGUI/GSTitleView.h" @@ -69,8 +71,15 @@ /* 7.0 gives us the NeXT Look (which is 8 pix wide including the shadow) */ #define COLOR_WELL_BORDER_WIDTH 7.0 +@interface NSOutlineView (Private) +- (void) _willDisplayCell: (NSCell*)cell + forTableColumn: (NSTableColumn *)tb + item: (id)item; +@end + @interface NSTableView (Private) -- (CGFloat *)_columnOrigins; +- (NSUInteger) _numberOfRows; +- (CGFloat *) _columnOrigins; - (void) _willDisplayCell: (NSCell*)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index; @@ -3355,10 +3364,7 @@ static NSDictionary *titleTextAttributes[3] = {nil, nil, nil}; inView: (NSView *)view { NSTableView *tableView = (NSTableView *)view; - // NSInteger numberOfRows = [tableView numberOfRows]; NSInteger numberOfColumns = [tableView numberOfColumns]; - // NSIndexSet *selectedRows = [tableView selectedRowIndexes]; - // NSColor *backgroundColor = [tableView backgroundColor]; CGFloat *columnOrigins = [tableView _columnOrigins]; NSInteger editedRow = [tableView editedRow]; NSInteger editedColumn = [tableView editedColumn]; @@ -3451,6 +3457,165 @@ static NSDictionary *titleTextAttributes[3] = {nil, nil, nil}; } } +- (void) drawOutlineViewRow: (NSInteger)rowIndex + clipRect: (NSRect)clipRect + inView: (NSView *)view +{ + static NSImage *collapsed = nil; + static NSImage *expanded = nil; + static NSImage *unexpandable = nil; + + NSOutlineView *ov = (NSOutlineView *)view; + NSCell *imageCell = nil; + NSRect imageRect; + NSInteger numberOfRows = [ov _numberOfRows]; + NSInteger numberOfColumns = [ov numberOfColumns]; + CGFloat *columnOrigins = [ov _columnOrigins]; + NSInteger editedRow = [ov editedRow]; + NSInteger editedColumn = [ov editedColumn]; + NSArray *tableColumns = [ov tableColumns]; + NSInteger startingColumn; + NSInteger endingColumn; + NSRect drawingRect; + CGFloat x_pos; + NSTableColumn *outlineTableColumn = [ov outlineTableColumn]; + NSInteger i = 0; + CGFloat indentationPerLevel = [ov indentationPerLevel]; + + if (expanded == nil) + { +#if 0 + /* Old Interface Builder style. */ + collapsed = [NSImage imageNamed: @"common_outlineCollapsed"]; + expanded = [NSImage imageNamed: @"common_outlineExpanded"]; + unexpandable = [NSImage imageNamed: @"common_outlineUnexpandable"]; +#else + /* Current OSX style images. */ + // FIXME ... better ones? + collapsed = [NSImage imageNamed: @"common_ArrowRightH"]; + expanded = [NSImage imageNamed: @"common_ArrowDownH"]; + unexpandable = [[NSImage alloc] initWithSize: [expanded size]]; +#endif + } + + if (rowIndex >= numberOfRows) + { + return; + } + + /* Determine starting column as fast as possible */ + x_pos = NSMinX (clipRect); + i = 0; + while ((i < numberOfColumns) && (x_pos > columnOrigins[i])) + { + i++; + } + startingColumn = (i - 1); + + if (startingColumn == -1) + startingColumn = 0; + + /* Determine ending column as fast as possible */ + x_pos = NSMaxX (clipRect); + // Nota Bene: we do *not* reset i + while ((i < numberOfColumns) && (x_pos > columnOrigins[i])) + { + i++; + } + endingColumn = (i - 1); + + if (endingColumn == -1) + endingColumn = numberOfColumns - 1; + + /* Draw the row between startingColumn and endingColumn */ + for (i = startingColumn; i <= endingColumn; i++) + { + id item = [ov itemAtRow: rowIndex]; + NSTableColumn *tb = [tableColumns objectAtIndex: i]; + NSCell *cell = [ov preparedCellAtColumn: i row: rowIndex]; + + [ov _willDisplayCell: cell + forTableColumn: tb + row: rowIndex]; + + if (i == editedColumn && rowIndex == editedRow) + { + [cell _setInEditing: YES]; + [cell setShowsFirstResponder: YES]; + } + else + { + id value = nil; + + value = [ov _objectValueForTableColumn: tb + row: rowIndex]; + NSLog(@"value = %@", value); + [cell setObjectValue: value]; + } + + drawingRect = [ov frameOfCellAtColumn: i + row: rowIndex]; + + if (tb == outlineTableColumn) + { + NSImage *image = nil; + NSInteger level = 0; + CGFloat indentationFactor = 0.0; + + // display the correct arrow... + if ([ov isItemExpanded: item]) + { + image = expanded; + } + else + { + image = collapsed; + } + + if (![ov isExpandable: item]) + { + image = unexpandable; + } + + level = [ov levelForItem: item]; + indentationFactor = indentationPerLevel * level; + imageCell = [[NSCell alloc] initImageCell: image]; + imageRect = [ov frameOfOutlineCellAtRow: rowIndex]; + + [ov _willDisplayCell: cell + forTableColumn: tb + item: item]; + + /* Do not indent if the delegate set the image to nil. */ + if ([imageCell image]) + { + imageRect.size.width = [image size].width; + imageRect.size.height = [image size].height; + [imageCell drawWithFrame: imageRect inView: ov]; + drawingRect.origin.x + += indentationFactor + imageRect.size.width + 5; + drawingRect.size.width + -= indentationFactor + imageRect.size.width + 5; + } + else + { + drawingRect.origin.x += indentationFactor; + drawingRect.size.width -= indentationFactor; + } + + RELEASE(imageCell); + } + + [cell drawWithFrame: drawingRect inView: ov]; + if (i == editedColumn && rowIndex == editedRow) + { + [cell _setInEditing: NO]; + [cell setShowsFirstResponder: NO]; + } + } +} + + - (void) drawBoxInClipRect: (NSRect)clipRect boxType: (NSBoxType)boxType borderType: (NSBorderType)borderType diff --git a/Source/NSOutlineView.m b/Source/NSOutlineView.m index 6da7a065d..4c2a62b2e 100644 --- a/Source/NSOutlineView.m +++ b/Source/NSOutlineView.m @@ -72,6 +72,8 @@ #import "GSFastEnumeration.h" #import "GSGuiPrivate.h" +#import "GNUstepGUI/GSTheme.h" + #include static NSMapTableKeyCallBacks keyCallBacks; @@ -92,12 +94,6 @@ static NSMutableSet *autoExpanded = nil; static NSDate *lastDragUpdate = nil; static NSDate *lastDragChange = nil; - -// Cache the arrow images... -static NSImage *collapsed = nil; -static NSImage *expanded = nil; -static NSImage *unexpandable = nil; - @interface NSOutlineView (NotificationRequestMethods) - (void) _postSelectionIsChangingNotification; - (void) _postSelectionDidChangeNotification; @@ -145,6 +141,11 @@ static NSImage *unexpandable = nil; @implementation NSOutlineView +// Cache the arrow images... +static NSImage *collapsed = nil; +static NSImage *expanded = nil; +static NSImage *unexpandable = nil; + // Initialize the class when it is loaded + (void) initialize { @@ -162,18 +163,20 @@ static NSImage *unexpandable = nil; [self exposeBinding: NSContentBinding]; [self exposeBinding: NSSelectionIndexesBinding]; [self exposeBinding: NSSortDescriptorsBinding]; + #if 0 -/* Old Interface Builder style. */ + /* Old Interface Builder style. */ collapsed = [NSImage imageNamed: @"common_outlineCollapsed"]; expanded = [NSImage imageNamed: @"common_outlineExpanded"]; unexpandable = [NSImage imageNamed: @"common_outlineUnexpandable"]; #else -/* Current OSX style images. */ -// FIXME ... better ones? + /* Current OSX style images. */ + // FIXME ... better ones? collapsed = [NSImage imageNamed: @"common_ArrowRightH"]; expanded = [NSImage imageNamed: @"common_ArrowDownH"]; unexpandable = [[NSImage alloc] initWithSize: [expanded size]]; #endif + autoExpanded = [NSMutableSet new]; } } @@ -969,138 +972,9 @@ static NSImage *unexpandable = nil; */ - (void) drawRow: (NSInteger)rowIndex clipRect: (NSRect)aRect { - NSInteger startingColumn; - NSInteger endingColumn; - NSRect drawingRect; - NSCell *imageCell = nil; - NSRect imageRect; - NSInteger i; - CGFloat x_pos; - - // If there is no data source and no binding there is nothing to do. - if (_dataSource == nil && _theBinding == nil) - { - return; - } - - /* Using columnAtPoint: here would make it called twice per row per drawn - rect - so we avoid it and do it natively */ - - if (rowIndex >= _numberOfRows) - { - return; - } - - /* Determine starting column as fast as possible */ - x_pos = NSMinX (aRect); - i = 0; - while ((i < _numberOfColumns) && (x_pos > _columnOrigins[i])) - { - i++; - } - startingColumn = (i - 1); - - if (startingColumn == -1) - startingColumn = 0; - - /* Determine ending column as fast as possible */ - x_pos = NSMaxX (aRect); - // Nota Bene: we do *not* reset i - while ((i < _numberOfColumns) && (x_pos > _columnOrigins[i])) - { - i++; - } - endingColumn = (i - 1); - - if (endingColumn == -1) - endingColumn = _numberOfColumns - 1; - - /* Draw the row between startingColumn and endingColumn */ - for (i = startingColumn; i <= endingColumn; i++) - { - id item = [self itemAtRow: rowIndex]; - NSTableColumn *tb = [_tableColumns objectAtIndex: i]; - NSCell *cell = [self preparedCellAtColumn: i row: rowIndex]; - - [self _willDisplayCell: cell - forTableColumn: tb - row: rowIndex]; - if (i == _editedColumn && rowIndex == _editedRow) - { - [cell _setInEditing: YES]; - [cell setShowsFirstResponder: YES]; - } - else - { - [cell setObjectValue: [_dataSource outlineView: self - objectValueForTableColumn: tb - byItem: item]]; - } - drawingRect = [self frameOfCellAtColumn: i - row: rowIndex]; - - if (tb == _outlineTableColumn) - { - NSImage *image = nil; - NSInteger level = 0; - CGFloat indentationFactor = 0.0; - // float originalWidth = drawingRect.size.width; - - // display the correct arrow... - if ([self isItemExpanded: item]) - { - image = expanded; - } - else - { - image = collapsed; - } - - if (![self isExpandable: item]) - { - image = unexpandable; - } - - level = [self levelForItem: item]; - indentationFactor = _indentationPerLevel * level; - imageCell = [[NSCell alloc] initImageCell: image]; - imageRect = [self frameOfOutlineCellAtRow: rowIndex]; - - if ([_delegate respondsToSelector: @selector(outlineView:willDisplayOutlineCell:forTableColumn:item:)]) - { - [_delegate outlineView: self - willDisplayOutlineCell: imageCell - forTableColumn: tb - item: item]; - } - - /* Do not indent if the delegate set the image to nil. */ - if ([imageCell image]) - { - imageRect.size.width = [image size].width; - imageRect.size.height = [image size].height; - [imageCell drawWithFrame: imageRect inView: self]; - drawingRect.origin.x - += indentationFactor + imageRect.size.width + 5; - drawingRect.size.width - -= indentationFactor + imageRect.size.width + 5; - } - else - { - drawingRect.origin.x += indentationFactor; - drawingRect.size.width -= indentationFactor; - } - - RELEASE(imageCell); - } - - [cell drawWithFrame: drawingRect inView: self]; - if (i == _editedColumn && rowIndex == _editedRow) - { - [cell _setInEditing: NO]; - [cell setShowsFirstResponder: NO]; - } - } + [[GSTheme theme] drawOutlineViewRow: rowIndex + clipRect: aRect + inView: self]; } - (void) drawRect: (NSRect)aRect @@ -1903,11 +1777,20 @@ Also returns the child index relative to this parent. */ - (void) _willDisplayCell: (NSCell*)cell forTableColumn: (NSTableColumn *)tb row: (NSInteger)index +{ + id item = [self itemAtRow: index]; + + [self _willDisplayCell: cell + forTableColumn: tb + item: item]; +} + +- (void) _willDisplayCell: (NSCell*)cell + forTableColumn: (NSTableColumn *)tb + item: (id)item { if (_del_responds) { - id item = [self itemAtRow: index]; - [_delegate outlineView: self willDisplayCell: cell forTableColumn: tb @@ -1990,6 +1873,9 @@ Also returns the child index relative to this parent. */ { if (_theBinding != nil) { + // NSUInteger c = [(NSArray *)[_theBinding destinationValue] count]; + // NSLog(@"*** numRows = %ld", c); + // return c; return [(NSArray *)[_theBinding destinationValue] count]; } diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 7419886f4..773abf45c 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -5811,6 +5811,11 @@ This method is deprecated, use -columnIndexesInRect:. */ [[_tableColumns objectAtIndex: index] setWidth: width]; } +- (NSInteger) _numberOfRows +{ + return _numberOfRows; +} + - (CGFloat *) _columnOrigins { return _columnOrigins;