tableView and NSCell processing and drawing updates

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/branches/gnustep_testplant_branch@37347 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Marcian Lytwyn 2013-11-01 15:35:17 +00:00
parent 731714853b
commit 0122926822
4 changed files with 160 additions and 103 deletions

View file

@ -153,6 +153,14 @@ enum {
NSCellHitTrackableArea = 1 << 2, NSCellHitTrackableArea = 1 << 2,
}; };
enum {
NSBackgroundStyleLight = 0,
NSBackgroundStyleDark = 1,
NSBackgroundStyleRaised = 2,
NSBackgroundStyleLowered = 3
};
typedef NSInteger NSBackgroundStyle;
@interface NSCell : NSObject <NSCopying, NSCoding> @interface NSCell : NSObject <NSCopying, NSCoding>
{ {
// Attributes // Attributes
@ -199,6 +207,7 @@ enum {
unsigned subclass_bool_four: 1; unsigned subclass_bool_four: 1;
// Set while the cell is edited/selected // Set while the cell is edited/selected
unsigned in_editing: 1; unsigned in_editing: 1;
unsigned background_style: 2;
} _cell; } _cell;
NSUInteger _mouse_down_flags; NSUInteger _mouse_down_flags;
NSUInteger _action_mask; NSUInteger _action_mask;
@ -511,6 +520,8 @@ enum {
#endif #endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) #if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
- (NSBackgroundStyle)backgroundStyle;
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle;
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView; - (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView;
#endif #endif

View file

@ -2599,10 +2599,8 @@ static NSDictionary *titleTextAttributes[3] = {nil, nil, nil};
float *columnOrigins = [tableView _columnOrigins]; float *columnOrigins = [tableView _columnOrigins];
int editedRow = [tableView editedRow]; int editedRow = [tableView editedRow];
int editedColumn = [tableView editedColumn]; int editedColumn = [tableView editedColumn];
NSArray *tableColumns = [tableView tableColumns]; int startingColumn;
int startingColumn;
int endingColumn; int endingColumn;
NSTableColumn *tb;
NSRect drawingRect; NSRect drawingRect;
NSCell *cell; NSCell *cell;
int i; int i;
@ -2613,96 +2611,88 @@ static NSDictionary *titleTextAttributes[3] = {nil, nil, nil};
return; return;
} }
/* Using columnAtPoint: here would make it called twice per row per drawn
rect - so we avoid it and do it natively */
/* Determine starting column as fast as possible */
x_pos = NSMinX (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;
BOOL respondsToIsGroupRow = [[tableView delegate] respondsToSelector:@selector(tableView:isGroupRow:)]; BOOL respondsToIsGroupRow = [[tableView delegate] respondsToSelector:@selector(tableView:isGroupRow:)];
// First, determine whether the table view delegate wants this row // First, determine whether the table view delegate wants this row
// to be a grouped cell row... // to be a grouped cell row...
if (respondsToIsGroupRow && [[tableView delegate] tableView:tableView isGroupRow:rowIndex]) if (respondsToIsGroupRow && [[tableView delegate] tableView:tableView isGroupRow:rowIndex])
{ {
cell = [tableView _dataCellForTableColumn:nil row:rowIndex]; cell = [tableView preparedCellAtColumn: -1 row:rowIndex];
if (cell) if (cell)
{ {
id objectValue = [dataSource tableView: tableView objectValueForTableColumn: nil row: rowIndex]; static NSGradient *GroupCellGradient = nil;
if (GroupCellGradient == nil)
{
NSColor *startColor = [NSColor colorWithCalibratedWhite:212.0 / 255.0 alpha:1.0f];
NSColor *endColor = [NSColor colorWithCalibratedWhite:217.0 / 255.0 alpha:1.0f];
GroupCellGradient = [[NSGradient alloc] initWithStartingColor:startColor endingColor:endColor];
}
[cell _setInEditing: NO]; [cell _setInEditing: NO];
[cell setShowsFirstResponder:NO]; [cell setShowsFirstResponder:NO];
[cell setFocusRingType:NSFocusRingTypeNone]; [cell setFocusRingType:NSFocusRingTypeNone];
[cell setBackgroundStyle:NSBackgroundStyleDark];
[tableView _willDisplayCell: cell forTableColumn: nil row: rowIndex];
[cell setObjectValue: objectValue];
// Get the drawing rectangle... // Get the drawing rectangle...
drawingRect = [tableView frameOfCellAtColumn: 0 row: rowIndex]; drawingRect = [tableView frameOfCellAtColumn: 0 row: rowIndex];
// Need to draw in the background gradient - this seems to be done outside the cell drawing // Need to draw in the background gradient - this seems to be done outside the cell drawing
// on Cocoa... // on Cocoa...
static NSGradient *GroupCellGradient = nil;
if (GroupCellGradient == nil)
{
NSColor *startColor = [NSColor colorWithCalibratedWhite:212.0 / 255.0 alpha:1.0f];
NSColor *endColor = [NSColor colorWithCalibratedWhite:217.0 / 255.0 alpha:1.0f];
GroupCellGradient = [[NSGradient alloc] initWithStartingColor:startColor endingColor:endColor];
}
// Draw the group row...
[GroupCellGradient drawInRect:drawingRect angle:90.0f]; [GroupCellGradient drawInRect:drawingRect angle:90.0f];
// Draw the group row...
[cell drawWithFrame: drawingRect inView: tableView]; [cell drawWithFrame: drawingRect inView: tableView];
} }
return;
} }
else
/* Draw the row between startingColumn and endingColumn */
for (i = startingColumn; i <= endingColumn; i++)
{ {
tb = [tableColumns objectAtIndex: i]; /* Using columnAtPoint: here would make it called twice per row per drawn
cell = [tableView _dataCellForTableColumn:tb row:rowIndex]; rect - so we avoid it and do it natively */
if (i == editedColumn && rowIndex == editedRow)
{
[cell _setInEditing: YES];
[cell setShowsFirstResponder:YES];
[cell setFocusRingType:NSFocusRingTypeDefault];
}
[tableView _willDisplayCell: cell /* Determine starting column as fast as possible */
forTableColumn: tb x_pos = NSMinX (clipRect);
row: rowIndex]; i = 0;
[cell setObjectValue: [dataSource tableView: tableView while ((i < numberOfColumns) && (x_pos > columnOrigins[i]))
objectValueForTableColumn: tb {
row: rowIndex]]; i++;
drawingRect = [tableView frameOfCellAtColumn: i }
row: rowIndex]; startingColumn = (i - 1);
[cell drawWithFrame: drawingRect inView: tableView];
if (i == editedColumn && rowIndex == editedRow) 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++)
{ {
[cell _setInEditing: NO]; cell = [tableView preparedCellAtColumn: i row:rowIndex];
[cell setShowsFirstResponder:NO]; if (i == editedColumn && rowIndex == editedRow)
[cell setFocusRingType:NSFocusRingTypeNone]; {
[cell _setInEditing: YES];
[cell setShowsFirstResponder:YES];
[cell setFocusRingType:NSFocusRingTypeDefault];
}
drawingRect = [tableView frameOfCellAtColumn: i row: rowIndex];
[cell drawWithFrame: drawingRect inView: tableView];
if (i == editedColumn && rowIndex == editedRow)
{
[cell _setInEditing: NO];
[cell setShowsFirstResponder:NO];
[cell setFocusRingType:NSFocusRingTypeNone];
}
} }
} }
} }

