PowerStatus: convert to BTabView.

* Move text inside battery if possible.
* Fix location of the spark.
* Fixes #5422 and #7330.
This commit is contained in:
Kacper Kasper 2017-11-20 23:12:32 +01:00
parent d1929affbb
commit 830758ad45
4 changed files with 206 additions and 144 deletions

View File

@ -10,10 +10,15 @@
#include "ExtendedInfoWindow.h"
#include <Box.h>
#include <ControlLook.h>
#include <Catalog.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <SpaceLayoutItem.h>
#include <TabView.h>
#include <algorithm>
#undef B_TRANSLATION_CONTEXT
@ -32,7 +37,10 @@ BatteryInfoView::BatteryInfoView()
{
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
SetLayout(new BGroupLayout(B_VERTICAL, B_USE_ITEM_SPACING));
BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0);
layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
0, B_USE_DEFAULT_SPACING);
SetLayout(layout);
for (size_t i = 0; i < kLinesCount; i++) {
BStringView* view = new BStringView("info", "");
@ -188,44 +196,107 @@ BatteryInfoView::_GetTextForLine(size_t line)
// #pragma mark -
BatteryTab::BatteryTab(BatteryInfoView* target,
ExtPowerStatusView* view)
:
fBatteryView(view)
{
}
BatteryTab::~BatteryTab()
{
}
void
BatteryTab::Select(BView* owner)
{
BTab::Select(owner);
fBatteryView->Select();
}
void
BatteryTab::DrawFocusMark(BView* owner, BRect frame)
{
float vertOffset = IsSelected() ? 3 : 2;
float horzOffset = IsSelected() ? 2 : 4;
float width = frame.Width() - horzOffset * 2;
BPoint pt1((frame.left + frame.right - width) / 2.0 + horzOffset,
frame.bottom - vertOffset);
BPoint pt2((frame.left + frame.right + width) / 2.0,
frame.bottom - vertOffset);
owner->SetHighUIColor(B_KEYBOARD_NAVIGATION_COLOR);
owner->StrokeLine(pt1, pt2);
}
void
BatteryTab::DrawLabel(BView* owner, BRect frame)
{
BRect rect = frame;
float size = std::min(rect.Width(), rect.Height());
rect.right = rect.left + size;
rect.bottom = rect.top + size;
if (frame.Width() > rect.Height()) {
rect.OffsetBy((frame.Width() - size) / 2.0f, 0.0f);
} else {
rect.OffsetBy(0.0f, (frame.Height() - size) / 2.0f);
}
fBatteryView->DrawTo(owner, rect);
}
BatteryTabView::BatteryTabView(const char* name)
:
BTabView(name)
{
}
BatteryTabView::~BatteryTabView()
{
}
BRect
BatteryTabView::TabFrame(int32 index) const
{
BRect bounds(Bounds());
float width = TabHeight();
float height = TabHeight();
float offset = BControlLook::ComposeSpacing(B_USE_WINDOW_SPACING);
switch (TabSide()) {
case kTopSide:
return BRect(offset + index * width, 0.0f,
offset + index * width + width, height);
case kBottomSide:
return BRect(offset + index * width, bounds.bottom - height,
offset + index * width + width, bounds.bottom);
case kLeftSide:
return BRect(0.0f, offset + index * width, height,
offset + index * width + width);
case kRightSide:
return BRect(bounds.right - height, offset + index * width,
bounds.right, offset + index * width + width);
default:
return BRect();
}
}
ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface,
BRect frame, int32 resizingMode, int batteryID,
ExtendedInfoWindow* window)
BatteryInfoView* batteryInfoView, ExtendedInfoWindow* window)
:
PowerStatusView(interface, frame, resizingMode, batteryID),
fExtendedInfoWindow(window),
fBatteryInfoView(window->GetExtendedBatteryInfoView()),
fSelected(false)
fBatteryInfoView(batteryInfoView),
fBatteryTabView(window->GetBatteryTabView())
{
}
void
ExtPowerStatusView::Draw(BRect updateRect)
{
if (fSelected) {
rgb_color lowColor = LowColor();
SetLowColor(102, 152, 203);
FillRect(updateRect, B_SOLID_LOW);
SetLowColor(lowColor);
}
PowerStatusView::Draw(updateRect);
}
void
ExtPowerStatusView::MouseDown(BPoint where)
{
if (!fSelected) {
fSelected = true;
Update(true);
if (ExtendedInfoWindow* window
= dynamic_cast<ExtendedInfoWindow*>(Window()))
window->BatterySelected(this);
}
}
void
ExtPowerStatusView::Select(bool select)
{
@ -253,6 +324,8 @@ ExtPowerStatusView::Update(bool force)
fBatteryInfoView->Update(fBatteryInfo, extInfo);
fBatteryInfoView->Invalidate();
fBatteryTabView->Invalidate();
}
@ -270,56 +343,36 @@ ExtendedInfoWindow::ExtendedInfoWindow(PowerStatusDriverInterface* interface)
{
fDriverInterface->AcquireReference();
BView *view = new BView(Bounds(), "view", B_FOLLOW_ALL, 0);
view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
AddChild(view);
fBatteryTabView = new BatteryTabView("tabview");
fBatteryTabView->SetBorder(B_NO_BORDER);
fBatteryTabView->SetTabHeight(70.0f);
fBatteryTabView->SetTabSide(BTabView::kLeftSide);
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0)
.Add(fBatteryTabView);
BGroupLayout* mainLayout = new BGroupLayout(B_VERTICAL);
mainLayout->SetSpacing(10);
mainLayout->SetInsets(10, 10, 10, 10);
view->SetLayout(mainLayout);
BRect rect = Bounds();
rect.InsetBy(5, 5);
BBox *infoBox = new BBox(rect, B_TRANSLATE("Power status box"));
infoBox->SetLabel(B_TRANSLATE("Battery info"));
BGroupLayout* infoLayout = new BGroupLayout(B_HORIZONTAL);
infoLayout->SetInsets(10, infoBox->TopBorderOffset() * 2 + 10, 10, 10);
infoLayout->SetSpacing(10);
infoBox->SetLayout(infoLayout);
mainLayout->AddView(infoBox);
BGroupView* batteryView = new BGroupView(B_VERTICAL);
batteryView->GroupLayout()->SetSpacing(10);
infoLayout->AddView(batteryView);
// create before the battery views
fBatteryInfoView = new BatteryInfoView();
BGroupLayout* batteryLayout = batteryView->GroupLayout();
BRect batteryRect(0, 0, 50, 30);
for (int i = 0; i < interface->GetBatteryCount(); i++) {
BatteryInfoView* batteryInfoView = new BatteryInfoView();
ExtPowerStatusView* view = new ExtPowerStatusView(interface,
batteryRect, B_FOLLOW_NONE, i, this);
view->SetExplicitMaxSize(BSize(70, 80));
view->SetExplicitMinSize(BSize(70, 80));
batteryRect, B_FOLLOW_NONE, i, batteryInfoView, this);
BatteryTab* tab = new BatteryTab(batteryInfoView, view);
fBatteryTabView->AddTab(batteryInfoView, tab);
// Has to be added, otherwise it won't get info updates
view->Hide();
AddChild(view);
batteryLayout->AddView(view);
fBatteryViewList.AddItem(view);
fDriverInterface->StartWatching(view);
if (!view->IsCritical())
fSelectedView = view;
}
batteryLayout->AddItem(BSpaceLayoutItem::CreateGlue());
infoLayout->AddView(fBatteryInfoView);
if (!fSelectedView && fBatteryViewList.CountItems() > 0)
fSelectedView = fBatteryViewList.ItemAt(0);
fSelectedView->Select();
BSize size = mainLayout->PreferredSize();
BSize size = GetLayout()->PreferredSize();
ResizeTo(size.width, size.height);
}
@ -333,20 +386,8 @@ ExtendedInfoWindow::~ExtendedInfoWindow()
}
BatteryInfoView*
ExtendedInfoWindow::GetExtendedBatteryInfoView()
BatteryTabView*
ExtendedInfoWindow::GetBatteryTabView()
{
return fBatteryInfoView;
}
void
ExtendedInfoWindow::BatterySelected(ExtPowerStatusView* view)
{
if (fSelectedView) {
fSelectedView->Select(false);
fSelectedView->Invalidate();
}
fSelectedView = view;
return fBatteryTabView;
}

