Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(945)

Side by Side Diff: ash/system/power/tray_power_date.cc

Issue 9562008: ash uber tray: Add entry for power and date. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/power/tray_power_date.h"
6
7 #include "ash/shell.h"
8 #include "ash/system/power/power_supply_status.h"
9 #include "ash/system/tray/system_tray_delegate.h"
10 #include "base/i18n/time_formatting.h"
11 #include "base/stringprintf.h"
12 #include "base/time.h"
13 #include "base/timer.h"
14 #include "base/utf_string_conversions.h"
15 #include "grit/ui_resources.h"
16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "third_party/skia/include/core/SkRect.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/image/image.h"
20 #include "ui/gfx/size.h"
21 #include "ui/views/controls/button/button.h"
22 #include "ui/views/controls/button/text_button.h"
23 #include "ui/views/controls/image_view.h"
24 #include "ui/views/controls/label.h"
25 #include "ui/views/layout/box_layout.h"
26 #include "ui/views/view.h"
27 #include "unicode/datefmt.h"
28 #include "unicode/fieldpos.h"
29 #include "unicode/fmtable.h"
30
31 namespace ash {
32 namespace internal {
33
34 namespace {
35 // Width and height of battery images.
36 const int kBatteryImageHeight = 26;
37 const int kBatteryImageWidth = 24;
38 // Number of different power states.
39 const int kNumPowerImages = 20;
40 // Amount of slop to add into the timer to make sure we're into the next minute
41 // when the timer goes off.
42 const int kTimerSlopSeconds = 1;
43
44 string16 FormatNicely(const base::Time& time) {
45 icu::UnicodeString date_string;
46
47 scoped_ptr<icu::DateFormat> formatter(
48 icu::DateFormat::createDateInstance(icu::DateFormat::kFull));
49 icu::FieldPosition position;
50 position.setField(UDAT_DAY_OF_WEEK_FIELD);
51 formatter->format(static_cast<UDate>(time.ToDoubleT() * 1000), date_string,
52 position);
stevenjb 2012/03/02 18:18:26 nit: date_string on separate line, and aligned wit
sadrul 2012/03/02 18:52:42 Done. (style-guide allows both)
stevenjb 2012/03/02 19:31:46 The chromium style guide says "put each argument o
sadrul 2012/03/02 19:34:54 This is for function definitions. The next bullet:
53 icu::UnicodeString day = date_string.retainBetween(position.getBeginIndex(),
54 position.getEndIndex());
stevenjb 2012/03/02 18:18:26 nit: aligin 2nd arg with 1st, or both on second li
sadrul 2012/03/02 18:52:42 ditto
55
56 date_string.remove();
57 formatter.reset(
58 icu::DateFormat::createDateInstance(icu::DateFormat::kMedium));
59 formatter->format(static_cast<UDate>(time.ToDoubleT() * 1000), date_string);
60
61 date_string += "\n";
62 date_string += day;
63
64 return string16(date_string.getBuffer(),
65 static_cast<size_t>(date_string.length()));
66 }
67
68 }
69
70 namespace tray {
71
72 // This view is used for both the tray and the popup.
73 class DateView : public views::Label {
74 public:
75 enum TimeType {
76 TIME,
77 DATE
78 };
79
80 DateView(base::HourClockType hour_type, TimeType type)
81 : hour_type_(hour_type),
82 type_(type) {
83 UpdateText();
84 }
85
86 virtual ~DateView() {
87 timer_.Stop();
88 }
89
90 private:
91 void UpdateText() {
92 base::Time now = base::Time::Now();
93 if (type_ == TIME) {
94 SetText(base::TimeFormatTimeOfDayWithHourClockType(now, hour_type_,
95 base::kDropAmPm));
stevenjb 2012/03/02 18:18:26 nit: alignment
sadrul 2012/03/02 18:52:42 Done.
96 } else {
97 SetText(FormatNicely(now));
98 }
99
100 SetTooltipText(base::TimeFormatFriendlyDate(now));
101 SchedulePaint();
102
103 // Try to set the timer to go off at the next change of the minute. We don't
104 // want to have the timer go off more than necessary since that will cause
105 // the CPU to wake up and consume power.
106 base::Time::Exploded exploded;
107 now.LocalExplode(&exploded);
108
109 // Often this will be called at minute boundaries, and we'll actually want
110 // 60 seconds from now.
111 int seconds_left = 60 - exploded.second;
112 if (seconds_left == 0)
113 seconds_left = 60;
114
115 // Make sure that the timer fires on the next minute. Without this, if it is
116 // called just a teeny bit early, then it will skip the next minute.
117 seconds_left += kTimerSlopSeconds;
118
119 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(seconds_left), this,
120 &DateView::UpdateText);
stevenjb 2012/03/02 18:18:26 nit: arg alignment
121 }
122
123 // Overridden from views::View.
124 virtual void OnLocaleChanged() OVERRIDE {
125 UpdateText();
126 }
127
128 base::OneShotTimer<DateView> timer_;
129 base::HourClockType hour_type_;
130 TimeType type_;
131
132 DISALLOW_COPY_AND_ASSIGN(DateView);
133 };
134
135 // This view is used only for the tray.
136 class PowerTrayView : public views::ImageView {
137 public:
138 PowerTrayView() {
139 UpdateImage();
140 }
141
142 virtual ~PowerTrayView() {
143 }
144
145 void UpdatePowerStatus(const PowerSupplyStatus& status) {
146 supply_status_ = status;
147 // Sanitize.
148 if (supply_status_.battery_is_full)
149 supply_status_.battery_percentage = 100.0;
150
151 UpdateImage();
152 }
153
154 private:
155 void UpdateImage() {
156 SkBitmap image;
157 gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
158 IDR_AURA_UBER_TRAY_POWER_SMALL);
159
160 int image_index = 0;
161 if (supply_status_.battery_percentage >= 100) {
162 image_index = kNumPowerImages - 1;
163 } else if (!supply_status_.battery_is_present) {
164 image_index = kNumPowerImages;
165 } else {
166 image_index = static_cast<int> (
167 supply_status_.battery_percentage / 100.0 *
168 (kNumPowerImages - 1));
169 image_index =
170 std::max(std::min(image_index, kNumPowerImages - 2), 0);
171 }
172
173 SkIRect region = SkIRect::MakeXYWH(
174 image_index * kBatteryImageWidth,
175 supply_status_.line_power_on ? 0 : kBatteryImageHeight,
176 kBatteryImageWidth, kBatteryImageHeight);
177 all.ToSkBitmap()->extractSubset(&image, region);
178
179 SetImage(image);
180 }
181
182 PowerSupplyStatus supply_status_;
183
184 DISALLOW_COPY_AND_ASSIGN(PowerTrayView);
185 };
186
187 // This view is used only for the popup.
188 class PowerPopupView : public views::Label {
189 public:
190 PowerPopupView() {
191 SetHorizontalAlignment(ALIGN_RIGHT);
192 UpdateText();
193 }
194
195 virtual ~PowerPopupView() {
196 }
197
198 void UpdatePowerStatus(const PowerSupplyStatus& status) {
199 supply_status_ = status;
200 // Sanitize.
201 if (supply_status_.battery_is_full)
202 supply_status_.battery_percentage = 100.0;
203
204 UpdateText();
205 }
206
207 private:
208 void UpdateText() {
209 base::TimeDelta time = base::TimeDelta::FromSeconds(
210 supply_status_.line_power_on ?
211 supply_status_.battery_seconds_to_full :
212 supply_status_.battery_seconds_to_empty);
213 int hour = time.InHours();
214 int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
215 // TODO: Translation
216 SetText(ASCIIToUTF16(base::StringPrintf("Battery: %.0lf%%\n%dh%02dm",
217 supply_status_.battery_percentage,
218 hour, min)));
219 }
220
221 PowerSupplyStatus supply_status_;
222
223 DISALLOW_COPY_AND_ASSIGN(PowerPopupView);
224 };
225
226 } // namespace tray
227
228 TrayPowerDate::TrayPowerDate()
229 : power_(NULL),
230 power_tray_(NULL) {
231 }
232
233 TrayPowerDate::~TrayPowerDate() {
234 }
235
236 views::View* TrayPowerDate::CreateTrayView() {
237 date_tray_.reset(new tray::DateView(base::k24HourClock,
238 tray::DateView::TIME));
239 date_tray_->SetFont(date_tray_->font().DeriveFont(-1, gfx::Font::BOLD));
240 date_tray_->SetAutoColorReadabilityEnabled(false);
241 date_tray_->SetEnabledColor(SK_ColorWHITE);
242
243 power_tray_.reset(new tray::PowerTrayView());
244
245 views::View* container = new views::View;
246 container->SetLayoutManager(new views::BoxLayout(
247 views::BoxLayout::kHorizontal, 0, 0, 0));
248 container->AddChildView(power_tray_.get());
249 container->AddChildView(date_tray_.get());
250
251 return container;
252 }
253
254 views::View* TrayPowerDate::CreateDefaultView() {
255 date_.reset(new tray::DateView(base::k24HourClock,
256 tray::DateView::DATE));
stevenjb 2012/03/02 18:18:26 nit: alignment
sadrul 2012/03/02 18:52:42 Done.
257 power_.reset(new tray::PowerPopupView());
258
259 views::View* container = new views::View;
260 views::BoxLayout* layout = new
261 views::BoxLayout(views::BoxLayout::kHorizontal, 0, 10, 0);
262 layout->set_spread_blank_space(true);
263 container->SetLayoutManager(layout);
264 container->set_background(views::Background::CreateSolidBackground(
265 SkColorSetARGB(255, 240, 240, 240)));
stevenjb 2012/03/02 18:18:26 nit: alignment
sadrul 2012/03/02 18:52:42 Done.
266 container->AddChildView(date_.get());
267 container->AddChildView(power_.get());
268 return container;
269 }
270
271 views::View* TrayPowerDate::CreateDetailedView() {
272 return NULL;
273 }
274
275 void TrayPowerDate::DestroyTrayView() {
276 date_tray_.reset();
277 power_tray_.reset();
278 }
279
280 void TrayPowerDate::DestroyDefaultView() {
281 date_.reset();
282 power_.reset();
283 }
284
285 void TrayPowerDate::DestroyDetailedView() {
286 }
287
288 void TrayPowerDate::OnPowerStatusChanged(const PowerSupplyStatus& status) {
289 power_tray_->UpdatePowerStatus(status);
290 if (power_.get())
291 power_->UpdatePowerStatus(status);
292 }
293
294 } // namespace internal
295 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698