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