View File

@ -1,9 +1,10 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Copyright 2009-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@Clemens-Zeidler.de
* Kacper Kasper, kacperkasper@gmail.com
*/
#ifndef EXTENDED_INFO_WINDOW_H
@ -13,6 +14,7 @@
#include <ObjectList.h>
#include <String.h>
#include <StringView.h>
#include <TabView.h>
#include <View.h>
#include <Window.h>
@ -40,16 +42,16 @@ private:
class ExtendedInfoWindow;
class BatteryTabView;
class ExtPowerStatusView : public PowerStatusView {
public:
ExtPowerStatusView(
PowerStatusDriverInterface* interface,
BRect frame, int32 resizingMode,
int batteryID, ExtendedInfoWindow* window);
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
int batteryID,
BatteryInfoView* batteryInfoView,
ExtendedInfoWindow* window);
virtual void Select(bool select = true);
@ -62,26 +64,49 @@ protected:
private:
ExtendedInfoWindow* fExtendedInfoWindow;
BatteryInfoView* fBatteryInfoView;
BatteryTabView* fBatteryTabView;
bool fSelected;
};
class BatteryTab : public BTab {
public:
BatteryTab(BatteryInfoView* target,
ExtPowerStatusView* view);
~BatteryTab();
virtual void Select(BView* owner);
virtual void DrawFocusMark(BView* owner, BRect frame);
virtual void DrawLabel(BView* owner, BRect frame);
private:
ExtPowerStatusView* fBatteryView;
};
class BatteryTabView : public BTabView {
public:
BatteryTabView(const char* name);
~BatteryTabView();
virtual BRect TabFrame(int32 index) const;
};
class ExtendedInfoWindow : public BWindow
{
public:
ExtendedInfoWindow(PowerStatusDriverInterface* interface);
~ExtendedInfoWindow();
BatteryInfoView* GetExtendedBatteryInfoView();
void BatterySelected(ExtPowerStatusView* view);
BatteryTabView* GetBatteryTabView();
private:
PowerStatusDriverInterface* fDriverInterface;
BObjectList<ExtPowerStatusView> fBatteryViewList;
BatteryInfoView* fBatteryInfoView;
BatteryTabView* fBatteryTabView;
ExtPowerStatusView* fSelectedView;
};

