blob: 5323f5c1a6d3f58cbc4148c836ba636b217c5035 [file] [log] [blame]
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001// 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"
Ben Murdocheb525c52013-07-10 11:40:50 +01009#include "ash/system/chromeos/power/power_status.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010#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"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010014#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010015#include "grit/ash_strings.h"
16#include "ui/base/l10n/l10n_util.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010017#include "ui/base/l10n/time_format.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010018#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
24namespace ash {
25namespace internal {
26
27namespace {
28
29// Top/bottom padding of the text items.
30const int kPaddingVertical = 10;
31// Specify min width of status label for layout.
32const int kLabelMinWidth = 120;
33// Padding between battery status text and battery icon on default view.
34const int kPaddingBetweenBatteryStatusAndIcon = 3;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010035} // namespace
36
37PowerStatusView::PowerStatusView(ViewType view_type,
38 bool default_view_right_align)
39 : default_view_right_align_(default_view_right_align),
40 status_label_(NULL),
41 time_label_(NULL),
42 time_status_label_(NULL),
43 percentage_label_(NULL),
44 icon_(NULL),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010045 view_type_(view_type) {
Ben Murdocheb525c52013-07-10 11:40:50 +010046 PowerStatus::Get()->AddObserver(this);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010047 if (view_type == VIEW_DEFAULT) {
48 time_status_label_ = new views::Label;
49 percentage_label_ = new views::Label;
50 percentage_label_->SetEnabledColor(kHeaderTextColorNormal);
51 LayoutDefaultView();
52 } else {
53 status_label_ = new views::Label;
54 time_label_ = new views::Label;
55 LayoutNotificationView();
56 }
Ben Murdocheb525c52013-07-10 11:40:50 +010057 OnPowerStatusChanged();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010058}
59
Ben Murdocheb525c52013-07-10 11:40:50 +010060PowerStatusView::~PowerStatusView() {
61 PowerStatus::Get()->RemoveObserver(this);
62}
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010063
Ben Murdocheb525c52013-07-10 11:40:50 +010064void PowerStatusView::OnPowerStatusChanged() {
65 view_type_ == VIEW_DEFAULT ?
66 UpdateTextForDefaultView() : UpdateTextForNotificationView();
67
68 if (icon_) {
69 icon_->SetImage(
70 PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_DARK));
71 icon_->SetVisible(true);
72 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010073}
74
75void PowerStatusView::LayoutDefaultView() {
76 if (default_view_right_align_) {
77 views::BoxLayout* layout =
78 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
79 kPaddingBetweenBatteryStatusAndIcon);
80 SetLayoutManager(layout);
81
82 AddChildView(percentage_label_);
83 AddChildView(time_status_label_);
84
85 icon_ = new views::ImageView;
86 AddChildView(icon_);
87 } else {
88 // PowerStatusView is left aligned on the system tray pop up item.
89 views::BoxLayout* layout =
90 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
91 kTrayPopupPaddingBetweenItems);
92 SetLayoutManager(layout);
93
94 icon_ =
95 new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight);
96 AddChildView(icon_);
97
98 AddChildView(percentage_label_);
99 AddChildView(time_status_label_);
100 }
101}
102
103void PowerStatusView::LayoutNotificationView() {
104 SetLayoutManager(
105 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
106 status_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
107 AddChildView(status_label_);
108
109 time_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
110 AddChildView(time_label_);
111}
112
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100113void PowerStatusView::UpdateTextForDefaultView() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100114 const PowerStatus& status = *PowerStatus::Get();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100115 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
116 base::string16 battery_percentage;
117 base::string16 battery_time_status;
Ben Murdocheb525c52013-07-10 11:40:50 +0100118
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100119 if (status.IsBatteryFull()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100120 battery_time_status =
121 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_FULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100122 } else {
123 battery_percentage = l10n_util::GetStringFUTF16(
124 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ONLY,
Ben Murdocheb525c52013-07-10 11:40:50 +0100125 base::IntToString16(status.GetRoundedBatteryPercent()));
126 if (status.IsUsbChargerConnected()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100127 battery_time_status = rb.GetLocalizedString(
128 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100129 } else if (status.IsBatteryTimeBeingCalculated()) {
130 battery_time_status =
131 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100132 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100133 base::TimeDelta time = status.IsBatteryCharging() ?
134 status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty();
135 if (PowerStatus::ShouldDisplayBatteryTime(time) &&
136 !status.IsBatteryDischargingOnLinePower()) {
137 int hour = 0, min = 0;
138 PowerStatus::SplitTimeIntoHoursAndMinutes(time, &hour, &min);
139 base::string16 minute = min < 10 ?
140 ASCIIToUTF16("0") + base::IntToString16(min) :
141 base::IntToString16(min);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100142 battery_time_status =
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100143 l10n_util::GetStringFUTF16(
144 status.IsBatteryCharging() ?
145 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_SHORT :
146 IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_SHORT,
147 base::IntToString16(hour),
148 minute);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100149 }
150 }
151 battery_percentage = battery_time_status.empty() ?
152 battery_percentage : battery_percentage + ASCIIToUTF16(" - ");
153 }
154 percentage_label_->SetVisible(!battery_percentage.empty());
155 percentage_label_->SetText(battery_percentage);
156 time_status_label_->SetVisible(!battery_time_status.empty());
157 time_status_label_->SetText(battery_time_status);
158}
159
160void PowerStatusView::UpdateTextForNotificationView() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100161 const PowerStatus& status = *PowerStatus::Get();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100162 if (status.IsBatteryFull()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100163 status_label_->SetText(
164 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
165 IDS_ASH_STATUS_TRAY_BATTERY_FULL));
166 } else {
Ben Murdocheb525c52013-07-10 11:40:50 +0100167 status_label_->SetText(
168 l10n_util::GetStringFUTF16(
169 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT,
170 base::IntToString16(status.GetRoundedBatteryPercent())));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100171 }
172
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100173 const base::TimeDelta time = status.IsBatteryCharging() ?
174 status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty();
Ben Murdocheb525c52013-07-10 11:40:50 +0100175
176 if (status.IsUsbChargerConnected()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100177 time_label_->SetText(
178 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
179 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE));
Ben Murdocheb525c52013-07-10 11:40:50 +0100180 } else if (status.IsBatteryTimeBeingCalculated()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100181 time_label_->SetText(
182 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
183 IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100184 } else if (PowerStatus::ShouldDisplayBatteryTime(time) &&
185 !status.IsBatteryDischargingOnLinePower()) {
186 int hour = 0, min = 0;
187 PowerStatus::SplitTimeIntoHoursAndMinutes(time, &hour, &min);
188 if (status.IsBatteryCharging()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100189 time_label_->SetText(
190 l10n_util::GetStringFUTF16(
191 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL,
192 base::IntToString16(hour),
193 base::IntToString16(min)));
194 } else {
Ben Murdocheb525c52013-07-10 11:40:50 +0100195 // This is a low battery warning prompting the user in minutes.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100196 min = hour * 60 + min;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100197 time_label_->SetText(ui::TimeFormat::TimeRemaining(
198 base::TimeDelta::FromMinutes(min)));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100199 }
200 } else {
201 time_label_->SetText(base::string16());
202 }
203}
204
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100205void PowerStatusView::ChildPreferredSizeChanged(views::View* child) {
206 PreferredSizeChanged();
207}
208
209gfx::Size PowerStatusView::GetPreferredSize() {
210 gfx::Size size = views::View::GetPreferredSize();
211 return gfx::Size(size.width(), kTrayPopupItemHeight);
212}
213
214int PowerStatusView::GetHeightForWidth(int width) {
215 return kTrayPopupItemHeight;
216}
217
218void PowerStatusView::Layout() {
219 views::View::Layout();
220
221 // Move the time_status_label_ closer to percentage_label_.
222 if (percentage_label_ && time_status_label_ &&
223 percentage_label_->visible() && time_status_label_->visible()) {
224 time_status_label_->SetX(percentage_label_->bounds().right() + 1);
225 }
226}
227
228} // namespace internal
229} // namespace ash