Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: ash/system/user/tray_user.cc

Issue 210903003: Implemented system tray UI for new account management. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More comments addressed. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "ash/system/user/tray_user.h" 5 #include "ash/system/user/tray_user.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <climits> 8 #include <climits>
9 #include <vector> 9 #include <vector>
10 10
11 #include "ash/ash_switches.h" 11 #include "ash/ash_switches.h"
12 #include "ash/metrics/user_metrics_recorder.h" 12 #include "ash/metrics/user_metrics_recorder.h"
13 #include "ash/multi_profile_uma.h" 13 #include "ash/multi_profile_uma.h"
14 #include "ash/popup_message.h" 14 #include "ash/popup_message.h"
15 #include "ash/root_window_controller.h" 15 #include "ash/root_window_controller.h"
16 #include "ash/session_state_delegate.h" 16 #include "ash/session_state_delegate.h"
17 #include "ash/shelf/shelf_layout_manager.h" 17 #include "ash/shelf/shelf_layout_manager.h"
18 #include "ash/shell.h" 18 #include "ash/shell.h"
19 #include "ash/shell_delegate.h" 19 #include "ash/shell_delegate.h"
20 #include "ash/system/tray/fixed_sized_scroll_view.h"
21 #include "ash/system/tray/hover_highlight_view.h"
20 #include "ash/system/tray/system_tray.h" 22 #include "ash/system/tray/system_tray.h"
21 #include "ash/system/tray/system_tray_delegate.h" 23 #include "ash/system/tray/system_tray_delegate.h"
22 #include "ash/system/tray/system_tray_notifier.h" 24 #include "ash/system/tray/system_tray_notifier.h"
23 #include "ash/system/tray/tray_constants.h" 25 #include "ash/system/tray/tray_constants.h"
26 #include "ash/system/tray/tray_details_view.h"
24 #include "ash/system/tray/tray_item_view.h" 27 #include "ash/system/tray/tray_item_view.h"
28 #include "ash/system/tray/tray_popup_header_button.h"
25 #include "ash/system/tray/tray_popup_label_button.h" 29 #include "ash/system/tray/tray_popup_label_button.h"
26 #include "ash/system/tray/tray_popup_label_button_border.h" 30 #include "ash/system/tray/tray_popup_label_button_border.h"
27 #include "ash/system/tray/tray_utils.h" 31 #include "ash/system/tray/tray_utils.h"
32 #include "ash/system/tray/view_click_listener.h"
33 #include "ash/system/user/user_accounts_delegate.h"
28 #include "base/i18n/rtl.h" 34 #include "base/i18n/rtl.h"
29 #include "base/logging.h" 35 #include "base/logging.h"
30 #include "base/memory/scoped_vector.h" 36 #include "base/memory/scoped_vector.h"
31 #include "base/strings/string16.h" 37 #include "base/strings/string16.h"
32 #include "base/strings/string_util.h" 38 #include "base/strings/string_util.h"
33 #include "base/strings/utf_string_conversions.h" 39 #include "base/strings/utf_string_conversions.h"
34 #include "grit/ash_resources.h" 40 #include "grit/ash_resources.h"
35 #include "grit/ash_strings.h" 41 #include "grit/ash_strings.h"
42 #include "grit/ui_resources.h"
36 #include "skia/ext/image_operations.h" 43 #include "skia/ext/image_operations.h"
37 #include "third_party/skia/include/core/SkCanvas.h" 44 #include "third_party/skia/include/core/SkCanvas.h"
38 #include "third_party/skia/include/core/SkPaint.h" 45 #include "third_party/skia/include/core/SkPaint.h"
39 #include "third_party/skia/include/core/SkPath.h" 46 #include "third_party/skia/include/core/SkPath.h"
40 #include "ui/aura/window.h" 47 #include "ui/aura/window.h"
41 #include "ui/base/l10n/l10n_util.h" 48 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/base/resource/resource_bundle.h" 49 #include "ui/base/resource/resource_bundle.h"
43 #include "ui/gfx/canvas.h" 50 #include "ui/gfx/canvas.h"
44 #include "ui/gfx/font_list.h" 51 #include "ui/gfx/font_list.h"
45 #include "ui/gfx/image/image.h" 52 #include "ui/gfx/image/image.h"
46 #include "ui/gfx/image/image_skia_operations.h" 53 #include "ui/gfx/image/image_skia_operations.h"
47 #include "ui/gfx/insets.h" 54 #include "ui/gfx/insets.h"
48 #include "ui/gfx/range/range.h" 55 #include "ui/gfx/range/range.h"
49 #include "ui/gfx/rect.h" 56 #include "ui/gfx/rect.h"
50 #include "ui/gfx/render_text.h" 57 #include "ui/gfx/render_text.h"
51 #include "ui/gfx/size.h" 58 #include "ui/gfx/size.h"
52 #include "ui/gfx/skia_util.h" 59 #include "ui/gfx/skia_util.h"
53 #include "ui/gfx/text_elider.h" 60 #include "ui/gfx/text_elider.h"
54 #include "ui/gfx/text_utils.h" 61 #include "ui/gfx/text_utils.h"
55 #include "ui/views/border.h" 62 #include "ui/views/border.h"
56 #include "ui/views/bubble/tray_bubble_view.h" 63 #include "ui/views/bubble/tray_bubble_view.h"
57 #include "ui/views/controls/button/button.h" 64 #include "ui/views/controls/button/button.h"
58 #include "ui/views/controls/button/custom_button.h" 65 #include "ui/views/controls/button/custom_button.h"
66 #include "ui/views/controls/button/image_button.h"
59 #include "ui/views/controls/image_view.h" 67 #include "ui/views/controls/image_view.h"
60 #include "ui/views/controls/label.h" 68 #include "ui/views/controls/label.h"
61 #include "ui/views/controls/link.h" 69 #include "ui/views/controls/link.h"
62 #include "ui/views/controls/link_listener.h" 70 #include "ui/views/controls/link_listener.h"
63 #include "ui/views/layout/box_layout.h" 71 #include "ui/views/layout/box_layout.h"
64 #include "ui/views/layout/fill_layout.h" 72 #include "ui/views/layout/fill_layout.h"
73 #include "ui/views/layout/grid_layout.h"
65 #include "ui/views/mouse_watcher.h" 74 #include "ui/views/mouse_watcher.h"
66 #include "ui/views/painter.h" 75 #include "ui/views/painter.h"
67 #include "ui/views/view.h" 76 #include "ui/views/view.h"
68 #include "ui/views/widget/widget.h" 77 #include "ui/views/widget/widget.h"
69 #include "ui/wm/core/shadow_types.h" 78 #include "ui/wm/core/shadow_types.h"
70 79
71 namespace { 80 namespace {
72 81
73 const int kUserDetailsVerticalPadding = 5; 82 const int kUserDetailsVerticalPadding = 5;
74 const int kUserCardVerticalPadding = 10; 83 const int kUserCardVerticalPadding = 10;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 delegate->SwitchActiveUser(delegate->GetUserID(user_index)); 140 delegate->SwitchActiveUser(delegate->GetUserID(user_index));
132 } 141 }
133 142
134 } // namespace 143 } // namespace
135 144
136 namespace ash { 145 namespace ash {
137 namespace internal { 146 namespace internal {
138 147
139 namespace tray { 148 namespace tray {
140 149
150 // Returns true when multi profile is supported.
151 bool IsMultiProfileSupportedAndUserActive() {
152 // We do not want to see any multi profile additions to a user view when the
153 // log in screen is shown.
154 return Shell::GetInstance()->delegate()->IsMultiProfilesEnabled() &&
155 !Shell::GetInstance()
156 ->session_state_delegate()
157 ->IsUserSessionBlocked();
158 }
159
160 // Returns true if account management is supported.
161 bool IsAccountManagementSupportedAndUserActive() {
162 return Shell::GetInstance()->delegate()->IsAccountManagementEnabled() &&
163 !Shell::GetInstance()
164 ->session_state_delegate()
165 ->IsUserSessionBlocked();
166 }
167
168 bool IsUserSessionBlocked() {
Mr4D (OOO till 08-26) 2014/03/30 23:38:26 Please add a comment here as well (e.g. Returns tr
oshima 2014/03/31 23:07:52 Also move this to the 1st place and let other util
dzhioev (left Google) 2014/04/01 17:25:02 Done.
dzhioev (left Google) 2014/04/01 17:25:02 Done.
169 return !Shell::GetInstance()
170 ->session_state_delegate()
171 ->IsUserSessionBlocked();
172 }
173
141 // A custom image view with rounded edges. 174 // A custom image view with rounded edges.
142 class RoundedImageView : public views::View { 175 class RoundedImageView : public views::View {
143 public: 176 public:
144 // Constructs a new rounded image view with rounded corners of radius 177 // Constructs a new rounded image view with rounded corners of radius
145 // |corner_radius|. If |active_user| is set, the icon will be drawn in 178 // |corner_radius|. If |active_user| is set, the icon will be drawn in
146 // full colors - otherwise it will fade into the background. 179 // full colors - otherwise it will fade into the background.
147 RoundedImageView(int corner_radius, bool active_user); 180 RoundedImageView(int corner_radius, bool active_user);
148 virtual ~RoundedImageView(); 181 virtual ~RoundedImageView();
149 182
150 // Set the image that should be displayed. The image contents is copied to the 183 // Set the image that should be displayed. The image contents is copied to the
(...skipping 22 matching lines...) Expand all
173 206
174 DISALLOW_COPY_AND_ASSIGN(RoundedImageView); 207 DISALLOW_COPY_AND_ASSIGN(RoundedImageView);
175 }; 208 };
176 209
177 // The user details shown in public account mode. This is essentially a label 210 // The user details shown in public account mode. This is essentially a label
178 // but with custom painting code as the text is styled with multiple colors and 211 // but with custom painting code as the text is styled with multiple colors and
179 // contains a link. 212 // contains a link.
180 class PublicAccountUserDetails : public views::View, 213 class PublicAccountUserDetails : public views::View,
181 public views::LinkListener { 214 public views::LinkListener {
182 public: 215 public:
183 PublicAccountUserDetails(SystemTrayItem* owner, int used_width); 216 PublicAccountUserDetails(int max_width);
184 virtual ~PublicAccountUserDetails(); 217 virtual ~PublicAccountUserDetails();
185 218
186 private: 219 private:
187 // Overridden from views::View. 220 // Overridden from views::View.
188 virtual void Layout() OVERRIDE; 221 virtual void Layout() OVERRIDE;
189 virtual gfx::Size GetPreferredSize() OVERRIDE; 222 virtual gfx::Size GetPreferredSize() OVERRIDE;
190 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 223 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
191 224
192 // Overridden from views::LinkListener. 225 // Overridden from views::LinkListener.
193 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 226 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
194 227
195 // Calculate a preferred size that ensures the label text and the following 228 // Calculate a preferred size that ensures the label text and the following
196 // link do not wrap over more than three lines in total for aesthetic reasons 229 // link do not wrap over more than three lines in total for aesthetic reasons
197 // if possible. 230 // if possible.
198 void CalculatePreferredSize(SystemTrayItem* owner, int used_width); 231 void CalculatePreferredSize(int max_allowed_width);
199 232
200 base::string16 text_; 233 base::string16 text_;
201 views::Link* learn_more_; 234 views::Link* learn_more_;
202 gfx::Size preferred_size_; 235 gfx::Size preferred_size_;
203 ScopedVector<gfx::RenderText> lines_; 236 ScopedVector<gfx::RenderText> lines_;
204 237
205 DISALLOW_COPY_AND_ASSIGN(PublicAccountUserDetails); 238 DISALLOW_COPY_AND_ASSIGN(PublicAccountUserDetails);
206 }; 239 };
207 240
208 // The button which holds the user card in case of multi profile. 241 // This view is used to wrap it's content and transform it into button.
209 class UserCard : public views::CustomButton { 242 class ButtonFromView : public views::CustomButton {
210 public: 243 public:
211 UserCard(views::ButtonListener* listener, bool active_user); 244 ButtonFromView(views::View* content,
212 virtual ~UserCard(); 245 views::ButtonListener* listener,
246 bool highlight_on_hover);
247 virtual ~ButtonFromView();
213 248
214 // Called when the border should remain even in the non highlighted state. 249 // Called when the border should remain even in the non highlighted state.
215 void ForceBorderVisible(bool show); 250 void ForceBorderVisible(bool show);
216 251
217 // Overridden from views::View 252 // Overridden from views::View
218 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; 253 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
219 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; 254 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
220 255
221 // Check if the item is hovered. 256 // Check if the item is hovered.
222 bool is_hovered_for_test() {return button_hovered_; } 257 bool is_hovered_for_test() {return button_hovered_; }
223 258
224 private: 259 private:
225 // Change the hover/active state of the "button" when the status changes. 260 // Change the hover/active state of the "button" when the status changes.
226 void ShowActive(); 261 void ShowActive();
227 262
228 // True if this is the active user. 263 // Content of button.
229 bool is_active_user_; 264 views::View* content_;
265
266 // Whether button should be highligthed on hover.
267 bool highlight_on_hover_;
230 268
231 // True if button is hovered. 269 // True if button is hovered.
232 bool button_hovered_; 270 bool button_hovered_;
233 271
234 // True if the border should be visible. 272 // True if the border should be always visible.
235 bool show_border_; 273 bool show_border_;
236 274
237 DISALLOW_COPY_AND_ASSIGN(UserCard); 275 DISALLOW_COPY_AND_ASSIGN(ButtonFromView);
238 }; 276 };
239 277
240 class UserViewMouseWatcherHost : public views::MouseWatcherHost { 278 class UserViewMouseWatcherHost : public views::MouseWatcherHost {
241 public: 279 public:
242 explicit UserViewMouseWatcherHost(const gfx::Rect& screen_area) 280 explicit UserViewMouseWatcherHost(const gfx::Rect& screen_area)
243 : screen_area_(screen_area) {} 281 : screen_area_(screen_area) {}
244 virtual ~UserViewMouseWatcherHost() {} 282 virtual ~UserViewMouseWatcherHost() {}
245 283
246 // Implementation of MouseWatcherHost. 284 // Implementation of MouseWatcherHost.
247 virtual bool Contains(const gfx::Point& screen_point, 285 virtual bool Contains(const gfx::Point& screen_point,
248 views::MouseWatcherHost::MouseEventType type) OVERRIDE { 286 views::MouseWatcherHost::MouseEventType type) OVERRIDE {
249 return screen_area_.Contains(screen_point); 287 return screen_area_.Contains(screen_point);
250 } 288 }
251 289
252 private: 290 private:
253 gfx::Rect screen_area_; 291 gfx::Rect screen_area_;
254 292
255 DISALLOW_COPY_AND_ASSIGN(UserViewMouseWatcherHost); 293 DISALLOW_COPY_AND_ASSIGN(UserViewMouseWatcherHost);
256 }; 294 };
257 295
258 // The view of a user item. 296 // The view of a user item.
259 class UserView : public views::View, 297 class UserView : public views::View,
260 public views::ButtonListener, 298 public views::ButtonListener,
261 public views::MouseWatcherListener { 299 public views::MouseWatcherListener {
262 public: 300 public:
263 UserView(SystemTrayItem* owner, 301 UserView(SystemTrayItem* owner,
264 ash::user::LoginStatus login, 302 ash::user::LoginStatus login,
265 MultiProfileIndex index); 303 MultiProfileIndex index,
304 bool for_detailed_view);
266 virtual ~UserView(); 305 virtual ~UserView();
267 306
268 // Overridden from MouseWatcherListener: 307 // Overridden from MouseWatcherListener:
269 virtual void MouseMovedOutOfHost() OVERRIDE; 308 virtual void MouseMovedOutOfHost() OVERRIDE;
270 309
271 TrayUser::TestState GetStateForTest() const; 310 TrayUser::TestState GetStateForTest() const;
272 gfx::Rect GetBoundsInScreenOfUserButtonForTest(); 311 gfx::Rect GetBoundsInScreenOfUserButtonForTest();
273 312
274 private: 313 private:
275 // Overridden from views::View. 314 // Overridden from views::View.
276 virtual gfx::Size GetPreferredSize() OVERRIDE; 315 virtual gfx::Size GetPreferredSize() OVERRIDE;
277 virtual int GetHeightForWidth(int width) OVERRIDE; 316 virtual int GetHeightForWidth(int width) OVERRIDE;
278 virtual void Layout() OVERRIDE; 317 virtual void Layout() OVERRIDE;
279 318
280 // Overridden from views::ButtonListener. 319 // Overridden from views::ButtonListener.
281 virtual void ButtonPressed(views::Button* sender, 320 virtual void ButtonPressed(views::Button* sender,
282 const ui::Event& event) OVERRIDE; 321 const ui::Event& event) OVERRIDE;
283 322
284 void AddLogoutButton(user::LoginStatus login); 323 void AddLogoutButton(user::LoginStatus login);
285 void AddUserCard(SystemTrayItem* owner, user::LoginStatus login); 324 void AddUserCard(user::LoginStatus login);
286
287 // Create a user icon representation for the user card.
288 views::View* CreateIconForUserCard(user::LoginStatus login);
289
290 // Create the additional user card content for the retail logged in mode.
291 void AddLoggedInRetailModeUserCardContent();
292
293 // Create the additional user card content for the public mode.
294 void AddLoggedInPublicModeUserCardContent(SystemTrayItem* owner);
295 325
296 // Create the menu option to add another user. If |disabled| is set the user 326 // Create the menu option to add another user. If |disabled| is set the user
297 // cannot actively click on the item. 327 // cannot actively click on the item.
298 void ToggleAddUserMenuOption(); 328 void ToggleAddUserMenuOption();
299 329
300 // Returns true when multi profile is supported.
301 bool SupportsMultiProfile();
302
303 MultiProfileIndex multiprofile_index_; 330 MultiProfileIndex multiprofile_index_;
304 // The view of the user card. 331 // The view of the user card.
305 views::View* user_card_view_; 332 views::View* user_card_view_;
306 333
307 // This is the owner system tray item of this view. 334 // This is the owner system tray item of this view.
308 SystemTrayItem* owner_; 335 SystemTrayItem* owner_;
309 336
310 // True if |user_card_view_| is a |UserView| - otherwise it is only a 337 // True if |user_card_view_| is a |ButtonFromView| - otherwise it is only
311 // |views::View|. 338 // a |UserCardView|.
312 bool is_user_card_; 339 bool is_user_card_button_;
340
313 views::View* logout_button_; 341 views::View* logout_button_;
314 scoped_ptr<PopupMessage> popup_message_; 342 scoped_ptr<PopupMessage> popup_message_;
315 scoped_ptr<views::Widget> add_menu_option_; 343 scoped_ptr<views::Widget> add_menu_option_;
316 344
317 // True when the add user panel is visible but not activatable. 345 // True when the add user panel is visible but not activatable.
318 bool add_user_visible_but_disabled_; 346 bool add_user_disabled_;
347
348 // True if this view will be used inside detailed view.
349 bool for_detailed_view_;
319 350
320 // The mouse watcher which takes care of out of window hover events. 351 // The mouse watcher which takes care of out of window hover events.
321 scoped_ptr<views::MouseWatcher> mouse_watcher_; 352 scoped_ptr<views::MouseWatcher> mouse_watcher_;
322 353
323 DISALLOW_COPY_AND_ASSIGN(UserView); 354 DISALLOW_COPY_AND_ASSIGN(UserView);
324 }; 355 };
325 356
326 // The menu item view which gets shown when the user clicks in multi profile 357 // The menu item view which gets shown when the user clicks in multi profile
327 // mode onto the user item. 358 // mode onto the user item.
328 class AddUserView : public views::CustomButton, 359 class AddUserView : public views::View {
329 public views::ButtonListener {
330 public: 360 public:
331 // The |owner| is the view for which this view gets created. The |listener| 361 // The |owner| is the view for which this view gets created.
332 // will get notified when this item gets clicked. 362 AddUserView(ButtonFromView* owner);
333 AddUserView(UserCard* owner, views::ButtonListener* listener);
334 virtual ~AddUserView(); 363 virtual ~AddUserView();
335 364
336 // Get the anchor view for a message. 365 // Get the anchor view for a message.
337 views::View* anchor() { return anchor_; } 366 views::View* anchor() { return anchor_; }
338 367
339 // Overridden from views::ButtonListener.
340 virtual void ButtonPressed(views::Button* sender,
341 const ui::Event& event) OVERRIDE;
342
343 private: 368 private:
344 // Overridden from views::View. 369 // Overridden from views::View.
345 virtual gfx::Size GetPreferredSize() OVERRIDE; 370 virtual gfx::Size GetPreferredSize() OVERRIDE;
346 virtual int GetHeightForWidth(int width) OVERRIDE;
347 virtual void Layout() OVERRIDE;
348 371
349 // Create the additional client content for this item. 372 // Create the additional client content for this item.
350 void AddContent(); 373 void AddContent();
351 374
352 // This is the content we create and show. 375 // This is the content we create and show.
353 views::View* add_user_; 376 views::View* add_user_;
354 377
355 // This listener will get informed when someone clicks on this button.
356 views::ButtonListener* listener_;
357
358 // This is the owner view of this item. 378 // This is the owner view of this item.
359 UserCard* owner_; 379 ButtonFromView* owner_;
360 380
361 // The anchor view for targetted bubble messages. 381 // The anchor view for targetted bubble messages.
362 views::View* anchor_; 382 views::View* anchor_;
363 383
364 DISALLOW_COPY_AND_ASSIGN(AddUserView); 384 DISALLOW_COPY_AND_ASSIGN(AddUserView);
365 }; 385 };
366 386
387 // The view displaying information about the user, such as user's avatar, email
388 // address, name, and more. View has no borders.
389 class UserCardView : public views::View {
390 public:
391 // |max_width| takes effect only if |login_status| is LOGGED_IN_PUBLIC.
392 UserCardView(user::LoginStatus login_status,
393 int max_width,
394 int multiprofile_index);
oshima 2014/03/31 23:07:52 virtual dtor
dzhioev (left Google) 2014/04/01 17:25:02 Done.
395
396 private:
397 // Creates the content for the retail logged in mode.
398 void AddRetailModeUserContent();
399
400 // Creates the content for the public mode.
401 void AddPublicModeUserContent(int max_width);
402
403 void AddUserContent(user::LoginStatus login_status, int multiprofile_index);
404
405 // Create a user icon representation.
406 views::View* CreateIcon(user::LoginStatus login_status,
407 int multiprofile_index);
408
409 DISALLOW_COPY_AND_ASSIGN(UserCardView);
410 };
411
412 class LogoutButton : public TrayPopupLabelButton {
413 public:
414 LogoutButton(views::ButtonListener* listener,
415 const base::string16& text,
416 bool placeholder)
oshima 2014/03/31 23:07:52 this variable name doesn't match the variable name
dzhioev (left Google) 2014/04/01 17:25:02 Done.
417 : TrayPopupLabelButton(listener, text), placeholder_(placeholder) {
418 SetEnabled(!placeholder_);
419 }
oshima 2014/03/31 23:07:52 virtual dtor
dzhioev (left Google) 2014/04/01 17:25:02 Done.
420
421 private:
422 virtual void Paint(gfx::Canvas* canvas) OVERRIDE {
423 // Just skip paint if this button used as a placeholder.
424 if (!placeholder_)
425 TrayPopupLabelButton::Paint(canvas);
426 }
427
428 bool placeholder_;
429 DISALLOW_COPY_AND_ASSIGN(LogoutButton);
430 };
431
432 // This detailed view appears after a click on the primary user's card when the
433 // new account managment is enabled.
434 class AccountsDetailedView : public TrayDetailsView,
435 public ViewClickListener,
436 public views::ButtonListener,
437 public ash::tray::UserAccountsDelegate::Observer {
438 public:
439 AccountsDetailedView(TrayUser* owner, user::LoginStatus login_status);
440 virtual ~AccountsDetailedView();
441
442 private:
443 static const int kAccountsViewVerticalPadding = 12;
444 static const int kPrimaryAccountColumnSetID = 0;
445 static const int kSecondaryAccountColumnSetID = 1;
446 static const int kPaddingBetweenAccounts = 20;
447
448 // Overridden from ViewClickListener.
449 virtual void OnViewClicked(views::View* sender) OVERRIDE;
450
451 // Overridden from views::ButtonListener.
452 virtual void ButtonPressed(views::Button* sender,
453 const ui::Event& event) OVERRIDE;
454
455 // Overridden from ash::tray::UserAccountsDelegate::Observer.
456 virtual void AccountListChanged() OVERRIDE;
457
458 void AddHeader(user::LoginStatus login_status);
459 void AddAccountList();
460 void AddAddAccountButton();
461 void AddFooter();
462
463 void UpdateAccountList();
464
465 views::View* CreateDeleteButton();
466
467 ash::tray::UserAccountsDelegate* delegate_;
468 views::View* account_list_;
469 views::View* add_account_button_;
470 views::View* add_user_button_;
471 std::map<views::View*, std::string> delete_button_to_account_id_;
472
473 DISALLOW_COPY_AND_ASSIGN(AccountsDetailedView);
474 };
475
367 RoundedImageView::RoundedImageView(int corner_radius, bool active_user) 476 RoundedImageView::RoundedImageView(int corner_radius, bool active_user)
368 : active_user_(active_user) { 477 : active_user_(active_user) {
369 for (int i = 0; i < 4; ++i) 478 for (int i = 0; i < 4; ++i)
370 corner_radius_[i] = corner_radius; 479 corner_radius_[i] = corner_radius;
371 } 480 }
372 481
373 RoundedImageView::~RoundedImageView() {} 482 RoundedImageView::~RoundedImageView() {}
374 483
375 void RoundedImageView::SetImage(const gfx::ImageSkia& img, 484 void RoundedImageView::SetImage(const gfx::ImageSkia& img,
376 const gfx::Size& size) { 485 const gfx::Size& size) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 SkPath path; 528 SkPath path;
420 path.addRoundRect(gfx::RectToSkRect(image_bounds), kRadius); 529 path.addRoundRect(gfx::RectToSkRect(image_bounds), kRadius);
421 SkPaint paint; 530 SkPaint paint;
422 paint.setAntiAlias(true); 531 paint.setAntiAlias(true);
423 paint.setXfermodeMode(active_user_ ? SkXfermode::kSrcOver_Mode : 532 paint.setXfermodeMode(active_user_ ? SkXfermode::kSrcOver_Mode :
424 SkXfermode::kLuminosity_Mode); 533 SkXfermode::kLuminosity_Mode);
425 canvas->DrawImageInPath(resized_, image_bounds.x(), image_bounds.y(), 534 canvas->DrawImageInPath(resized_, image_bounds.x(), image_bounds.y(),
426 path, paint); 535 path, paint);
427 } 536 }
428 537
429 PublicAccountUserDetails::PublicAccountUserDetails(SystemTrayItem* owner, 538 PublicAccountUserDetails::PublicAccountUserDetails(int max_width)
430 int used_width)
431 : learn_more_(NULL) { 539 : learn_more_(NULL) {
432 const int inner_padding = 540 const int inner_padding =
433 kTrayPopupPaddingHorizontal - kTrayPopupPaddingBetweenItems; 541 kTrayPopupPaddingHorizontal - kTrayPopupPaddingBetweenItems;
434 const bool rtl = base::i18n::IsRTL(); 542 const bool rtl = base::i18n::IsRTL();
435 SetBorder(views::Border::CreateEmptyBorder(kUserDetailsVerticalPadding, 543 SetBorder(views::Border::CreateEmptyBorder(kUserDetailsVerticalPadding,
436 rtl ? 0 : inner_padding, 544 rtl ? 0 : inner_padding,
437 kUserDetailsVerticalPadding, 545 kUserDetailsVerticalPadding,
438 rtl ? inner_padding : 0)); 546 rtl ? inner_padding : 0));
439 547
440 // Retrieve the user's display name and wrap it with markers. 548 // Retrieve the user's display name and wrap it with markers.
(...skipping 10 matching lines...) Expand all
451 base::i18n::WrapStringWithLTRFormatting(&domain); 559 base::i18n::WrapStringWithLTRFormatting(&domain);
452 // Retrieve the label text, inserting the display name and domain. 560 // Retrieve the label text, inserting the display name and domain.
453 text_ = l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_PUBLIC_LABEL, 561 text_ = l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_PUBLIC_LABEL,
454 display_name, domain); 562 display_name, domain);
455 563
456 learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE)); 564 learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE));
457 learn_more_->SetUnderline(false); 565 learn_more_->SetUnderline(false);
458 learn_more_->set_listener(this); 566 learn_more_->set_listener(this);
459 AddChildView(learn_more_); 567 AddChildView(learn_more_);
460 568
461 CalculatePreferredSize(owner, used_width); 569 CalculatePreferredSize(max_width);
462 } 570 }
463 571
464 PublicAccountUserDetails::~PublicAccountUserDetails() {} 572 PublicAccountUserDetails::~PublicAccountUserDetails() {}
465 573
466 void PublicAccountUserDetails::Layout() { 574 void PublicAccountUserDetails::Layout() {
467 lines_.clear(); 575 lines_.clear();
468 const gfx::Rect contents_area = GetContentsBounds(); 576 const gfx::Rect contents_area = GetContentsBounds();
469 if (contents_area.IsEmpty()) 577 if (contents_area.IsEmpty())
470 return; 578 return;
471 579
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 } 650 }
543 views::View::OnPaint(canvas); 651 views::View::OnPaint(canvas);
544 } 652 }
545 653
546 void PublicAccountUserDetails::LinkClicked(views::Link* source, 654 void PublicAccountUserDetails::LinkClicked(views::Link* source,
547 int event_flags) { 655 int event_flags) {
548 DCHECK_EQ(source, learn_more_); 656 DCHECK_EQ(source, learn_more_);
549 Shell::GetInstance()->system_tray_delegate()->ShowPublicAccountInfo(); 657 Shell::GetInstance()->system_tray_delegate()->ShowPublicAccountInfo();
550 } 658 }
551 659
552 void PublicAccountUserDetails::CalculatePreferredSize(SystemTrayItem* owner, 660 void PublicAccountUserDetails::CalculatePreferredSize(int max_allowed_width) {
553 int used_width) {
554 const gfx::FontList font_list; 661 const gfx::FontList font_list;
555 const gfx::Size link_size = learn_more_->GetPreferredSize(); 662 const gfx::Size link_size = learn_more_->GetPreferredSize();
556 const int space_width = 663 const int space_width =
557 gfx::GetStringWidth(base::ASCIIToUTF16(" "), font_list); 664 gfx::GetStringWidth(base::ASCIIToUTF16(" "), font_list);
558 const gfx::Insets insets = GetInsets(); 665 const gfx::Insets insets = GetInsets();
559 views::TrayBubbleView* bubble_view = 666 int min_width = link_size.width();
560 owner->system_tray()->GetSystemBubble()->bubble_view();
561 int min_width = std::max(
562 link_size.width(),
563 bubble_view->GetPreferredSize().width() - (used_width + insets.width()));
564 int max_width = std::min( 667 int max_width = std::min(
565 gfx::GetStringWidth(text_, font_list) + space_width + link_size.width(), 668 gfx::GetStringWidth(text_, font_list) + space_width + link_size.width(),
566 bubble_view->GetMaximumSize().width() - (used_width + insets.width())); 669 max_allowed_width - insets.width());
567 // Do a binary search for the minimum width that ensures no more than three 670 // Do a binary search for the minimum width that ensures no more than three
568 // lines are needed. The lower bound is the minimum of the current bubble 671 // lines are needed. The lower bound is the minimum of the current bubble
569 // width and the width of the link (as no wrapping is permitted inside the 672 // width and the width of the link (as no wrapping is permitted inside the
570 // link). The upper bound is the maximum of the largest allowed bubble width 673 // link). The upper bound is the maximum of the largest allowed bubble width
571 // and the sum of the label text and link widths when put on a single line. 674 // and the sum of the label text and link widths when put on a single line.
572 std::vector<base::string16> lines; 675 std::vector<base::string16> lines;
573 while (min_width < max_width) { 676 while (min_width < max_width) {
574 lines.clear(); 677 lines.clear();
575 const int width = (min_width + max_width) / 2; 678 const int width = (min_width + max_width) / 2;
576 const bool too_narrow = 679 const bool too_narrow =
(...skipping 18 matching lines...) Expand all
595 if (min_width - gfx::GetStringWidth(lines.back(), font_list) <= 698 if (min_width - gfx::GetStringWidth(lines.back(), font_list) <=
596 space_width + link_size.width()) { 699 space_width + link_size.width()) {
597 ++line_count; 700 ++line_count;
598 } 701 }
599 const int line_height = font_list.GetHeight(); 702 const int line_height = font_list.GetHeight();
600 const int link_extra_height = std::max( 703 const int link_extra_height = std::max(
601 link_size.height() - learn_more_->GetInsets().top() - line_height, 0); 704 link_size.height() - learn_more_->GetInsets().top() - line_height, 0);
602 preferred_size_ = gfx::Size( 705 preferred_size_ = gfx::Size(
603 min_width + insets.width(), 706 min_width + insets.width(),
604 line_count * line_height + link_extra_height + insets.height()); 707 line_count * line_height + link_extra_height + insets.height());
605
606 bubble_view->SetWidth(preferred_size_.width() + used_width);
607 } 708 }
608 709
609 UserCard::UserCard(views::ButtonListener* listener, bool active_user) 710 ButtonFromView::ButtonFromView(views::View* content,
711 views::ButtonListener* listener,
712 bool highlight_on_hover)
610 : CustomButton(listener), 713 : CustomButton(listener),
611 is_active_user_(active_user), 714 content_(content),
715 highlight_on_hover_(highlight_on_hover),
612 button_hovered_(false), 716 button_hovered_(false),
613 show_border_(false) { 717 show_border_(false) {
614 if (is_active_user_) { 718 set_notify_enter_exit_on_child(true);
615 set_background( 719 SetLayoutManager(
616 views::Background::CreateSolidBackground(kBackgroundColor)); 720 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
617 ShowActive(); 721 AddChildView(content_);
618 } 722 ShowActive();
619 } 723 }
620 724
621 UserCard::~UserCard() {} 725 ButtonFromView::~ButtonFromView() {}
622 726
623 void UserCard::ForceBorderVisible(bool show) { 727 void ButtonFromView::ForceBorderVisible(bool show) {
624 show_border_ = show; 728 show_border_ = show;
625 ShowActive(); 729 ShowActive();
626 } 730 }
627 731
628 void UserCard::OnMouseEntered(const ui::MouseEvent& event) { 732 void ButtonFromView::OnMouseEntered(const ui::MouseEvent& event) {
629 if (is_active_user_) { 733 button_hovered_ = true;
630 button_hovered_ = true; 734 ShowActive();
631 background()->SetNativeControlColor(kHoverBackgroundColor);
632 ShowActive();
633 }
634 } 735 }
635 736
636 void UserCard::OnMouseExited(const ui::MouseEvent& event) { 737 void ButtonFromView::OnMouseExited(const ui::MouseEvent& event) {
637 if (is_active_user_) { 738 button_hovered_ = false;
638 button_hovered_ = false; 739 ShowActive();
639 background()->SetNativeControlColor(kBackgroundColor);
640 ShowActive();
641 }
642 } 740 }
643 741
644 void UserCard::ShowActive() { 742 void ButtonFromView::ShowActive() {
645 int width = button_hovered_ || show_border_ ? 1 : 0; 743 bool border_visible =
646 SetBorder(views::Border::CreateSolidSidedBorder( 744 (button_hovered_ && highlight_on_hover_) || show_border_;
647 width, width, width, 1, kBorderColor)); 745 SkColor border_color = border_visible ? kBorderColor : SK_ColorTRANSPARENT;
746 SetBorder(views::Border::CreateSolidBorder(1, border_color));
747 if (highlight_on_hover_) {
748 SkColor background_color =
749 button_hovered_ ? kHoverBackgroundColor : kBackgroundColor;
750 content_->set_background(
751 views::Background::CreateSolidBackground(background_color));
752 set_background(views::Background::CreateSolidBackground(background_color));
753 }
648 SchedulePaint(); 754 SchedulePaint();
649 } 755 }
650 756
651 UserView::UserView(SystemTrayItem* owner, 757 UserView::UserView(SystemTrayItem* owner,
652 user::LoginStatus login, 758 user::LoginStatus login,
653 MultiProfileIndex index) 759 MultiProfileIndex index,
760 bool for_detailed_view)
654 : multiprofile_index_(index), 761 : multiprofile_index_(index),
655 user_card_view_(NULL), 762 user_card_view_(NULL),
656 owner_(owner), 763 owner_(owner),
657 is_user_card_(false), 764 is_user_card_button_(false),
658 logout_button_(NULL), 765 logout_button_(NULL),
659 add_user_visible_but_disabled_(false) { 766 add_user_disabled_(false),
767 for_detailed_view_(for_detailed_view) {
660 CHECK_NE(user::LOGGED_IN_NONE, login); 768 CHECK_NE(user::LOGGED_IN_NONE, login);
661 if (!index) { 769 if (!index) {
662 // Only the logged in user will have a background. All other users will have 770 // Only the logged in user will have a background. All other users will have
663 // to allow the TrayPopupContainer highlighting the menu line. 771 // to allow the TrayPopupContainer highlighting the menu line.
664 set_background(views::Background::CreateSolidBackground( 772 set_background(views::Background::CreateSolidBackground(
665 login == user::LOGGED_IN_PUBLIC ? kPublicAccountBackgroundColor : 773 login == user::LOGGED_IN_PUBLIC ? kPublicAccountBackgroundColor :
666 kBackgroundColor)); 774 kBackgroundColor));
667 } 775 }
668 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 776 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
669 kTrayPopupPaddingBetweenItems)); 777 kTrayPopupPaddingBetweenItems));
670 // The logout button must be added before the user card so that the user card 778 // The logout button must be added before the user card so that the user card
671 // can correctly calculate the remaining available width. 779 // can correctly calculate the remaining available width.
672 // Note that only the current multiprofile user gets a button. 780 // Note that only the current multiprofile user gets a button.
673 if (!multiprofile_index_) 781 if (!multiprofile_index_)
674 AddLogoutButton(login); 782 AddLogoutButton(login);
675 AddUserCard(owner, login); 783 AddUserCard(login);
676 } 784 }
677 785
678 UserView::~UserView() {} 786 UserView::~UserView() {}
679 787
680 void UserView::MouseMovedOutOfHost() { 788 void UserView::MouseMovedOutOfHost() {
681 popup_message_.reset(); 789 popup_message_.reset();
682 mouse_watcher_.reset(); 790 mouse_watcher_.reset();
683 add_menu_option_.reset(); 791 add_menu_option_.reset();
684 } 792 }
685 793
686 TrayUser::TestState UserView::GetStateForTest() const { 794 TrayUser::TestState UserView::GetStateForTest() const {
687 if (add_menu_option_.get()) { 795 if (add_menu_option_.get()) {
688 return add_user_visible_but_disabled_ ? TrayUser::ACTIVE_BUT_DISABLED : 796 return add_user_disabled_ ? TrayUser::ACTIVE_BUT_DISABLED
689 TrayUser::ACTIVE; 797 : TrayUser::ACTIVE;
690 } 798 }
691 799
692 if (!is_user_card_) 800 if (!is_user_card_button_)
693 return TrayUser::SHOWN; 801 return TrayUser::SHOWN;
694 802
695 return static_cast<UserCard*>(user_card_view_)->is_hovered_for_test() ? 803 return static_cast<ButtonFromView*>(user_card_view_)->is_hovered_for_test()
696 TrayUser::HOVERED : TrayUser::SHOWN; 804 ? TrayUser::HOVERED
805 : TrayUser::SHOWN;
697 } 806 }
698 807
699 gfx::Rect UserView::GetBoundsInScreenOfUserButtonForTest() { 808 gfx::Rect UserView::GetBoundsInScreenOfUserButtonForTest() {
700 DCHECK(user_card_view_); 809 DCHECK(user_card_view_);
701 return user_card_view_->GetBoundsInScreen(); 810 return user_card_view_->GetBoundsInScreen();
702 } 811 }
703 812
704 gfx::Size UserView::GetPreferredSize() { 813 gfx::Size UserView::GetPreferredSize() {
705 gfx::Size size = views::View::GetPreferredSize(); 814 gfx::Size size = views::View::GetPreferredSize();
706 // Only the active user panel will be forced to a certain height. 815 // Only the active user panel will be forced to a certain height.
(...skipping 12 matching lines...) Expand all
719 gfx::Rect contents_area(GetContentsBounds()); 828 gfx::Rect contents_area(GetContentsBounds());
720 if (user_card_view_ && logout_button_) { 829 if (user_card_view_ && logout_button_) {
721 // Give the logout button the space it requests. 830 // Give the logout button the space it requests.
722 gfx::Rect logout_area = contents_area; 831 gfx::Rect logout_area = contents_area;
723 logout_area.ClampToCenteredSize(logout_button_->GetPreferredSize()); 832 logout_area.ClampToCenteredSize(logout_button_->GetPreferredSize());
724 logout_area.set_x(contents_area.right() - logout_area.width()); 833 logout_area.set_x(contents_area.right() - logout_area.width());
725 834
726 // Give the remaining space to the user card. 835 // Give the remaining space to the user card.
727 gfx::Rect user_card_area = contents_area; 836 gfx::Rect user_card_area = contents_area;
728 int remaining_width = contents_area.width() - logout_area.width(); 837 int remaining_width = contents_area.width() - logout_area.width();
729 if (SupportsMultiProfile()) { 838 if (IsMultiProfileSupportedAndUserActive() ||
839 IsAccountManagementSupportedAndUserActive()) {
730 // In multiprofile case |user_card_view_| and |logout_button_| have to 840 // In multiprofile case |user_card_view_| and |logout_button_| have to
731 // have the same height. 841 // have the same height.
732 int y = std::min(user_card_area.y(), logout_area.y()); 842 int y = std::min(user_card_area.y(), logout_area.y());
733 int height = std::max(user_card_area.height(), logout_area.height()); 843 int height = std::max(user_card_area.height(), logout_area.height());
734 logout_area.set_y(y); 844 logout_area.set_y(y);
735 logout_area.set_height(height); 845 logout_area.set_height(height);
736 user_card_area.set_y(y); 846 user_card_area.set_y(y);
737 user_card_area.set_height(height); 847 user_card_area.set_height(height);
738 848
739 // In multiprofile mode we have also to increase the size of the card by 849 // In multiprofile mode we have also to increase the size of the card by
(...skipping 18 matching lines...) Expand all
758 } else if (logout_button_) { 868 } else if (logout_button_) {
759 logout_button_->SetBoundsRect(contents_area); 869 logout_button_->SetBoundsRect(contents_area);
760 } 870 }
761 } 871 }
762 872
763 void UserView::ButtonPressed(views::Button* sender, const ui::Event& event) { 873 void UserView::ButtonPressed(views::Button* sender, const ui::Event& event) {
764 if (sender == logout_button_) { 874 if (sender == logout_button_) {
765 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 875 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
766 ash::UMA_STATUS_AREA_SIGN_OUT); 876 ash::UMA_STATUS_AREA_SIGN_OUT);
767 Shell::GetInstance()->system_tray_delegate()->SignOut(); 877 Shell::GetInstance()->system_tray_delegate()->SignOut();
768 } else if (sender == user_card_view_ && SupportsMultiProfile()) { 878 } else if (sender == user_card_view_ && !multiprofile_index_ &&
879 IsAccountManagementSupportedAndUserActive()) {
880 owner_->TransitionDetailedView();
881 } else if (sender == user_card_view_ &&
882 IsMultiProfileSupportedAndUserActive()) {
769 if (!multiprofile_index_) { 883 if (!multiprofile_index_) {
770 ToggleAddUserMenuOption(); 884 ToggleAddUserMenuOption();
771 } else { 885 } else {
772 SwitchUser(multiprofile_index_); 886 SwitchUser(multiprofile_index_);
773 // Since the user list is about to change the system menu should get 887 // Since the user list is about to change the system menu should get
774 // closed. 888 // closed.
775 owner_->system_tray()->CloseSystemBubble(); 889 owner_->system_tray()->CloseSystemBubble();
776 } 890 }
777 } else if (add_menu_option_.get() && 891 } else if (add_menu_option_.get() &&
778 sender == add_menu_option_->GetContentsView()) { 892 sender == add_menu_option_->GetContentsView()) {
779 // Let the user add another account to the session. 893 // Let the user add another account to the session.
780 MultiProfileUMA::RecordSigninUser(MultiProfileUMA::SIGNIN_USER_BY_TRAY); 894 MultiProfileUMA::RecordSigninUser(MultiProfileUMA::SIGNIN_USER_BY_TRAY);
781 Shell::GetInstance()->system_tray_delegate()->ShowUserLogin(); 895 Shell::GetInstance()->system_tray_delegate()->ShowUserLogin();
782 owner_->system_tray()->CloseSystemBubble(); 896 owner_->system_tray()->CloseSystemBubble();
783 } else { 897 } else {
784 NOTREACHED(); 898 NOTREACHED();
785 } 899 }
786 } 900 }
787 901
788 void UserView::AddLogoutButton(user::LoginStatus login) { 902 void UserView::AddLogoutButton(user::LoginStatus login) {
789 const base::string16 title = user::GetLocalizedSignOutStringForStatus(login, 903 const base::string16 title = user::GetLocalizedSignOutStringForStatus(login,
790 true); 904 true);
791 TrayPopupLabelButton* logout_button = new TrayPopupLabelButton(this, title); 905 TrayPopupLabelButton* logout_button =
906 new LogoutButton(this, title, for_detailed_view_);
792 logout_button->SetAccessibleName(title); 907 logout_button->SetAccessibleName(title);
793 logout_button_ = logout_button; 908 logout_button_ = logout_button;
794 // In public account mode, the logout button border has a custom color. 909 // In public account mode, the logout button border has a custom color.
795 if (login == user::LOGGED_IN_PUBLIC) { 910 if (login == user::LOGGED_IN_PUBLIC) {
796 scoped_ptr<TrayPopupLabelButtonBorder> border( 911 scoped_ptr<TrayPopupLabelButtonBorder> border(
797 new TrayPopupLabelButtonBorder()); 912 new TrayPopupLabelButtonBorder());
798 border->SetPainter(false, views::Button::STATE_NORMAL, 913 border->SetPainter(false, views::Button::STATE_NORMAL,
799 views::Painter::CreateImageGridPainter( 914 views::Painter::CreateImageGridPainter(
800 kPublicAccountLogoutButtonBorderImagesNormal)); 915 kPublicAccountLogoutButtonBorderImagesNormal));
801 border->SetPainter(false, views::Button::STATE_HOVERED, 916 border->SetPainter(false, views::Button::STATE_HOVERED,
802 views::Painter::CreateImageGridPainter( 917 views::Painter::CreateImageGridPainter(
803 kPublicAccountLogoutButtonBorderImagesHovered)); 918 kPublicAccountLogoutButtonBorderImagesHovered));
804 border->SetPainter(false, views::Button::STATE_PRESSED, 919 border->SetPainter(false, views::Button::STATE_PRESSED,
805 views::Painter::CreateImageGridPainter( 920 views::Painter::CreateImageGridPainter(
806 kPublicAccountLogoutButtonBorderImagesHovered)); 921 kPublicAccountLogoutButtonBorderImagesHovered));
807 logout_button_->SetBorder(border.PassAs<views::Border>()); 922 logout_button_->SetBorder(border.PassAs<views::Border>());
808 } 923 }
809 AddChildView(logout_button_); 924 AddChildView(logout_button_);
810 } 925 }
811 926
812 void UserView::AddUserCard(SystemTrayItem* owner, user::LoginStatus login) { 927 void UserView::AddUserCard(user::LoginStatus login) {
813 // Add padding around the panel. 928 // Add padding around the panel.
814 SetBorder(views::Border::CreateEmptyBorder(kUserCardVerticalPadding, 929 SetBorder(views::Border::CreateEmptyBorder(kUserCardVerticalPadding,
815 kTrayPopupPaddingHorizontal, 930 kTrayPopupPaddingHorizontal,
816 kUserCardVerticalPadding, 931 kUserCardVerticalPadding,
817 kTrayPopupPaddingHorizontal)); 932 kTrayPopupPaddingHorizontal));
818 933
819 if (SupportsMultiProfile() && login != user::LOGGED_IN_RETAIL_MODE) { 934 views::TrayBubbleView* bubble_view =
820 user_card_view_ = new UserCard(this, multiprofile_index_ == 0); 935 owner_->system_tray()->GetSystemBubble()->bubble_view();
821 is_user_card_ = true; 936 int max_card_width =
822 } else { 937 bubble_view->GetMaximumSize().width() -
823 user_card_view_ = new views::View(); 938 (2 * kTrayPopupPaddingHorizontal + kTrayPopupPaddingBetweenItems);
824 is_user_card_ = false; 939 if (logout_button_)
940 max_card_width -= logout_button_->GetPreferredSize().width();
941 user_card_view_ =
942 new UserCardView(login, max_card_width, multiprofile_index_);
943 bool clickable = IsMultiProfileSupportedAndUserActive() ||
944 IsAccountManagementSupportedAndUserActive();
945 if (clickable) {
946 // To allow the border to start before the icon, reduce the size before and
947 // add an inset to the icon to get the spacing.
948 if (!multiprofile_index_) {
949 SetBorder(views::Border::CreateEmptyBorder(
950 kUserCardVerticalPadding,
951 kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset,
952 kUserCardVerticalPadding,
953 kTrayPopupPaddingHorizontal));
954 user_card_view_->SetBorder(views::Border::CreateEmptyBorder(
955 0, kTrayUserTileHoverBorderInset, 0, 0));
956 }
957 if (!for_detailed_view_) {
958 user_card_view_ =
959 new ButtonFromView(user_card_view_, this, !multiprofile_index_);
960 } else {
961 // We want user card for detailed view to have exactly the same look
962 // as user card for default view. That's why we wrap it in a button
963 // without click listener and special hover behaviour.
964 user_card_view_ = new ButtonFromView(user_card_view_, NULL, false);
965 }
966 is_user_card_button_ = true;
825 } 967 }
826
827 user_card_view_->SetLayoutManager(new views::BoxLayout(
828 views::BoxLayout::kHorizontal, 0, 0 , kTrayPopupPaddingBetweenItems));
829 AddChildViewAt(user_card_view_, 0); 968 AddChildViewAt(user_card_view_, 0);
830 969 // Card for locally managed user can consume more space than currently
831 if (login == user::LOGGED_IN_RETAIL_MODE) { 970 // available. In that case we should increase system bubble's width.
832 AddLoggedInRetailModeUserCardContent(); 971 if (login == user::LOGGED_IN_PUBLIC)
833 return; 972 bubble_view->SetWidth(GetPreferredSize().width());
834 }
835
836 // The entire user card should trigger hover (the inner items get disabled).
837 user_card_view_->SetEnabled(true);
838 user_card_view_->set_notify_enter_exit_on_child(true);
839
840 if (login == user::LOGGED_IN_PUBLIC) {
841 AddLoggedInPublicModeUserCardContent(owner);
842 return;
843 }
844
845 views::View* icon = CreateIconForUserCard(login);
846 user_card_view_->AddChildView(icon);
847
848 // To allow the border to start before the icon, reduce the size before and
849 // add an inset to the icon to get the spacing.
850 if (multiprofile_index_ == 0 && SupportsMultiProfile()) {
851 icon->SetBorder(views::Border::CreateEmptyBorder(
852 0, kTrayUserTileHoverBorderInset, 0, 0));
853 SetBorder(views::Border::CreateEmptyBorder(
854 kUserCardVerticalPadding,
855 kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset,
856 kUserCardVerticalPadding,
857 kTrayPopupPaddingHorizontal));
858 }
859 SessionStateDelegate* delegate =
860 Shell::GetInstance()->session_state_delegate();
861 views::Label* username = NULL;
862 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
863 if (!multiprofile_index_) {
864 base::string16 user_name_string =
865 login == user::LOGGED_IN_GUEST ?
866 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_GUEST_LABEL) :
867 delegate->GetUserDisplayName(multiprofile_index_);
868 if (!user_name_string.empty()) {
869 username = new views::Label(user_name_string);
870 username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
871 }
872 }
873
874 views::Label* additional = NULL;
875 if (login != user::LOGGED_IN_GUEST) {
876 base::string16 user_email_string =
877 login == user::LOGGED_IN_LOCALLY_MANAGED ?
878 bundle.GetLocalizedString(
879 IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL) :
880 base::UTF8ToUTF16(delegate->GetUserEmail(multiprofile_index_));
881 if (!user_email_string.empty()) {
882 additional = new views::Label(user_email_string);
883 additional->SetFontList(
884 bundle.GetFontList(ui::ResourceBundle::SmallFont));
885 additional->SetHorizontalAlignment(gfx::ALIGN_LEFT);
886 }
887 }
888
889 // Adjust text properties dependent on if it is an active or inactive user.
890 if (multiprofile_index_) {
891 // Fade the text of non active users to 50%.
892 SkColor text_color = additional->enabled_color();
893 text_color = SkColorSetA(text_color, SkColorGetA(text_color) / 2);
894 if (additional)
895 additional->SetDisabledColor(text_color);
896 if (username)
897 username->SetDisabledColor(text_color);
898 }
899
900 if (additional && username) {
901 views::View* details = new views::View;
902 details->SetLayoutManager(new views::BoxLayout(
903 views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0));
904 details->AddChildView(username);
905 details->AddChildView(additional);
906 user_card_view_->AddChildView(details);
907 } else {
908 if (username)
909 user_card_view_->AddChildView(username);
910 if (additional)
911 user_card_view_->AddChildView(additional);
912 }
913 }
914
915 views::View* UserView::CreateIconForUserCard(user::LoginStatus login) {
916 RoundedImageView* icon = new RoundedImageView(kProfileRoundedCornerRadius,
917 multiprofile_index_ == 0);
918 icon->SetEnabled(false);
919 if (login == user::LOGGED_IN_GUEST) {
920 icon->SetImage(*ui::ResourceBundle::GetSharedInstance().
921 GetImageNamed(IDR_AURA_UBER_TRAY_GUEST_ICON).ToImageSkia(),
922 gfx::Size(kUserIconSize, kUserIconSize));
923 } else {
924 SessionStateDelegate* delegate =
925 Shell::GetInstance()->session_state_delegate();
926 content::BrowserContext* context = delegate->GetBrowserContextByIndex(
927 multiprofile_index_);
928 icon->SetImage(delegate->GetUserImage(context),
929 gfx::Size(kUserIconSize, kUserIconSize));
930 }
931 return icon;
932 }
933
934 void UserView::AddLoggedInRetailModeUserCardContent() {
935 views::Label* details = new views::Label;
936 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
937 details->SetText(
938 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_KIOSK_LABEL));
939 details->SetBorder(views::Border::CreateEmptyBorder(0, 4, 0, 1));
940 details->SetHorizontalAlignment(gfx::ALIGN_LEFT);
941 user_card_view_->AddChildView(details);
942 }
943
944 void UserView::AddLoggedInPublicModeUserCardContent(SystemTrayItem* owner) {
945 user_card_view_->AddChildView(CreateIconForUserCard(user::LOGGED_IN_PUBLIC));
946 user_card_view_->AddChildView(new PublicAccountUserDetails(
947 owner, GetPreferredSize().width() + kTrayPopupPaddingBetweenItems));
948 } 973 }
949 974
950 void UserView::ToggleAddUserMenuOption() { 975 void UserView::ToggleAddUserMenuOption() {
951 if (add_menu_option_.get()) { 976 if (add_menu_option_.get()) {
952 popup_message_.reset(); 977 popup_message_.reset();
953 mouse_watcher_.reset(); 978 mouse_watcher_.reset();
954 add_menu_option_.reset(); 979 add_menu_option_.reset();
955 return; 980 return;
956 } 981 }
957 982
958 // Note: We do not need to install a global event handler to delete this 983 // Note: We do not need to install a global event handler to delete this
959 // item since it will destroyed automatically before the menu / user menu item 984 // item since it will destroyed automatically before the menu / user menu item
960 // gets destroyed.. 985 // gets destroyed..
961 const SessionStateDelegate* session_state_delegate =
962 Shell::GetInstance()->session_state_delegate();
963 add_user_visible_but_disabled_ =
964 session_state_delegate->NumberOfLoggedInUsers() >=
965 session_state_delegate->GetMaximumNumberOfLoggedInUsers();
966 add_menu_option_.reset(new views::Widget); 986 add_menu_option_.reset(new views::Widget);
967 views::Widget::InitParams params; 987 views::Widget::InitParams params;
968 params.type = views::Widget::InitParams::TYPE_TOOLTIP; 988 params.type = views::Widget::InitParams::TYPE_TOOLTIP;
969 params.keep_on_top = true; 989 params.keep_on_top = true;
970 params.context = this->GetWidget()->GetNativeWindow(); 990 params.context = this->GetWidget()->GetNativeWindow();
971 params.accept_events = true; 991 params.accept_events = true;
972 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 992 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
973 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 993 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
974 add_menu_option_->Init(params); 994 add_menu_option_->Init(params);
975 add_menu_option_->SetOpacity(0xFF); 995 add_menu_option_->SetOpacity(0xFF);
976 add_menu_option_->GetNativeWindow()->set_owned_by_parent(false); 996 add_menu_option_->GetNativeWindow()->set_owned_by_parent(false);
977 SetShadowType(add_menu_option_->GetNativeView(), 997 SetShadowType(add_menu_option_->GetNativeView(),
978 wm::SHADOW_TYPE_NONE); 998 wm::SHADOW_TYPE_NONE);
979 999
980 // Position it below our user card. 1000 // Position it below our user card.
981 gfx::Rect bounds = user_card_view_->GetBoundsInScreen(); 1001 gfx::Rect bounds = user_card_view_->GetBoundsInScreen();
982 bounds.set_y(bounds.y() + bounds.height()); 1002 bounds.set_y(bounds.y() + bounds.height());
983 add_menu_option_->SetBounds(bounds); 1003 add_menu_option_->SetBounds(bounds);
984 1004
985 // Show the content. 1005 // Show the content.
986 AddUserView* add_user_view = new AddUserView(
987 static_cast<UserCard*>(user_card_view_), this);
988 add_menu_option_->SetContentsView(add_user_view);
989 add_menu_option_->SetAlwaysOnTop(true); 1006 add_menu_option_->SetAlwaysOnTop(true);
990 add_menu_option_->Show(); 1007 add_menu_option_->Show();
991 if (add_user_visible_but_disabled_) { 1008
1009 AddUserView* add_user_view =
1010 new AddUserView(static_cast<ButtonFromView*>(user_card_view_));
1011
1012 const SessionStateDelegate* delegate =
1013 Shell::GetInstance()->session_state_delegate();
1014 add_user_disabled_ = delegate->NumberOfLoggedInUsers() >=
1015 delegate->GetMaximumNumberOfLoggedInUsers();
1016 ButtonFromView* button = add_user_disabled_
1017 ? new ButtonFromView(add_user_view, NULL, false)
1018 : new ButtonFromView(add_user_view, this, true);
1019 button->ForceBorderVisible(true);
1020 add_menu_option_->SetContentsView(button);
1021
1022 if (add_user_disabled_) {
992 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 1023 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
993 popup_message_.reset(new PopupMessage( 1024 popup_message_.reset(new PopupMessage(
994 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER), 1025 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER),
995 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER), 1026 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER),
996 PopupMessage::ICON_WARNING, 1027 PopupMessage::ICON_WARNING,
997 add_user_view->anchor(), 1028 add_user_view->anchor(),
998 views::BubbleBorder::TOP_LEFT, 1029 views::BubbleBorder::TOP_LEFT,
999 gfx::Size(parent()->bounds().width() - kPopupMessageOffset, 0), 1030 gfx::Size(parent()->bounds().width() - kPopupMessageOffset, 0),
1000 2 * kPopupMessageOffset)); 1031 2 * kPopupMessageOffset));
1001 } 1032 }
1002 // Find the screen area which encloses both elements and sets then a mouse 1033 // Find the screen area which encloses both elements and sets then a mouse
1003 // watcher which will close the "menu". 1034 // watcher which will close the "menu".
1004 gfx::Rect area = user_card_view_->GetBoundsInScreen(); 1035 gfx::Rect area = user_card_view_->GetBoundsInScreen();
1005 area.set_height(2 * area.height()); 1036 area.set_height(2 * area.height());
1006 mouse_watcher_.reset(new views::MouseWatcher( 1037 mouse_watcher_.reset(new views::MouseWatcher(
1007 new UserViewMouseWatcherHost(area), 1038 new UserViewMouseWatcherHost(area),
1008 this)); 1039 this));
1009 mouse_watcher_->Start(); 1040 mouse_watcher_->Start();
1010 } 1041 }
1011 1042
1012 bool UserView::SupportsMultiProfile() { 1043 AddUserView::AddUserView(ButtonFromView* owner)
1013 // We do not want to see any multi profile additions to a user view when the 1044 : add_user_(NULL), owner_(owner), anchor_(NULL) {
1014 // log in screen is shown.
1015 return Shell::GetInstance()->delegate()->IsMultiProfilesEnabled() &&
1016 !Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked();
1017 }
1018
1019 AddUserView::AddUserView(UserCard* owner, views::ButtonListener* listener)
1020 : CustomButton(listener),
1021 add_user_(NULL),
1022 listener_(listener),
1023 owner_(owner),
1024 anchor_(NULL) {
1025 AddContent(); 1045 AddContent();
1026 owner_->ForceBorderVisible(true); 1046 owner_->ForceBorderVisible(true);
1027 } 1047 }
1028 1048
1029 AddUserView::~AddUserView() { 1049 AddUserView::~AddUserView() {
1030 owner_->ForceBorderVisible(false); 1050 owner_->ForceBorderVisible(false);
1031 } 1051 }
1032 1052
1033 gfx::Size AddUserView::GetPreferredSize() { 1053 gfx::Size AddUserView::GetPreferredSize() {
1034 return owner_->bounds().size(); 1054 return owner_->bounds().size();
1035 } 1055 }
1036 1056
1037 int AddUserView::GetHeightForWidth(int width) {
1038 return owner_->bounds().size().height();
1039 }
1040
1041 void AddUserView::Layout() {
1042 gfx::Rect contents_area(GetContentsBounds());
1043 add_user_->SetBoundsRect(contents_area);
1044 }
1045
1046 void AddUserView::ButtonPressed(views::Button* sender, const ui::Event& event) {
1047 if (add_user_ == sender)
1048 listener_->ButtonPressed(this, event);
1049 else
1050 NOTREACHED();
1051 }
1052
1053 void AddUserView::AddContent() { 1057 void AddUserView::AddContent() {
1054 set_notify_enter_exit_on_child(true);
1055
1056 const SessionStateDelegate* delegate =
1057 Shell::GetInstance()->session_state_delegate();
1058 bool enable = delegate->NumberOfLoggedInUsers() <
1059 delegate->GetMaximumNumberOfLoggedInUsers();
1060
1061 SetLayoutManager(new views::FillLayout()); 1058 SetLayoutManager(new views::FillLayout());
1062 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); 1059 set_background(views::Background::CreateSolidBackground(kBackgroundColor));
1063 1060
1064 // Add padding around the panel. 1061 add_user_ = new views::View;
1065 SetBorder(views::Border::CreateSolidBorder(1, kBorderColor));
1066
1067 add_user_ = new UserCard(this, enable);
1068 add_user_->SetBorder(views::Border::CreateEmptyBorder( 1062 add_user_->SetBorder(views::Border::CreateEmptyBorder(
1069 kUserCardVerticalPadding, 1063 kUserCardVerticalPadding,
1070 kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset, 1064 kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset,
1071 kUserCardVerticalPadding, 1065 kUserCardVerticalPadding,
1072 kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset)); 1066 kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset));
1073 1067
1074 add_user_->SetLayoutManager(new views::BoxLayout( 1068 add_user_->SetLayoutManager(new views::BoxLayout(
1075 views::BoxLayout::kHorizontal, 0, 0 , kTrayPopupPaddingBetweenItems)); 1069 views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems));
1076 AddChildViewAt(add_user_, 0); 1070 AddChildViewAt(add_user_, 0);
1077 1071
1078 // Add the [+] icon which is also the anchor for messages. 1072 // Add the [+] icon which is also the anchor for messages.
1079 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 1073 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
1080 RoundedImageView* icon = new RoundedImageView(kProfileRoundedCornerRadius, 1074 RoundedImageView* icon = new RoundedImageView(kProfileRoundedCornerRadius,
1081 true); 1075 true);
1082 anchor_ = icon; 1076 anchor_ = icon;
1083 icon->SetImage(*ui::ResourceBundle::GetSharedInstance(). 1077 icon->SetImage(*ui::ResourceBundle::GetSharedInstance().
1084 GetImageNamed(IDR_AURA_UBER_TRAY_ADD_MULTIPROFILE_USER).ToImageSkia(), 1078 GetImageNamed(IDR_AURA_UBER_TRAY_ADD_MULTIPROFILE_USER).ToImageSkia(),
1085 gfx::Size(kUserIconSize, kUserIconSize)); 1079 gfx::Size(kUserIconSize, kUserIconSize));
1086 add_user_->AddChildView(icon); 1080 add_user_->AddChildView(icon);
1087 1081
1088 // Add the command text. 1082 // Add the command text.
1089 views::Label* command_label = new views::Label( 1083 views::Label* command_label = new views::Label(
1090 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); 1084 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT));
1091 command_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 1085 command_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1092 add_user_->AddChildView(command_label); 1086 add_user_->AddChildView(command_label);
1093 } 1087 }
1094 1088
1089 UserCardView::UserCardView(user::LoginStatus login_status,
1090 int max_width,
1091 int multiprofile_index) {
1092 SetLayoutManager(new views::BoxLayout(
1093 views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems));
1094 switch (login_status) {
1095 case user::LOGGED_IN_RETAIL_MODE:
1096 AddRetailModeUserContent();
1097 break;
1098 case user::LOGGED_IN_PUBLIC:
1099 AddPublicModeUserContent(max_width);
1100 break;
1101 default:
1102 AddUserContent(login_status, multiprofile_index);
1103 break;
1104 }
1105 }
1106
1107 void UserCardView::AddRetailModeUserContent() {
1108 views::Label* details = new views::Label;
1109 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
1110 details->SetText(bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_KIOSK_LABEL));
1111 details->SetBorder(views::Border::CreateEmptyBorder(0, 4, 0, 1));
1112 details->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1113 AddChildView(details);
1114 }
1115
1116 void UserCardView::AddPublicModeUserContent(int max_width) {
1117 views::View* icon = CreateIcon(user::LOGGED_IN_PUBLIC, 0);
1118 AddChildView(icon);
1119 int details_max_width = max_width - icon->GetPreferredSize().width() -
1120 kTrayPopupPaddingBetweenItems;
1121 AddChildView(new PublicAccountUserDetails(details_max_width));
1122 }
1123
1124 void UserCardView::AddUserContent(user::LoginStatus login_status,
1125 int multiprofile_index) {
1126 views::View* icon = CreateIcon(login_status, multiprofile_index);
1127 AddChildView(icon);
1128 views::Label* username = NULL;
1129 SessionStateDelegate* delegate =
1130 Shell::GetInstance()->session_state_delegate();
1131 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
1132 if (!multiprofile_index) {
1133 base::string16 user_name_string =
1134 login_status == user::LOGGED_IN_GUEST
1135 ? bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_GUEST_LABEL)
1136 : delegate->GetUserDisplayName(multiprofile_index);
1137 if (user_name_string.empty() && IsAccountManagementSupportedAndUserActive())
1138 user_name_string =
1139 base::ASCIIToUTF16(delegate->GetUserEmail(multiprofile_index));
1140 if (!user_name_string.empty()) {
1141 username = new views::Label(user_name_string);
1142 username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1143 }
1144 }
1145
1146 views::Label* additional = NULL;
1147 if (login_status != user::LOGGED_IN_GUEST &&
1148 (multiprofile_index || !IsAccountManagementSupportedAndUserActive())) {
1149 base::string16 user_email_string =
1150 login_status == user::LOGGED_IN_LOCALLY_MANAGED
1151 ? bundle.GetLocalizedString(
1152 IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL)
1153 : base::UTF8ToUTF16(delegate->GetUserEmail(multiprofile_index));
1154 if (!user_email_string.empty()) {
1155 additional = new views::Label(user_email_string);
1156 additional->SetFontList(
1157 bundle.GetFontList(ui::ResourceBundle::SmallFont));
1158 additional->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1159 }
1160 }
1161
1162 // Adjust text properties dependent on if it is an active or inactive user.
1163 if (multiprofile_index) {
1164 // Fade the text of non active users to 50%.
1165 SkColor text_color = additional->enabled_color();
1166 text_color = SkColorSetA(text_color, SkColorGetA(text_color) / 2);
1167 if (additional)
1168 additional->SetDisabledColor(text_color);
1169 if (username)
1170 username->SetDisabledColor(text_color);
1171 }
1172
1173 if (additional && username) {
1174 views::View* details = new views::View;
1175 details->SetLayoutManager(new views::BoxLayout(
1176 views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0));
1177 details->AddChildView(username);
1178 details->AddChildView(additional);
1179 AddChildView(details);
1180 } else {
1181 if (username)
1182 AddChildView(username);
1183 if (additional)
1184 AddChildView(additional);
1185 }
1186 }
1187
1188 views::View* UserCardView::CreateIcon(user::LoginStatus login_status,
1189 int multiprofile_index) {
1190 RoundedImageView* icon = new RoundedImageView(kProfileRoundedCornerRadius,
1191 multiprofile_index == 0);
1192 if (login_status == user::LOGGED_IN_GUEST) {
1193 icon->SetImage(*ui::ResourceBundle::GetSharedInstance()
1194 .GetImageNamed(IDR_AURA_UBER_TRAY_GUEST_ICON)
1195 .ToImageSkia(),
1196 gfx::Size(kUserIconSize, kUserIconSize));
1197 } else {
1198 SessionStateDelegate* delegate =
1199 Shell::GetInstance()->session_state_delegate();
1200 content::BrowserContext* context =
1201 delegate->GetBrowserContextByIndex(multiprofile_index);
1202 icon->SetImage(delegate->GetUserImage(context),
1203 gfx::Size(kUserIconSize, kUserIconSize));
1204 }
1205 return icon;
1206 }
1207
1208 AccountsDetailedView::AccountsDetailedView(TrayUser* owner,
1209 user::LoginStatus login_status)
1210 : TrayDetailsView(owner),
1211 delegate_(NULL),
1212 account_list_(NULL),
1213 add_account_button_(NULL),
1214 add_user_button_(NULL) {
1215 std::string user_id =
1216 Shell::GetInstance()->session_state_delegate()->GetUserID(0);
1217 delegate_ =
1218 Shell::GetInstance()->system_tray_delegate()->GetUserAccountsDelegate(
1219 user_id);
1220 delegate_->AddObserver(this);
1221 AddHeader(login_status);
1222 CreateScrollableList();
1223 AddAccountList();
1224 AddAddAccountButton();
1225 AddFooter();
1226 }
1227
1228 AccountsDetailedView::~AccountsDetailedView() {
1229 delegate_->RemoveObserver(this);
1230 }
1231
1232 void AccountsDetailedView::OnViewClicked(views::View* sender) {
1233 if (sender == footer()->content())
1234 TransitionToDefaultView();
1235 else if (sender == add_account_button_)
1236 delegate_->LaunchAddAccountDialog();
1237 else
1238 NOTREACHED();
1239 }
1240
1241 void AccountsDetailedView::ButtonPressed(views::Button* sender,
1242 const ui::Event& event) {
1243 std::map<views::View*, std::string>::iterator it =
1244 delete_button_to_account_id_.find(sender);
1245 if (it != delete_button_to_account_id_.end()) {
1246 delegate_->DeleteAccount(it->second);
1247 } else if (add_user_button_ && add_user_button_ == sender) {
1248 MultiProfileUMA::RecordSigninUser(MultiProfileUMA::SIGNIN_USER_BY_TRAY);
1249 Shell::GetInstance()->system_tray_delegate()->ShowUserLogin();
1250 owner()->system_tray()->CloseSystemBubble();
1251 } else {
1252 NOTREACHED();
1253 }
1254 }
1255
1256 void AccountsDetailedView::AccountListChanged() { UpdateAccountList(); }
1257
1258 void AccountsDetailedView::AddHeader(user::LoginStatus login_status) {
1259 views::View* user_view_container = new views::View;
1260 user_view_container->SetLayoutManager(
1261 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
1262 user_view_container->SetBorder(
1263 views::Border::CreateSolidSidedBorder(0, 0, 1, 0, kBorderLightColor));
1264 user_view_container->AddChildView(
1265 new tray::UserView(owner(), login_status, 0, true));
1266 AddChildView(user_view_container);
1267 }
1268
1269 void AccountsDetailedView::AddAccountList() {
1270 scroll_content()->SetBorder(
1271 views::Border::CreateEmptyBorder(kAccountsViewVerticalPadding,
1272 kTrayPopupPaddingHorizontal,
1273 kAccountsViewVerticalPadding,
1274 kTrayPopupPaddingHorizontal));
1275 views::Label* account_list_title = new views::Label(
1276 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCOUNT_LIST_TITLE));
1277 account_list_title->SetEnabledColor(SkColorSetARGB(0x7f, 0, 0, 0));
1278 account_list_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1279 scroll_content()->AddChildView(account_list_title);
1280 account_list_ = new views::View();
1281 UpdateAccountList();
1282 scroll_content()->AddChildView(account_list_);
1283 }
1284
1285 void AccountsDetailedView::AddAddAccountButton() {
1286 SessionStateDelegate* session_state_delegate =
1287 Shell::GetInstance()->session_state_delegate();
1288 HoverHighlightView* add_account_button = new HoverHighlightView(this);
1289 base::string16 user_name = session_state_delegate->GetUserGivenName(0);
1290 if (user_name.empty())
1291 user_name = session_state_delegate->GetUserDisplayName(0);
1292 if (user_name.empty())
1293 user_name = base::ASCIIToUTF16(session_state_delegate->GetUserEmail(0));
1294 add_account_button->AddLabel(
1295 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_ADD_ACCOUNT_LABEL,
1296 user_name),
1297 gfx::ALIGN_CENTER,
1298 gfx::Font::NORMAL);
1299 AddChildView(add_account_button);
1300 add_account_button_ = add_account_button;
1301 }
1302
1303 void AccountsDetailedView::AddFooter() {
1304 CreateSpecialRow(IDS_ASH_STATUS_TRAY_ACCOUNTS_TITLE, this);
1305 if (!IsMultiProfileSupportedAndUserActive())
1306 return;
1307 TrayPopupHeaderButton* add_user_button =
1308 new TrayPopupHeaderButton(this,
1309 IDR_AURA_UBER_TRAY_NETWORK_INFO,
1310 IDR_AURA_UBER_TRAY_NETWORK_INFO,
1311 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
1312 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
1313 IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT);
1314 add_user_button->SetTooltipText(
1315 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT));
1316 footer()->AddButton(add_user_button);
1317 add_user_button_ = add_user_button;
1318 }
1319
1320 void AccountsDetailedView::UpdateAccountList() {
1321 // Clear existing view.
1322 delete_button_to_account_id_.clear();
1323 account_list_->RemoveAllChildViews(true);
1324
1325 // Configuring layout manager.
1326 views::GridLayout* layout = new views::GridLayout(account_list_);
1327 account_list_->SetLayoutManager(layout);
1328 views::ColumnSet* primary_account_row =
1329 layout->AddColumnSet(kPrimaryAccountColumnSetID);
1330 primary_account_row->AddColumn(views::GridLayout::LEADING,
1331 views::GridLayout::BASELINE,
1332 1.0,
1333 views::GridLayout::USE_PREF,
1334 0,
1335 0);
1336 views::ColumnSet* secondary_account_row =
1337 layout->AddColumnSet(kSecondaryAccountColumnSetID);
1338 secondary_account_row->AddColumn(views::GridLayout::FILL,
1339 views::GridLayout::BASELINE,
1340 1.0,
1341 views::GridLayout::USE_PREF,
1342 0,
1343 0);
1344 secondary_account_row->AddPaddingColumn(0.0, kTrayPopupPaddingBetweenItems);
1345 secondary_account_row->AddColumn(views::GridLayout::FILL,
1346 views::GridLayout::BASELINE,
1347 0.0,
1348 views::GridLayout::USE_PREF,
1349 0,
1350 0);
1351
1352 // Adding primary account.
1353 layout->AddPaddingRow(0.0, kPaddingBetweenAccounts);
1354 layout->StartRow(0.0, kPrimaryAccountColumnSetID);
1355 const std::string& primary_account = delegate_->GetPrimaryAccount();
1356 views::Label* primary_account_label =
1357 new views::Label(l10n_util::GetStringFUTF16(
1358 IDS_ASH_STATUS_TRAY_PRIMARY_ACCOUNT_LABEL,
1359 base::ASCIIToUTF16(
1360 delegate_->GetAccountDisplayName(primary_account))));
1361 layout->AddView(primary_account_label);
1362
1363 // Adding secondary accounts.
1364 const std::vector<std::string>& secondary_accounts =
1365 delegate_->GetSecondaryAccountsList();
1366 for (size_t i = 0; i < secondary_accounts.size(); ++i) {
1367 layout->AddPaddingRow(0.0, kPaddingBetweenAccounts);
1368 layout->StartRow(0.0, kSecondaryAccountColumnSetID);
1369 const std::string& account_id = secondary_accounts[i];
1370 views::Label* account_label = new views::Label(
1371 base::ASCIIToUTF16(delegate_->GetAccountDisplayName(account_id)));
1372 account_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1373 layout->AddView(account_label);
1374 views::View* delete_button = CreateDeleteButton();
1375 delete_button_to_account_id_[delete_button] = account_id;
1376 layout->AddView(delete_button);
1377 }
1378
1379 scroll_content()->SizeToPreferredSize();
1380 scroller()->Layout();
1381 }
1382
1383 views::View* AccountsDetailedView::CreateDeleteButton() {
1384 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
1385 views::ImageButton* delete_button = new views::ImageButton(this);
1386 delete_button->SetImage(views::Button::STATE_NORMAL,
1387 rb.GetImageNamed(IDR_CLOSE_2).ToImageSkia());
1388 delete_button->SetImage(views::Button::STATE_HOVERED,
1389 rb.GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
1390 delete_button->SetImage(views::Button::STATE_PRESSED,
1391 rb.GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
1392 return delete_button;
1393 }
1394
1095 } // namespace tray 1395 } // namespace tray
1096 1396
1097 TrayUser::TrayUser(SystemTray* system_tray, MultiProfileIndex index) 1397 TrayUser::TrayUser(SystemTray* system_tray, MultiProfileIndex index)
1098 : SystemTrayItem(system_tray), 1398 : SystemTrayItem(system_tray),
1099 multiprofile_index_(index), 1399 multiprofile_index_(index),
1100 user_(NULL), 1400 user_(NULL),
1101 layout_view_(NULL), 1401 layout_view_(NULL),
1102 avatar_(NULL), 1402 avatar_(NULL),
1103 label_(NULL) { 1403 label_(NULL) {
1104 Shell::GetInstance()->system_tray_notifier()->AddUserObserver(this); 1404 Shell::GetInstance()->system_tray_notifier()->AddUserObserver(this);
(...skipping 22 matching lines...) Expand all
1127 return user_->GetBoundsInScreenOfUserButtonForTest(); 1427 return user_->GetBoundsInScreenOfUserButtonForTest();
1128 } 1428 }
1129 1429
1130 void TrayUser::UpdateAfterLoginStatusChangeForTest(user::LoginStatus status) { 1430 void TrayUser::UpdateAfterLoginStatusChangeForTest(user::LoginStatus status) {
1131 UpdateAfterLoginStatusChange(status); 1431 UpdateAfterLoginStatusChange(status);
1132 } 1432 }
1133 1433
1134 views::View* TrayUser::CreateTrayView(user::LoginStatus status) { 1434 views::View* TrayUser::CreateTrayView(user::LoginStatus status) {
1135 CHECK(layout_view_ == NULL); 1435 CHECK(layout_view_ == NULL);
1136 1436
1137 layout_view_ = new views::View(); 1437 layout_view_ = new views::View;
1138 layout_view_->SetLayoutManager( 1438 layout_view_->SetLayoutManager(
1139 new views::BoxLayout(views::BoxLayout::kHorizontal, 1439 new views::BoxLayout(views::BoxLayout::kHorizontal,
1140 0, 0, kUserLabelToIconPadding)); 1440 0, 0, kUserLabelToIconPadding));
1141 UpdateAfterLoginStatusChange(status); 1441 UpdateAfterLoginStatusChange(status);
1142 return layout_view_; 1442 return layout_view_;
1143 } 1443 }
1144 1444
1145 views::View* TrayUser::CreateDefaultView(user::LoginStatus status) { 1445 views::View* TrayUser::CreateDefaultView(user::LoginStatus status) {
1146 if (status == user::LOGGED_IN_NONE) 1446 if (status == user::LOGGED_IN_NONE)
1147 return NULL; 1447 return NULL;
1148 const SessionStateDelegate* session_state_delegate = 1448 const SessionStateDelegate* session_state_delegate =
1149 Shell::GetInstance()->session_state_delegate(); 1449 Shell::GetInstance()->session_state_delegate();
1150 1450
1151 // If the screen is locked show only the currently active user. 1451 // If the screen is locked show only the currently active user.
1152 if (multiprofile_index_ && session_state_delegate->IsUserSessionBlocked()) 1452 if (multiprofile_index_ && session_state_delegate->IsUserSessionBlocked())
1153 return NULL; 1453 return NULL;
1154 1454
1155 CHECK(user_ == NULL); 1455 CHECK(user_ == NULL);
1156 1456
1157 int logged_in_users = session_state_delegate->NumberOfLoggedInUsers(); 1457 int logged_in_users = session_state_delegate->NumberOfLoggedInUsers();
1158 1458
1159 // Do not show more UserView's then there are logged in users. 1459 // Do not show more UserView's then there are logged in users.
1160 if (multiprofile_index_ >= logged_in_users) 1460 if (multiprofile_index_ >= logged_in_users)
1161 return NULL; 1461 return NULL;
1162 1462
1163 user_ = new tray::UserView(this, status, multiprofile_index_); 1463 user_ = new tray::UserView(this, status, multiprofile_index_, false);
1164 return user_; 1464 return user_;
1165 } 1465 }
1166 1466
1167 views::View* TrayUser::CreateDetailedView(user::LoginStatus status) { 1467 views::View* TrayUser::CreateDetailedView(user::LoginStatus status) {
1168 return NULL; 1468 return new tray::AccountsDetailedView(this, status);
1169 } 1469 }
1170 1470
1171 void TrayUser::DestroyTrayView() { 1471 void TrayUser::DestroyTrayView() {
1172 layout_view_ = NULL; 1472 layout_view_ = NULL;
1173 avatar_ = NULL; 1473 avatar_ = NULL;
1174 label_ = NULL; 1474 label_ = NULL;
1175 } 1475 }
1176 1476
1177 void TrayUser::DestroyDefaultView() { 1477 void TrayUser::DestroyDefaultView() {
1178 user_ = NULL; 1478 user_ = NULL;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 internal::GetRootWindowController( 1660 internal::GetRootWindowController(
1361 system_tray()->GetWidget()->GetNativeWindow()->GetRootWindow()); 1661 system_tray()->GetWidget()->GetNativeWindow()->GetRootWindow());
1362 if (controller && controller->shelf()) { 1662 if (controller && controller->shelf()) {
1363 UpdateAfterShelfAlignmentChange( 1663 UpdateAfterShelfAlignmentChange(
1364 controller->GetShelfLayoutManager()->GetAlignment()); 1664 controller->GetShelfLayoutManager()->GetAlignment());
1365 } 1665 }
1366 } 1666 }
1367 1667
1368 } // namespace internal 1668 } // namespace internal
1369 } // namespace ash 1669 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698