Chromium Code Reviews| 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_icon_controller.h" | 5 #import "chrome/browser/ui/cocoa/profiles/avatar_icon_controller.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| 11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/profiles/profile_avatar_icon_util.h" | 13 #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
| 14 #include "chrome/browser/profiles/profile_info_cache.h" | 14 #include "chrome/browser/profiles/profile_info_cache.h" |
| 15 #include "chrome/browser/profiles/profile_manager.h" | 15 #include "chrome/browser/profiles/profile_manager.h" |
| 16 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/browser_window.h" | |
| 18 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | |
| 19 #import "chrome/browser/ui/cocoa/profiles/avatar_label_button.h" | |
| 20 #include "chrome/grit/generated_resources.h" | 17 #include "chrome/grit/generated_resources.h" |
| 21 #include "grit/theme_resources.h" | 18 #include "grit/theme_resources.h" |
| 22 #include "ui/base/l10n/l10n_util_mac.h" | 19 #include "ui/base/l10n/l10n_util_mac.h" |
| 23 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
| 24 #include "ui/gfx/image/image.h" | 21 #include "ui/gfx/image/image.h" |
| 25 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | 22 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
| 26 | 23 |
| 27 namespace { | |
| 28 | |
| 29 // Space between the avatar label and the left edge of the container containing | |
| 30 // the label and the icon. | |
| 31 const CGFloat kAvatarSpacing = 4; | |
| 32 | |
| 33 // Space between the bottom of the avatar icon and the bottom of the avatar | |
| 34 // label. | |
| 35 const CGFloat kAvatarLabelBottomSpacing = 3; | |
| 36 | |
| 37 // Space between the right edge of the avatar label and the right edge of the | |
| 38 // avatar icon. | |
| 39 const CGFloat kAvatarLabelRightSpacing = 2; | |
| 40 | |
| 41 } // namespace | |
| 42 | |
| 43 @interface AvatarIconController (Private) | 24 @interface AvatarIconController (Private) |
| 44 - (void)setButtonEnabled:(BOOL)flag; | 25 - (void)setButtonEnabled:(BOOL)flag; |
| 45 - (NSImage*)compositeImageWithShadow:(NSImage*)image; | 26 - (NSImage*)compositeImageWithShadow:(NSImage*)image; |
| 46 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent; | |
| 47 - (void)addOrRemoveButtonIfNecessary; | |
| 48 @end | |
| 49 | |
| 50 // Declare a 10.7+ private API. | |
| 51 // NSThemeFrame < NSTitledFrame < NSFrameView < NSView. | |
| 52 @interface NSView (NSThemeFrame) | |
| 53 - (void)_tileTitlebarAndRedisplay:(BOOL)redisplay; | |
| 54 @end | 27 @end |
| 55 | 28 |
| 56 @implementation AvatarIconController | 29 @implementation AvatarIconController |
| 57 | 30 |
| 58 - (id)initWithBrowser:(Browser*)browser { | 31 - (id)initWithBrowser:(Browser*)browser { |
| 59 if ((self = [super initWithBrowser:browser])) { | 32 if ((self = [super initWithBrowser:browser])) { |
| 60 browser_ = browser; | 33 browser_ = browser; |
| 61 | 34 |
| 62 base::scoped_nsobject<NSView> container( | 35 base::scoped_nsobject<NSView> container( |
| 63 [[NSView alloc] initWithFrame:NSMakeRect( | 36 [[NSView alloc] initWithFrame:NSMakeRect( |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 93 [cell accessibilitySetOverrideValue: | 66 [cell accessibilitySetOverrideValue: |
| 94 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_NAME) | 67 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_NAME) |
| 95 forAttribute:NSAccessibilityTitleAttribute]; | 68 forAttribute:NSAccessibilityTitleAttribute]; |
| 96 [cell accessibilitySetOverrideValue: | 69 [cell accessibilitySetOverrideValue: |
| 97 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) | 70 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) |
| 98 forAttribute:NSAccessibilityHelpAttribute]; | 71 forAttribute:NSAccessibilityHelpAttribute]; |
| 99 [cell accessibilitySetOverrideValue: | 72 [cell accessibilitySetOverrideValue: |
| 100 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) | 73 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) |
| 101 forAttribute:NSAccessibilityDescriptionAttribute]; | 74 forAttribute:NSAccessibilityDescriptionAttribute]; |
| 102 | 75 |
| 103 Profile* profile = browser_->profile(); | 76 NSImage* icon = ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| 77 IDR_OTR_ICON).ToNSImage(); | |
| 78 [button_ setImage:[self compositeImageWithShadow:icon]]; | |
| 79 [button_ setEnabled:NO]; | |
| 104 | 80 |
| 105 if (profile->IsOffTheRecord() || profile->IsGuestSession()) { | |
| 106 const int icon_id = profile->IsGuestSession() ? | |
| 107 profiles::GetPlaceholderAvatarIconResourceID() : IDR_OTR_ICON; | |
| 108 NSImage* icon = ResourceBundle::GetSharedInstance().GetNativeImageNamed( | |
| 109 icon_id).ToNSImage(); | |
| 110 [self setImage:[self compositeImageWithShadow:icon]]; | |
| 111 [self setButtonEnabled:profile->IsGuestSession()]; | |
| 112 } else { | |
| 113 [self setButtonEnabled:YES]; | |
| 114 [self updateAvatarButtonAndLayoutParent:NO]; | |
| 115 | |
| 116 // Supervised users cannot enter incognito mode, so we only need to check | |
| 117 // it in this code path. | |
| 118 if (profile->IsSupervised()) { | |
| 119 // Initialize the avatar label button. | |
| 120 CGFloat extraWidth = | |
| 121 profiles::kAvatarIconWidth + kAvatarLabelRightSpacing; | |
| 122 NSRect frame = NSMakeRect( | |
| 123 kAvatarSpacing, kAvatarLabelBottomSpacing, extraWidth, 0); | |
| 124 labelButton_.reset([[AvatarLabelButton alloc] initWithFrame:frame]); | |
| 125 [labelButton_ setTarget:self]; | |
| 126 [labelButton_ setAction:@selector(buttonClicked:)]; | |
| 127 [[self view] addSubview:labelButton_]; | |
| 128 | |
| 129 // Resize the container and reposition the avatar button. | |
| 130 NSSize textSize = [[labelButton_ cell] labelTextSize]; | |
| 131 [container setFrameSize: | |
| 132 NSMakeSize([labelButton_ frame].size.width + kAvatarSpacing, | |
| 133 profiles::kAvatarIconHeight)]; | |
| 134 [button_ | |
| 135 setFrameOrigin:NSMakePoint(kAvatarSpacing + textSize.width, 0)]; | |
| 136 } | |
| 137 } | |
| 138 [[self view] addSubview:button_]; | 81 [[self view] addSubview:button_]; |
| 139 } | 82 } |
| 140 return self; | 83 return self; |
| 141 } | 84 } |
| 142 | 85 |
| 143 - (NSButton*)labelButtonView { | |
| 144 return labelButton_.get(); | |
| 145 } | |
| 146 | |
| 147 - (void)setImage:(NSImage*)image { | |
| 148 [button_ setImage:image]; | |
| 149 } | |
| 150 | |
| 151 - (void)setButtonEnabled:(BOOL)flag { | |
| 152 [button_ setEnabled:flag]; | |
| 153 } | |
| 154 | |
| 155 // This will take in an original image and redraw it with a shadow. | 86 // This will take in an original image and redraw it with a shadow. |
| 156 - (NSImage*)compositeImageWithShadow:(NSImage*)image { | 87 - (NSImage*)compositeImageWithShadow:(NSImage*)image { |
| 157 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | 88 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
| 158 | 89 |
| 159 base::scoped_nsobject<NSImage> destination( | 90 base::scoped_nsobject<NSImage> destination( |
| 160 [[NSImage alloc] initWithSize:[image size]]); | 91 [[NSImage alloc] initWithSize:[image size]]); |
| 161 | 92 |
| 162 NSRect destRect = NSZeroRect; | 93 NSRect destRect = NSZeroRect; |
| 163 destRect.size = [destination size]; | 94 destRect.size = [destination size]; |
| 164 | 95 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 176 operation:NSCompositeSourceOver | 107 operation:NSCompositeSourceOver |
| 177 fraction:1.0 | 108 fraction:1.0 |
| 178 respectFlipped:YES | 109 respectFlipped:YES |
| 179 hints:nil]; | 110 hints:nil]; |
| 180 | 111 |
| 181 [destination unlockFocus]; | 112 [destination unlockFocus]; |
| 182 | 113 |
| 183 return destination.autorelease(); | 114 return destination.autorelease(); |
| 184 } | 115 } |
| 185 | 116 |
| 186 // Updates the avatar information from the profile cache. | |
| 187 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent { | |
|
Robert Sesek
2016/01/26 18:37:56
Can this be removed safely? AvatarBaseController i
Marc Treib
2016/01/27 14:06:54
Good catch! I've added back an empty implementatio
| |
| 188 // No updates are needed for an incognito or guest window, as the avatar | |
| 189 // is always fixed. | |
| 190 Profile* profile = browser_->profile(); | |
| 191 if (profile->IsOffTheRecord() || profile->IsGuestSession()) | |
| 192 return; | |
| 193 | |
| 194 ProfileInfoCache& cache = | |
| 195 g_browser_process->profile_manager()->GetProfileInfoCache(); | |
| 196 size_t index = | |
| 197 cache.GetIndexOfProfileWithPath(browser_->profile()->GetPath()); | |
| 198 if (index == std::string::npos) | |
| 199 return; | |
| 200 | |
| 201 BOOL is_gaia_picture = | |
| 202 cache.IsUsingGAIAPictureOfProfileAtIndex(index) && | |
| 203 cache.GetGAIAPictureOfProfileAtIndex(index); | |
| 204 gfx::Image icon = profiles::GetAvatarIconForTitleBar( | |
| 205 cache.GetAvatarIconOfProfileAtIndex(index), is_gaia_picture, | |
| 206 profiles::kAvatarIconWidth, profiles::kAvatarIconHeight); | |
| 207 [self setImage:icon.ToNSImage()]; | |
| 208 | |
| 209 const base::string16& name = cache.GetNameOfProfileAtIndex(index); | |
| 210 NSString* nsName = base::SysUTF16ToNSString(name); | |
| 211 [button_ setToolTip:nsName]; | |
| 212 [[button_ cell] | |
| 213 accessibilitySetOverrideValue:nsName | |
| 214 forAttribute:NSAccessibilityValueAttribute]; | |
| 215 if (layoutParent) | |
| 216 [self addOrRemoveButtonIfNecessary]; | |
| 217 } | |
| 218 | |
| 219 // If the second-to-last profile was removed or a second profile was added, | |
| 220 // show or hide the avatar button from the window frame. | |
| 221 - (void)addOrRemoveButtonIfNecessary { | |
| 222 if (browser_->profile()->IsOffTheRecord()) | |
| 223 return; | |
| 224 | |
| 225 BrowserWindowController* wc = base::mac::ObjCCast<BrowserWindowController>( | |
| 226 [browser_->window()->GetNativeWindow() windowController]); | |
| 227 if (!wc) | |
| 228 return; | |
| 229 | |
| 230 [self.view setHidden:![wc shouldShowAvatar]]; | |
| 231 | |
| 232 // If the avatar is being added or removed, then the Lion fullscreen button | |
| 233 // needs to be adjusted. Since the fullscreen button is positioned by | |
| 234 // FramedBrowserWindow using private APIs, the easiest way to update the | |
| 235 // position of the button is through this private API. Resizing the window | |
| 236 // also works, but invoking |-display| does not. | |
| 237 NSView* themeFrame = [[[wc window] contentView] superview]; | |
| 238 if ([themeFrame respondsToSelector:@selector(_tileTitlebarAndRedisplay:)]) | |
| 239 [themeFrame _tileTitlebarAndRedisplay:YES]; | |
| 240 | |
| 241 // This needs to be called after the fullscreen button is positioned, because | |
| 242 // TabStripController's rightIndentForControls depends on it. | |
| 243 [wc layoutSubviews]; | |
| 244 } | |
| 245 | |
| 246 @end | 117 @end |
| OLD | NEW |