xref: /haiku/src/apps/powerstatus/ExtendedInfoWindow.cpp (revision 0d452c8f34013b611a54c746a71c05e28796eae2)
1 /*
2  * Copyright 2009, 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  */
8 
9 
10 #include "ExtendedInfoWindow.h"
11 
12 #include <Box.h>
13 #include <Catalog.h>
14 #include <GroupView.h>
15 #include <SpaceLayoutItem.h>
16 
17 
18 #undef B_TRANSLATE_CONTEXT
19 #define B_TRANSLATE_CONTEXT "PowerStatus"
20 
21 
22 const int kLineSpacing = 5;
23 
24 
25 FontString::FontString()
26 {
27 	font = be_plain_font;
28 }
29 
30 
31 //	#pragma mark -
32 
33 
34 BatteryInfoView::BatteryInfoView()
35 	:
36 	BView("battery info view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
37 	fPreferredSize(200, 200),
38 	fMaxStringSize(0, 0)
39 {
40 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
41 }
42 
43 
44 BatteryInfoView::~BatteryInfoView()
45 {
46 	_ClearStringList();
47 }
48 
49 
50 void
51 BatteryInfoView::Update(battery_info& info, acpi_extended_battery_info& extInfo)
52 {
53 	fBatteryInfo = info;
54 	fBatteryExtendedInfo = extInfo;
55 
56 	_FillStringList();
57 }
58 
59 
60 void
61 BatteryInfoView::Draw(BRect updateRect)
62 {
63 	SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
64 
65 	BPoint point(10, 10);
66 
67 	float space = _MeasureString("").height + kLineSpacing;
68 
69 	for (int i = 0; i < fStringList.CountItems(); i++) {
70 		FontString* fontString = fStringList.ItemAt(i);
71 		SetFont(fontString->font);
72 		DrawString(fontString->string.String(), point);
73 		point.y += space;
74 	}
75 }
76 
77 
78 void
79 BatteryInfoView::GetPreferredSize(float* width, float* height)
80 {
81 	*width = fPreferredSize.width;
82 	*height = fPreferredSize.height;
83 }
84 
85 
86 void
87 BatteryInfoView::AttachedToWindow()
88 {
89 	Window()->CenterOnScreen();
90 }
91 
92 
93 BSize
94 BatteryInfoView::_MeasureString(const BString& string)
95 {
96 	BFont font;
97 	GetFont(&font);
98 	BSize size;
99 
100 	size.width = font.StringWidth(string);
101 
102 	font_height height;
103 	font.GetHeight(&height);
104 	size.height = height.ascent + height.descent;
105 
106 	return size;
107 }
108 
109 
110 void
111 BatteryInfoView::_FillStringList()
112 {
113 	_ClearStringList();
114 
115 	BString powerUnit;
116 	BString rateUnit;
117 	switch (fBatteryExtendedInfo.power_unit) {
118 		case 0:
119 			powerUnit = B_TRANSLATE(" mWh");
120 			rateUnit = B_TRANSLATE(" mW");
121 			break;
122 
123 		case 1:
124 			powerUnit = B_TRANSLATE(" mAh");
125 			rateUnit = B_TRANSLATE(" mA");
126 			break;
127 	}
128 
129 	FontString* fontString;
130 
131 	fontString = new FontString;
132 	fStringList.AddItem(fontString);
133 	fontString->font = be_bold_font;
134 
135 	if ((fBatteryInfo.state & BATTERY_CHARGING) != 0)
136 		fontString->string = B_TRANSLATE("Battery charging");
137 	else if ((fBatteryInfo.state & BATTERY_DISCHARGING) != 0)
138 		fontString->string = B_TRANSLATE("Battery discharging");
139 	else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0
140 		&& fBatteryExtendedInfo.model_number[0] == '\0'
141 		&& fBatteryExtendedInfo.serial_number[0] == '\0'
142 		&& fBatteryExtendedInfo.type[0] == '\0'
143 		&& fBatteryExtendedInfo.oem_info[0] == '\0')
144 		fontString->string = B_TRANSLATE("Empty battery slot");
145 	else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0)
146 		fontString->string = B_TRANSLATE("Damaged battery");
147 	else
148 		fontString->string = B_TRANSLATE("Battery unused");
149 
150 	fontString = new FontString;
151 	fontString->string = B_TRANSLATE("Capacity: ");
152 	fontString->string << fBatteryInfo.capacity;
153 	fontString->string << powerUnit;
154 	_AddToStringList(fontString);
155 
156 	fontString = new FontString;
157 	fontString->string = B_TRANSLATE("Last full charge: ");
158 	fontString->string << fBatteryInfo.full_capacity;
159 	fontString->string << powerUnit;
160 	_AddToStringList(fontString);
161 
162 	fontString = new FontString;
163 	fontString->string = B_TRANSLATE("Current rate: ");
164 	fontString->string << fBatteryInfo.current_rate;
165 	fontString->string << rateUnit;
166 	_AddToStringList(fontString);
167 
168 	// empty line
169 	fontString = new FontString;
170 	_AddToStringList(fontString);
171 
172 	fontString = new FontString;
173 	fontString->string = B_TRANSLATE("Design capacity: ");
174 	fontString->string << fBatteryExtendedInfo.design_capacity;
175 	fontString->string << powerUnit;
176 	_AddToStringList(fontString);
177 
178 	fontString = new FontString;
179 	fontString->string = B_TRANSLATE("Technology: ");
180 	if (fBatteryExtendedInfo.technology == 0)
181 		fontString->string << B_TRANSLATE("non-rechargeable");
182 	else if (fBatteryExtendedInfo.technology == 1)
183 		fontString->string << B_TRANSLATE("rechargeable");
184 	else
185 		fontString->string << "?";
186 	_AddToStringList(fontString);
187 
188 	fontString = new FontString;
189 	fontString->string = B_TRANSLATE("Design voltage: ");
190 	fontString->string << fBatteryExtendedInfo.design_voltage;
191 	fontString->string << B_TRANSLATE(" mV");
192 	_AddToStringList(fontString);
193 
194 	fontString = new FontString;
195 	fontString->string = B_TRANSLATE("Design capacity warning: ");
196 	fontString->string << fBatteryExtendedInfo.design_capacity_warning;
197 	fontString->string << powerUnit;
198 	_AddToStringList(fontString);
199 
200 	fontString = new FontString;
201 	fontString->string = B_TRANSLATE("Design capacity low warning: ");
202 	fontString->string << fBatteryExtendedInfo.design_capacity_low;
203 	fontString->string << powerUnit;
204 	_AddToStringList(fontString);
205 
206 	fontString = new FontString;
207 	fontString->string = B_TRANSLATE("Capacity granularity 1: ");
208 	fontString->string << fBatteryExtendedInfo.capacity_granularity_1;
209 	fontString->string << powerUnit;
210 	_AddToStringList(fontString);
211 
212 	fontString = new FontString;
213 	fontString->string = B_TRANSLATE("Capacity granularity 2: ");
214 	fontString->string << fBatteryExtendedInfo.capacity_granularity_2;
215 	fontString->string << powerUnit;
216 	_AddToStringList(fontString);
217 
218 	fontString = new FontString;
219 	fontString->string = B_TRANSLATE("Model number: ");
220 	fontString->string << fBatteryExtendedInfo.model_number;
221 	_AddToStringList(fontString);
222 
223 	fontString = new FontString;
224 	fontString->string = B_TRANSLATE("Serial number: ");
225 	fontString->string << fBatteryExtendedInfo.serial_number;
226 	_AddToStringList(fontString);
227 
228 	fontString = new FontString;
229 	fontString->string = B_TRANSLATE("Type: ");
230 	fontString->string += fBatteryExtendedInfo.type;
231 	_AddToStringList(fontString);
232 
233 	fontString = new FontString;
234 	fontString->string = B_TRANSLATE("OEM info: ");
235 	fontString->string += fBatteryExtendedInfo.oem_info;
236 	_AddToStringList(fontString);
237 
238 	fPreferredSize.width = fMaxStringSize.width + 10;
239 	fPreferredSize.height = (fMaxStringSize.height + kLineSpacing) *
240 		fStringList.CountItems();
241 }
242 
243 
244 void
245 BatteryInfoView::_AddToStringList(FontString* fontString)
246 {
247 	fStringList.AddItem(fontString);
248 	BSize stringSize = _MeasureString(fontString->string);
249 	if (fMaxStringSize.width < stringSize.width)
250 		fMaxStringSize = stringSize;
251 }
252 
253 
254 void
255 BatteryInfoView::_ClearStringList()
256 {
257 	for (int i = 0; i < fStringList.CountItems(); i ++)
258 		delete fStringList.ItemAt(i);
259 	fStringList.MakeEmpty();
260 	fMaxStringSize = BSize(0, 0);
261 }
262 
263 
264 //	#pragma mark -
265 
266 
267 ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface,
268 		BRect frame, int32 resizingMode, int batteryID,
269 		ExtendedInfoWindow* window)
270 	:
271 	PowerStatusView(interface, frame, resizingMode, batteryID),
272 	fExtendedInfoWindow(window),
273 	fBatteryInfoView(window->GetExtendedBatteryInfoView()),
274 	fSelected(false)
275 {
276 }
277 
278 
279 void
280 ExtPowerStatusView::Draw(BRect updateRect)
281 {
282 	if (fSelected)
283 		SetLowColor(102, 152, 203);
284 	else
285 		SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
286 
287 	PowerStatusView::Draw(updateRect);
288 }
289 
290 
291 void
292 ExtPowerStatusView::MouseDown(BPoint where)
293 {
294 	if (!fSelected) {
295 		fSelected = true;
296 		Update(true);
297 		if (ExtendedInfoWindow* window
298 				= dynamic_cast<ExtendedInfoWindow*>(Window()))
299 			window->BatterySelected(this);
300 	}
301 }
302 
303 
304 void
305 ExtPowerStatusView::Select(bool select)
306 {
307 	fSelected = select;
308 	Update(true);
309 }
310 
311 
312 bool
313 ExtPowerStatusView::IsCritical()
314 {
315 	return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0;
316 }
317 
318 
319 void
320 ExtPowerStatusView::Update(bool force)
321 {
322 	PowerStatusView::Update(force);
323 	if (!fSelected)
324 		return;
325 
326 	acpi_extended_battery_info extInfo;
327 	fDriverInterface->GetExtendedBatteryInfo(&extInfo, fBatteryID);
328 
329 	fBatteryInfoView->Update(fBatteryInfo, extInfo);
330 	fBatteryInfoView->Invalidate();
331 }
332 
333 
334 //	#pragma mark -
335 
336 
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 	BView *view = new BView(Bounds(), "view", B_FOLLOW_ALL, 0);
349 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
350 	AddChild(view);
351 
352 	BGroupLayout* mainLayout = new BGroupLayout(B_VERTICAL);
353 	mainLayout->SetSpacing(10);
354 	mainLayout->SetInsets(10, 10, 10, 10);
355 	view->SetLayout(mainLayout);
356 
357 	BRect rect = Bounds();
358 	rect.InsetBy(5, 5);
359 	BBox *infoBox = new BBox(rect, B_TRANSLATE("Power status box"));
360 	infoBox->SetLabel(B_TRANSLATE("Battery info"));
361 	BGroupLayout* infoLayout = new BGroupLayout(B_HORIZONTAL);
362 	infoLayout->SetInsets(10, infoBox->TopBorderOffset() * 2 + 10, 10, 10);
363 	infoLayout->SetSpacing(10);
364 	infoBox->SetLayout(infoLayout);
365 	mainLayout->AddView(infoBox);
366 
367 	BGroupView* batteryView = new BGroupView(B_VERTICAL);
368 	batteryView->GroupLayout()->SetSpacing(10);
369 	infoLayout->AddView(batteryView);
370 
371 	// create before the battery views
372 	fBatteryInfoView = new BatteryInfoView();
373 
374 	BGroupLayout* batteryLayout = batteryView->GroupLayout();
375 	BRect batteryRect(0, 0, 50, 30);
376 	for (int i = 0; i < interface->GetBatteryCount(); i++) {
377 		ExtPowerStatusView* view = new ExtPowerStatusView(interface,
378 			batteryRect, B_FOLLOW_NONE, i, this);
379 		view->SetExplicitMaxSize(BSize(70, 80));
380 		view->SetExplicitMinSize(BSize(70, 80));
381 
382 		batteryLayout->AddView(view);
383 		fBatteryViewList.AddItem(view);
384 		fDriverInterface->StartWatching(view);
385 		if (!view->IsCritical())
386 			fSelectedView = view;
387 	}
388 
389 	batteryLayout->AddItem(BSpaceLayoutItem::CreateGlue());
390 
391 	infoLayout->AddView(fBatteryInfoView);
392 
393 	if (!fSelectedView && fBatteryViewList.CountItems() > 0)
394 		fSelectedView = fBatteryViewList.ItemAt(0);
395 	fSelectedView->Select();
396 
397 	BSize size = mainLayout->PreferredSize();
398 	ResizeTo(size.width, size.height);
399 }
400 
401 
402 ExtendedInfoWindow::~ExtendedInfoWindow()
403 {
404 	for (int i = 0; i < fBatteryViewList.CountItems(); i++)
405 		fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i));
406 
407 	fDriverInterface->ReleaseReference();
408 }
409 
410 
411 BatteryInfoView*
412 ExtendedInfoWindow::GetExtendedBatteryInfoView()
413 {
414 	return fBatteryInfoView;
415 }
416 
417 
418 void
419 ExtendedInfoWindow::BatterySelected(ExtPowerStatusView* view)
420 {
421 	if (fSelectedView) {
422 		fSelectedView->Select(false);
423 		fSelectedView->Invalidate();
424 	}
425 
426 	fSelectedView = view;
427 }
428