xref: /haiku/src/apps/pulse/CPUButton.cpp (revision b6b0567fbd186f8ce8a0c90bdc7a7b5b4c649678)
1 //****************************************************************************************
2 //
3 //	File:		CPUButton.cpp
4 //
5 //	Written by:	Daniel Switkin
6 //
7 //	Copyright 1999, Be Incorporated
8 //
9 //****************************************************************************************
10 
11 
12 #include "CPUButton.h"
13 
14 #include <stdlib.h>
15 
16 #include <Alert.h>
17 
18 #include <syscalls.h>
19 
20 #include "PulseApp.h"
21 #include "PulseView.h"
22 #include "Common.h"
23 
24 
25 CPUButton::CPUButton(BRect rect, const char *name, const char *label, BMessage *message)
26 	: BControl(rect, name, label, message, B_FOLLOW_NONE, B_WILL_DRAW)
27 {
28 	SetValue(B_CONTROL_ON);
29 	SetViewColor(B_TRANSPARENT_COLOR);
30 	fReplicant = false;
31 
32 	_InitData();
33 }
34 
35 
36 CPUButton::CPUButton(BMessage *message)
37 	: BControl(message)
38 {
39 	fReplicant = true;
40 	_InitData();
41 }
42 
43 
44 CPUButton::~CPUButton()
45 {
46 }
47 
48 
49 void
50 CPUButton::_InitData()
51 {
52 	fOffColor.red = fOffColor.green = fOffColor.blue = 184;
53 	fOffColor.alpha = 255;
54 
55 	fCPU = atoi(Label()) - 1;
56 }
57 
58 
59 //! Redraw the button depending on whether it's up or down
60 void
61 CPUButton::Draw(BRect rect)
62 {
63 	bool value = (bool)Value();
64 	SetHighColor(value ? fOnColor : fOffColor);
65 
66 	BRect bounds = Bounds();
67 	BRect color_rect(bounds);
68 	color_rect.InsetBy(2, 2);
69 	if (value) {
70 		color_rect.bottom -= 1;
71 		color_rect.right -= 1;
72 	}
73 	FillRect(bounds);
74 
75 	if (value)
76 		SetHighColor(80, 80, 80);
77 	else
78 		SetHighColor(255, 255, 255);
79 
80 	BPoint start(0, 0);
81 	BPoint end(bounds.right, 0);
82 	StrokeLine(start, end);
83 	end.Set(0, bounds.bottom);
84 	StrokeLine(start, end);
85 
86 	if (value)
87 		SetHighColor(32, 32, 32);
88 	else
89 		SetHighColor(216, 216, 216);
90 
91 	start.Set(1, 1);
92 	end.Set(bounds.right - 1, 1);
93 	StrokeLine(start, end);
94 	end.Set(1, bounds.bottom - 1);
95 	StrokeLine(start, end);
96 
97 	if (value)
98 		SetHighColor(216, 216, 216);
99 	else
100 		SetHighColor(80, 80, 80);
101 
102 	start.Set(bounds.left + 1, bounds.bottom - 1);
103 	end.Set(bounds.right - 1, bounds.bottom - 1);
104 	StrokeLine(start, end);
105 	start.Set(bounds.right - 1, bounds.top + 1);
106 	StrokeLine(start, end);
107 
108 	if (value)
109 		SetHighColor(255, 255, 255);
110 	else
111 		SetHighColor(32, 32, 32);
112 
113 	start.Set(bounds.left, bounds.bottom);
114 	end.Set(bounds.right, bounds.bottom);
115 	StrokeLine(start, end);
116 	start.Set(bounds.right, bounds.top);
117 	StrokeLine(start, end);
118 
119 	if (value) {
120 		SetHighColor(0, 0, 0);
121 		start.Set(bounds.left + 2, bounds.bottom - 2);
122 		end.Set(bounds.right - 2, bounds.bottom - 2);
123 		StrokeLine(start, end);
124 		start.Set(bounds.right - 2, bounds.top + 2);
125 		StrokeLine(start, end);
126 	}
127 
128 	// Try to keep the text centered
129 	BFont font;
130 	GetFont(&font);
131 	int label_width = (int)font.StringWidth(Label());
132 	int rect_width = bounds.IntegerWidth() - 1;
133 	int rect_height = bounds.IntegerHeight();
134 	font_height fh;
135 	font.GetHeight(&fh);
136 	int label_height = (int)fh.ascent;
137 	int x_pos = (int)(((double)(rect_width - label_width) / 2.0) + 0.5);
138 	int y_pos = (rect_height - label_height) / 2 + label_height;
139 
140 	MovePenTo(x_pos, y_pos);
141 	SetHighColor(0, 0, 0);
142 	SetDrawingMode(B_OP_OVER);
143 	DrawString(Label());
144 }
145 
146 
147 //! Track the mouse without blocking the window
148 void
149 CPUButton::MouseDown(BPoint point)
150 {
151 	SetValue(!Value());
152 	SetTracking(true);
153 	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
154 }
155 
156 
157 void
158 CPUButton::MouseUp(BPoint point)
159 {
160 	if (Bounds().Contains(point))
161 		Invoke();
162 
163 	SetTracking(false);
164 }
165 
166 
167 void
168 CPUButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
169 {
170 	if (IsTracking()) {
171 		if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
172 			SetValue(!Value());
173 	}
174 }
175 
176 
177 status_t
178 CPUButton::Invoke(BMessage *message)
179 {
180 	if (!LastEnabledCPU(fCPU)) {
181 		_kern_set_cpu_enabled(fCPU, Value());
182 	} else {
183 		BAlert *alert = new BAlert(NULL, "You can't disable the last active CPU.", "OK");
184 		alert->Go(NULL);
185 		SetValue(!Value());
186 	}
187 
188 	return B_OK;
189 }
190 
191 
192 CPUButton *
193 CPUButton::Instantiate(BMessage *data)
194 {
195 	if (!validate_instantiation(data, "CPUButton"))
196 		return NULL;
197 
198 	return new CPUButton(data);
199 }
200 
201 
202 status_t
203 CPUButton::Archive(BMessage *data, bool deep) const
204 {
205 	BControl::Archive(data, deep);
206 	data->AddString("add_on", APP_SIGNATURE);
207 	data->AddString("class", "CPUButton");
208 	return B_OK;
209 }
210 
211 
212 void
213 CPUButton::MessageReceived(BMessage *message)
214 {
215 	switch (message->what) {
216 		case B_ABOUT_REQUESTED: {
217 			BAlert *alert = new BAlert("Info", "Pulse\n\nBy David Ramsey and Arve Hjønnevåg\nRevised by Daniel Switkin", "OK");
218 			// Use the asynchronous version so we don't block the window's thread
219 			alert->Go(NULL);
220 			break;
221 		}
222 		case PV_REPLICANT_PULSE: {
223 			// Make sure we're consistent with our CPU
224 			if (_kern_cpu_enabled(fCPU) != Value() && !IsTracking())
225 				SetValue(!Value());
226 			break;
227 		}
228 		default:
229 			BControl::MessageReceived(message);
230 			break;
231 	}
232 }
233 
234 
235 void
236 CPUButton::UpdateColors(int32 color)
237 {
238 	fOnColor.red = (color & 0xff000000) >> 24;
239 	fOnColor.green = (color & 0x00ff0000) >> 16;
240 	fOnColor.blue = (color & 0x0000ff00) >> 8;
241 	Draw(Bounds());
242 }
243 
244 
245 void
246 CPUButton::AttachedToWindow()
247 {
248 	SetTarget(this);
249 	SetFont(be_plain_font);
250 	SetFontSize(10);
251 
252 	if (fReplicant) {
253 		Prefs *prefs = new Prefs();
254 		UpdateColors(prefs->normal_bar_color);
255 		delete prefs;
256 	} else {
257 		PulseApp *pulseapp = (PulseApp *)be_app;
258 		UpdateColors(pulseapp->prefs->normal_bar_color);
259 	}
260 
261 	BMessenger messenger(this);
262 	fPulseRunner = new BMessageRunner(messenger, new BMessage(PV_REPLICANT_PULSE),
263 		200000, -1);
264 }
265 
266 
267 void
268 CPUButton::DetachedFromWindow()
269 {
270 	delete fPulseRunner;
271 }
272 
273