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/chromeos/brightness/tray_brightness.h" 6 7 #include "ash/accelerators/accelerator_controller.h" 8 #include "ash/ash_constants.h" 9 #include "ash/metrics/user_metrics_recorder.h" 10 #include "ash/shell.h" 11 #include "ash/system/brightness_control_delegate.h" 12 #include "ash/system/tray/fixed_sized_image_view.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 "base/bind.h" 17 #include "base/message_loop/message_loop.h" 18 #include "base/strings/utf_string_conversions.h" 19 #include "chromeos/dbus/dbus_thread_manager.h" 20 #include "chromeos/dbus/power_manager_client.h" 21 #include "grit/ash_resources.h" 22 #include "grit/ash_strings.h" 23 #include "ui/base/resource/resource_bundle.h" 24 #include "ui/gfx/image/image.h" 25 #include "ui/views/controls/button/image_button.h" 26 #include "ui/views/controls/image_view.h" 27 #include "ui/views/controls/label.h" 28 #include "ui/views/controls/slider.h" 29 #include "ui/views/layout/box_layout.h" 30 #include "ui/views/view.h" 31 32 namespace ash { 33 namespace internal { 34 35 namespace tray { 36 37 namespace { 38 39 // We don't let the screen brightness go lower than this when it's being 40 // adjusted via the slider. Otherwise, if the user doesn't know about the 41 // brightness keys, they may turn the backlight off and not know how to turn it 42 // back on. 43 const double kMinBrightnessPercent = 5.0; 44 45 } // namespace 46 47 class BrightnessView : public views::View, 48 public views::SliderListener { 49 public: 50 explicit BrightnessView(double initial_percent) 51 : dragging_(false), 52 last_percent_(initial_percent) { 53 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 54 kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingBetweenItems)); 55 56 views::ImageView* icon = new FixedSizedImageView(0, kTrayPopupItemHeight); 57 gfx::Image image = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 58 IDR_AURA_UBER_TRAY_BRIGHTNESS); 59 icon->SetImage(image.ToImageSkia()); 60 AddChildView(icon); 61 62 slider_ = new views::Slider(this, views::Slider::HORIZONTAL); 63 slider_->set_focus_border_color(kFocusBorderColor); 64 slider_->SetValue(static_cast<float>(initial_percent / 100.0)); 65 slider_->SetAccessibleName( 66 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( 67 IDS_ASH_STATUS_TRAY_BRIGHTNESS)); 68 AddChildView(slider_); 69 } 70 71 virtual ~BrightnessView() {} 72 73 // |percent| is in the range [0.0, 100.0]. 74 void SetBrightnessPercent(double percent) { 75 last_percent_ = percent; 76 if (!dragging_) 77 slider_->SetValue(static_cast<float>(percent / 100.0)); 78 } 79 80 private: 81 // Overridden from views::View. 82 virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE { 83 int w = width() - slider_->x(); 84 slider_->SetSize(gfx::Size(w, slider_->height())); 85 } 86 87 // Overridden from views:SliderListener. 88 virtual void SliderValueChanged(views::Slider* sender, 89 float value, 90 float old_value, 91 views::SliderChangeReason reason) OVERRIDE { 92 DCHECK_EQ(sender, slider_); 93 if (reason != views::VALUE_CHANGED_BY_USER) 94 return; 95 AcceleratorController* ac = Shell::GetInstance()->accelerator_controller(); 96 if (ac->brightness_control_delegate()) { 97 double percent = std::max(value * 100.0, kMinBrightnessPercent); 98 ac->brightness_control_delegate()->SetBrightnessPercent(percent, true); 99 } 100 } 101 102 // Overridden from views:SliderListener. 103 virtual void SliderDragStarted(views::Slider* slider) OVERRIDE { 104 DCHECK_EQ(slider, slider_); 105 dragging_ = true; 106 } 107 108 // Overridden from views:SliderListener. 109 virtual void SliderDragEnded(views::Slider* slider) OVERRIDE { 110 DCHECK_EQ(slider, slider_); 111 dragging_ = false; 112 slider_->SetValue(static_cast<float>(last_percent_ / 100.0)); 113 } 114 115 views::Slider* slider_; 116 117 // Is |slider_| currently being dragged? 118 bool dragging_; 119 120 // Last brightness level that we observed, in the range [0.0, 100.0]. 121 double last_percent_; 122 123 DISALLOW_COPY_AND_ASSIGN(BrightnessView); 124 }; 125 126 } // namespace tray 127 128 TrayBrightness::TrayBrightness(SystemTray* system_tray) 129 : SystemTrayItem(system_tray), 130 weak_ptr_factory_(this), 131 brightness_view_(NULL), 132 is_default_view_(false), 133 current_percent_(100.0), 134 got_current_percent_(false) { 135 // Post a task to get the initial brightness; the BrightnessControlDelegate 136 // isn't created yet. 137 base::MessageLoopForUI::current()->PostTask( 138 FROM_HERE, 139 base::Bind(&TrayBrightness::GetInitialBrightness, 140 weak_ptr_factory_.GetWeakPtr())); 141 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 142 AddObserver(this); 143 } 144 145 TrayBrightness::~TrayBrightness() { 146 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 147 RemoveObserver(this); 148 } 149 150 void TrayBrightness::GetInitialBrightness() { 151 BrightnessControlDelegate* delegate = 152 Shell::GetInstance()->accelerator_controller()-> 153 brightness_control_delegate(); 154 // Worrisome, but happens in unit tests, so don't log anything. 155 if (!delegate) 156 return; 157 delegate->GetBrightnessPercent( 158 base::Bind(&TrayBrightness::HandleInitialBrightness, 159 weak_ptr_factory_.GetWeakPtr())); 160 } 161 162 void TrayBrightness::HandleInitialBrightness(double percent) { 163 if (!got_current_percent_) 164 HandleBrightnessChanged(percent, false); 165 } 166 167 views::View* TrayBrightness::CreateTrayView(user::LoginStatus status) { 168 return NULL; 169 } 170 171 views::View* TrayBrightness::CreateDefaultView(user::LoginStatus status) { 172 return NULL; 173 } 174 175 views::View* TrayBrightness::CreateDetailedView(user::LoginStatus status) { 176 CHECK(brightness_view_ == NULL); 177 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 178 ash::UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW); 179 brightness_view_ = new tray::BrightnessView(current_percent_); 180 is_default_view_ = false; 181 return brightness_view_; 182 } 183 184 void TrayBrightness::DestroyTrayView() { 185 } 186 187 void TrayBrightness::DestroyDefaultView() { 188 if (is_default_view_) 189 brightness_view_ = NULL; 190 } 191 192 void TrayBrightness::DestroyDetailedView() { 193 if (!is_default_view_) 194 brightness_view_ = NULL; 195 } 196 197 void TrayBrightness::UpdateAfterLoginStatusChange(user::LoginStatus status) { 198 } 199 200 bool TrayBrightness::ShouldHideArrow() const { 201 return true; 202 } 203 204 bool TrayBrightness::ShouldShowLauncher() const { 205 return false; 206 } 207 208 void TrayBrightness::BrightnessChanged(int level, bool user_initiated) { 209 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 210 ash::UMA_STATUS_AREA_BRIGHTNESS_CHANGED); 211 double percent = static_cast<double>(level); 212 HandleBrightnessChanged(percent, user_initiated); 213 } 214 215 void TrayBrightness::HandleBrightnessChanged(double percent, 216 bool user_initiated) { 217 current_percent_ = percent; 218 got_current_percent_ = true; 219 220 if (brightness_view_) 221 brightness_view_->SetBrightnessPercent(percent); 222 if (!user_initiated) 223 return; 224 225 if (brightness_view_) 226 SetDetailedViewCloseDelay(kTrayPopupAutoCloseDelayInSeconds); 227 else 228 PopupDetailedView(kTrayPopupAutoCloseDelayInSeconds, false); 229 } 230 231 } // namespace internal 232 } // namespace ash 233