View file

@ -1597,6 +1597,16 @@ static NSColor *dtxtCol;
*interval = 0.1; *interval = 0.1;
} }
- (NSBackgroundStyle)backgroundStyle
{
return(_cell.background_style);
}
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
{
_cell.background_style = backgroundStyle;
}
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView - (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView
{ {
NSUInteger hitResult = NSCellHitNone; NSUInteger hitResult = NSCellHitNone;
@ -1617,6 +1627,7 @@ static NSColor *dtxtCol;
NSString *stringValue = [self stringValue]; NSString *stringValue = [self stringValue];
if (stringValue && [stringValue length]) if (stringValue && [stringValue length])
{ {
// TODO: Needs to be the string rect NOT the title rect area...
NSRect checkFrame = [self titleRectForBounds:cellFrame]; NSRect checkFrame = [self titleRectForBounds:cellFrame];
if (NSPointInRect(point, checkFrame)) if (NSPointInRect(point, checkFrame))
hitResult |= NSCellHitContentArea; hitResult |= NSCellHitContentArea;
@ -2855,24 +2866,55 @@ static NSColor *dtxtCol;
are deallocated at the end of the run loop. */ are deallocated at the end of the run loop. */
- (NSDictionary*) _nonAutoreleasedTypingAttributes - (NSDictionary*) _nonAutoreleasedTypingAttributes
{ {
NSDictionary *attr; NSDictionary *attr = nil;
NSColor *color;
NSMutableParagraphStyle *paragraphStyle;
color = [self textColor]; switch (_cell.background_style)
/* Note: There are only a few possible paragraph styles for cells. {
TODO: Cache them and reuse them for the whole app lifetime. */ case NSBackgroundStyleDark:
paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; {
[paragraphStyle setLineBreakMode: [self lineBreakMode]]; NSFont *font = [NSFont fontWithName:@"LucidaGrande-Bold" size:12.0];
[paragraphStyle setBaseWritingDirection: [self baseWritingDirection]]; NSColor *color = [NSColor colorWithCalibratedWhite:0.458824 alpha:1.0];
[paragraphStyle setAlignment: [self alignment]];
/* Note: There are only a few possible paragraph styles for cells.
TODO: Cache them and reuse them for the whole app lifetime. */
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paragraphStyle setLineBreakMode: [self lineBreakMode]];
[paragraphStyle setBaseWritingDirection: [self baseWritingDirection]];
[paragraphStyle setAlignment: [self alignment]];
attr = [[NSDictionary alloc] initWithObjectsAndKeys:
font, NSFontAttributeName,
color, NSForegroundColorAttributeName,
paragraphStyle, NSParagraphStyleAttributeName,
nil];
RELEASE (paragraphStyle);
break;
}
// TODO: Add raised style settings...
case NSBackgroundStyleRaised:
// TODO: Add lowered style settings...
case NSBackgroundStyleLowered:
case NSBackgroundStyleLight:
default:
{
NSColor *color = [self textColor];
/* Note: There are only a few possible paragraph styles for cells.
TODO: Cache them and reuse them for the whole app lifetime. */
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paragraphStyle setLineBreakMode: [self lineBreakMode]];
[paragraphStyle setBaseWritingDirection: [self baseWritingDirection]];
[paragraphStyle setAlignment: [self alignment]];
attr = [[NSDictionary alloc] initWithObjectsAndKeys: attr = [[NSDictionary alloc] initWithObjectsAndKeys:
_font, NSFontAttributeName, _font, NSFontAttributeName,
color, NSForegroundColorAttributeName, color, NSForegroundColorAttributeName,
paragraphStyle, NSParagraphStyleAttributeName, paragraphStyle, NSParagraphStyleAttributeName,
nil]; nil];
RELEASE (paragraphStyle); RELEASE (paragraphStyle);
break;
}
}
return attr; return attr;
} }

View file

@ -3190,19 +3190,34 @@ byExtendingSelection: (BOOL)flag
- (NSCell *) preparedCellAtColumn: (NSInteger)columnIndex row: (NSInteger)rowIndex - (NSCell *) preparedCellAtColumn: (NSInteger)columnIndex row: (NSInteger)rowIndex
{ {
NSCell *cell = nil; NSCell *cell = nil;
NSTableColumn *tb = [_tableColumns objectAtIndex: columnIndex]; NSTableColumn *tb = nil;
// -1 on Cocoa means nil table column for group row cell...
if (columnIndex >= 0)
tb = [_tableColumns objectAtIndex: columnIndex];
if ([_delegate respondsToSelector: if ([_delegate respondsToSelector: @selector(tableView:dataCellForTableColumn:row:)])
@selector(tableView:dataCellForTableColumn:row:)])
{ {
cell = [_delegate tableView: self dataCellForTableColumn: tb cell = [_delegate tableView: self dataCellForTableColumn: tb row: rowIndex];
row: rowIndex];
} }
if (cell == nil)
// If no cell and we're requesting a non-group cell...
if ((cell == nil) && tb)
{ {
cell = [tb dataCellForRow: rowIndex]; cell = [tb dataCellForRow: rowIndex];
} }
// If we got a cell get the object value...this is done here in Cocoa...
if (cell)
{
// Get the object value from the delegate or nil...
[cell setObjectValue:[self _objectValueForTableColumn:tb row:rowIndex]];
// Inform delegate we are getting ready to display
[self _willDisplayCell: cell forTableColumn: tb row: rowIndex];
}
return cell; return cell;
} }
@ -3574,13 +3589,8 @@ static inline float computePeriod(NSPoint mouseLocationWin,
- (NSUInteger)_hitTestForEvent:(NSEvent*)event atColumn:(NSInteger)column row:(NSInteger)row - (NSUInteger)_hitTestForEvent:(NSEvent*)event atColumn:(NSInteger)column row:(NSInteger)row
{ {
NSTableColumn *tableColumn = ((column == -1) ? nil : [[self tableColumns] objectAtIndex:column]); NSCell *cell = [self preparedCellAtColumn: column row: row];
NSCell *cell = [self _dataCellForTableColumn:tableColumn row:row]; NSRect cellFrame = [self frameOfCellAtColumn:(column == -1) ? 0 : column row:row];
NSRect cellFrame = [self frameOfCellAtColumn:(column == -1) ? 0 : column row:row];
id objectValue = [self _objectValueForTableColumn:tableColumn row:row];
// Initialize object value for data cell...
[cell setObjectValue:objectValue];
// Return the hit result... // Return the hit result...
return([cell hitTestForEvent:event inRect:cellFrame ofView:self]); return([cell hitTestForEvent:event inRect:cellFrame ofView:self]);
@ -3619,13 +3629,17 @@ static inline float computePeriod(NSPoint mouseLocationWin,
if ([theEvent type] == NSLeftMouseDown) if ([theEvent type] == NSLeftMouseDown)
{ {
// If the cell processed the mouse hit... // If the cell processed the mouse hit...
BOOL isGrouped = [[self delegate] tableView:self isGroupRow:_clickedRow]; NSInteger theColumn = _clickedColumn;
NSInteger theColumn = (isGrouped ? -1 : _clickedColumn); BOOL responds = [[self delegate] respondsToSelector: @selector(tableView:isGroupRow:)];
NSUInteger hitResult = [self _hitTestForEvent:theEvent atColumn:theColumn row:_clickedRow];
// Check for grouped row...
if (responds && [[self delegate] tableView:self isGroupRow:_clickedRow])
theColumn = -1;
// Application specific hit test processing is handled within the delegate's should select callbacks // Application specific hit test processing is handled within the delegate's should select callbacks
// if they're implemented...however - I'm not sure when this SHOULD be invoked... // if they're implemented...however - I'm not sure when this SHOULD be invoked...
[self _shouldSelectRow:_clickedRow]; if ([self _hitTestForEvent:theEvent atColumn:theColumn row:_clickedRow] != NSCellHitNone)
[self _shouldSelectRow:_clickedRow];
} }
if ([theEvent type] == NSLeftMouseDown if ([theEvent type] == NSLeftMouseDown