| 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" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "ui/base/nine_image_painter_factory.h" | 29 #include "ui/base/nine_image_painter_factory.h" |
| 30 #include "ui/base/resource/resource_bundle.h" | 30 #include "ui/base/resource/resource_bundle.h" |
| 31 #include "ui/gfx/color_palette.h" | 31 #include "ui/gfx/color_palette.h" |
| 32 #include "ui/gfx/image/image_skia_operations.h" | 32 #include "ui/gfx/image/image_skia_operations.h" |
| 33 #include "ui/gfx/image/image_skia_util_mac.h" | 33 #include "ui/gfx/image/image_skia_util_mac.h" |
| 34 #include "ui/gfx/paint_vector_icon.h" | 34 #include "ui/gfx/paint_vector_icon.h" |
| 35 #include "ui/gfx/vector_icons_public.h" | 35 #include "ui/gfx/vector_icons_public.h" |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| 39 const ui::NinePartImageIds kNormalBorderImageIds = | |
| 40 IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); | |
| 41 const ui::NinePartImageIds kHoverBorderImageIds = | |
| 42 IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); | |
| 43 const ui::NinePartImageIds kPressedBorderImageIds = | |
| 44 IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); | |
| 45 const ui::NinePartImageIds kThemedBorderImageIds = | |
| 46 IMAGE_GRID(IDR_AVATAR_THEMED_MAC_BUTTON_NORMAL); | |
| 47 | |
| 48 NSImage* GetImageFromResourceID(int resourceId) { | 39 NSImage* GetImageFromResourceID(int resourceId) { |
| 49 return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( | 40 return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| 50 resourceId).ToNSImage(); | 41 resourceId).ToNSImage(); |
| 51 } | 42 } |
| 52 | 43 |
| 53 const SkColor kMaterialButtonHoverColor = SkColorSetARGB(20, 0, 0, 0); | 44 const SkColor kMaterialButtonHoverColor = SkColorSetARGB(20, 0, 0, 0); |
| 54 const SkColor kMaterialButtonPressedColor = SkColorSetARGB(31, 0, 0, 0); | 45 const SkColor kMaterialButtonPressedColor = SkColorSetARGB(31, 0, 0, 0); |
| 55 const SkColor kMaterialAvatarIconColor = SkColorSetRGB(0x5a, 0x5a, 0x5a); | 46 const SkColor kMaterialAvatarIconColor = SkColorSetRGB(0x5a, 0x5a, 0x5a); |
| 56 | 47 |
| 57 CGFloat ButtonHeight() { | 48 const CGFloat kButtonHeight = 24; |
| 58 const CGFloat kButtonHeight = 28; | |
| 59 const CGFloat kMaterialButtonHeight = 24; | |
| 60 return ui::MaterialDesignController::IsModeMaterial() ? kMaterialButtonHeight | |
| 61 : kButtonHeight; | |
| 62 } | |
| 63 | 49 |
| 64 // NSButtons have a default padding of 5px. Non-MD buttons should have a | 50 // NSButtons have a default padding of 5px. Buttons should have a padding of |
| 65 // padding of 8px. Meanwhile, MD buttons should have a padding of 6px. | 51 // 6px. |
| 66 CGFloat ButtonExtraPadding() { | 52 const CGFloat kButtonExtraPadding = 6 - 5; |
| 67 const CGFloat kDefaultPadding = 5; | |
| 68 const CGFloat kButtonExtraPadding = 8 - kDefaultPadding; | |
| 69 const CGFloat kMaterialButtonExtraPadding = 6 - kDefaultPadding; | |
| 70 | |
| 71 return ui::MaterialDesignController::IsModeMaterial() | |
| 72 ? kMaterialButtonExtraPadding | |
| 73 : kButtonExtraPadding; | |
| 74 } | |
| 75 | 53 |
| 76 // Extra padding for the MD signed out avatar button. | 54 // Extra padding for the MD signed out avatar button. |
| 77 const CGFloat kMaterialSignedOutWidthPadding = 2; | 55 const CGFloat kMaterialSignedOutWidthPadding = 2; |
| 78 | 56 |
| 79 // Kern value for the MD avatar button title. | 57 // Kern value for the MD avatar button title. |
| 80 const CGFloat kMaterialTitleKern = 0.25; | 58 const CGFloat kMaterialTitleKern = 0.25; |
| 81 | 59 |
| 82 } // namespace | 60 } // namespace |
| 83 | 61 |
| 84 // Button cell with a custom border given by a set of nine-patch image grids. | 62 // Button cell with a custom border given by a set of nine-patch image grids. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 100 } | 78 } |
| 101 return self; | 79 return self; |
| 102 } | 80 } |
| 103 | 81 |
| 104 - (NSSize)cellSize { | 82 - (NSSize)cellSize { |
| 105 NSSize buttonSize = [super cellSize]; | 83 NSSize buttonSize = [super cellSize]; |
| 106 | 84 |
| 107 // An image and no error means we are drawing the generic button, which | 85 // An image and no error means we are drawing the generic button, which |
| 108 // is square. Otherwise, we are displaying the profile's name and an | 86 // is square. Otherwise, we are displaying the profile's name and an |
| 109 // optional authentication error icon. | 87 // optional authentication error icon. |
| 110 if ([self image] && !hasError_) { | 88 if ([self image] && !hasError_) |
| 111 buttonSize.width = ButtonHeight(); | 89 buttonSize.width = kButtonHeight + kMaterialSignedOutWidthPadding; |
| 112 if (ui::MaterialDesignController::IsModeMaterial()) | 90 else |
| 113 buttonSize.width += kMaterialSignedOutWidthPadding; | 91 buttonSize.width += 2 * kButtonExtraPadding; |
| 114 } else { | 92 buttonSize.height = kButtonHeight; |
| 115 buttonSize.width += 2 * ButtonExtraPadding(); | |
| 116 } | |
| 117 buttonSize.height = ButtonHeight(); | |
| 118 return buttonSize; | 93 return buttonSize; |
| 119 } | 94 } |
| 120 | 95 |
| 121 - (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView*)controlView { | 96 - (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView*)controlView { |
| 122 NSRect frameAfterPadding = NSInsetRect(frame, ButtonExtraPadding(), 0); | 97 NSRect frameAfterPadding = NSInsetRect(frame, kButtonExtraPadding, 0); |
| 123 [super drawInteriorWithFrame:frameAfterPadding inView:controlView]; | 98 [super drawInteriorWithFrame:frameAfterPadding inView:controlView]; |
| 124 } | 99 } |
| 125 | 100 |
| 126 - (void)drawImage:(NSImage*)image | 101 - (void)drawImage:(NSImage*)image |
| 127 withFrame:(NSRect)frame | 102 withFrame:(NSRect)frame |
| 128 inView:(NSView*)controlView { | 103 inView:(NSView*)controlView { |
| 129 // The image used in the generic button case as well as the material-designed | 104 // The image used in the generic button case as well as the material-designed |
| 130 // error icon both need to be shifted down slightly to be centered correctly. | 105 // error icon both need to be shifted down slightly to be centered correctly. |
| 131 // TODO(noms): When the assets are fixed, remove this latter offset. | 106 // TODO(noms): When the assets are fixed, remove this latter offset. |
| 132 if (!hasError_ || switches::IsMaterialDesignUserMenu()) | 107 if (!hasError_ || switches::IsMaterialDesignUserMenu()) |
| 133 frame = NSOffsetRect(frame, 0, 1); | 108 frame = NSOffsetRect(frame, 0, 1); |
| 134 [super drawImage:image withFrame:frame inView:controlView]; | 109 [super drawImage:image withFrame:frame inView:controlView]; |
| 135 } | 110 } |
| 136 | 111 |
| 137 - (void)drawBezelWithFrame:(NSRect)frame | 112 - (void)drawBezelWithFrame:(NSRect)frame |
| 138 inView:(NSView*)controlView { | 113 inView:(NSView*)controlView { |
| 139 HoverState hoverState = | 114 HoverState hoverState = |
| 140 [base::mac::ObjCCastStrict<AvatarButton>(controlView) hoverState]; | 115 [base::mac::ObjCCastStrict<AvatarButton>(controlView) hoverState]; |
| 141 | 116 |
| 142 if (ui::MaterialDesignController::IsModeMaterial()) { | 117 NSColor* backgroundColor = nil; |
| 143 NSColor* backgroundColor = nil; | 118 if (hoverState == kHoverStateMouseDown) { |
| 144 if (hoverState == kHoverStateMouseDown) { | 119 backgroundColor = skia::SkColorToSRGBNSColor(kMaterialButtonPressedColor); |
| 145 backgroundColor = skia::SkColorToSRGBNSColor(kMaterialButtonPressedColor); | 120 } else if (hoverState == kHoverStateMouseOver) { |
| 146 } else if (hoverState == kHoverStateMouseOver) { | 121 backgroundColor = skia::SkColorToSRGBNSColor(kMaterialButtonHoverColor); |
| 147 backgroundColor = skia::SkColorToSRGBNSColor(kMaterialButtonHoverColor); | 122 } |
| 148 } | |
| 149 | 123 |
| 150 if (backgroundColor) { | 124 if (backgroundColor) { |
| 151 [backgroundColor set]; | 125 [backgroundColor set]; |
| 152 NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:frame | 126 NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:frame |
| 153 xRadius:2.0f | 127 xRadius:2.0f |
| 154 yRadius:2.0f]; | 128 yRadius:2.0f]; |
| 155 [path fill]; | 129 [path fill]; |
| 156 } | |
| 157 } else { | |
| 158 ui::NinePartImageIds imageIds = kNormalBorderImageIds; | |
| 159 if (isThemedWindow_) | |
| 160 imageIds = kThemedBorderImageIds; | |
| 161 | |
| 162 if (hoverState == kHoverStateMouseDown) | |
| 163 imageIds = kPressedBorderImageIds; | |
| 164 else if (hoverState == kHoverStateMouseOver) | |
| 165 imageIds = kHoverBorderImageIds; | |
| 166 ui::DrawNinePartImage(frame, imageIds, NSCompositeSourceOver, 1.0, true); | |
| 167 } | 130 } |
| 168 } | 131 } |
| 169 | 132 |
| 170 - (void)drawFocusRingMaskWithFrame:(NSRect)frame inView:(NSView*)view { | 133 - (void)drawFocusRingMaskWithFrame:(NSRect)frame inView:(NSView*)view { |
| 171 // Match the bezel's shape. | 134 // Match the bezel's shape. |
| 172 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2, 2) | 135 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2, 2) |
| 173 xRadius:2 | 136 xRadius:2 |
| 174 yRadius:2] fill]; | 137 yRadius:2] fill]; |
| 175 } | 138 } |
| 176 | 139 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 213 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 251 [super dealloc]; | 214 [super dealloc]; |
| 252 } | 215 } |
| 253 | 216 |
| 254 - (void)themeDidChangeNotification:(NSNotification*)aNotification { | 217 - (void)themeDidChangeNotification:(NSNotification*)aNotification { |
| 255 // Redraw the button if the window has switched between themed and native | 218 // Redraw the button if the window has switched between themed and native |
| 256 // or if we're in MD design. | 219 // or if we're in MD design. |
| 257 ThemeService* themeService = | 220 ThemeService* themeService = |
| 258 ThemeServiceFactory::GetForProfile(browser_->profile()); | 221 ThemeServiceFactory::GetForProfile(browser_->profile()); |
| 259 BOOL updatedIsThemedWindow = !themeService->UsingSystemTheme(); | 222 BOOL updatedIsThemedWindow = !themeService->UsingSystemTheme(); |
| 260 if (isThemedWindow_ != updatedIsThemedWindow || | 223 isThemedWindow_ = updatedIsThemedWindow; |
| 261 ui::MaterialDesignController::IsModeMaterial()) { | 224 [[button_ cell] setIsThemedWindow:isThemedWindow_]; |
| 262 isThemedWindow_ = updatedIsThemedWindow; | 225 [self updateAvatarButtonAndLayoutParent:YES]; |
| 263 [[button_ cell] setIsThemedWindow:isThemedWindow_]; | |
| 264 [self updateAvatarButtonAndLayoutParent:YES]; | |
| 265 } | |
| 266 } | 226 } |
| 267 | 227 |
| 268 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent { | 228 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent { |
| 269 // The button text has a black foreground and a white drop shadow for regular | 229 // The button text has a black foreground and a white drop shadow for regular |
| 270 // windows, and a light text with a dark drop shadow for guest windows | 230 // windows, and a light text with a dark drop shadow for guest windows |
| 271 // which are themed with a dark background. If we're using MD, then there | 231 // which are themed with a dark background. If we're using MD, then there |
| 272 // should be no drop shadows. | 232 // should be no drop shadows. |
| 273 BOOL isMaterial = ui::MaterialDesignController::IsModeMaterial(); | |
| 274 | |
| 275 NSColor* foregroundColor; | 233 NSColor* foregroundColor; |
| 276 if (isMaterial) { | 234 const ui::ThemeProvider* theme = |
| 277 const ui::ThemeProvider* theme = | 235 &ThemeService::GetThemeProviderForProfile(browser_->profile()); |
| 278 &ThemeService::GetThemeProviderForProfile(browser_->profile()); | 236 foregroundColor = theme ? theme->GetNSColor(ThemeProperties::COLOR_TAB_TEXT) |
| 279 foregroundColor = theme ? theme->GetNSColor(ThemeProperties::COLOR_TAB_TEXT) | |
| 280 : [NSColor blackColor]; | |
| 281 } else { | |
| 282 foregroundColor = browser_->profile()->IsGuestSession() | |
| 283 ? [NSColor colorWithCalibratedWhite:1.0 alpha:0.9] | |
| 284 : [NSColor blackColor]; | 237 : [NSColor blackColor]; |
| 285 } | |
| 286 | 238 |
| 287 ProfileAttributesStorage& storage = | 239 ProfileAttributesStorage& storage = |
| 288 g_browser_process->profile_manager()->GetProfileAttributesStorage(); | 240 g_browser_process->profile_manager()->GetProfileAttributesStorage(); |
| 289 // If there is a single local profile, then use the generic avatar button | 241 // If there is a single local profile, then use the generic avatar button |
| 290 // instead of the profile name. Never use the generic button if the active | 242 // instead of the profile name. Never use the generic button if the active |
| 291 // profile is Guest. | 243 // profile is Guest. |
| 292 bool useGenericButton = | 244 bool useGenericButton = |
| 293 !browser_->profile()->IsGuestSession() && | 245 !browser_->profile()->IsGuestSession() && |
| 294 storage.GetNumberOfProfiles() == 1 && | 246 storage.GetNumberOfProfiles() == 1 && |
| 295 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); | 247 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); |
| 296 | 248 |
| 297 NSString* buttonTitle = base::SysUTF16ToNSString(useGenericButton ? | 249 NSString* buttonTitle = base::SysUTF16ToNSString(useGenericButton ? |
| 298 base::string16() : | 250 base::string16() : |
| 299 profiles::GetAvatarButtonTextForProfile(browser_->profile())); | 251 profiles::GetAvatarButtonTextForProfile(browser_->profile())); |
| 300 [[button_ cell] setHasError:hasError_ withTitle:buttonTitle]; | 252 [[button_ cell] setHasError:hasError_ withTitle:buttonTitle]; |
| 301 | 253 |
| 302 AvatarButton* button = | 254 AvatarButton* button = |
| 303 base::mac::ObjCCastStrict<AvatarButton>(button_); | 255 base::mac::ObjCCastStrict<AvatarButton>(button_); |
| 304 | 256 |
| 305 if (useGenericButton) { | 257 if (useGenericButton) { |
| 306 if (isMaterial) { | 258 NSImage* avatarIcon = NSImageFromImageSkia(gfx::CreateVectorIcon( |
| 307 NSImage* avatarIcon = NSImageFromImageSkia( | 259 gfx::VectorIconId::USER_ACCOUNT_AVATAR, 18, kMaterialAvatarIconColor)); |
| 308 gfx::CreateVectorIcon(gfx::VectorIconId::USER_ACCOUNT_AVATAR, 18, | 260 [button setDefaultImage:avatarIcon]; |
| 309 kMaterialAvatarIconColor)); | 261 [button setHoverImage:nil]; |
| 310 [button setDefaultImage:avatarIcon]; | 262 [button setPressedImage:nil]; |
| 311 [button setHoverImage:nil]; | |
| 312 [button setPressedImage:nil]; | |
| 313 } else { | |
| 314 [button setDefaultImage:GetImageFromResourceID( | |
| 315 IDR_AVATAR_NATIVE_BUTTON_AVATAR)]; | |
| 316 [button setHoverImage:GetImageFromResourceID( | |
| 317 IDR_AVATAR_NATIVE_BUTTON_AVATAR_HOVER)]; | |
| 318 [button setPressedImage:GetImageFromResourceID( | |
| 319 IDR_AVATAR_NATIVE_BUTTON_AVATAR_PRESSED)]; | |
| 320 // This is a workaround for an issue in the HoverImageButton where the | |
| 321 // button is initially sized incorrectly unless a default image is | |
| 322 // provided. | |
| 323 // See crbug.com/298501. | |
| 324 [button setImage:GetImageFromResourceID(IDR_AVATAR_NATIVE_BUTTON_AVATAR)]; | |
| 325 } | |
| 326 [button setImagePosition:NSImageOnly]; | 263 [button setImagePosition:NSImageOnly]; |
| 327 } else if (hasError_) { | 264 } else if (hasError_) { |
| 328 NSImage* errorIcon = | 265 NSImage* errorIcon = NSImageFromImageSkia(gfx::CreateVectorIcon( |
| 329 isMaterial | 266 gfx::VectorIconId::SYNC_PROBLEM, 16, gfx::kGoogleRed700)); |
| 330 ? NSImageFromImageSkia(gfx::CreateVectorIcon( | |
| 331 gfx::VectorIconId::SYNC_PROBLEM, 16, gfx::kGoogleRed700)) | |
| 332 : GetImageFromResourceID(IDR_ICON_PROFILES_AVATAR_BUTTON_ERROR); | |
| 333 [button setDefaultImage:errorIcon]; | 267 [button setDefaultImage:errorIcon]; |
| 334 [button setHoverImage:nil]; | 268 [button setHoverImage:nil]; |
| 335 [button setPressedImage:nil]; | 269 [button setPressedImage:nil]; |
| 336 [button setImage:errorIcon]; | 270 [button setImage:errorIcon]; |
| 337 [button setImagePosition:isMaterial ? NSImageLeft : NSImageRight]; | 271 [button setImagePosition:NSImageLeft]; |
| 338 } else { | 272 } else { |
| 339 [button setDefaultImage:nil]; | 273 [button setDefaultImage:nil]; |
| 340 [button setHoverImage:nil]; | 274 [button setHoverImage:nil]; |
| 341 [button setPressedImage:nil]; | 275 [button setPressedImage:nil]; |
| 342 [button setImagePosition:NSNoImage]; | 276 [button setImagePosition:NSNoImage]; |
| 343 } | 277 } |
| 344 | 278 |
| 345 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( | 279 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( |
| 346 [[NSMutableParagraphStyle alloc] init]); | 280 [[NSMutableParagraphStyle alloc] init]); |
| 347 [paragraphStyle setAlignment:NSLeftTextAlignment]; | 281 [paragraphStyle setAlignment:NSLeftTextAlignment]; |
| 348 | 282 |
| 349 if (isMaterial) { | 283 base::scoped_nsobject<NSAttributedString> attributedTitle([ |
| 350 base::scoped_nsobject<NSAttributedString> attributedTitle( | 284 [NSAttributedString alloc] |
| 351 [[NSAttributedString alloc] | 285 initWithString:buttonTitle |
| 352 initWithString:buttonTitle | 286 attributes:@{ |
| 353 attributes:@{ | 287 NSForegroundColorAttributeName : foregroundColor, |
| 354 NSForegroundColorAttributeName : foregroundColor, | 288 NSParagraphStyleAttributeName : paragraphStyle, |
| 355 NSParagraphStyleAttributeName : paragraphStyle, | 289 NSKernAttributeName : [NSNumber numberWithFloat:kMaterialTitleKern] |
| 356 NSKernAttributeName : | 290 }]); |
| 357 [NSNumber numberWithFloat:kMaterialTitleKern] | 291 [button_ setAttributedTitle:attributedTitle]; |
| 358 }]); | |
| 359 [button_ setAttributedTitle:attributedTitle]; | |
| 360 } else { | |
| 361 // Create the white drop shadow. | |
| 362 base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); | |
| 363 [shadow setShadowOffset:NSMakeSize(0, -1)]; | |
| 364 [shadow setShadowBlurRadius:0]; | |
| 365 if (browser_->profile()->IsGuestSession()) | |
| 366 [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.4]]; | |
| 367 else if (!isThemedWindow_) | |
| 368 [shadow setShadowColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.7]]; | |
| 369 else | |
| 370 [shadow setShadowColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.4]]; | |
| 371 | |
| 372 base::scoped_nsobject<NSAttributedString> attributedTitle( | |
| 373 [[NSAttributedString alloc] | |
| 374 initWithString:buttonTitle | |
| 375 attributes:@{ | |
| 376 NSShadowAttributeName : shadow.get(), | |
| 377 NSForegroundColorAttributeName : foregroundColor, | |
| 378 NSParagraphStyleAttributeName : paragraphStyle | |
| 379 }]); | |
| 380 [button_ setAttributedTitle:attributedTitle]; | |
| 381 } | |
| 382 [button_ sizeToFit]; | 292 [button_ sizeToFit]; |
| 383 | 293 |
| 384 if (layoutParent) { | 294 if (layoutParent) { |
| 385 // Because the width of the button might have changed, the parent browser | 295 // Because the width of the button might have changed, the parent browser |
| 386 // frame needs to recalculate the button bounds and redraw it. | 296 // frame needs to recalculate the button bounds and redraw it. |
| 387 [[BrowserWindowController | 297 [[BrowserWindowController |
| 388 browserWindowControllerForWindow:browser_->window()->GetNativeWindow()] | 298 browserWindowControllerForWindow:browser_->window()->GetNativeWindow()] |
| 389 layoutSubviews]; | 299 layoutSubviews]; |
| 390 } | 300 } |
| 391 } | 301 } |
| 392 | 302 |
| 393 - (void)setErrorStatus:(BOOL)hasError { | 303 - (void)setErrorStatus:(BOOL)hasError { |
| 394 hasError_ = hasError; | 304 hasError_ = hasError; |
| 395 [self updateAvatarButtonAndLayoutParent:YES]; | 305 [self updateAvatarButtonAndLayoutParent:YES]; |
| 396 } | 306 } |
| 397 | 307 |
| 398 @end | 308 @end |
| OLD | NEW |