Home | History | Annotate | Download | only in power
      1 // Copyright (c) 2012 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/power/power_status_view.h"
      6 
      7 #include "ash/shell.h"
      8 #include "ash/shell_delegate.h"
      9 #include "ash/system/chromeos/power/power_status.h"
     10 #include "ash/system/chromeos/power/tray_power.h"
     11 #include "ash/system/tray/fixed_sized_image_view.h"
     12 #include "ash/system/tray/tray_constants.h"
     13 #include "base/strings/string_number_conversions.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "grit/ash_strings.h"
     16 #include "ui/base/l10n/l10n_util.h"
     17 #include "ui/base/l10n/time_format.h"
     18 #include "ui/base/resource/resource_bundle.h"
     19 #include "ui/views/controls/image_view.h"
     20 #include "ui/views/controls/label.h"
     21 #include "ui/views/layout/box_layout.h"
     22 #include "ui/views/layout/grid_layout.h"
     23 
     24 namespace ash {
     25 
     26 // Padding between battery status text and battery icon on default view.
     27 const int kPaddingBetweenBatteryStatusAndIcon = 3;
     28 
     29 PowerStatusView::PowerStatusView(ViewType view_type,
     30                                  bool default_view_right_align)
     31     : default_view_right_align_(default_view_right_align),
     32       status_label_(NULL),
     33       time_label_(NULL),
     34       time_status_label_(NULL),
     35       percentage_label_(NULL),
     36       icon_(NULL),
     37       view_type_(view_type) {
     38   PowerStatus::Get()->AddObserver(this);
     39   if (view_type == VIEW_DEFAULT) {
     40     time_status_label_ = new views::Label;
     41     percentage_label_ = new views::Label;
     42     percentage_label_->SetEnabledColor(kHeaderTextColorNormal);
     43     LayoutDefaultView();
     44   } else {
     45     status_label_ = new views::Label;
     46     time_label_ = new views::Label;
     47     LayoutNotificationView();
     48   }
     49   OnPowerStatusChanged();
     50 }
     51 
     52 PowerStatusView::~PowerStatusView() {
     53   PowerStatus::Get()->RemoveObserver(this);
     54 }
     55 
     56 void PowerStatusView::OnPowerStatusChanged() {
     57   view_type_ == VIEW_DEFAULT ?
     58       UpdateTextForDefaultView() : UpdateTextForNotificationView();
     59 
     60   if (icon_) {
     61     icon_->SetImage(
     62         PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_DARK));
     63     icon_->SetVisible(true);
     64   }
     65 }
     66 
     67 void PowerStatusView::LayoutDefaultView() {
     68   if (default_view_right_align_) {
     69     views::BoxLayout* layout =
     70         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
     71                              kPaddingBetweenBatteryStatusAndIcon);
     72     SetLayoutManager(layout);
     73 
     74     AddChildView(percentage_label_);
     75     AddChildView(time_status_label_);
     76 
     77     icon_ = new views::ImageView;
     78     AddChildView(icon_);
     79   } else {
     80     // PowerStatusView is left aligned on the system tray pop up item.
     81     views::BoxLayout* layout =
     82         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
     83                              kTrayPopupPaddingBetweenItems);
     84     SetLayoutManager(layout);
     85 
     86     icon_ = new ash::FixedSizedImageView(0, ash::kTrayPopupItemHeight);
     87     AddChildView(icon_);
     88 
     89     AddChildView(percentage_label_);
     90     AddChildView(time_status_label_);
     91   }
     92 }
     93 
     94 void PowerStatusView::LayoutNotificationView() {
     95   SetLayoutManager(
     96       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
     97   status_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     98   AddChildView(status_label_);
     99 
    100   time_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    101   AddChildView(time_label_);
    102 }
    103 
    104 void PowerStatusView::UpdateTextForDefaultView() {
    105   const PowerStatus& status = *PowerStatus::Get();
    106   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    107   base::string16 battery_percentage;
    108   base::string16 battery_time_status;
    109 
    110   if (status.IsBatteryFull()) {
    111     battery_time_status =
    112         rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_FULL);
    113   } else {
    114     battery_percentage = l10n_util::GetStringFUTF16(
    115         IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ONLY,
    116         base::IntToString16(status.GetRoundedBatteryPercent()));
    117     if (status.IsUsbChargerConnected()) {
    118       battery_time_status = rb.GetLocalizedString(
    119           IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE);
    120     } else if (status.IsBatteryTimeBeingCalculated()) {
    121       battery_time_status =
    122           rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING);
    123     } else {
    124       base::TimeDelta time = status.IsBatteryCharging() ?
    125           status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty();
    126       if (PowerStatus::ShouldDisplayBatteryTime(time) &&
    127           !status.IsBatteryDischargingOnLinePower()) {
    128         int hour = 0, min = 0;
    129         PowerStatus::SplitTimeIntoHoursAndMinutes(time, &hour, &min);
    130         base::string16 minute = min < 10 ?
    131             base::ASCIIToUTF16("0") + base::IntToString16(min) :
    132             base::IntToString16(min);
    133         battery_time_status =
    134             l10n_util::GetStringFUTF16(
    135                 status.IsBatteryCharging() ?
    136                 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_SHORT :
    137                 IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_SHORT,
    138                 base::IntToString16(hour),
    139                 minute);
    140       }
    141     }
    142     battery_percentage = battery_time_status.empty() ?
    143         battery_percentage : battery_percentage + base::ASCIIToUTF16(" - ");
    144   }
    145   percentage_label_->SetVisible(!battery_percentage.empty());
    146   percentage_label_->SetText(battery_percentage);
    147   time_status_label_->SetVisible(!battery_time_status.empty());
    148   time_status_label_->SetText(battery_time_status);
    149 }
    150 
    151 void PowerStatusView::UpdateTextForNotificationView() {
    152   const PowerStatus& status = *PowerStatus::Get();
    153   if (status.IsBatteryFull()) {
    154     status_label_->SetText(
    155         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
    156             IDS_ASH_STATUS_TRAY_BATTERY_FULL));
    157   } else {
    158     status_label_->SetText(
    159         l10n_util::GetStringFUTF16(
    160             IDS_ASH_STATUS_TRAY_BATTERY_PERCENT,
    161             base::IntToString16(status.GetRoundedBatteryPercent())));
    162   }
    163 
    164   const base::TimeDelta time = status.IsBatteryCharging() ?
    165       status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty();
    166 
    167   if (status.IsUsbChargerConnected()) {
    168     time_label_->SetText(
    169         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
    170             IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE));
    171   } else if (status.IsBatteryTimeBeingCalculated()) {
    172     time_label_->SetText(
    173         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
    174             IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING));
    175   } else if (PowerStatus::ShouldDisplayBatteryTime(time) &&
    176              !status.IsBatteryDischargingOnLinePower()) {
    177     int hour = 0, min = 0;
    178     PowerStatus::SplitTimeIntoHoursAndMinutes(time, &hour, &min);
    179     if (status.IsBatteryCharging()) {
    180       time_label_->SetText(
    181           l10n_util::GetStringFUTF16(
    182               IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL,
    183               base::IntToString16(hour),
    184               base::IntToString16(min)));
    185     } else {
    186       // This is a low battery warning prompting the user in minutes.
    187       time_label_->SetText(ui::TimeFormat::Simple(
    188           ui::TimeFormat::FORMAT_REMAINING, ui::TimeFormat::LENGTH_LONG,
    189           base::TimeDelta::FromMinutes(hour * 60 + min)));
    190     }
    191   } else {
    192     time_label_->SetText(base::string16());
    193   }
    194 }
    195 
    196 void PowerStatusView::ChildPreferredSizeChanged(views::View* child) {
    197   PreferredSizeChanged();
    198 }
    199 
    200 gfx::Size PowerStatusView::GetPreferredSize() const {
    201   gfx::Size size = views::View::GetPreferredSize();
    202   return gfx::Size(size.width(), kTrayPopupItemHeight);
    203 }
    204 
    205 int PowerStatusView::GetHeightForWidth(int width) const {
    206   return kTrayPopupItemHeight;
    207 }
    208 
    209 void PowerStatusView::Layout() {
    210   views::View::Layout();
    211 
    212   // Move the time_status_label_ closer to percentage_label_.
    213   if (percentage_label_ && time_status_label_ &&
    214       percentage_label_->visible() && time_status_label_->visible()) {
    215     time_status_label_->SetX(percentage_label_->bounds().right() + 1);
    216   }
    217 }
    218 
    219 }  // namespace ash
    220