1 // Copyright 2014 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/chromeos/session/logout_button_tray.h" 6 7 #include "ash/shelf/shelf_types.h" 8 #include "ash/shell.h" 9 #include "ash/system/chromeos/session/logout_confirmation_controller.h" 10 #include "ash/system/status_area_widget.h" 11 #include "ash/system/tray/system_tray_delegate.h" 12 #include "ash/system/tray/system_tray_notifier.h" 13 #include "ash/system/tray/tray_constants.h" 14 #include "ash/system/tray/tray_utils.h" 15 #include "base/logging.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "grit/ash_resources.h" 18 #include "third_party/skia/include/core/SkColor.h" 19 #include "ui/events/event.h" 20 #include "ui/gfx/geometry/insets.h" 21 #include "ui/gfx/geometry/size.h" 22 #include "ui/views/bubble/tray_bubble_view.h" 23 #include "ui/views/controls/button/label_button.h" 24 #include "ui/views/controls/button/label_button_border.h" 25 #include "ui/views/painter.h" 26 27 namespace ash { 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 } // namespace 66 67 LogoutButton::LogoutButton(views::ButtonListener* listener) 68 : views::LabelButton(listener, base::string16()) { 69 SetupLabelForTray(label()); 70 SetFontList(label()->font_list()); 71 for (size_t state = 0; state < views::Button::STATE_COUNT; ++state) 72 SetTextColor(static_cast<views::Button::ButtonState>(state), SK_ColorWHITE); 73 74 scoped_ptr<views::LabelButtonBorder> border( 75 new views::LabelButtonBorder(views::Button::STYLE_TEXTBUTTON)); 76 border->SetPainter(false, views::Button::STATE_NORMAL, 77 views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages)); 78 border->SetPainter(false, views::Button::STATE_HOVERED, 79 views::Painter::CreateImageGridPainter(kLogoutButtonNormalImages)); 80 border->SetPainter(false, views::Button::STATE_PRESSED, 81 views::Painter::CreateImageGridPainter(kLogoutButtonPushedImages)); 82 gfx::Insets insets = border->GetInsets(); 83 insets += gfx::Insets(0, kLogoutButtonHorizontalExtraPadding, 84 0, kLogoutButtonHorizontalExtraPadding); 85 border->set_insets(insets); 86 SetBorder(border.PassAs<views::Border>()); 87 set_animate_on_state_change(false); 88 89 set_min_size(gfx::Size(0, kShelfItemHeight)); 90 } 91 92 LogoutButton::~LogoutButton() { 93 } 94 95 LogoutButtonTray::LogoutButtonTray(StatusAreaWidget* status_area_widget) 96 : TrayBackgroundView(status_area_widget), 97 button_(NULL), 98 login_status_(user::LOGGED_IN_NONE), 99 show_logout_button_in_tray_(false) { 100 button_ = new LogoutButton(this); 101 tray_container()->AddChildView(button_); 102 tray_container()->SetBorder(views::Border::NullBorder()); 103 Shell::GetInstance()->system_tray_notifier()->AddLogoutButtonObserver(this); 104 } 105 106 LogoutButtonTray::~LogoutButtonTray() { 107 Shell::GetInstance()->system_tray_notifier()-> 108 RemoveLogoutButtonObserver(this); 109 } 110 111 void LogoutButtonTray::SetShelfAlignment(ShelfAlignment alignment) { 112 TrayBackgroundView::SetShelfAlignment(alignment); 113 tray_container()->SetBorder(views::Border::NullBorder()); 114 } 115 116 base::string16 LogoutButtonTray::GetAccessibleNameForTray() { 117 return button_->GetText(); 118 } 119 120 void LogoutButtonTray::HideBubbleWithView( 121 const views::TrayBubbleView* bubble_view) { 122 } 123 124 bool LogoutButtonTray::ClickedOutsideBubble() { 125 return false; 126 } 127 128 void LogoutButtonTray::OnShowLogoutButtonInTrayChanged(bool show) { 129 show_logout_button_in_tray_ = show; 130 UpdateVisibility(); 131 } 132 133 void LogoutButtonTray::OnLogoutDialogDurationChanged(base::TimeDelta duration) { 134 dialog_duration_ = duration; 135 } 136 137 void LogoutButtonTray::ButtonPressed(views::Button* sender, 138 const ui::Event& event) { 139 DCHECK_EQ(sender, button_); 140 if (dialog_duration_ <= base::TimeDelta()) { 141 // Sign out immediately if |dialog_duration_| is non-positive. 142 Shell::GetInstance()->system_tray_delegate()->SignOut(); 143 } else if (Shell::GetInstance()->logout_confirmation_controller()) { 144 Shell::GetInstance()->logout_confirmation_controller()->ConfirmLogout( 145 base::TimeTicks::Now() + dialog_duration_); 146 } 147 } 148 149 void LogoutButtonTray::UpdateAfterLoginStatusChange( 150 user::LoginStatus login_status) { 151 login_status_ = login_status; 152 const base::string16 title = 153 GetLocalizedSignOutStringForStatus(login_status, false); 154 button_->SetText(title); 155 button_->SetAccessibleName(title); 156 UpdateVisibility(); 157 } 158 159 void LogoutButtonTray::UpdateVisibility() { 160 SetVisible(show_logout_button_in_tray_ && 161 login_status_ != user::LOGGED_IN_NONE && 162 login_status_ != user::LOGGED_IN_LOCKED); 163 } 164 165 } // namespace ash 166