tray_brightness.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
32namespace ash {
33namespace internal {
34
35namespace tray {
36
37namespace {
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.
43const double kMinBrightnessPercent = 5.0;
44
45}  // namespace
46
47class 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
128TrayBrightness::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
145TrayBrightness::~TrayBrightness() {
146  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
147      RemoveObserver(this);
148}
149
150void 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
162void TrayBrightness::HandleInitialBrightness(double percent) {
163  if (!got_current_percent_)
164    HandleBrightnessChanged(percent, false);
165}
166
167views::View* TrayBrightness::CreateTrayView(user::LoginStatus status) {
168  return NULL;
169}
170
171views::View* TrayBrightness::CreateDefaultView(user::LoginStatus status) {
172  return NULL;
173}
174
175views::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
184void TrayBrightness::DestroyTrayView() {
185}
186
187void TrayBrightness::DestroyDefaultView() {
188  if (is_default_view_)
189    brightness_view_ = NULL;
190}
191
192void TrayBrightness::DestroyDetailedView() {
193  if (!is_default_view_)
194    brightness_view_ = NULL;
195}
196
197void TrayBrightness::UpdateAfterLoginStatusChange(user::LoginStatus status) {
198}
199
200bool TrayBrightness::ShouldHideArrow() const {
201  return true;
202}
203
204bool TrayBrightness::ShouldShowShelf() const {
205  return false;
206}
207
208void 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
215void 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