348 lines
6.9 KiB
C++
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;
|
|
}
|