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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
@interface HyperlinkButtonCell ()
- (void)customizeButtonCell;
@end
@implementation HyperlinkButtonCell
@dynamic textColor;
@synthesize underlineOnHover = underlineOnHover_;
+ (NSColor*)defaultTextColor {
return [NSColor blueColor];
}
+ (NSButton*)buttonWithString:(NSString*)string {
NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
scoped_nsobject<HyperlinkButtonCell> cell(
[[HyperlinkButtonCell alloc] initTextCell:string]);
[cell setAlignment:NSLeftTextAlignment];
[button setCell:cell.get()];
[button setBezelStyle:NSRegularSquareBezelStyle];
return button;
}
// Designated initializer.
- (id)init {
if ((self = [super init])) {
[self customizeButtonCell];
}
return self;
}
// Initializer called when the cell is loaded from the NIB.
- (id)initWithCoder:(NSCoder*)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self customizeButtonCell];
}
return self;
}
// Initializer for code-based creation.
- (id)initTextCell:(NSString*)title {
if ((self = [super initTextCell:title])) {
[self customizeButtonCell];
}
return self;
}
// Because an NSButtonCell has multiple initializers, this method performs the
// common cell customization code.
- (void)customizeButtonCell {
[self setBordered:NO];
[self setTextColor:[HyperlinkButtonCell defaultTextColor]];
CGFloat fontSize = [NSFont systemFontSizeForControlSize:[self controlSize]];
NSFont* font = [NSFont controlContentFontOfSize:fontSize];
[self setFont:font];
// Do not change button appearance when we are pushed.
[self setHighlightsBy:NSNoCellMask];
// We need to set this so that we can override |-mouseEntered:| and
// |-mouseExited:| to change the cursor style on hover states.
[self setShowsBorderOnlyWhileMouseInside:YES];
}
- (void)setControlSize:(NSControlSize)size {
[super setControlSize:size];
[self customizeButtonCell]; // recompute |font|.
}
// Creates the NSDictionary of attributes for the attributed string.
- (NSDictionary*)linkAttributes {
NSUInteger underlineMask = NSNoUnderlineStyle;
if (!underlineOnHover_ || (mouseIsInside_ && [self isEnabled]))
underlineMask = NSUnderlinePatternSolid | NSUnderlineStyleSingle;
scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
[[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
[paragraphStyle setAlignment:[self alignment]];
[paragraphStyle setLineBreakMode:[self lineBreakMode]];
return [NSDictionary dictionaryWithObjectsAndKeys:
[self textColor], NSForegroundColorAttributeName,
[NSNumber numberWithInt:underlineMask], NSUnderlineStyleAttributeName,
[self font], NSFontAttributeName,
[NSCursor pointingHandCursor], NSCursorAttributeName,
paragraphStyle.get(), NSParagraphStyleAttributeName,
nil
];
}
// Override the drawing for the cell so that the custom style attributes
// can always be applied and so that ellipses will appear when appropriate.
- (NSRect)drawTitle:(NSAttributedString*)title
withFrame:(NSRect)frame
inView:(NSView*)controlView {
NSDictionary* linkAttributes = [self linkAttributes];
NSString* plainTitle = [title string];
[plainTitle drawWithRect:frame
options:(NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingTruncatesLastVisibleLine)
attributes:linkAttributes];
return frame;
}
// Override the default behavior to draw the border. Instead, change the cursor.
- (void)mouseEntered:(NSEvent*)event {
mouseIsInside_ = YES;
if ([self isEnabled])
[[NSCursor pointingHandCursor] push];
else
[[NSCursor currentCursor] push];
if (underlineOnHover_)
[[self controlView] setNeedsDisplay:YES];
}
- (void)mouseExited:(NSEvent*)event {
mouseIsInside_ = NO;
[NSCursor pop];
if (underlineOnHover_)
[[self controlView] setNeedsDisplay:YES];
}
// Setters and getters.
- (NSColor*)textColor {
if ([self isEnabled])
return textColor_.get();
else
return [NSColor disabledControlTextColor];
}
- (void)setTextColor:(NSColor*)color {
textColor_.reset([color retain]);
}
// Override so that |-sizeToFit| works better with this type of cell.
- (NSSize)cellSize {
NSSize size = [super cellSize];
size.width += 2;
return size;
}
@end
|