blob: cb8629877e9f1755624a3f4b757d9261cdd1e749 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/user/tray_user.h"
#include "ash/ash_switches.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_state_delegate.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell_delegate.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_item_view.h"
#include "ash/system/tray/tray_utils.h"
#include "ash/system/user/accounts_detailed_view.h"
#include "ash/system/user/rounded_image_view.h"
#include "ash/system/user/user_view.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "components/user_manager/user_info.h"
#include "grit/ash_strings.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace {
const int kUserLabelToIconPadding = 5;
} // namespace
namespace ash {
TrayUser::TrayUser(SystemTray* system_tray, MultiProfileIndex index)
: SystemTrayItem(system_tray),
multiprofile_index_(index),
user_(NULL),
layout_view_(NULL),
avatar_(NULL),
label_(NULL) {
Shell::GetInstance()->system_tray_notifier()->AddUserObserver(this);
}
TrayUser::~TrayUser() {
Shell::GetInstance()->system_tray_notifier()->RemoveUserObserver(this);
}
TrayUser::TestState TrayUser::GetStateForTest() const {
if (!user_)
return HIDDEN;
return user_->GetStateForTest();
}
gfx::Size TrayUser::GetLayoutSizeForTest() const {
if (!layout_view_) {
return gfx::Size(0, 0);
} else {
return layout_view_->size();
}
}
gfx::Rect TrayUser::GetUserPanelBoundsInScreenForTest() const {
DCHECK(user_);
return user_->GetBoundsInScreenOfUserButtonForTest();
}
void TrayUser::UpdateAfterLoginStatusChangeForTest(user::LoginStatus status) {
UpdateAfterLoginStatusChange(status);
}
views::View* TrayUser::CreateTrayView(user::LoginStatus status) {
CHECK(layout_view_ == NULL);
layout_view_ = new views::View;
layout_view_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal,
0, 0, kUserLabelToIconPadding));
UpdateAfterLoginStatusChange(status);
return layout_view_;
}
views::View* TrayUser::CreateDefaultView(user::LoginStatus status) {
if (status == user::LOGGED_IN_NONE)
return NULL;
const SessionStateDelegate* session_state_delegate =
Shell::GetInstance()->session_state_delegate();
// If the screen is locked show only the currently active user.
if (multiprofile_index_ && session_state_delegate->IsUserSessionBlocked())
return NULL;
CHECK(user_ == NULL);
int logged_in_users = session_state_delegate->NumberOfLoggedInUsers();
// Do not show more UserView's then there are logged in users.
if (multiprofile_index_ >= logged_in_users)
return NULL;
user_ = new tray::UserView(this, status, multiprofile_index_, false);
return user_;
}
views::View* TrayUser::CreateDetailedView(user::LoginStatus status) {
return new tray::AccountsDetailedView(this, status);
}
void TrayUser::DestroyTrayView() {
layout_view_ = NULL;
avatar_ = NULL;
label_ = NULL;
}
void TrayUser::DestroyDefaultView() {
user_ = NULL;
}
void TrayUser::DestroyDetailedView() {
}
void TrayUser::UpdateAfterLoginStatusChange(user::LoginStatus status) {
// Only the active user is represented in the tray.
if (!layout_view_)
return;
if (GetTrayIndex() > 0)
return;
bool need_label = false;
bool need_avatar = false;
switch (status) {
case user::LOGGED_IN_LOCKED:
case user::LOGGED_IN_USER:
case user::LOGGED_IN_OWNER:
case user::LOGGED_IN_PUBLIC:
need_avatar = true;
break;
case user::LOGGED_IN_SUPERVISED:
need_avatar = true;
need_label = true;
break;
case user::LOGGED_IN_GUEST:
need_label = true;
break;
case user::LOGGED_IN_RETAIL_MODE:
case user::LOGGED_IN_KIOSK_APP:
case user::LOGGED_IN_NONE:
break;
}
if ((need_avatar != (avatar_ != NULL)) ||
(need_label != (label_ != NULL))) {
layout_view_->RemoveAllChildViews(true);
if (need_label) {
label_ = new views::Label;
SetupLabelForTray(label_);
layout_view_->AddChildView(label_);
} else {
label_ = NULL;
}
if (need_avatar) {
avatar_ = new tray::RoundedImageView(kTrayAvatarCornerRadius, true);
layout_view_->AddChildView(avatar_);
} else {
avatar_ = NULL;
}
}
if (status == user::LOGGED_IN_SUPERVISED) {
label_->SetText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SUPERVISED_LABEL));
} else if (status == user::LOGGED_IN_GUEST) {
label_->SetText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_GUEST_LABEL));
}
if (avatar_) {
avatar_->SetCornerRadii(
0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius, 0);
avatar_->SetBorder(views::Border::NullBorder());
}
UpdateAvatarImage(status);
// Update layout after setting label_ and avatar_ with new login status.
UpdateLayoutOfItem();
}
void TrayUser::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
// Inactive users won't have a layout.
if (!layout_view_)
return;
if (alignment == SHELF_ALIGNMENT_BOTTOM ||
alignment == SHELF_ALIGNMENT_TOP) {
if (avatar_) {
avatar_->SetBorder(views::Border::NullBorder());
avatar_->SetCornerRadii(
0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius, 0);
}
if (label_) {
// If label_ hasn't figured out its size yet, do that first.
if (label_->GetContentsBounds().height() == 0)
label_->SizeToPreferredSize();
int height = label_->GetContentsBounds().height();
int vertical_pad = (kTrayItemSize - height) / 2;
int remainder = height % 2;
label_->SetBorder(views::Border::CreateEmptyBorder(
vertical_pad + remainder,
kTrayLabelItemHorizontalPaddingBottomAlignment,
vertical_pad,
kTrayLabelItemHorizontalPaddingBottomAlignment));
}
layout_view_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal,
0, 0, kUserLabelToIconPadding));
} else {
if (avatar_) {
avatar_->SetBorder(views::Border::NullBorder());
avatar_->SetCornerRadii(
0, 0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius);
}
if (label_) {
label_->SetBorder(views::Border::CreateEmptyBorder(
kTrayLabelItemVerticalPaddingVerticalAlignment,
kTrayLabelItemHorizontalPaddingBottomAlignment,
kTrayLabelItemVerticalPaddingVerticalAlignment,
kTrayLabelItemHorizontalPaddingBottomAlignment));
}
layout_view_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical,
0, 0, kUserLabelToIconPadding));
}
}
void TrayUser::OnUserUpdate() {
UpdateAvatarImage(Shell::GetInstance()->system_tray_delegate()->
GetUserLoginStatus());
}
void TrayUser::OnUserAddedToSession() {
SessionStateDelegate* session_state_delegate =
Shell::GetInstance()->session_state_delegate();
// Only create views for user items which are logged in.
if (GetTrayIndex() >= session_state_delegate->NumberOfLoggedInUsers())
return;
// Enforce a layout change that newly added items become visible.
UpdateLayoutOfItem();
// Update the user item.
UpdateAvatarImage(
Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus());
}
void TrayUser::UpdateAvatarImage(user::LoginStatus status) {
SessionStateDelegate* session_state_delegate =
Shell::GetInstance()->session_state_delegate();
if (!avatar_ ||
GetTrayIndex() >= session_state_delegate->NumberOfLoggedInUsers())
return;
content::BrowserContext* context = session_state_delegate->
GetBrowserContextByIndex(GetTrayIndex());
avatar_->SetImage(session_state_delegate->GetUserInfo(context)->GetImage(),
gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
// Unit tests might come here with no images for some users.
if (avatar_->size().IsEmpty())
avatar_->SetSize(gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
}
MultiProfileIndex TrayUser::GetTrayIndex() {
Shell* shell = Shell::GetInstance();
// If multi profile is not enabled we can use the normal index.
if (!shell->delegate()->IsMultiProfilesEnabled())
return multiprofile_index_;
// In case of multi profile we need to mirror the indices since the system
// tray items are in the reverse order then the menu items.
return shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers() -
1 - multiprofile_index_;
}
void TrayUser::UpdateLayoutOfItem() {
RootWindowController* controller = GetRootWindowController(
system_tray()->GetWidget()->GetNativeWindow()->GetRootWindow());
if (controller && controller->shelf()) {
UpdateAfterShelfAlignmentChange(
controller->GetShelfLayoutManager()->GetAlignment());
}
}
} // namespace ash