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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
index d8c3acc5b34c3984d33bcc6cc0fad7ff4524aac1..72315e8dc924ab3fff8e29d13f1913f587522420 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
@@ -4,6 +4,138 @@
#import "chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/sdk_forward_declarations.h"
+#import "chrome/browser/ui/cocoa/image_button_cell.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+#include "skia/ext/skia_utils_mac.h"
+#import "ui/base/cocoa/nsview_additions.h"
+#include "ui/base/material_design/material_design_controller.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/image/image_skia_util_mac.h"
+#include "ui/gfx/paint_vector_icon.h"
+
+namespace {
+
+// The bounds of toolbar buttons in Material Design.
+const NSRect kMDButtonBounds = NSMakeRect(0, 0, 28, 28);
+
+// The size of a toolbar button icon in Material Design. A toolbar button image
+// consists of a border and background, with a centered icon.
+const NSSize kMDButtonIconSize = NSMakeSize(16, 16);
+
+} // namespace
+
+// An NSCustomImageRep subclass that creates the "three dots" image of the
+// Material Design browser tools icon.
+@interface BrowserToolsImageRep : NSCustomImageRep
+@property (retain, nonatomic) NSColor* fillColor;
+// NSCustomImageRep delegate method that performs the drawing.
++ (void)drawBrowserToolsIcon:(BrowserToolsImageRep*)imageRep;
+@end
+
+@implementation BrowserToolsImageRep
+
+@synthesize fillColor = fillColor_;
+
+- (void)dealloc {
+ [fillColor_ release];
+ [super dealloc];
+}
+
++ (void)drawBrowserToolsIcon:(BrowserToolsImageRep*)imageRep {
+ [imageRep.fillColor set];
+ NSBezierPath* dotPath =
+ [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(6.5, 1.5, 3, 3)];
+ CGContextRef context = static_cast<CGContextRef>(
+ [[NSGraphicsContext currentContext] graphicsPort]);
+ // Draw the three dots by drawing |dotPath| in three different locations.
+ for (NSUInteger i = 0; i < 3; i++) {
+ [dotPath fill];
+ CGContextTranslateCTM(context, 0, 5);
+ }
+}
+
+@end
+
+// An NSCustomImageRep subclass that draws a Material Design background behind
+// and border around a centered icon image.
+@interface ToolbarButtonImageRep : NSCustomImageRep
+@property (retain, nonatomic) NSImage* icon;
+@property (assign, nonatomic) ToolbarButtonImageBackgroundStyle style;
+// NSCustomImageRep delegate method that performs the drawing.
++ (void)drawImage:(ToolbarButtonImageRep*)imageRep;
+@end
+
+@implementation ToolbarButtonImageRep
+
+@synthesize icon = icon_;
+@synthesize style = style_;
+
+- (void)dealloc {
+ [icon_ release];
+ [super dealloc];
+}
+
++ (void)drawImage:(ToolbarButtonImageRep*)imageRep {
+ // Create the path used for the background fill.
+ NSRect destRect = NSInsetRect(kMDButtonBounds, 2, 2);
+ NSBezierPath* roundedRectPath =
+ [NSBezierPath bezierPathWithRoundedRect:destRect xRadius:2 yRadius:2];
+
+ // Determine the fill color.
+ NSColor* fillColor = nil;
+ switch (imageRep.style) {
+ case ToolbarButtonImageBackgroundStyle::HOVER:
+ fillColor = [NSColor colorWithCalibratedWhite:0 alpha:0.08];
+ break;
+ case ToolbarButtonImageBackgroundStyle::HOVER_THEMED:
+ fillColor = [NSColor colorWithCalibratedWhite:1 alpha:0.08];
+ break;
+ case ToolbarButtonImageBackgroundStyle::PRESSED:
+ fillColor = [NSColor colorWithCalibratedWhite:0 alpha:0.12];
+ break;
+ case ToolbarButtonImageBackgroundStyle::PRESSED_THEMED:
+ fillColor = [NSColor colorWithCalibratedWhite:1 alpha:0.12];
+ break;
+ }
+
+ // Fill the path.
+ [fillColor set];
+ [roundedRectPath fill];
+
+ // Compute the icon's location and draw it there.
+ CGFloat iconInset =
+ (kMDButtonBounds.size.width - kMDButtonIconSize.width) / 2;
+ NSRect iconDestRect = NSInsetRect(kMDButtonBounds, iconInset, iconInset);
+ [imageRep.icon drawInRect:iconDestRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1];
+}
+
+@end
+
+@interface ToolbarButton ()
+// Returns an image that draws the browser tools button icon using vector
+// commands.
+- (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor;
+// Returns an button image by combining |iconImage| with the specified button
+// background.
+- (NSImage*)imageForIcon:(NSImage*)iconImage
+ withBackgroundStyle:(ToolbarButtonImageBackgroundStyle)style;
+// Creates and assigns images for the button's various states (pressed, hover,
+// etc.).
+- (void)setImagesFromIconId:(gfx::VectorIconId)iconId;
+// Implemented to set the button's icon when added to the browser window. We
+// can't set the image before this because its appearance depends upon the
+// browser window's theme.
+- (void)viewDidMoveToWindow;
+
+@end
+
+
@implementation ToolbarButton
@synthesize handleMiddleClick = handleMiddleClick_;
@@ -55,4 +187,156 @@
yRadius:2] fill];
}
+- (SkColor)iconColor:(BOOL)themeIsDark {
+ return themeIsDark ? SK_ColorWHITE : SkColorSetRGB(0x5A, 0x5A, 0x5A);
+}
+
+- (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor {
+ // Create a |BrowserToolsImageRep| to draw the browser tools icon using
+ // the provided fill color.
+ base::scoped_nsobject<BrowserToolsImageRep> imageRep =
+ [[BrowserToolsImageRep alloc]
+ initWithDrawSelector:@selector(drawBrowserToolsIcon:)
+ delegate:[BrowserToolsImageRep class]];
+ [imageRep setFillColor:skia::SkColorToCalibratedNSColor(fillColor)];
+
+ // Create the image from the image rep.
+ NSImage* browserToolsIcon =
+ [[[NSImage alloc] initWithSize:kMDButtonIconSize] autorelease];
+ [browserToolsIcon setCacheMode:NSImageCacheAlways];
+ [browserToolsIcon addRepresentation:imageRep];
+
+ return browserToolsIcon;
+}
+
+- (NSImage*)imageForIcon:(NSImage*)iconImage
+ withBackgroundStyle:(ToolbarButtonImageBackgroundStyle)style {
+ // Create a |ToolbarButtonImageRep| to draw the button image using
+ // the provided icon and background style.
+ base::scoped_nsobject<ToolbarButtonImageRep> imageRep =
+ [[ToolbarButtonImageRep alloc]
+ initWithDrawSelector:@selector(drawImage:)
+ delegate:[ToolbarButtonImageRep class]];
+ [imageRep setIcon:iconImage];
+ [imageRep setStyle:style];
+
+ // Create the image from the image rep.
+ NSImage* image =
+ [[[NSImage alloc] initWithSize:kMDButtonBounds.size] autorelease];
+ [image setCacheMode:NSImageCacheAlways];
+ [image addRepresentation:imageRep];
+
+ return image;
+}
+
+- (void)setImagesFromIconId:(gfx::VectorIconId)iconId {
+ // Compute the normal and disabled icon colors.
+ BOOL isDarkTheme = [[self window] hasDarkTheme];
+ const SkColor iconColor = [self iconColor:isDarkTheme];
+ CGFloat normalAlpha = isDarkTheme ? 0xCC : 0xFF;
+ const SkColor normalColor = SkColorSetA(iconColor, normalAlpha);
+ const SkColor disabledColor = SkColorSetA(iconColor, 0x33);
+
+ // Create the normal and disabled state icons. These icons are
+ // always the same shape, but use a different color.
+ NSImage* normalIcon = nil;
+ NSImage* disabledIcon = nil;
+ if (iconId == gfx::VectorIconId::BROWSER_TOOLS) {
+ normalIcon = [self browserToolsIconForFillColor:normalColor];
+ disabledIcon = [self browserToolsIconForFillColor:disabledColor];
+ } else {
+ normalIcon = NSImageFromImageSkia(
+ gfx::CreateVectorIcon(iconId, kMDButtonIconSize.width, normalColor));
+ disabledIcon = NSImageFromImageSkia(
+ gfx::CreateVectorIcon(iconId, kMDButtonIconSize.width, disabledColor));
+ }
+
+ ImageButtonCell* theCell = base::mac::ObjCCast<ImageButtonCell>([self cell]);
+ // Set the image for the default state, which is just the icon.
+ [theCell setImage:normalIcon forButtonState:image_button_cell::kDefaultState];
+
+ // Determine the appropriate image background style for the hover and pressed
+ // states.
+ ToolbarButtonImageBackgroundStyle hoverStyle;
+ ToolbarButtonImageBackgroundStyle pressedStyle;
+ const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
+ bool isNonIncognitoSystemTheme = themeProvider &&
+ !themeProvider->InIncognitoMode() && themeProvider->UsingSystemTheme();
+ // Use the regular style only when using the system (i.e. non-custom) theme
+ // and not in Incognito mode.
+ if (isNonIncognitoSystemTheme) {
+ hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER;
+ pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED;
+ } else {
+ hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER_THEMED;
+ pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED_THEMED;
+ }
+
+ // Create and set the image for the hover state.
+ NSImage* hoverImage =
+ [self imageForIcon:normalIcon withBackgroundStyle:hoverStyle];
+ [theCell setImage:hoverImage
+ forButtonState:image_button_cell::kHoverState];
+
+ // Create and set the image for the pressed state.
+ NSImage* pressedImage =
+ [self imageForIcon:normalIcon withBackgroundStyle:pressedStyle];
+ [theCell setImage:pressedImage
+ forButtonState:image_button_cell::kPressedState];
+
+ // Set the image for the disabled state, which is just the disabled icon,
+ // except if this is the home button.
+ if (iconId == gfx::VectorIconId::NAVIGATE_RELOAD) {
+ [theCell setImage:nil forButtonState:image_button_cell::kDisabledState];
+ } else {
+ [theCell setImage:disabledIcon
+ forButtonState:image_button_cell::kDisabledState];
+ }
+ [self setNeedsDisplay:YES];
+}
+
+- (void)resetIcons {
+ // Compute the button's icon.
+ gfx::VectorIconId icon_id = gfx::VectorIconId::VECTOR_ICON_NONE;
+ switch ([self viewID]) {
+ case VIEW_ID_BACK_BUTTON:
+ icon_id = gfx::VectorIconId::NAVIGATE_BACK;
+ break;
+ case VIEW_ID_FORWARD_BUTTON:
+ icon_id = gfx::VectorIconId::NAVIGATE_FORWARD;
+ break;
+ case VIEW_ID_HOME_BUTTON:
+ icon_id = gfx::VectorIconId::NAVIGATE_HOME;
+ break;
+ case VIEW_ID_APP_MENU:
+ icon_id = gfx::VectorIconId::BROWSER_TOOLS;
+ break;
+ default:
+ break;
+ }
+
+ // Set it.
+ if (icon_id != gfx::VectorIconId::VECTOR_ICON_NONE) {
+ [self setImagesFromIconId:icon_id];
+ }
+}
+
+- (void)viewDidMoveToWindow {
+ // In Material Design we want to catch when the button is attached to its
+ // window so that we can configure its appearance based on the window's
+ // theme.
+ if ([self window] && ui::MaterialDesignController::IsModeMaterial()) {
+ [self resetIcons];
+ }
+}
+
+// ThemedWindowDrawing implementation.
+
+- (void)windowDidChangeTheme {
+ [self resetIcons];
+}
+
+- (void)windowDidChangeActive {
+}
+
@end
« 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