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 27namespace ash { 28namespace { 29 30const int kLogoutButtonHorizontalExtraPadding = 7; 31 32const 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 44const 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 56class 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 67LogoutButton::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 92LogoutButton::~LogoutButton() { 93} 94 95LogoutButtonTray::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 106LogoutButtonTray::~LogoutButtonTray() { 107 Shell::GetInstance()->system_tray_notifier()-> 108 RemoveLogoutButtonObserver(this); 109} 110 111void LogoutButtonTray::SetShelfAlignment(ShelfAlignment alignment) { 112 TrayBackgroundView::SetShelfAlignment(alignment); 113 tray_container()->SetBorder(views::Border::NullBorder()); 114} 115 116base::string16 LogoutButtonTray::GetAccessibleNameForTray() { 117 return button_->GetText(); 118} 119 120void LogoutButtonTray::HideBubbleWithView( 121 const views::TrayBubbleView* bubble_view) { 122} 123 124bool LogoutButtonTray::ClickedOutsideBubble() { 125 return false; 126} 127 128void LogoutButtonTray::OnShowLogoutButtonInTrayChanged(bool show) { 129 show_logout_button_in_tray_ = show; 130 UpdateVisibility(); 131} 132 133void LogoutButtonTray::OnLogoutDialogDurationChanged(base::TimeDelta duration) { 134 dialog_duration_ = duration; 135} 136 137void 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 149void 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 159void 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