Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm

Issue 1680773006: Implement Material Design for Mac toolbar. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@md_master
Patch Set: Change button hover and pressed styles. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.h" 5 #import "chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.h"
6 6
7 #include "base/mac/foundation_util.h"
8 #include "base/mac/sdk_forward_declarations.h"
9 #import "chrome/browser/ui/cocoa/image_button_cell.h"
10 #import "chrome/browser/ui/cocoa/themed_window.h"
11 #import "chrome/browser/ui/cocoa/view_id_util.h"
12 #include "skia/ext/skia_utils_mac.h"
13 #import "ui/base/cocoa/nsview_additions.h"
14 #include "ui/base/material_design/material_design_controller.h"
15 #include "ui/base/theme_provider.h"
16 #include "ui/gfx/image/image_skia_util_mac.h"
17 #include "ui/gfx/paint_vector_icon.h"
18
19 namespace {
20
21 // The bounds of toolbar buttons in Material Design.
22 const NSRect kMDButtonBounds = NSMakeRect(0, 0, 28, 28);
23
24 // The size of a toolbar button icon in Material Design. A toolbar button image
25 // consists of a border and background, with a centered icon.
26 const NSSize kMDButtonIconSize = NSMakeSize(16, 16);
27
28 } // namespace
29
30 // An NSCustomImageRep subclass that creates the "three dots" image of the
31 // Material Design browser tools icon.
32 @interface BrowserToolsImageRep : NSCustomImageRep
33 @property (retain, nonatomic) NSColor* fillColor;
34 // NSCustomImageRep delegate method that performs the drawing.
35 + (void)drawBrowserToolsIcon:(BrowserToolsImageRep*)imageRep;
36 @end
37
38 @implementation BrowserToolsImageRep
39
40 @synthesize fillColor = fillColor_;
41
42 - (void)dealloc {
43 [fillColor_ release];
44 [super dealloc];
45 }
46
47 + (void)drawBrowserToolsIcon:(BrowserToolsImageRep*)imageRep {
48 [imageRep.fillColor set];
49 NSBezierPath* dotPath =
50 [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(6.5, 1.5, 3, 3)];
51 CGContextRef context = static_cast<CGContextRef>(
52 [[NSGraphicsContext currentContext] graphicsPort]);
53 // Draw the three dots by drawing |dotPath| in three different locations.
54 for (NSUInteger i = 0; i < 3; i++) {
55 [dotPath fill];
56 CGContextTranslateCTM(context, 0, 5);
57 }
58 }
59
60 @end
61
62 // An NSCustomImageRep subclass that draws a Material Design background behind
63 // and border around a centered icon image.
64 @interface ToolbarButtonImageRep : NSCustomImageRep
65 @property (retain, nonatomic) NSImage* icon;
66 @property (assign, nonatomic) ToolbarButtonImageBackgroundStyle style;
67 // NSCustomImageRep delegate method that performs the drawing.
68 + (void)drawImage:(ToolbarButtonImageRep*)imageRep;
69 @end
70
71 @implementation ToolbarButtonImageRep
72
73 @synthesize icon = icon_;
74 @synthesize style = style_;
75
76 - (void)dealloc {
77 [icon_ release];
78 [super dealloc];
79 }
80
81 + (void)drawImage:(ToolbarButtonImageRep*)imageRep {
82 // Create the path used for the background fill.
83 NSRect destRect = NSInsetRect(kMDButtonBounds, 2, 2);
84 NSBezierPath* roundedRectPath =
85 [NSBezierPath bezierPathWithRoundedRect:destRect xRadius:2 yRadius:2];
86
87 // Determine the fill color.
88 NSColor* fillColor = nil;
89 switch (imageRep.style) {
90 case ToolbarButtonImageBackgroundStyle::HOVER:
91 fillColor = [NSColor colorWithCalibratedWhite:0 alpha:0.08];
92 break;
93 case ToolbarButtonImageBackgroundStyle::HOVER_THEMED:
94 fillColor = [NSColor colorWithCalibratedWhite:1 alpha:0.08];
95 break;
96 case ToolbarButtonImageBackgroundStyle::PRESSED:
97 fillColor = [NSColor colorWithCalibratedWhite:0 alpha:0.12];
98 break;
99 case ToolbarButtonImageBackgroundStyle::PRESSED_THEMED:
100 fillColor = [NSColor colorWithCalibratedWhite:1 alpha:0.12];
101 break;
102 }
103
104 // Fill the path.
105 [fillColor set];
106 [roundedRectPath fill];
107
108 // Compute the icon's location and draw it there.
109 CGFloat iconInset =
110 (kMDButtonBounds.size.width - kMDButtonIconSize.width) / 2;
111 NSRect iconDestRect = NSInsetRect(kMDButtonBounds, iconInset, iconInset);
112 [imageRep.icon drawInRect:iconDestRect
113 fromRect:NSZeroRect
114 operation:NSCompositeSourceOver
115 fraction:1];
116 }
117
118 @end
119
120 @interface ToolbarButton ()
121 // Returns an image that draws the browser tools button icon using vector
122 // commands.
123 - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor;
124 // Returns an button image by combining |iconImage| with the specified button
125 // background.
126 - (NSImage*)imageForIcon:(NSImage*)iconImage
127 withBackgroundStyle:(ToolbarButtonImageBackgroundStyle)style;
128 // Creates and assigns images for the button's various states (pressed, hover,
129 // etc.).
130 - (void)setImagesFromIconId:(gfx::VectorIconId)iconId;
131 // Implemented to set the button's icon when added to the browser window. We
132 // can't set the image before this because its appearance depends upon the
133 // browser window's theme.
134 - (void)viewDidMoveToWindow;
135
136 @end
137
138
7 @implementation ToolbarButton 139 @implementation ToolbarButton
8 140
9 @synthesize handleMiddleClick = handleMiddleClick_; 141 @synthesize handleMiddleClick = handleMiddleClick_;
10 142
11 - (void)otherMouseDown:(NSEvent*)theEvent { 143 - (void)otherMouseDown:(NSEvent*)theEvent {
12 if (![self shouldHandleEvent:theEvent]) { 144 if (![self shouldHandleEvent:theEvent]) {
13 [super otherMouseDown:theEvent]; 145 [super otherMouseDown:theEvent];
14 return; 146 return;
15 } 147 }
16 148
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 return handleMiddleClick_ && [theEvent buttonNumber] == 2; 180 return handleMiddleClick_ && [theEvent buttonNumber] == 2;
49 } 181 }
50 182
51 - (void)drawFocusRingMask { 183 - (void)drawFocusRingMask {
52 // Match the hover image's bezel. 184 // Match the hover image's bezel.
53 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], 2, 2) 185 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], 2, 2)
54 xRadius:2 186 xRadius:2
55 yRadius:2] fill]; 187 yRadius:2] fill];
56 } 188 }
57 189
190 - (SkColor)iconColor:(BOOL)themeIsDark {
191 return themeIsDark ? SK_ColorWHITE : SkColorSetRGB(0x5A, 0x5A, 0x5A);
192 }
193
194 - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor {
195 // Create a |BrowserToolsImageRep| to draw the browser tools icon using
196 // the provided fill color.
197 base::scoped_nsobject<BrowserToolsImageRep> imageRep =
198 [[BrowserToolsImageRep alloc]
199 initWithDrawSelector:@selector(drawBrowserToolsIcon:)
200 delegate:[BrowserToolsImageRep class]];
201 [imageRep setFillColor:skia::SkColorToCalibratedNSColor(fillColor)];
202
203 // Create the image from the image rep.
204 NSImage* browserToolsIcon =
205 [[[NSImage alloc] initWithSize:kMDButtonIconSize] autorelease];
206 [browserToolsIcon setCacheMode:NSImageCacheAlways];
207 [browserToolsIcon addRepresentation:imageRep];
208
209 return browserToolsIcon;
210 }
211
212 - (NSImage*)imageForIcon:(NSImage*)iconImage
213 withBackgroundStyle:(ToolbarButtonImageBackgroundStyle)style {
214 // Create a |ToolbarButtonImageRep| to draw the button image using
215 // the provided icon and background style.
216 base::scoped_nsobject<ToolbarButtonImageRep> imageRep =
217 [[ToolbarButtonImageRep alloc]
218 initWithDrawSelector:@selector(drawImage:)
219 delegate:[ToolbarButtonImageRep class]];
220 [imageRep setIcon:iconImage];
221 [imageRep setStyle:style];
222
223 // Create the image from the image rep.
224 NSImage* image =
225 [[[NSImage alloc] initWithSize:kMDButtonBounds.size] autorelease];
226 [image setCacheMode:NSImageCacheAlways];
227 [image addRepresentation:imageRep];
228
229 return image;
230 }
231
232 - (void)setImagesFromIconId:(gfx::VectorIconId)iconId {
233 // Compute the normal and disabled icon colors.
234 BOOL isDarkTheme = [[self window] hasDarkTheme];
235 const SkColor iconColor = [self iconColor:isDarkTheme];
236 CGFloat normalAlpha = isDarkTheme ? 0xCC : 0xFF;
237 const SkColor normalColor = SkColorSetA(iconColor, normalAlpha);
238 const SkColor disabledColor = SkColorSetA(iconColor, 0x33);
239
240 // Create the normal and disabled state icons. These icons are
241 // always the same shape, but use a different color.
242 NSImage* normalIcon = nil;
243 NSImage* disabledIcon = nil;
244 if (iconId == gfx::VectorIconId::BROWSER_TOOLS) {
245 normalIcon = [self browserToolsIconForFillColor:normalColor];
246 disabledIcon = [self browserToolsIconForFillColor:disabledColor];
247 } else {
248 normalIcon = NSImageFromImageSkia(
249 gfx::CreateVectorIcon(iconId, kMDButtonIconSize.width, normalColor));
250 disabledIcon = NSImageFromImageSkia(
251 gfx::CreateVectorIcon(iconId, kMDButtonIconSize.width, disabledColor));
252 }
253
254 ImageButtonCell* theCell = base::mac::ObjCCast<ImageButtonCell>([self cell]);
255 // Set the image for the default state, which is just the icon.
256 [theCell setImage:normalIcon forButtonState:image_button_cell::kDefaultState];
257
258 // Determine the appropriate image background style for the hover and pressed
259 // states.
260 ToolbarButtonImageBackgroundStyle hoverStyle;
261 ToolbarButtonImageBackgroundStyle pressedStyle;
262 const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
263 bool isNonIncognitoSystemTheme = themeProvider &&
264 !themeProvider->InIncognitoMode() && themeProvider->UsingSystemTheme();
265 // Use the regular style only when using the system (i.e. non-custom) theme
266 // and not in Incognito mode.
267 if (isNonIncognitoSystemTheme) {
268 hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER;
269 pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED;
270 } else {
271 hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER_THEMED;
272 pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED_THEMED;
273 }
274
275 // Create and set the image for the hover state.
276 NSImage* hoverImage =
277 [self imageForIcon:normalIcon withBackgroundStyle:hoverStyle];
278 [theCell setImage:hoverImage
279 forButtonState:image_button_cell::kHoverState];
280
281 // Create and set the image for the pressed state.
282 NSImage* pressedImage =
283 [self imageForIcon:normalIcon withBackgroundStyle:pressedStyle];
284 [theCell setImage:pressedImage
285 forButtonState:image_button_cell::kPressedState];
286
287 // Set the image for the disabled state, which is just the disabled icon,
288 // except if this is the home button.
289 if (iconId == gfx::VectorIconId::NAVIGATE_RELOAD) {
290 [theCell setImage:nil forButtonState:image_button_cell::kDisabledState];
291 } else {
292 [theCell setImage:disabledIcon
293 forButtonState:image_button_cell::kDisabledState];
294 }
295 [self setNeedsDisplay:YES];
296 }
297
298 - (void)resetIcons {
299 // Compute the button's icon.
300 gfx::VectorIconId icon_id = gfx::VectorIconId::VECTOR_ICON_NONE;
301 switch ([self viewID]) {
302 case VIEW_ID_BACK_BUTTON:
303 icon_id = gfx::VectorIconId::NAVIGATE_BACK;
304 break;
305 case VIEW_ID_FORWARD_BUTTON:
306 icon_id = gfx::VectorIconId::NAVIGATE_FORWARD;
307 break;
308 case VIEW_ID_HOME_BUTTON:
309 icon_id = gfx::VectorIconId::NAVIGATE_HOME;
310 break;
311 case VIEW_ID_APP_MENU:
312 icon_id = gfx::VectorIconId::BROWSER_TOOLS;
313 break;
314 default:
315 break;
316 }
317
318 // Set it.
319 if (icon_id != gfx::VectorIconId::VECTOR_ICON_NONE) {
320 [self setImagesFromIconId:icon_id];
321 }
322 }
323
324 - (void)viewDidMoveToWindow {
325 // In Material Design we want to catch when the button is attached to its
326 // window so that we can configure its appearance based on the window's
327 // theme.
328 if ([self window] && ui::MaterialDesignController::IsModeMaterial()) {
329 [self resetIcons];
330 }
331 }
332
333 // ThemedWindowDrawing implementation.
334
335 - (void)windowDidChangeTheme {
336 [self resetIcons];
337 }
338
339 - (void)windowDidChangeActive {
340 }
341
58 @end 342 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.h ('k') | chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698