blob: 87d1f1a991d549faf6d7306e4e74b833fa5f840e [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/brightness/tray_brightness.h"
#include "ash/accelerators/accelerator_controller.h"
#include "ash/ash_constants.h"
#include "ash/shell.h"
#include "ash/system/brightness/brightness_control_delegate.h"
#include "ash/system/tray/fixed_sized_image_view.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/tray/tray_constants.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/slider.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
namespace ash {
namespace internal {
namespace tray {
namespace {
// We don't let the screen brightness go lower than this when it's being
// adjusted via the slider. Otherwise, if the user doesn't know about the
// brightness keys, they may turn the backlight off and not know how to turn it
// back on.
const double kMinBrightnessPercent = 5.0;
} // namespace
class BrightnessView : public views::View,
public views::SliderListener {
public:
explicit BrightnessView(double initial_percent)
: dragging_(false),
last_percent_(initial_percent) {
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingBetweenItems));
views::ImageView* icon = new FixedSizedImageView(0, kTrayPopupItemHeight);
gfx::Image image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_AURA_UBER_TRAY_BRIGHTNESS);
icon->SetImage(image.ToImageSkia());
AddChildView(icon);
slider_ = new views::Slider(this, views::Slider::HORIZONTAL);
slider_->set_focus_border_color(kFocusBorderColor);
slider_->SetValue(static_cast<float>(initial_percent / 100.0));
slider_->SetAccessibleName(
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
IDS_ASH_STATUS_TRAY_BRIGHTNESS));
AddChildView(slider_);
}
virtual ~BrightnessView() {}
// |percent| is in the range [0.0, 100.0].
void SetBrightnessPercent(double percent) {
last_percent_ = percent;
if (!dragging_)
slider_->SetValue(static_cast<float>(percent / 100.0));
}
private:
// Overridden from views::View.
virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE {
int w = width() - slider_->x();
slider_->SetSize(gfx::Size(w, slider_->height()));
}
// Overridden from views:SliderListener.
virtual void SliderValueChanged(views::Slider* sender,
float value,
float old_value,
views::SliderChangeReason reason) OVERRIDE {
DCHECK_EQ(sender, slider_);
if (reason != views::VALUE_CHANGED_BY_USER)
return;
AcceleratorController* ac = Shell::GetInstance()->accelerator_controller();
if (ac->brightness_control_delegate()) {
double percent = std::max(value * 100.0, kMinBrightnessPercent);
ac->brightness_control_delegate()->SetBrightnessPercent(percent, true);
}
}
// Overridden from views:SliderListener.
virtual void SliderDragStarted(views::Slider* slider) OVERRIDE {
DCHECK_EQ(slider, slider_);
dragging_ = true;
}
// Overridden from views:SliderListener.
virtual void SliderDragEnded(views::Slider* slider) OVERRIDE {
DCHECK_EQ(slider, slider_);
dragging_ = false;
slider_->SetValue(static_cast<float>(last_percent_ / 100.0));
}
views::Slider* slider_;
// Is |slider_| currently being dragged?
bool dragging_;
// Last brightness level that we observed, in the range [0.0, 100.0].
double last_percent_;
DISALLOW_COPY_AND_ASSIGN(BrightnessView);
};
} // namespace tray
TrayBrightness::TrayBrightness(SystemTray* system_tray)
: SystemTrayItem(system_tray),
weak_ptr_factory_(this),
brightness_view_(NULL),
is_default_view_(false),
current_percent_(100.0),
got_current_percent_(false) {
// Post a task to get the initial brightness; the BrightnessControlDelegate
// isn't created yet.
base::MessageLoopForUI::current()->PostTask(
FROM_HERE,
base::Bind(&TrayBrightness::GetInitialBrightness,
weak_ptr_factory_.GetWeakPtr()));
Shell::GetInstance()->system_tray_notifier()->AddBrightnessObserver(this);
}
TrayBrightness::~TrayBrightness() {
Shell::GetInstance()->system_tray_notifier()->RemoveBrightnessObserver(this);
}
void TrayBrightness::GetInitialBrightness() {
BrightnessControlDelegate* delegate =
Shell::GetInstance()->accelerator_controller()->
brightness_control_delegate();
// Worrisome, but happens in unit tests, so don't log anything.
if (!delegate)
return;
delegate->GetBrightnessPercent(
base::Bind(&TrayBrightness::HandleInitialBrightness,
weak_ptr_factory_.GetWeakPtr()));
}
void TrayBrightness::HandleInitialBrightness(double percent) {
if (!got_current_percent_)
OnBrightnessChanged(percent, false);
}
views::View* TrayBrightness::CreateTrayView(user::LoginStatus status) {
return NULL;
}
views::View* TrayBrightness::CreateDefaultView(user::LoginStatus status) {
return NULL;
}
views::View* TrayBrightness::CreateDetailedView(user::LoginStatus status) {
CHECK(brightness_view_ == NULL);
brightness_view_ = new tray::BrightnessView(current_percent_);
is_default_view_ = false;
return brightness_view_;
}
void TrayBrightness::DestroyTrayView() {
}
void TrayBrightness::DestroyDefaultView() {
if (is_default_view_)
brightness_view_ = NULL;
}
void TrayBrightness::DestroyDetailedView() {
if (!is_default_view_)
brightness_view_ = NULL;
}
void TrayBrightness::UpdateAfterLoginStatusChange(user::LoginStatus status) {
}
bool TrayBrightness::ShouldHideArrow() const {
return true;
}
bool TrayBrightness::ShouldShowLauncher() const {
return false;
}
void TrayBrightness::OnBrightnessChanged(double percent, bool user_initiated) {
current_percent_ = percent;
got_current_percent_ = true;
if (brightness_view_)
brightness_view_->SetBrightnessPercent(percent);
if (!user_initiated)
return;
if (brightness_view_)
SetDetailedViewCloseDelay(kTrayPopupAutoCloseDelayInSeconds);
else
PopupDetailedView(kTrayPopupAutoCloseDelayInSeconds, false);
}
} // namespace internal
} // namespace ash