| OLD | NEW |
| 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" | 7 #include "base/mac/foundation_util.h" |
| 8 #include "base/mac/sdk_forward_declarations.h" | 8 #include "base/mac/sdk_forward_declarations.h" |
| 9 #import "chrome/browser/ui/cocoa/image_button_cell.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" | 10 #import "chrome/browser/ui/cocoa/view_id_util.h" |
| 12 #include "skia/ext/skia_utils_mac.h" | 11 #include "skia/ext/skia_utils_mac.h" |
| 13 #import "ui/base/cocoa/nsview_additions.h" | 12 #import "ui/base/cocoa/nsview_additions.h" |
| 14 #include "ui/base/material_design/material_design_controller.h" | 13 #include "ui/base/material_design/material_design_controller.h" |
| 15 #include "ui/base/theme_provider.h" | 14 #include "ui/base/theme_provider.h" |
| 16 #include "ui/gfx/image/image_skia_util_mac.h" | 15 #include "ui/gfx/image/image_skia_util_mac.h" |
| 17 #include "ui/gfx/paint_vector_icon.h" | 16 #include "ui/gfx/paint_vector_icon.h" |
| 18 | 17 |
| 19 namespace { | 18 namespace { |
| 20 | 19 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 break; | 97 break; |
| 99 case ToolbarButtonImageBackgroundStyle::PRESSED_THEMED: | 98 case ToolbarButtonImageBackgroundStyle::PRESSED_THEMED: |
| 100 fillColor = [NSColor colorWithCalibratedWhite:1 alpha:0.12]; | 99 fillColor = [NSColor colorWithCalibratedWhite:1 alpha:0.12]; |
| 101 break; | 100 break; |
| 102 } | 101 } |
| 103 | 102 |
| 104 // Fill the path. | 103 // Fill the path. |
| 105 [fillColor set]; | 104 [fillColor set]; |
| 106 [roundedRectPath fill]; | 105 [roundedRectPath fill]; |
| 107 | 106 |
| 108 // Compute the icon's location and draw it there. | 107 // Center the icon within the button. |
| 109 CGFloat iconInset = | 108 NSSize iconSize = [imageRep.icon size]; |
| 110 (kMDButtonBounds.size.width - kMDButtonIconSize.width) / 2; | 109 CGFloat iconInset = (kMDButtonBounds.size.width - iconSize.width) / 2; |
| 111 NSRect iconDestRect = NSInsetRect(kMDButtonBounds, iconInset, iconInset); | 110 NSRect iconDestRect = NSInsetRect(kMDButtonBounds, iconInset, iconInset); |
| 112 [imageRep.icon drawInRect:iconDestRect | 111 [imageRep.icon drawInRect:iconDestRect |
| 113 fromRect:NSZeroRect | 112 fromRect:NSZeroRect |
| 114 operation:NSCompositeSourceOver | 113 operation:NSCompositeSourceOver |
| 115 fraction:1]; | 114 fraction:1]; |
| 116 } | 115 } |
| 117 | 116 |
| 118 @end | 117 @end |
| 119 | 118 |
| 120 @interface ToolbarButton () | 119 @interface ToolbarButton () |
| 121 // Returns an image that draws the browser tools button icon using vector | 120 // Returns an image that draws the browser tools button icon using vector |
| 122 // commands. | 121 // commands. |
| 123 - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor; | 122 - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor; |
| 124 // Returns an button image by combining |iconImage| with the specified button | 123 // Returns an button image by combining |iconImage| with the specified button |
| 125 // background. | 124 // background. |
| 126 - (NSImage*)imageForIcon:(NSImage*)iconImage | 125 - (NSImage*)imageForIcon:(NSImage*)iconImage |
| 127 withBackgroundStyle:(ToolbarButtonImageBackgroundStyle)style; | 126 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 | 127 // 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 | 128 // can't set the image before this because its appearance depends upon the |
| 133 // browser window's theme. | 129 // browser window's theme. |
| 134 - (void)viewDidMoveToWindow; | 130 - (void)viewDidMoveToWindow; |
| 135 | 131 |
| 136 @end | 132 @end |
| 137 | 133 |
| 138 | 134 |
| 139 @implementation ToolbarButton | 135 @implementation ToolbarButton |
| 140 | 136 |
| 141 @synthesize handleMiddleClick = handleMiddleClick_; | 137 @synthesize handleMiddleClick = handleMiddleClick_; |
| 142 | 138 |
| 139 + (NSSize)toolbarButtonSize { |
| 140 if (!ui::MaterialDesignController::IsModeMaterial()) { |
| 141 return NSMakeSize(29, 29); |
| 142 } |
| 143 |
| 144 return kMDButtonBounds.size; |
| 145 } |
| 146 |
| 143 - (void)otherMouseDown:(NSEvent*)theEvent { | 147 - (void)otherMouseDown:(NSEvent*)theEvent { |
| 144 if (![self shouldHandleEvent:theEvent]) { | 148 if (![self shouldHandleEvent:theEvent]) { |
| 145 [super otherMouseDown:theEvent]; | 149 [super otherMouseDown:theEvent]; |
| 146 return; | 150 return; |
| 147 } | 151 } |
| 148 | 152 |
| 149 NSEvent* nextEvent = theEvent; | 153 NSEvent* nextEvent = theEvent; |
| 150 BOOL isInside; | 154 BOOL isInside; |
| 151 | 155 |
| 152 // Loop until middle button is released. Also, the mouse cursor is outside of | 156 // Loop until middle button is released. Also, the mouse cursor is outside of |
| (...skipping 27 matching lines...) Expand all Loading... |
| 180 return handleMiddleClick_ && [theEvent buttonNumber] == 2; | 184 return handleMiddleClick_ && [theEvent buttonNumber] == 2; |
| 181 } | 185 } |
| 182 | 186 |
| 183 - (void)drawFocusRingMask { | 187 - (void)drawFocusRingMask { |
| 184 // Match the hover image's bezel. | 188 // Match the hover image's bezel. |
| 185 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], 2, 2) | 189 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], 2, 2) |
| 186 xRadius:2 | 190 xRadius:2 |
| 187 yRadius:2] fill]; | 191 yRadius:2] fill]; |
| 188 } | 192 } |
| 189 | 193 |
| 190 - (SkColor)iconColor:(BOOL)themeIsDark { | 194 - (gfx::VectorIconId)vectorIconId { |
| 195 switch ([self viewID]) { |
| 196 case VIEW_ID_BACK_BUTTON: |
| 197 return gfx::VectorIconId::NAVIGATE_BACK; |
| 198 case VIEW_ID_FORWARD_BUTTON: |
| 199 return gfx::VectorIconId::NAVIGATE_FORWARD; |
| 200 case VIEW_ID_HOME_BUTTON: |
| 201 return gfx::VectorIconId::NAVIGATE_HOME; |
| 202 case VIEW_ID_APP_MENU: |
| 203 return gfx::VectorIconId::BROWSER_TOOLS; |
| 204 default: |
| 205 break; |
| 206 } |
| 207 |
| 208 return gfx::VectorIconId::VECTOR_ICON_NONE; |
| 209 } |
| 210 |
| 211 - (SkColor)vectorIconColor:(BOOL)themeIsDark { |
| 191 return themeIsDark ? SK_ColorWHITE : SkColorSetRGB(0x5A, 0x5A, 0x5A); | 212 return themeIsDark ? SK_ColorWHITE : SkColorSetRGB(0x5A, 0x5A, 0x5A); |
| 192 } | 213 } |
| 193 | 214 |
| 194 - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor { | 215 - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor { |
| 195 // Create a |BrowserToolsImageRep| to draw the browser tools icon using | 216 // Create a |BrowserToolsImageRep| to draw the browser tools icon using |
| 196 // the provided fill color. | 217 // the provided fill color. |
| 197 base::scoped_nsobject<BrowserToolsImageRep> imageRep = | 218 base::scoped_nsobject<BrowserToolsImageRep> imageRep = |
| 198 [[BrowserToolsImageRep alloc] | 219 [[BrowserToolsImageRep alloc] |
| 199 initWithDrawSelector:@selector(drawBrowserToolsIcon:) | 220 initWithDrawSelector:@selector(drawBrowserToolsIcon:) |
| 200 delegate:[BrowserToolsImageRep class]]; | 221 delegate:[BrowserToolsImageRep class]]; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 222 | 243 |
| 223 // Create the image from the image rep. | 244 // Create the image from the image rep. |
| 224 NSImage* image = | 245 NSImage* image = |
| 225 [[[NSImage alloc] initWithSize:kMDButtonBounds.size] autorelease]; | 246 [[[NSImage alloc] initWithSize:kMDButtonBounds.size] autorelease]; |
| 226 [image setCacheMode:NSImageCacheAlways]; | 247 [image setCacheMode:NSImageCacheAlways]; |
| 227 [image addRepresentation:imageRep]; | 248 [image addRepresentation:imageRep]; |
| 228 | 249 |
| 229 return image; | 250 return image; |
| 230 } | 251 } |
| 231 | 252 |
| 232 - (void)setImagesFromIconId:(gfx::VectorIconId)iconId { | 253 - (void)setImage:(NSImage*)anImage { |
| 233 // Compute the normal and disabled icon colors. | 254 [super setImage:anImage]; |
| 234 BOOL isDarkTheme = [[self window] hasDarkTheme]; | 255 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 235 const SkColor iconColor = [self iconColor:isDarkTheme]; | 256 [self resetButtonStateImages]; |
| 236 CGFloat normalAlpha = isDarkTheme ? 0xCC : 0xFF; | 257 } |
| 237 const SkColor normalColor = SkColorSetA(iconColor, normalAlpha); | 258 } |
| 238 const SkColor disabledColor = SkColorSetA(iconColor, 0x33); | |
| 239 | 259 |
| 240 // Create the normal and disabled state icons. These icons are | 260 - (void)resetButtonStateImages { |
| 241 // always the same shape, but use a different color. | 261 DCHECK(ui::MaterialDesignController::IsModeMaterial()); |
| 262 |
| 242 NSImage* normalIcon = nil; | 263 NSImage* normalIcon = nil; |
| 243 NSImage* disabledIcon = nil; | 264 NSImage* disabledIcon = nil; |
| 244 if (iconId == gfx::VectorIconId::BROWSER_TOOLS) { | 265 |
| 245 normalIcon = [self browserToolsIconForFillColor:normalColor]; | 266 gfx::VectorIconId iconId = [self vectorIconId]; |
| 246 disabledIcon = [self browserToolsIconForFillColor:disabledColor]; | 267 if (iconId == gfx::VectorIconId::VECTOR_ICON_NONE) { |
| 268 // If the button does not have a vector icon id (e.g. it's an extension |
| 269 // button), use its image. |
| 270 normalIcon = disabledIcon = [self image]; |
| 247 } else { | 271 } else { |
| 248 normalIcon = NSImageFromImageSkia( | 272 // Compute the normal and disabled vector icon colors. |
| 249 gfx::CreateVectorIcon(iconId, kMDButtonIconSize.width, normalColor)); | 273 BOOL isDarkTheme = [[self window] hasDarkTheme]; |
| 250 disabledIcon = NSImageFromImageSkia( | 274 const SkColor vectorIconColor = [self vectorIconColor:isDarkTheme]; |
| 251 gfx::CreateVectorIcon(iconId, kMDButtonIconSize.width, disabledColor)); | 275 CGFloat normalAlpha = isDarkTheme ? 0xCC : 0xFF; |
| 276 const SkColor normalColor = SkColorSetA(vectorIconColor, normalAlpha); |
| 277 const SkColor disabledColor = SkColorSetA(vectorIconColor, 0x33); |
| 278 |
| 279 // Create the normal and disabled state icons. These icons are always the |
| 280 // same shape but use a different color. |
| 281 if (iconId == gfx::VectorIconId::BROWSER_TOOLS) { |
| 282 normalIcon = [self browserToolsIconForFillColor:normalColor]; |
| 283 disabledIcon = [self browserToolsIconForFillColor:disabledColor]; |
| 284 } else { |
| 285 normalIcon = NSImageFromImageSkia( |
| 286 gfx::CreateVectorIcon(iconId, |
| 287 kMDButtonIconSize.width, |
| 288 normalColor)); |
| 289 |
| 290 // The home button has no icon for its disabled state. |
| 291 if (iconId != gfx::VectorIconId::NAVIGATE_RELOAD) { |
| 292 disabledIcon = NSImageFromImageSkia( |
| 293 gfx::CreateVectorIcon(iconId, |
| 294 kMDButtonIconSize.width, |
| 295 disabledColor)); |
| 296 } |
| 297 } |
| 252 } | 298 } |
| 253 | 299 |
| 254 ImageButtonCell* theCell = base::mac::ObjCCast<ImageButtonCell>([self cell]); | 300 ImageButtonCell* theCell = base::mac::ObjCCast<ImageButtonCell>([self cell]); |
| 255 // Set the image for the default state, which is just the icon. | 301 // Set the image for the default state, which is just the icon. |
| 256 [theCell setImage:normalIcon forButtonState:image_button_cell::kDefaultState]; | 302 [theCell setImage:normalIcon forButtonState:image_button_cell::kDefaultState]; |
| 257 | 303 |
| 258 // Determine the appropriate image background style for the hover and pressed | 304 // Determine the appropriate image background style for the hover and pressed |
| 259 // states. | 305 // states. |
| 260 ToolbarButtonImageBackgroundStyle hoverStyle; | 306 ToolbarButtonImageBackgroundStyle hoverStyle = |
| 261 ToolbarButtonImageBackgroundStyle pressedStyle; | 307 ToolbarButtonImageBackgroundStyle::HOVER; |
| 308 ToolbarButtonImageBackgroundStyle pressedStyle = |
| 309 ToolbarButtonImageBackgroundStyle::PRESSED; |
| 310 |
| 311 // Use the themed style for custom themes and Incognito mode. |
| 262 const ui::ThemeProvider* themeProvider = [[self window] themeProvider]; | 312 const ui::ThemeProvider* themeProvider = [[self window] themeProvider]; |
| 263 bool isNonIncognitoSystemTheme = themeProvider && | 313 bool incongitoMode = themeProvider && themeProvider->InIncognitoMode(); |
| 264 !themeProvider->InIncognitoMode() && themeProvider->UsingSystemTheme(); | 314 bool usingACustomTheme = themeProvider && !themeProvider->UsingSystemTheme(); |
| 265 // Use the regular style only when using the system (i.e. non-custom) theme | 315 if (usingACustomTheme || incongitoMode) { |
| 266 // and not in Incognito mode. | |
| 267 if (isNonIncognitoSystemTheme) { | |
| 268 hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER; | |
| 269 pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED; | |
| 270 } else { | |
| 271 hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER_THEMED; | 316 hoverStyle = ToolbarButtonImageBackgroundStyle::HOVER_THEMED; |
| 272 pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED_THEMED; | 317 pressedStyle = ToolbarButtonImageBackgroundStyle::PRESSED_THEMED; |
| 273 } | 318 } |
| 274 | 319 |
| 275 // Create and set the image for the hover state. | 320 // Create and set the hover state image. |
| 276 NSImage* hoverImage = | 321 NSImage* hoverImage = |
| 277 [self imageForIcon:normalIcon withBackgroundStyle:hoverStyle]; | 322 [self imageForIcon:normalIcon withBackgroundStyle:hoverStyle]; |
| 278 [theCell setImage:hoverImage | 323 [theCell setImage:hoverImage |
| 279 forButtonState:image_button_cell::kHoverState]; | 324 forButtonState:image_button_cell::kHoverState]; |
| 280 | 325 |
| 281 // Create and set the image for the pressed state. | 326 // Create and set the pressed state image. |
| 282 NSImage* pressedImage = | 327 NSImage* pressedImage = |
| 283 [self imageForIcon:normalIcon withBackgroundStyle:pressedStyle]; | 328 [self imageForIcon:normalIcon withBackgroundStyle:pressedStyle]; |
| 284 [theCell setImage:pressedImage | 329 [theCell setImage:pressedImage |
| 285 forButtonState:image_button_cell::kPressedState]; | 330 forButtonState:image_button_cell::kPressedState]; |
| 286 | 331 |
| 287 // Set the image for the disabled state, which is just the disabled icon, | 332 // Set the disabled state image. |
| 288 // except if this is the home button. | 333 [theCell setImage:disabledIcon |
| 289 if (iconId == gfx::VectorIconId::NAVIGATE_RELOAD) { | 334 forButtonState:image_button_cell::kDisabledState]; |
| 290 [theCell setImage:nil forButtonState:image_button_cell::kDisabledState]; | 335 |
| 291 } else { | |
| 292 [theCell setImage:disabledIcon | |
| 293 forButtonState:image_button_cell::kDisabledState]; | |
| 294 } | |
| 295 [self setNeedsDisplay:YES]; | 336 [self setNeedsDisplay:YES]; |
| 296 } | 337 } |
| 297 | 338 |
| 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 { | 339 - (void)viewDidMoveToWindow { |
| 325 // In Material Design we want to catch when the button is attached to its | 340 // 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 | 341 // window so that we can configure its appearance based on the window's |
| 327 // theme. | 342 // theme. |
| 328 if ([self window] && ui::MaterialDesignController::IsModeMaterial()) { | 343 if ([self window] && ui::MaterialDesignController::IsModeMaterial()) { |
| 329 [self resetIcons]; | 344 [self resetButtonStateImages]; |
| 330 } | 345 } |
| 331 } | 346 } |
| 332 | 347 |
| 333 // ThemedWindowDrawing implementation. | 348 // ThemedWindowDrawing implementation. |
| 334 | 349 |
| 335 - (void)windowDidChangeTheme { | 350 - (void)windowDidChangeTheme { |
| 336 [self resetIcons]; | 351 // Update the hover and pressed image backgrounds to match the current theme. |
| 352 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 353 [self resetButtonStateImages]; |
| 354 } |
| 337 } | 355 } |
| 338 | 356 |
| 339 - (void)windowDidChangeActive { | 357 - (void)windowDidChangeActive { |
| 340 } | 358 } |
| 341 | 359 |
| 342 @end | 360 @end |
| OLD | NEW |