1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// found in the LICENSE file.
4a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/user/user_view.h"
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
7a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <algorithm>
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/multi_profile_uma.h"
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/popup_message.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/session/session_state_delegate.h"
12a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/shell.h"
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/shell_delegate.h"
14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/tray/system_tray.h"
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/tray/system_tray_delegate.h"
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/tray/tray_popup_label_button.h"
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/tray/tray_popup_label_button_border.h"
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/user/button_from_view.h"
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/user/config.h"
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/user/rounded_image_view.h"
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/system/user/user_card_view.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/user_manager/user_info.h"
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "grit/ash_resources.h"
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "grit/ash_strings.h"
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/base/l10n/l10n_util.h"
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/base/resource/resource_bundle.h"
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/views/layout/fill_layout.h"
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/views/painter.h"
29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/wm/core/shadow_types.h"
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace ash {
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace tray {
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace {
35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kPublicAccountLogoutButtonBorderImagesNormal[] = {
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_NORMAL_BACKGROUND,
39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_NORMAL_BACKGROUND,
40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_NORMAL_BACKGROUND,
42a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_NORMAL_BACKGROUND,
43a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_NORMAL_BACKGROUND,
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_NORMAL_BACKGROUND,
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kPublicAccountLogoutButtonBorderImagesHovered[] = {
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
50a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_LABEL_BUTTON_HOVER_BACKGROUND,
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    IDR_AURA_TRAY_POPUP_PUBLIC_ACCOUNT_LOGOUT_BUTTON_BORDER,
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// When a hover border is used, it is starting this many pixels before the icon
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// position.
62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kTrayUserTileHoverBorderInset = 10;
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Offsetting the popup message relative to the tray menu.
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kPopupMessageOffset = 25;
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Switch to a user with the given |user_index|.
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid SwitchUser(ash::MultiProfileIndex user_index) {
69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Do not switch users when the log screen is presented.
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (ash::Shell::GetInstance()
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          ->session_state_delegate()
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          ->IsUserSessionBlocked())
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(user_index > 0);
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ash::SessionStateDelegate* delegate =
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ash::Shell::GetInstance()->session_state_delegate();
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ash::MultiProfileUMA::RecordSwitchActiveUser(
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ash::MultiProfileUMA::SWITCH_ACTIVE_USER_BY_TRAY);
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  delegate->SwitchActiveUser(delegate->GetUserInfo(user_index)->GetUserID());
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
83a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass LogoutButton : public TrayPopupLabelButton {
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public:
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // If |placeholder| is true, button is used as placeholder. That means that
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // button is inactive and is not painted, but consume the same ammount of
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // space, as if it was painted.
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  LogoutButton(views::ButtonListener* listener,
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch               const base::string16& text,
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch               bool placeholder)
91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      : TrayPopupLabelButton(listener, text), placeholder_(placeholder) {
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SetEnabled(!placeholder_);
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual ~LogoutButton() {}
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch private:
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void Paint(gfx::Canvas* canvas,
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     const views::CullSet& cull_set) OVERRIDE {
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Just skip paint if this button used as a placeholder.
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!placeholder_)
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      TrayPopupLabelButton::Paint(canvas, cull_set);
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  bool placeholder_;
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DISALLOW_COPY_AND_ASSIGN(LogoutButton);
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass UserViewMouseWatcherHost : public views::MouseWatcherHost {
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public:
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  explicit UserViewMouseWatcherHost(const gfx::Rect& screen_area)
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      : screen_area_(screen_area) {}
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual ~UserViewMouseWatcherHost() {}
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Implementation of MouseWatcherHost.
116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual bool Contains(const gfx::Point& screen_point,
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                        views::MouseWatcherHost::MouseEventType type) OVERRIDE {
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return screen_area_.Contains(screen_point);
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch private:
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect screen_area_;
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DISALLOW_COPY_AND_ASSIGN(UserViewMouseWatcherHost);
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// The menu item view which gets shown when the user clicks in multi profile
128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// mode onto the user item.
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass AddUserView : public views::View {
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public:
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The |owner| is the view for which this view gets created.
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddUserView(ButtonFromView* owner);
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  virtual ~AddUserView();
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Get the anchor view for a message.
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::View* anchor() { return anchor_; }
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch private:
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Overridden from views::View.
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE;
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create the additional client content for this item.
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  void AddContent();
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // This is the content we create and show.
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::View* add_user_;
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // This is the owner view of this item.
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ButtonFromView* owner_;
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The anchor view for targetted bubble messages.
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::View* anchor_;
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DISALLOW_COPY_AND_ASSIGN(AddUserView);
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
157a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochAddUserView::AddUserView(ButtonFromView* owner)
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : add_user_(NULL), owner_(owner), anchor_(NULL) {
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddContent();
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  owner_->ForceBorderVisible(true);
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
162a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
163a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochAddUserView::~AddUserView() {
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  owner_->ForceBorderVisible(false);
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size AddUserView::GetPreferredSize() const {
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return owner_->bounds().size();
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid AddUserView::AddContent() {
172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetLayoutManager(new views::FillLayout());
173a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  set_background(views::Background::CreateSolidBackground(kBackgroundColor));
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_user_ = new views::View;
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_user_->SetBorder(views::Border::CreateEmptyBorder(
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      0, kTrayUserTileHoverBorderInset, 0, 0));
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_user_->SetLayoutManager(new views::BoxLayout(
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems));
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddChildViewAt(add_user_, 0);
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Add the [+] icon which is also the anchor for messages.
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  RoundedImageView* icon = new RoundedImageView(kTrayAvatarCornerRadius, true);
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  anchor_ = icon;
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  icon->SetImage(*ui::ResourceBundle::GetSharedInstance()
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      .GetImageNamed(IDR_AURA_UBER_TRAY_ADD_MULTIPROFILE_USER)
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      .ToImageSkia(),
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_user_->AddChildView(icon);
191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
192a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Add the command text.
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::Label* command_label = new views::Label(
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT));
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  command_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
196a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_user_->AddChildView(command_label);
197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
199a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace
200a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
201a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochUserView::UserView(SystemTrayItem* owner,
202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   user::LoginStatus login,
203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   MultiProfileIndex index,
204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   bool for_detailed_view)
205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : multiprofile_index_(index),
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      user_card_view_(NULL),
207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      owner_(owner),
208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      is_user_card_button_(false),
209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      logout_button_(NULL),
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      add_user_enabled_(true),
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      for_detailed_view_(for_detailed_view),
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      focus_manager_(NULL) {
213a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CHECK_NE(user::LOGGED_IN_NONE, login);
214a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!index) {
215a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Only the logged in user will have a background. All other users will have
216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // to allow the TrayPopupContainer highlighting the menu line.
217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    set_background(views::Background::CreateSolidBackground(
218a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        login == user::LOGGED_IN_PUBLIC ? kPublicAccountBackgroundColor
219a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        : kBackgroundColor));
220a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
221a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetLayoutManager(new views::BoxLayout(
222a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems));
223a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The logout button must be added before the user card so that the user card
224a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // can correctly calculate the remaining available width.
225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Note that only the current multiprofile user gets a button.
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!multiprofile_index_)
227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    AddLogoutButton(login);
228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddUserCard(login);
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
231116680a4aac90f2aa7413d9095a592090648e557Ben MurdochUserView::~UserView() {
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RemoveAddUserMenuOption();
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
234a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UserView::MouseMovedOutOfHost() {
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RemoveAddUserMenuOption();
237a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
238a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
239a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochTrayUser::TestState UserView::GetStateForTest() const {
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (add_menu_option_.get()) {
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return add_user_enabled_ ? TrayUser::ACTIVE : TrayUser::ACTIVE_BUT_DISABLED;
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!is_user_card_button_)
245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return TrayUser::SHOWN;
246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return static_cast<ButtonFromView*>(user_card_view_)->is_hovered_for_test()
248a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch             ? TrayUser::HOVERED
249a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch             : TrayUser::SHOWN;
250a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
252a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochgfx::Rect UserView::GetBoundsInScreenOfUserButtonForTest() {
253a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(user_card_view_);
254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return user_card_view_->GetBoundsInScreen();
255a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size UserView::GetPreferredSize() const {
258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Size size = views::View::GetPreferredSize();
259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Only the active user panel will be forced to a certain height.
260a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!multiprofile_index_) {
261a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    size.set_height(
262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        std::max(size.height(), kTrayPopupItemHeight + GetInsets().height()));
263a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
264a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return size;
265a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
266a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int UserView::GetHeightForWidth(int width) const {
268a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return GetPreferredSize().height();
269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UserView::Layout() {
272a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect contents_area(GetContentsBounds());
273a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (user_card_view_ && logout_button_) {
274a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Give the logout button the space it requests.
275a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    gfx::Rect logout_area = contents_area;
276a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    logout_area.ClampToCenteredSize(logout_button_->GetPreferredSize());
277a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    logout_area.set_x(contents_area.right() - logout_area.width());
278a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
279a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Give the remaining space to the user card.
280a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    gfx::Rect user_card_area = contents_area;
281a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int remaining_width = contents_area.width() - logout_area.width();
282a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (IsMultiProfileSupportedAndUserActive() ||
283a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        IsMultiAccountSupportedAndUserActive()) {
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // In multiprofile/multiaccount case |user_card_view_| and
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // |logout_button_| have to have the same height.
286a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      int y = std::min(user_card_area.y(), logout_area.y());
287a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      int height = std::max(user_card_area.height(), logout_area.height());
288a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      logout_area.set_y(y);
289a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      logout_area.set_height(height);
290a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      user_card_area.set_y(y);
291a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      user_card_area.set_height(height);
292a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
293a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // In multiprofile mode we have also to increase the size of the card by
294a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // the size of the border to make it overlap with the logout button.
295a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      user_card_area.set_width(std::max(0, remaining_width + 1));
296a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
297a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // To make the logout button symmetrical with the user card we also make
298a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // the button longer by the same size the hover area in front of the icon
299a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // got inset.
300a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      logout_area.set_width(logout_area.width() +
301a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            kTrayUserTileHoverBorderInset);
302a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else {
303a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // In all other modes we have to make sure that there is enough spacing
304a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // between the two.
305a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      remaining_width -= kTrayPopupPaddingBetweenItems;
306a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
307a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    user_card_area.set_width(remaining_width);
308a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    user_card_view_->SetBoundsRect(user_card_area);
309a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    logout_button_->SetBoundsRect(logout_area);
310a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (user_card_view_) {
311a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    user_card_view_->SetBoundsRect(contents_area);
312a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (logout_button_) {
313a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    logout_button_->SetBoundsRect(contents_area);
314a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
315a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
316a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
317a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UserView::ButtonPressed(views::Button* sender, const ui::Event& event) {
318a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (sender == logout_button_) {
319a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Shell::GetInstance()->metrics()->RecordUserMetricsAction(
320a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        ash::UMA_STATUS_AREA_SIGN_OUT);
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RemoveAddUserMenuOption();
322a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Shell::GetInstance()->system_tray_delegate()->SignOut();
323a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (sender == user_card_view_ && !multiprofile_index_ &&
324a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch             IsMultiAccountSupportedAndUserActive()) {
325a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    owner_->TransitionDetailedView();
326a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (sender == user_card_view_ &&
327a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch             IsMultiProfileSupportedAndUserActive()) {
328a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!multiprofile_index_) {
329a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ToggleAddUserMenuOption();
330a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else {
331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      RemoveAddUserMenuOption();
332a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SwitchUser(multiprofile_index_);
333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // Since the user list is about to change the system menu should get
334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // closed.
335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      owner_->system_tray()->CloseSystemBubble();
336a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
337a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (add_menu_option_.get() &&
338a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch             sender == add_menu_option_->GetContentsView()) {
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RemoveAddUserMenuOption();
340a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Let the user add another account to the session.
341a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    MultiProfileUMA::RecordSigninUser(MultiProfileUMA::SIGNIN_USER_BY_TRAY);
342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Shell::GetInstance()->system_tray_delegate()->ShowUserLogin();
343a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    owner_->system_tray()->CloseSystemBubble();
344a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else {
345a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    NOTREACHED();
346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
348a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
349116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserView::OnWillChangeFocus(View* focused_before, View* focused_now) {
350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (focused_now)
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RemoveAddUserMenuOption();
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
354116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserView::OnDidChangeFocus(View* focused_before, View* focused_now) {
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Nothing to do here.
356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
358a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UserView::AddLogoutButton(user::LoginStatus login) {
359a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const base::string16 title =
360a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      user::GetLocalizedSignOutStringForStatus(login, true);
361a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  TrayPopupLabelButton* logout_button =
362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new LogoutButton(this, title, for_detailed_view_);
363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  logout_button->SetAccessibleName(title);
364a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  logout_button_ = logout_button;
365a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // In public account mode, the logout button border has a custom color.
366a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (login == user::LOGGED_IN_PUBLIC) {
367a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    scoped_ptr<TrayPopupLabelButtonBorder> border(
368a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        new TrayPopupLabelButtonBorder());
369a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    border->SetPainter(false,
370a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       views::Button::STATE_NORMAL,
371a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       views::Painter::CreateImageGridPainter(
372a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           kPublicAccountLogoutButtonBorderImagesNormal));
373a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    border->SetPainter(false,
374a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       views::Button::STATE_HOVERED,
375a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       views::Painter::CreateImageGridPainter(
376a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           kPublicAccountLogoutButtonBorderImagesHovered));
377a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    border->SetPainter(false,
378a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       views::Button::STATE_PRESSED,
379a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       views::Painter::CreateImageGridPainter(
380a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           kPublicAccountLogoutButtonBorderImagesHovered));
381a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    logout_button_->SetBorder(border.PassAs<views::Border>());
382a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
383a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddChildView(logout_button_);
384a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
385a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
386a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UserView::AddUserCard(user::LoginStatus login) {
387a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Add padding around the panel.
388a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetBorder(views::Border::CreateEmptyBorder(kTrayPopupUserCardVerticalPadding,
389a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             kTrayPopupPaddingHorizontal,
390a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             kTrayPopupUserCardVerticalPadding,
391a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             kTrayPopupPaddingHorizontal));
392a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
393a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::TrayBubbleView* bubble_view =
394a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      owner_->system_tray()->GetSystemBubble()->bubble_view();
395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int max_card_width =
396a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      bubble_view->GetMaximumSize().width() -
397a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (2 * kTrayPopupPaddingHorizontal + kTrayPopupPaddingBetweenItems);
398a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (logout_button_)
399a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    max_card_width -= logout_button_->GetPreferredSize().width();
400a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  user_card_view_ =
401a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new UserCardView(login, max_card_width, multiprofile_index_);
40203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // The entry is clickable when no system modal dialog is open and one of the
40303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // multi user options is active.
40403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool clickable = !Shell::GetInstance()->IsSystemModalWindowOpen() &&
40503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   (IsMultiProfileSupportedAndUserActive() ||
40603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                    IsMultiAccountSupportedAndUserActive());
407a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (clickable) {
408a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // To allow the border to start before the icon, reduce the size before and
409a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // add an inset to the icon to get the spacing.
410a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!multiprofile_index_) {
411a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SetBorder(views::Border::CreateEmptyBorder(
412a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          kTrayPopupUserCardVerticalPadding,
413a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset,
414a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          kTrayPopupUserCardVerticalPadding,
415a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          kTrayPopupPaddingHorizontal));
416a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      user_card_view_->SetBorder(views::Border::CreateEmptyBorder(
417a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          0, kTrayUserTileHoverBorderInset, 0, 0));
418a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    gfx::Insets insets = gfx::Insets(1, 1, 1, 1);
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    views::View* contents_view = user_card_view_;
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ButtonFromView* button = NULL;
422a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!for_detailed_view_) {
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (multiprofile_index_) {
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // Since the activation border needs to be drawn around the tile, we
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // have to put the tile into another view which fills the menu panel,
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // but keeping the offsets of the content.
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        contents_view = new views::View();
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        contents_view->SetBorder(views::Border::CreateEmptyBorder(
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            kTrayPopupUserCardVerticalPadding,
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            kTrayPopupPaddingHorizontal,
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            kTrayPopupUserCardVerticalPadding,
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            kTrayPopupPaddingHorizontal));
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        contents_view->SetLayoutManager(new views::FillLayout());
434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        SetBorder(views::Border::CreateEmptyBorder(0, 0, 0, 0));
435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        contents_view->AddChildView(user_card_view_);
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        insets = gfx::Insets(1, 1, 1, 3);
437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      button = new ButtonFromView(contents_view,
439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  this,
440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  !multiprofile_index_,
441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  insets);
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // TODO(skuhne): For accessibility we need to call |SetAccessibleName|
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // with a useful name (string freeze for M37 has passed).
444a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else {
445a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // We want user card for detailed view to have exactly the same look
446a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      // as user card for default view. That's why we wrap it in a button
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // without click listener and special hover behavior.
448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      button = new ButtonFromView(contents_view, NULL, false, insets);
449a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // A click on the button should not trigger a focus change.
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    button->set_request_focus_on_press(false);
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    user_card_view_ = button;
453a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    is_user_card_button_ = true;
454a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
455a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddChildViewAt(user_card_view_, 0);
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Card for supervised user can consume more space than currently
457a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // available. In that case we should increase system bubble's width.
458a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (login == user::LOGGED_IN_PUBLIC)
459a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    bubble_view->SetWidth(GetPreferredSize().width());
460a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
461a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
462a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UserView::ToggleAddUserMenuOption() {
463a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (add_menu_option_.get()) {
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RemoveAddUserMenuOption();
465a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
466a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
467a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
468a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Note: We do not need to install a global event handler to delete this
469a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // item since it will destroyed automatically before the menu / user menu item
470a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // gets destroyed..
471a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_.reset(new views::Widget);
472a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::Widget::InitParams params;
473a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.type = views::Widget::InitParams::TYPE_TOOLTIP;
474a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.keep_on_top = true;
475a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.context = this->GetWidget()->GetNativeWindow();
476a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.accept_events = true;
477a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
478a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
479a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->Init(params);
480a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->SetOpacity(0xFF);
481a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->GetNativeWindow()->set_owned_by_parent(false);
482a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetShadowType(add_menu_option_->GetNativeView(), wm::SHADOW_TYPE_NONE);
483a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
484a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Position it below our user card.
485a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect bounds = user_card_view_->GetBoundsInScreen();
486a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  bounds.set_y(bounds.y() + bounds.height());
487a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->SetBounds(bounds);
488a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
489a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Show the content.
490a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->SetAlwaysOnTop(true);
491a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->Show();
492a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
493a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddUserView* add_user_view =
494a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new AddUserView(static_cast<ButtonFromView*>(user_card_view_));
495a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
496a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const SessionStateDelegate* delegate =
497a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      Shell::GetInstance()->session_state_delegate();
4986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SessionStateDelegate::AddUserError add_user_error;
5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  add_user_enabled_ = delegate->CanAddUserToMultiProfile(&add_user_error);
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ButtonFromView* button = new ButtonFromView(add_user_view,
5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              add_user_enabled_ ? this : NULL,
5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              add_user_enabled_,
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              gfx::Insets(1, 1, 1, 1));
506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  button->set_request_focus_on_press(false);
507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  button->SetAccessibleName(
508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT));
509a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  button->ForceBorderVisible(true);
510a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  add_menu_option_->SetContentsView(button);
511a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (add_user_enabled_) {
5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // We activate the entry automatically if invoked with focus.
5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (user_card_view_->HasFocus()) {
5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      button->GetFocusManager()->SetFocusedView(button);
5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      user_card_view_->GetFocusManager()->SetFocusedView(button);
5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
519a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int message_id = 0;
5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    switch (add_user_error) {
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case SessionStateDelegate::ADD_USER_ERROR_NOT_ALLOWED_PRIMARY_USER:
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        message_id = IDS_ASH_STATUS_TRAY_MESSAGE_NOT_ALLOWED_PRIMARY_USER;
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case SessionStateDelegate::ADD_USER_ERROR_MAXIMUM_USERS_REACHED:
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        message_id = IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER;
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case SessionStateDelegate::ADD_USER_ERROR_OUT_OF_USERS:
5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        message_id = IDS_ASH_STATUS_TRAY_MESSAGE_OUT_OF_USERS;
5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      default:
5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        NOTREACHED() << "Unknown adding user error " << add_user_error;
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
5346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
535a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    popup_message_.reset(new PopupMessage(
536a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER),
5376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        bundle.GetLocalizedString(message_id),
538a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        PopupMessage::ICON_WARNING,
539a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        add_user_view->anchor(),
540a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        views::BubbleBorder::TOP_LEFT,
541a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        gfx::Size(parent()->bounds().width() - kPopupMessageOffset, 0),
542a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        2 * kPopupMessageOffset));
543a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
544a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Find the screen area which encloses both elements and sets then a mouse
545a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // watcher which will close the "menu".
546a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect area = user_card_view_->GetBoundsInScreen();
547a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  area.set_height(2 * area.height());
548a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  mouse_watcher_.reset(
549a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new views::MouseWatcher(new UserViewMouseWatcherHost(area), this));
550a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  mouse_watcher_->Start();
551116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Install a listener to focus changes so that we can remove the card when
552116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the focus gets changed. When called through the destruction of the bubble,
553116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the FocusManager cannot be determined anymore and we remember it here.
554116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  focus_manager_ = user_card_view_->GetFocusManager();
555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  focus_manager_->AddFocusChangeListener(this);
556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
557116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
558116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserView::RemoveAddUserMenuOption() {
559116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!add_menu_option_.get())
560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  focus_manager_->RemoveFocusChangeListener(this);
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  focus_manager_ = NULL;
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (user_card_view_->GetFocusManager())
564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    user_card_view_->GetFocusManager()->ClearFocus();
565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  popup_message_.reset();
566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  mouse_watcher_.reset();
567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  add_menu_option_.reset();
568a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
569a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
570a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace tray
571a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace ash
572