1// Copyright 2013 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.
4
5#include "ash/system/logout_button/logout_button_tray.h"
6
7#include "ash/shelf/shelf_types.h"
8#include "ash/shell.h"
9#include "ash/system/status_area_widget.h"
10#include "ash/system/tray/system_tray_delegate.h"
11#include "ash/system/tray/system_tray_notifier.h"
12#include "ash/system/tray/tray_constants.h"
13#include "ash/system/tray/tray_utils.h"
14#include "base/logging.h"
15#include "grit/ash_resources.h"
16#include "third_party/skia/include/core/SkColor.h"
17#include "ui/events/event.h"
18#include "ui/gfx/font.h"
19#include "ui/gfx/insets.h"
20#include "ui/gfx/size.h"
21#include "ui/views/bubble/tray_bubble_view.h"
22#include "ui/views/controls/button/label_button.h"
23#include "ui/views/controls/button/label_button_border.h"
24#include "ui/views/painter.h"
25
26namespace ash {
27
28namespace internal {
29
30namespace {
31
32const int kLogoutButtonHorizontalExtraPadding = 7;
33
34const int kLogoutButtonNormalImages[] = {
35  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_TOP_LEFT,
36  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_TOP,
37  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_TOP_RIGHT,
38  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_LEFT,
39  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_CENTER,
40  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_RIGHT,
41  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_BOTTOM_LEFT,
42  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_BOTTOM,
43  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_BOTTOM_RIGHT
44};
45
46const int kLogoutButtonPushedImages[] = {
47  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_TOP_LEFT,
48  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_TOP,
49  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_TOP_RIGHT,
50  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_LEFT,
51  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_CENTER,
52  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_RIGHT,
53  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_BOTTOM_LEFT,
54  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_BOTTOM,
55  IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_BOTTOM_RIGHT
56};
57
58class LogoutButton : public views::LabelButton {
59 public:
60  LogoutButton(views::ButtonListener* listener);
61  virtual ~LogoutButton();
62
63 private:
64  DISALLOW_COPY_AND_ASSIGN(LogoutButton);
65};
66
67}  // namespace
68
69LogoutButton::LogoutButton(views::ButtonListener* listener)
70    : views::LabelButton(listener, base::string16()) {
71  SetupLabelForTray(label());
72  SetFont(GetFont().DeriveFont(0, gfx::Font::NORMAL));
73  for (size_t state = 0; state < views::Button::STATE_COUNT; ++state)
74    SetTextColor(static_cast<views::Button::ButtonState>(state), SK_ColorWHITE);
75
76  views::LabelButtonBorder* border =
77      new views::LabelButtonBorder(views::Button::STYLE_TEXTBUTTON);
78  border->SetPainter(false, views::Button::STATE_NORMAL,
79      views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages));
80  border->SetPainter(false, views::Button::STATE_HOVERED,
81      views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages));
82  border->SetPainter(false, views::Button::STATE_PRESSED,
83      views::Painter::CreateImageGridPainter(kLogoutButtonPushedImages));
84  gfx::Insets insets = border->GetInsets();
85  insets += gfx::Insets(0, kLogoutButtonHorizontalExtraPadding,
86                        0, kLogoutButtonHorizontalExtraPadding);
87  border->set_insets(insets);
88  set_border(border);
89  set_animate_on_state_change(false);
90
91  set_min_size(gfx::Size(0, GetShelfItemHeight()));
92}
93
94LogoutButton::~LogoutButton() {
95}
96
97LogoutButtonTray::LogoutButtonTray(StatusAreaWidget* status_area_widget)
98    : TrayBackgroundView(status_area_widget),
99      button_(NULL),
100      login_status_(user::LOGGED_IN_NONE),
101      show_logout_button_in_tray_(false) {
102  button_ = new LogoutButton(this);
103  tray_container()->AddChildView(button_);
104  tray_container()->set_border(NULL);
105  Shell::GetInstance()->system_tray_notifier()->AddLogoutButtonObserver(this);
106}
107
108LogoutButtonTray::~LogoutButtonTray() {
109  Shell::GetInstance()->system_tray_notifier()->
110      RemoveLogoutButtonObserver(this);
111}
112
113void LogoutButtonTray::SetShelfAlignment(ShelfAlignment alignment) {
114  TrayBackgroundView::SetShelfAlignment(alignment);
115  tray_container()->set_border(NULL);
116}
117
118base::string16 LogoutButtonTray::GetAccessibleNameForTray() {
119  return button_->GetText();
120}
121
122void LogoutButtonTray::HideBubbleWithView(
123    const views::TrayBubbleView* bubble_view) {
124}
125
126bool LogoutButtonTray::ClickedOutsideBubble() {
127  return false;
128}
129
130void LogoutButtonTray::OnShowLogoutButtonInTrayChanged(bool show) {
131  show_logout_button_in_tray_ = show;
132  UpdateVisibility();
133}
134
135void LogoutButtonTray::ButtonPressed(views::Button* sender,
136                                     const ui::Event& event) {
137  DCHECK_EQ(sender, button_);
138  Shell::GetInstance()->system_tray_delegate()->SignOut();
139}
140
141void LogoutButtonTray::UpdateAfterLoginStatusChange(
142    user::LoginStatus login_status) {
143  login_status_ = login_status;
144  const base::string16 title =
145      GetLocalizedSignOutStringForStatus(login_status, false);
146  button_->SetText(title);
147  button_->SetAccessibleName(title);
148  UpdateVisibility();
149}
150
151void LogoutButtonTray::UpdateVisibility() {
152  SetVisible(show_logout_button_in_tray_ &&
153             login_status_ != user::LOGGED_IN_NONE &&
154             login_status_ != user::LOGGED_IN_LOCKED);
155}
156
157}  // namespace internal
158}  // namespace ash
159