1 /*
2 * Copyright 2009-2017, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Clemens Zeidler, haiku@Clemens-Zeidler.de
7 * Kacper Kasper, kacperkasper@gmail.com
8 */
9
10
11 #include "ExtendedInfoWindow.h"
12
13 #include <ControlLook.h>
14 #include <Catalog.h>
15 #include <GroupView.h>
16 #include <LayoutBuilder.h>
17 #include <SpaceLayoutItem.h>
18 #include <TabView.h>
19
20
21 #include <algorithm>
22
23
24 #undef B_TRANSLATION_CONTEXT
25 #define B_TRANSLATION_CONTEXT "PowerStatus"
26
27
28 const size_t kLinesCount = 16;
29
30
31 // #pragma mark -
32
33
BatteryInfoView()34 BatteryInfoView::BatteryInfoView()
35 :
36 BView("battery info view", B_AUTO_UPDATE_SIZE_LIMITS)
37 {
38 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
39
40 BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0);
41 layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
42 0, B_USE_DEFAULT_SPACING);
43 SetLayout(layout);
44
45 for (size_t i = 0; i < kLinesCount; i++) {
46 BStringView* view = new BStringView("info", "");
47 AddChild(view);
48 fStringList.AddItem(view);
49 }
50 fStringList.ItemAt(0)->SetFont(be_bold_font);
51 AddChild(BSpaceLayoutItem::CreateGlue());
52 }
53
54
~BatteryInfoView()55 BatteryInfoView::~BatteryInfoView()
56 {
57 for (int32 i = 0; i < fStringList.CountItems(); i++)
58 delete fStringList.ItemAt(i);
59 }
60
61
62 void
Update(battery_info & info,acpi_extended_battery_info & extInfo)63 BatteryInfoView::Update(battery_info& info, acpi_extended_battery_info& extInfo)
64 {
65 fBatteryInfo = info;
66 fBatteryExtendedInfo = extInfo;
67
68 for (size_t i = 0; i < kLinesCount; i++) {
69 fStringList.ItemAt(i)->SetText(_GetTextForLine(i));
70 }
71 }
72
73
74 void
AttachedToWindow()75 BatteryInfoView::AttachedToWindow()
76 {
77 Window()->CenterOnScreen();
78 }
79
80
81 BString
_GetTextForLine(size_t line)82 BatteryInfoView::_GetTextForLine(size_t line)
83 {
84 BString powerUnit;
85 BString rateUnit;
86 switch (fBatteryExtendedInfo.power_unit) {
87 case 0:
88 powerUnit = B_TRANSLATE(" mWh");
89 rateUnit = B_TRANSLATE(" mW");
90 break;
91
92 case 1:
93 powerUnit = B_TRANSLATE(" mAh");
94 rateUnit = B_TRANSLATE(" mA");
95 break;
96 }
97
98 BString string;
99 switch (line) {
100 case 0: {
101 if ((fBatteryInfo.state & BATTERY_CHARGING) != 0)
102 string = B_TRANSLATE("Battery charging");
103 else if ((fBatteryInfo.state & BATTERY_DISCHARGING) != 0)
104 string = B_TRANSLATE("Battery discharging");
105 else if ((fBatteryInfo.state & BATTERY_NOT_CHARGING) != 0)
106 string = B_TRANSLATE("Battery not charging");
107 else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0
108 && fBatteryExtendedInfo.model_number[0] == '\0'
109 && fBatteryExtendedInfo.serial_number[0] == '\0'
110 && fBatteryExtendedInfo.type[0] == '\0'
111 && fBatteryExtendedInfo.oem_info[0] == '\0')
112 string = B_TRANSLATE("Empty battery slot");
113 else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0)
114 string = B_TRANSLATE("Damaged or missing battery");
115 else
116 string = B_TRANSLATE("Battery unused");
117 break;
118 }
119 case 1:
120 string = B_TRANSLATE("Capacity: ");
121 string << fBatteryInfo.capacity;
122 string << powerUnit;
123 break;
124 case 2:
125 string = B_TRANSLATE("Last full charge: ");
126 string << fBatteryInfo.full_capacity;
127 string << powerUnit;
128 break;
129 case 3:
130 string = B_TRANSLATE("Current rate: ");
131 string << fBatteryInfo.current_rate;
132 string << rateUnit;
133 break;
134 // case 4 missed intentionally
135 case 5:
136 string = B_TRANSLATE("Design capacity: ");
137 string << fBatteryExtendedInfo.design_capacity;
138 string << powerUnit;
139 break;
140 case 6:
141 string = B_TRANSLATE("Technology: ");
142 if (fBatteryExtendedInfo.technology == 0)
143 string << B_TRANSLATE("non-rechargeable");
144 else if (fBatteryExtendedInfo.technology == 1)
145 string << B_TRANSLATE("rechargeable");
146 else
147 string << "?";
148 break;
149 case 7:
150 string = B_TRANSLATE("Design voltage: ");
151 string << fBatteryExtendedInfo.design_voltage;
152 string << B_TRANSLATE(" mV");
153 break;
154 case 8:
155 string = B_TRANSLATE("Design capacity warning: ");
156 string << fBatteryExtendedInfo.design_capacity_warning;
157 string << powerUnit;
158 break;
159 case 9:
160 string = B_TRANSLATE("Design capacity low warning: ");
161 string << fBatteryExtendedInfo.design_capacity_low;
162 string << powerUnit;
163 break;
164 case 10:
165 string = B_TRANSLATE("Capacity granularity 1: ");
166 string << fBatteryExtendedInfo.capacity_granularity_1;
167 string << powerUnit;
168 break;
169 case 11:
170 string = B_TRANSLATE("Capacity granularity 2: ");
171 string << fBatteryExtendedInfo.capacity_granularity_2;
172 string << powerUnit;
173 break;
174 case 12:
175 string = B_TRANSLATE("Model number: ");
176 string << fBatteryExtendedInfo.model_number;
177 break;
178 case 13:
179 string = B_TRANSLATE("Serial number: ");
180 string << fBatteryExtendedInfo.serial_number;
181 break;
182 case 14:
183 string = B_TRANSLATE("Type: ");
184 string += fBatteryExtendedInfo.type;
185 break;
186 case 15:
187 string = B_TRANSLATE("OEM info: ");
188 string += fBatteryExtendedInfo.oem_info;
189 break;
190 default:
191 string = "";
192 break;
193 }
194 return string;
195 }
196
197
198 // #pragma mark -
199
200
BatteryTab(BatteryInfoView * target,ExtPowerStatusView * view)201 BatteryTab::BatteryTab(BatteryInfoView* target,
202 ExtPowerStatusView* view)
203 :
204 fBatteryView(view)
205 {
206 }
207
208
~BatteryTab()209 BatteryTab::~BatteryTab()
210 {
211 }
212
213
214 void
Select(BView * owner)215 BatteryTab::Select(BView* owner)
216 {
217 BTab::Select(owner);
218 fBatteryView->Select();
219 }
220
221 void
DrawFocusMark(BView * owner,BRect frame)222 BatteryTab::DrawFocusMark(BView* owner, BRect frame)
223 {
224 float vertOffset = IsSelected() ? 3 : 2;
225 float horzOffset = IsSelected() ? 2 : 4;
226 float width = frame.Width() - horzOffset * 2;
227 BPoint pt1((frame.left + frame.right - width) / 2.0 + horzOffset,
228 frame.bottom - vertOffset);
229 BPoint pt2((frame.left + frame.right + width) / 2.0,
230 frame.bottom - vertOffset);
231 owner->SetHighUIColor(B_KEYBOARD_NAVIGATION_COLOR);
232 owner->StrokeLine(pt1, pt2);
233 }
234
235
236 void
DrawLabel(BView * owner,BRect frame)237 BatteryTab::DrawLabel(BView* owner, BRect frame)
238 {
239 BRect rect = frame;
240 float size = std::min(rect.Width(), rect.Height());
241 rect.right = rect.left + size;
242 rect.bottom = rect.top + size;
243 if (frame.Width() > rect.Height()) {
244 rect.OffsetBy((frame.Width() - size) / 2.0f, 0.0f);
245 } else {
246 rect.OffsetBy(0.0f, (frame.Height() - size) / 2.0f);
247 }
248 fBatteryView->DrawTo(owner, rect);
249 }
250
251
BatteryTabView(const char * name)252 BatteryTabView::BatteryTabView(const char* name)
253 :
254 BTabView(name)
255 {
256 }
257
258
~BatteryTabView()259 BatteryTabView::~BatteryTabView()
260 {
261 }
262
263
264 BRect
TabFrame(int32 index) const265 BatteryTabView::TabFrame(int32 index) const
266 {
267 BRect bounds(Bounds());
268 float width = TabHeight();
269 float height = TabHeight();
270 float offset = BControlLook::ComposeSpacing(B_USE_WINDOW_SPACING);
271 switch (TabSide()) {
272 case kTopSide:
273 return BRect(offset + index * width, 0.0f,
274 offset + index * width + width, height);
275 case kBottomSide:
276 return BRect(offset + index * width, bounds.bottom - height,
277 offset + index * width + width, bounds.bottom);
278 case kLeftSide:
279 return BRect(0.0f, offset + index * width, height,
280 offset + index * width + width);
281 case kRightSide:
282 return BRect(bounds.right - height, offset + index * width,
283 bounds.right, offset + index * width + width);
284 default:
285 return BRect();
286 }
287 }
288
289
ExtPowerStatusView(PowerStatusDriverInterface * interface,BRect frame,int32 resizingMode,int batteryID,BatteryInfoView * batteryInfoView,ExtendedInfoWindow * window)290 ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface,
291 BRect frame, int32 resizingMode, int batteryID,
292 BatteryInfoView* batteryInfoView, ExtendedInfoWindow* window)
293 :
294 PowerStatusView(interface, frame, resizingMode, batteryID),
295 fExtendedInfoWindow(window),
296 fBatteryInfoView(batteryInfoView),
297 fBatteryTabView(window->GetBatteryTabView())
298 {
299 }
300
301
302 void
Select(bool select)303 ExtPowerStatusView::Select(bool select)
304 {
305 fSelected = select;
306 Update(true);
307 }
308
309
310 bool
IsCritical()311 ExtPowerStatusView::IsCritical()
312 {
313 return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0;
314 }
315
316
317 void
Update(bool force,bool notify)318 ExtPowerStatusView::Update(bool force, bool notify)
319 {
320 PowerStatusView::Update(force);
321 if (!fSelected)
322 return;
323
324 acpi_extended_battery_info extInfo;
325 fDriverInterface->GetExtendedBatteryInfo(fBatteryID, &extInfo);
326
327 fBatteryInfoView->Update(fBatteryInfo, extInfo);
328 fBatteryInfoView->Invalidate();
329
330 fBatteryTabView->Invalidate();
331 }
332
333
334 // #pragma mark -
335
336
ExtendedInfoWindow(PowerStatusDriverInterface * interface)337 ExtendedInfoWindow::ExtendedInfoWindow(PowerStatusDriverInterface* interface)
338 :
339 BWindow(BRect(100, 150, 500, 500), B_TRANSLATE("Extended battery info"),
340 B_TITLED_WINDOW,
341 B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AVOID_FRONT
342 | B_ASYNCHRONOUS_CONTROLS),
343 fDriverInterface(interface),
344 fSelectedView(NULL)
345 {
346 fDriverInterface->AcquireReference();
347
348 BRect batteryRect(BPoint(0, 0), be_control_look->ComposeIconSize(50));
349 float tabHeight = ceilf(batteryRect.Height() * 1.4f);
350 fBatteryTabView = new BatteryTabView("tabview");
351 fBatteryTabView->SetBorder(B_NO_BORDER);
352 fBatteryTabView->SetTabHeight(tabHeight);
353 fBatteryTabView->SetTabSide(BTabView::kLeftSide);
354 BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
355 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0)
356 .Add(fBatteryTabView);
357
358 for (int i = 0; i < interface->GetBatteryCount(); i++) {
359 BatteryInfoView* batteryInfoView = new BatteryInfoView();
360 ExtPowerStatusView* view = new ExtPowerStatusView(interface,
361 batteryRect, B_FOLLOW_NONE, i, batteryInfoView, this);
362 BatteryTab* tab = new BatteryTab(batteryInfoView, view);
363 fBatteryTabView->AddTab(batteryInfoView, tab);
364 // Has to be added, otherwise it won't get info updates
365 view->Hide();
366 AddChild(view);
367
368 fBatteryViewList.AddItem(view);
369 fDriverInterface->StartWatching(view);
370 if (!view->IsCritical())
371 fSelectedView = view;
372 }
373
374 if (!fSelectedView && fBatteryViewList.CountItems() > 0)
375 fSelectedView = fBatteryViewList.ItemAt(0);
376 fSelectedView->Select();
377
378 BSize size = GetLayout()->PreferredSize();
379 ResizeTo(size.width, size.height);
380 }
381
382
~ExtendedInfoWindow()383 ExtendedInfoWindow::~ExtendedInfoWindow()
384 {
385 for (int i = 0; i < fBatteryViewList.CountItems(); i++)
386 fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i));
387
388 fDriverInterface->ReleaseReference();
389 }
390
391
392 BatteryTabView*
GetBatteryTabView()393 ExtendedInfoWindow::GetBatteryTabView()
394 {
395 return fBatteryTabView;
396 }
397