Add support for header views in table view and scroll view

This commit is contained in:
Ross Boucher committed 2009-06-24 15:12:26 -07:00
1 parent 1fecae3dc0
commit 849dda0725
5 files changed
+203 -36

No files matched your search

+77 -27
View File
@@ -38,7 +38,8 @@
@implementation CPScrollView : CPView
{
CPClipView _contentView;
CPClipView _headerClipView;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
@@ -57,23 +58,27 @@
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_verticalLineScroll = 10.0;
_verticalPageScroll = 10.0;
_horizontalLineScroll = 10.0;
_horizontalPageScroll = 10.0;
_contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
_contentView = [[CPClipView alloc] initWithFrame:[self clipViewFrame]];
[self addSubview:_contentView];
_headerClipView = [[CPClipView alloc] initWithFrame:[self headerClipViewFrame]];
[self addSubview:_headerClipView];
[self setHasVerticalScroller:YES];
[self setHasHorizontalScroller:YES];
}
return self;
}
@@ -114,7 +119,7 @@
_contentView = aContentView;
[_contentView setFrame:CGRectMake(0.0, 0.0, size.width, size.height)];
[_contentView setFrame:[self clipViewFrame]];
[_contentView setDocumentView:documentView];
[self addSubview:_contentView];
@@ -134,8 +139,13 @@
*/
- (void)setDocumentView:(CPView)aView
{
[_contentView setDocumentView:aView];
[self reflectScrolledClipView:_contentView];
[_contentView setDocumentView:aView];
[_headerClipView setDocumentView:[self _headerView]];
[_contentView setFrame:[self clipViewFrame]];
[_headerClipView setFrame:[self headerClipViewFrame]];
[self reflectScrolledClipView:_contentView];
}
/*!
@@ -167,17 +177,19 @@
// [_horizontalScroller setEnabled:NO];
}
[_contentView setFrame:[self bounds]];
[_contentView setFrame:[self clipViewFrame]];
--_recursionCount;
return;
}
var documentFrame = [documentView frame],
contentViewFrame = [self bounds],
var documentFrame = [documentView frame], // the size of the whole document
clipViewFrame = [self clipViewFrame], // the size of the visible document, within the scrollbars
headerViewFrame = [self headerClipViewFrame],
headerViewHeight = _CGRectGetHeight(headerViewFrame),
scrollPoint = [_contentView bounds].origin,
difference = _CGSizeMake(CPRectGetWidth(documentFrame) - CPRectGetWidth(contentViewFrame), CPRectGetHeight(documentFrame) - CPRectGetHeight(contentViewFrame)),
difference = _CGSizeMake(CPRectGetWidth(documentFrame) - CPRectGetWidth(clipViewFrame), CPRectGetHeight(documentFrame) - CPRectGetHeight(clipViewFrame)),
shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > 0.0) && _hasVerticalScroller,
shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > 0.0) && _hasHorizontalScroller,
wasShowingVerticalScroller = ![_verticalScroller isHidden],
@@ -203,17 +215,17 @@
if (shouldShowVerticalScroller)
{
var verticalScrollerHeight = CPRectGetHeight(contentViewFrame);
var verticalScrollerHeight = CPRectGetHeight([self bounds]) - headerViewHeight;
if (shouldShowHorizontalScroller)
verticalScrollerHeight -= horizontalScrollerHeight;
difference.width += verticalScrollerWidth;
contentViewFrame.size.width -= verticalScrollerWidth;
clipViewFrame.size.width -= verticalScrollerWidth;
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height
knobProportion:CPRectGetHeight(contentViewFrame) / CPRectGetHeight(documentFrame)];
[_verticalScroller setFrame:CPRectMake(CPRectGetMaxX(contentViewFrame), 0.0, verticalScrollerWidth, verticalScrollerHeight)];
knobProportion:CPRectGetHeight(clipViewFrame) / CPRectGetHeight(documentFrame)];
[_verticalScroller setFrame:CPRectMake(CPRectGetMaxX(clipViewFrame), headerViewHeight, verticalScrollerWidth, verticalScrollerHeight)];
}
else if (wasShowingVerticalScroller)
[_verticalScroller setFloatValue:0.0 knobProportion:1.0];
@@ -221,16 +233,17 @@
if (shouldShowHorizontalScroller)
{
difference.height += horizontalScrollerHeight;
contentViewFrame.size.height -= horizontalScrollerHeight;
clipViewFrame.size.height -= horizontalScrollerHeight;
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width
knobProportion:CPRectGetWidth(contentViewFrame) / CPRectGetWidth(documentFrame)];
[_horizontalScroller setFrame:CPRectMake(0.0, CPRectGetMaxY(contentViewFrame), CPRectGetWidth(contentViewFrame), horizontalScrollerHeight)];
knobProportion:CPRectGetWidth(clipViewFrame) / CPRectGetWidth(documentFrame)];
[_horizontalScroller setFrame:CPRectMake(0.0, CPRectGetMaxY(clipViewFrame), CPRectGetWidth(clipViewFrame), horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
[_horizontalScroller setFloatValue:0.0 knobProportion:1.0];
[_contentView setFrame:contentViewFrame];
[_contentView setFrame:clipViewFrame];
[_headerClipView setFrame:headerViewFrame];
--_recursionCount;
}
@@ -384,13 +397,47 @@
{
return _autohidesScrollers;
}
/*
- (void)setFrameSize:(CPRect)aSize
- (CGRect)insetBounds
{
[super setFrameSize:aSize];
return [self bounds];
}
- (CPView)_headerView
{
var documentView = [self documentView];
[self reflectScrolledClipView:_contentView];
}*/
if ([documentView respondsToSelector:@selector(headerView)])
return [documentView performSelector:@selector(headerView)];
return nil;
}
- (CGRect)headerClipViewFrame
{
var headerView = [self _headerView],
bounds = [self insetBounds];
if (!headerView)
return CGRectMakeZero();
bounds.size.height = [headerView bounds].size.height;
bounds.size.width -= _verticalScroller ? [_verticalScroller frame].size.width : [CPScroller scrollerWidth];
return bounds;
}
- (CGRect)clipViewFrame
{
var bounds = [self insetBounds],
headerViewFrame = [self headerClipViewFrame];
bounds.origin.y += headerViewFrame.size.height;
bounds.size.height -= headerViewFrame.size.height;
return bounds;
}
/* @ignore */
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
@@ -448,6 +495,7 @@
}
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
}
/*!
@@ -588,6 +636,7 @@
contentBounds.origin.y += [anEvent deltaY] * _verticalLineScroll;
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
}
- (void)keyDown:(CPEvent)anEvent
@@ -627,6 +676,7 @@
}
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin, 0)];
}
@end
+99 -3
View File
@@ -1,9 +1,38 @@
/*
* CPTableHeaderView.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPView.j>
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPView.j"
@implementation CPTableHeaderView : CPView
{
int _resizedColumn @accessors(readonly, property=resizedColumn);
int _draggedColumn @accessors(readonly, property=draggedColumn);
float _draggedDistance @accessors(readonly, property=draggedDistance);
CPTableView _tableView @accessors(property=tableView);
}
- (void)initWithFrame:(CGRect)aFrame
@@ -11,9 +40,76 @@
self = [super initWithFrame:aFrame];
if (self)
[self setBackgroundColor:[CPColor redColor]];
{
_resizedColumn = CPNotFound;
_draggedColumn = CPNotFound;
_draggedDistance = 0.0;
}
return self;
}
@end
- (int)columnAtPoint:(CGPoint)aPoint
{
if (!CGRectContainsPoint([self bounds], aPoint))
return CPNotFound;
// at this point, we can essentially ignore height, because all columns have equal heights
// and that height is equal to the height of our own bounds, which we know we are inside of
var index = 0,
count = [[_tableView tableColumns] count],
tableSpacing = [_tableView intercellSpacing],
tableColumns = [_tableView tableColumns],
leftOffset = 0,
pointX = aPoint.x;
for (; index < count; index++)
{
var width = [tableColumns[index] width] + tableSpacing.width;
if (pointX >= leftOffset && pointX < leftOffset + width)
return index;
leftOffset += width;
}
return CPNotFound;
}
- (CGRect)headerRectOfColumn:(int)aColumnIndex
{
var tableColumns = [_tableView tableColumns],
tableSpacing = [_tableView intercellSpacing],
bounds = [self bounds];
if (aColumnIndex < 0 || aColumnIndex > [tableColumns count])
[CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"];
bounds.size.width = [tableColumns[aColumnIndex] width] + tableSpacing.width;
while (--aColumnIndex >= 0)
bounds.origin.x += [tableColumns[aColumnIndex] width] + tableSpacing.width;
return bounds;
}
- (void)drawRect:(CGRect)aRect
{
var tableColumns = [_tableView tableColumns];
var count = [tableColumns count];
var columnRect = [self bounds];
var spacing = [_tableView intercellSpacing];
for (i = 0; i < count; ++i) {
var column = [tableColumns objectAtIndex:i];
var headerView = [column headerView] ;
columnRect.size.width = [column width] + spacing.width;
// [headerView setHighlighted:[_tableView isColumnSelected:[[_tableView tableColumns] indexOfObject:column]]];
[headerView setFrame:columnRect];
columnRect.origin.x += [column width] + spacing.width;
[self addSubview:headerView] ;
}
}
@end
+1 -1
View File
@@ -54,7 +54,7 @@ CPTableColumnUserResizingMask = 2;
_maxWidth = 1000000.0;
[self setIdentifier:anIdentifier];
[self setHeaderView:[CPTableHeaderView new]];
[self setHeaderView:[CPTextField new]];
[self setDataView:[CPTextField new]];
}
+19
View File
@@ -79,6 +79,8 @@ CPTableViewSelectionHighlightStyleSourceList = 1;
unsigned _currentHighlightedTableColumn;
unsigned _numberOfRows;
CPTableHeaderView _headerView;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -113,6 +115,11 @@ CPTableViewSelectionHighlightStyleSourceList = 1;
_cachedDataViews = { };
_intercellSpacing = _CGSizeMake(0.0, 0.0);
_rowHeight = 24.0;
_headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)];
[_headerView setAutoresizingMask:CPViewWidthSizable];
[_headerView setTableView:self];
}
return self;
@@ -459,6 +466,18 @@ _cachedDataViews = { };
* - setCornerView:
* - cornerView
*/
- (CPView)headerView
{
return _headerView;
}
- (void)setHeaderView:(CPView)aHeaderView
{
_headerView = aHeaderView;
[_headerView setTableView:self];
}
//Layout Support
// Complexity:
+7 -5
View File
@@ -38,15 +38,15 @@ CPLogRegister(CPLogConsole);
iconImage = [[CPImage alloc] initWithContentsOfFile:"http://cappuccino.org/images/favicon.png" size:CGSizeMake(16,16)];
for (var i = 1; i <= 10; i++)
for (var i = 1; i <= 20; 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 "+i];
[[column headerView] sizeToFit];
[column setWidth:[[column headerView] frame].size.width + 20];
[column setWidth:200.0];
// [column setWidth:200.0];
[tableView addTableColumn:column];
}
@@ -58,6 +58,8 @@ CPLogRegister(CPLogConsole);
[view addSubview:scrollView];
[scrollView setAutohidesScrollers:YES];
[tableView setDelegate:self];
[tableView setDataSource:self];
}