xref: /haiku/src/apps/pulse/CPUButton.cpp (revision 2ee53d23fa2810c7e342b79228757162dd9f075c)
152a38012Sejakowatz //****************************************************************************************
252a38012Sejakowatz //
352a38012Sejakowatz //	File:		CPUButton.cpp
452a38012Sejakowatz //
552a38012Sejakowatz //	Written by:	Daniel Switkin
652a38012Sejakowatz //
752a38012Sejakowatz //	Copyright 1999, Be Incorporated
852a38012Sejakowatz //
952a38012Sejakowatz //****************************************************************************************
1052a38012Sejakowatz 
114ccfb086SAxel Dörfler 
1252a38012Sejakowatz #include "CPUButton.h"
1387df8902SIngo Weinhold 
1487df8902SIngo Weinhold #include <stdlib.h>
15*2ee53d23SPhilippe Saint-Pierre #include <string.h>
1687df8902SIngo Weinhold 
1787df8902SIngo Weinhold #include <Alert.h>
18e20b1568SPhilippe Saint-Pierre #include <Dragger.h>
19e20b1568SPhilippe Saint-Pierre #include <PopUpMenu.h>
20e20b1568SPhilippe Saint-Pierre 
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 
2952a38012Sejakowatz 
304ccfb086SAxel Dörfler CPUButton::CPUButton(BRect rect, const char *name, const char *label, BMessage *message)
314ccfb086SAxel Dörfler 	: BControl(rect, name, label, message, B_FOLLOW_NONE, B_WILL_DRAW)
324ccfb086SAxel Dörfler {
3352a38012Sejakowatz 	SetValue(B_CONTROL_ON);
3452a38012Sejakowatz 	SetViewColor(B_TRANSPARENT_COLOR);
354ccfb086SAxel Dörfler 	fReplicant = false;
364ccfb086SAxel Dörfler 
374ccfb086SAxel Dörfler 	_InitData();
3852a38012Sejakowatz }
3952a38012Sejakowatz 
404ccfb086SAxel Dörfler 
414ccfb086SAxel Dörfler CPUButton::CPUButton(BMessage *message)
424ccfb086SAxel Dörfler 	: BControl(message)
434ccfb086SAxel Dörfler {
444ccfb086SAxel Dörfler 	fReplicant = true;
45e20b1568SPhilippe Saint-Pierre 
46e20b1568SPhilippe Saint-Pierre 	/* We remove the dragger if we are in deskbar */
47e20b1568SPhilippe Saint-Pierre 	if (CountChildren() > 1)
48e20b1568SPhilippe Saint-Pierre 		RemoveChild(ChildAt(1));
49e20b1568SPhilippe Saint-Pierre 
50e20b1568SPhilippe Saint-Pierre 	ResizeBy(-7, -7);
51e20b1568SPhilippe Saint-Pierre 
524ccfb086SAxel Dörfler 	_InitData();
5352a38012Sejakowatz }
5452a38012Sejakowatz 
554ccfb086SAxel Dörfler 
564ccfb086SAxel Dörfler CPUButton::~CPUButton()
574ccfb086SAxel Dörfler {
584ccfb086SAxel Dörfler }
594ccfb086SAxel Dörfler 
604ccfb086SAxel Dörfler 
614ccfb086SAxel Dörfler void
624ccfb086SAxel Dörfler CPUButton::_InitData()
634ccfb086SAxel Dörfler {
644ccfb086SAxel Dörfler 	fOffColor.red = fOffColor.green = fOffColor.blue = 184;
654ccfb086SAxel Dörfler 	fOffColor.alpha = 255;
664ccfb086SAxel Dörfler 
674ccfb086SAxel Dörfler 	fCPU = atoi(Label()) - 1;
684ccfb086SAxel Dörfler }
694ccfb086SAxel Dörfler 
704ccfb086SAxel Dörfler 
71e20b1568SPhilippe Saint-Pierre void
72e20b1568SPhilippe Saint-Pierre CPUButton::_AddDragger()
73e20b1568SPhilippe Saint-Pierre {
74e20b1568SPhilippe Saint-Pierre 	BRect rect(Bounds());
75e20b1568SPhilippe Saint-Pierre 	rect.top = rect.bottom - 7;
76e20b1568SPhilippe Saint-Pierre 	rect.left = rect.right - 7;
77e20b1568SPhilippe Saint-Pierre 	BDragger* dragger = new BDragger(rect, this,
78e20b1568SPhilippe Saint-Pierre 		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
79e20b1568SPhilippe Saint-Pierre 	AddChild(dragger);
80e20b1568SPhilippe Saint-Pierre }
81e20b1568SPhilippe Saint-Pierre 
82e20b1568SPhilippe Saint-Pierre 
834ccfb086SAxel Dörfler //! Redraw the button depending on whether it's up or down
844ccfb086SAxel Dörfler void
854ccfb086SAxel Dörfler CPUButton::Draw(BRect rect)
864ccfb086SAxel Dörfler {
8752a38012Sejakowatz 	bool value = (bool)Value();
884ccfb086SAxel Dörfler 	SetHighColor(value ? fOnColor : fOffColor);
8952a38012Sejakowatz 
90e20b1568SPhilippe Saint-Pierre 	if (!fReplicant) {
91e20b1568SPhilippe Saint-Pierre 		SetLowColor(Parent()->LowColor());
92e20b1568SPhilippe Saint-Pierre 		FillRect(Bounds(), B_SOLID_LOW);
93e20b1568SPhilippe Saint-Pierre 	}
94e20b1568SPhilippe Saint-Pierre 
9552a38012Sejakowatz 	BRect bounds = Bounds();
96e20b1568SPhilippe Saint-Pierre 	if (!fReplicantInDeskbar) {
97e20b1568SPhilippe Saint-Pierre 		bounds.bottom -= 7;
98e20b1568SPhilippe Saint-Pierre 		bounds.right -= 7;
99e20b1568SPhilippe Saint-Pierre 	}
10052a38012Sejakowatz 	BRect color_rect(bounds);
10152a38012Sejakowatz 	color_rect.InsetBy(2, 2);
10252a38012Sejakowatz 	if (value) {
10352a38012Sejakowatz 		color_rect.bottom -= 1;
10452a38012Sejakowatz 		color_rect.right -= 1;
10552a38012Sejakowatz 	}
10652a38012Sejakowatz 	FillRect(bounds);
10752a38012Sejakowatz 
1084ccfb086SAxel Dörfler 	if (value)
1094ccfb086SAxel Dörfler 		SetHighColor(80, 80, 80);
1104ccfb086SAxel Dörfler 	else
1114ccfb086SAxel Dörfler 		SetHighColor(255, 255, 255);
1124ccfb086SAxel Dörfler 
11352a38012Sejakowatz 	BPoint start(0, 0);
11452a38012Sejakowatz 	BPoint end(bounds.right, 0);
11552a38012Sejakowatz 	StrokeLine(start, end);
11652a38012Sejakowatz 	end.Set(0, bounds.bottom);
11752a38012Sejakowatz 	StrokeLine(start, end);
11852a38012Sejakowatz 
1194ccfb086SAxel Dörfler 	if (value)
1204ccfb086SAxel Dörfler 		SetHighColor(32, 32, 32);
1214ccfb086SAxel Dörfler 	else
1224ccfb086SAxel Dörfler 		SetHighColor(216, 216, 216);
1234ccfb086SAxel Dörfler 
12452a38012Sejakowatz 	start.Set(1, 1);
12552a38012Sejakowatz 	end.Set(bounds.right - 1, 1);
12652a38012Sejakowatz 	StrokeLine(start, end);
12752a38012Sejakowatz 	end.Set(1, bounds.bottom - 1);
12852a38012Sejakowatz 	StrokeLine(start, end);
12952a38012Sejakowatz 
1304ccfb086SAxel Dörfler 	if (value)
1314ccfb086SAxel Dörfler 		SetHighColor(216, 216, 216);
1324ccfb086SAxel Dörfler 	else
1334ccfb086SAxel Dörfler 		SetHighColor(80, 80, 80);
1344ccfb086SAxel Dörfler 
13552a38012Sejakowatz 	start.Set(bounds.left + 1, bounds.bottom - 1);
13652a38012Sejakowatz 	end.Set(bounds.right - 1, bounds.bottom - 1);
13752a38012Sejakowatz 	StrokeLine(start, end);
13852a38012Sejakowatz 	start.Set(bounds.right - 1, bounds.top + 1);
13952a38012Sejakowatz 	StrokeLine(start, end);
14052a38012Sejakowatz 
1414ccfb086SAxel Dörfler 	if (value)
1424ccfb086SAxel Dörfler 		SetHighColor(255, 255, 255);
1434ccfb086SAxel Dörfler 	else
1444ccfb086SAxel Dörfler 		SetHighColor(32, 32, 32);
1454ccfb086SAxel Dörfler 
14652a38012Sejakowatz 	start.Set(bounds.left, bounds.bottom);
14752a38012Sejakowatz 	end.Set(bounds.right, bounds.bottom);
14852a38012Sejakowatz 	StrokeLine(start, end);
14952a38012Sejakowatz 	start.Set(bounds.right, bounds.top);
15052a38012Sejakowatz 	StrokeLine(start, end);
15152a38012Sejakowatz 
15252a38012Sejakowatz 	if (value) {
15352a38012Sejakowatz 		SetHighColor(0, 0, 0);
15452a38012Sejakowatz 		start.Set(bounds.left + 2, bounds.bottom - 2);
15552a38012Sejakowatz 		end.Set(bounds.right - 2, bounds.bottom - 2);
15652a38012Sejakowatz 		StrokeLine(start, end);
15752a38012Sejakowatz 		start.Set(bounds.right - 2, bounds.top + 2);
15852a38012Sejakowatz 		StrokeLine(start, end);
15952a38012Sejakowatz 	}
16052a38012Sejakowatz 
16152a38012Sejakowatz 	// Try to keep the text centered
16252a38012Sejakowatz 	BFont font;
16352a38012Sejakowatz 	GetFont(&font);
16452a38012Sejakowatz 	int label_width = (int)font.StringWidth(Label());
16552a38012Sejakowatz 	int rect_width = bounds.IntegerWidth() - 1;
16652a38012Sejakowatz 	int rect_height = bounds.IntegerHeight();
16752a38012Sejakowatz 	font_height fh;
16852a38012Sejakowatz 	font.GetHeight(&fh);
16952a38012Sejakowatz 	int label_height = (int)fh.ascent;
17052a38012Sejakowatz 	int x_pos = (int)(((double)(rect_width - label_width) / 2.0) + 0.5);
17152a38012Sejakowatz 	int y_pos = (rect_height - label_height) / 2 + label_height;
17252a38012Sejakowatz 
17352a38012Sejakowatz 	MovePenTo(x_pos, y_pos);
17452a38012Sejakowatz 	SetHighColor(0, 0, 0);
17552a38012Sejakowatz 	SetDrawingMode(B_OP_OVER);
17652a38012Sejakowatz 	DrawString(Label());
17752a38012Sejakowatz }
17852a38012Sejakowatz 
1794ccfb086SAxel Dörfler 
1804ccfb086SAxel Dörfler //! Track the mouse without blocking the window
1814ccfb086SAxel Dörfler void
1824ccfb086SAxel Dörfler CPUButton::MouseDown(BPoint point)
1834ccfb086SAxel Dörfler {
184e20b1568SPhilippe Saint-Pierre 	BPoint mousePosition;
185e20b1568SPhilippe Saint-Pierre 	uint32 mouseButtons;
186e20b1568SPhilippe Saint-Pierre 
187e20b1568SPhilippe Saint-Pierre 	GetMouse(&mousePosition, &mouseButtons);
188e20b1568SPhilippe Saint-Pierre 
189e20b1568SPhilippe Saint-Pierre 	if ((B_PRIMARY_MOUSE_BUTTON & mouseButtons) != 0) {
19052a38012Sejakowatz 		SetValue(!Value());
19152a38012Sejakowatz 		SetTracking(true);
19252a38012Sejakowatz 		SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
193e20b1568SPhilippe Saint-Pierre 	} else if ((B_SECONDARY_MOUSE_BUTTON & mouseButtons) != 0
194e20b1568SPhilippe Saint-Pierre 		&& fReplicantInDeskbar) {
195e20b1568SPhilippe Saint-Pierre 		BPopUpMenu *menu = new BPopUpMenu("Deskbar menu");
196e20b1568SPhilippe Saint-Pierre 		menu->AddItem(new BMenuItem("About Pulse" B_UTF8_ELLIPSIS,
197e20b1568SPhilippe Saint-Pierre 			new BMessage(B_ABOUT_REQUESTED)));
198e20b1568SPhilippe Saint-Pierre 		menu->AddSeparatorItem();
199e20b1568SPhilippe Saint-Pierre 		menu->AddItem(new BMenuItem("Remove replicant",
200e20b1568SPhilippe Saint-Pierre 			new BMessage(kDeleteReplicant)));
201e20b1568SPhilippe Saint-Pierre 		menu->SetTargetForItems(this);
202e20b1568SPhilippe Saint-Pierre 
203e20b1568SPhilippe Saint-Pierre 		ConvertToScreen(&point);
204e20b1568SPhilippe Saint-Pierre 		menu->Go(point, true, true, true);
205e20b1568SPhilippe Saint-Pierre 	}
20652a38012Sejakowatz }
20752a38012Sejakowatz 
2084ccfb086SAxel Dörfler 
2094ccfb086SAxel Dörfler void
2104ccfb086SAxel Dörfler CPUButton::MouseUp(BPoint point)
2114ccfb086SAxel Dörfler {
212e20b1568SPhilippe Saint-Pierre 	if (IsTracking()) {
2134ccfb086SAxel Dörfler 		if (Bounds().Contains(point))
2144ccfb086SAxel Dörfler 			Invoke();
2154ccfb086SAxel Dörfler 
21652a38012Sejakowatz 		SetTracking(false);
21752a38012Sejakowatz 	}
218e20b1568SPhilippe Saint-Pierre }
21952a38012Sejakowatz 
2204ccfb086SAxel Dörfler 
2214ccfb086SAxel Dörfler void
2224ccfb086SAxel Dörfler CPUButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
2234ccfb086SAxel Dörfler {
22452a38012Sejakowatz 	if (IsTracking()) {
2254ccfb086SAxel Dörfler 		if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
2264ccfb086SAxel Dörfler 			SetValue(!Value());
22752a38012Sejakowatz 	}
22852a38012Sejakowatz }
22952a38012Sejakowatz 
23052a38012Sejakowatz 
2314ccfb086SAxel Dörfler status_t
2324ccfb086SAxel Dörfler CPUButton::Invoke(BMessage *message)
2334ccfb086SAxel Dörfler {
2344ccfb086SAxel Dörfler 	if (!LastEnabledCPU(fCPU)) {
23587df8902SIngo Weinhold 		_kern_set_cpu_enabled(fCPU, Value());
23652a38012Sejakowatz 	} else {
23752a38012Sejakowatz 		BAlert *alert = new BAlert(NULL, "You can't disable the last active CPU.", "OK");
23852a38012Sejakowatz 		alert->Go(NULL);
23952a38012Sejakowatz 		SetValue(!Value());
24052a38012Sejakowatz 	}
24152a38012Sejakowatz 
24252a38012Sejakowatz 	return B_OK;
24352a38012Sejakowatz }
24452a38012Sejakowatz 
2454ccfb086SAxel Dörfler 
2464ccfb086SAxel Dörfler CPUButton *
2474ccfb086SAxel Dörfler CPUButton::Instantiate(BMessage *data)
2484ccfb086SAxel Dörfler {
2494ccfb086SAxel Dörfler 	if (!validate_instantiation(data, "CPUButton"))
2504ccfb086SAxel Dörfler 		return NULL;
2514ccfb086SAxel Dörfler 
25252a38012Sejakowatz 	return new CPUButton(data);
25352a38012Sejakowatz }
25452a38012Sejakowatz 
2554ccfb086SAxel Dörfler 
2564ccfb086SAxel Dörfler status_t
2574ccfb086SAxel Dörfler CPUButton::Archive(BMessage *data, bool deep) const
2584ccfb086SAxel Dörfler {
25952a38012Sejakowatz 	BControl::Archive(data, deep);
26052a38012Sejakowatz 	data->AddString("add_on", APP_SIGNATURE);
26152a38012Sejakowatz 	data->AddString("class", "CPUButton");
26252a38012Sejakowatz 	return B_OK;
26352a38012Sejakowatz }
26452a38012Sejakowatz 
2654ccfb086SAxel Dörfler 
2664ccfb086SAxel Dörfler void
2674ccfb086SAxel Dörfler CPUButton::MessageReceived(BMessage *message)
2684ccfb086SAxel Dörfler {
26952a38012Sejakowatz 	switch (message->what) {
27052a38012Sejakowatz 		case B_ABOUT_REQUESTED: {
27152a38012Sejakowatz 			BAlert *alert = new BAlert("Info", "Pulse\n\nBy David Ramsey and Arve Hjønnevåg\nRevised by Daniel Switkin", "OK");
27252a38012Sejakowatz 			// Use the asynchronous version so we don't block the window's thread
27352a38012Sejakowatz 			alert->Go(NULL);
27452a38012Sejakowatz 			break;
27552a38012Sejakowatz 		}
27652a38012Sejakowatz 		case PV_REPLICANT_PULSE: {
27752a38012Sejakowatz 			// Make sure we're consistent with our CPU
27887df8902SIngo Weinhold 			if (_kern_cpu_enabled(fCPU) != Value() && !IsTracking())
2794ccfb086SAxel Dörfler 				SetValue(!Value());
28052a38012Sejakowatz 			break;
28152a38012Sejakowatz 		}
282e20b1568SPhilippe Saint-Pierre 		case kDeleteReplicant: {
283e20b1568SPhilippe Saint-Pierre 			Window()->PostMessage(kDeleteReplicant, this, NULL);
284e20b1568SPhilippe Saint-Pierre 			break;
285e20b1568SPhilippe Saint-Pierre 		}
28652a38012Sejakowatz 		default:
28752a38012Sejakowatz 			BControl::MessageReceived(message);
28852a38012Sejakowatz 			break;
28952a38012Sejakowatz 	}
29052a38012Sejakowatz }
29152a38012Sejakowatz 
2924ccfb086SAxel Dörfler 
2934ccfb086SAxel Dörfler void
2944ccfb086SAxel Dörfler CPUButton::UpdateColors(int32 color)
2954ccfb086SAxel Dörfler {
2964ccfb086SAxel Dörfler 	fOnColor.red = (color & 0xff000000) >> 24;
2974ccfb086SAxel Dörfler 	fOnColor.green = (color & 0x00ff0000) >> 16;
2984ccfb086SAxel Dörfler 	fOnColor.blue = (color & 0x0000ff00) >> 8;
29952a38012Sejakowatz 	Draw(Bounds());
30052a38012Sejakowatz }
30152a38012Sejakowatz 
3024ccfb086SAxel Dörfler 
3034ccfb086SAxel Dörfler void
3044ccfb086SAxel Dörfler CPUButton::AttachedToWindow()
3054ccfb086SAxel Dörfler {
30652a38012Sejakowatz 	SetTarget(this);
30752a38012Sejakowatz 	SetFont(be_plain_font);
30852a38012Sejakowatz 	SetFontSize(10);
30952a38012Sejakowatz 
310e20b1568SPhilippe Saint-Pierre 	fReplicantInDeskbar = false;
311e20b1568SPhilippe Saint-Pierre 
3124ccfb086SAxel Dörfler 	if (fReplicant) {
313e20b1568SPhilippe Saint-Pierre 		if (strcmp(Window()->Title(), "Deskbar")) {
314e20b1568SPhilippe Saint-Pierre 			// return to original size
315e20b1568SPhilippe Saint-Pierre 			ResizeBy(7, 7);
316e20b1568SPhilippe Saint-Pierre 			_AddDragger();
317e20b1568SPhilippe Saint-Pierre 		} else
318e20b1568SPhilippe Saint-Pierre 			fReplicantInDeskbar = true;
319e20b1568SPhilippe Saint-Pierre 
32052a38012Sejakowatz 		Prefs *prefs = new Prefs();
32152a38012Sejakowatz 		UpdateColors(prefs->normal_bar_color);
32252a38012Sejakowatz 		delete prefs;
32352a38012Sejakowatz 	} else {
32452a38012Sejakowatz 		PulseApp *pulseapp = (PulseApp *)be_app;
32552a38012Sejakowatz 		UpdateColors(pulseapp->prefs->normal_bar_color);
326e20b1568SPhilippe Saint-Pierre 		_AddDragger();
32752a38012Sejakowatz 	}
32852a38012Sejakowatz 
32952a38012Sejakowatz 	BMessenger messenger(this);
3304ccfb086SAxel Dörfler 	fPulseRunner = new BMessageRunner(messenger, new BMessage(PV_REPLICANT_PULSE),
33152a38012Sejakowatz 		200000, -1);
33252a38012Sejakowatz }
33352a38012Sejakowatz 
3344ccfb086SAxel Dörfler 
3354ccfb086SAxel Dörfler void
3364ccfb086SAxel Dörfler CPUButton::DetachedFromWindow()
3374ccfb086SAxel Dörfler {
3384ccfb086SAxel Dörfler 	delete fPulseRunner;
33952a38012Sejakowatz }
340