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; | 27 - (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 | 28 @end |
55 | 29 |
56 @implementation AvatarIconController | 30 @implementation AvatarIconController |
57 | 31 |
58 - (id)initWithBrowser:(Browser*)browser { | 32 - (id)initWithBrowser:(Browser*)browser { |
59 if ((self = [super initWithBrowser:browser])) { | 33 if ((self = [super initWithBrowser:browser])) { |
60 browser_ = browser; | 34 browser_ = browser; |
61 | 35 |
62 base::scoped_nsobject<NSView> container( | 36 base::scoped_nsobject<NSView> container( |
63 [[NSView alloc] initWithFrame:NSMakeRect( | 37 [[NSView alloc] initWithFrame:NSMakeRect( |
(...skipping 29 matching lines...) Expand all Loading... |
93 [cell accessibilitySetOverrideValue: | 67 [cell accessibilitySetOverrideValue: |
94 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_NAME) | 68 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_NAME) |
95 forAttribute:NSAccessibilityTitleAttribute]; | 69 forAttribute:NSAccessibilityTitleAttribute]; |
96 [cell accessibilitySetOverrideValue: | 70 [cell accessibilitySetOverrideValue: |
97 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) | 71 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) |
98 forAttribute:NSAccessibilityHelpAttribute]; | 72 forAttribute:NSAccessibilityHelpAttribute]; |
99 [cell accessibilitySetOverrideValue: | 73 [cell accessibilitySetOverrideValue: |
100 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) | 74 l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION) |
101 forAttribute:NSAccessibilityDescriptionAttribute]; | 75 forAttribute:NSAccessibilityDescriptionAttribute]; |
102 | 76 |
103 Profile* profile = browser_->profile(); | 77 NSImage* icon = ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| 78 IDR_OTR_ICON).ToNSImage(); |
| 79 [button_ setImage:[self compositeImageWithShadow:icon]]; |
| 80 [button_ setEnabled:NO]; |
104 | 81 |
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_]; | 82 [[self view] addSubview:button_]; |
139 } | 83 } |
140 return self; | 84 return self; |
141 } | 85 } |
142 | 86 |
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. | 87 // This will take in an original image and redraw it with a shadow. |
156 - (NSImage*)compositeImageWithShadow:(NSImage*)image { | 88 - (NSImage*)compositeImageWithShadow:(NSImage*)image { |
157 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | 89 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
158 | 90 |
159 base::scoped_nsobject<NSImage> destination( | 91 base::scoped_nsobject<NSImage> destination( |
160 [[NSImage alloc] initWithSize:[image size]]); | 92 [[NSImage alloc] initWithSize:[image size]]); |
161 | 93 |
162 NSRect destRect = NSZeroRect; | 94 NSRect destRect = NSZeroRect; |
163 destRect.size = [destination size]; | 95 destRect.size = [destination size]; |
164 | 96 |
(...skipping 11 matching lines...) Expand all Loading... |
176 operation:NSCompositeSourceOver | 108 operation:NSCompositeSourceOver |
177 fraction:1.0 | 109 fraction:1.0 |
178 respectFlipped:YES | 110 respectFlipped:YES |
179 hints:nil]; | 111 hints:nil]; |
180 | 112 |
181 [destination unlockFocus]; | 113 [destination unlockFocus]; |
182 | 114 |
183 return destination.autorelease(); | 115 return destination.autorelease(); |
184 } | 116 } |
185 | 117 |
186 // Updates the avatar information from the profile cache. | 118 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent {} |
187 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent { | |
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 | 119 |
246 @end | 120 @end |
OLD | NEW |