bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 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" |
sky@chromium.org | 86ccbd4 | 2013-09-18 18:11:54 | [diff] [blame] | 17 | #include "ui/events/event.h" |
yukishiino@chromium.org | c3d71b64 | 2014-02-05 08:39:47 | [diff] [blame^] | 18 | #include "ui/gfx/geometry/insets.h" |
| 19 | #include "ui/gfx/geometry/size.h" |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 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 { |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 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 | |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 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 | |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 80 | } // namespace |
| 81 | |
| 82 | LogoutButton::LogoutButton(views::ButtonListener* listener) |
| 83 | : views::LabelButton(listener, base::string16()) { |
| 84 | SetupLabelForTray(label()); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 85 | for (size_t state = 0; state < views::Button::STATE_COUNT; ++state) |
| 86 | SetTextColor(static_cast<views::Button::ButtonState>(state), SK_ColorWHITE); |
| 87 | |
erg@chromium.org | 9137e73 | 2014-01-24 22:49:41 | [diff] [blame] | 88 | scoped_ptr<views::LabelButtonBorder> border( |
| 89 | new views::LabelButtonBorder(views::Button::STYLE_TEXTBUTTON)); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 90 | border->SetPainter(false, views::Button::STATE_NORMAL, |
| 91 | views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages)); |
| 92 | border->SetPainter(false, views::Button::STATE_HOVERED, |
| 93 | views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages)); |
| 94 | border->SetPainter(false, views::Button::STATE_PRESSED, |
| 95 | views::Painter::CreateImageGridPainter(kLogoutButtonPushedImages)); |
| 96 | gfx::Insets insets = border->GetInsets(); |
| 97 | insets += gfx::Insets(0, kLogoutButtonHorizontalExtraPadding, |
| 98 | 0, kLogoutButtonHorizontalExtraPadding); |
| 99 | border->set_insets(insets); |
erg@chromium.org | 9137e73 | 2014-01-24 22:49:41 | [diff] [blame] | 100 | SetBorder(border.PassAs<views::Border>()); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 101 | set_animate_on_state_change(false); |
| 102 | |
| 103 | set_min_size(gfx::Size(0, GetShelfItemHeight())); |
| 104 | } |
| 105 | |
| 106 | LogoutButton::~LogoutButton() { |
| 107 | } |
| 108 | |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 109 | void LogoutConfirmationDialogDelegate::LogoutCurrentUser() { |
| 110 | Shell::GetInstance()->system_tray_delegate()->SignOut(); |
| 111 | } |
| 112 | |
| 113 | base::TimeTicks LogoutConfirmationDialogDelegate::GetCurrentTime() const { |
| 114 | return base::TimeTicks::Now(); |
| 115 | } |
| 116 | |
| 117 | void LogoutConfirmationDialogDelegate::ShowDialog( |
| 118 | views::DialogDelegate *dialog) { |
| 119 | views::DialogDelegate::CreateDialogWidget( |
| 120 | dialog, ash::Shell::GetPrimaryRootWindow(), NULL); |
| 121 | dialog->GetWidget()->Show(); |
| 122 | } |
| 123 | |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 124 | LogoutButtonTray::LogoutButtonTray(StatusAreaWidget* status_area_widget) |
| 125 | : TrayBackgroundView(status_area_widget), |
| 126 | button_(NULL), |
| 127 | login_status_(user::LOGGED_IN_NONE), |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 128 | show_logout_button_in_tray_(false), |
| 129 | confirmation_dialog_(NULL), |
| 130 | confirmation_delegate_(new LogoutConfirmationDialogDelegate) { |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 131 | button_ = new LogoutButton(this); |
| 132 | tray_container()->AddChildView(button_); |
erg@chromium.org | 9137e73 | 2014-01-24 22:49:41 | [diff] [blame] | 133 | tray_container()->SetBorder(views::Border::NullBorder()); |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 134 | // The Shell may not exist in some unit tests. |
| 135 | if (Shell::HasInstance()) { |
| 136 | Shell::GetInstance()->system_tray_notifier()-> |
| 137 | AddLogoutButtonObserver(this); |
| 138 | } |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | LogoutButtonTray::~LogoutButtonTray() { |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 142 | EnsureConfirmationDialogIsClosed(); |
| 143 | // The Shell may not exist in some unit tests. |
| 144 | if (Shell::HasInstance()) { |
| 145 | Shell::GetInstance()->system_tray_notifier()-> |
| 146 | RemoveLogoutButtonObserver(this); |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | bool LogoutButtonTray::IsConfirmationDialogShowing() const { |
| 151 | return confirmation_dialog_ != NULL; |
| 152 | } |
| 153 | |
| 154 | void LogoutButtonTray::EnsureConfirmationDialogIsShowing() { |
| 155 | if (!confirmation_dialog_) { |
| 156 | confirmation_dialog_ = new LogoutConfirmationDialogView( |
| 157 | this, confirmation_delegate_.get()); |
| 158 | confirmation_dialog_->Show(dialog_duration_); |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | void LogoutButtonTray::EnsureConfirmationDialogIsClosed() { |
| 163 | if (confirmation_dialog_) |
| 164 | confirmation_dialog_->Close(); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | void LogoutButtonTray::SetShelfAlignment(ShelfAlignment alignment) { |
| 168 | TrayBackgroundView::SetShelfAlignment(alignment); |
erg@chromium.org | 9137e73 | 2014-01-24 22:49:41 | [diff] [blame] | 169 | tray_container()->SetBorder(views::Border::NullBorder()); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | base::string16 LogoutButtonTray::GetAccessibleNameForTray() { |
| 173 | return button_->GetText(); |
| 174 | } |
| 175 | |
| 176 | void LogoutButtonTray::HideBubbleWithView( |
| 177 | const views::TrayBubbleView* bubble_view) { |
| 178 | } |
| 179 | |
| 180 | bool LogoutButtonTray::ClickedOutsideBubble() { |
| 181 | return false; |
| 182 | } |
| 183 | |
| 184 | void LogoutButtonTray::OnShowLogoutButtonInTrayChanged(bool show) { |
| 185 | show_logout_button_in_tray_ = show; |
| 186 | UpdateVisibility(); |
| 187 | } |
| 188 | |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 189 | void LogoutButtonTray::OnLogoutDialogDurationChanged(base::TimeDelta duration) { |
| 190 | dialog_duration_ = duration; |
| 191 | if (confirmation_dialog_) |
| 192 | confirmation_dialog_->UpdateDialogDuration(dialog_duration_); |
| 193 | } |
| 194 | |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 195 | void LogoutButtonTray::ButtonPressed(views::Button* sender, |
| 196 | const ui::Event& event) { |
| 197 | DCHECK_EQ(sender, button_); |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 198 | // Sign out immediately if |dialog_duration_| is non-positive. |
| 199 | if (dialog_duration_ <= base::TimeDelta()) |
| 200 | confirmation_delegate_->LogoutCurrentUser(); |
| 201 | else |
| 202 | EnsureConfirmationDialogIsShowing(); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | void LogoutButtonTray::UpdateAfterLoginStatusChange( |
| 206 | user::LoginStatus login_status) { |
| 207 | login_status_ = login_status; |
| 208 | const base::string16 title = |
| 209 | GetLocalizedSignOutStringForStatus(login_status, false); |
| 210 | button_->SetText(title); |
| 211 | button_->SetAccessibleName(title); |
| 212 | UpdateVisibility(); |
| 213 | } |
| 214 | |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 215 | void LogoutButtonTray::ReleaseConfirmationDialog() { |
| 216 | confirmation_dialog_ = NULL; |
| 217 | } |
| 218 | |
| 219 | void LogoutButtonTray::SetDelegateForTest( |
| 220 | scoped_ptr<LogoutConfirmationDialogView::Delegate> delegate) { |
| 221 | confirmation_delegate_ = delegate.Pass(); |
| 222 | } |
| 223 | |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 224 | void LogoutButtonTray::UpdateVisibility() { |
| 225 | SetVisible(show_logout_button_in_tray_ && |
| 226 | login_status_ != user::LOGGED_IN_NONE && |
| 227 | login_status_ != user::LOGGED_IN_LOCKED); |
binjin@chromium.org | d31967e | 2014-01-08 12:26:12 | [diff] [blame] | 228 | if (!show_logout_button_in_tray_) |
| 229 | EnsureConfirmationDialogIsClosed(); |
bartfab@chromium.org | c80357d | 2013-08-14 11:54:42 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | } // namespace internal |
| 233 | } // namespace ash |