16aed176cSClemens Zeidler /* 2d1929affSKacper Kasper * Copyright 2009-2017, Haiku, Inc. All Rights Reserved. 36aed176cSClemens Zeidler * Distributed under the terms of the MIT License. 46aed176cSClemens Zeidler * 56aed176cSClemens Zeidler * Authors: 66aed176cSClemens Zeidler * Clemens Zeidler, haiku@Clemens-Zeidler.de 7d1929affSKacper Kasper * Kacper Kasper, kacperkasper@gmail.com 86aed176cSClemens Zeidler */ 96aed176cSClemens Zeidler 10bd767f5aSAxel Dörfler 116aed176cSClemens Zeidler #include "ExtendedInfoWindow.h" 126aed176cSClemens Zeidler 13*830758adSKacper Kasper #include <ControlLook.h> 143bd54e05SAdrien Destugues #include <Catalog.h> 156aed176cSClemens Zeidler #include <GroupView.h> 16*830758adSKacper Kasper #include <LayoutBuilder.h> 176aed176cSClemens Zeidler #include <SpaceLayoutItem.h> 18*830758adSKacper Kasper #include <TabView.h> 19*830758adSKacper Kasper 20*830758adSKacper Kasper 21*830758adSKacper Kasper #include <algorithm> 226aed176cSClemens Zeidler 236aed176cSClemens Zeidler 24546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 25546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "PowerStatus" 263bd54e05SAdrien Destugues 273bd54e05SAdrien Destugues 28d1929affSKacper Kasper const size_t kLinesCount = 16; 29e391ec67SClemens Zeidler 30e391ec67SClemens Zeidler 31bd767f5aSAxel Dörfler // #pragma mark - 32bd767f5aSAxel Dörfler 33e391ec67SClemens Zeidler 34e391ec67SClemens Zeidler BatteryInfoView::BatteryInfoView() 356aed176cSClemens Zeidler : 36d1929affSKacper Kasper BView("battery info view", B_AUTO_UPDATE_SIZE_LIMITS) 376aed176cSClemens Zeidler { 38fa19dd44Slooncraz SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 39d1929affSKacper Kasper 40*830758adSKacper Kasper BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0); 41*830758adSKacper Kasper layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 42*830758adSKacper Kasper 0, B_USE_DEFAULT_SPACING); 43*830758adSKacper Kasper SetLayout(layout); 44d1929affSKacper Kasper 45d1929affSKacper Kasper for (size_t i = 0; i < kLinesCount; i++) { 46d1929affSKacper Kasper BStringView* view = new BStringView("info", ""); 47d1929affSKacper Kasper AddChild(view); 48d1929affSKacper Kasper fStringList.AddItem(view); 49d1929affSKacper Kasper } 50d1929affSKacper Kasper fStringList.ItemAt(0)->SetFont(be_bold_font); 51d1929affSKacper Kasper AddChild(BSpaceLayoutItem::CreateGlue()); 526aed176cSClemens Zeidler } 536aed176cSClemens Zeidler 546aed176cSClemens Zeidler 55e391ec67SClemens Zeidler BatteryInfoView::~BatteryInfoView() 56e391ec67SClemens Zeidler { 57d1929affSKacper Kasper for (int32 i = 0; i < fStringList.CountItems(); i++) 58d1929affSKacper Kasper delete fStringList.ItemAt(i); 59e391ec67SClemens Zeidler } 60e391ec67SClemens Zeidler 61e391ec67SClemens Zeidler 626aed176cSClemens Zeidler void 636aed176cSClemens Zeidler BatteryInfoView::Update(battery_info& info, acpi_extended_battery_info& extInfo) 646aed176cSClemens Zeidler { 656aed176cSClemens Zeidler fBatteryInfo = info; 666aed176cSClemens Zeidler fBatteryExtendedInfo = extInfo; 67e391ec67SClemens Zeidler 68d1929affSKacper Kasper for (size_t i = 0; i < kLinesCount; i++) { 69d1929affSKacper Kasper fStringList.ItemAt(i)->SetText(_GetTextForLine(i)); 706aed176cSClemens Zeidler } 71e391ec67SClemens Zeidler } 72e391ec67SClemens Zeidler 73e391ec67SClemens Zeidler 748b24b02fSClemens Zeidler void 758b24b02fSClemens Zeidler BatteryInfoView::AttachedToWindow() 768b24b02fSClemens Zeidler { 773e1f071cSClemens Zeidler Window()->CenterOnScreen(); 788b24b02fSClemens Zeidler } 798b24b02fSClemens Zeidler 808b24b02fSClemens Zeidler 81d1929affSKacper Kasper BString 82d1929affSKacper Kasper BatteryInfoView::_GetTextForLine(size_t line) 83e391ec67SClemens Zeidler { 846aed176cSClemens Zeidler BString powerUnit; 856aed176cSClemens Zeidler BString rateUnit; 866aed176cSClemens Zeidler switch (fBatteryExtendedInfo.power_unit) { 876aed176cSClemens Zeidler case 0: 883bd54e05SAdrien Destugues powerUnit = B_TRANSLATE(" mWh"); 893bd54e05SAdrien Destugues rateUnit = B_TRANSLATE(" mW"); 906aed176cSClemens Zeidler break; 916aed176cSClemens Zeidler 926aed176cSClemens Zeidler case 1: 933bd54e05SAdrien Destugues powerUnit = B_TRANSLATE(" mAh"); 943bd54e05SAdrien Destugues rateUnit = B_TRANSLATE(" mA"); 956aed176cSClemens Zeidler break; 966aed176cSClemens Zeidler } 976aed176cSClemens Zeidler 98d1929affSKacper Kasper BString string; 99d1929affSKacper Kasper switch (line) { 100d1929affSKacper Kasper case 0: { 101a11e2f43SAxel Dörfler if ((fBatteryInfo.state & BATTERY_CHARGING) != 0) 102d1929affSKacper Kasper string = B_TRANSLATE("Battery charging"); 103a11e2f43SAxel Dörfler else if ((fBatteryInfo.state & BATTERY_DISCHARGING) != 0) 104d1929affSKacper Kasper string = B_TRANSLATE("Battery discharging"); 105a11e2f43SAxel Dörfler else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0 106829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.model_number[0] == '\0' 107829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.serial_number[0] == '\0' 108829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.type[0] == '\0' 109829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.oem_info[0] == '\0') 110d1929affSKacper Kasper string = B_TRANSLATE("Empty battery slot"); 111a11e2f43SAxel Dörfler else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0) 112d1929affSKacper Kasper string = B_TRANSLATE("Damaged battery"); 1136aed176cSClemens Zeidler else 114d1929affSKacper Kasper string = B_TRANSLATE("Battery unused"); 115d1929affSKacper Kasper break; 116d1929affSKacper Kasper } 117d1929affSKacper Kasper case 1: 118d1929affSKacper Kasper string = B_TRANSLATE("Capacity: "); 119d1929affSKacper Kasper string << fBatteryInfo.capacity; 120d1929affSKacper Kasper string << powerUnit; 121d1929affSKacper Kasper break; 122d1929affSKacper Kasper case 2: 123d1929affSKacper Kasper string = B_TRANSLATE("Last full charge: "); 124d1929affSKacper Kasper string << fBatteryInfo.full_capacity; 125d1929affSKacper Kasper string << powerUnit; 126d1929affSKacper Kasper break; 127d1929affSKacper Kasper case 3: 128d1929affSKacper Kasper string = B_TRANSLATE("Current rate: "); 129d1929affSKacper Kasper string << fBatteryInfo.current_rate; 130d1929affSKacper Kasper string << rateUnit; 131d1929affSKacper Kasper break; 132d1929affSKacper Kasper // case 4 missed intentionally 133d1929affSKacper Kasper case 5: 134d1929affSKacper Kasper string = B_TRANSLATE("Design capacity: "); 135d1929affSKacper Kasper string << fBatteryExtendedInfo.design_capacity; 136d1929affSKacper Kasper string << powerUnit; 137d1929affSKacper Kasper break; 138d1929affSKacper Kasper case 6: 139d1929affSKacper Kasper string = B_TRANSLATE("Technology: "); 140b636a0ecSClemens Zeidler if (fBatteryExtendedInfo.technology == 0) 141d1929affSKacper Kasper string << B_TRANSLATE("non-rechargeable"); 142b636a0ecSClemens Zeidler else if (fBatteryExtendedInfo.technology == 1) 143d1929affSKacper Kasper string << B_TRANSLATE("rechargeable"); 144b636a0ecSClemens Zeidler else 145d1929affSKacper Kasper string << "?"; 146d1929affSKacper Kasper break; 147d1929affSKacper Kasper case 7: 148d1929affSKacper Kasper string = B_TRANSLATE("Design voltage: "); 149d1929affSKacper Kasper string << fBatteryExtendedInfo.design_voltage; 150d1929affSKacper Kasper string << B_TRANSLATE(" mV"); 151d1929affSKacper Kasper break; 152d1929affSKacper Kasper case 8: 153d1929affSKacper Kasper string = B_TRANSLATE("Design capacity warning: "); 154d1929affSKacper Kasper string << fBatteryExtendedInfo.design_capacity_warning; 155d1929affSKacper Kasper string << powerUnit; 156d1929affSKacper Kasper break; 157d1929affSKacper Kasper case 9: 158d1929affSKacper Kasper string = B_TRANSLATE("Design capacity low warning: "); 159d1929affSKacper Kasper string << fBatteryExtendedInfo.design_capacity_low; 160d1929affSKacper Kasper string << powerUnit; 161d1929affSKacper Kasper break; 162d1929affSKacper Kasper case 10: 163d1929affSKacper Kasper string = B_TRANSLATE("Capacity granularity 1: "); 164d1929affSKacper Kasper string << fBatteryExtendedInfo.capacity_granularity_1; 165d1929affSKacper Kasper string << powerUnit; 166d1929affSKacper Kasper break; 167d1929affSKacper Kasper case 11: 168d1929affSKacper Kasper string = B_TRANSLATE("Capacity granularity 2: "); 169d1929affSKacper Kasper string << fBatteryExtendedInfo.capacity_granularity_2; 170d1929affSKacper Kasper string << powerUnit; 171d1929affSKacper Kasper break; 172d1929affSKacper Kasper case 12: 173d1929affSKacper Kasper string = B_TRANSLATE("Model number: "); 174d1929affSKacper Kasper string << fBatteryExtendedInfo.model_number; 175d1929affSKacper Kasper break; 176d1929affSKacper Kasper case 13: 177d1929affSKacper Kasper string = B_TRANSLATE("Serial number: "); 178d1929affSKacper Kasper string << fBatteryExtendedInfo.serial_number; 179d1929affSKacper Kasper break; 180d1929affSKacper Kasper case 14: 181d1929affSKacper Kasper string = B_TRANSLATE("Type: "); 182d1929affSKacper Kasper string += fBatteryExtendedInfo.type; 183d1929affSKacper Kasper break; 184d1929affSKacper Kasper case 15: 185d1929affSKacper Kasper string = B_TRANSLATE("OEM info: "); 186d1929affSKacper Kasper string += fBatteryExtendedInfo.oem_info; 187d1929affSKacper Kasper break; 188d1929affSKacper Kasper default: 189d1929affSKacper Kasper string = ""; 190d1929affSKacper Kasper break; 191e391ec67SClemens Zeidler } 192d1929affSKacper Kasper return string; 1936aed176cSClemens Zeidler } 1946aed176cSClemens Zeidler 1956aed176cSClemens Zeidler 196bd767f5aSAxel Dörfler // #pragma mark - 197bd767f5aSAxel Dörfler 198bd767f5aSAxel Dörfler 199*830758adSKacper Kasper BatteryTab::BatteryTab(BatteryInfoView* target, 200*830758adSKacper Kasper ExtPowerStatusView* view) 201*830758adSKacper Kasper : 202*830758adSKacper Kasper fBatteryView(view) 203*830758adSKacper Kasper { 204*830758adSKacper Kasper } 205*830758adSKacper Kasper 206*830758adSKacper Kasper 207*830758adSKacper Kasper BatteryTab::~BatteryTab() 208*830758adSKacper Kasper { 209*830758adSKacper Kasper } 210*830758adSKacper Kasper 211*830758adSKacper Kasper 212*830758adSKacper Kasper void 213*830758adSKacper Kasper BatteryTab::Select(BView* owner) 214*830758adSKacper Kasper { 215*830758adSKacper Kasper BTab::Select(owner); 216*830758adSKacper Kasper fBatteryView->Select(); 217*830758adSKacper Kasper } 218*830758adSKacper Kasper 219*830758adSKacper Kasper void 220*830758adSKacper Kasper BatteryTab::DrawFocusMark(BView* owner, BRect frame) 221*830758adSKacper Kasper { 222*830758adSKacper Kasper float vertOffset = IsSelected() ? 3 : 2; 223*830758adSKacper Kasper float horzOffset = IsSelected() ? 2 : 4; 224*830758adSKacper Kasper float width = frame.Width() - horzOffset * 2; 225*830758adSKacper Kasper BPoint pt1((frame.left + frame.right - width) / 2.0 + horzOffset, 226*830758adSKacper Kasper frame.bottom - vertOffset); 227*830758adSKacper Kasper BPoint pt2((frame.left + frame.right + width) / 2.0, 228*830758adSKacper Kasper frame.bottom - vertOffset); 229*830758adSKacper Kasper owner->SetHighUIColor(B_KEYBOARD_NAVIGATION_COLOR); 230*830758adSKacper Kasper owner->StrokeLine(pt1, pt2); 231*830758adSKacper Kasper } 232*830758adSKacper Kasper 233*830758adSKacper Kasper 234*830758adSKacper Kasper void 235*830758adSKacper Kasper BatteryTab::DrawLabel(BView* owner, BRect frame) 236*830758adSKacper Kasper { 237*830758adSKacper Kasper BRect rect = frame; 238*830758adSKacper Kasper float size = std::min(rect.Width(), rect.Height()); 239*830758adSKacper Kasper rect.right = rect.left + size; 240*830758adSKacper Kasper rect.bottom = rect.top + size; 241*830758adSKacper Kasper if (frame.Width() > rect.Height()) { 242*830758adSKacper Kasper rect.OffsetBy((frame.Width() - size) / 2.0f, 0.0f); 243*830758adSKacper Kasper } else { 244*830758adSKacper Kasper rect.OffsetBy(0.0f, (frame.Height() - size) / 2.0f); 245*830758adSKacper Kasper } 246*830758adSKacper Kasper fBatteryView->DrawTo(owner, rect); 247*830758adSKacper Kasper } 248*830758adSKacper Kasper 249*830758adSKacper Kasper 250*830758adSKacper Kasper BatteryTabView::BatteryTabView(const char* name) 251*830758adSKacper Kasper : 252*830758adSKacper Kasper BTabView(name) 253*830758adSKacper Kasper { 254*830758adSKacper Kasper } 255*830758adSKacper Kasper 256*830758adSKacper Kasper 257*830758adSKacper Kasper BatteryTabView::~BatteryTabView() 258*830758adSKacper Kasper { 259*830758adSKacper Kasper } 260*830758adSKacper Kasper 261*830758adSKacper Kasper 262*830758adSKacper Kasper BRect 263*830758adSKacper Kasper BatteryTabView::TabFrame(int32 index) const 264*830758adSKacper Kasper { 265*830758adSKacper Kasper BRect bounds(Bounds()); 266*830758adSKacper Kasper float width = TabHeight(); 267*830758adSKacper Kasper float height = TabHeight(); 268*830758adSKacper Kasper float offset = BControlLook::ComposeSpacing(B_USE_WINDOW_SPACING); 269*830758adSKacper Kasper switch (TabSide()) { 270*830758adSKacper Kasper case kTopSide: 271*830758adSKacper Kasper return BRect(offset + index * width, 0.0f, 272*830758adSKacper Kasper offset + index * width + width, height); 273*830758adSKacper Kasper case kBottomSide: 274*830758adSKacper Kasper return BRect(offset + index * width, bounds.bottom - height, 275*830758adSKacper Kasper offset + index * width + width, bounds.bottom); 276*830758adSKacper Kasper case kLeftSide: 277*830758adSKacper Kasper return BRect(0.0f, offset + index * width, height, 278*830758adSKacper Kasper offset + index * width + width); 279*830758adSKacper Kasper case kRightSide: 280*830758adSKacper Kasper return BRect(bounds.right - height, offset + index * width, 281*830758adSKacper Kasper bounds.right, offset + index * width + width); 282*830758adSKacper Kasper default: 283*830758adSKacper Kasper return BRect(); 284*830758adSKacper Kasper } 285*830758adSKacper Kasper } 286*830758adSKacper Kasper 287*830758adSKacper Kasper 2886aed176cSClemens Zeidler ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface, 289bd767f5aSAxel Dörfler BRect frame, int32 resizingMode, int batteryID, 290*830758adSKacper Kasper BatteryInfoView* batteryInfoView, ExtendedInfoWindow* window) 2916aed176cSClemens Zeidler : 292bd767f5aSAxel Dörfler PowerStatusView(interface, frame, resizingMode, batteryID), 2936aed176cSClemens Zeidler fExtendedInfoWindow(window), 294*830758adSKacper Kasper fBatteryInfoView(batteryInfoView), 295*830758adSKacper Kasper fBatteryTabView(window->GetBatteryTabView()) 2966aed176cSClemens Zeidler { 2976aed176cSClemens Zeidler } 2986aed176cSClemens Zeidler 2996aed176cSClemens Zeidler 3006aed176cSClemens Zeidler void 3016aed176cSClemens Zeidler ExtPowerStatusView::Select(bool select) 3026aed176cSClemens Zeidler { 3036aed176cSClemens Zeidler fSelected = select; 304bd767f5aSAxel Dörfler Update(true); 3056aed176cSClemens Zeidler } 3066aed176cSClemens Zeidler 3076aed176cSClemens Zeidler 3086aed176cSClemens Zeidler bool 309bd767f5aSAxel Dörfler ExtPowerStatusView::IsCritical() 3106aed176cSClemens Zeidler { 311bd767f5aSAxel Dörfler return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0; 3126aed176cSClemens Zeidler } 3136aed176cSClemens Zeidler 3146aed176cSClemens Zeidler 3156aed176cSClemens Zeidler void 316bd767f5aSAxel Dörfler ExtPowerStatusView::Update(bool force) 3176aed176cSClemens Zeidler { 318bd767f5aSAxel Dörfler PowerStatusView::Update(force); 3196aed176cSClemens Zeidler if (!fSelected) 3206aed176cSClemens Zeidler return; 3216aed176cSClemens Zeidler 3226aed176cSClemens Zeidler acpi_extended_battery_info extInfo; 323b19e9d5bSAxel Dörfler fDriverInterface->GetExtendedBatteryInfo(fBatteryID, &extInfo); 3246aed176cSClemens Zeidler 3256aed176cSClemens Zeidler fBatteryInfoView->Update(fBatteryInfo, extInfo); 3266aed176cSClemens Zeidler fBatteryInfoView->Invalidate(); 327*830758adSKacper Kasper 328*830758adSKacper Kasper fBatteryTabView->Invalidate(); 3296aed176cSClemens Zeidler } 3306aed176cSClemens Zeidler 3316aed176cSClemens Zeidler 332bd767f5aSAxel Dörfler // #pragma mark - 333bd767f5aSAxel Dörfler 334bd767f5aSAxel Dörfler 3356aed176cSClemens Zeidler ExtendedInfoWindow::ExtendedInfoWindow(PowerStatusDriverInterface* interface) 3366aed176cSClemens Zeidler : 3373bd54e05SAdrien Destugues BWindow(BRect(100, 150, 500, 500), B_TRANSLATE("Extended battery info"), 3383bd54e05SAdrien Destugues B_TITLED_WINDOW, 339b19e9d5bSAxel Dörfler B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AVOID_FRONT 340b19e9d5bSAxel Dörfler | B_ASYNCHRONOUS_CONTROLS), 3416aed176cSClemens Zeidler fDriverInterface(interface), 3426aed176cSClemens Zeidler fSelectedView(NULL) 3436aed176cSClemens Zeidler { 34408145692SClemens Zeidler fDriverInterface->AcquireReference(); 34508145692SClemens Zeidler 346*830758adSKacper Kasper fBatteryTabView = new BatteryTabView("tabview"); 347*830758adSKacper Kasper fBatteryTabView->SetBorder(B_NO_BORDER); 348*830758adSKacper Kasper fBatteryTabView->SetTabHeight(70.0f); 349*830758adSKacper Kasper fBatteryTabView->SetTabSide(BTabView::kLeftSide); 350*830758adSKacper Kasper BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 351*830758adSKacper Kasper .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0) 352*830758adSKacper Kasper .Add(fBatteryTabView); 3536aed176cSClemens Zeidler 3546aed176cSClemens Zeidler BRect batteryRect(0, 0, 50, 30); 3556aed176cSClemens Zeidler for (int i = 0; i < interface->GetBatteryCount(); i++) { 356*830758adSKacper Kasper BatteryInfoView* batteryInfoView = new BatteryInfoView(); 3576aed176cSClemens Zeidler ExtPowerStatusView* view = new ExtPowerStatusView(interface, 358*830758adSKacper Kasper batteryRect, B_FOLLOW_NONE, i, batteryInfoView, this); 359*830758adSKacper Kasper BatteryTab* tab = new BatteryTab(batteryInfoView, view); 360*830758adSKacper Kasper fBatteryTabView->AddTab(batteryInfoView, tab); 361*830758adSKacper Kasper // Has to be added, otherwise it won't get info updates 362*830758adSKacper Kasper view->Hide(); 363*830758adSKacper Kasper AddChild(view); 364e391ec67SClemens Zeidler 3656aed176cSClemens Zeidler fBatteryViewList.AddItem(view); 3666aed176cSClemens Zeidler fDriverInterface->StartWatching(view); 367bd767f5aSAxel Dörfler if (!view->IsCritical()) 3686aed176cSClemens Zeidler fSelectedView = view; 3696aed176cSClemens Zeidler } 3706aed176cSClemens Zeidler 3716aed176cSClemens Zeidler if (!fSelectedView && fBatteryViewList.CountItems() > 0) 3726aed176cSClemens Zeidler fSelectedView = fBatteryViewList.ItemAt(0); 3736aed176cSClemens Zeidler fSelectedView->Select(); 3746aed176cSClemens Zeidler 375*830758adSKacper Kasper BSize size = GetLayout()->PreferredSize(); 3766aed176cSClemens Zeidler ResizeTo(size.width, size.height); 3776aed176cSClemens Zeidler } 3786aed176cSClemens Zeidler 3796aed176cSClemens Zeidler 3806aed176cSClemens Zeidler ExtendedInfoWindow::~ExtendedInfoWindow() 3816aed176cSClemens Zeidler { 38208145692SClemens Zeidler for (int i = 0; i < fBatteryViewList.CountItems(); i++) 3836aed176cSClemens Zeidler fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i)); 38408145692SClemens Zeidler 38508145692SClemens Zeidler fDriverInterface->ReleaseReference(); 3866aed176cSClemens Zeidler } 3876aed176cSClemens Zeidler 3886aed176cSClemens Zeidler 389*830758adSKacper Kasper BatteryTabView* 390*830758adSKacper Kasper ExtendedInfoWindow::GetBatteryTabView() 3916aed176cSClemens Zeidler { 392*830758adSKacper Kasper return fBatteryTabView; 3936aed176cSClemens Zeidler } 394