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

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

Powered by Google App Engine
This is Rietveld 408576698