blob: 57b70779cf3694d3621ce5801e426fa70b00fac3 [file] [log] [blame]
// Copyright 2013 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 "ui/base/cocoa/controls/hyperlink_button_cell.h"
@interface HyperlinkButtonCell ()
- (void)customizeButtonCell;
@end
@implementation HyperlinkButtonCell
@dynamic textColor;
@synthesize underlineOnHover = underlineOnHover_;
@synthesize shouldUnderline = shouldUnderline_;
+ (NSColor*)defaultTextColor {
return [NSColor blueColor];
}
+ (NSButton*)buttonWithString:(NSString*)string {
NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
base::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;
}
- (id)copyWithZone:(NSZone*)zone {
NSColor* color = textColor_.release();
HyperlinkButtonCell* cell = [super copyWithZone:zone];
cell->textColor_.reset([color copy]);
textColor_.reset(color);
return cell;
}
// Because an NSButtonCell has multiple initializers, this method performs the
// common cell customization code.
- (void)customizeButtonCell {
[self setBordered:NO];
[self setTextColor:[HyperlinkButtonCell defaultTextColor]];
[self setShouldUnderline:YES];
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 (shouldUnderline_ &&
(!underlineOnHover_ || (mouseIsInside_ && [self isEnabled])))
underlineMask = NSUnderlinePatternSolid | NSUnderlineStyleSingle;
base::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