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_TRANSLATION_CONTEXT 19#define B_TRANSLATION_CONTEXT "PowerStatus" 20 21 22const int kLineSpacing = 5; 23 24 25FontString::FontString() 26{ 27 font = be_plain_font; 28} 29 30 31// #pragma mark - 32 33 34BatteryInfoView::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 44BatteryInfoView::~BatteryInfoView() 45{ 46 _ClearStringList(); 47} 48 49 50void 51BatteryInfoView::Update(battery_info& info, acpi_extended_battery_info& extInfo) 52{ 53 fBatteryInfo = info; 54 fBatteryExtendedInfo = extInfo; 55 56 _FillStringList(); 57} 58 59 60void 61BatteryInfoView::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 78void 79BatteryInfoView::GetPreferredSize(float* width, float* height) 80{ 81 *width = fPreferredSize.width; 82 *height = fPreferredSize.height; 83} 84 85 86void 87BatteryInfoView::AttachedToWindow() 88{ 89 Window()->CenterOnScreen(); 90} 91 92 93BSize 94BatteryInfoView::_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 110void 111BatteryInfoView::_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 244void 245BatteryInfoView::_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 254void 255BatteryInfoView::_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 267ExtPowerStatusView::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 279void 280ExtPowerStatusView::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 291void 292ExtPowerStatusView::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 304void 305ExtPowerStatusView::Select(bool select) 306{ 307 fSelected = select; 308 Update(true); 309} 310 311 312bool 313ExtPowerStatusView::IsCritical() 314{ 315 return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0; 316} 317 318 319void 320ExtPowerStatusView::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 337ExtendedInfoWindow::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 402ExtendedInfoWindow::~ExtendedInfoWindow() 403{ 404 for (int i = 0; i < fBatteryViewList.CountItems(); i++) 405 fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i)); 406 407 fDriverInterface->ReleaseReference(); 408} 409 410 411BatteryInfoView* 412ExtendedInfoWindow::GetExtendedBatteryInfoView() 413{ 414 return fBatteryInfoView; 415} 416 417 418void 419ExtendedInfoWindow::BatterySelected(ExtPowerStatusView* view) 420{ 421 if (fSelectedView) { 422 fSelectedView->Select(false); 423 fSelectedView->Invalidate(); 424 } 425 426 fSelectedView = view; 427} 428