1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "ui/base/cocoa/controls/hyperlink_button_cell.h"
7 @interface HyperlinkButtonCell ()
8 - (void)customizeButtonCell;
11 @implementation HyperlinkButtonCell
14 @synthesize underlineOnHover = underlineOnHover_;
15 @synthesize shouldUnderline = shouldUnderline_;
17 + (NSColor*)defaultTextColor {
18 return [NSColor blueColor];
21 + (NSButton*)buttonWithString:(NSString*)string {
22 NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
23 base::scoped_nsobject<HyperlinkButtonCell> cell(
24 [[HyperlinkButtonCell alloc] initTextCell:string]);
25 [cell setAlignment:NSLeftTextAlignment];
26 [button setCell:cell.get()];
27 [button setBezelStyle:NSRegularSquareBezelStyle];
31 // Designated initializer.
33 if ((self = [super init])) {
34 [self customizeButtonCell];
39 // Initializer called when the cell is loaded from the NIB.
40 - (id)initWithCoder:(NSCoder*)aDecoder {
41 if ((self = [super initWithCoder:aDecoder])) {
42 [self customizeButtonCell];
47 // Initializer for code-based creation.
48 - (id)initTextCell:(NSString*)title {
49 if ((self = [super initTextCell:title])) {
50 [self customizeButtonCell];
55 - (id)copyWithZone:(NSZone*)zone {
56 NSColor* color = textColor_.release();
57 HyperlinkButtonCell* cell = [super copyWithZone:zone];
58 cell->textColor_.reset([color copy]);
59 textColor_.reset(color);
63 // Because an NSButtonCell has multiple initializers, this method performs the
64 // common cell customization code.
65 - (void)customizeButtonCell {
66 [self setBordered:NO];
67 [self setTextColor:[HyperlinkButtonCell defaultTextColor]];
68 [self setShouldUnderline:YES];
70 CGFloat fontSize = [NSFont systemFontSizeForControlSize:[self controlSize]];
71 NSFont* font = [NSFont controlContentFontOfSize:fontSize];
74 // Do not change button appearance when we are pushed.
75 [self setHighlightsBy:NSNoCellMask];
77 // We need to set this so that we can override |-mouseEntered:| and
78 // |-mouseExited:| to change the cursor style on hover states.
79 [self setShowsBorderOnlyWhileMouseInside:YES];
82 - (void)setControlSize:(NSControlSize)size {
83 [super setControlSize:size];
84 [self customizeButtonCell]; // recompute |font|.
87 // Creates the NSDictionary of attributes for the attributed string.
88 - (NSDictionary*)linkAttributes {
89 NSUInteger underlineMask = NSNoUnderlineStyle;
90 if (shouldUnderline_ &&
91 (!underlineOnHover_ || (mouseIsInside_ && [self isEnabled])))
92 underlineMask = NSUnderlinePatternSolid | NSUnderlineStyleSingle;
94 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
95 [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
96 [paragraphStyle setAlignment:[self alignment]];
97 [paragraphStyle setLineBreakMode:[self lineBreakMode]];
99 return [NSDictionary dictionaryWithObjectsAndKeys:
100 [self textColor], NSForegroundColorAttributeName,
101 [NSNumber numberWithInt:underlineMask], NSUnderlineStyleAttributeName,
102 [self font], NSFontAttributeName,
103 [NSCursor pointingHandCursor], NSCursorAttributeName,
104 paragraphStyle.get(), NSParagraphStyleAttributeName,
109 // Override the drawing for the cell so that the custom style attributes
110 // can always be applied and so that ellipses will appear when appropriate.
111 - (NSRect)drawTitle:(NSAttributedString*)title
112 withFrame:(NSRect)frame
113 inView:(NSView*)controlView {
114 NSDictionary* linkAttributes = [self linkAttributes];
115 NSString* plainTitle = [title string];
116 [plainTitle drawWithRect:frame
117 options:(NSStringDrawingUsesLineFragmentOrigin |
118 NSStringDrawingTruncatesLastVisibleLine)
119 attributes:linkAttributes];
123 // Override the default behavior to draw the border. Instead, change the cursor.
124 - (void)mouseEntered:(NSEvent*)event {
125 mouseIsInside_ = YES;
126 if ([self isEnabled])
127 [[NSCursor pointingHandCursor] push];
129 [[NSCursor currentCursor] push];
130 if (underlineOnHover_)
131 [[self controlView] setNeedsDisplay:YES];
134 - (void)mouseExited:(NSEvent*)event {
137 if (underlineOnHover_)
138 [[self controlView] setNeedsDisplay:YES];
141 // Setters and getters.
142 - (NSColor*)textColor {
143 if ([self isEnabled])
144 return textColor_.get();
146 return [NSColor disabledControlTextColor];
149 - (void)setTextColor:(NSColor*)color {
150 textColor_.reset([color retain]);
153 // Override so that |-sizeToFit| works better with this type of cell.
155 NSSize size = [super cellSize];