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 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 55 BatteryInfoView::~BatteryInfoView() 56 { 57 for (int32 i = 0; i < fStringList.CountItems(); i++) 58 delete fStringList.ItemAt(i); 59 } 60 61 62 void 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 75 BatteryInfoView::AttachedToWindow() 76 { 77 Window()->CenterOnScreen(); 78 } 79 80 81 BString 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_CRITICAL_STATE) != 0 106 && fBatteryExtendedInfo.model_number[0] == '\0' 107 && fBatteryExtendedInfo.serial_number[0] == '\0' 108 && fBatteryExtendedInfo.type[0] == '\0' 109 && fBatteryExtendedInfo.oem_info[0] == '\0') 110 string = B_TRANSLATE("Empty battery slot"); 111 else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0) 112 string = B_TRANSLATE("Damaged battery"); 113 else 114 string = B_TRANSLATE("Battery unused"); 115 break; 116 } 117 case 1: 118 string = B_TRANSLATE("Capacity: "); 119 string << fBatteryInfo.capacity; 120 string << powerUnit; 121 break; 122 case 2: 123 string = B_TRANSLATE("Last full charge: "); 124 string << fBatteryInfo.full_capacity; 125 string << powerUnit; 126 break; 127 case 3: 128 string = B_TRANSLATE("Current rate: "); 129 string << fBatteryInfo.current_rate; 130 string << rateUnit; 131 break; 132 // case 4 missed intentionally 133 case 5: 134 string = B_TRANSLATE("Design capacity: "); 135 string << fBatteryExtendedInfo.design_capacity; 136 string << powerUnit; 137 break; 138 case 6: 139 string = B_TRANSLATE("Technology: "); 140 if (fBatteryExtendedInfo.technology == 0) 141 string << B_TRANSLATE("non-rechargeable"); 142 else if (fBatteryExtendedInfo.technology == 1) 143 string << B_TRANSLATE("rechargeable"); 144 else 145 string << "?"; 146 break; 147 case 7: 148 string = B_TRANSLATE("Design voltage: "); 149 string << fBatteryExtendedInfo.design_voltage; 150 string << B_TRANSLATE(" mV"); 151 break; 152 case 8: 153 string = B_TRANSLATE("Design capacity warning: "); 154 string << fBatteryExtendedInfo.design_capacity_warning; 155 string << powerUnit; 156 break; 157 case 9: 158 string = B_TRANSLATE("Design capacity low warning: "); 159 string << fBatteryExtendedInfo.design_capacity_low; 160 string << powerUnit; 161 break; 162 case 10: 163 string = B_TRANSLATE("Capacity granularity 1: "); 164 string << fBatteryExtendedInfo.capacity_granularity_1; 165 string << powerUnit; 166 break; 167 case 11: 168 string = B_TRANSLATE("Capacity granularity 2: "); 169 string << fBatteryExtendedInfo.capacity_granularity_2; 170 string << powerUnit; 171 break; 172 case 12: 173 string = B_TRANSLATE("Model number: "); 174 string << fBatteryExtendedInfo.model_number; 175 break; 176 case 13: 177 string = B_TRANSLATE("Serial number: "); 178 string << fBatteryExtendedInfo.serial_number; 179 break; 180 case 14: 181 string = B_TRANSLATE("Type: "); 182 string += fBatteryExtendedInfo.type; 183 break; 184 case 15: 185 string = B_TRANSLATE("OEM info: "); 186 string += fBatteryExtendedInfo.oem_info; 187 break; 188 default: 189 string = ""; 190 break; 191 } 192 return string; 193 } 194 195 196 // #pragma mark - 197 198 199 BatteryTab::BatteryTab(BatteryInfoView* target, 200 ExtPowerStatusView* view) 201 : 202 fBatteryView(view) 203 { 204 } 205 206 207 BatteryTab::~BatteryTab() 208 { 209 } 210 211 212 void 213 BatteryTab::Select(BView* owner) 214 { 215 BTab::Select(owner); 216 fBatteryView->Select(); 217 } 218 219 void 220 BatteryTab::DrawFocusMark(BView* owner, BRect frame) 221 { 222 float vertOffset = IsSelected() ? 3 : 2; 223 float horzOffset = IsSelected() ? 2 : 4; 224 float width = frame.Width() - horzOffset * 2; 225 BPoint pt1((frame.left + frame.right - width) / 2.0 + horzOffset, 226 frame.bottom - vertOffset); 227 BPoint pt2((frame.left + frame.right + width) / 2.0, 228 frame.bottom - vertOffset); 229 owner->SetHighUIColor(B_KEYBOARD_NAVIGATION_COLOR); 230 owner->StrokeLine(pt1, pt2); 231 } 232 233 234 void 235 BatteryTab::DrawLabel(BView* owner, BRect frame) 236 { 237 BRect rect = frame; 238 float size = std::min(rect.Width(), rect.Height()); 239 rect.right = rect.left + size; 240 rect.bottom = rect.top + size; 241 if (frame.Width() > rect.Height()) { 242 rect.OffsetBy((frame.Width() - size) / 2.0f, 0.0f); 243 } else { 244 rect.OffsetBy(0.0f, (frame.Height() - size) / 2.0f); 245 } 246 fBatteryView->DrawTo(owner, rect); 247 } 248 249 250 BatteryTabView::BatteryTabView(const char* name) 251 : 252 BTabView(name) 253 { 254 } 255 256 257 BatteryTabView::~BatteryTabView() 258 { 259 } 260 261 262 BRect 263 BatteryTabView::TabFrame(int32 index) const 264 { 265 BRect bounds(Bounds()); 266 float width = TabHeight(); 267 float height = TabHeight(); 268 float offset = BControlLook::ComposeSpacing(B_USE_WINDOW_SPACING); 269 switch (TabSide()) { 270 case kTopSide: 271 return BRect(offset + index * width, 0.0f, 272 offset + index * width + width, height); 273 case kBottomSide: 274 return BRect(offset + index * width, bounds.bottom - height, 275 offset + index * width + width, bounds.bottom); 276 case kLeftSide: 277 return BRect(0.0f, offset + index * width, height, 278 offset + index * width + width); 279 case kRightSide: 280 return BRect(bounds.right - height, offset + index * width, 281 bounds.right, offset + index * width + width); 282 default: 283 return BRect(); 284 } 285 } 286 287 288 ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface, 289 BRect frame, int32 resizingMode, int batteryID, 290 BatteryInfoView* batteryInfoView, ExtendedInfoWindow* window) 291 : 292 PowerStatusView(interface, frame, resizingMode, batteryID), 293 fExtendedInfoWindow(window), 294 fBatteryInfoView(batteryInfoView), 295 fBatteryTabView(window->GetBatteryTabView()) 296 { 297 } 298 299 300 void 301 ExtPowerStatusView::Select(bool select) 302 { 303 fSelected = select; 304 Update(true); 305 } 306 307 308 bool 309 ExtPowerStatusView::IsCritical() 310 { 311 return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0; 312 } 313 314 315 void 316 ExtPowerStatusView::Update(bool force) 317 { 318 PowerStatusView::Update(force); 319 if (!fSelected) 320 return; 321 322 acpi_extended_battery_info extInfo; 323 fDriverInterface->GetExtendedBatteryInfo(fBatteryID, &extInfo); 324 325 fBatteryInfoView->Update(fBatteryInfo, extInfo); 326 fBatteryInfoView->Invalidate(); 327 328 fBatteryTabView->Invalidate(); 329 } 330 331 332 // #pragma mark - 333 334 335 ExtendedInfoWindow::ExtendedInfoWindow(PowerStatusDriverInterface* interface) 336 : 337 BWindow(BRect(100, 150, 500, 500), B_TRANSLATE("Extended battery info"), 338 B_TITLED_WINDOW, 339 B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AVOID_FRONT 340 | B_ASYNCHRONOUS_CONTROLS), 341 fDriverInterface(interface), 342 fSelectedView(NULL) 343 { 344 fDriverInterface->AcquireReference(); 345 346 float scale = be_plain_font->Size() / 12.0f; 347 float tabHeight = 70.0f * scale; 348 BRect batteryRect(0, 0, 50 * scale, 50 * scale); 349 fBatteryTabView = new BatteryTabView("tabview"); 350 fBatteryTabView->SetBorder(B_NO_BORDER); 351 fBatteryTabView->SetTabHeight(tabHeight); 352 fBatteryTabView->SetTabSide(BTabView::kLeftSide); 353 BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 354 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0) 355 .Add(fBatteryTabView); 356 357 for (int i = 0; i < interface->GetBatteryCount(); i++) { 358 BatteryInfoView* batteryInfoView = new BatteryInfoView(); 359 ExtPowerStatusView* view = new ExtPowerStatusView(interface, 360 batteryRect, B_FOLLOW_NONE, i, batteryInfoView, this); 361 BatteryTab* tab = new BatteryTab(batteryInfoView, view); 362 fBatteryTabView->AddTab(batteryInfoView, tab); 363 // Has to be added, otherwise it won't get info updates 364 view->Hide(); 365 AddChild(view); 366 367 fBatteryViewList.AddItem(view); 368 fDriverInterface->StartWatching(view); 369 if (!view->IsCritical()) 370 fSelectedView = view; 371 } 372 373 if (!fSelectedView && fBatteryViewList.CountItems() > 0) 374 fSelectedView = fBatteryViewList.ItemAt(0); 375 fSelectedView->Select(); 376 377 BSize size = GetLayout()->PreferredSize(); 378 ResizeTo(size.width, size.height); 379 } 380 381 382 ExtendedInfoWindow::~ExtendedInfoWindow() 383 { 384 for (int i = 0; i < fBatteryViewList.CountItems(); i++) 385 fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i)); 386 387 fDriverInterface->ReleaseReference(); 388 } 389 390 391 BatteryTabView* 392 ExtendedInfoWindow::GetBatteryTabView() 393 { 394 return fBatteryTabView; 395 } 396