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