Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / ash / system / logout_button / logout_button_tray.cc
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_list.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
26 namespace ash {
27 namespace internal {
28
29 namespace {
30
31 const int kLogoutButtonHorizontalExtraPadding = 7;
32
33 const int kLogoutButtonNormalImages[] = {
34   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_TOP_LEFT,
35   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_TOP,
36   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_TOP_RIGHT,
37   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_LEFT,
38   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_CENTER,
39   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_RIGHT,
40   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_BOTTOM_LEFT,
41   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_BOTTOM,
42   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_NORMAL_BOTTOM_RIGHT
43 };
44
45 const int kLogoutButtonPushedImages[] = {
46   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_TOP_LEFT,
47   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_TOP,
48   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_TOP_RIGHT,
49   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_LEFT,
50   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_CENTER,
51   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_RIGHT,
52   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_BOTTOM_LEFT,
53   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_BOTTOM,
54   IDR_AURA_UBER_TRAY_LOGOUT_BUTTON_PUSHED_BOTTOM_RIGHT
55 };
56
57 class LogoutButton : public views::LabelButton {
58  public:
59   LogoutButton(views::ButtonListener* listener);
60   virtual ~LogoutButton();
61
62  private:
63   DISALLOW_COPY_AND_ASSIGN(LogoutButton);
64 };
65
66 class LogoutConfirmationDialogDelegate
67     : public LogoutConfirmationDialogView::Delegate {
68
69  public:
70   LogoutConfirmationDialogDelegate() {}
71   virtual ~LogoutConfirmationDialogDelegate() {}
72
73   virtual void LogoutCurrentUser() OVERRIDE;
74   virtual base::TimeTicks GetCurrentTime() const OVERRIDE;
75   virtual void ShowDialog(views::DialogDelegate* dialog) OVERRIDE;
76
77  private:
78   DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationDialogDelegate);
79 };
80
81 }  // namespace
82
83 LogoutButton::LogoutButton(views::ButtonListener* listener)
84     : views::LabelButton(listener, base::string16()) {
85   SetupLabelForTray(label());
86   SetFontList(
87       GetFontList().DeriveFontListWithSizeDeltaAndStyle(0, gfx::Font::NORMAL));
88   for (size_t state = 0; state < views::Button::STATE_COUNT; ++state)
89     SetTextColor(static_cast<views::Button::ButtonState>(state), SK_ColorWHITE);
90
91   scoped_ptr<views::LabelButtonBorder> border(
92       new views::LabelButtonBorder(views::Button::STYLE_TEXTBUTTON));
93   border->SetPainter(false, views::Button::STATE_NORMAL,
94       views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages));
95   border->SetPainter(false, views::Button::STATE_HOVERED,
96       views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages));
97   border->SetPainter(false, views::Button::STATE_PRESSED,
98       views::Painter::CreateImageGridPainter(kLogoutButtonPushedImages));
99   gfx::Insets insets = border->GetInsets();
100   insets += gfx::Insets(0, kLogoutButtonHorizontalExtraPadding,
101                         0, kLogoutButtonHorizontalExtraPadding);
102   border->set_insets(insets);
103   SetBorder(border.PassAs<views::Border>());
104   set_animate_on_state_change(false);
105
106   set_min_size(gfx::Size(0, GetShelfItemHeight()));
107 }
108
109 LogoutButton::~LogoutButton() {
110 }
111
112 void LogoutConfirmationDialogDelegate::LogoutCurrentUser() {
113   Shell::GetInstance()->system_tray_delegate()->SignOut();
114 }
115
116 base::TimeTicks LogoutConfirmationDialogDelegate::GetCurrentTime() const {
117   return base::TimeTicks::Now();
118 }
119
120 void LogoutConfirmationDialogDelegate::ShowDialog(
121     views::DialogDelegate *dialog) {
122   views::DialogDelegate::CreateDialogWidget(
123       dialog, ash::Shell::GetPrimaryRootWindow(), NULL);
124   dialog->GetWidget()->Show();
125 }
126
127 LogoutButtonTray::LogoutButtonTray(StatusAreaWidget* status_area_widget)
128     : TrayBackgroundView(status_area_widget),
129       button_(NULL),
130       login_status_(user::LOGGED_IN_NONE),
131       show_logout_button_in_tray_(false),
132       confirmation_dialog_(NULL),
133       confirmation_delegate_(new LogoutConfirmationDialogDelegate) {
134   button_ = new LogoutButton(this);
135   tray_container()->AddChildView(button_);
136   tray_container()->SetBorder(views::Border::NullBorder());
137   // The Shell may not exist in some unit tests.
138   if (Shell::HasInstance()) {
139     Shell::GetInstance()->system_tray_notifier()->
140         AddLogoutButtonObserver(this);
141   }
142 }
143
144 LogoutButtonTray::~LogoutButtonTray() {
145   EnsureConfirmationDialogIsClosed();
146   // The Shell may not exist in some unit tests.
147   if (Shell::HasInstance()) {
148     Shell::GetInstance()->system_tray_notifier()->
149         RemoveLogoutButtonObserver(this);
150   }
151 }
152
153 bool LogoutButtonTray::IsConfirmationDialogShowing() const {
154   return confirmation_dialog_ != NULL;
155 }
156
157 void LogoutButtonTray::EnsureConfirmationDialogIsShowing() {
158   if (!confirmation_dialog_) {
159     confirmation_dialog_ = new LogoutConfirmationDialogView(
160         this, confirmation_delegate_.get());
161     confirmation_dialog_->Show(dialog_duration_);
162   }
163 }
164
165 void LogoutButtonTray::EnsureConfirmationDialogIsClosed() {
166   if (confirmation_dialog_)
167     confirmation_dialog_->Close();
168 }
169
170 void LogoutButtonTray::SetShelfAlignment(ShelfAlignment alignment) {
171   TrayBackgroundView::SetShelfAlignment(alignment);
172   tray_container()->SetBorder(views::Border::NullBorder());
173 }
174
175 base::string16 LogoutButtonTray::GetAccessibleNameForTray() {
176   return button_->GetText();
177 }
178
179 void LogoutButtonTray::HideBubbleWithView(
180     const views::TrayBubbleView* bubble_view) {
181 }
182
183 bool LogoutButtonTray::ClickedOutsideBubble() {
184   return false;
185 }
186
187 void LogoutButtonTray::OnShowLogoutButtonInTrayChanged(bool show) {
188   show_logout_button_in_tray_ = show;
189   UpdateVisibility();
190 }
191
192 void LogoutButtonTray::OnLogoutDialogDurationChanged(base::TimeDelta duration) {
193   dialog_duration_ = duration;
194   if (confirmation_dialog_)
195     confirmation_dialog_->UpdateDialogDuration(dialog_duration_);
196 }
197
198 void LogoutButtonTray::ButtonPressed(views::Button* sender,
199                                      const ui::Event& event) {
200   DCHECK_EQ(sender, button_);
201   // Sign out immediately if |dialog_duration_| is non-positive.
202   if (dialog_duration_ <= base::TimeDelta())
203     confirmation_delegate_->LogoutCurrentUser();
204   else
205     EnsureConfirmationDialogIsShowing();
206 }
207
208 void LogoutButtonTray::UpdateAfterLoginStatusChange(
209     user::LoginStatus login_status) {
210   login_status_ = login_status;
211   const base::string16 title =
212       GetLocalizedSignOutStringForStatus(login_status, false);
213   button_->SetText(title);
214   button_->SetAccessibleName(title);
215   UpdateVisibility();
216 }
217
218 void LogoutButtonTray::ReleaseConfirmationDialog() {
219   confirmation_dialog_ = NULL;
220 }
221
222 void LogoutButtonTray::SetDelegateForTest(
223     scoped_ptr<LogoutConfirmationDialogView::Delegate> delegate) {
224   confirmation_delegate_ = delegate.Pass();
225 }
226
227 void LogoutButtonTray::UpdateVisibility() {
228   SetVisible(show_logout_button_in_tray_ &&
229              login_status_ != user::LOGGED_IN_NONE &&
230              login_status_ != user::LOGGED_IN_LOCKED);
231   if (!show_logout_button_in_tray_)
232     EnsureConfirmationDialogIsClosed();
233 }
234
235 }  // namespace internal
236 }  // namespace ash