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