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 28const size_t kLinesCount = 16; 29 30 31// #pragma mark - 32 33 34BatteryInfoView::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 55BatteryInfoView::~BatteryInfoView() 56{ 57 for (int32 i = 0; i < fStringList.CountItems(); i++) 58 delete fStringList.ItemAt(i); 59} 60 61 62void 63BatteryInfoView::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 74void 75BatteryInfoView::AttachedToWindow() 76{ 77 Window()->CenterOnScreen(); 78} 79 80 81BString 82BatteryInfoView::_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 201BatteryTab::BatteryTab(BatteryInfoView* target, 202 ExtPowerStatusView* view) 203 : 204 fBatteryView(view) 205{ 206} 207 208 209BatteryTab::~BatteryTab() 210{ 211} 212 213 214void 215BatteryTab::Select(BView* owner) 216{ 217 BTab::Select(owner); 218 fBatteryView->Select(); 219} 220 221void 222BatteryTab::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 236void 237BatteryTab::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 252BatteryTabView::BatteryTabView(const char* name) 253 : 254 BTabView(name) 255{ 256} 257 258 259BatteryTabView::~BatteryTabView() 260{ 261} 262 263 264BRect 265BatteryTabView::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 290ExtPowerStatusView::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 302void 303ExtPowerStatusView::Select(bool select) 304{ 305 fSelected = select; 306 Update(true); 307} 308 309 310bool 311ExtPowerStatusView::IsCritical() 312{ 313 return (fBatteryInfo.state & BATTERY_CRITICAL_STATE) != 0; 314} 315 316 317void 318ExtPowerStatusView::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 337ExtendedInfoWindow::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 383ExtendedInfoWindow::~ExtendedInfoWindow() 384{ 385 for (int i = 0; i < fBatteryViewList.CountItems(); i++) 386 fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i)); 387 388 fDriverInterface->ReleaseReference(); 389} 390 391 392BatteryTabView* 393ExtendedInfoWindow::GetBatteryTabView() 394{ 395 return fBatteryTabView; 396} 397