142f6e06fSWim van der Meer//*****************************************************************************
252a38012Sejakowatz//
352a38012Sejakowatz//	File:		CPUButton.cpp
452a38012Sejakowatz//
552a38012Sejakowatz//	Written by:	Daniel Switkin
652a38012Sejakowatz//
752a38012Sejakowatz//	Copyright 1999, Be Incorporated
852a38012Sejakowatz//
942f6e06fSWim van der Meer//*****************************************************************************
104ccfb086SAxel Dörfler
1152a38012Sejakowatz#include "CPUButton.h"
1287df8902SIngo Weinhold
1387df8902SIngo Weinhold#include <stdlib.h>
142ee53d23SPhilippe Saint-Pierre#include <string.h>
1587df8902SIngo Weinhold
1687df8902SIngo Weinhold#include <Alert.h>
1742f6e06fSWim van der Meer#include <Catalog.h>
18e20b1568SPhilippe Saint-Pierre#include <Dragger.h>
19e20b1568SPhilippe Saint-Pierre#include <PopUpMenu.h>
2055f0b964SSiarzhuk Zharski#include <TextView.h>
21e20b1568SPhilippe Saint-Pierre#include <ViewPrivate.h>
2287df8902SIngo Weinhold
2387df8902SIngo Weinhold#include <syscalls.h>
2487df8902SIngo Weinhold
2552a38012Sejakowatz#include "PulseApp.h"
2652a38012Sejakowatz#include "PulseView.h"
2752a38012Sejakowatz#include "Common.h"
2852a38012Sejakowatz
29546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
30546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "CPUButton"
3142f6e06fSWim van der Meer
3252a38012Sejakowatz
334ccfb086SAxel DörflerCPUButton::CPUButton(BRect rect, const char *name, const char *label, BMessage *message)
344ccfb086SAxel Dörfler	: BControl(rect, name, label, message, B_FOLLOW_NONE, B_WILL_DRAW)
354ccfb086SAxel Dörfler{
3652a38012Sejakowatz	SetValue(B_CONTROL_ON);
3752a38012Sejakowatz	SetViewColor(B_TRANSPARENT_COLOR);
384ccfb086SAxel Dörfler	fReplicant = false;
394ccfb086SAxel Dörfler
404ccfb086SAxel Dörfler	_InitData();
414ccfb086SAxel Dörfler}
424ccfb086SAxel Dörfler
434ccfb086SAxel Dörfler
444ccfb086SAxel DörflerCPUButton::CPUButton(BMessage *message)
454ccfb086SAxel Dörfler	: BControl(message)
464ccfb086SAxel Dörfler{
474ccfb086SAxel Dörfler	fReplicant = true;
48e20b1568SPhilippe Saint-Pierre
49e20b1568SPhilippe Saint-Pierre	/* We remove the dragger if we are in deskbar */
50e20b1568SPhilippe Saint-Pierre	if (CountChildren() > 1)
51e20b1568SPhilippe Saint-Pierre		RemoveChild(ChildAt(1));
52e20b1568SPhilippe Saint-Pierre
53431bbe1cSPhilippe Saint-Pierre	ResizeTo(CPUBUTTON_WIDTH, CPUBUTTON_HEIGHT);
54e20b1568SPhilippe Saint-Pierre
554ccfb086SAxel Dörfler	_InitData();
564ccfb086SAxel Dörfler}
574ccfb086SAxel Dörfler
584ccfb086SAxel Dörfler
594ccfb086SAxel DörflerCPUButton::~CPUButton()
604ccfb086SAxel Dörfler{
6152a38012Sejakowatz}
6252a38012Sejakowatz
634ccfb086SAxel Dörfler
644ccfb086SAxel Dörflervoid
654ccfb086SAxel DörflerCPUButton::_InitData()
664ccfb086SAxel Dörfler{
674ccfb086SAxel Dörfler	fOffColor.red = fOffColor.green = fOffColor.blue = 184;
684ccfb086SAxel Dörfler	fOffColor.alpha = 255;
694ccfb086SAxel Dörfler
704ccfb086SAxel Dörfler	fCPU = atoi(Label()) - 1;
7152a38012Sejakowatz}
7252a38012Sejakowatz
734ccfb086SAxel Dörfler
74e20b1568SPhilippe Saint-Pierrevoid
75e20b1568SPhilippe Saint-PierreCPUButton::_AddDragger()
76e20b1568SPhilippe Saint-Pierre{
77e20b1568SPhilippe Saint-Pierre	BRect rect(Bounds());
78e20b1568SPhilippe Saint-Pierre	rect.top = rect.bottom - 7;
79e20b1568SPhilippe Saint-Pierre	rect.left = rect.right - 7;
80e20b1568SPhilippe Saint-Pierre	BDragger* dragger = new BDragger(rect, this,
81e20b1568SPhilippe Saint-Pierre		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
82e20b1568SPhilippe Saint-Pierre	AddChild(dragger);
83e20b1568SPhilippe Saint-Pierre}
84e20b1568SPhilippe Saint-Pierre
85e20b1568SPhilippe Saint-Pierre
864ccfb086SAxel Dörfler//! Redraw the button depending on whether it's up or down
874ccfb086SAxel Dörflervoid
884ccfb086SAxel DörflerCPUButton::Draw(BRect rect)
894ccfb086SAxel Dörfler{
9052a38012Sejakowatz	bool value = (bool)Value();
914ccfb086SAxel Dörfler	SetHighColor(value ? fOnColor : fOffColor);
9252a38012Sejakowatz
93e20b1568SPhilippe Saint-Pierre	if (!fReplicant) {
94e20b1568SPhilippe Saint-Pierre		SetLowColor(Parent()->LowColor());
95e20b1568SPhilippe Saint-Pierre		FillRect(Bounds(), B_SOLID_LOW);
96e20b1568SPhilippe Saint-Pierre	}
97e20b1568SPhilippe Saint-Pierre
9852a38012Sejakowatz	BRect bounds = Bounds();
99431bbe1cSPhilippe Saint-Pierre	if (fReplicant && !fReplicantInDeskbar) {
100431bbe1cSPhilippe Saint-Pierre		bounds.bottom -= 4;
101431bbe1cSPhilippe Saint-Pierre		bounds.right -= 4;
102431bbe1cSPhilippe Saint-Pierre	} else if (!fReplicant) {
103e20b1568SPhilippe Saint-Pierre		bounds.bottom -= 7;
104e20b1568SPhilippe Saint-Pierre		bounds.right -= 7;
105e20b1568SPhilippe Saint-Pierre	}
10652a38012Sejakowatz	BRect color_rect(bounds);
10752a38012Sejakowatz	color_rect.InsetBy(2, 2);
10852a38012Sejakowatz	if (value) {
10952a38012Sejakowatz		color_rect.bottom -= 1;
11052a38012Sejakowatz		color_rect.right -= 1;
11152a38012Sejakowatz	}
11252a38012Sejakowatz	FillRect(bounds);
1134ccfb086SAxel Dörfler
1144ccfb086SAxel Dörfler	if (value)
1154ccfb086SAxel Dörfler		SetHighColor(80, 80, 80);
1164ccfb086SAxel Dörfler	else
1174ccfb086SAxel Dörfler		SetHighColor(255, 255, 255);
1184ccfb086SAxel Dörfler
11952a38012Sejakowatz	BPoint start(0, 0);
12052a38012Sejakowatz	BPoint end(bounds.right, 0);
12152a38012Sejakowatz	StrokeLine(start, end);
12252a38012Sejakowatz	end.Set(0, bounds.bottom);
12352a38012Sejakowatz	StrokeLine(start, end);
1244ccfb086SAxel Dörfler
1254ccfb086SAxel Dörfler	if (value)
1264ccfb086SAxel Dörfler		SetHighColor(32, 32, 32);
1274ccfb086SAxel Dörfler	else
1284ccfb086SAxel Dörfler		SetHighColor(216, 216, 216);
1294ccfb086SAxel Dörfler
13052a38012Sejakowatz	start.Set(1, 1);
13152a38012Sejakowatz	end.Set(bounds.right - 1, 1);
13252a38012Sejakowatz	StrokeLine(start, end);
13352a38012Sejakowatz	end.Set(1, bounds.bottom - 1);
13452a38012Sejakowatz	StrokeLine(start, end);
1354ccfb086SAxel Dörfler
1364ccfb086SAxel Dörfler	if (value)
1374ccfb086SAxel Dörfler		SetHighColor(216, 216, 216);
1384ccfb086SAxel Dörfler	else
1394ccfb086SAxel Dörfler		SetHighColor(80, 80, 80);
1404ccfb086SAxel Dörfler
14152a38012Sejakowatz	start.Set(bounds.left + 1, bounds.bottom - 1);
14252a38012Sejakowatz	end.Set(bounds.right - 1, bounds.bottom - 1);
14352a38012Sejakowatz	StrokeLine(start, end);
14452a38012Sejakowatz	start.Set(bounds.right - 1, bounds.top + 1);
14552a38012Sejakowatz	StrokeLine(start, end);
14652a38012Sejakowatz
1474ccfb086SAxel Dörfler	if (value)
1484ccfb086SAxel Dörfler		SetHighColor(255, 255, 255);
1494ccfb086SAxel Dörfler	else
1504ccfb086SAxel Dörfler		SetHighColor(32, 32, 32);
1514ccfb086SAxel Dörfler
15252a38012Sejakowatz	start.Set(bounds.left, bounds.bottom);
15352a38012Sejakowatz	end.Set(bounds.right, bounds.bottom);
15452a38012Sejakowatz	StrokeLine(start, end);
15552a38012Sejakowatz	start.Set(bounds.right, bounds.top);
15652a38012Sejakowatz	StrokeLine(start, end);
1574ccfb086SAxel Dörfler
15852a38012Sejakowatz	if (value) {
15952a38012Sejakowatz		SetHighColor(0, 0, 0);
16052a38012Sejakowatz		start.Set(bounds.left + 2, bounds.bottom - 2);
16152a38012Sejakowatz		end.Set(bounds.right - 2, bounds.bottom - 2);
16252a38012Sejakowatz		StrokeLine(start, end);
16352a38012Sejakowatz		start.Set(bounds.right - 2, bounds.top + 2);
16452a38012Sejakowatz		StrokeLine(start, end);
16552a38012Sejakowatz	}
1664ccfb086SAxel Dörfler
16752a38012Sejakowatz	// Try to keep the text centered
16852a38012Sejakowatz	BFont font;
16952a38012Sejakowatz	GetFont(&font);
17052a38012Sejakowatz	int label_width = (int)font.StringWidth(Label());
17152a38012Sejakowatz	int rect_width = bounds.IntegerWidth() - 1;
17252a38012Sejakowatz	int rect_height = bounds.IntegerHeight();
17352a38012Sejakowatz	font_height fh;
17452a38012Sejakowatz	font.GetHeight(&fh);
17552a38012Sejakowatz	int label_height = (int)fh.ascent;
17652a38012Sejakowatz	int x_pos = (int)(((double)(rect_width - label_width) / 2.0) + 0.5);
17752a38012Sejakowatz	int y_pos = (rect_height - label_height) / 2 + label_height;
1784ccfb086SAxel Dörfler
17952a38012Sejakowatz	MovePenTo(x_pos, y_pos);
18052a38012Sejakowatz	SetHighColor(0, 0, 0);
18152a38012Sejakowatz	SetDrawingMode(B_OP_OVER);
18252a38012Sejakowatz	DrawString(Label());
18352a38012Sejakowatz}
18452a38012Sejakowatz
1854ccfb086SAxel Dörfler
1864ccfb086SAxel Dörfler//! Track the mouse without blocking the window
1874ccfb086SAxel Dörflervoid
1884ccfb086SAxel DörflerCPUButton::MouseDown(BPoint point)
1894ccfb086SAxel Dörfler{
190e20b1568SPhilippe Saint-Pierre	BPoint mousePosition;
191e20b1568SPhilippe Saint-Pierre	uint32 mouseButtons;
192e20b1568SPhilippe Saint-Pierre
193e20b1568SPhilippe Saint-Pierre	GetMouse(&mousePosition, &mouseButtons);
194e20b1568SPhilippe Saint-Pierre
195e20b1568SPhilippe Saint-Pierre	if ((B_PRIMARY_MOUSE_BUTTON & mouseButtons) != 0) {
196e20b1568SPhilippe Saint-Pierre		SetValue(!Value());
197e20b1568SPhilippe Saint-Pierre		SetTracking(true);
198e20b1568SPhilippe Saint-Pierre		SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
199e20b1568SPhilippe Saint-Pierre	} else if ((B_SECONDARY_MOUSE_BUTTON & mouseButtons) != 0
200e20b1568SPhilippe Saint-Pierre		&& fReplicantInDeskbar) {
20142f6e06fSWim van der Meer		BPopUpMenu *menu = new BPopUpMenu(B_TRANSLATE("Deskbar menu"));
20242f6e06fSWim van der Meer		menu->AddItem(new BMenuItem(B_TRANSLATE("About Pulse" B_UTF8_ELLIPSIS),
203e20b1568SPhilippe Saint-Pierre			new BMessage(B_ABOUT_REQUESTED)));
204e20b1568SPhilippe Saint-Pierre		menu->AddSeparatorItem();
20542f6e06fSWim van der Meer		menu->AddItem(new BMenuItem(B_TRANSLATE("Remove replicant"),
206e20b1568SPhilippe Saint-Pierre			new BMessage(kDeleteReplicant)));
207e20b1568SPhilippe Saint-Pierre		menu->SetTargetForItems(this);
208e20b1568SPhilippe Saint-Pierre
209e20b1568SPhilippe Saint-Pierre		ConvertToScreen(&point);
210e20b1568SPhilippe Saint-Pierre		menu->Go(point, true, true, true);
211e20b1568SPhilippe Saint-Pierre	}
21252a38012Sejakowatz}
21352a38012Sejakowatz
2144ccfb086SAxel Dörfler
2154ccfb086SAxel Dörflervoid
2164ccfb086SAxel DörflerCPUButton::MouseUp(BPoint point)
2174ccfb086SAxel Dörfler{
218e20b1568SPhilippe Saint-Pierre	if (IsTracking()) {
219e20b1568SPhilippe Saint-Pierre		if (Bounds().Contains(point))
220e20b1568SPhilippe Saint-Pierre			Invoke();
2214ccfb086SAxel Dörfler
222e20b1568SPhilippe Saint-Pierre		SetTracking(false);
223e20b1568SPhilippe Saint-Pierre	}
22452a38012Sejakowatz}
22552a38012Sejakowatz
2264ccfb086SAxel Dörfler
2274ccfb086SAxel Dörflervoid
2284ccfb086SAxel DörflerCPUButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
2294ccfb086SAxel Dörfler{
23052a38012Sejakowatz	if (IsTracking()) {
2314ccfb086SAxel Dörfler		if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
2324ccfb086SAxel Dörfler			SetValue(!Value());
23352a38012Sejakowatz	}
23452a38012Sejakowatz}
23552a38012Sejakowatz
2364ccfb086SAxel Dörfler
2374ccfb086SAxel Dörflerstatus_t
2384ccfb086SAxel DörflerCPUButton::Invoke(BMessage *message)
2394ccfb086SAxel Dörfler{
2404ccfb086SAxel Dörfler	if (!LastEnabledCPU(fCPU)) {
24187df8902SIngo Weinhold		_kern_set_cpu_enabled(fCPU, Value());
24252a38012Sejakowatz	} else {
24355f0b964SSiarzhuk Zharski		BAlert *alert = new BAlert(B_TRANSLATE("Info"),
24455f0b964SSiarzhuk Zharski			B_TRANSLATE("You can't disable the last active CPU."),
24555f0b964SSiarzhuk Zharski			B_TRANSLATE("OK"));
246aed35104SHumdinger		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
24752a38012Sejakowatz		alert->Go(NULL);
24852a38012Sejakowatz		SetValue(!Value());
24952a38012Sejakowatz	}
25087df8902SIngo Weinhold
25152a38012Sejakowatz	return B_OK;
25252a38012Sejakowatz}
25352a38012Sejakowatz
2544ccfb086SAxel Dörfler
2554ccfb086SAxel DörflerCPUButton *
2564ccfb086SAxel DörflerCPUButton::Instantiate(BMessage *data)
2574ccfb086SAxel Dörfler{
2584ccfb086SAxel Dörfler	if (!validate_instantiation(data, "CPUButton"))
2594ccfb086SAxel Dörfler		return NULL;
2604ccfb086SAxel Dörfler
26152a38012Sejakowatz	return new CPUButton(data);
26252a38012Sejakowatz}
26352a38012Sejakowatz
2644ccfb086SAxel Dörfler
2654ccfb086SAxel Dörflerstatus_t
2664ccfb086SAxel DörflerCPUButton::Archive(BMessage *data, bool deep) const
2674ccfb086SAxel Dörfler{
26852a38012Sejakowatz	BControl::Archive(data, deep);
26952a38012Sejakowatz	data->AddString("add_on", APP_SIGNATURE);
27052a38012Sejakowatz	data->AddString("class", "CPUButton");
27152a38012Sejakowatz	return B_OK;
27252a38012Sejakowatz}
27352a38012Sejakowatz
2744ccfb086SAxel Dörfler
2754ccfb086SAxel Dörflervoid
2764ccfb086SAxel DörflerCPUButton::MessageReceived(BMessage *message)
2774ccfb086SAxel Dörfler{
2784ccfb086SAxel Dörfler	switch (message->what) {
27952a38012Sejakowatz		case B_ABOUT_REQUESTED: {
28071302e7cSJonas Sundström			PulseApp::ShowAbout(false);
28152a38012Sejakowatz			break;
28252a38012Sejakowatz		}
28352a38012Sejakowatz		case PV_REPLICANT_PULSE: {
28452a38012Sejakowatz			// Make sure we're consistent with our CPU
28587df8902SIngo Weinhold			if (_kern_cpu_enabled(fCPU) != Value() && !IsTracking())
2864ccfb086SAxel Dörfler				SetValue(!Value());
28752a38012Sejakowatz			break;
28852a38012Sejakowatz		}
289e20b1568SPhilippe Saint-Pierre		case kDeleteReplicant: {
290e20b1568SPhilippe Saint-Pierre			Window()->PostMessage(kDeleteReplicant, this, NULL);
291e20b1568SPhilippe Saint-Pierre			break;
292e20b1568SPhilippe Saint-Pierre		}
29352a38012Sejakowatz		default:
29452a38012Sejakowatz			BControl::MessageReceived(message);
29552a38012Sejakowatz			break;
29652a38012Sejakowatz	}
29752a38012Sejakowatz}
29852a38012Sejakowatz
2994ccfb086SAxel Dörfler
3004ccfb086SAxel Dörflervoid
3014ccfb086SAxel DörflerCPUButton::UpdateColors(int32 color)
3024ccfb086SAxel Dörfler{
3034ccfb086SAxel Dörfler	fOnColor.red = (color & 0xff000000) >> 24;
3044ccfb086SAxel Dörfler	fOnColor.green = (color & 0x00ff0000) >> 16;
3054ccfb086SAxel Dörfler	fOnColor.blue = (color & 0x0000ff00) >> 8;
30652a38012Sejakowatz	Draw(Bounds());
30752a38012Sejakowatz}
30852a38012Sejakowatz
3094ccfb086SAxel Dörfler
3104ccfb086SAxel Dörflervoid
3114ccfb086SAxel DörflerCPUButton::AttachedToWindow()
3124ccfb086SAxel Dörfler{
31352a38012Sejakowatz	SetTarget(this);
31452a38012Sejakowatz	SetFont(be_plain_font);
31552a38012Sejakowatz	SetFontSize(10);
3169c353c97SAugustin Cavalier
317e20b1568SPhilippe Saint-Pierre	fReplicantInDeskbar = false;
3184ccfb086SAxel Dörfler
3194ccfb086SAxel Dörfler	if (fReplicant) {
320919d3b76SPhilippe Saint-Pierre		if (strcmp(Window()->Title(), B_TRANSLATE("Deskbar"))) {
321431bbe1cSPhilippe Saint-Pierre			// Make room for dragger
322431bbe1cSPhilippe Saint-Pierre			ResizeBy(4, 4);
323431bbe1cSPhilippe Saint-Pierre
324e20b1568SPhilippe Saint-Pierre			_AddDragger();
325e20b1568SPhilippe Saint-Pierre		} else
326e20b1568SPhilippe Saint-Pierre			fReplicantInDeskbar = true;
327e20b1568SPhilippe Saint-Pierre
32852a38012Sejakowatz		Prefs *prefs = new Prefs();
32952a38012Sejakowatz		UpdateColors(prefs->normal_bar_color);
33052a38012Sejakowatz		delete prefs;
33152a38012Sejakowatz	} else {
33252a38012Sejakowatz		PulseApp *pulseapp = (PulseApp *)be_app;
33352a38012Sejakowatz		UpdateColors(pulseapp->prefs->normal_bar_color);
334e20b1568SPhilippe Saint-Pierre		_AddDragger();
33552a38012Sejakowatz	}
3364ccfb086SAxel Dörfler
33752a38012Sejakowatz	BMessenger messenger(this);
3384ccfb086SAxel Dörfler	fPulseRunner = new BMessageRunner(messenger, new BMessage(PV_REPLICANT_PULSE),
33952a38012Sejakowatz		200000, -1);
34052a38012Sejakowatz}
34152a38012Sejakowatz
3424ccfb086SAxel Dörfler
3434ccfb086SAxel Dörflervoid
3444ccfb086SAxel DörflerCPUButton::DetachedFromWindow()
3454ccfb086SAxel Dörfler{
3464ccfb086SAxel Dörfler	delete fPulseRunner;
347285c5708Sshatty}
348