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 13830758adSKacper Kasper #include <ControlLook.h> 143bd54e05SAdrien Destugues #include <Catalog.h> 156aed176cSClemens Zeidler #include <GroupView.h> 16830758adSKacper Kasper #include <LayoutBuilder.h> 176aed176cSClemens Zeidler #include <SpaceLayoutItem.h> 18830758adSKacper Kasper #include <TabView.h> 19830758adSKacper Kasper 20830758adSKacper Kasper 21830758adSKacper 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 40830758adSKacper Kasper BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0); 41830758adSKacper Kasper layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 42830758adSKacper Kasper 0, B_USE_DEFAULT_SPACING); 43830758adSKacper 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"); 105*96bad768SJérôme Duval else if ((fBatteryInfo.state & BATTERY_NOT_CHARGING) != 0) 106*96bad768SJérôme Duval string = B_TRANSLATE("Battery not charging"); 107a11e2f43SAxel Dörfler else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0 108829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.model_number[0] == '\0' 109829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.serial_number[0] == '\0' 110829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.type[0] == '\0' 111829200a0SAlexander von Gluck IV && fBatteryExtendedInfo.oem_info[0] == '\0') 112d1929affSKacper Kasper string = B_TRANSLATE("Empty battery slot"); 113a11e2f43SAxel Dörfler else if ((fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0) 114d1929affSKacper Kasper string = B_TRANSLATE("Damaged battery"); 1156aed176cSClemens Zeidler else 116d1929affSKacper Kasper string = B_TRANSLATE("Battery unused"); 117d1929affSKacper Kasper break; 118d1929affSKacper Kasper } 119d1929affSKacper Kasper case 1: 120d1929affSKacper Kasper string = B_TRANSLATE("Capacity: "); 121d1929affSKacper Kasper string << fBatteryInfo.capacity; 122d1929affSKacper Kasper string << powerUnit; 123d1929affSKacper Kasper break; 124d1929affSKacper Kasper case 2: 125d1929affSKacper Kasper string = B_TRANSLATE("Last full charge: "); 126d1929affSKacper Kasper string << fBatteryInfo.full_capacity; 127d1929affSKacper Kasper string << powerUnit; 128d1929affSKacper Kasper break; 129d1929affSKacper Kasper case 3: 130d1929affSKacper Kasper string = B_TRANSLATE("Current rate: "); 131d1929affSKacper Kasper string << fBatteryInfo.current_rate; 132d1929affSKacper Kasper string << rateUnit; 133d1929affSKacper Kasper break; 134d1929affSKacper Kasper // case 4 missed intentionally 135d1929affSKacper Kasper case 5: 136d1929affSKacper Kasper string = B_TRANSLATE("Design capacity: "); 137d1929affSKacper Kasper string << fBatteryExtendedInfo.design_capacity; 138d1929affSKacper Kasper string << powerUnit; 139d1929affSKacper Kasper break; 140d1929affSKacper Kasper case 6: 141d1929affSKacper Kasper string = B_TRANSLATE("Technology: "); 142b636a0ecSClemens Zeidler if (fBatteryExtendedInfo.technology == 0) 143d1929affSKacper Kasper string << B_TRANSLATE("non-rechargeable"); 144b636a0ecSClemens Zeidler else if (fBatteryExtendedInfo.technology == 1) 145d1929affSKacper Kasper string << B_TRANSLATE("rechargeable"); 146b636a0ecSClemens Zeidler else 147d1929affSKacper Kasper string << "?"; 148d1929affSKacper Kasper break; 149d1929affSKacper Kasper case 7: 150d1929affSKacper Kasper string = B_TRANSLATE("Design voltage: "); 151d1929affSKacper Kasper string << fBatteryExtendedInfo.design_voltage; 152d1929affSKacper Kasper string << B_TRANSLATE(" mV"); 153d1929affSKacper Kasper break; 154d1929affSKacper Kasper case 8: 155d1929affSKacper Kasper string = B_TRANSLATE("Design capacity warning: "); 156d1929affSKacper Kasper string << fBatteryExtendedInfo.design_capacity_warning; 157d1929affSKacper Kasper string << powerUnit; 158d1929affSKacper Kasper break; 159d1929affSKacper Kasper case 9: 160d1929affSKacper Kasper string = B_TRANSLATE("Design capacity low warning: "); 161d1929affSKacper Kasper string << fBatteryExtendedInfo.design_capacity_low; 162d1929affSKacper Kasper string << powerUnit; 163d1929affSKacper Kasper break; 164d1929affSKacper Kasper case 10: 165d1929affSKacper Kasper string = B_TRANSLATE("Capacity granularity 1: "); 166d1929affSKacper Kasper string << fBatteryExtendedInfo.capacity_granularity_1; 167d1929affSKacper Kasper string << powerUnit; 168d1929affSKacper Kasper break; 169d1929affSKacper Kasper case 11: 170d1929affSKacper Kasper string = B_TRANSLATE("Capacity granularity 2: "); 171d1929affSKacper Kasper string << fBatteryExtendedInfo.capacity_granularity_2; 172d1929affSKacper Kasper string << powerUnit; 173d1929affSKacper Kasper break; 174d1929affSKacper Kasper case 12: 175d1929affSKacper Kasper string = B_TRANSLATE("Model number: "); 176d1929affSKacper Kasper string << fBatteryExtendedInfo.model_number; 177d1929affSKacper Kasper break; 178d1929affSKacper Kasper case 13: 179d1929affSKacper Kasper string = B_TRANSLATE("Serial number: "); 180d1929affSKacper Kasper string << fBatteryExtendedInfo.serial_number; 181d1929affSKacper Kasper break; 182d1929affSKacper Kasper case 14: 183d1929affSKacper Kasper string = B_TRANSLATE("Type: "); 184d1929affSKacper Kasper string += fBatteryExtendedInfo.type; 185d1929affSKacper Kasper break; 186d1929affSKacper Kasper case 15: 187d1929affSKacper Kasper string = B_TRANSLATE("OEM info: "); 188d1929affSKacper Kasper string += fBatteryExtendedInfo.oem_info; 189d1929affSKacper Kasper break; 190d1929affSKacper Kasper default: 191d1929affSKacper Kasper string = ""; 192d1929affSKacper Kasper break; 193e391ec67SClemens Zeidler } 194d1929affSKacper Kasper return string; 1956aed176cSClemens Zeidler } 1966aed176cSClemens Zeidler 1976aed176cSClemens Zeidler 198bd767f5aSAxel Dörfler // #pragma mark - 199bd767f5aSAxel Dörfler 200bd767f5aSAxel Dörfler 201830758adSKacper Kasper BatteryTab::BatteryTab(BatteryInfoView* target, 202830758adSKacper Kasper ExtPowerStatusView* view) 203830758adSKacper Kasper : 204830758adSKacper Kasper fBatteryView(view) 205830758adSKacper Kasper { 206830758adSKacper Kasper } 207830758adSKacper Kasper 208830758adSKacper Kasper 209830758adSKacper Kasper BatteryTab::~BatteryTab() 210830758adSKacper Kasper { 211830758adSKacper Kasper } 212830758adSKacper Kasper 213830758adSKacper Kasper 214830758adSKacper Kasper void 215830758adSKacper Kasper BatteryTab::Select(BView* owner) 216830758adSKacper Kasper { 217830758adSKacper Kasper BTab::Select(owner); 218830758adSKacper Kasper fBatteryView->Select(); 219830758adSKacper Kasper } 220830758adSKacper Kasper 221830758adSKacper Kasper void 222830758adSKacper Kasper BatteryTab::DrawFocusMark(BView* owner, BRect frame) 223830758adSKacper Kasper { 224830758adSKacper Kasper float vertOffset = IsSelected() ? 3 : 2; 225830758adSKacper Kasper float horzOffset = IsSelected() ? 2 : 4; 226830758adSKacper Kasper float width = frame.Width() - horzOffset * 2; 227830758adSKacper Kasper BPoint pt1((frame.left + frame.right - width) / 2.0 + horzOffset, 228830758adSKacper Kasper frame.bottom - vertOffset); 229830758adSKacper Kasper BPoint pt2((frame.left + frame.right + width) / 2.0, 230830758adSKacper Kasper frame.bottom - vertOffset); 231830758adSKacper Kasper owner->SetHighUIColor(B_KEYBOARD_NAVIGATION_COLOR); 232830758adSKacper Kasper owner->StrokeLine(pt1, pt2); 233830758adSKacper Kasper } 234830758adSKacper Kasper 235830758adSKacper Kasper 236830758adSKacper Kasper void 237830758adSKacper Kasper BatteryTab::DrawLabel(BView* owner, BRect frame) 238830758adSKacper Kasper { 239830758adSKacper Kasper BRect rect = frame; 240830758adSKacper Kasper float size = std::min(rect.Width(), rect.Height()); 241830758adSKacper Kasper rect.right = rect.left + size; 242830758adSKacper Kasper rect.bottom = rect.top + size; 243830758adSKacper Kasper if (frame.Width() > rect.Height()) { 244830758adSKacper Kasper rect.OffsetBy((frame.Width() - size) / 2.0f, 0.0f); 245830758adSKacper Kasper } else { 246830758adSKacper Kasper rect.OffsetBy(0.0f, (frame.Height() - size) / 2.0f); 247830758adSKacper Kasper } 248830758adSKacper Kasper fBatteryView->DrawTo(owner, rect); 249830758adSKacper Kasper } 250830758adSKacper Kasper 251830758adSKacper Kasper 252830758adSKacper Kasper BatteryTabView::BatteryTabView(const char* name) 253830758adSKacper Kasper : 254830758adSKacper Kasper BTabView(name) 255830758adSKacper Kasper { 256830758adSKacper Kasper } 257830758adSKacper Kasper 258830758adSKacper Kasper 259830758adSKacper Kasper BatteryTabView::~BatteryTabView() 260830758adSKacper Kasper { 261830758adSKacper Kasper } 262830758adSKacper Kasper 263830758adSKacper Kasper 264830758adSKacper Kasper BRect 265830758adSKacper Kasper BatteryTabView::TabFrame(int32 index) const 266830758adSKacper Kasper { 267830758adSKacper Kasper BRect bounds(Bounds()); 268830758adSKacper Kasper float width = TabHeight(); 269830758adSKacper Kasper float height = TabHeight(); 270830758adSKacper Kasper float offset = BControlLook::ComposeSpacing(B_USE_WINDOW_SPACING); 271830758adSKacper Kasper switch (TabSide()) { 272830758adSKacper Kasper case kTopSide: 273830758adSKacper Kasper return BRect(offset + index * width, 0.0f, 274830758adSKacper Kasper offset + index * width + width, height); 275830758adSKacper Kasper case kBottomSide: 276830758adSKacper Kasper return BRect(offset + index * width, bounds.bottom - height, 277830758adSKacper Kasper offset + index * width + width, bounds.bottom); 278830758adSKacper Kasper case kLeftSide: 279830758adSKacper Kasper return BRect(0.0f, offset + index * width, height, 280830758adSKacper Kasper offset + index * width + width); 281830758adSKacper Kasper case kRightSide: 282830758adSKacper Kasper return BRect(bounds.right - height, offset + index * width, 283830758adSKacper Kasper bounds.right, offset + index * width + width); 284830758adSKacper Kasper default: 285830758adSKacper Kasper return BRect(); 286830758adSKacper Kasper } 287830758adSKacper Kasper } 288830758adSKacper Kasper 289830758adSKacper Kasper 2906aed176cSClemens Zeidler ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface, 291bd767f5aSAxel Dörfler BRect frame, int32 resizingMode, int batteryID, 292830758adSKacper Kasper BatteryInfoView* batteryInfoView, ExtendedInfoWindow* window) 2936aed176cSClemens Zeidler : 294bd767f5aSAxel Dörfler PowerStatusView(interface, frame, resizingMode, batteryID), 2956aed176cSClemens Zeidler fExtendedInfoWindow(window), 296830758adSKacper Kasper fBatteryInfoView(batteryInfoView), 297830758adSKacper Kasper fBatteryTabView(window->GetBatteryTabView()) 2986aed176cSClemens Zeidler { 2996aed176cSClemens Zeidler } 3006aed176cSClemens Zeidler 3016aed176cSClemens Zeidler 3026aed176cSClemens Zeidler void 3036aed176cSClemens Zeidler ExtPowerStatusView::Select(bool select) 3046aed176cSClemens Zeidler { 3056aed176cSClemens Zeidler fSelected = select; 306bd767f5aSAxel Dörfler Update(true); 3076aed176cSClemens Zeidler } 3086aed176cSClemens Zeidler 3096aed176cSClemens Zeidler 3106aed176cSClemens Zeidler bool 311bd767f5aSAxel Dörfler ExtPowerStatusView::IsCritical() 3126aed176cSClemens Zeidler { 313bd767f5aSAxel Dörfler return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0; 3146aed176cSClemens Zeidler } 3156aed176cSClemens Zeidler 3166aed176cSClemens Zeidler 3176aed176cSClemens Zeidler void 31810074df1SPawan Wadhwani ExtPowerStatusView::Update(bool force, bool notify) 3196aed176cSClemens Zeidler { 320bd767f5aSAxel Dörfler PowerStatusView::Update(force); 3216aed176cSClemens Zeidler if (!fSelected) 3226aed176cSClemens Zeidler return; 3236aed176cSClemens Zeidler 3246aed176cSClemens Zeidler acpi_extended_battery_info extInfo; 325b19e9d5bSAxel Dörfler fDriverInterface->GetExtendedBatteryInfo(fBatteryID, &extInfo); 3266aed176cSClemens Zeidler 3276aed176cSClemens Zeidler fBatteryInfoView->Update(fBatteryInfo, extInfo); 3286aed176cSClemens Zeidler fBatteryInfoView->Invalidate(); 329830758adSKacper Kasper 330830758adSKacper Kasper fBatteryTabView->Invalidate(); 3316aed176cSClemens Zeidler } 3326aed176cSClemens Zeidler 3336aed176cSClemens Zeidler 334bd767f5aSAxel Dörfler // #pragma mark - 335bd767f5aSAxel Dörfler 336bd767f5aSAxel Dörfler 3376aed176cSClemens Zeidler ExtendedInfoWindow::ExtendedInfoWindow(PowerStatusDriverInterface* interface) 3386aed176cSClemens Zeidler : 3393bd54e05SAdrien Destugues BWindow(BRect(100, 150, 500, 500), B_TRANSLATE("Extended battery info"), 3403bd54e05SAdrien Destugues B_TITLED_WINDOW, 341b19e9d5bSAxel Dörfler B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AVOID_FRONT 342b19e9d5bSAxel Dörfler | B_ASYNCHRONOUS_CONTROLS), 3436aed176cSClemens Zeidler fDriverInterface(interface), 3446aed176cSClemens Zeidler fSelectedView(NULL) 3456aed176cSClemens Zeidler { 34608145692SClemens Zeidler fDriverInterface->AcquireReference(); 34708145692SClemens Zeidler 34859d0a832SAugustin Cavalier BRect batteryRect(BPoint(0, 0), be_control_look->ComposeIconSize(50)); 34959d0a832SAugustin Cavalier float tabHeight = ceilf(batteryRect.Height() * 1.4f); 350830758adSKacper Kasper fBatteryTabView = new BatteryTabView("tabview"); 351830758adSKacper Kasper fBatteryTabView->SetBorder(B_NO_BORDER); 35254606559SKacper Kasper fBatteryTabView->SetTabHeight(tabHeight); 353830758adSKacper Kasper fBatteryTabView->SetTabSide(BTabView::kLeftSide); 354830758adSKacper Kasper BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 355830758adSKacper Kasper .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0) 356830758adSKacper Kasper .Add(fBatteryTabView); 3576aed176cSClemens Zeidler 3586aed176cSClemens Zeidler for (int i = 0; i < interface->GetBatteryCount(); i++) { 359830758adSKacper Kasper BatteryInfoView* batteryInfoView = new BatteryInfoView(); 3606aed176cSClemens Zeidler ExtPowerStatusView* view = new ExtPowerStatusView(interface, 361830758adSKacper Kasper batteryRect, B_FOLLOW_NONE, i, batteryInfoView, this); 362830758adSKacper Kasper BatteryTab* tab = new BatteryTab(batteryInfoView, view); 363830758adSKacper Kasper fBatteryTabView->AddTab(batteryInfoView, tab); 364830758adSKacper Kasper // Has to be added, otherwise it won't get info updates 365830758adSKacper Kasper view->Hide(); 366830758adSKacper Kasper AddChild(view); 367e391ec67SClemens Zeidler 3686aed176cSClemens Zeidler fBatteryViewList.AddItem(view); 3696aed176cSClemens Zeidler fDriverInterface->StartWatching(view); 370bd767f5aSAxel Dörfler if (!view->IsCritical()) 3716aed176cSClemens Zeidler fSelectedView = view; 3726aed176cSClemens Zeidler } 3736aed176cSClemens Zeidler 3746aed176cSClemens Zeidler if (!fSelectedView && fBatteryViewList.CountItems() > 0) 3756aed176cSClemens Zeidler fSelectedView = fBatteryViewList.ItemAt(0); 3766aed176cSClemens Zeidler fSelectedView->Select(); 3776aed176cSClemens Zeidler 378830758adSKacper Kasper BSize size = GetLayout()->PreferredSize(); 3796aed176cSClemens Zeidler ResizeTo(size.width, size.height); 3806aed176cSClemens Zeidler } 3816aed176cSClemens Zeidler 3826aed176cSClemens Zeidler 3836aed176cSClemens Zeidler ExtendedInfoWindow::~ExtendedInfoWindow() 3846aed176cSClemens Zeidler { 38508145692SClemens Zeidler for (int i = 0; i < fBatteryViewList.CountItems(); i++) 3866aed176cSClemens Zeidler fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i)); 38708145692SClemens Zeidler 38808145692SClemens Zeidler fDriverInterface->ReleaseReference(); 3896aed176cSClemens Zeidler } 3906aed176cSClemens Zeidler 3916aed176cSClemens Zeidler 392830758adSKacper Kasper BatteryTabView* 393830758adSKacper Kasper ExtendedInfoWindow::GetBatteryTabView() 3946aed176cSClemens Zeidler { 395830758adSKacper Kasper return fBatteryTabView; 3966aed176cSClemens Zeidler } 397