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/blue_label_button.h"
7 #include "base/mac/foundation_util.h"
8 #include "skia/ext/skia_utils_mac.h"
9 #include "third_party/skia/include/core/SkColor.h"
10 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
13 const CGFloat kCornerRadius = 2;
15 const CGFloat kTopBottomTextPadding = 7;
16 const CGFloat kLeftRightTextPadding = 15;
17 const SkColor kTextShadowColor = SkColorSetRGB(0x53, 0x8c, 0xea);
19 const SkColor kShadowColor = SkColorSetRGB(0xe9, 0xe9, 0xe9);
20 const SkColor kDefaultColor = SkColorSetRGB(0x5a, 0x97, 0xff);
21 const SkColor kHoverColor = SkColorSetRGB(0x55, 0x8f, 0xf3);
22 const SkColor kPressedColor = SkColorSetRGB(0x42, 0x79, 0xd8);
24 const SkColor kInnerRingColor = SkColorSetRGB(0x64, 0x9e, 0xff);
25 const SkColor kFocusInnerRingColor = SkColorSetRGB(0xad, 0xcc, 0xff);
26 const SkColor kPressInnerRingColor = SkColorSetRGB(0x3f, 0x73, 0xcd);
28 const SkColor kOuterRingColor = SkColorSetRGB(0x2b, 0x67, 0xce);
29 const SkColor kPressOuterRingColor = SkColorSetRGB(0x23, 0x52, 0xa2);
31 @interface BlueLabelButtonCell : NSButtonCell
33 + (NSAttributedString*)generateAttributedString:(NSString*)buttonText;
37 @implementation BlueLabelButton
40 return [BlueLabelButtonCell class];
43 - (id)initWithFrame:(NSRect)frameRect {
44 if ((self = [super initWithFrame:frameRect])) {
45 [self setBezelStyle:NSSmallSquareBezelStyle];
52 @implementation BlueLabelButtonCell
54 + (NSAttributedString*)generateAttributedString:(NSString*)buttonText {
55 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
56 NSFont* buttonFont = rb.GetFontList(ui::ResourceBundle::SmallFont).
57 GetPrimaryFont().GetNativeFont();
58 base::scoped_nsobject<NSMutableParagraphStyle> buttonTextParagraphStyle(
59 [[NSMutableParagraphStyle alloc] init]);
60 [buttonTextParagraphStyle setAlignment:NSCenterTextAlignment];
62 base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
63 [shadow setShadowOffset:NSMakeSize(0, -1)];
64 [shadow setShadowBlurRadius:0];
65 [shadow setShadowColor:gfx::SkColorToSRGBNSColor(kTextShadowColor)];
67 NSDictionary* buttonTextAttributes = @{
68 NSParagraphStyleAttributeName : buttonTextParagraphStyle,
69 NSFontAttributeName : buttonFont,
70 NSForegroundColorAttributeName : [NSColor whiteColor],
71 NSShadowAttributeName : shadow.get()
73 base::scoped_nsobject<NSAttributedString> attributedButtonText(
74 [[NSAttributedString alloc] initWithString:buttonText
75 attributes:buttonTextAttributes]);
76 return attributedButtonText.autorelease();
80 NSAttributedString* attributedTitle =
81 [[self class] generateAttributedString:[self title]];
82 NSSize textSize = [attributedTitle size];
84 // Add 1 to maintain identical height w/ previous drawing code.
85 textSize.height += 2 * kTopBottomTextPadding + 1;
86 textSize.width += 2 * kLeftRightTextPadding;
90 - (NSRect)drawTitle:(NSAttributedString*)title
91 withFrame:(NSRect)frame
92 inView:(NSView*)controlView {
93 // Fuzz factor to adjust for the drop shadow. Based on visual inspection.
96 // Ensure LCD font smoothing is enabled when layer backed.
97 // This is safe to do because we know we are drawing on an opaque background.
98 gfx::ScopedNSGraphicsContextSaveGState scopedGState;
99 NSGraphicsContext* context = [NSGraphicsContext currentContext];
100 CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
101 CGContextSetShouldSmoothFonts(cgContext, true);
103 NSAttributedString* attributedTitle =
104 [[self class] generateAttributedString:[self title]];
105 [attributedTitle drawInRect:frame];
109 - (void)drawBezelWithFrame:(NSRect)frame
110 inView:(NSView*)controlView {
111 NSColor* centerColor;
114 HoverState hoverState =
115 [base::mac::ObjCCastStrict<HoverButton>(controlView) hoverState];
116 // Leave a sliver of height 1 for the button drop shadow.
117 frame.size.height -= 1;
119 if (hoverState == kHoverStateMouseDown && [self isHighlighted]) {
120 centerColor = gfx::SkColorToSRGBNSColor(kPressedColor);
121 innerColor = gfx::SkColorToSRGBNSColor(kPressInnerRingColor);
122 outerColor = gfx::SkColorToSRGBNSColor(kPressOuterRingColor);
124 centerColor = hoverState == kHoverStateMouseOver ?
125 gfx::SkColorToSRGBNSColor(kHoverColor) :
126 gfx::SkColorToSRGBNSColor(kDefaultColor);
127 innerColor = [self showsFirstResponder] ?
128 gfx::SkColorToSRGBNSColor(kFocusInnerRingColor) :
129 gfx::SkColorToSRGBNSColor(kInnerRingColor);
130 outerColor = gfx::SkColorToSRGBNSColor(kOuterRingColor);
133 gfx::ScopedNSGraphicsContextSaveGState context;
134 base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
135 [shadow setShadowOffset:NSMakeSize(0, -1)];
136 [shadow setShadowBlurRadius:1.0];
137 [shadow setShadowColor:gfx::SkColorToSRGBNSColor(kShadowColor)];
141 [[NSBezierPath bezierPathWithRoundedRect:frame
142 xRadius:kCornerRadius
143 yRadius:kCornerRadius] fill];
147 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 1, 1)
148 xRadius:kCornerRadius
149 yRadius:kCornerRadius] fill];
151 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2, 2)
152 xRadius:kCornerRadius
153 yRadius:kCornerRadius] fill];