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. 4 5#import "ui/base/cocoa/controls/blue_label_button.h" 6 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" 12 13const CGFloat kCornerRadius = 2; 14 15const CGFloat kTopBottomTextPadding = 7; 16const CGFloat kLeftRightTextPadding = 15; 17const SkColor kTextShadowColor = SkColorSetRGB(0x53, 0x8c, 0xea); 18 19const SkColor kShadowColor = SkColorSetRGB(0xe9, 0xe9, 0xe9); 20const SkColor kDefaultColor = SkColorSetRGB(0x5a, 0x97, 0xff); 21const SkColor kHoverColor = SkColorSetRGB(0x55, 0x8f, 0xf3); 22const SkColor kPressedColor = SkColorSetRGB(0x42, 0x79, 0xd8); 23 24const SkColor kInnerRingColor = SkColorSetRGB(0x64, 0x9e, 0xff); 25const SkColor kFocusInnerRingColor = SkColorSetRGB(0xad, 0xcc, 0xff); 26const SkColor kPressInnerRingColor = SkColorSetRGB(0x3f, 0x73, 0xcd); 27 28const SkColor kOuterRingColor = SkColorSetRGB(0x2b, 0x67, 0xce); 29const SkColor kPressOuterRingColor = SkColorSetRGB(0x23, 0x52, 0xa2); 30 31@interface BlueLabelButtonCell : NSButtonCell 32 33+ (NSAttributedString*)generateAttributedString:(NSString*)buttonText; 34 35@end 36 37@implementation BlueLabelButton 38 39+ (Class)cellClass { 40 return [BlueLabelButtonCell class]; 41} 42 43- (id)initWithFrame:(NSRect)frameRect { 44 if ((self = [super initWithFrame:frameRect])) { 45 [self setBezelStyle:NSSmallSquareBezelStyle]; 46 } 47 return self; 48} 49 50@end 51 52@implementation BlueLabelButtonCell 53 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]; 61 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)]; 66 67 NSDictionary* buttonTextAttributes = @{ 68 NSParagraphStyleAttributeName : buttonTextParagraphStyle, 69 NSFontAttributeName : buttonFont, 70 NSForegroundColorAttributeName : [NSColor whiteColor], 71 NSShadowAttributeName : shadow.get() 72 }; 73 base::scoped_nsobject<NSAttributedString> attributedButtonText( 74 [[NSAttributedString alloc] initWithString:buttonText 75 attributes:buttonTextAttributes]); 76 return attributedButtonText.autorelease(); 77} 78 79- (NSSize)cellSize { 80 NSAttributedString* attributedTitle = 81 [[self class] generateAttributedString:[self title]]; 82 NSSize textSize = [attributedTitle size]; 83 84 // Add 1 to maintain identical height w/ previous drawing code. 85 textSize.height += 2 * kTopBottomTextPadding + 1; 86 textSize.width += 2 * kLeftRightTextPadding; 87 return textSize; 88} 89 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. 94 frame.origin.y -= 1; 95 96 NSAttributedString* attributedTitle = 97 [[self class] generateAttributedString:[self title]]; 98 gfx::ScopedNSGraphicsContextSaveGState context; 99 [attributedTitle drawInRect:frame]; 100 return frame; 101} 102 103- (void)drawBezelWithFrame:(NSRect)frame 104 inView:(NSView*)controlView { 105 NSColor* centerColor; 106 NSColor* innerColor; 107 NSColor* outerColor; 108 HoverState hoverState = 109 [base::mac::ObjCCastStrict<HoverButton>(controlView) hoverState]; 110 // Leave a sliver of height 1 for the button drop shadow. 111 frame.size.height -= 1; 112 113 if (hoverState == kHoverStateMouseDown && [self isHighlighted]) { 114 centerColor = gfx::SkColorToSRGBNSColor(kPressedColor); 115 innerColor = gfx::SkColorToSRGBNSColor(kPressInnerRingColor); 116 outerColor = gfx::SkColorToSRGBNSColor(kPressOuterRingColor); 117 } else { 118 centerColor = hoverState == kHoverStateMouseOver ? 119 gfx::SkColorToSRGBNSColor(kHoverColor) : 120 gfx::SkColorToSRGBNSColor(kDefaultColor); 121 innerColor = [self showsFirstResponder] ? 122 gfx::SkColorToSRGBNSColor(kFocusInnerRingColor) : 123 gfx::SkColorToSRGBNSColor(kInnerRingColor); 124 outerColor = gfx::SkColorToSRGBNSColor(kOuterRingColor); 125 } 126 { 127 gfx::ScopedNSGraphicsContextSaveGState context; 128 base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); 129 [shadow setShadowOffset:NSMakeSize(0, -1)]; 130 [shadow setShadowBlurRadius:1.0]; 131 [shadow setShadowColor:gfx::SkColorToSRGBNSColor(kShadowColor)]; 132 [shadow set]; 133 [outerColor set]; 134 135 [[NSBezierPath bezierPathWithRoundedRect:frame 136 xRadius:kCornerRadius 137 yRadius:kCornerRadius] fill]; 138 } 139 140 [innerColor set]; 141 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 1, 1) 142 xRadius:kCornerRadius 143 yRadius:kCornerRadius] fill]; 144 [centerColor set]; 145 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2, 2) 146 xRadius:kCornerRadius 147 yRadius:kCornerRadius] fill]; 148} 149 150@end 151