26 @implementation _CPTableColumnHeaderView :
CPView
28 _CPImageAndTextView _textField;
33 return @"columnHeader";
39 forKeys:[@"background-color", @"text-alignment", @"line-break-mode", @"text-inset", @"text-color", @"font", @"text-shadow-color", @"text-shadow-offset"]];
42 - (void)initWithFrame:(CGRect)frame
44 self = [
super initWithFrame:frame];
53 _textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
55 [_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
57 [_textField setLineBreakMode:CPLineBreakByTruncatingTail];
58 [_textField setAlignment:CPLeftTextAlignment];
59 [_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
61 [
self addSubview:_textField];
64 - (void)layoutSubviews
66 [
self setBackgroundColor:[
self currentValueForThemeAttribute:@"background-color"]];
68 var inset = [
self currentValueForThemeAttribute:@"text-inset"],
69 bounds = [
self bounds];
71 [_textField setFrame:_CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
72 [_textField setTextColor:[
self currentValueForThemeAttribute:@"text-color"]];
73 [_textField setFont:[
self currentValueForThemeAttribute:@"font"]];
74 [_textField setTextShadowColor:[
self currentValueForThemeAttribute:@"text-shadow-color"]];
75 [_textField setTextShadowOffset:[
self currentValueForThemeAttribute:@"text-shadow-offset"]];
76 [_textField setAlignment:[
self currentValueForThemeAttribute:@"text-alignment"]];
77 [_textField setLineBreakMode:[
self currentValueForThemeAttribute:@"line-break-mode"]];
80 - (void)setStringValue:(
CPString)string
82 [_textField setText:string];
87 return [_textField text];
97 [_textField sizeToFit];
100 - (void)setFont:(
CPFont)aFont
102 [
self setValue:aFont forThemeAttribute:@"font"];
107 return [
self currentValueForThemeAttribute:@"font"]
110 - (void)setAlignment:(CPTextAlignment)alignment
112 [
self setValue:alignment forThemeAttribute:@"text-alignment"];
115 - (CPTextAlignment)alignment
117 return [
self currentValueForThemeAttribute:@"text-alignment"]
120 - (void)setLineBreakMode:(CPLineBreakMode)mode
122 [
self setValue:mode forThemeAttribute:@"line-break-mode"];
125 - (CPLineBreakMode)lineBreakMode
127 return [
self currentValueForThemeAttribute:@"line-break-mode"]
130 - (void)setTextColor:(
CPColor)aColor
132 [
self setValue:aColor forThemeAttribute:@"text-color"];
137 return [
self currentValueForThemeAttribute:@"text-color"]
140 - (void)setTextShadowColor:(
CPColor)aColor
142 [
self setValue:aColor forThemeAttribute:@"text-shadow-color"];
147 return [
self currentValueForThemeAttribute:@"text-shadow-color"]
150 - (void)_setIndicatorImage:(
CPImage)anImage
154 [_textField setImage:anImage];
155 [_textField setImagePosition:CPImageRight];
159 [_textField setImagePosition:CPNoImage];
165 var _CPTableColumnHeaderViewStringValueKey =
@"_CPTableColumnHeaderViewStringValueKey",
166 _CPTableColumnHeaderViewFontKey =
@"_CPTableColumnHeaderViewFontKey",
167 _CPTableColumnHeaderViewTextColorKey =
@"_CPTableColumnHeaderViewTextColorKey",
168 _CPTableColumnHeaderViewTextShadowColorKey =
@"_CPTableColumnHeaderViewTextShadowColorKey",
169 _CPTableColumnHeaderViewAlignmentKey =
@"_CPTableColumnHeaderViewAlignmentKey",
170 _CPTableColumnHeaderViewLineBreakModeKey =
@"_CPTableColumnHeaderViewLineBreakModeKey",
171 _CPTableColumnHeaderViewImageKey =
@"_CPTableColumnHeaderViewImageKey";
173 @implementation _CPTableColumnHeaderView (CPCoding)
175 - (id)initWithCoder:(
CPCoder)aCoder
177 if (
self = [super initWithCoder:aCoder])
180 [
self _setIndicatorImage:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewImageKey]];
181 [
self setStringValue:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewStringValueKey]];
182 [
self setFont:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewFontKey]];
183 [
self setTextColor:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewTextColorKey]];
184 [
self setTextShadowColor:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewTextShadowColorKey]];
185 [
self setAlignment:[aCoder decodeIntForKey:_CPTableColumnHeaderViewAlignmentKey]];
186 [
self setLineBreakMode:[aCoder decodeIntForKey:_CPTableColumnHeaderViewLineBreakModeKey]];
192 - (void)encodeWithCoder:(
CPCoder)aCoder
194 [
super encodeWithCoder:aCoder];
196 [aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
197 [aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
198 [aCoder encodeObject:[
self font] forKey:_CPTableColumnHeaderViewFontKey];
199 [aCoder encodeObject:[
self textColor] forKey:_CPTableColumnHeaderViewTextColorKey];
200 [aCoder encodeObject:[
self textShadowColor] forKey:_CPTableColumnHeaderViewTextShadowColorKey];
201 [aCoder encodeInt:[
self alignment] forKey:_CPTableColumnHeaderViewAlignmentKey];
202 [aCoder encodeInt:[
self lineBreakMode] forKey:_CPTableColumnHeaderViewLineBreakModeKey];
209 CGPoint _mouseDownLocation;
210 CGPoint _previousTrackingLocation;
216 BOOL _isTrackingColumn;
217 BOOL _drawsColumnLines;
219 float _columnOldWidth;
226 return @"tableHeaderRow";
229 + (id)themeAttributes
232 forKeys:[@"background-color", @"divider-color"]];
237 _mouseDownLocation = _CGPointMakeZero();
238 _previousTrackingLocation = _CGPointMakeZero();
244 _isTrackingColumn = NO;
245 _drawsColumnLines = YES;
247 _columnOldWidth = 0.0;
249 [
self setBackgroundColor:[
self currentValueForThemeAttribute:@"background-color"]];
252 - (id)initWithFrame:(CGRect)aFrame
262 - (int)columnAtPoint:(CGPoint)aPoint
264 return [_tableView columnAtPoint:CGPointMake(aPoint.x, aPoint.y)];
267 - (CGRect)headerRectOfColumn:(
int)aColumnIndex
269 var headerRect = CGRectMakeCopy([
self bounds]),
270 columnRect = [_tableView rectOfColumn:aColumnIndex];
272 headerRect.origin.x = _CGRectGetMinX(columnRect);
273 headerRect.size.width = _CGRectGetWidth(columnRect);
278 - (void)setDrawsColumnLines:(BOOL)aFlag
280 _drawsColumnLines = aFlag;
283 - (BOOL)drawsColumnLines
285 return _drawsColumnLines;
288 - (CGRect)_cursorRectForColumn:(
int)column
291 return _CGRectMakeZero();
293 var rect = [
self headerRectOfColumn:column];
295 rect.origin.x = _CGRectGetMaxX(rect) - 5;
296 rect.size.width = 20;
301 - (void)_setPressedColumn:(CPInteger)column
303 if (_pressedColumn != -1)
305 var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
306 [headerView unsetThemeState:CPThemeStateHighlighted];
311 var headerView = [_tableView._tableColumns[column] headerView];
312 [headerView setThemeState:CPThemeStateHighlighted];
315 _pressedColumn = column;
325 var type = [theEvent
type],
329 currentLocation.x -= 5.0;
338 else if ([
self _shouldStopTrackingTableColumn:columnIndex at:currentLocation])
340 [_tableView _didClickTableColumn:columnIndex modifierFlags:[theEvent
modifierFlags]];
343 _isTrackingColumn = NO;
346 [
self _updateResizeCursor:[CPApp currentEvent]];
354 if (columnIndex === -1)
357 _mouseDownLocation = currentLocation;
358 _activeColumn = columnIndex;
360 [_tableView _sendDelegateDidMouseDownInHeader:columnIndex];
367 _isTrackingColumn = YES;
376 if (_activeColumn === columnIndex && _CGRectContainsPoint([
self headerRectOfColumn:columnIndex], currentLocation))
378 if (_isTrackingColumn && _pressedColumn !== -1)
380 if (![
self continueTrackingTableColumn:columnIndex at:currentLocation])
385 }
else if (_isTrackingColumn && _pressedColumn !== -1)
390 _previousTrackingLocation = currentLocation;
391 [CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
394 - (void)startTrackingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
396 [
self _setPressedColumn:aColumnIndex];
399 - (BOOL)continueTrackingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
401 if ([
self _shouldDragTableColumn:aColumnIndex at:aPoint])
404 offset = _CGPointMakeZero(),
405 view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
406 viewLocation = _CGPointMakeZero();
408 viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
409 viewLocation.y = _CGRectGetMinY(columnRect) + offset.y;
420 - (BOOL)_shouldStopTrackingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
422 return _isTrackingColumn && _activeColumn === aColumnIndex &&
423 _CGRectContainsPoint([
self headerRectOfColumn:aColumnIndex], aPoint);
426 - (void)stopTrackingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
428 [
self _setPressedColumn:CPNotFound];
429 [
self _updateResizeCursor:[CPApp currentEvent]];
432 - (BOOL)_shouldDragTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
434 return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
437 - (CGRect)_headerRectOfLastVisibleColumn
439 var tableColumns = [_tableView tableColumns],
440 columnIndex = [tableColumns count];
442 while (columnIndex--)
444 var tableColumn = [tableColumns objectAtIndex:columnIndex];
446 if (![tableColumn isHidden])
447 return [
self headerRectOfColumn:columnIndex];
453 - (void)_constrainDragView:(
CPView)theDragView at:(CGPoint)aPoint
455 var tableColumns = [_tableView tableColumns],
456 lastColumnRect = [
self _headerRectOfLastVisibleColumn],
457 activeColumnRect = [
self headerRectOfColumn:_activeColumn],
458 dragWindow = [theDragView
window],
459 frame = [dragWindow frame];
462 frame.origin = [[
self window] convertGlobalToBase:frame.origin];
464 frame.origin = [
self convertPoint:frame.origin fromView:nil];
467 frame.origin.x = MAX(0.0, MIN(_CGRectGetMinX(
frame), _CGRectGetMaxX(lastColumnRect) - _CGRectGetWidth(activeColumnRect)));
470 frame.origin.y = _CGRectGetMinY(lastColumnRect);
473 frame.origin = [
self convertPoint:frame.origin toView:nil];
475 frame.origin = [[
self window] convertBaseToGlobal:frame.origin];
477 [dragWindow setFrame:frame];
480 - (void)_moveColumn:(
int)aFromIndex toColumn:(
int)aToIndex
482 [_tableView moveColumn:aFromIndex toColumn:aToIndex];
483 _activeColumn = aToIndex;
484 _pressedColumn = _activeColumn;
487 - (void)draggedView:(
CPView)aView beganAt:(CGPoint)aPoint
491 var column = [[_tableView tableColumns] objectAtIndex:_activeColumn];
493 [[column headerView] setHidden:YES];
494 [_tableView _setDraggedColumn:column];
499 - (void)draggedView:(
CPView)aView movedTo:(CGPoint)aPoint
501 [
self _constrainDragView:aView at:aPoint];
503 var dragWindow = [aView
window],
504 dragWindowFrame = [dragWindow frame];
506 var hoverPoint = CGPointCreateCopy(aPoint);
508 if (aPoint.x < _previousTrackingLocation.x)
509 hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
510 else if (aPoint.x > _previousTrackingLocation.x)
511 hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
520 if (hoveredColumn !== -1)
523 columnCenterPoint = [
self convertPoint:CGPointMake(_CGRectGetMidX(columnRect), _CGRectGetMidY(columnRect))
fromView:self];
524 if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
525 [
self _moveColumn:_activeColumn toColumn:hoveredColumn];
526 else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
527 [
self _moveColumn:_activeColumn toColumn:hoveredColumn];
530 _previousTrackingLocation = aPoint;
533 - (void)draggedView:(
CPImage)aView endedAt:(CGPoint)aLocation operation:(CPDragOperation)anOperation
536 _isTrackingColumn = NO;
538 [_tableView _setDraggedColumn:nil];
539 [[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:NO];
545 - (BOOL)shouldResizeTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
550 if (_isTrackingColumn)
553 return [_tableView allowsColumnResizing] && _CGRectContainsPoint([
self _cursorRectForColumn:aColumnIndex], aPoint);
556 - (void)startResizingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
560 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
562 [tableColumn setDisableResizingPosting:YES];
563 [_tableView setDisableAutomaticResizing:YES];
566 - (void)continueResizingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
568 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
569 newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
571 if (newWidth < [tableColumn minWidth])
573 else if (newWidth > [tableColumn maxWidth])
577 _tableView._lastColumnShouldSnap = NO;
578 [tableColumn setWidth:newWidth];
586 - (void)stopResizingTableColumn:(
int)aColumnIndex at:(CGPoint)aPoint
588 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
589 [tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
590 [tableColumn setDisableResizingPosting:NO];
591 [_tableView setDisableAutomaticResizing:NO];
596 - (void)_updateResizeCursor:(
CPEvent)theEvent
599 if (![_tableView allowsColumnResizing] || ([theEvent type] ===
CPLeftMouseUp && ![[
self window] acceptsMouseMovedEvents]))
605 var mouseLocation = [
self convertPoint:[theEvent
locationInWindow] fromView:nil],
606 mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
607 overColumn = [
self columnAtPoint:mouseOverLocation];
609 if (overColumn >= 0 && _CGRectContainsPoint([
self _cursorRectForColumn:overColumn], mouseLocation))
611 var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
612 width = [tableColumn width];
614 if (
width == [tableColumn minWidth])
616 else if (
width == [tableColumn maxWidth])
627 [
self _updateResizeCursor:theEvent];
632 [
self _updateResizeCursor:theEvent];
641 - (void)layoutSubviews
643 var tableColumns = [_tableView tableColumns],
644 count = [tableColumns count];
646 for (var i = 0; i < count; i++)
648 var column = [tableColumns objectAtIndex:i],
649 headerView = [column headerView],
653 frame.origin.x -= 0.5;
654 frame.size.width -= 1.0;
655 frame.size.height -= 0.5;
659 [headerView setFrame:frame];
661 if ([headerView superview] !=
self)
668 - (void)drawRect:(CGRect)aRect
670 if (!_tableView || ![
self drawsColumnLines])
674 exposedColumnIndexes = [_tableView columnIndexesInRect:aRect],
676 tableColumns = [_tableView tableColumns],
677 exposedTableColumns = _tableView._exposedColumns,
678 firstIndex = [exposedTableColumns firstIndex],
679 exposedRange =
CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
684 [exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
686 var columnArrayIndex = 0,
687 columnArrayCount = columnsArray.length,
691 for (; columnArrayIndex < columnArrayCount; columnArrayIndex++)
694 var columnIndex = columnsArray[columnArrayIndex],
697 columnMaxX = _CGRectGetMaxX(columnToStroke);
721 if (
self = [super initWithCoder:aCoder])
724 _tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
728 _drawsColumnLines = [aCoder decodeBoolForKey:CPTableHeaderViewDrawsColumnLines];
731 _drawsColumnLines = YES;
732 CPLog.warn(
"The tableview header being decoded is using an old cib. Please run Nib2Cib.");
742 [aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
743 [aCoder encodeBool:_drawsColumnLines forKey:CPTableHeaderViewDrawsColumnLines];