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