27 @implementation _CPTableColumnHeaderView :
CPView 29 _CPImageAndTextView _textField;
34 return @"columnHeader";
43 @"text-inset": CGInsetMakeZero(),
47 @"text-shadow-offset": CGSizeMakeZero()
51 - (id)initWithFrame:(CGRect)frame
53 self = [
super initWithFrame:frame];
63 _textField = [[_CPImageAndTextView alloc] initWithFrame:
64 CGRectMake(5.0, 0.0, CGRectGetWidth([
self bounds]) - 10.0, CGRectGetHeight([
self bounds]))];
66 [_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
68 [_textField setLineBreakMode:CPLineBreakByTruncatingTail];
71 [_textField setAlignment:CPLeftTextAlignment];
72 [_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
74 [_textField setTextShadowOffset:CGSizeMake(0,1)];
76 [
self addSubview:_textField];
79 - (void)layoutSubviews
81 [
self setBackgroundColor:[
self currentValueForThemeAttribute:@"background-color"]];
83 var inset = [
self currentValueForThemeAttribute:@"text-inset"],
86 [_textField setFrame:CGRectMake(inset.left, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
87 [_textField setTextColor:[
self currentValueForThemeAttribute:@"text-color"]];
88 [_textField setFont:[
self currentValueForThemeAttribute:@"font"]];
89 [_textField setTextShadowColor:[
self currentValueForThemeAttribute:@"text-shadow-color"]];
90 [_textField setTextShadowOffset:[
self currentValueForThemeAttribute:@"text-shadow-offset"]];
91 [_textField setAlignment:[
self currentValueForThemeAttribute:@"text-alignment"]];
92 [_textField setLineBreakMode:[
self currentValueForThemeAttribute:@"line-break-mode"]];
95 - (void)setStringValue:(
CPString)string
97 [_textField setText:string];
102 return [_textField text];
112 [_textField sizeToFit];
115 - (void)setFont:(
CPFont)aFont
117 [
self setValue:aFont forThemeAttribute:@"font"];
122 return [
self currentValueForThemeAttribute:@"font"];
125 - (void)setAlignment:(CPTextAlignment)alignment
127 [
self setValue:alignment forThemeAttribute:@"text-alignment"];
130 - (CPTextAlignment)alignment
132 return [
self currentValueForThemeAttribute:@"text-alignment"];
135 - (void)setLineBreakMode:(CPLineBreakMode)mode
137 [
self setValue:mode forThemeAttribute:@"line-break-mode"];
140 - (CPLineBreakMode)lineBreakMode
142 return [
self currentValueForThemeAttribute:@"line-break-mode"];
145 - (void)setTextColor:(
CPColor)aColor
147 [
self setValue:aColor forThemeAttribute:@"text-color"];
152 return [
self currentValueForThemeAttribute:@"text-color"];
155 - (void)setTextShadowColor:(
CPColor)aColor
157 [
self setValue:aColor forThemeAttribute:@"text-shadow-color"];
162 return [
self currentValueForThemeAttribute:@"text-shadow-color"];
165 - (void)_setIndicatorImage:(
CPImage)anImage
169 [_textField setImage:anImage];
170 [_textField setImagePosition:CPImageRight];
174 [_textField setImagePosition:CPNoImage];
180 return [_textField imagePosition] ===
CPNoImage ? nil : [_textField image];
183 - (void)drawRect:(CGRect)aRect
185 var
bounds = [
self bounds];
187 if (!CGRectIntersectsRect(aRect,
bounds))
191 maxX = CGRectGetMaxX(
bounds) - 0.5;
206 var _CPTableColumnHeaderViewStringValueKey =
@"_CPTableColumnHeaderViewStringValueKey",
207 _CPTableColumnHeaderViewFontKey =
@"_CPTableColumnHeaderViewFontKey",
208 _CPTableColumnHeaderViewImageKey =
@"_CPTableColumnHeaderViewImageKey",
209 _CPTableColumnHeaderViewIsDraggingKey =
@"_CPTableColumnHeaderViewIsDraggingKey";
211 @implementation _CPTableColumnHeaderView (CPCoding)
213 - (id)initWithCoder:(
CPCoder)aCoder
215 if (
self = [super initWithCoder:aCoder])
218 [
self _setIndicatorImage:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewImageKey]];
219 [
self setStringValue:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewStringValueKey]];
220 [
self setFont:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewFontKey]];
226 - (void)encodeWithCoder:(
CPCoder)aCoder
228 [
super encodeWithCoder:aCoder];
230 [aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
231 [aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
232 [aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
244 CGPoint _mouseDownLocation;
245 CGPoint _columnMouseDownLocation;
246 CGPoint _mouseEnterExitLocation;
247 CGPoint _previousTrackingLocation;
257 CPView _columnDragHeaderView;
258 CPView _columnDragClipView;
260 float _columnOldWidth;
267 return @"tableHeaderRow";
275 @"divider-thickness": 1.0
281 _mouseDownLocation = CGPointMakeZero();
282 _columnMouseDownLocation = CGPointMakeZero();
283 _mouseEnterExitLocation = CGPointMakeZero();
284 _previousTrackingLocation = CGPointMakeZero();
293 _columnOldWidth = 0.0;
295 [
self setBackgroundColor:[
self currentValueForThemeAttribute:@"background-color"]];
298 - (id)initWithFrame:(CGRect)aFrame
312 - (CPInteger)draggedColumn
314 return _isDragging ? _activeColumn : -1;
317 - (float)draggedDistance
320 return (CGRectGetMinX(_columnDragClipView) - _columnMouseDownLocation.x);
325 - (CPInteger)resizedColumn
328 return _activeColumn;
335 - (CPInteger)columnAtPoint:(CGPoint)aPoint
337 return [_tableView columnAtPoint:aPoint];
340 - (CGRect)headerRectOfColumn:(CPInteger)aColumnIndex
342 var headerRect = [
self bounds],
343 columnRect = [_tableView rectOfColumn:aColumnIndex];
345 headerRect.origin.x = CGRectGetMinX(columnRect);
346 headerRect.size.width = CGRectGetWidth(columnRect);
353 - (void)viewDidMoveToWindow
360 - (void)layoutSubviews
362 var tableColumns = [_tableView tableColumns],
363 count = [tableColumns count];
365 for (var i = 0; i < count; i++)
367 var column = [tableColumns objectAtIndex:i],
368 headerView = [column headerView],
371 [headerView setFrame:frame];
373 if ([headerView superview] !=
self)
389 _mouseDownLocation = currentLocation;
391 _canDragColumn = YES;
393 [_tableView _sendDelegateMouseDownInHeaderOfTableColumn:columnIndex];
395 if ([
self _shouldResizeTableColumn:
columnIndex at:currentLocation])
396 [
self _startResizingTableColumn:columnIndex at:currentLocation];
398 [
self _setPressedColumn:columnIndex];
409 [
self _autoscroll:theEvent localLocation:currentLocation];
410 [
self _continueResizingTableColumn:_activeColumn at:currentLocation];
412 else if (_isDragging)
414 [
self _autoscroll:theEvent localLocation:currentLocation];
415 [
self _dragTableColumn:_activeColumn to:currentLocation];
419 if (CGRectContainsPoint([
self headerRectOfColumn:_activeColumn], currentLocation))
421 if ([
self _shouldDragTableColumn:
columnIndex at:currentLocation])
422 [
self _startDraggingTableColumn:columnIndex at:currentLocation];
424 [
self _setPressedColumn:_activeColumn];
427 [
self _setPressedColumn:-1];
435 [
self _stopResizingTableColumn:_activeColumn];
437 else if (_isDragging)
439 [
self _stopDraggingTableColumn:_activeColumn];
441 else if (_activeColumn != -1)
445 if (CGRectContainsPoint([
self headerRectOfColumn:_activeColumn], currentLocation))
446 [_tableView _didClickTableColumn:_activeColumn modifierFlags:[theEvent
modifierFlags]];
449 [
self _setPressedColumn:-1];
450 [
self _updateResizeCursor:[CPApp currentEvent]];
462 - (void)updateTrackingAreas
464 if (_tableHeaderViewTrackingAreas)
466 for (var i = 0, count = [_tableHeaderViewTrackingAreas count]; i < count; i++)
467 [
self removeTrackingArea:_tableHeaderViewTrackingAreas[i]];
469 _tableHeaderViewTrackingAreas = nil;
477 _tableHeaderViewTrackingAreas = @[];
479 for (var i = 0; i < _tableView._tableColumns.length; i++)
494 [
self _updateResizeCursor:anEvent];
501 - (CGRect)_cursorRectForColumn:(CPInteger)column
504 return CGRectMakeZero();
514 - (void)_setPressedColumn:(CPInteger)column
516 if (_pressedColumn === column)
519 if (_pressedColumn != -1)
521 var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
522 [headerView unsetThemeState:CPThemeStateHighlighted];
527 var headerView = [_tableView._tableColumns[column] headerView];
528 [headerView setThemeState:CPThemeStateHighlighted];
536 _pressedColumn = column;
539 - (BOOL)_shouldDragTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
544 - (void)_autoscroll:(
CPEvent)theEvent localLocation:(CGPoint)theLocation
547 var constrainedLocation = CGPointMake(theLocation.x, CGRectGetMaxY([
self frame])),
549 location:[
self convertPoint:constrainedLocation toView:nil]
558 [
self autoscroll:constrainedEvent];
559 [_tableView autoscroll:constrainedEvent];
562 - (CGRect)_headerRectOfLastVisibleColumn
564 var tableColumns = [_tableView tableColumns],
569 var tableColumn = [tableColumns objectAtIndex:columnIndex];
572 return [
self headerRectOfColumn:columnIndex];
578 - (CGPoint)_constrainDragPoint:(CGPoint)aPoint
581 var visibleRect = [_tableView visibleRect],
582 lastColumnRect = [
self _headerRectOfLastVisibleColumn],
583 activeColumnRect = [
self headerRectOfColumn:_activeColumn],
584 maxX = CGRectGetMaxX(lastColumnRect) - CGRectGetWidth(activeColumnRect) - CGRectGetMinX(visibleRect),
585 point = CGPointMake(MAX(MIN(aPoint.x, maxX), -CGRectGetMinX(visibleRect)), aPoint.y);
590 - (void)_moveColumn:(CPInteger)aFromIndex toColumn:(CPInteger)aToIndex
592 [_tableView moveColumn:aFromIndex toColumn:aToIndex];
593 _activeColumn = aToIndex;
594 _pressedColumn = _activeColumn;
596 [_tableView _setDraggedColumn:_activeColumn];
598 [
self setNeedsDisplay:YES];
606 - (void)_startDraggingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
609 _columnDragView = [_tableView _dragViewForColumn:aColumnIndex];
610 _previousTrackingLocation = aPoint;
613 var headerHeight = CGRectGetHeight([
self frame]),
614 scrollView = [
self enclosingScrollView],
615 contentFrame = [[scrollView contentView] frame];
617 contentFrame.origin.y -= headerHeight;
618 contentFrame.size.height += headerHeight;
620 _columnDragClipView = [[
CPView alloc] initWithFrame:contentFrame];
622 [_columnDragClipView addSubview:_columnDragView];
625 [scrollView addSubview:_columnDragClipView positioned:CPWindowAbove relativeTo:self];
628 var headerView = [[[_tableView tableColumns] objectAtIndex:aColumnIndex] headerView];
630 [[headerView subviews] makeObjectsPerformSelector:@selector(setHidden:) withObject:YES];
633 [headerView unsetThemeStates:[CPThemeStateHighlighted, CPThemeStateSelected]];
636 _columnDragHeaderView = [_columnDragView viewWithTag:CPTableHeaderViewDragColumnHeaderTag];
638 _columnMouseDownLocation = [
self convertPoint:_mouseDownLocation toView:_columnDragHeaderView];
640 [_tableView _setDraggedColumn:aColumnIndex];
644 [
self setNeedsDisplay:YES];
647 - (void)_dragTableColumn:(CPInteger)aColumnIndex to:(CGPoint)aPoint
649 var delta = aPoint.x - _previousTrackingLocation.x,
650 columnPoint = [_columnDragHeaderView convertPoint:aPoint fromView:self];
653 if ((delta > 0 && columnPoint.x > _columnMouseDownLocation.x) || (delta < 0 && columnPoint.x < _columnMouseDownLocation.x))
655 var dragFrame = [_columnDragView frame],
656 newOrigin = [
self _constrainDragPoint:CGPointMake(CGRectGetMinX(dragFrame) + delta, CGRectGetMinY(dragFrame))];
658 [_columnDragView setFrameOrigin:newOrigin];
661 var hoverPoint = CGPointMakeCopy(aPoint);
664 dragFrame = [
self convertRect:dragFrame fromView:[_columnDragView superview]];
667 hoverPoint.x = CGRectGetMaxX(dragFrame);
669 hoverPoint.x = CGRectGetMinX(dragFrame);
671 var hoveredColumn = [
self columnAtPoint:hoverPoint];
673 if (hoveredColumn !== -1)
675 var columnRect = [
self headerRectOfColumn:hoveredColumn],
676 columnCenterPoint = CGPointMake(CGRectGetMidX(columnRect), CGRectGetMidY(columnRect));
678 if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
679 [
self _moveColumn:_activeColumn toColumn:hoveredColumn];
680 else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
681 [
self _moveColumn:_activeColumn toColumn:hoveredColumn];
685 _previousTrackingLocation = aPoint;
688 - (void)_stopDraggingTableColumn:(CPInteger)aColumnIndex
692 [_columnDragClipView removeFromSuperview];
693 [_tableView _setDraggedColumn:-1];
695 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
696 headerView = [tableColumn headerView];
698 [[headerView subviews] makeObjectsPerformSelector:@selector(setHidden:) withObject:NO];
700 if (_tableView._draggedColumnIsSelected)
701 [headerView setThemeState:CPThemeStateSelected];
703 [_tableView _reloadDataViews];
704 [[_tableView headerView] setNeedsLayout];
707 [
self updateTrackingAreas];
709 [_tableView _sendDelegateDidDragTableColumn:tableColumn];
712 - (BOOL)_shouldResizeTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
717 return [_tableView allowsColumnResizing] && CGRectContainsPoint([
self _cursorRectForColumn:aColumnIndex], aPoint);
720 - (void)_startResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
723 _previousTrackingLocation = aPoint;
724 _activeColumn = aColumnIndex;
726 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
728 _columnOldWidth = [tableColumn width];
730 [tableColumn setDisableResizingPosting:YES];
731 [_tableView setDisableAutomaticResizing:YES];
734 - (void)_continueResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
736 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
737 delta = aPoint.x - _previousTrackingLocation.x,
738 spacing = [_tableView intercellSpacing].
width,
739 newWidth = [tableColumn
width] + spacing + delta,
740 minWidth = [tableColumn minWidth] + spacing,
741 maxWidth = [tableColumn maxWidth] + spacing;
743 if (newWidth <= minWidth)
745 else if (newWidth >= maxWidth)
750 var columnRect = [_tableView rectOfColumn:aColumnIndex],
751 columnWidth = CGRectGetWidth(columnRect);
753 if ((delta > 0 && columnWidth == maxWidth) || (delta < 0 && columnWidth == minWidth))
756 var columnMinX = CGRectGetMinX(columnRect),
757 columnMaxX = CGRectGetMaxX(columnRect);
759 if ((delta > 0 && aPoint.x > columnMaxX) || (delta < 0 && aPoint.x < columnMaxX))
761 [tableColumn setWidth:newWidth - spacing];
763 [
self setNeedsLayout];
764 [
self setNeedsDisplay:YES];
767 _previousTrackingLocation = aPoint;
770 - (void)_stopResizingTableColumn:(CPInteger)aColumnIndex
772 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
774 if ([tableColumn
width] != _columnOldWidth)
776 [_tableView _didResizeTableColumn:tableColumn oldWidth:_columnOldWidth];
777 [
self updateTrackingAreas];
780 [tableColumn setDisableResizingPosting:NO];
781 [_tableView setDisableAutomaticResizing:NO];
786 - (void)_updateResizeCursor:(
CPEvent)theEvent
788 var mouseLocation = [
self convertPoint:[theEvent
locationInWindow] fromView:nil],
790 overColumn = [
self columnAtPoint:mouseOverLocation];
792 if (overColumn >= 0 && CGRectContainsPoint([
self _cursorRectForColumn:overColumn], mouseLocation))
794 var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
795 spacing = [_tableView intercellSpacing].width,
796 width = [tableColumn width];
798 if (
width <= [tableColumn minWidth])
800 else if (
width >= [tableColumn maxWidth])
817 if (
self = [super initWithCoder:aCoder])
820 _tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
829 [aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
id initWithFrame:(CGRect aFrame)
id mouseEventWithType:location:modifierFlags:timestamp:windowNumber:context:eventNumber:clickCount:pressure:(CPEventType anEventType, [location] CGPoint aPoint, [modifierFlags] unsigned modifierFlags, [timestamp] CPTimeInterval aTimestamp, [windowNumber] int aWindowNumber, [context] CPGraphicsContext aGraphicsContext, [eventNumber] int anEventNumber, [clickCount] int aClickCount, [pressure] float aPressure)
void addSubview:(CPView aSubview)
CPGraphicsContext currentContext()
An object representation of nil.
CPTableColumnUserResizingMask
CPCursor resizeRightCursor()
function CGContextSetStrokeColor(aContext, aColor)
CGPoint locationInWindow()
CPTrackingActiveInKeyWindow
function CGContextAddLineToPoint(aContext, x, y)
void setAcceptsMouseMovedEvents:(BOOL shouldAcceptMouseMovedEvents)
function CGContextStrokePath(aContext)
A mutable key-value pair collection.
function CGContextSetLineWidth(aContext, aLineWidth)
CPCursor closedHandCursor()
An immutable string (collection of characters).
CGPoint convertPoint:fromView:(CGPoint aPoint, [fromView] CPView aView)
CPCellImagePosition CPNoImage
CPColor colorWithRed:green:blue:alpha:(float red, [green] float green, [blue] float blue, [alpha] float alpha)
void viewDidMoveToWindow()
CPCursor resizeLeftRightCursor()
void encodeWithCoder:(CPCoder aCoder)
function CGContextBeginPath(aContext)
CPLineBreakByTruncatingTail
CPTimeInterval timestamp()
CPFont boldSystemFontOfSize:(CGSize aSize)
Defines methods for use when archiving & restoring (enc/decoding).
void updateTrackingAreas()
void addTrackingArea:(CPTrackingArea trackingArea)
CPTextAlignment CPLeftTextAlignment
CPTrackingArea initWithRect:options:owner:userInfo:(CGRect aRect, [options] CPTrackingAreaOptions options, [owner] id owner, [userInfo] CPDictionary userInfo)
function CGContextMoveToPoint(aContext, x, y)
CPCursor resizeLeftCursor()