| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/profiles/avatar_button_controller.h" | 5 #import "chrome/browser/ui/cocoa/profiles/avatar_button_controller.h" |
| 6 | 6 |
| 7 #include "base/mac/foundation_util.h" | 7 #include "base/mac/foundation_util.h" |
| 8 #include "base/strings/sys_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
| 9 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
| 10 #include "chrome/browser/profiles/profile_attributes_entry.h" | 10 #include "chrome/browser/profiles/profile_attributes_entry.h" |
| 11 #include "chrome/browser/profiles/profile_attributes_storage.h" | 11 #include "chrome/browser/profiles/profile_attributes_storage.h" |
| 12 #include "chrome/browser/profiles/profile_manager.h" | 12 #include "chrome/browser/profiles/profile_manager.h" |
| 13 #include "chrome/browser/profiles/profiles_state.h" | 13 #include "chrome/browser/profiles/profiles_state.h" |
| 14 #include "chrome/browser/themes/theme_service.h" | 14 #include "chrome/browser/themes/theme_service.h" |
| 15 #include "chrome/browser/themes/theme_service_factory.h" | 15 #include "chrome/browser/themes/theme_service_factory.h" |
| 16 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/browser_window.h" | 17 #include "chrome/browser/ui/browser_window.h" |
| 18 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 18 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 19 #include "chrome/browser/ui/cocoa/l10n_util.h" | 19 #include "chrome/browser/ui/cocoa/l10n_util.h" |
| 20 #import "chrome/browser/ui/cocoa/profiles/avatar_button.h" | 20 #import "chrome/browser/ui/cocoa/profiles/avatar_button.h" |
| 21 #include "chrome/grit/generated_resources.h" | 21 #include "chrome/grit/generated_resources.h" |
| 22 #import "chrome/browser/themes/theme_properties.h" | 22 #import "chrome/browser/themes/theme_properties.h" |
| 23 #include "chrome/grit/theme_resources.h" | 23 #include "chrome/grit/theme_resources.h" |
| 24 #include "components/signin/core/common/profile_management_switches.h" | 24 #include "components/signin/core/common/profile_management_switches.h" |
| 25 #include "skia/ext/skia_utils_mac.h" | 25 #include "skia/ext/skia_utils_mac.h" |
| 26 #import "ui/base/cocoa/appkit_utils.h" | 26 #import "ui/base/cocoa/appkit_utils.h" |
| 27 #include "ui/base/l10n/l10n_util_mac.h" | 27 #include "ui/base/l10n/l10n_util_mac.h" |
| 28 #include "ui/base/material_design/material_design_controller.h" | 28 #include "ui/base/material_design/material_design_controller.h" |
| 29 #include "ui/base/nine_image_painter_factory.h" | |
| 30 #include "ui/base/resource/resource_bundle.h" | |
| 31 #include "ui/gfx/color_palette.h" | 29 #include "ui/gfx/color_palette.h" |
| 32 #include "ui/gfx/image/image_skia_operations.h" | |
| 33 #include "ui/gfx/image/image_skia_util_mac.h" | 30 #include "ui/gfx/image/image_skia_util_mac.h" |
| 34 #include "ui/gfx/paint_vector_icon.h" | 31 #include "ui/gfx/paint_vector_icon.h" |
| 35 #include "ui/gfx/vector_icons_public.h" | 32 #include "ui/gfx/vector_icons_public.h" |
| 36 | 33 |
| 37 namespace { | 34 namespace { |
| 38 | 35 |
| 39 NSImage* GetImageFromResourceID(int resourceId) { | 36 const SkColor kButtonHoverColor = SkColorSetARGB(20, 0, 0, 0); |
| 40 return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( | 37 const SkColor kButtonPressedColor = SkColorSetARGB(31, 0, 0, 0); |
| 41 resourceId).ToNSImage(); | 38 const SkColor kAvatarIconColor = SkColorSetRGB(0x5a, 0x5a, 0x5a); |
| 42 } | |
| 43 | |
| 44 const SkColor kMaterialButtonHoverColor = SkColorSetARGB(20, 0, 0, 0); | |
| 45 const SkColor kMaterialButtonPressedColor = SkColorSetARGB(31, 0, 0, 0); | |
| 46 const SkColor kMaterialAvatarIconColor = SkColorSetRGB(0x5a, 0x5a, 0x5a); | |
| 47 | 39 |
| 48 const CGFloat kButtonHeight = 24; | 40 const CGFloat kButtonHeight = 24; |
| 49 | 41 |
| 50 // NSButtons have a default padding of 5px. Buttons should have a padding of | 42 // NSButtons have a default padding of 5px. Buttons should have a padding of |
| 51 // 6px. | 43 // 6px. |
| 52 const CGFloat kButtonExtraPadding = 6 - 5; | 44 const CGFloat kButtonExtraPadding = 6 - 5; |
| 53 | 45 |
| 54 // Extra padding for the MD signed out avatar button. | 46 // Extra padding for the signed out avatar button. |
| 55 const CGFloat kMaterialSignedOutWidthPadding = 2; | 47 const CGFloat kSignedOutWidthPadding = 2; |
| 56 | 48 |
| 57 // Kern value for the MD avatar button title. | 49 // Kern value for the avatar button title. |
| 58 const CGFloat kMaterialTitleKern = 0.25; | 50 const CGFloat kTitleKern = 0.25; |
| 59 | 51 |
| 60 } // namespace | 52 } // namespace |
| 61 | 53 |
| 62 // Button cell with a custom border given by a set of nine-patch image grids. | 54 // Button cell with a custom border given by a set of nine-patch image grids. |
| 63 @interface CustomThemeButtonCell : NSButtonCell { | 55 @interface CustomThemeButtonCell : NSButtonCell { |
| 64 @private | 56 @private |
| 65 BOOL isThemedWindow_; | 57 BOOL isThemedWindow_; |
| 66 BOOL hasError_; | 58 BOOL hasError_; |
| 67 } | 59 } |
| 68 - (void)setIsThemedWindow:(BOOL)isThemedWindow; | 60 - (void)setIsThemedWindow:(BOOL)isThemedWindow; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 79 return self; | 71 return self; |
| 80 } | 72 } |
| 81 | 73 |
| 82 - (NSSize)cellSize { | 74 - (NSSize)cellSize { |
| 83 NSSize buttonSize = [super cellSize]; | 75 NSSize buttonSize = [super cellSize]; |
| 84 | 76 |
| 85 // An image and no error means we are drawing the generic button, which | 77 // An image and no error means we are drawing the generic button, which |
| 86 // is square. Otherwise, we are displaying the profile's name and an | 78 // is square. Otherwise, we are displaying the profile's name and an |
| 87 // optional authentication error icon. | 79 // optional authentication error icon. |
| 88 if ([self image] && !hasError_) | 80 if ([self image] && !hasError_) |
| 89 buttonSize.width = kButtonHeight + kMaterialSignedOutWidthPadding; | 81 buttonSize.width = kButtonHeight + kSignedOutWidthPadding; |
| 90 else | 82 else |
| 91 buttonSize.width += 2 * kButtonExtraPadding; | 83 buttonSize.width += 2 * kButtonExtraPadding; |
| 92 buttonSize.height = kButtonHeight; | 84 buttonSize.height = kButtonHeight; |
| 93 return buttonSize; | 85 return buttonSize; |
| 94 } | 86 } |
| 95 | 87 |
| 96 - (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView*)controlView { | 88 - (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView*)controlView { |
| 97 NSRect frameAfterPadding = NSInsetRect(frame, kButtonExtraPadding, 0); | 89 NSRect frameAfterPadding = NSInsetRect(frame, kButtonExtraPadding, 0); |
| 98 [super drawInteriorWithFrame:frameAfterPadding inView:controlView]; | 90 [super drawInteriorWithFrame:frameAfterPadding inView:controlView]; |
| 99 } | 91 } |
| 100 | 92 |
| 101 - (void)drawImage:(NSImage*)image | 93 - (void)drawImage:(NSImage*)image |
| 102 withFrame:(NSRect)frame | 94 withFrame:(NSRect)frame |
| 103 inView:(NSView*)controlView { | 95 inView:(NSView*)controlView { |
| 104 // The image used in the generic button case as well as the material-designed | 96 // The image used in the generic button case as well as the error icon both |
| 105 // error icon both need to be shifted down slightly to be centered correctly. | 97 // need to be shifted down slightly to be centered correctly. |
| 106 // TODO(noms): When the assets are fixed, remove this latter offset. | 98 // TODO(noms): When the assets are fixed, remove this latter offset. |
| 107 if (!hasError_ || switches::IsMaterialDesignUserMenu()) | 99 if (!hasError_ || switches::IsMaterialDesignUserMenu()) |
| 108 frame = NSOffsetRect(frame, 0, 1); | 100 frame = NSOffsetRect(frame, 0, 1); |
| 109 [super drawImage:image withFrame:frame inView:controlView]; | 101 [super drawImage:image withFrame:frame inView:controlView]; |
| 110 } | 102 } |
| 111 | 103 |
| 112 - (void)drawBezelWithFrame:(NSRect)frame | 104 - (void)drawBezelWithFrame:(NSRect)frame |
| 113 inView:(NSView*)controlView { | 105 inView:(NSView*)controlView { |
| 114 HoverState hoverState = | 106 HoverState hoverState = |
| 115 [base::mac::ObjCCastStrict<AvatarButton>(controlView) hoverState]; | 107 [base::mac::ObjCCastStrict<AvatarButton>(controlView) hoverState]; |
| 116 | 108 |
| 117 NSColor* backgroundColor = nil; | 109 NSColor* backgroundColor = nil; |
| 118 if (hoverState == kHoverStateMouseDown) { | 110 if (hoverState == kHoverStateMouseDown) { |
| 119 backgroundColor = skia::SkColorToSRGBNSColor(kMaterialButtonPressedColor); | 111 backgroundColor = skia::SkColorToSRGBNSColor(kButtonPressedColor); |
| 120 } else if (hoverState == kHoverStateMouseOver) { | 112 } else if (hoverState == kHoverStateMouseOver) { |
| 121 backgroundColor = skia::SkColorToSRGBNSColor(kMaterialButtonHoverColor); | 113 backgroundColor = skia::SkColorToSRGBNSColor(kButtonHoverColor); |
| 122 } | 114 } |
| 123 | 115 |
| 124 if (backgroundColor) { | 116 if (backgroundColor) { |
| 125 [backgroundColor set]; | 117 [backgroundColor set]; |
| 126 NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:frame | 118 NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:frame |
| 127 xRadius:2.0f | 119 xRadius:2.0f |
| 128 yRadius:2.0f]; | 120 yRadius:2.0f]; |
| 129 [path fill]; | 121 [path fill]; |
| 130 } | 122 } |
| 131 } | 123 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 } | 200 } |
| 209 return self; | 201 return self; |
| 210 } | 202 } |
| 211 | 203 |
| 212 - (void)dealloc { | 204 - (void)dealloc { |
| 213 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 205 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 214 [super dealloc]; | 206 [super dealloc]; |
| 215 } | 207 } |
| 216 | 208 |
| 217 - (void)themeDidChangeNotification:(NSNotification*)aNotification { | 209 - (void)themeDidChangeNotification:(NSNotification*)aNotification { |
| 218 // Redraw the button if the window has switched between themed and native | |
| 219 // or if we're in MD design. | |
| 220 ThemeService* themeService = | 210 ThemeService* themeService = |
| 221 ThemeServiceFactory::GetForProfile(browser_->profile()); | 211 ThemeServiceFactory::GetForProfile(browser_->profile()); |
| 222 BOOL updatedIsThemedWindow = !themeService->UsingSystemTheme(); | 212 BOOL updatedIsThemedWindow = !themeService->UsingSystemTheme(); |
| 223 isThemedWindow_ = updatedIsThemedWindow; | 213 isThemedWindow_ = updatedIsThemedWindow; |
| 224 [[button_ cell] setIsThemedWindow:isThemedWindow_]; | 214 [[button_ cell] setIsThemedWindow:isThemedWindow_]; |
| 225 [self updateAvatarButtonAndLayoutParent:YES]; | 215 [self updateAvatarButtonAndLayoutParent:YES]; |
| 226 } | 216 } |
| 227 | 217 |
| 228 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent { | 218 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent { |
| 229 // The button text has a black foreground and a white drop shadow for regular | 219 // The button text has a black foreground and a white drop shadow for regular |
| 230 // windows, and a light text with a dark drop shadow for guest windows | 220 // windows, and a light text with a dark drop shadow for guest windows |
| 231 // which are themed with a dark background. If we're using MD, then there | 221 // which are themed with a dark background. |
| 232 // should be no drop shadows. | |
| 233 NSColor* foregroundColor; | 222 NSColor* foregroundColor; |
| 234 const ui::ThemeProvider* theme = | 223 const ui::ThemeProvider* theme = |
| 235 &ThemeService::GetThemeProviderForProfile(browser_->profile()); | 224 &ThemeService::GetThemeProviderForProfile(browser_->profile()); |
| 236 foregroundColor = theme ? theme->GetNSColor(ThemeProperties::COLOR_TAB_TEXT) | 225 foregroundColor = theme ? theme->GetNSColor(ThemeProperties::COLOR_TAB_TEXT) |
| 237 : [NSColor blackColor]; | 226 : [NSColor blackColor]; |
| 238 | 227 |
| 239 ProfileAttributesStorage& storage = | 228 ProfileAttributesStorage& storage = |
| 240 g_browser_process->profile_manager()->GetProfileAttributesStorage(); | 229 g_browser_process->profile_manager()->GetProfileAttributesStorage(); |
| 241 // If there is a single local profile, then use the generic avatar button | 230 // If there is a single local profile, then use the generic avatar button |
| 242 // instead of the profile name. Never use the generic button if the active | 231 // instead of the profile name. Never use the generic button if the active |
| 243 // profile is Guest. | 232 // profile is Guest. |
| 244 bool useGenericButton = | 233 bool useGenericButton = |
| 245 !browser_->profile()->IsGuestSession() && | 234 !browser_->profile()->IsGuestSession() && |
| 246 storage.GetNumberOfProfiles() == 1 && | 235 storage.GetNumberOfProfiles() == 1 && |
| 247 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); | 236 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); |
| 248 | 237 |
| 249 NSString* buttonTitle = base::SysUTF16ToNSString(useGenericButton ? | 238 NSString* buttonTitle = base::SysUTF16ToNSString(useGenericButton ? |
| 250 base::string16() : | 239 base::string16() : |
| 251 profiles::GetAvatarButtonTextForProfile(browser_->profile())); | 240 profiles::GetAvatarButtonTextForProfile(browser_->profile())); |
| 252 [[button_ cell] setHasError:hasError_ withTitle:buttonTitle]; | 241 [[button_ cell] setHasError:hasError_ withTitle:buttonTitle]; |
| 253 | 242 |
| 254 AvatarButton* button = | 243 AvatarButton* button = |
| 255 base::mac::ObjCCastStrict<AvatarButton>(button_); | 244 base::mac::ObjCCastStrict<AvatarButton>(button_); |
| 256 | 245 |
| 257 if (useGenericButton) { | 246 if (useGenericButton) { |
| 258 NSImage* avatarIcon = NSImageFromImageSkia(gfx::CreateVectorIcon( | 247 NSImage* avatarIcon = NSImageFromImageSkia(gfx::CreateVectorIcon( |
| 259 gfx::VectorIconId::USER_ACCOUNT_AVATAR, 18, kMaterialAvatarIconColor)); | 248 gfx::VectorIconId::USER_ACCOUNT_AVATAR, 18, kAvatarIconColor)); |
| 260 [button setDefaultImage:avatarIcon]; | 249 [button setDefaultImage:avatarIcon]; |
| 261 [button setHoverImage:nil]; | 250 [button setHoverImage:nil]; |
| 262 [button setPressedImage:nil]; | 251 [button setPressedImage:nil]; |
| 263 [button setImagePosition:NSImageOnly]; | 252 [button setImagePosition:NSImageOnly]; |
| 264 } else if (hasError_) { | 253 } else if (hasError_) { |
| 265 NSImage* errorIcon = NSImageFromImageSkia(gfx::CreateVectorIcon( | 254 NSImage* errorIcon = NSImageFromImageSkia(gfx::CreateVectorIcon( |
| 266 gfx::VectorIconId::SYNC_PROBLEM, 16, gfx::kGoogleRed700)); | 255 gfx::VectorIconId::SYNC_PROBLEM, 16, gfx::kGoogleRed700)); |
| 267 [button setDefaultImage:errorIcon]; | 256 [button setDefaultImage:errorIcon]; |
| 268 [button setHoverImage:nil]; | 257 [button setHoverImage:nil]; |
| 269 [button setPressedImage:nil]; | 258 [button setPressedImage:nil]; |
| 270 [button setImage:errorIcon]; | 259 [button setImage:errorIcon]; |
| 271 [button setImagePosition:NSImageLeft]; | 260 [button setImagePosition:NSImageLeft]; |
| 272 } else { | 261 } else { |
| 273 [button setDefaultImage:nil]; | 262 [button setDefaultImage:nil]; |
| 274 [button setHoverImage:nil]; | 263 [button setHoverImage:nil]; |
| 275 [button setPressedImage:nil]; | 264 [button setPressedImage:nil]; |
| 276 [button setImagePosition:NSNoImage]; | 265 [button setImagePosition:NSNoImage]; |
| 277 } | 266 } |
| 278 | 267 |
| 279 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( | 268 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( |
| 280 [[NSMutableParagraphStyle alloc] init]); | 269 [[NSMutableParagraphStyle alloc] init]); |
| 281 [paragraphStyle setAlignment:NSLeftTextAlignment]; | 270 [paragraphStyle setAlignment:NSLeftTextAlignment]; |
| 282 | 271 |
| 283 base::scoped_nsobject<NSAttributedString> attributedTitle([ | 272 base::scoped_nsobject<NSAttributedString> attributedTitle( |
| 284 [NSAttributedString alloc] | 273 [[NSAttributedString alloc] |
| 285 initWithString:buttonTitle | 274 initWithString:buttonTitle |
| 286 attributes:@{ | 275 attributes:@{ |
| 287 NSForegroundColorAttributeName : foregroundColor, | 276 NSForegroundColorAttributeName : foregroundColor, |
| 288 NSParagraphStyleAttributeName : paragraphStyle, | 277 NSParagraphStyleAttributeName : paragraphStyle, |
| 289 NSKernAttributeName : [NSNumber numberWithFloat:kMaterialTitleKern] | 278 NSKernAttributeName : [NSNumber numberWithFloat:kTitleKern] |
| 290 }]); | 279 }]); |
| 291 [button_ setAttributedTitle:attributedTitle]; | 280 [button_ setAttributedTitle:attributedTitle]; |
| 292 [button_ sizeToFit]; | 281 [button_ sizeToFit]; |
| 293 | 282 |
| 294 if (layoutParent) { | 283 if (layoutParent) { |
| 295 // Because the width of the button might have changed, the parent browser | 284 // Because the width of the button might have changed, the parent browser |
| 296 // frame needs to recalculate the button bounds and redraw it. | 285 // frame needs to recalculate the button bounds and redraw it. |
| 297 [[BrowserWindowController | 286 [[BrowserWindowController |
| 298 browserWindowControllerForWindow:browser_->window()->GetNativeWindow()] | 287 browserWindowControllerForWindow:browser_->window()->GetNativeWindow()] |
| 299 layoutSubviews]; | 288 layoutSubviews]; |
| 300 } | 289 } |
| 301 } | 290 } |
| 302 | 291 |
| 303 - (void)setErrorStatus:(BOOL)hasError { | 292 - (void)setErrorStatus:(BOOL)hasError { |
| 304 hasError_ = hasError; | 293 hasError_ = hasError; |
| 305 [self updateAvatarButtonAndLayoutParent:YES]; | 294 [self updateAvatarButtonAndLayoutParent:YES]; |
| 306 } | 295 } |
| 307 | 296 |
| 308 @end | 297 @end |
| OLD | NEW |