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