diff --git a/AppKit/CPButtonBar.j b/AppKit/CPButtonBar.j index e0d66f78f..a66fb7b86 100644 --- a/AppKit/CPButtonBar.j +++ b/AppKit/CPButtonBar.j @@ -8,6 +8,16 @@ { } +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + [self setNeedsLayout]; + + return self; +} + + (CPString)themeClass { return @"button-bar"; diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 972d48d64..b38f754e4 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -618,140 +618,146 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ @end +// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever... var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem) { if (!anItem) return; - - // Get the existing info if it exists. - var itemInfosForItems = anOutlineView._itemInfosForItems, - dataSource = anOutlineView._outlineViewDataSource, - itemUID = [anItem UID], - itemInfo = itemInfosForItems[itemUID]; - - // If we're not in the tree, then just bail. - if (!itemInfo) - return []; - - // See if the item itself can be swapped out. - var parent = itemInfo.parent, - parentItemInfo = parent ? itemInfosForItems[[parent UID]] : anOutlineView._rootItemInfo, - parentChildren = parentItemInfo.children, - index = [parentChildren indexOfObjectIdenticalTo:anItem], - newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent]; - - if (anItem !== newItem) - { - itemInfosForItems[[anItem UID]] = nil; - itemInfosForItems[[newItem UID]] = itemInfo; - - parentChildren[index] = newItem; - anOutlineView._itemsForRows[itemInfo.row] = newItem; - } - - itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem]; - itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded; -} - -var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate) -{ - var itemInfosForItems = anOutlineView._itemInfosForItems, - dataSource = anOutlineView._outlineViewDataSource; - - if (!anItem) - var itemInfo = anOutlineView._rootItemInfo; - - else + with(anOutlineView) { // Get the existing info if it exists. - var itemUID = [anItem UID], + var itemInfosForItems = _itemInfosForItems, + dataSource = _outlineViewDataSource, + itemUID = [anItem UID], itemInfo = itemInfosForItems[itemUID]; - + // If we're not in the tree, then just bail. if (!itemInfo) return []; - - itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem]; - - // If we were previously expanded, but now no longer expandable, "de-expand". - // NOTE: we are *not* collapsing, thus no notification is posted. - if (!itemInfo.isExpandable && itemInfo.isExpanded) + + // See if the item itself can be swapped out. + var parent = itemInfo.parent, + parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo, + parentChildren = parentItemInfo.children, + index = [parentChildren indexOfObjectIdenticalTo:anItem], + newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent]; + + if (anItem !== newItem) { - itemInfo.isExpanded = NO; + itemInfosForItems[[anItem UID]] = nil; + itemInfosForItems[[newItem UID]] = itemInfo; + + parentChildren[index] = newItem; + _itemsForRows[itemInfo.row] = newItem; + } + + itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem]; + itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded; + } +} + +// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever... +var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate) +{ + with(anOutlineView) + { + var itemInfosForItems = _itemInfosForItems, + dataSource = _outlineViewDataSource; + + if (!anItem) + var itemInfo = _rootItemInfo; + + else + { + // Get the existing info if it exists. + var itemUID = [anItem UID], + itemInfo = itemInfosForItems[itemUID]; + + // If we're not in the tree, then just bail. + if (!itemInfo) + return []; + + itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem]; + + // If we were previously expanded, but now no longer expandable, "de-expand". + // NOTE: we are *not* collapsing, thus no notification is posted. + if (!itemInfo.isExpandable && itemInfo.isExpanded) + { + itemInfo.isExpanded = NO; + itemInfo.children = []; + } + } + + // The root item does not count as a descendant. + var weight = itemInfo.weight, + descendants = anItem ? [anItem] : []; + + if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) || + ![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem])) + { + var index = 0, + count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem], + level = itemInfo.level + 1; + itemInfo.children = []; - } - } - - // The root item does not count as a descendant. - var weight = itemInfo.weight, - descendants = anItem ? [anItem] : []; - - if (itemInfo.isExpanded && (!(anOutlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) || - ![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem])) - { - var index = 0, - count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem], - level = itemInfo.level + 1; - - itemInfo.children = []; - - for (; index < count; ++index) - { - var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem], - childItemInfo = itemInfosForItems[[childItem UID]]; - - if (!childItemInfo) + + for (; index < count; ++index) { - childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 }; - itemInfosForItems[[childItem UID]] = childItemInfo; + var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem], + childItemInfo = itemInfosForItems[[childItem UID]]; + + if (!childItemInfo) + { + childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 }; + itemInfosForItems[[childItem UID]] = childItemInfo; + } + + itemInfo.children[index] = childItem; + + var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES); + + childItemInfo.parent = anItem; + childItemInfo.level = level; + descendants = descendants.concat(childDescendants); } - - itemInfo.children[index] = childItem; - - var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES); - - childItemInfo.parent = anItem; - childItemInfo.level = level; - descendants = descendants.concat(childDescendants); } - } - - itemInfo.weight = descendants.length; - - if (!isIntermediate) - { - // row = -1 is the root item, so just go to row 0 since it is ignored. - var index = MAX(itemInfo.row, 0), - itemsForRows = anOutlineView._itemsForRows; - - descendants.unshift(index, weight); - - itemsForRows.splice.apply(itemsForRows, descendants); - - var count = itemsForRows.length; - - for (; index < count; ++index) - itemInfosForItems[[itemsForRows[index] UID]].row = index; - - var deltaWeight = itemInfo.weight - weight; - - if (deltaWeight !== 0) + + itemInfo.weight = descendants.length; + + if (!isIntermediate) { - var parent = itemInfo.parent; - - while (parent) + // row = -1 is the root item, so just go to row 0 since it is ignored. + var index = MAX(itemInfo.row, 0), + itemsForRows = _itemsForRows; + + descendants.unshift(index, weight); + + itemsForRows.splice.apply(itemsForRows, descendants); + + var count = itemsForRows.length; + + for (; index < count; ++index) + itemInfosForItems[[itemsForRows[index] UID]].row = index; + + var deltaWeight = itemInfo.weight - weight; + + if (deltaWeight !== 0) { - var parentItemInfo = itemInfosForItems[[parent UID]]; - - parentItemInfo.weight += deltaWeight; - parent = parentItemInfo.parent; + var parent = itemInfo.parent; + + while (parent) + { + var parentItemInfo = itemInfosForItems[[parent UID]]; + + parentItemInfo.weight += deltaWeight; + parent = parentItemInfo.parent; + } + + if (anItem) + _rootItemInfo.weight += deltaWeight; } - - if (anItem) - anOutlineView._rootItemInfo.weight += deltaWeight; } - } - + }//end of with return descendants; } diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 9b298b812..30edea8a0 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -23,112 +23,39 @@ @import "CPTableColumn.j" @import "CPTableView.j" @import "CPView.j" -@import + +var CPThemeStatePressed = CPThemeState("pressed"); -var _headerGradient = nil, - _selectedHeaderGradient = nil, - _pressedHeaderGradient = nil, - _selectedPressedHeaderGradient = nil, - - supportsCanvasGradient = NO; - -// FIX ME: _CPTableColumnHeaderView has code for drawn gradients. -// We need to decide if we're going to draw it or just use images throughout. @implementation _CPTableColumnHeaderView : CPView { - BOOL _isPressed; CPTextField _textField; } -+ (void)initialize -{ - supportsCanvasGradient = NO;//CPFeatureIsCompatible(CPHTMLCanvasFeature); -} - -+ (CGGradient)headerGradient -{ - if (!_headerGradient) - _headerGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(),[1.0,1.0,1.0,1.0,0.929,0.929,0.929,1.0], [0.3,1], 2); - - return _headerGradient; -} - -+ (CGGradient)selectedHeaderGradient -{ - if (!_selectedHeaderGradient) - _selectedHeaderGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [0.804,0.851,0.918,1.0,0.655,0.718,0.8,1.0], [0.3,1], 2); - - return _selectedHeaderGradient; -} - -+ (CGGradient)pressedHeaderGradient -{ - if (!_pressedHeaderGradient) - _pressedHeaderGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(),[0.929,0.929,0.929,1.0,1.0,1.0,1.0,1.0], [0.3,1], 2); - - return _pressedHeaderGradient; -} - -+ (CGGradient)selectedPressedHeaderGradient -{ - if (!_selectedPressedHeaderGradient) - _selectedPressedHeaderGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [0.655,0.718,0.8,1.0,0.804,0.851,0.918,1.0], [0.3,1], 2); - - return _selectedPressedHeaderGradient; -} - - (void)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - _isPressed = NO; _textField = [[CPTextField alloc] initWithFrame:[self bounds]]; [_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; [self addSubview:_textField]; - - if (!supportsCanvasGradient) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; - - //[self setValue:headerColor forThemeAttribute:@"background-color" inState:CPThemeStateNormal]; - //[self setValue:headerHighlightedColor forThemeAttribute:@"background-color" inState:CPThemeStateHighlighted]; } return self; } -- (void)setPressed:(BOOL)flag +- (void)layoutSubviews { - _isPressed = flag; - var isSelected = ([self themeState] & CPThemeStateSelected); - - if(_isPressed && isSelected) + var themeState = [self themeState]; + + if((themeState & CPThemeStateSelected) && (themeState & CPThemeStatePressed)) [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]]; - else if (isSelected) + else if (themeState == CPThemeStateSelected) [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]]; - else if (_isPressed) + else if (themeState == CPThemeStatePressed) [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]]; else [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; - - - [self setNeedsDisplay:YES]; -} - -- (BOOL)setThemeState:(CPThemeState)aState -{ - if (supportsCanvasGradient) - [super setThemeState:aState]; - else if (aState & CPThemeStateHighlighted) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]]; -} - -- (BOOL)unsetThemeState:(CPThemeState)aState -{ - if (supportsCanvasGradient) - [super unsetThemeState:aState]; - else if (aState & CPThemeStateHighlighted) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; } - (void)setStringValue:(CPString)string @@ -148,32 +75,8 @@ var _headerGradient = nil, - (void)sizeToFit { + [_textField sizeToFit]; } - -- (void)drawRect:(CGRect)rect -{ - if (!supportsCanvasGradient) - return; - - var context = [[CPGraphicsContext currentContext] graphicsPort], - bounds = [self bounds], - isSelected = ([self themeState] & CPThemeStateSelected); - - if (_isPressed && isSelected) - gradient = [_CPTableColumnHeaderView selectedPressedHeaderGradient]; - else if (isSelected) - gradient = [_CPTableColumnHeaderView selectedHeaderGradient]; - else if (_isPressed) - gradient = [_CPTableColumnHeaderView pressedHeaderGradient]; - else - gradient = [_CPTableColumnHeaderView headerGradient]; - - CGContextBeginPath(context); - CGContextAddRect(context, bounds); - CGContextDrawLinearGradient(context, gradient, CGPointMakeZero(), CGPointMake(0, CGRectGetHeight(bounds)), 0); - CGContextClosePath(context); -} - @end @implementation CPTableHeaderView : CPView @@ -258,11 +161,21 @@ var _headerGradient = nil, return rect; } -- (void)_updatePressed:(BOOL)flag +- (void)_setPressedColumn:(CPInteger)column { - var headerView = [_tableView._tableColumns[_pressedColumn] headerView]; - if ([headerView respondsToSelector:@selector(setPressed:)]) - [headerView setPressed:flag]; + if (_pressedColumn != CPNotFound) + { + var headerView = [_tableView._tableColumns[_pressedColumn] headerView]; + [headerView unsetThemeState:CPThemeStatePressed]; + } + + if (column != CPNotFound) + { + var headerView = [_tableView._tableColumns[column] headerView]; + [headerView setThemeState:CPThemeStatePressed]; + } + + _pressedColumn = column; } - (void)mouseDown:(CPEvent)theEvent @@ -279,8 +192,7 @@ var _headerGradient = nil, [[_tableView delegate] tableView:_tableView mouseDownInHeaderOfTableColumn:[[_tableView tableColumns] objectAtIndex:clickedColumn]]; - _pressedColumn = clickedColumn; - [self _updatePressed:YES]; + [self _setPressedColumn:clickedColumn]; } - (void)mouseUp:(CPEvent)theEvent @@ -288,14 +200,10 @@ var _headerGradient = nil, var location = [self convertPoint:[theEvent locationInWindow] fromView:nil], clickedColumn = [self columnAtPoint:location]; - if (clickedColumn == -1) - return; + [self _setPressedColumn:CPNotFound]; - if (_pressedColumn != CPNotFound) - { - [self _updatePressed:NO]; - _pressedColumn = CPNotFound; - } + if (clickedColumn == -1) + return; if ([_tableView allowsColumnSelection]) { @@ -374,15 +282,13 @@ var _headerGradient = nil, columnMaxX = CGRectGetMaxX(columnToStroke); CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMinY(columnToStroke))); - CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke)) - 1); + CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke))); } CGContextClosePath(context); CGContextStrokePath(context); - - return; - - /* + +/* var maxY = CGRectGetMaxY([self bounds]); // draw normal gradient for remaining space if (supportsCanvasGradient) @@ -400,7 +306,8 @@ var _headerGradient = nil, CGContextMoveToPoint(context, 0, maxY - 0.5); CGContextAddLineToPoint(context, CGRectGetMaxX([self bounds]), maxY - 0.5); CGContextClosePath(context); - CGContextStrokePath(context);*/ + CGContextStrokePath(context); +*/ } @end diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 176166f80..74aeaffc6 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -122,6 +122,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; @end +/*! + @ingroup appkit + @class CPTableView + + CPTableView object displays record-oriented data in a table and allows the user to edit values and resize and rearrange columns. + A CPTableView requires you to set a dataSource which implements numberOfRowsInTableView: and tableView:objectValueForTableColumn:row: +*/ @implementation CPTableView : CPControl { id _dataSource; @@ -183,14 +190,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; SEL _doubleAction; unsigned _columnAutoResizingStyle; -// BOOL _verticalMotionCanDrag; -// unsigned _destinationDragStyle; -// BOOL _isSelectingSession; -// CPIndexSet _draggedRowIndexes; -// _dropOperationDrawingView _dropOperationFeedbackView; -// CPDragOperation _dragOperationDefaultMask; -// int _retargetedDropRow; -// CPDragOperation _retargetedDropOperation; + BOOL _verticalMotionCanDrag; + unsigned _destinationDragStyle; + BOOL _isSelectingSession; + CPIndexSet _draggedRowIndexes; + _dropOperationDrawingView _dropOperationFeedbackView; + CPDragOperation _dragOperationDefaultMask; + int _retargetedDropRow; + CPDragOperation _retargetedDropOperation; } - (id)initWithFrame:(CGRect)aFrame @@ -239,22 +246,20 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _cornerView = [[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))]; - _selectedColumnIndexes = [CPIndexSet indexSet]; _selectedRowIndexes = [CPIndexSet indexSet]; -window.setTimeout(function(){ - self._draggedRowIndexes = [CPIndexSet indexSet]; - self._verticalMotionCanDrag = YES; - self._isSelectingSession = NO; - self._retargetedDropRow = nil; - self._retargetedDropOperation = nil; - self._dragOperationDefaultMask = nil; - self._destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; - self._dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; + + _draggedRowIndexes = [CPIndexSet indexSet]; + _verticalMotionCanDrag = YES; + _isSelectingSession = NO; + _retargetedDropRow = nil; + _retargetedDropOperation = nil; + _dragOperationDefaultMask = nil; + _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; + _dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; [self addSubview:_dropOperationFeedbackView]; [_dropOperationFeedbackView setHidden:YES]; [_dropOperationFeedbackView setTableView:self]; -},0); _tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self]; [_tableDrawView setBackgroundColor:[CPColor clearColor]]; @@ -265,6 +270,11 @@ window.setTimeout(function(){ return self; } + +/*! + Sets the receiverŐs data source to a given object. + @param anObject The data source for the receiver. The object must implement the appropriate methods. +*/ - (void)setDataSource:(id)aDataSource { if (_dataSource === aDataSource) @@ -302,6 +312,9 @@ window.setTimeout(function(){ [self reloadData]; } +/*! + Returns the object that provides the data displayed by the receiver. +*/ - (id)dataSource { return _dataSource; @@ -309,6 +322,11 @@ window.setTimeout(function(){ //Loading Data +/*! + Reloads the data for only the specified rows and columns. + @param rowIndexes The indexes of the rows to update. + @param columnIndexes The indexes of the columns to update. +*/ - (void)reloadDataForRowIndexes:(CPIndexSet)rowIndexes columnIndexes:(CPIndexSet)columnIndexes { [self reloadData]; @@ -316,7 +334,10 @@ window.setTimeout(function(){ // [_previouslyExposedColumns removeIndexes:columnIndexes]; } - +/*! + Reloads the data for all rows and columns. + +*/ - (void)reloadData { if (!_dataSource) @@ -333,7 +354,10 @@ window.setTimeout(function(){ } //Target-action Behavior - +/*! + Sets the message sent to the target when the user double-clicks an uneditable cell or a column header to a given selector. + @param aSelector The message the receiver sends to its target when the user double-clicks an uneditable cell or a column header. +*/ - (void)setDoubleAction:(SEL)anAction { _doubleAction = anAction; @@ -370,6 +394,10 @@ window.setTimeout(function(){ return _allowsColumnResizing; } +/*! + Controls whether the user can select more than one row or column at a time. + @param aFlag YES to allow the user to select multiple rows or columns, otherwise NO. +*/ - (void)setAllowsMultipleSelection:(BOOL)shouldAllowMultipleSelection { _allowsMultipleSelection = !!shouldAllowMultipleSelection; @@ -380,6 +408,10 @@ window.setTimeout(function(){ return _allowsMultipleSelection; } +/*! + Controls whether the receiver allows zero rows or columns to be selected. + @param aFlag YES if an empty selection is allowed, otherwise NO. +*/ - (void)setAllowsEmptySelection:(BOOL)shouldAllowEmptySelection { _allowsEmptySelection = !!shouldAllowEmptySelection; @@ -390,6 +422,11 @@ window.setTimeout(function(){ return _allowsEmptySelection; } +/*! + Controls whether the user can select an entire column by clicking its header. + @param aFlag YES to allow the user to select columns, otherwise NO. +*/ + - (void)setAllowsColumnSelection:(BOOL)shouldAllowColumnSelection { _allowsColumnSelection = !!shouldAllowColumnSelection; @@ -438,13 +475,12 @@ window.setTimeout(function(){ return _rowHeight; } +/*! + Sets whether the receiver uses the standard alternating row colors for its background. + @param aFlag YES to specify standard alternating row colors for the background, NO to specify a solid color. +*/ - (void)setUsesAlternatingRowBackgroundColors:(BOOL)shouldUseAlternatingRowBackgroundColors { - // TODO:need to look at how one actually sets the alternating row, a tip at: - // http://forums.macnn.com/79/developer-center/228347/nstableview-alternating-row-colors/ - // otherwise this may not be feasible or may introduce an additional change req'd in CP - // we'd probably need to iterate through rowId % 2 == 0 and setBackgroundColor with - // whatever the alternating row color is. _usesAlternatingRowBackgroundColors = shouldUseAlternatingRowBackgroundColors; } @@ -453,6 +489,11 @@ window.setTimeout(function(){ return _usesAlternatingRowBackgroundColors; } +/*! + Sets the colors for the rows as they alternate. The number of colors can be arbitrary. By deafult these colors are white and light blue. + @param anArray an array of CPColors +*/ + - (void)setAlternatingRowBackgroundColors:(CPArray)alternatingRowBackgroundColors { if ([_alternatingRowBackgroundColors isEqual:alternatingRowBackgroundColors]) @@ -489,6 +530,11 @@ window.setTimeout(function(){ } } +/*! + Sets the highlight color for rows. By default this color is blue. + @param aColor a CPColor +*/ + - (void)setSelectionHightlightColor:(CPColor)aColor { _selectionHightlightColor = aColor; @@ -504,6 +550,10 @@ window.setTimeout(function(){ * - setIndicatorImage:inTableColumn: */ +/*! + Sets the grid color in the non highlighted state. + @param aColor a CPColor +*/ - (void)setGridColor:(CPColor)aColor { if (_gridColor === aColor) @@ -519,6 +569,11 @@ window.setTimeout(function(){ return _gridColor; } +/*! + Sets the grid style mask to specify if no grid lines, vertical grid lines, or horizontal grid lines should be displayed. + @param gridType The grid style mask. CPTableViewGridNone, CPTableViewSolidVerticalGridLineMask, CPTableViewSolidHorizontalGridLineMask +*/ + - (void)setGridStyleMask:(unsigned)aGrideStyleMask { if (_gridStyleMask === aGrideStyleMask) @@ -536,6 +591,10 @@ window.setTimeout(function(){ //Column Management +/*! + Adds a given column as the last column of the receiver. + @param aColumn The column to add to the receiver. +*/ - (void)addTableColumn:(CPTableColumn)aTableColumn { [_tableColumns addObject:aTableColumn]; @@ -549,6 +608,10 @@ window.setTimeout(function(){ [self setNeedsLayout]; } +/*! + Removes a given column from the receiver. + @param aTableColumn The column to remove from the receiver. +*/ - (void)removeTableColumn:(CPTableColumn)aTableColumn { if ([aTableColumn tableView] !== self) @@ -575,6 +638,12 @@ window.setTimeout(function(){ [self setNeedsLayout]; } + +/*! + Moves the column and heading at a given index to a new given index. + @param columnIndex The current index of the column to move. + @param newIndex The new index for the moved column. +*/ - (void)moveColumn:(unsigned)fromIndex toColumn:(unsigned)toIndex { fromIndex = +fromIndex; @@ -627,6 +696,12 @@ window.setTimeout(function(){ } //Selecting Columns and Rows + +/*! + Sets the column selection using indexes. + @param columns a CPIndexSet of columns to select + @param aFlag should extend the selection thereby retaining the previous selection +*/ - (void)selectColumnIndexes:(CPIndexSet)columns byExtendingSelection:(BOOL)shouldExtendSelection { // If we're out of range, just return @@ -655,6 +730,11 @@ window.setTimeout(function(){ [self _noteSelectionDidChange]; } +/*! + Sets the row selection using indexes. + @param rows a CPIndexSet of rows to select + @param aFlag should extend the selection thereby retaining the previous selection +*/ - (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection { if ([rows isEqualToIndexSet:_selectedRowIndexes] || (([rows firstIndex] != CPNotFound && [rows firstIndex] < 0) || [rows lastIndex] >= [self numberOfRows])) @@ -811,6 +891,10 @@ window.setTimeout(function(){ * - allowsTypeSelect * - setAllowsTypeSelect: */ + +/*! + Deselects all rows +*/ - (void)deselectAll { [self selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO]; @@ -958,6 +1042,11 @@ window.setTimeout(function(){ // Complexity: // O(1) +/*! + Returns a range of indices for the rows that lie wholly or partially within the vertical boundaries of a given rectangle. + @param aRect A rectangle in the coordinate system of the receiver. +*/ + - (CPRange)rowsInRect:(CGRect)aRect { // If we have no rows, then we won't intersect anything. @@ -988,6 +1077,11 @@ window.setTimeout(function(){ // Complexity: // O(lg Columns) if table view contains no hidden columns // O(Columns) if table view contains hidden columns + +/*! + Returns the indexes of the receiverŐs columns that intersect the specified rectangle. + @param aRect A rectangle in the coordinate system of the receiver. +*/ - (CPIndexSet)columnIndexesInRect:(CGRect)aRect { var column = MAX(0, [self columnAtPoint:_CGPointMake(aRect.origin.x, 0.0)]), @@ -1183,6 +1277,10 @@ window.setTimeout(function(){ } +/*! + Sets the column autoresizing style of the receiver to a given style. + @param aStyle The column autoresizing style for the receiver. CPTableViewNoColumnAutoresizing, CPTableViewUniformColumnAutoresizingStyle, CPTableViewLastColumnOnlyAutoresizingStyle, CPTableViewFirstColumnOnlyAutoresizingStyle +*/ - (void)setColumnAutoresizingStyle:(unsigned)style { //FIX ME: CPTableViewSequentialColumnAutoresizingStyle and CPTableViewReverseSequentialColumnAutoresizingStyle are not yet implemented @@ -1194,6 +1292,9 @@ window.setTimeout(function(){ return _columnAutoResizingStyle; } +/*! + Resizes the last column if thereŐs room so the receiver fits exactly within its enclosing clip view. +*/ - (void)sizeLastColumnToFit { var superview = [self superview]; @@ -1268,11 +1369,19 @@ window.setTimeout(function(){ * - scrollColumnToVisible: */ +/*! + Scrolls the receiver vertically in an enclosing NSClipView so the row specified by rowIndex is visible. + @param aRowIndex the index of the row to scroll to. +*/ - (void)scrollRowToVisible:(int)rowIndex { [self scrollRectToVisible:[self rectOfRow:rowIndex]]; } +/*! + Scrolls the receiver and header view horizontally in an enclosing NSClipView so the column specified by columnIndex is visible. + @param aColumnIndex the index of the column to scroll to. +*/ - (void)scrollColumnToVisible:(int)columnIndex { [self scrollRectToVisible:[self rectOfColumn:columnIndex]]; @@ -1432,6 +1541,11 @@ window.setTimeout(function(){ * - setVerticalMotionCanBeginDrag: * - verticalMotionCanBeginDrag */ +/*! + Returns whether the receiver allows dragging the rows at rowIndexes with a drag initiated at mousedDownPoint. + @param rowIndexes an index set of rows to be dragged + @param aPoint the point at which the mouse was clicked. +*/ - (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint { return YES; @@ -1503,8 +1617,8 @@ window.setTimeout(function(){ _dragOperationDefaultMask = mask; } -/* - this should be called inside tableView:validateDrop:... method +/*! + This should be called inside tableView:validateDrop:... method either drop on or above, specify the row as -1 to select the whole table for drop on */ @@ -1520,16 +1634,16 @@ window.setTimeout(function(){ _retargetedDropOperation = operation; } -/* - can be: +/*! + sets the feedback style for when the table is the destination of a drag operation + Can be: None Regular Source List - - FIX ME: this should vary up the highlight color, currently nothing is being done with it */ - (void)setDraggingDestinationFeedbackStyle:(CPTableViewDraggingDestinationFeedbackStyle)aStyle { + //FIX ME: this should vary up the highlight color, currently nothing is being done with it _destinationDragStyle = aStyle; } @@ -1538,6 +1652,10 @@ window.setTimeout(function(){ return _destinationDragStyle; } +/*! + Sets whether vertical motion is treated as a drag or selection change to flag. + @param aFlag If flag is NO then vertical motion will not start a drag. The default is YES. +*/ - (void)setVerticalMotionCanBeginDrag:(BOOL)aFlag { _verticalMotionCanDrag = aFlag; @@ -1823,7 +1941,10 @@ window.setTimeout(function(){ } - (void)_drawRect:(CGRect)aRect -{ +{ + // FIX ME: All three of these methods will likely need to be rewritten for 1.0 + // We've got grid drawing in highlightSelection and crap everywhere. + var exposedRect = [self _exposedRect]; [self drawBackgroundInClipRect:exposedRect]; @@ -1831,11 +1952,6 @@ window.setTimeout(function(){ [self highlightSelectionInClipRect:exposedRect]; } -- (void)drawRect:(CGRect)aRect -{ - [_tableDrawView display]; -} - - (void)drawBackgroundInClipRect:(CGRect)aRect { if (![self usesAlternatingRowBackgroundColors]) @@ -1866,13 +1982,14 @@ window.setTimeout(function(){ while (colorIndex--) { - var row = firstRow % colorCount + firstRow + colorIndex, + var row = firstRow - firstRow % colorCount + colorIndex, fillRect = nil; CGContextBeginPath(context); for (; row <= lastRow; row += colorCount) - CGContextAddRect(context, CGRectIntersection(aRect, fillRect = [self rectOfRow:row])); + if (row >= firstRow) + CGContextAddRect(context, CGRectIntersection(aRect, fillRect = [self rectOfRow:row])); if (row - colorCount === lastRow) heightFilled = _CGRectGetMaxY(fillRect); @@ -2027,33 +2144,34 @@ window.setTimeout(function(){ CGContextBeginPath(context); gridStyleMask = [self gridStyleMask]; - for(var i=0; i < count2-1; i++) + for(var i=0; i < count2; i++) { - var rect = [self rectOfRow:indexes[i]], - minX = _CGRectGetMinX(rect) - 0.5, - maxX = _CGRectGetMaxX(rect) - 0.5, - minY = _CGRectGetMinY(rect) - 0.5, - maxY = _CGRectGetMaxY(rect) - 0.5; + var rect = objj_msgSend(self, rectSelector, indexes[i]), + minX = CGRectGetMinX(rect) - 0.5, + maxX = CGRectGetMaxX(rect) - 0.5, + minY = CGRectGetMinY(rect) - 0.5, + maxY = CGRectGetMaxY(rect) - 0.5; - //FIX ME: if there are vertical lines we need to make them white too... - /*if (gridStyleMask & CPTableViewSolidVerticalGridLineMask) + if ([_selectedRowIndexes count] >= 1 && gridStyleMask & CPTableViewSolidVerticalGridLineMask) { var exposedColumns = [self columnIndexesInRect:aRect], - columnIndexes = [], - exposedColumns2 = CPMakeRange([exposedColumns firstIndex], [exposedColumns lastIndex] - firstColumn + 1); - [exposedColumns getIndexes:columnIndexes maxCount:-1 inIndexRange:exposedColumns2], - columnCount = [exposedColumns count]; - - for(var c = 0; c < columnCount - 1; c++) + exposedColumnIndexes = [], + firstExposedColumn = [exposedColumns firstIndex], + exposedRange = CPMakeRange(firstExposedColumn, [exposedColumns lastIndex] - firstExposedColumn + 1); + [exposedColumns getIndexes:exposedColumnIndexes maxCount:-1 inIndexRange:exposedRange]; + var exposedColumnCount = [exposedColumnIndexes count]; + + for(var c = firstExposedColumn; c < exposedColumnCount; c++) { - var colRect = [self rectOfColumn:columnIndexes[c]], - colX = _CGRectGetMaxX(rect) - 0.5; - console.log("colX"); + //console.log(columnIndexes); + var colRect = [self rectOfColumn:exposedColumnIndexes[c]], + colX = CGRectGetMaxX(colRect) + 0.5; + //console.log(colX); CGContextMoveToPoint(context, colX, minY); CGContextAddLineToPoint(context, colX, maxY); } - }*/ + } CGContextMoveToPoint(context, minX, maxY); CGContextAddLineToPoint(context, maxX, maxY); @@ -2126,12 +2244,17 @@ window.setTimeout(function(){ */ +/* + @ignore +*/ - (BOOL)tracksMouseOutsideOfFrame { return YES; } -/* ignore */ +/* + @ignore +*/ - (BOOL)startTrackingAt:(CGPoint)aPoint { var row = [self rowAtPoint:aPoint]; @@ -2165,6 +2288,9 @@ window.setTimeout(function(){ return YES; } +/* + @ignore +*/ - (void)trackMouse:(CPEvent)anEvent { // Prevent CPControl from eating the mouse events when we are in a drag session @@ -2174,7 +2300,9 @@ window.setTimeout(function(){ [CPApp sendEvent:anEvent]; } -/* ignore */ +/* + @ignore +*/ - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint { var row = [self rowAtPoint:aPoint]; @@ -2249,6 +2377,9 @@ window.setTimeout(function(){ return YES; } +/*! + @ignore +*/ - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp { _isSelectingSession = NO; @@ -2311,7 +2442,7 @@ window.setTimeout(function(){ [self sendAction:_doubleAction to:_target]; } -/* +/*! @ignore */ - (CPDragOperation)draggingEntered:(id)sender diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j index 60ac59129..e3a621fb8 100644 --- a/AppKit/Platform/DOM/CPPlatform.j +++ b/AppKit/Platform/DOM/CPPlatform.j @@ -24,7 +24,8 @@ CPPlatformDidClearBodyElementNotification = @"CPPlatformDidClearBodyElementNot CPPlatformWillClearBodyElementNotification = @"CPPlatformWillClearBodyElementNotification"; var screenNeedsInitialization = NO, - mainBodyElement = nil; + mainBodyElement = nil, + elementRemovalTest = new RegExp("\\bcpdontremove\\b", "g"); @implementation CPPlatform : CPBasePlatform { @@ -99,7 +100,16 @@ var screenNeedsInitialization = NO, var bodyElement = [self mainBodyElement]; // Get rid of any of the original contents of the page. - bodyElement.innerHTML = ""; + var children = bodyElement.childNodes, + length = children.length; + + while (length--) + { + var element = children[length]; + if (!element.className || element.className.match(elementRemovalTest) === null) + bodyElement.removeChild(element); + } + bodyElement.style.overflow = "hidden"; if (document.documentElement) diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j index 1beb80c6f..7b82f4493 100644 --- a/AppKit/Platform/DOM/CPPlatformString.j +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -33,25 +33,10 @@ var DOMSpanElement = nil, + (void)bootstrap { [self createDOMElements]; - - [[CPNotificationCenter defaultCenter] - addObserver:self - selector:@selector(platformDidClearBodyElement:) - name:CPPlatformDidClearBodyElementNotification - object:CPPlatform]; - - [[CPNotificationCenter defaultCenter] - addObserver:self - selector:@selector(platformWillClearBodyElement:) - name:CPPlatformWillClearBodyElementNotification - object:CPPlatform]; } + (void)createDOMElements { - if (DOMIFrameElement) - return; - DOMIFrameElement = document.createElement("iframe"); // necessary for Safari caching bug: DOMIFrameElement.name = "iframe_" + FLOOR(RAND() * 10000); @@ -63,6 +48,7 @@ var DOMSpanElement = nil, DOMIFrameElement.style.borderWidth = "0px"; DOMIFrameElement.style.overflow = "hidden"; DOMIFrameElement.style.zIndex = 100000000000; + DOMIFrameElement.className = "cpdontremove"; var bodyElement = [CPPlatform mainBodyElement]; @@ -89,27 +75,6 @@ var DOMSpanElement = nil, DOMDivElement.appendChild(DOMSpanElement); } -+ (void)removeDOMElements -{ - var iframe = DOMIFrameElement, - bodyElement = [CPPlatform mainBodyElement]; - - DOMSpanElement = nil; - DOMIFrameElement = nil; - - bodyElement.removeChild(iframe); -} - -+ (void)platformDidClearBodyElement:(CPNotification)aNotification -{ - [self createDOMElements]; -} - -+ (void)platformWillClearBodyElement:(CPNotification)aNotification -{ - [self removeDOMElements]; -} - + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { if (!aFont) diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 5c73c69cc..e6cff4912 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -239,6 +239,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMFocusElement.style.zIndex = "-1000"; _DOMFocusElement.style.opacity = "0"; _DOMFocusElement.style.filter = "alpha(opacity=0)"; + _DOMFocusElement.className = "cpdontremove"; _DOMBodyElement.appendChild(_DOMFocusElement); @@ -248,6 +249,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMPasteboardElement.style.position = "absolute"; _DOMPasteboardElement.style.top = "-10000px"; _DOMPasteboardElement.style.zIndex = "999"; + _DOMPasteboardElement.className = "cpdontremove"; _DOMBodyElement.appendChild(_DOMPasteboardElement); @@ -255,11 +257,6 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMPasteboardElement.blur(); } -- (void)platformDidClearBodyElement:(CPNotification)aNotification -{ - [self createDOMElements]; -} - - (void)registerDOMWindow { var theDocument = _DOMWindow.document; @@ -273,14 +270,6 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMBodyElement.webkitTouchCallout = "none"; [self createDOMElements]; - - if (window === _DOMWindow) - [[CPNotificationCenter defaultCenter] - addObserver:self - selector:@selector(platformDidClearBodyElement:) - name:CPPlatformDidClearBodyElementNotification - object:CPPlatform]; - [self _addLayers]; var theClass = [self class], diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index eb4b7830a..98fb0d160 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -39,6 +39,7 @@ CPLogRegister(CPLogConsole); [tableView setAllowsMultipleSelection:YES]; [tableView setAllowsColumnSelection:YES]; [tableView setUsesAlternatingRowBackgroundColors:YES]; + [tableView setAlternatingRowBackgroundColors:[[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"], [CPColor colorWithHexString:@"f4e7ff"]]]; [tableView setGridStyleMask:CPTableViewSolidHorizontalGridLineMask | CPTableViewSolidVerticalGridLineMask]; // [tableView setBackgroundColor:[CPColor blueColor]];