haiku/src/apps/pulse/CPUButton.cpp

348 lines
6.9 KiB
C++

//*****************************************************************************
//
// File: CPUButton.cpp
//
// Written by: Daniel Switkin
//
// Copyright 1999, Be Incorporated
//
//*****************************************************************************
#include "CPUButton.h"
#include <stdlib.h>
#include <string.h>
#include <Alert.h>
#include <Catalog.h>
#include <Dragger.h>
#include <PopUpMenu.h>
#include <TextView.h>
#include <ViewPrivate.h>
#include <syscalls.h>
#include "PulseApp.h"
#include "PulseView.h"
#include "Common.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "CPUButton"
CPUButton::CPUButton(BRect rect, const char *name, const char *label, BMessage *message)
: BControl(rect, name, label, message, B_FOLLOW_NONE, B_WILL_DRAW)
{
SetValue(B_CONTROL_ON);
SetViewColor(B_TRANSPARENT_COLOR);
fReplicant = false;
_InitData();
}
CPUButton::CPUButton(BMessage *message)
: BControl(message)
{
fReplicant = true;
/* We remove the dragger if we are in deskbar */
if (CountChildren() > 1)
RemoveChild(ChildAt(1));
ResizeTo(CPUBUTTON_WIDTH, CPUBUTTON_HEIGHT);
_InitData();
}
CPUButton::~CPUButton()
{
}
void
CPUButton::_InitData()
{
fOffColor.red = fOffColor.green = fOffColor.blue = 184;
fOffColor.alpha = 255;
fCPU = atoi(Label()) - 1;
}
void
CPUButton::_AddDragger()
{
BRect rect(Bounds());
rect.top = rect.bottom - 7;
rect.left = rect.right - 7;
BDragger* dragger = new BDragger(rect, this,
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
AddChild(dragger);
}
//! Redraw the button depending on whether it's up or down
void
CPUButton::Draw(BRect rect)
{
bool value = (bool)Value();
SetHighColor(value ? fOnColor : fOffColor);
if (!fReplicant) {
SetLowColor(Parent()->LowColor());
FillRect(Bounds(), B_SOLID_LOW);
}
BRect bounds = Bounds();
if (fReplicant && !fReplicantInDeskbar) {
bounds.bottom -= 4;
bounds.right -= 4;
} else if (!fReplicant) {
bounds.bottom -= 7;
bounds.right -= 7;
}
BRect color_rect(bounds);
color_rect.InsetBy(2, 2);
if (value) {
color_rect.bottom -= 1;
color_rect.right -= 1;
}
FillRect(bounds);
if (value)
SetHighColor(80, 80, 80);
else
SetHighColor(255, 255, 255);
BPoint start(0, 0);
BPoint end(bounds.right, 0);
StrokeLine(start, end);
end.Set(0, bounds.bottom);
StrokeLine(start, end);
if (value)
SetHighColor(32, 32, 32);
else
SetHighColor(216, 216, 216);
start.Set(1, 1);
end.Set(bounds.right - 1, 1);
StrokeLine(start, end);
end.Set(1, bounds.bottom - 1);
StrokeLine(start, end);
if (value)
SetHighColor(216, 216, 216);
else
SetHighColor(80, 80, 80);
start.Set(bounds.left + 1, bounds.bottom - 1);
end.Set(bounds.right - 1, bounds.bottom - 1);
StrokeLine(start, end);
start.Set(bounds.right - 1, bounds.top + 1);
StrokeLine(start, end);
if (value)
SetHighColor(255, 255, 255);
else
SetHighColor(32, 32, 32);
start.Set(bounds.left, bounds.bottom);
end.Set(bounds.right, bounds.bottom);
StrokeLine(start, end);
start.Set(bounds.right, bounds.top);
StrokeLine(start, end);
if (value) {
SetHighColor(0, 0, 0);
start.Set(bounds.left + 2, bounds.bottom - 2);
end.Set(bounds.right - 2, bounds.bottom - 2);
StrokeLine(start, end);
start.Set(bounds.right - 2, bounds.top + 2);
StrokeLine(start, end);
}
// Try to keep the text centered
BFont font;
GetFont(&font);
int label_width = (int)font.StringWidth(Label());
int rect_width = bounds.IntegerWidth() - 1;
int rect_height = bounds.IntegerHeight();
font_height fh;
font.GetHeight(&fh);
int label_height = (int)fh.ascent;
int x_pos = (int)(((double)(rect_width - label_width) / 2.0) + 0.5);
int y_pos = (rect_height - label_height) / 2 + label_height;
MovePenTo(x_pos, y_pos);
SetHighColor(0, 0, 0);
SetDrawingMode(B_OP_OVER);
DrawString(Label());
}
//! Track the mouse without blocking the window
void
CPUButton::MouseDown(BPoint point)
{
BPoint mousePosition;
uint32 mouseButtons;
GetMouse(&mousePosition, &mouseButtons);
if ((B_PRIMARY_MOUSE_BUTTON & mouseButtons) != 0) {
SetValue(!Value());
SetTracking(true);
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
} else if ((B_SECONDARY_MOUSE_BUTTON & mouseButtons) != 0
&& fReplicantInDeskbar) {
BPopUpMenu *menu = new BPopUpMenu(B_TRANSLATE("Deskbar menu"));
menu->AddItem(new BMenuItem(B_TRANSLATE("About Pulse" B_UTF8_ELLIPSIS),
new BMessage(B_ABOUT_REQUESTED)));
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem(B_TRANSLATE("Remove replicant"),
new BMessage(kDeleteReplicant)));
menu->SetTargetForItems(this);
ConvertToScreen(&point);
menu->Go(point, true, true, true);
}
}
void
CPUButton::MouseUp(BPoint point)
{
if (IsTracking()) {
if (Bounds().Contains(point))
Invoke();
SetTracking(false);
}
}
void
CPUButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
{
if (IsTracking()) {
if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
SetValue(!Value());
}
}
status_t
CPUButton::Invoke(BMessage *message)
{
if (!LastEnabledCPU(fCPU)) {
_kern_set_cpu_enabled(fCPU, Value());
} else {
BAlert *alert = new BAlert(B_TRANSLATE("Info"),
B_TRANSLATE("You can't disable the last active CPU."),
B_TRANSLATE("OK"));
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go(NULL);
SetValue(!Value());
}
return B_OK;
}
CPUButton *
CPUButton::Instantiate(BMessage *data)
{
if (!validate_instantiation(data, "CPUButton"))
return NULL;
return new CPUButton(data);
}
status_t
CPUButton::Archive(BMessage *data, bool deep) const
{
BControl::Archive(data, deep);
data->AddString("add_on", APP_SIGNATURE);
data->AddString("class", "CPUButton");
return B_OK;
}
void
CPUButton::MessageReceived(BMessage *message)
{
switch (message->what) {
case B_ABOUT_REQUESTED: {
be_app->PostMessage(B_ABOUT_REQUESTED);
break;
}
case PV_REPLICANT_PULSE: {
// Make sure we're consistent with our CPU
if (_kern_cpu_enabled(fCPU) != Value() && !IsTracking())
SetValue(!Value());
break;
}
case kDeleteReplicant: {
Window()->PostMessage(kDeleteReplicant, this, NULL);
break;
}
default:
BControl::MessageReceived(message);
break;
}
}
void
CPUButton::UpdateColors(int32 color)
{
fOnColor.red = (color & 0xff000000) >> 24;
fOnColor.green = (color & 0x00ff0000) >> 16;
fOnColor.blue = (color & 0x0000ff00) >> 8;
Draw(Bounds());
}
void
CPUButton::AttachedToWindow()
{
SetTarget(this);
SetFont(be_plain_font);
SetFontSize(10);
fReplicantInDeskbar = false;
if (fReplicant) {
if (strcmp(Window()->Title(), B_TRANSLATE("Deskbar"))) {
// Make room for dragger
ResizeBy(4, 4);
_AddDragger();
} else
fReplicantInDeskbar = true;
Prefs *prefs = new Prefs();
UpdateColors(prefs->normal_bar_color);
delete prefs;
} else {
PulseApp *pulseapp = (PulseApp *)be_app;
UpdateColors(pulseapp->fPrefs->normal_bar_color);
_AddDragger();
}
BMessenger messenger(this);
fPulseRunner = new BMessageRunner(messenger, new BMessage(PV_REPLICANT_PULSE),
200000, -1);
}
void
CPUButton::DetachedFromWindow()
{
delete fPulseRunner;
}