| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/system/chromeos/power/power_status_view.h" | 5 #include "ash/system/chromeos/power/power_status_view.h" |
| 6 | 6 |
| 7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
| 8 #include "ash/shell_delegate.h" | 8 #include "ash/shell_delegate.h" |
| 9 #include "ash/system/chromeos/power/power_status.h" |
| 9 #include "ash/system/chromeos/power/tray_power.h" | 10 #include "ash/system/chromeos/power/tray_power.h" |
| 10 #include "ash/system/tray/fixed_sized_image_view.h" | 11 #include "ash/system/tray/fixed_sized_image_view.h" |
| 11 #include "ash/system/tray/tray_constants.h" | 12 #include "ash/system/tray/tray_constants.h" |
| 12 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 14 #include "grit/ash_strings.h" | 15 #include "grit/ash_strings.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 16 #include "ui/base/l10n/l10n_util.h" |
| 16 #include "ui/base/resource/resource_bundle.h" | 17 #include "ui/base/resource/resource_bundle.h" |
| 17 #include "ui/views/controls/image_view.h" | 18 #include "ui/views/controls/image_view.h" |
| 18 #include "ui/views/controls/label.h" | 19 #include "ui/views/controls/label.h" |
| 19 #include "ui/views/layout/box_layout.h" | 20 #include "ui/views/layout/box_layout.h" |
| 20 #include "ui/views/layout/grid_layout.h" | 21 #include "ui/views/layout/grid_layout.h" |
| 21 | 22 |
| 22 namespace ash { | 23 namespace ash { |
| 23 namespace internal { | 24 namespace internal { |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 // Top/bottom padding of the text items. | 28 // Top/bottom padding of the text items. |
| 28 const int kPaddingVertical = 10; | 29 const int kPaddingVertical = 10; |
| 29 // Specify min width of status label for layout. | 30 // Specify min width of status label for layout. |
| 30 const int kLabelMinWidth = 120; | 31 const int kLabelMinWidth = 120; |
| 31 // Padding between battery status text and battery icon on default view. | 32 // Padding between battery status text and battery icon on default view. |
| 32 const int kPaddingBetweenBatteryStatusAndIcon = 3; | 33 const int kPaddingBetweenBatteryStatusAndIcon = 3; |
| 33 // Minimum battery percentage rendered in UI. | |
| 34 const int kMinBatteryPercent = 1; | |
| 35 } // namespace | 34 } // namespace |
| 36 | 35 |
| 37 PowerStatusView::PowerStatusView(ViewType view_type, | 36 PowerStatusView::PowerStatusView(ViewType view_type, |
| 38 bool default_view_right_align) | 37 bool default_view_right_align) |
| 39 : default_view_right_align_(default_view_right_align), | 38 : default_view_right_align_(default_view_right_align), |
| 40 status_label_(NULL), | 39 status_label_(NULL), |
| 41 time_label_(NULL), | 40 time_label_(NULL), |
| 42 time_status_label_(NULL), | 41 time_status_label_(NULL), |
| 43 percentage_label_(NULL), | 42 percentage_label_(NULL), |
| 44 icon_(NULL), | 43 icon_(NULL), |
| 45 icon_image_index_(-1), | |
| 46 icon_image_offset_(0), | |
| 47 battery_charging_unreliable_(false), | |
| 48 view_type_(view_type) { | 44 view_type_(view_type) { |
| 45 PowerStatus::Get()->AddObserver(this); |
| 49 if (view_type == VIEW_DEFAULT) { | 46 if (view_type == VIEW_DEFAULT) { |
| 50 time_status_label_ = new views::Label; | 47 time_status_label_ = new views::Label; |
| 51 percentage_label_ = new views::Label; | 48 percentage_label_ = new views::Label; |
| 52 percentage_label_->SetEnabledColor(kHeaderTextColorNormal); | 49 percentage_label_->SetEnabledColor(kHeaderTextColorNormal); |
| 53 LayoutDefaultView(); | 50 LayoutDefaultView(); |
| 54 } else { | 51 } else { |
| 55 status_label_ = new views::Label; | 52 status_label_ = new views::Label; |
| 56 time_label_ = new views::Label; | 53 time_label_ = new views::Label; |
| 57 LayoutNotificationView(); | 54 LayoutNotificationView(); |
| 58 } | 55 } |
| 59 Update(); | 56 OnPowerStatusChanged(); |
| 60 } | 57 } |
| 61 | 58 |
| 62 void PowerStatusView::UpdatePowerStatus( | 59 PowerStatusView::~PowerStatusView() { |
| 63 const chromeos::PowerSupplyStatus& status) { | 60 PowerStatus::Get()->RemoveObserver(this); |
| 64 supply_status_ = status; | 61 } |
| 65 // Sanitize. | |
| 66 if (supply_status_.battery_is_full) | |
| 67 supply_status_.battery_percentage = 100.0; | |
| 68 | 62 |
| 69 Update(); | 63 void PowerStatusView::OnPowerStatusChanged() { |
| 64 view_type_ == VIEW_DEFAULT ? |
| 65 UpdateTextForDefaultView() : UpdateTextForNotificationView(); |
| 66 |
| 67 if (icon_) { |
| 68 icon_->SetImage( |
| 69 PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_DARK)); |
| 70 icon_->SetVisible(true); |
| 71 } |
| 70 } | 72 } |
| 71 | 73 |
| 72 void PowerStatusView::LayoutDefaultView() { | 74 void PowerStatusView::LayoutDefaultView() { |
| 73 if (default_view_right_align_) { | 75 if (default_view_right_align_) { |
| 74 views::BoxLayout* layout = | 76 views::BoxLayout* layout = |
| 75 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, | 77 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, |
| 76 kPaddingBetweenBatteryStatusAndIcon); | 78 kPaddingBetweenBatteryStatusAndIcon); |
| 77 SetLayoutManager(layout); | 79 SetLayoutManager(layout); |
| 78 | 80 |
| 79 AddChildView(percentage_label_); | 81 AddChildView(percentage_label_); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 100 void PowerStatusView::LayoutNotificationView() { | 102 void PowerStatusView::LayoutNotificationView() { |
| 101 SetLayoutManager( | 103 SetLayoutManager( |
| 102 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | 104 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); |
| 103 status_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 105 status_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 104 AddChildView(status_label_); | 106 AddChildView(status_label_); |
| 105 | 107 |
| 106 time_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 108 time_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 107 AddChildView(time_label_); | 109 AddChildView(time_label_); |
| 108 } | 110 } |
| 109 | 111 |
| 110 void PowerStatusView::UpdateText() { | |
| 111 view_type_ == VIEW_DEFAULT ? | |
| 112 UpdateTextForDefaultView() : UpdateTextForNotificationView(); | |
| 113 accessible_name_ = TrayPower::GetAccessibleNameString(supply_status_); | |
| 114 } | |
| 115 | |
| 116 void PowerStatusView::UpdateTextForDefaultView() { | 112 void PowerStatusView::UpdateTextForDefaultView() { |
| 113 const PowerStatus& status = *PowerStatus::Get(); |
| 117 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 114 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 118 base::string16 battery_percentage; | 115 base::string16 battery_percentage; |
| 119 base::string16 battery_time_status; | 116 base::string16 battery_time_status; |
| 120 bool is_charging_unreliable = | 117 |
| 121 TrayPower::IsBatteryChargingUnreliable(supply_status_); | 118 if (status.IsLinePowerConnected() && status.IsBatteryFull()) { |
| 122 if (supply_status_.line_power_on && supply_status_.battery_is_full) { | |
| 123 battery_time_status = | 119 battery_time_status = |
| 124 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_FULL); | 120 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_FULL); |
| 125 } else if (supply_status_.battery_percentage < 0.0f) { | |
| 126 battery_time_status = | |
| 127 is_charging_unreliable ? | |
| 128 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE) : | |
| 129 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING); | |
| 130 } else { | 121 } else { |
| 131 battery_percentage = l10n_util::GetStringFUTF16( | 122 battery_percentage = l10n_util::GetStringFUTF16( |
| 132 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ONLY, | 123 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ONLY, |
| 133 base::IntToString16(TrayPower::GetRoundedBatteryPercentage( | 124 base::IntToString16(status.GetRoundedBatteryPercent())); |
| 134 supply_status_.battery_percentage))); | 125 if (status.IsUsbChargerConnected()) { |
| 135 if (is_charging_unreliable) { | |
| 136 battery_time_status = rb.GetLocalizedString( | 126 battery_time_status = rb.GetLocalizedString( |
| 137 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE); | 127 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE); |
| 138 } else { | 128 } else { |
| 139 if (supply_status_.is_calculating_battery_time) { | 129 if (status.IsBatteryTimeBeingCalculated()) { |
| 140 battery_time_status = | 130 battery_time_status = |
| 141 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING); | 131 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING); |
| 142 } else { | 132 } else { |
| 143 base::TimeDelta time = base::TimeDelta::FromSeconds( | 133 base::TimeDelta time = status.IsLinePowerConnected() ? |
| 144 supply_status_.line_power_on ? | 134 status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty(); |
| 145 supply_status_.battery_seconds_to_full : | |
| 146 supply_status_.battery_seconds_to_empty); | |
| 147 int hour = time.InHours(); | 135 int hour = time.InHours(); |
| 148 int min = (time - base::TimeDelta::FromHours(hour)).InMinutes(); | 136 int min = (time - base::TimeDelta::FromHours(hour)).InMinutes(); |
| 149 if (hour || min) { | 137 if (hour || min) { |
| 150 base::string16 minute = min < 10 ? | 138 base::string16 minute = min < 10 ? |
| 151 ASCIIToUTF16("0") + base::IntToString16(min) : | 139 ASCIIToUTF16("0") + base::IntToString16(min) : |
| 152 base::IntToString16(min); | 140 base::IntToString16(min); |
| 153 battery_time_status = | 141 battery_time_status = |
| 154 l10n_util::GetStringFUTF16( | 142 l10n_util::GetStringFUTF16( |
| 155 supply_status_.line_power_on ? | 143 status.IsLinePowerConnected() ? |
| 156 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_SHORT : | 144 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_SHORT : |
| 157 IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_SHORT, | 145 IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_SHORT, |
| 158 base::IntToString16(hour), | 146 base::IntToString16(hour), |
| 159 minute); | 147 minute); |
| 160 } | 148 } |
| 161 } | 149 } |
| 162 } | 150 } |
| 163 battery_percentage = battery_time_status.empty() ? | 151 battery_percentage = battery_time_status.empty() ? |
| 164 battery_percentage : battery_percentage + ASCIIToUTF16(" - "); | 152 battery_percentage : battery_percentage + ASCIIToUTF16(" - "); |
| 165 } | 153 } |
| 166 percentage_label_->SetVisible(!battery_percentage.empty()); | 154 percentage_label_->SetVisible(!battery_percentage.empty()); |
| 167 percentage_label_->SetText(battery_percentage); | 155 percentage_label_->SetText(battery_percentage); |
| 168 time_status_label_->SetVisible(!battery_time_status.empty()); | 156 time_status_label_->SetVisible(!battery_time_status.empty()); |
| 169 time_status_label_->SetText(battery_time_status); | 157 time_status_label_->SetText(battery_time_status); |
| 170 } | 158 } |
| 171 | 159 |
| 172 void PowerStatusView::UpdateTextForNotificationView() { | 160 void PowerStatusView::UpdateTextForNotificationView() { |
| 173 int hour = 0; | 161 const PowerStatus& status = *PowerStatus::Get(); |
| 174 int min = 0; | 162 if (status.IsLinePowerConnected() && status.IsBatteryFull()) { |
| 175 if (!supply_status_.is_calculating_battery_time) { | |
| 176 base::TimeDelta time = base::TimeDelta::FromSeconds( | |
| 177 supply_status_.line_power_on ? | |
| 178 supply_status_.battery_seconds_to_full : | |
| 179 supply_status_.battery_seconds_to_empty); | |
| 180 hour = time.InHours(); | |
| 181 min = (time - base::TimeDelta::FromHours(hour)).InMinutes(); | |
| 182 } | |
| 183 bool is_charging_unreliable = | |
| 184 TrayPower::IsBatteryChargingUnreliable(supply_status_); | |
| 185 if (supply_status_.line_power_on && supply_status_.battery_is_full) { | |
| 186 status_label_->SetText( | 163 status_label_->SetText( |
| 187 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( | 164 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( |
| 188 IDS_ASH_STATUS_TRAY_BATTERY_FULL)); | 165 IDS_ASH_STATUS_TRAY_BATTERY_FULL)); |
| 189 } else { | 166 } else { |
| 190 if (supply_status_.battery_percentage < 0.0f) { | 167 status_label_->SetText( |
| 191 // If charging is unreliable and no percentage available, we | 168 l10n_util::GetStringFUTF16( |
| 192 // leave the top field, |staus_label|, blank. We do not want to | 169 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT, |
| 193 // show "Calculating". The user is informed in the bottom field, | 170 base::IntToString16(status.GetRoundedBatteryPercent()))); |
| 194 // |time_label|, that "Charging not reliable". | |
| 195 status_label_->SetText( | |
| 196 is_charging_unreliable ? | |
| 197 base::string16() : | |
| 198 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( | |
| 199 IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING)); | |
| 200 } else { | |
| 201 status_label_->SetText( | |
| 202 l10n_util::GetStringFUTF16( | |
| 203 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT, | |
| 204 base::IntToString16(TrayPower::GetRoundedBatteryPercentage( | |
| 205 supply_status_.battery_percentage)))); | |
| 206 } | |
| 207 } | 171 } |
| 208 | 172 |
| 209 if (is_charging_unreliable) { | 173 int hour = 0; |
| 174 int min = 0; |
| 175 if (!status.IsBatteryTimeBeingCalculated()) { |
| 176 base::TimeDelta time = status.IsLinePowerConnected() ? |
| 177 status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty(); |
| 178 hour = time.InHours(); |
| 179 min = (time - base::TimeDelta::FromHours(hour)).InMinutes(); |
| 180 } |
| 181 |
| 182 if (status.IsUsbChargerConnected()) { |
| 210 time_label_->SetText( | 183 time_label_->SetText( |
| 211 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( | 184 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( |
| 212 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE)); | 185 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE)); |
| 213 } else if (supply_status_.is_calculating_battery_time) { | 186 } else if (status.IsBatteryTimeBeingCalculated()) { |
| 214 time_label_->SetText( | 187 time_label_->SetText( |
| 215 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( | 188 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( |
| 216 IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING)); | 189 IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING)); |
| 217 } else if (hour || min) { | 190 } else if (hour || min) { |
| 218 if (supply_status_.line_power_on) { | 191 if (status.IsLinePowerConnected()) { |
| 219 time_label_->SetText( | 192 time_label_->SetText( |
| 220 l10n_util::GetStringFUTF16( | 193 l10n_util::GetStringFUTF16( |
| 221 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL, | 194 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL, |
| 222 base::IntToString16(hour), | 195 base::IntToString16(hour), |
| 223 base::IntToString16(min))); | 196 base::IntToString16(min))); |
| 224 } else { | 197 } else { |
| 225 // This is a low battery warning, which prompts user when battery | 198 // This is a low battery warning prompting the user in minutes. |
| 226 // time left is not much (ie in minutes). | |
| 227 min = hour * 60 + min; | 199 min = hour * 60 + min; |
| 228 ShellDelegate* delegate = Shell::GetInstance()->delegate(); | 200 ShellDelegate* delegate = Shell::GetInstance()->delegate(); |
| 229 if (delegate) { | 201 if (delegate) { |
| 230 time_label_->SetText(delegate->GetTimeRemainingString( | 202 time_label_->SetText(delegate->GetTimeRemainingString( |
| 231 base::TimeDelta::FromMinutes(min))); | 203 base::TimeDelta::FromMinutes(min))); |
| 232 } else { | 204 } else { |
| 233 time_label_->SetText(base::string16()); | 205 time_label_->SetText(base::string16()); |
| 234 } | 206 } |
| 235 } | 207 } |
| 236 } else { | 208 } else { |
| 237 time_label_->SetText(base::string16()); | 209 time_label_->SetText(base::string16()); |
| 238 } | 210 } |
| 239 } | 211 } |
| 240 | 212 |
| 241 base::string16 PowerStatusView::GetBatteryTimeAccessibilityString( | |
| 242 int hour, int min) { | |
| 243 DCHECK(hour || min); | |
| 244 if (hour && !min) { | |
| 245 return Shell::GetInstance()->delegate()->GetTimeDurationLongString( | |
| 246 base::TimeDelta::FromHours(hour)); | |
| 247 } else if (min && !hour) { | |
| 248 return Shell::GetInstance()->delegate()->GetTimeDurationLongString( | |
| 249 base::TimeDelta::FromMinutes(min)); | |
| 250 } else { | |
| 251 return l10n_util::GetStringFUTF16( | |
| 252 IDS_ASH_STATUS_TRAY_BATTERY_TIME_ACCESSIBLE, | |
| 253 Shell::GetInstance()->delegate()->GetTimeDurationLongString( | |
| 254 base::TimeDelta::FromHours(hour)), | |
| 255 Shell::GetInstance()->delegate()->GetTimeDurationLongString( | |
| 256 base::TimeDelta::FromMinutes(min))); | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 void PowerStatusView::UpdateIcon() { | |
| 261 if (icon_) { | |
| 262 int index = TrayPower::GetBatteryImageIndex(supply_status_); | |
| 263 int offset = TrayPower::GetBatteryImageOffset(supply_status_); | |
| 264 bool charging_unreliable = | |
| 265 TrayPower::IsBatteryChargingUnreliable(supply_status_); | |
| 266 if (icon_image_index_ != index || | |
| 267 icon_image_offset_ != offset || | |
| 268 battery_charging_unreliable_ != charging_unreliable) { | |
| 269 icon_image_index_ = index; | |
| 270 icon_image_offset_ = offset; | |
| 271 battery_charging_unreliable_ = charging_unreliable; | |
| 272 if (icon_image_index_ != -1) { | |
| 273 icon_->SetImage( | |
| 274 TrayPower::GetBatteryImage(icon_image_index_, | |
| 275 icon_image_offset_, | |
| 276 battery_charging_unreliable_, | |
| 277 ICON_DARK)); | |
| 278 } | |
| 279 } | |
| 280 icon_->SetVisible(true); | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 void PowerStatusView::Update() { | |
| 285 UpdateText(); | |
| 286 UpdateIcon(); | |
| 287 } | |
| 288 | |
| 289 void PowerStatusView::ChildPreferredSizeChanged(views::View* child) { | 213 void PowerStatusView::ChildPreferredSizeChanged(views::View* child) { |
| 290 PreferredSizeChanged(); | 214 PreferredSizeChanged(); |
| 291 } | 215 } |
| 292 | 216 |
| 293 gfx::Size PowerStatusView::GetPreferredSize() { | 217 gfx::Size PowerStatusView::GetPreferredSize() { |
| 294 gfx::Size size = views::View::GetPreferredSize(); | 218 gfx::Size size = views::View::GetPreferredSize(); |
| 295 return gfx::Size(size.width(), kTrayPopupItemHeight); | 219 return gfx::Size(size.width(), kTrayPopupItemHeight); |
| 296 } | 220 } |
| 297 | 221 |
| 298 int PowerStatusView::GetHeightForWidth(int width) { | 222 int PowerStatusView::GetHeightForWidth(int width) { |
| 299 return kTrayPopupItemHeight; | 223 return kTrayPopupItemHeight; |
| 300 } | 224 } |
| 301 | 225 |
| 302 void PowerStatusView::Layout() { | 226 void PowerStatusView::Layout() { |
| 303 views::View::Layout(); | 227 views::View::Layout(); |
| 304 | 228 |
| 305 // Move the time_status_label_ closer to percentage_label_. | 229 // Move the time_status_label_ closer to percentage_label_. |
| 306 if (percentage_label_ && time_status_label_ && | 230 if (percentage_label_ && time_status_label_ && |
| 307 percentage_label_->visible() && time_status_label_->visible()) { | 231 percentage_label_->visible() && time_status_label_->visible()) { |
| 308 time_status_label_->SetX(percentage_label_->bounds().right() + 1); | 232 time_status_label_->SetX(percentage_label_->bounds().right() + 1); |
| 309 } | 233 } |
| 310 } | 234 } |
| 311 | 235 |
| 312 } // namespace internal | 236 } // namespace internal |
| 313 } // namespace ash | 237 } // namespace ash |
| OLD | NEW |