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