-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSSYPopUpTableHeaderCell.m
110 lines (89 loc) · 3.83 KB
/
SSYPopUpTableHeaderCell.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#import "SSYPopUpTableHeaderCell.h"
@interface SSYPopUpTableHeaderCell ()
@property CGFloat lostWidth ;
@end
@implementation SSYPopUpTableHeaderCell
@synthesize lostWidth ;
- (id)copyWithZone:(NSZone *)zone {
SSYPopUpTableHeaderCell* copy = [[SSYPopUpTableHeaderCell allocWithZone: zone] init] ;
[copy setLostWidth:[self lostWidth]] ;
return copy ;
}
- (id)init {
if (self = [super init]) {
// Set up the popup cell attributes
[self setControlSize:NSMiniControlSize] ;
[self setBordered:NO] ;
[self setBezeled:NO] ;
[self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]] ;
}
return self ;
}
- (void)drawWithFrame:(NSRect)cellFrame
inView:(NSView*)controlView {
// Apple's documentation for this -[NSCell drawWithFrame:inView: states
// "This method draws the cell in the currently focused view,
// which can be different from the controlView passed in. Taking advantage
// of this behavior is not recommended, however.
// So, in order to not "take advantage" of this, I lockFocus on the
// controlView which was passed in.
[controlView lockFocus] ;
// Let's make sure it worked
if ([NSView focusView] != controlView) {
NSLog(@"Internal Error 040-9481 in %s", __PRETTY_FUNCTION__) ;
// Just continue since I'm not sure what the bad effect would be!
}
// First we draw the bezel and whatever background gradient there might be.
// We omit drawing the title by simply setting it to an empty string.
NSTableHeaderCell* templateHeaderCell = [[NSTableHeaderCell alloc] init] ;
[templateHeaderCell setTitle:@""] ;
[templateHeaderCell drawWithFrame:cellFrame
inView:controlView] ;
[templateHeaderCell release] ;
// Second, draw the pair of popup arrows near the right edge
// and also remove width from the right of cellFrame.size.width
// so that only the part available for text remains in cellFrame.size.width
if (cellFrame.size.width > 0) {
// Arrow design is based on a cell frame height of 17.0 pixels,
// which I believe is the standard and only height for an NSTableHeaderView
// But design is scaled in case anyone ever comes up with a new height.
CGFloat scaleFactor = cellFrame.size.height / 17.0 ;
CGFloat whitespaceOnRight = 5.0 * scaleFactor ;
CGFloat whitespaceOnTopOrBottom = 3.0 * scaleFactor ;
CGFloat arrowSeparationY = 3.0 * scaleFactor ;
CGFloat arrowHeight = (cellFrame.size.height - arrowSeparationY)/2 - whitespaceOnTopOrBottom ;
CGFloat arrowWidth = arrowHeight ;
CGFloat arrowHalfWidth = arrowWidth/2.0 ;
CGFloat middleY = cellFrame.size.height / 2 ;
CGFloat lostWidth_ = whitespaceOnRight + arrowWidth ;
[self setLostWidth:lostWidth_] ;
CGFloat arrowMinX = NSMaxX(cellFrame) - lostWidth_ ;
CGFloat arrowOffsetY = arrowSeparationY / 2 ;
CGFloat topArrowBottom = middleY + arrowOffsetY ;
CGFloat bottomArrowTop = middleY - arrowOffsetY ;
NSBezierPath* path ;
[[NSColor blackColor] set] ;
// Draw the top arrow (that points up)
path = [NSBezierPath bezierPath] ;
[path moveToPoint:NSMakePoint(arrowMinX, topArrowBottom)] ;
[path relativeLineToPoint:NSMakePoint(arrowWidth, 0)] ;
[path relativeLineToPoint:NSMakePoint(-arrowHalfWidth, arrowHeight)] ;
[path closePath] ;
[path fill] ;
// Draw the lower triangle that points down
path = [NSBezierPath bezierPath] ;
[path moveToPoint:NSMakePoint(arrowMinX, bottomArrowTop)] ;
[path relativeLineToPoint:NSMakePoint(arrowWidth, 0)] ;
[path relativeLineToPoint:NSMakePoint(-arrowHalfWidth, -arrowHeight)] ;
[path closePath] ;
[path fill] ;
cellFrame.size.width -= lostWidth_ ;
}
// Third, draw only the interior portion of the popup menu, "which includes
// the image or text portion but does not include the border"
// This will draw the title of the currently-selected item.
[self drawInteriorWithFrame:cellFrame
inView:controlView] ;
[controlView unlockFocus] ;
}
@end