don't pretend to support dbus on windows in dbus_export.h
[chromium-blink-merge.git] / ash / system / user / tray_user.cc
blobcb8629877e9f1755624a3f4b757d9261cdd1e749
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
3 // found in the LICENSE file.
5 #include "ash/system/user/tray_user.h"
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/session/session_state_delegate.h"
10 #include "ash/shelf/shelf_layout_manager.h"
11 #include "ash/shell_delegate.h"
12 #include "ash/system/tray/system_tray.h"
13 #include "ash/system/tray/system_tray_delegate.h"
14 #include "ash/system/tray/system_tray_notifier.h"
15 #include "ash/system/tray/tray_constants.h"
16 #include "ash/system/tray/tray_item_view.h"
17 #include "ash/system/tray/tray_utils.h"
18 #include "ash/system/user/accounts_detailed_view.h"
19 #include "ash/system/user/rounded_image_view.h"
20 #include "ash/system/user/user_view.h"
21 #include "base/logging.h"
22 #include "base/strings/string16.h"
23 #include "components/user_manager/user_info.h"
24 #include "grit/ash_strings.h"
25 #include "ui/aura/window.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/gfx/image/image.h"
28 #include "ui/views/border.h"
29 #include "ui/views/controls/label.h"
30 #include "ui/views/layout/box_layout.h"
31 #include "ui/views/view.h"
32 #include "ui/views/widget/widget.h"
34 namespace {
36 const int kUserLabelToIconPadding = 5;
38 } // namespace
40 namespace ash {
42 TrayUser::TrayUser(SystemTray* system_tray, MultiProfileIndex index)
43 : SystemTrayItem(system_tray),
44 multiprofile_index_(index),
45 user_(NULL),
46 layout_view_(NULL),
47 avatar_(NULL),
48 label_(NULL) {
49 Shell::GetInstance()->system_tray_notifier()->AddUserObserver(this);
52 TrayUser::~TrayUser() {
53 Shell::GetInstance()->system_tray_notifier()->RemoveUserObserver(this);
56 TrayUser::TestState TrayUser::GetStateForTest() const {
57 if (!user_)
58 return HIDDEN;
59 return user_->GetStateForTest();
62 gfx::Size TrayUser::GetLayoutSizeForTest() const {
63 if (!layout_view_) {
64 return gfx::Size(0, 0);
65 } else {
66 return layout_view_->size();
70 gfx::Rect TrayUser::GetUserPanelBoundsInScreenForTest() const {
71 DCHECK(user_);
72 return user_->GetBoundsInScreenOfUserButtonForTest();
75 void TrayUser::UpdateAfterLoginStatusChangeForTest(user::LoginStatus status) {
76 UpdateAfterLoginStatusChange(status);
79 views::View* TrayUser::CreateTrayView(user::LoginStatus status) {
80 CHECK(layout_view_ == NULL);
82 layout_view_ = new views::View;
83 layout_view_->SetLayoutManager(
84 new views::BoxLayout(views::BoxLayout::kHorizontal,
85 0, 0, kUserLabelToIconPadding));
86 UpdateAfterLoginStatusChange(status);
87 return layout_view_;
90 views::View* TrayUser::CreateDefaultView(user::LoginStatus status) {
91 if (status == user::LOGGED_IN_NONE)
92 return NULL;
93 const SessionStateDelegate* session_state_delegate =
94 Shell::GetInstance()->session_state_delegate();
96 // If the screen is locked show only the currently active user.
97 if (multiprofile_index_ && session_state_delegate->IsUserSessionBlocked())
98 return NULL;
100 CHECK(user_ == NULL);
102 int logged_in_users = session_state_delegate->NumberOfLoggedInUsers();
104 // Do not show more UserView's then there are logged in users.
105 if (multiprofile_index_ >= logged_in_users)
106 return NULL;
108 user_ = new tray::UserView(this, status, multiprofile_index_, false);
109 return user_;
112 views::View* TrayUser::CreateDetailedView(user::LoginStatus status) {
113 return new tray::AccountsDetailedView(this, status);
116 void TrayUser::DestroyTrayView() {
117 layout_view_ = NULL;
118 avatar_ = NULL;
119 label_ = NULL;
122 void TrayUser::DestroyDefaultView() {
123 user_ = NULL;
126 void TrayUser::DestroyDetailedView() {
129 void TrayUser::UpdateAfterLoginStatusChange(user::LoginStatus status) {
130 // Only the active user is represented in the tray.
131 if (!layout_view_)
132 return;
133 if (GetTrayIndex() > 0)
134 return;
135 bool need_label = false;
136 bool need_avatar = false;
137 switch (status) {
138 case user::LOGGED_IN_LOCKED:
139 case user::LOGGED_IN_USER:
140 case user::LOGGED_IN_OWNER:
141 case user::LOGGED_IN_PUBLIC:
142 need_avatar = true;
143 break;
144 case user::LOGGED_IN_SUPERVISED:
145 need_avatar = true;
146 need_label = true;
147 break;
148 case user::LOGGED_IN_GUEST:
149 need_label = true;
150 break;
151 case user::LOGGED_IN_RETAIL_MODE:
152 case user::LOGGED_IN_KIOSK_APP:
153 case user::LOGGED_IN_NONE:
154 break;
157 if ((need_avatar != (avatar_ != NULL)) ||
158 (need_label != (label_ != NULL))) {
159 layout_view_->RemoveAllChildViews(true);
160 if (need_label) {
161 label_ = new views::Label;
162 SetupLabelForTray(label_);
163 layout_view_->AddChildView(label_);
164 } else {
165 label_ = NULL;
167 if (need_avatar) {
168 avatar_ = new tray::RoundedImageView(kTrayAvatarCornerRadius, true);
169 layout_view_->AddChildView(avatar_);
170 } else {
171 avatar_ = NULL;
175 if (status == user::LOGGED_IN_SUPERVISED) {
176 label_->SetText(
177 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SUPERVISED_LABEL));
178 } else if (status == user::LOGGED_IN_GUEST) {
179 label_->SetText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_GUEST_LABEL));
182 if (avatar_) {
183 avatar_->SetCornerRadii(
184 0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius, 0);
185 avatar_->SetBorder(views::Border::NullBorder());
187 UpdateAvatarImage(status);
189 // Update layout after setting label_ and avatar_ with new login status.
190 UpdateLayoutOfItem();
193 void TrayUser::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
194 // Inactive users won't have a layout.
195 if (!layout_view_)
196 return;
197 if (alignment == SHELF_ALIGNMENT_BOTTOM ||
198 alignment == SHELF_ALIGNMENT_TOP) {
199 if (avatar_) {
200 avatar_->SetBorder(views::Border::NullBorder());
201 avatar_->SetCornerRadii(
202 0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius, 0);
204 if (label_) {
205 // If label_ hasn't figured out its size yet, do that first.
206 if (label_->GetContentsBounds().height() == 0)
207 label_->SizeToPreferredSize();
208 int height = label_->GetContentsBounds().height();
209 int vertical_pad = (kTrayItemSize - height) / 2;
210 int remainder = height % 2;
211 label_->SetBorder(views::Border::CreateEmptyBorder(
212 vertical_pad + remainder,
213 kTrayLabelItemHorizontalPaddingBottomAlignment,
214 vertical_pad,
215 kTrayLabelItemHorizontalPaddingBottomAlignment));
217 layout_view_->SetLayoutManager(
218 new views::BoxLayout(views::BoxLayout::kHorizontal,
219 0, 0, kUserLabelToIconPadding));
220 } else {
221 if (avatar_) {
222 avatar_->SetBorder(views::Border::NullBorder());
223 avatar_->SetCornerRadii(
224 0, 0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius);
226 if (label_) {
227 label_->SetBorder(views::Border::CreateEmptyBorder(
228 kTrayLabelItemVerticalPaddingVerticalAlignment,
229 kTrayLabelItemHorizontalPaddingBottomAlignment,
230 kTrayLabelItemVerticalPaddingVerticalAlignment,
231 kTrayLabelItemHorizontalPaddingBottomAlignment));
233 layout_view_->SetLayoutManager(
234 new views::BoxLayout(views::BoxLayout::kVertical,
235 0, 0, kUserLabelToIconPadding));
239 void TrayUser::OnUserUpdate() {
240 UpdateAvatarImage(Shell::GetInstance()->system_tray_delegate()->
241 GetUserLoginStatus());
244 void TrayUser::OnUserAddedToSession() {
245 SessionStateDelegate* session_state_delegate =
246 Shell::GetInstance()->session_state_delegate();
247 // Only create views for user items which are logged in.
248 if (GetTrayIndex() >= session_state_delegate->NumberOfLoggedInUsers())
249 return;
251 // Enforce a layout change that newly added items become visible.
252 UpdateLayoutOfItem();
254 // Update the user item.
255 UpdateAvatarImage(
256 Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus());
259 void TrayUser::UpdateAvatarImage(user::LoginStatus status) {
260 SessionStateDelegate* session_state_delegate =
261 Shell::GetInstance()->session_state_delegate();
262 if (!avatar_ ||
263 GetTrayIndex() >= session_state_delegate->NumberOfLoggedInUsers())
264 return;
266 content::BrowserContext* context = session_state_delegate->
267 GetBrowserContextByIndex(GetTrayIndex());
268 avatar_->SetImage(session_state_delegate->GetUserInfo(context)->GetImage(),
269 gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
271 // Unit tests might come here with no images for some users.
272 if (avatar_->size().IsEmpty())
273 avatar_->SetSize(gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
276 MultiProfileIndex TrayUser::GetTrayIndex() {
277 Shell* shell = Shell::GetInstance();
278 // If multi profile is not enabled we can use the normal index.
279 if (!shell->delegate()->IsMultiProfilesEnabled())
280 return multiprofile_index_;
281 // In case of multi profile we need to mirror the indices since the system
282 // tray items are in the reverse order then the menu items.
283 return shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers() -
284 1 - multiprofile_index_;
287 void TrayUser::UpdateLayoutOfItem() {
288 RootWindowController* controller = GetRootWindowController(
289 system_tray()->GetWidget()->GetNativeWindow()->GetRootWindow());
290 if (controller && controller->shelf()) {
291 UpdateAfterShelfAlignmentChange(
292 controller->GetShelfLayoutManager()->GetAlignment());
296 } // namespace ash