From 201fda96a5a7c5f286fd2e0a0f6f839974a54cf0 Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Thu, 18 Jun 2009 16:56:49 -0700 Subject: [PATCH] Getting something on the screen. Reviewed by me. --- AppKit/NEWCPTableColumn.j | 21 ++- AppKit/NEWCPTableView.j | 275 ++++++++++++++++++++++++++++++++++---- TableTest/AppController.j | 65 ++++----- 3 files changed, 299 insertions(+), 62 deletions(-) diff --git a/AppKit/NEWCPTableColumn.j b/AppKit/NEWCPTableColumn.j index 38513111b..6f5bc33ce 100644 --- a/AppKit/NEWCPTableColumn.j +++ b/AppKit/NEWCPTableColumn.j @@ -27,6 +27,8 @@ CPTableColumnUserResizingMask = 2; { CPTableView _tableView; CPView _headerView; + CPView _dataView; + Object _dataViewData; float _width; float _minWidth; @@ -45,8 +47,15 @@ CPTableColumnUserResizingMask = 2; if (self) { + _dataViewData = { }; + + _width = 100.0; + _minWidth = 10.0; + _maxWidth = 1000000.0; + [self setIdentifier:anIdentifier]; [self setHeaderView:[CPTableHeaderView new]]; + [self setDataView:[CPTextField new]]; } return self @@ -162,7 +171,7 @@ CPTableColumnUserResizingMask = 2; { if (!aView) [CPException raise:CPInvalidArgumentException reason:@"Attempt to set nil header view on " + [self description]]; - + _headerView = aView; } @@ -190,7 +199,7 @@ CPTableColumnUserResizingMask = 2; /* Returns the CPView object used by the CPTableView to draw values for the receiver. - + By default, this method just calls dataView. Subclassers can override if they need to potentially use different cells for different rows. Subclasses should expect this method to be invoked with row equal to -1 in cases where no actual row is involved but the table @@ -204,7 +213,7 @@ CPTableColumnUserResizingMask = 2; - (id)_newDataViewForRow:(int)aRowIndex { var dataView = [self dataViewForRow:aRowIndex], - dataViewUID = [view UID]; + dataViewUID = [dataView UID]; // if we haven't cached an archive of the data view, do it now if (!_dataViewData[dataViewUID]) @@ -213,7 +222,7 @@ CPTableColumnUserResizingMask = 2; // unarchive the data view cache var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]]; - return newView; + return newDataView; } //Setting the Identifier @@ -232,7 +241,7 @@ CPTableColumnUserResizingMask = 2; - (id)identifier { return _identifier; -} +} //Controlling Editability @@ -252,7 +261,7 @@ CPTableColumnUserResizingMask = 2; { return _isEditable; } - + //Sorting - (void)setSortDescriptorPrototype:(CPSortDescriptor)aSortDescriptor { diff --git a/AppKit/NEWCPTableView.j b/AppKit/NEWCPTableView.j index a605012f1..edf020fc0 100644 --- a/AppKit/NEWCPTableView.j +++ b/AppKit/NEWCPTableView.j @@ -4,6 +4,8 @@ @import "CPControl.j" @import "CPTableColumn.j" +#include "CoreGraphics/CGGeometry.h" + var CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_ = 1 << 2, @@ -50,6 +52,10 @@ CPTableViewSelectionHighlightStyleSourceList = 1; CPInteger _implementedDelegateMethods; CPArray _tableColumns; + CPArray _tableColumnRanges; + CPInteger _dirtyTableColumnRangeIndex; + + Object _objectValues; //Configuring Behavior BOOL _allowsColumnReordering; @@ -65,8 +71,6 @@ CPTableViewSelectionHighlightStyleSourceList = 1; unsigned _currentHighlightedTableColumn; unsigned _numberOfRows; - unsigned _numberOfColumns; - } - (id)initWithFrame:(CGRect)aFrame @@ -86,6 +90,14 @@ CPTableViewSelectionHighlightStyleSourceList = 1; // _selectionHighlightMask = CPTableViewSelectionHighlightStyleRegular; _tableColumns = []; + _tableColumnRanges = []; + _dirtyTableColumnRangeIndex = CPNotFound; + + _objectValues = { }; + _numberOfRows = 0; + + _intercellSpacing = _CGSizeMake(0.0, 0.0); + _rowHeight = 24.0; } return self; @@ -137,7 +149,13 @@ CPTableViewSelectionHighlightStyleSourceList = 1; - (void)reloadData { + if (!_dataSource) + return; + _numberOfRows = [_dataSource numberOfRowsInTableView:self]; + _objectValues = { }; + + [self layoutSubviews]; } //Target-action Behavior @@ -220,6 +238,10 @@ CPTableViewSelectionHighlightStyleSourceList = 1; [self setNeedsLayout]; } +- (void)setThemeState:(int)astae +{ +} + - (CGSize)intercellSpacing { return _CGSizeMakeCopy(_intercellSpacing); @@ -282,12 +304,29 @@ CPTableViewSelectionHighlightStyleSourceList = 1; { [_tableColumns addObject:aTableColumn]; + if (_dirtyTableColumnRangeIndex < 0) + _dirtyTableColumnRangeIndex = _tableColumns.length - 1; + else + _dirtyTableColumnRangeIndex = MIN(_tableColumns.length - 1, _dirtyTableColumnRangeIndex); + [self setNeedsLayout]; } - (void)removeTableColumn:(CPTableColumn)aTableColumn { - [_tableColumns removeObjectIdenticalTo:aTableColumn]; + var index = [_tableColumns indeOfObjectIdenticalTo:aTableColumn]; + + [_tableColumns removeObjectAtIndex:index]; + + var tableColumnUID = [aTableColumn UID]; + + if (_objectValues[tableColumnUID]) + _objectValues[tableColumnUID] = nil; + + if (_dirtyTableColumnRangeIndex < 0) + _dirtyTableColumnRangeIndex = index; + else + _dirtyTableColumnRangeIndex = MIN(index, _dirtyTableColumnRangeIndex); [self setNeedsLayout]; } @@ -300,6 +339,11 @@ CPTableViewSelectionHighlightStyleSourceList = 1; if (fromIndex === toIndex) return; + if (_dirtyTableColumnRangeIndex < 0) + _dirtyTableColumnRangeIndex = MIN(fromIndex, toIndex); + else + _dirtyTableColumnRangeIndex = MIN(fromIndex, toIndex, _dirtyTableColumnRangeIndex); + if (toIndex > fromIndex) --toIndex; @@ -393,26 +437,138 @@ CPTableViewSelectionHighlightStyleSourceList = 1; * Ð cornerView */ //Layout Support -/* -- (void)_recalculateTableColumnRects + +- (void)_recalculateTableColumnRanges { - for () - _tabelColumnWidths[index] = CGRectMake(); + if (_dirtyTableColumnRangeIndex < 0) + return; + + var index = _dirtyTableColumnRangeIndex, + count = _tableColumns.length, + x = index === 0 ? 0.0 : CPMaxRange(_tableColumnRanges[index - 1]); + + for (; index < count; ++index) + { + var tableColumn = _tableColumns[index]; + + if ([tableColumn isHidden]) + _tableColumnRanges[index] = CPMakeRange(x, 0.0); + + else + { + var width = [_tableColumns[index] width]; + + _tableColumnRanges[index] = CPMakeRange(x, width); + + x += width; + } + } + + _tableColumnRanges.length = count; + _dirtyTableColumnRangeIndex = CPNotFound; } - (CGRect)rectOfColumn:(CPInteger)aColumnIndex { - if (?) - [self _recalculateTableColumnRects]; + aColumnIndex = +aColumnIndex; - return CGRectMake(_tableColumnWidth[aColumnIndex]; + if (aColumnIndex < 0 || aColumnIndex >= _tableColumns.length) + return _CGRectMakeZero(); + + if (_dirtyTableColumnRangeIndex !== CPNotFound) + [self _recalculateTableColumnRanges]; + + var range = _tableColumnRanges[aColumnIndex]; + + return _CGRectMake(range.location, 0.0, range.length, CGRectGetHeight([self bounds])); } - * Ð rectOfRow: - * Ð rowsInRect: - * Ð columnIndexesInRect: - * Ð columnAtPoint: - * Ð rowAtPoint: +- (CGRect)rectOfRow:(CPInteger)aRowIndex +{ + if (NO) + return NULL; + + return _CGRectMake(0.0, (aRowIndex * (_rowHeight + _intercellSpacing.height)), _CGRectGetWidth([self bounds]), _rowHeight); +} + +- (CPRange)rowsInRect:(CGRect)aRect +{ + return CPMakeRange( MAX(0, [self rowAtPoint:aRect.origin]), + MIN(_numberOfRows, [self rowAtPoint:_CGPointMake(_CGRectGetMaxX(aRect), _CGRectGetMaxY(aRect))])); +} + +- (CPIndexSet)columnIndexesInRect:(CGRect)aRect +{ + var indexSet = [CPIndexSet indexSet], + column = MAX(0, [self columnAtPoint:_CGPointMake(aRect.origin.x, 0.0)]), + lastColumn = [self columnAtPoint:_CGPointMake(_CGRectGetMaxX(aRect), 0.0)]; + + if (lastColumn === CPNotFound) + lastColumn = [self numberOfColumns] - 1; + + for (; column <= lastColumn; ++column) + { + var tableColumn = _tableColumns[column]; + + if (![tableColumn isHidden]) + [indexSet addIndex:column]; + } + + return indexSet; +} + +- (CPInteger)columnAtPoint:(CGPoint)aPoint +{ + if (!CGRectContainsPoint([self bounds], aPoint)) + return CPNotFound; + + if (_dirtyTableColumnRangeIndex !== CPNotFound) + [self _recalculateTableColumnRanges]; + + var x = aPoint.x, + low = 0, + high = _tableColumnRanges.length - 1; + + while (low <= high) + { + var middle = FLOOR(low + (high - low) / 2), + range = _tableColumnRanges[middle]; + + if (x < range.location) + high = middle - 1; + + else if (x > CPMaxRange(range)) + low = middle + 1; + + else + { + var numberOfColumns = _tableColumnRanges.length; + + while (middle < numberOfColumns && [_tableColumns[middle] isHidden]) + ++middle; + + if (middle < numberOfColumns) + return middle; + + return CPNotFound; + } + } + + return CPNotFound; +} + +- (CPInteger)rowAtPoint:(CGPoint)aPoint +{ + var y = aPoint.y; + + if (NO) + { + } + + return FLOOR(y / (_rowHeight + _intercellSpacing.height)); +} + +/* * Ð frameOfCellAtColumn:row: * Ð columnAutoresizingStyle * Ð setColumnAutoresizingStyle: @@ -421,15 +577,6 @@ CPTableViewSelectionHighlightStyleSourceList = 1; * Ð tile * Ð sizeToFit * Ð noteHeightOfRowsWithIndexesChanged: - * Ð tableView:heightOfRow: delegate method - * Ð columnsInRect: Deprecated in Mac OS X v10.5 -*/ -//Drawing -/* - * Ð drawRow:clipRect: - * Ð drawGridInClipRect: - * Ð highlightSelectionInClipRect: - * Ð drawBackgroundInClipRect: */ //Scrolling /* @@ -575,7 +722,7 @@ CPTableViewSelectionHighlightStyleSourceList = 1; /* Ð (CPTableColumn)highlightedTableColumn { - + } * Ð setHighlightedTableColumn: @@ -604,9 +751,85 @@ CPTableViewSelectionHighlightStyleSourceList = 1; * Ð textDidEndEditing: */ +- (id)_objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex +{ + var tableColumnUID = [aTableColumn UID], + tableColumnObjectValues = _objectValues[tableColumnUID]; + + if (!tableColumnObjectValues) + { + tableColumnObjectValues = []; + _objectValues[tableColumnUID] = tableColumnObjectValues; + } + + var objectValue = tableColumnObjectValues[aRowIndex]; + + if (objectValue === undefined) + { + objectValue = [_dataSource tableView:self objectValueForTableColumn:aTableColumn row:aRowIndex]; + tableColumnObjectValues[aRowIndex] = objectValue; + } + + return objectValue; +} + +- (CGRect)_exposedRect +{ + var superview = [self superview]; + + if (!superview) + return [self bounds]; + + return [self convertRect:CGRectIntersection([superview bounds], [self frame]) fromView:superview]; +} + +- (void)load +{console.log("logging."); + if (!_dataSource) + { + // remove? + return; + } + + // SLOWMO + var subviews = [self subviews], + count = [subviews count]; + + while (count--) + [subviews[count] removeFromSuperview]; + + var exposedRect = [self _exposedRect], + exposedRows = [self rowsInRect:exposedRect], + exposedColumns = [self columnIndexesInRect:exposedRect], + columnIndex = [exposedColumns firstIndex]; + + while (columnIndex !== CPNotFound) + { + var tableColumn = _tableColumns[columnIndex], + tableColumnRange = _tableColumnRanges[columnIndex]; + + var rowIndex = exposedRows.location, + lastRowIndex = CPMaxRange(exposedRows); + + for (; rowIndex < lastRowIndex; ++rowIndex) + { + var dataView = [tableColumn _newDataViewForRow:rowIndex], + rectOfRow = [self rectOfRow:rowIndex]; + + [dataView setBackgroundColor:[CPColor redColor]]; + [dataView setFrame:_CGRectMake(tableColumnRange.location, _CGRectGetMinY(rectOfRow), tableColumnRange.length, _CGRectGetHeight(rectOfRow))]; + [dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:rowIndex]]; + + [self addSubview:dataView]; + } + + columnIndex = [exposedColumns indexGreaterThanIndex:columnIndex]; + } +} + - (void)layoutSubviews { - + [self load]; } @end diff --git a/TableTest/AppController.j b/TableTest/AppController.j index 97e6e1ba4..79c6cd957 100644 --- a/TableTest/AppController.j +++ b/TableTest/AppController.j @@ -1,14 +1,15 @@ -import -import +@import +@import +@import + CPLogRegister(CPLogConsole); @implementation AppController : CPObject { - CPTableView _tableView; - CPArray _data; - CPImage _iconImage; + CPTableView tableView; + CPImage iconImage; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification @@ -18,42 +19,45 @@ CPLogRegister(CPLogConsole); [view setBackgroundColor:[CPColor whiteColor]]; [view enterFullScreenMode:nil withOptions:nil]; - _data = [1, 2]; - - _tableView = [[CPTableView alloc] initWithFrame:[view bounds]]; - //[_tableView setBackgroundColor:[CPColor blueColor]]; - + tableView = [[NEWCPTableView alloc] initWithFrame:CGRectMake(0.0, 0.0, 500.0, 500.0)];//[view bounds]]; + + [tableView setBackgroundColor:[CPColor blueColor]]; + var iconView = [[CPImageView alloc] initWithFrame:CGRectMake(16,16,0,0)]; + [iconView setImageScaling:CPScaleNone]; - var iconColumn = [[CPTableColumn alloc] initWithIdentifier:"icons"]; - [iconColumn setWidth:32]; + var iconColumn = [[NEWCPTableColumn alloc] initWithIdentifier:"icons"]; + + [iconColumn setWidth:32.0]; [iconColumn setDataView:iconView]; - - [_tableView addTableColumn:iconColumn]; + + [tableView addTableColumn:iconColumn]; for (var i = 1; i <= 10; i++) { - var column = [[CPTableColumn alloc] initWithIdentifier:String(i)]; + var column = [[NEWCPTableColumn alloc] initWithIdentifier:String(i)]; - [[column headerView] setStringValue:"Number"]; - [[column headerView] sizeToFit]; - [column setWidth:[[column headerView] frame].size.width]; +// [[column headerView] setStringValue:"Number"]; +// [[column headerView] sizeToFit]; +// [column setWidth:[[column headerView] frame].size.width]; + + [column setWidth:200.0]; - [_tableView addTableColumn:column]; + [tableView addTableColumn:column]; } - + var scrollView = [[CPScrollView alloc] initWithFrame:[view bounds]]; - - [scrollView setDocumentView:_tableView]; + + [scrollView setDocumentView:tableView]; [scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; - + [view addSubview:scrollView]; + + [tableView setDelegate:self]; + [tableView setDataSource:self]; - [_tableView setDelegate:self]; - [_tableView setDataSource:self]; - - _iconImage = [[CPImage alloc] initWithContentsOfFile:"http://cappuccino.org/images/favicon.png" size:CGSizeMake(16,16)]; + iconImage = [[CPImage alloc] initWithContentsOfFile:"http://cappuccino.org/images/favicon.png" size:CGSizeMake(16,16)]; } - (int)numberOfRowsInTableView:(CPTableView)tableView @@ -63,8 +67,8 @@ CPLogRegister(CPLogConsole); - (id)tableView:(CPTableView)tableView objectValueForTableColumn:(CPTableColumn)tableColumn row:(int)row { - if ([tableColumn identifier] == "icons") - return _iconImage + if ([tableColumn identifier] === "icons") + return iconImage else return String((row + 1) * [[tableColumn identifier] intValue]); } @@ -90,7 +94,8 @@ CPLogRegister(CPLogConsole); //CPLog.debug(@"shouldSelectRow %d", rowIndex); for (var i = 2, sqrt = SQRT(rowIndex+1); i <= sqrt; i++) if ((rowIndex+1) % i === 0) - return false + return false; + return true; }