View File

@ -1,11 +1,12 @@
/*
* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Clemens Zeidler, haiku@Clemens-Zeidler.de
* Alexander von Gluck, kallisti5@unixzen.com
* Kacper Kasper, kacperkasper@gmail.com
*/
@ -161,7 +162,7 @@ PowerStatusView::MessageReceived(BMessage *message)
void
PowerStatusView::_DrawBattery(BRect rect)
PowerStatusView::_DrawBattery(BView* view, BRect rect)
{
BRect lightningRect = rect;
float quarter = floorf((rect.Height() + 1) / 4);
@ -172,31 +173,33 @@ PowerStatusView::_DrawBattery(BRect rect)
float left = rect.left;
rect.left += rect.Width() / 11;
lightningRect.left = rect.left;
lightningRect.InsetBy(0.0f, 5.0f * rect.Height() / 16);
if (LowColor().Brightness() > 100)
SetHighColor(0, 0, 0);
if (view->LowColor().Brightness() > 100)
view->SetHighColor(0, 0, 0);
else
SetHighColor(128, 128, 128);
view->SetHighColor(128, 128, 128);
float gap = 1;
if (rect.Height() > 8) {
gap = ceilf((rect.left - left) / 2);
// left
FillRect(BRect(rect.left, rect.top, rect.left + gap - 1, rect.bottom));
view->FillRect(BRect(rect.left, rect.top, rect.left + gap - 1, rect.bottom));
// right
FillRect(BRect(rect.right - gap + 1, rect.top, rect.right,
view->FillRect(BRect(rect.right - gap + 1, rect.top, rect.right,
rect.bottom));
// top
FillRect(BRect(rect.left + gap, rect.top, rect.right - gap,
view->FillRect(BRect(rect.left + gap, rect.top, rect.right - gap,
rect.top + gap - 1));
// bottom
FillRect(BRect(rect.left + gap, rect.bottom + 1 - gap,
view->FillRect(BRect(rect.left + gap, rect.bottom + 1 - gap,
rect.right - gap, rect.bottom));
} else
StrokeRect(rect);
view->StrokeRect(rect);
FillRect(BRect(left, floorf(rect.top + rect.Height() / 4) + 1,
view->FillRect(BRect(left, floorf(rect.top + rect.Height() / 4) + 1,
rect.left - 1, floorf(rect.bottom - rect.Height() / 4)));
int32 percent = fPercent;
@ -208,7 +211,7 @@ PowerStatusView::_DrawBattery(BRect rect)
if (percent > 0) {
rect.InsetBy(gap, gap);
rgb_color base = (rgb_color){84, 84, 84, 255};
if (LowColor().Brightness() < 128)
if (view->LowColor().Brightness() < 128)
base = (rgb_color){172, 172, 172, 255};
if (be_control_look != NULL) {
@ -216,7 +219,7 @@ PowerStatusView::_DrawBattery(BRect rect)
if (fHasBattery && percent > 0)
empty.left += empty.Width() * percent / 100.0;
be_control_look->DrawButtonBackground(this, empty, empty, base,
be_control_look->DrawButtonBackground(view, empty, empty, base,
fHasBattery
? BControlLook::B_ACTIVATED : BControlLook::B_DISABLED,
fHasBattery && percent > 0
@ -236,18 +239,17 @@ PowerStatusView::_DrawBattery(BRect rect)
rect.right = rect.left + rect.Width() * percent / 100.0;
if (be_control_look != NULL) {
be_control_look->DrawButtonBackground(this, rect, rect, base,
be_control_look->DrawButtonBackground(view, rect, rect, base,
fHasBattery ? 0 : BControlLook::B_DISABLED);
} else
FillRect(rect);
view->FillRect(rect);
}
}
if (fOnline) {
// When charging, draw a lightning symbol over the battery.
SetHighColor(255, 255, 0, 180);
SetDrawingMode(B_OP_ALPHA);
SetScale(std::min(lightningRect.Width(), lightningRect.Height()) / 16);
view->SetHighColor(255, 255, 0, 180);
view->SetDrawingMode(B_OP_ALPHA);
static const BPoint points[] = {
BPoint(3, 14),
@ -257,54 +259,49 @@ PowerStatusView::_DrawBattery(BRect rect)
BPoint(9, 12),
BPoint(9, 10)
};
FillPolygon(points, 6);
view->FillPolygon(points, 6, lightningRect);
SetScale(1);
SetDrawingMode(B_OP_OVER);
view->SetDrawingMode(B_OP_OVER);
}
SetHighColor(0, 0, 0);
view->SetHighColor(0, 0, 0);
}
void
PowerStatusView::Draw(BRect updateRect)
{
bool drawBackground = Parent() == NULL
|| (Parent()->Flags() & B_DRAW_ON_CHILDREN) == 0;
DrawTo(this, Bounds());
}
float aspect = Bounds().Width() / Bounds().Height();
bool below = aspect <= 1.0f;
void
PowerStatusView::DrawTo(BView* view, BRect rect)
{
bool inside = rect.Width() >= 50.0f && rect.Height() >= 40.0f;
font_height fontHeight;
GetFontHeight(&fontHeight);
view->GetFontHeight(&fontHeight);
float baseLine = ceilf(fontHeight.ascent);
char text[64];
_SetLabel(text, sizeof(text));
float textHeight = ceilf(fontHeight.descent + fontHeight.ascent);
float textWidth = StringWidth(text);
float textWidth = view->StringWidth(text);
bool showLabel = fShowLabel && text[0];
BRect iconRect;
if (fShowStatusIcon) {
iconRect = Bounds();
iconRect = rect;
if (showLabel) {
if (below)
iconRect.bottom -= textHeight + 2;
else
if (inside == false)
iconRect.right -= textWidth + 2;
}
// make a square
iconRect.bottom = min_c(iconRect.bottom, iconRect.right);
iconRect.right = iconRect.bottom;
if (iconRect.Width() + 1 >= kMinIconWidth
&& iconRect.Height() + 1 >= kMinIconHeight) {
_DrawBattery(iconRect);
_DrawBattery(view, iconRect);
} else {
// there is not enough space for the icon
iconRect.Set(0, 0, -1, -1);
@ -312,32 +309,30 @@ PowerStatusView::Draw(BRect updateRect)
}
if (showLabel) {
BPoint point(0, baseLine);
BPoint point(0, baseLine + rect.top);
if (iconRect.IsValid()) {
if (below) {
point.x = (iconRect.Width() - textWidth) / 2;
point.y += iconRect.Height() + 2;
if (inside == true) {
point.x = rect.left + (iconRect.Width() - textWidth) / 2 +
iconRect.Width() / 20;
point.y += (iconRect.Height() - textHeight) / 2;
} else {
point.x = iconRect.Width() + 2;
point.x = rect.left + iconRect.Width() + 2;
point.y += (iconRect.Height() - textHeight) / 2;
}
} else {
point.x = (Bounds().Width() - textWidth) / 2;
point.x = rect.left + (Bounds().Width() - textWidth) / 2;
point.y += (Bounds().Height() - textHeight) / 2;
}
if (drawBackground)
SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
else {
SetDrawingMode(B_OP_OVER);
if (LowColor().Brightness() > 100)
SetHighColor(0, 0, 0);
else
SetHighColor(255, 255, 255);
view->SetDrawingMode(B_OP_OVER);
if (fInDeskbar == false || inside == true) {
view->SetHighUIColor(B_CONTROL_BACKGROUND_COLOR);
view->DrawString(text, BPoint(point.x + 1, point.y + 1));
}
view->SetHighUIColor(B_CONTROL_TEXT_COLOR);
DrawString(text, point);
view->DrawString(text, point);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -34,6 +34,7 @@ public:
virtual void MessageReceived(BMessage* message);
virtual void Draw(BRect updateRect);
void DrawTo(BView* view, BRect rect);
protected:
@ -48,7 +49,7 @@ private:
void _GetBatteryInfo(int batteryID, battery_info* info);
void _Init();
void _SetLabel(char* buffer, size_t bufferLength);
void _DrawBattery(BRect rect);
void _DrawBattery(BView* view, BRect rect);
void _NotifyLowBattery();
protected: