root/ash/system/chromeos/brightness/tray_brightness.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_default_view
  2. last_percent_
  3. SetBrightnessPercent
  4. OnMaximizeModeStarted
  5. OnMaximizeModeEnded
  6. OnBoundsChanged
  7. SliderValueChanged
  8. SliderDragStarted
  9. SliderDragEnded
  10. got_current_percent_
  11. GetInitialBrightness
  12. HandleInitialBrightness
  13. CreateTrayView
  14. CreateDefaultView
  15. CreateDetailedView
  16. DestroyTrayView
  17. DestroyDefaultView
  18. DestroyDetailedView
  19. UpdateAfterLoginStatusChange
  20. ShouldHideArrow
  21. ShouldShowShelf
  22. BrightnessChanged
  23. HandleBrightnessChanged

// Copyright 2013 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/chromeos/brightness/tray_brightness.h"

#include "ash/accelerators/accelerator_controller.h"
#include "ash/ash_constants.h"
#include "ash/display/display_manager.h"
#include "ash/metrics/user_metrics_recorder.h"
#include "ash/shell.h"
#include "ash/shell_observer.h"
#include "ash/system/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 "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.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 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 ShellObserver,
                       public views::View,
                       public views::SliderListener {
 public:
  BrightnessView(bool default_view, double initial_percent);
  virtual ~BrightnessView();

  bool is_default_view() const {
    return is_default_view_;
  }

  // |percent| is in the range [0.0, 100.0].
  void SetBrightnessPercent(double percent);

  // ShellObserver:
  virtual void OnMaximizeModeStarted() OVERRIDE;
  virtual void OnMaximizeModeEnded() OVERRIDE;

 private:
  // views::View:
  virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE;

  // views:SliderListener:
  virtual void SliderValueChanged(views::Slider* sender,
                                  float value,
                                  float old_value,
                                  views::SliderChangeReason reason) OVERRIDE;

  // views:SliderListener:
  virtual void SliderDragStarted(views::Slider* slider) OVERRIDE;
  virtual void SliderDragEnded(views::Slider* slider) OVERRIDE;

  views::Slider* slider_;

  // Is |slider_| currently being dragged?
  bool dragging_;

  // True if this view is for the default tray view. Used to control hide/show
  // behaviour of the default view when entering or leaving Maximize Mode.
  bool is_default_view_;

  // Last brightness level that we observed, in the range [0.0, 100.0].
  double last_percent_;

  DISALLOW_COPY_AND_ASSIGN(BrightnessView);
};

BrightnessView::BrightnessView(bool default_view, double initial_percent)
    : dragging_(false),
      is_default_view_(default_view),
      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_);

  if (is_default_view_) {
    Shell::GetInstance()->AddShellObserver(this);
    SetVisible(Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled());
  }
}

BrightnessView::~BrightnessView() {
  if (is_default_view_)
    Shell::GetInstance()->RemoveShellObserver(this);
}

void BrightnessView::SetBrightnessPercent(double percent) {
  last_percent_ = percent;
  if (!dragging_)
    slider_->SetValue(static_cast<float>(percent / 100.0));
}

void BrightnessView::OnMaximizeModeStarted() {
  SetVisible(true);
}

void BrightnessView::OnMaximizeModeEnded() {
  SetVisible(false);
}

void BrightnessView::OnBoundsChanged(const gfx::Rect& old_bounds) {
  int w = width() - slider_->x();
  slider_->SetSize(gfx::Size(w, slider_->height()));
}

void BrightnessView::SliderValueChanged(views::Slider* sender,
                                float value,
                                float old_value,
                                views::SliderChangeReason reason) {
  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);
  }
}

void BrightnessView::SliderDragStarted(views::Slider* slider) {
  DCHECK_EQ(slider, slider_);
  dragging_ = true;
}

void BrightnessView::SliderDragEnded(views::Slider* slider) {
  DCHECK_EQ(slider, slider_);
  dragging_ = false;
  slider_->SetValue(static_cast<float>(last_percent_ / 100.0));
}

}  // namespace tray

TrayBrightness::TrayBrightness(SystemTray* system_tray)
    : SystemTrayItem(system_tray),
      weak_ptr_factory_(this),
      brightness_view_(NULL),
      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()));
  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
      AddObserver(this);
}

TrayBrightness::~TrayBrightness() {
  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
      RemoveObserver(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_)
    HandleBrightnessChanged(percent, false);
}

views::View* TrayBrightness::CreateTrayView(user::LoginStatus status) {
  return NULL;
}

views::View* TrayBrightness::CreateDefaultView(user::LoginStatus status) {
  CHECK(brightness_view_ == NULL);
  brightness_view_ = new tray::BrightnessView(true, current_percent_);
  return brightness_view_;
}

views::View* TrayBrightness::CreateDetailedView(user::LoginStatus status) {
  CHECK(brightness_view_ == NULL);
  Shell::GetInstance()->metrics()->RecordUserMetricsAction(
      ash::UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW);
  brightness_view_ = new tray::BrightnessView(false, current_percent_);
  return brightness_view_;
}

void TrayBrightness::DestroyTrayView() {
}

void TrayBrightness::DestroyDefaultView() {
  if (brightness_view_ && brightness_view_->is_default_view())
    brightness_view_ = NULL;
}

void TrayBrightness::DestroyDetailedView() {
  if (brightness_view_ && !brightness_view_->is_default_view())
    brightness_view_ = NULL;
}

void TrayBrightness::UpdateAfterLoginStatusChange(user::LoginStatus status) {
}

bool TrayBrightness::ShouldHideArrow() const {
  return true;
}

bool TrayBrightness::ShouldShowShelf() const {
  return false;
}

void TrayBrightness::BrightnessChanged(int level, bool user_initiated) {
  Shell::GetInstance()->metrics()->RecordUserMetricsAction(
      ash::UMA_STATUS_AREA_BRIGHTNESS_CHANGED);
  double percent = static_cast<double>(level);
  HandleBrightnessChanged(percent, user_initiated);
}

void TrayBrightness::HandleBrightnessChanged(double percent,
                                             bool user_initiated) {
  current_percent_ = percent;
  got_current_percent_ = true;

  if (brightness_view_)
    brightness_view_->SetBrightnessPercent(percent);

  if (!user_initiated)
    return;

  // Never show the bubble on systems that lack internal displays: if an
  // external display's brightness is changed, it may already display the new
  // level via an on-screen display.
  if (!Shell::GetInstance()->display_manager()->HasInternalDisplay())
    return;

  if (brightness_view_)
    SetDetailedViewCloseDelay(kTrayPopupAutoCloseDelayInSeconds);
  else
    PopupDetailedView(kTrayPopupAutoCloseDelayInSeconds, false);
}

}  // namespace ash

/* [<][>][^][v][top][bottom][index][help] */