00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPTableColumn.j"
00024 @import "CPTableView.j"
00025 @import "CPView.j"
00026
00027 @implementation _CPTableColumnHeaderView : CPView
00028 {
00029 _CPImageAndTextView _textField;
00030 }
00031
00032 - (void)initWithFrame:(CGRect)frame
00033 {
00034 self = [super initWithFrame:frame];
00035 if (self)
00036 {
00037 [self _init];
00038 }
00039
00040 return self;
00041 }
00042
00043 - (void)_init
00044 {
00045 _textField = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(5, 1, CGRectGetWidth([self bounds]) - 10, CGRectGetHeight([self bounds]) - 1)];
00046 [_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
00047
00048 [_textField setLineBreakMode:CPLineBreakByTruncatingTail];
00049 [_textField setTextColor: [CPColor colorWithHexString: @"333333"]];
00050 [_textField setFont:[CPFont boldSystemFontOfSize:12.0]];
00051 [_textField setAlignment:CPLeftTextAlignment];
00052 [_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
00053 [_textField setTextShadowColor:[CPColor whiteColor]];
00054 [_textField setTextShadowOffset:CGSizeMake(0,1)];
00055
00056 [self addSubview:_textField];
00057 }
00058
00059 - (void)layoutSubviews
00060 {
00061 var themeState = [self themeState];
00062
00063 if(themeState & CPThemeStateSelected && themeState & CPThemeStateHighlighted)
00064 [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]];
00065 else if (themeState & CPThemeStateSelected)
00066 [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]];
00067 else if (themeState & CPThemeStateHighlighted)
00068 [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]];
00069 else
00070 [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
00071 }
00072
00073 - (void)setStringValue:(CPString)string
00074 {
00075 [_textField setText:string];
00076 }
00077
00078 - (CPString)stringValue
00079 {
00080 return [_textField text];
00081 }
00082
00083 - (void)textField
00084 {
00085 return _textField;
00086 }
00087
00088 - (void)sizeToFit
00089 {
00090 [_textField sizeToFit];
00091 }
00092
00093 - (void)setFont:(CPFont)aFont
00094 {
00095 [_textField setFont:aFont];
00096 }
00097
00098 - (void)setValue:(id)aValue forThemeAttribute:(id)aKey
00099 {
00100 [_textField setValue:aValue forThemeAttribute:aKey];
00101 }
00102
00103 - (void)_setIndicatorImage:(CPImage)anImage
00104 {
00105 if (anImage)
00106 {
00107 [_textField setImage:anImage];
00108 [_textField setImagePosition:CPImageRight];
00109 }
00110 else
00111 {
00112 [_textField setImagePosition:CPNoImage];
00113 }
00114 }
00115
00116 @end
00117
00118 var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringValueKey",
00119 _CPTableColumnHeaderViewFontKey = @"_CPTableColumnHeaderViewFontKey",
00120 _CPTableColumnHeaderViewImageKey = @"_CPTableColumnHeaderViewImageKey";
00121
00122 @implementation _CPTableColumnHeaderView (CPCoding)
00123
00124 - (id)initWithCoder:(CPCoder)aCoder
00125 {
00126 if (self = [super initWithCoder:aCoder])
00127 {
00128 [self _init];
00129 [self _setIndicatorImage:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewImageKey]];
00130 [self setStringValue:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewStringValueKey]];
00131 [self setFont:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewFontKey]];
00132 }
00133
00134 return self;
00135 }
00136
00137 - (void)encodeWithCoder:(CPCoder)aCoder
00138 {
00139 [super encodeWithCoder:aCoder];
00140
00141 [aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
00142 [aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
00143 [aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
00144 }
00145
00146 @end
00147
00148 @implementation CPTableHeaderView : CPView
00149 {
00150 int _resizedColumn @accessors(readonly, property=resizedColumn);
00151 int _draggedColumn @accessors(readonly, property=draggedColumn);
00152 int _pressedColumn @accessors(readonly, property=pressedColumn);
00153
00154 float _draggedDistance @accessors(readonly, property=draggedDistance);
00155 float _lastLocation;
00156 float _columnOldWidth;
00157
00158 CPTableView _tableView @accessors(property=tableView);
00159 }
00160
00161 - (void)_init
00162 {
00163 _resizedColumn = -1;
00164 _draggedColumn = -1;
00165 _pressedColumn = -1;
00166 _draggedDistance = 0.0;
00167 _lastLocation = nil;
00168 _columnOldWidth = nil;
00169
00170 [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
00171 }
00172
00173 - (id)initWithFrame:(CGRect)aFrame
00174 {
00175 self = [super initWithFrame:aFrame];
00176
00177 if (self)
00178 [self _init];
00179
00180 return self;
00181 }
00182
00183 - (int)columnAtPoint:(CGPoint)aPoint
00184 {
00185 return [_tableView columnAtPoint:CGPointMake(aPoint.x, 0)];
00186 }
00187
00188 - (CGRect)headerRectOfColumn:(int)aColumnIndex
00189 {
00190 var tableColumns = [_tableView tableColumns];
00191
00192 if (aColumnIndex < 0 || aColumnIndex > [tableColumns count])
00193 [CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"];
00194
00195
00196
00197 var tableRange = _tableView._tableColumnRanges[aColumnIndex],
00198 bounds = [self bounds];
00199
00200 var rMinX = ROUND(tableRange.location);
00201 bounds.origin.x = rMinX;
00202 bounds.size.width = FLOOR(tableRange.length + tableRange.location - rMinX);
00203
00204 return bounds;
00205 }
00206
00207 - (CGRect)_cursorRectForColumn:(int)column
00208 {
00209 if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
00210 return CGRectMakeZero();
00211
00212 var rect = [self headerRectOfColumn:column];
00213
00214 rect.origin.x = CGRectGetMaxX(rect) - 5;
00215 rect.size.width = 20;
00216
00217 return rect;
00218 }
00219
00220 - (void)_setPressedColumn:(CPInteger)column
00221 {
00222 if (_pressedColumn != -1)
00223 {
00224 var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
00225 [headerView unsetThemeState:CPThemeStateHighlighted];
00226 }
00227
00228 if (column != -1)
00229 {
00230 var headerView = [_tableView._tableColumns[column] headerView];
00231 [headerView setThemeState:CPThemeStateHighlighted];
00232 }
00233
00234 _pressedColumn = column;
00235 }
00236
00237 - (void)mouseDown:(CPEvent)theEvent
00238 {
00239 var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
00240 clickedColumn = [self columnAtPoint:mouseLocation];
00241
00242
00243 [_tableView _sendDelegateDidMouseDownInHeader:clickedColumn];
00244
00245 var resizeLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
00246 resizedColumn = [self columnAtPoint:resizeLocation];
00247
00248 if (resizedColumn == -1)
00249 return;
00250
00251
00252 if ([_tableView allowsColumnResizing]
00253 && CGRectContainsPoint([self _cursorRectForColumn:resizedColumn], mouseLocation))
00254 {
00255 _resizedColumn = resizedColumn;
00256 [_tableView._tableColumns[_resizedColumn] setDisableResizingPosting:YES];
00257 [_tableView setDisableAutomaticResizing:YES];
00258 [self trackResizeWithEvent:theEvent];
00259 }
00260 else
00261 {
00262 [self _setPressedColumn:clickedColumn];
00263 [self trackMouseWithEvent:theEvent];
00264 }
00265 }
00266
00267 - (void)trackMouseWithEvent:(CPEvent)theEvent
00268 {
00269 var type = [theEvent type];
00270
00271 if (type == CPLeftMouseUp)
00272 {
00273 var location = [self convertPoint:[theEvent locationInWindow] fromView:nil],
00274 clickedColumn = [self columnAtPoint:location];
00275
00276 [self _setPressedColumn:-1];
00277
00278 if (clickedColumn != -1)
00279 [_tableView _didClickTableColumn:clickedColumn modifierFlags:[theEvent modifierFlags]];
00280
00281 return;
00282 }
00283
00284 [CPApp setTarget:self selector:@selector(trackMouseWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPLeftMouseDownMask untilDate:nil inMode:nil dequeue:YES];
00285 }
00286
00287 - (void)trackResizeWithEvent:(CPEvent)anEvent
00288 {
00289 var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
00290 tableColumn = [[_tableView tableColumns] objectAtIndex:_resizedColumn],
00291 type = [anEvent type];
00292
00293 if (_lastLocation == nil)
00294 _lastLocation = location;
00295
00296 if (_columnOldWidth == nil)
00297 _columnOldWidth = [tableColumn width];
00298
00299 if (type === CPLeftMouseUp)
00300 {
00301 [self _updateResizeCursor:anEvent];
00302
00303 [tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
00304 [tableColumn setDisableResizingPosting:NO];
00305 [_tableView setDisableAutomaticResizing:NO];
00306
00307 _resizedColumn = -1;
00308 _lastLocation = nil;
00309 _columnOldWidth = nil;
00310
00311 return;
00312 }
00313 else if (type === CPLeftMouseDragged)
00314 {
00315 var newWidth = [tableColumn width] + location.x - _lastLocation.x;
00316
00317 if (newWidth < [tableColumn minWidth])
00318 [[CPCursor resizeRightCursor] set];
00319 else if (newWidth > [tableColumn maxWidth])
00320 [[CPCursor resizeLeftCursor] set];
00321 else
00322 {
00323 _tableView._lastColumnShouldSnap = NO;
00324 [tableColumn setWidth:newWidth];
00325
00326
00327
00328 _lastLocation = location;
00329
00330 [[CPCursor resizeLeftRightCursor] set];
00331 [self setNeedsLayout];
00332 [self setNeedsDisplay:YES];
00333 }
00334 }
00335
00336 [CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
00337 }
00338
00339 - (void)_updateResizeCursor:(CPEvent)theEvent
00340 {
00341
00342 if (![_tableView allowsColumnResizing] || ([theEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents]))
00343 {
00344 [[CPCursor arrowCursor] set];
00345 return;
00346 }
00347
00348 var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
00349 mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
00350 overColumn = [self columnAtPoint:mouseOverLocation];
00351
00352 if (overColumn >= 0 && CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
00353 {
00354 var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
00355 width = [tableColumn width];
00356
00357 if (width == [tableColumn minWidth])
00358 [[CPCursor resizeRightCursor] set];
00359 else if (width == [tableColumn maxWidth])
00360 [[CPCursor resizeLeftCursor] set];
00361 else
00362 [[CPCursor resizeLeftRightCursor] set];
00363 }
00364 else
00365 [[CPCursor arrowCursor] set];
00366 }
00367
00368 - (void)viewDidMoveToWindow
00369 {
00370
00371
00372 }
00373
00374 - (void)mouseEntered:(CPEvent)theEvent
00375 {
00376 [self _updateResizeCursor:theEvent];
00377 }
00378
00379 - (void)mouseMoved:(CPEvent)theEvent
00380 {
00381 [self _updateResizeCursor:theEvent];
00382 }
00383
00384 - (void)mouseExited:(CPEvent)theEvent
00385 {
00386
00387 [[CPCursor arrowCursor] set];
00388 }
00389
00390 - (void)layoutSubviews
00391 {
00392 var tableColumns = [_tableView tableColumns],
00393 count = [tableColumns count];
00394
00395 for (var i = 0; i < count; i++)
00396 {
00397 var column = [tableColumns objectAtIndex:i],
00398 headerView = [column headerView];
00399
00400 var frame = [self headerRectOfColumn:i];
00401 frame.size.height -= 0.5;
00402 if (i > 0)
00403 {
00404 frame.origin.x += 0.5;
00405 frame.size.width -= 1;
00406 }
00407
00408 [headerView setFrame:frame];
00409
00410 if([headerView superview] != self)
00411 [self addSubview:headerView];
00412 }
00413 }
00414
00415 - (void)drawRect:(CGRect)aRect
00416 {
00417 if (!_tableView)
00418 return;
00419
00420 var context = [[CPGraphicsContext currentContext] graphicsPort],
00421 exposedColumnIndexes = [_tableView columnIndexesInRect:aRect],
00422 columnsArray = [],
00423 tableColumns = [_tableView tableColumns],
00424 exposedTableColumns = _tableView._exposedColumns,
00425 firstIndex = [exposedTableColumns firstIndex],
00426 exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
00427
00428 CGContextSetLineWidth(context, 1);
00429 CGContextSetStrokeColor(context, [_tableView gridColor]);
00430
00431 [exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
00432
00433 var columnArrayIndex = 0,
00434 columnArrayCount = columnsArray.length,
00435 columnMaxX;
00436
00437 CGContextBeginPath(context);
00438 for(; columnArrayIndex < columnArrayCount; columnArrayIndex++)
00439 {
00440
00441 var columnIndex = columnsArray[columnArrayIndex],
00442 columnToStroke = [self headerRectOfColumn:columnIndex];
00443
00444 columnMaxX = CGRectGetMaxX(columnToStroke);
00445
00446 CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMinY(columnToStroke)));
00447 CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke)));
00448 }
00449
00450 CGContextClosePath(context);
00451 CGContextStrokePath(context);
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 }
00474
00475 @end
00476
00477 var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey";
00478
00479 @implementation CPTableHeaderView (CPCoding)
00480
00481 - (id)initWithCoder:(CPCoder)aCoder
00482 {
00483 if (self = [super initWithCoder:aCoder])
00484 {
00485 [self _init];
00486 _tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
00487 }
00488
00489 return self;
00490 }
00491
00492 - (void)encodeWithCoder:(CPCoder)aCoder
00493 {
00494 [super encodeWithCoder:aCoder];
00495 [aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
00496 }
00497
00498 @end
00499