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.right, 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
310 - (CPInteger)draggedColumn
312 return _isDragging ? _activeColumn : -1;
315 - (float)draggedDistance
318 return (CGRectGetMinX(_columnDragClipView) - _columnMouseDownLocation.x);
323 - (CPInteger)resizedColumn
326 return _activeColumn;
333 - (CPInteger)columnAtPoint:(CGPoint)aPoint
335 return [_tableView columnAtPoint:aPoint];
338 - (CGRect)headerRectOfColumn:(CPInteger)aColumnIndex
340 var headerRect = [
self bounds],
341 columnRect = [_tableView rectOfColumn:aColumnIndex];
343 headerRect.origin.x = CGRectGetMinX(columnRect);
344 headerRect.size.width = CGRectGetWidth(columnRect);
351 - (void)viewDidMoveToWindow
358 - (void)layoutSubviews
360 var tableColumns = [_tableView tableColumns],
361 count = [tableColumns count];
363 for (var i = 0; i < count; i++)
365 var column = [tableColumns objectAtIndex:i],
366 headerView = [column headerView],
369 [headerView setFrame:frame];
371 if ([headerView superview] !=
self)
387 _mouseDownLocation = currentLocation;
389 _canDragColumn = YES;
391 [_tableView _sendDelegateMouseDownInHeaderOfTableColumn:columnIndex];
393 if ([
self _shouldResizeTableColumn:
columnIndex at:currentLocation])
394 [
self _startResizingTableColumn:columnIndex at:currentLocation];
396 [
self _setPressedColumn:columnIndex];
407 [
self _autoscroll:theEvent localLocation:currentLocation];
408 [
self _continueResizingTableColumn:_activeColumn at:currentLocation];
410 else if (_isDragging)
414 [
self _dragTableColumn:_activeColumn to:currentLocation];
418 if (CGRectContainsPoint([
self headerRectOfColumn:_activeColumn], currentLocation))
420 if ([
self _shouldDragTableColumn:
columnIndex at:currentLocation])
421 [
self _startDraggingTableColumn:columnIndex at:currentLocation];
423 [
self _setPressedColumn:_activeColumn];
426 [
self _setPressedColumn:-1];
434 [
self _stopResizingTableColumn:_activeColumn];
436 else if (_isDragging)
438 [
self _stopDraggingTableColumn:_activeColumn];
440 else if (_activeColumn != -1)
444 if (CGRectContainsPoint([
self headerRectOfColumn:_activeColumn], currentLocation))
445 [_tableView _didClickTableColumn:_activeColumn modifierFlags:[theEvent
modifierFlags]];
448 [
self _setPressedColumn:-1];
449 [
self _updateResizeCursor:[CPApp currentEvent]];
458 if (CGPointEqualToPoint(location, _mouseEnterExitLocation))
461 _mouseEnterExitLocation = location;
463 [
self _updateResizeCursor:theEvent];
468 [
self _updateResizeCursor:theEvent];
475 if (CGPointEqualToPoint(location, _mouseEnterExitLocation))
478 _mouseEnterExitLocation = location;
488 - (CGRect)_cursorRectForColumn:(CPInteger)column
491 return CGRectMakeZero();
501 - (void)_setPressedColumn:(CPInteger)column
503 if (_pressedColumn === column)
506 if (_pressedColumn != -1)
508 var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
509 [headerView unsetThemeState:CPThemeStateHighlighted];
514 var headerView = [_tableView._tableColumns[column] headerView];
515 [headerView setThemeState:CPThemeStateHighlighted];
523 _pressedColumn = column;
526 - (BOOL)_shouldDragTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
531 - (void)_autoscroll:(
CPEvent)theEvent localLocation:(CGPoint)theLocation
534 var constrainedLocation = CGPointMake(theLocation.x, CGRectGetMinY([_tableView visibleRect])),
536 location:[
self convertPoint:constrainedLocation toView:nil]
545 [
self autoscroll:constrainedEvent];
546 [_tableView autoscroll:constrainedEvent];
549 - (CGRect)_headerRectOfLastVisibleColumn
551 var tableColumns = [_tableView tableColumns],
556 var tableColumn = [tableColumns objectAtIndex:columnIndex];
559 return [
self headerRectOfColumn:columnIndex];
565 - (CGPoint)_constrainDragPoint:(CGPoint)aPoint
568 var visibleRect = [_tableView visibleRect],
569 lastColumnRect = [
self _headerRectOfLastVisibleColumn],
570 activeColumnRect = [
self headerRectOfColumn:_activeColumn],
571 maxX = CGRectGetMaxX(lastColumnRect) - CGRectGetWidth(activeColumnRect) - CGRectGetMinX(visibleRect),
572 point = CGPointMake(MAX(MIN(aPoint.x, maxX), -CGRectGetMinX(visibleRect)), aPoint.y);
577 - (void)_moveColumn:(CPInteger)aFromIndex toColumn:(CPInteger)aToIndex
579 [_tableView moveColumn:aFromIndex toColumn:aToIndex];
580 _activeColumn = aToIndex;
581 _pressedColumn = _activeColumn;
583 [_tableView _setDraggedColumn:_activeColumn];
585 [
self setNeedsDisplay:YES];
593 - (void)_startDraggingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
596 _columnDragView = [_tableView _dragViewForColumn:aColumnIndex];
597 _previousTrackingLocation = aPoint;
600 var headerHeight = CGRectGetHeight([
self frame]),
601 scrollView = [
self enclosingScrollView],
602 contentFrame = [[scrollView contentView] frame];
604 contentFrame.origin.y -= headerHeight;
605 contentFrame.size.height += headerHeight;
607 _columnDragClipView = [[
CPView alloc] initWithFrame:contentFrame];
609 [_columnDragClipView addSubview:_columnDragView];
612 [scrollView addSubview:_columnDragClipView positioned:CPWindowAbove relativeTo:self];
615 var headerView = [[[_tableView tableColumns] objectAtIndex:aColumnIndex] headerView];
617 [[headerView subviews] makeObjectsPerformSelector:@selector(setHidden:) withObject:YES];
620 [headerView unsetThemeState:CPThemeStateHighlighted | CPThemeStateSelected];
623 _columnDragHeaderView = [_columnDragView viewWithTag:CPTableHeaderViewDragColumnHeaderTag];
625 _columnMouseDownLocation = [
self convertPoint:_mouseDownLocation toView:_columnDragHeaderView];
627 [_tableView _setDraggedColumn:aColumnIndex];
631 [
self setNeedsDisplay:YES];
634 - (void)_dragTableColumn:(CPInteger)aColumnIndex to:(CGPoint)aPoint
636 var delta = aPoint.x - _previousTrackingLocation.x,
637 columnPoint = [_columnDragHeaderView convertPoint:aPoint fromView:self];
640 if ((delta > 0 && columnPoint.x > _columnMouseDownLocation.x) || (delta < 0 && columnPoint.x < _columnMouseDownLocation.x))
642 var dragFrame = [_columnDragView frame],
643 newOrigin = [
self _constrainDragPoint:CGPointMake(CGRectGetMinX(dragFrame) + delta, CGRectGetMinY(dragFrame))];
645 [_columnDragView setFrameOrigin:newOrigin];
648 var hoverPoint = CGPointMakeCopy(aPoint);
651 dragFrame = [
self convertRect:dragFrame fromView:[_columnDragView superview]];
654 hoverPoint.x = CGRectGetMaxX(dragFrame);
656 hoverPoint.x = CGRectGetMinX(dragFrame);
658 var hoveredColumn = [
self columnAtPoint:hoverPoint];
660 if (hoveredColumn !== -1)
662 var columnRect = [
self headerRectOfColumn:hoveredColumn],
663 columnCenterPoint = CGPointMake(CGRectGetMidX(columnRect), CGRectGetMidY(columnRect));
665 if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
666 [
self _moveColumn:_activeColumn toColumn:hoveredColumn];
667 else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
668 [
self _moveColumn:_activeColumn toColumn:hoveredColumn];
672 _previousTrackingLocation = aPoint;
675 - (void)_stopDraggingTableColumn:(CPInteger)aColumnIndex
679 [_columnDragClipView removeFromSuperview];
680 [_tableView _setDraggedColumn:-1];
682 var headerView = [[[_tableView tableColumns] objectAtIndex:aColumnIndex] headerView];
684 [[headerView subviews] makeObjectsPerformSelector:@selector(setHidden:) withObject:NO];
686 if (_tableView._draggedColumnIsSelected)
687 [headerView setThemeState:CPThemeStateSelected];
689 var columnRect = [_tableView rectOfColumn:aColumnIndex];
691 [_tableView _reloadDataViews];
692 [[_tableView headerView] setNeedsLayout];
697 - (BOOL)_shouldResizeTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
702 return [_tableView allowsColumnResizing] && CGRectContainsPoint([
self _cursorRectForColumn:aColumnIndex], aPoint);
705 - (void)_startResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
708 _previousTrackingLocation = aPoint;
709 _activeColumn = aColumnIndex;
711 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
713 _columnOldWidth = [tableColumn width];
715 [tableColumn setDisableResizingPosting:YES];
716 [_tableView setDisableAutomaticResizing:YES];
719 - (void)_continueResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
721 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
722 delta = aPoint.x - _previousTrackingLocation.x,
723 spacing = [_tableView intercellSpacing].
width,
724 newWidth = [tableColumn
width] + spacing + delta,
725 minWidth = [tableColumn minWidth] + spacing,
726 maxWidth = [tableColumn maxWidth] + spacing;
728 if (newWidth <= minWidth)
730 else if (newWidth >= maxWidth)
735 var columnRect = [_tableView rectOfColumn:aColumnIndex],
736 columnWidth = CGRectGetWidth(columnRect);
738 if ((delta > 0 && columnWidth == maxWidth) || (delta < 0 && columnWidth == minWidth))
741 var columnMinX = CGRectGetMinX(columnRect),
742 columnMaxX = CGRectGetMaxX(columnRect);
744 if ((delta > 0 && aPoint.x > columnMaxX) || (delta < 0 && aPoint.x < columnMaxX))
746 [tableColumn setWidth:newWidth - spacing];
748 [
self setNeedsLayout];
749 [
self setNeedsDisplay:YES];
752 _previousTrackingLocation = aPoint;
755 - (void)_stopResizingTableColumn:(CPInteger)aColumnIndex
757 var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
759 if ([tableColumn
width] != _columnOldWidth)
760 [_tableView _didResizeTableColumn:tableColumn oldWidth:_columnOldWidth];
762 [tableColumn setDisableResizingPosting:NO];
763 [_tableView setDisableAutomaticResizing:NO];
768 - (void)_updateResizeCursor:(
CPEvent)theEvent
771 if (![_tableView allowsColumnResizing] || ([theEvent type] ===
CPLeftMouseUp && ![[
self window] acceptsMouseMovedEvents]))
777 var mouseLocation = [
self convertPoint:[theEvent
locationInWindow] fromView:nil],
779 overColumn = [
self columnAtPoint:mouseOverLocation];
781 if (overColumn >= 0 && CGRectContainsPoint([
self _cursorRectForColumn:overColumn], mouseLocation))
783 var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
784 spacing = [_tableView intercellSpacing].width,
785 width = [tableColumn width];
787 if (
width <= [tableColumn minWidth])
789 else if (
width >= [tableColumn maxWidth])
806 if (
self = [super initWithCoder:aCoder])
809 _tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
818 [aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];