1 // Copyright (c) 2012 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/date/tray_date.h" 6 7 #include "ash/metrics/user_metrics_recorder.h" 8 #include "ash/session_state_delegate.h" 9 #include "ash/shell.h" 10 #include "ash/shell_delegate.h" 11 #include "ash/system/date/date_view.h" 12 #include "ash/system/tray/system_tray.h" 13 #include "ash/system/tray/system_tray_delegate.h" 14 #include "ash/system/tray/system_tray_notifier.h" 15 #include "ash/system/tray/tray_constants.h" 16 #include "ash/system/tray/tray_item_view.h" 17 #include "ash/system/tray/tray_popup_header_button.h" 18 #include "base/i18n/time_formatting.h" 19 #include "base/strings/stringprintf.h" 20 #include "base/strings/utf_string_conversions.h" 21 #include "base/time/time.h" 22 #include "base/timer/timer.h" 23 #include "grit/ash_resources.h" 24 #include "grit/ash_strings.h" 25 #include "third_party/icu/source/i18n/unicode/datefmt.h" 26 #include "third_party/icu/source/i18n/unicode/fieldpos.h" 27 #include "third_party/icu/source/i18n/unicode/fmtable.h" 28 #include "third_party/skia/include/core/SkRect.h" 29 #include "ui/base/l10n/l10n_util.h" 30 #include "ui/base/resource/resource_bundle.h" 31 #include "ui/gfx/image/image.h" 32 #include "ui/gfx/image/image_skia.h" 33 #include "ui/gfx/size.h" 34 #include "ui/views/controls/button/button.h" 35 #include "ui/views/controls/image_view.h" 36 #include "ui/views/controls/label.h" 37 #include "ui/views/layout/box_layout.h" 38 #include "ui/views/layout/fill_layout.h" 39 #include "ui/views/painter.h" 40 #include "ui/views/view.h" 41 #include "ui/views/widget/widget.h" 42 43 #if defined(OS_CHROMEOS) 44 #include "ash/system/chromeos/system_clock_observer.h" 45 #endif 46 47 namespace { 48 49 const int kPaddingVertical = 19; 50 51 } // namespace 52 53 namespace ash { 54 namespace internal { 55 56 class DateDefaultView : public views::View, 57 public views::ButtonListener { 58 public: 59 explicit DateDefaultView(ash::user::LoginStatus login) 60 : help_(NULL), 61 shutdown_(NULL), 62 lock_(NULL), 63 date_view_(NULL) { 64 SetLayoutManager(new views::FillLayout); 65 66 date_view_ = new tray::DateView(); 67 date_view_->set_border(views::Border::CreateEmptyBorder(kPaddingVertical, 68 ash::kTrayPopupPaddingHorizontal, 69 0, 70 0)); 71 SpecialPopupRow* view = new SpecialPopupRow(); 72 view->SetContent(date_view_); 73 AddChildView(view); 74 75 if (login == ash::user::LOGGED_IN_LOCKED || 76 login == ash::user::LOGGED_IN_NONE) 77 return; 78 79 date_view_->SetActionable(true); 80 81 help_ = new TrayPopupHeaderButton(this, 82 IDR_AURA_UBER_TRAY_HELP, 83 IDR_AURA_UBER_TRAY_HELP, 84 IDR_AURA_UBER_TRAY_HELP_HOVER, 85 IDR_AURA_UBER_TRAY_HELP_HOVER, 86 IDS_ASH_STATUS_TRAY_HELP); 87 help_->SetTooltipText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_HELP)); 88 view->AddButton(help_); 89 90 #if !defined(OS_WIN) 91 if (login != ash::user::LOGGED_IN_LOCKED && 92 login != ash::user::LOGGED_IN_RETAIL_MODE) { 93 shutdown_ = new TrayPopupHeaderButton(this, 94 IDR_AURA_UBER_TRAY_SHUTDOWN, 95 IDR_AURA_UBER_TRAY_SHUTDOWN, 96 IDR_AURA_UBER_TRAY_SHUTDOWN_HOVER, 97 IDR_AURA_UBER_TRAY_SHUTDOWN_HOVER, 98 IDS_ASH_STATUS_TRAY_SHUTDOWN); 99 shutdown_->SetTooltipText( 100 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SHUTDOWN)); 101 view->AddButton(shutdown_); 102 } 103 104 if (ash::Shell::GetInstance()->session_state_delegate()->CanLockScreen()) { 105 lock_ = new TrayPopupHeaderButton(this, 106 IDR_AURA_UBER_TRAY_LOCKSCREEN, 107 IDR_AURA_UBER_TRAY_LOCKSCREEN, 108 IDR_AURA_UBER_TRAY_LOCKSCREEN_HOVER, 109 IDR_AURA_UBER_TRAY_LOCKSCREEN_HOVER, 110 IDS_ASH_STATUS_TRAY_LOCK); 111 lock_->SetTooltipText( 112 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_LOCK)); 113 view->AddButton(lock_); 114 } 115 #endif // !defined(OS_WIN) 116 } 117 118 virtual ~DateDefaultView() {} 119 120 views::View* GetHelpButtonView() const { 121 return help_; 122 } 123 124 tray::DateView* GetDateView() const { 125 return date_view_; 126 } 127 128 private: 129 // Overridden from views::ButtonListener. 130 virtual void ButtonPressed(views::Button* sender, 131 const ui::Event& event) OVERRIDE { 132 ash::Shell* shell = ash::Shell::GetInstance(); 133 ash::SystemTrayDelegate* tray_delegate = shell->system_tray_delegate(); 134 if (sender == help_) { 135 shell->metrics()->RecordUserMetricsAction(ash::UMA_TRAY_HELP); 136 tray_delegate->ShowHelp(); 137 } else if (sender == shutdown_) { 138 shell->metrics()->RecordUserMetricsAction(ash::UMA_TRAY_SHUT_DOWN); 139 tray_delegate->ShutDown(); 140 } else if (sender == lock_) { 141 shell->metrics()->RecordUserMetricsAction(ash::UMA_TRAY_LOCK_SCREEN); 142 tray_delegate->RequestLockScreen(); 143 } else { 144 NOTREACHED(); 145 } 146 } 147 148 TrayPopupHeaderButton* help_; 149 TrayPopupHeaderButton* shutdown_; 150 TrayPopupHeaderButton* lock_; 151 tray::DateView* date_view_; 152 153 DISALLOW_COPY_AND_ASSIGN(DateDefaultView); 154 }; 155 156 TrayDate::TrayDate(SystemTray* system_tray) 157 : SystemTrayItem(system_tray), 158 time_tray_(NULL), 159 default_view_(NULL) { 160 #if defined(OS_CHROMEOS) 161 system_clock_observer_.reset(new SystemClockObserver()); 162 #endif 163 Shell::GetInstance()->system_tray_notifier()->AddClockObserver(this); 164 } 165 166 TrayDate::~TrayDate() { 167 Shell::GetInstance()->system_tray_notifier()->RemoveClockObserver(this); 168 } 169 170 views::View* TrayDate::GetHelpButtonView() const { 171 if (!default_view_) 172 return NULL; 173 return default_view_->GetHelpButtonView(); 174 } 175 176 views::View* TrayDate::CreateTrayView(user::LoginStatus status) { 177 CHECK(time_tray_ == NULL); 178 ClockLayout clock_layout = 179 (system_tray()->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM || 180 system_tray()->shelf_alignment() == SHELF_ALIGNMENT_TOP) ? 181 HORIZONTAL_CLOCK : VERTICAL_CLOCK; 182 time_tray_ = new tray::TimeView(clock_layout); 183 views::View* view = new TrayItemView(this); 184 view->AddChildView(time_tray_); 185 return view; 186 } 187 188 views::View* TrayDate::CreateDefaultView(user::LoginStatus status) { 189 default_view_ = new DateDefaultView(status); 190 return default_view_; 191 } 192 193 views::View* TrayDate::CreateDetailedView(user::LoginStatus status) { 194 return NULL; 195 } 196 197 void TrayDate::DestroyTrayView() { 198 time_tray_ = NULL; 199 } 200 201 void TrayDate::DestroyDefaultView() { 202 default_view_ = NULL; 203 } 204 205 void TrayDate::DestroyDetailedView() { 206 } 207 208 void TrayDate::UpdateAfterLoginStatusChange(user::LoginStatus status) { 209 } 210 211 void TrayDate::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { 212 if (time_tray_) { 213 ClockLayout clock_layout = (alignment == SHELF_ALIGNMENT_BOTTOM || 214 alignment == SHELF_ALIGNMENT_TOP) ? 215 HORIZONTAL_CLOCK : VERTICAL_CLOCK; 216 time_tray_->UpdateClockLayout(clock_layout); 217 } 218 } 219 220 void TrayDate::OnDateFormatChanged() { 221 if (time_tray_) 222 time_tray_->UpdateTimeFormat(); 223 if (default_view_) 224 default_view_->GetDateView()->UpdateTimeFormat(); 225 } 226 227 void TrayDate::OnSystemClockTimeUpdated() { 228 if (time_tray_) 229 time_tray_->UpdateTimeFormat(); 230 if (default_view_) 231 default_view_->GetDateView()->UpdateTimeFormat(); 232 } 233 234 void TrayDate::Refresh() { 235 if (time_tray_) 236 time_tray_->UpdateText(); 237 } 238 239 } // namespace internal 240 } // namespace ash 241