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
PowerStatusView(ViewType view_type,bool default_view_right_align)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
~PowerStatusView()53 PowerStatusView::~PowerStatusView() {
54 PowerStatus::Get()->RemoveObserver(this);
55 }
56
OnPowerStatusChanged()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
LayoutDefaultView()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
LayoutNotificationView()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
UpdateTextForDefaultView()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
UpdateTextForNotificationView()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
ChildPreferredSizeChanged(views::View * child)197 void PowerStatusView::ChildPreferredSizeChanged(views::View* child) {
198 PreferredSizeChanged();
199 }
200
GetPreferredSize()201 gfx::Size PowerStatusView::GetPreferredSize() {
202 gfx::Size size = views::View::GetPreferredSize();
203 return gfx::Size(size.width(), kTrayPopupItemHeight);
204 }
205
GetHeightForWidth(int width)206 int PowerStatusView::GetHeightForWidth(int width) {
207 return kTrayPopupItemHeight;
208 }
209
Layout()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