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_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 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 201 BatteryTab::BatteryTab(BatteryInfoView* target, 202 ExtPowerStatusView* view) 203 : 204 fBatteryView(view) 205 { 206 } 207 208 209 BatteryTab::~BatteryTab() 210 { 211 } 212 213 214 void 215 BatteryTab::Select(BView* owner) 216 { 217 BTab::Select(owner); 218 fBatteryView->Select(); 219 } 220 221 void 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 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 252 BatteryTabView::BatteryTabView(const char* name) 253 : 254 BTabView(name) 255 { 256 } 257 258 259 BatteryTabView::~BatteryTabView() 260 { 261 } 262 263 264 BRect 265 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 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 303 ExtPowerStatusView::Select(bool select) 304 { 305 fSelected = select; 306 Update(true); 307 } 308 309 310 bool 311 ExtPowerStatusView::IsCritical() 312 { 313 return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0; 314 } 315 316 317 void 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 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 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* 393 ExtendedInfoWindow::GetBatteryTabView() 394 { 395 return fBatteryTabView; 396 } 397