//***************************************************************************** // // File: CPUButton.cpp // // Written by: Daniel Switkin // // Copyright 1999, Be Incorporated // //***************************************************************************** #include "CPUButton.h" #include #include #include #include #include #include #include #include #include #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; }