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