xref: /haiku/src/apps/pulse/NormalPulseView.cpp (revision 47c05920fde47c2618efccd24bd82f1e79cdf05a)
1 //*****************************************************************************
2 //
3 //	File:		NormalPulseView.cpp
4 //
5 //	Written by:	Daniel Switkin
6 //
7 //	Copyright 1999, Be Incorporated
8 //
9 //*****************************************************************************
10 
11 
12 #include "NormalPulseView.h"
13 #include "Common.h"
14 #include "Pictures"
15 
16 #include <Catalog.h>
17 #include <Bitmap.h>
18 #include <Dragger.h>
19 #include <IconUtils.h>
20 #include <Window.h>
21 
22 #include <algorithm>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include <cpu_type.h>
28 
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "NormalPulseView"
31 
32 
33 NormalPulseView::NormalPulseView(BRect rect)
34 	: PulseView(rect, "NormalPulseView"),
35 	fBrandLogo(NULL)
36 {
37 	SetResizingMode(B_NOT_RESIZABLE);
38 	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
39 	SetLowUIColor(ViewUIColor());
40 
41 	mode1->SetLabel(B_TRANSLATE("Mini mode"));
42 	mode1->SetMessage(new BMessage(PV_MINI_MODE));
43 	mode2->SetLabel(B_TRANSLATE("Deskbar mode"));
44 	mode2->SetMessage(new BMessage(PV_DESKBAR_MODE));
45 
46 	DetermineVendorAndProcessor();
47 	BFont font(be_plain_font);
48 	font.SetSize(8);
49 	SetFont(&font);
50 
51 	float width = std::max(StringWidth(fProcessor), 48.0f);
52 	fChipRect = BRect(10, (rect.Height() - width - 15) / 2, 25 + width,
53 		(rect.Height() + width + 15) / 2);
54 	float progressLeft = fChipRect.right + 29;
55 	float cpuLeft = fChipRect.right + 5;
56 
57 	// Allocate progress bars and button pointers
58 	system_info systemInfo;
59 	get_system_info(&systemInfo);
60 	fCpuCount = systemInfo.cpu_count;
61 	fProgressBars = new ProgressBar *[fCpuCount];
62 	fCpuButtons = new CPUButton *[fCpuCount];
63 
64 	// Set up the CPU activity bars and buttons
65 	for (int x = 0; x < fCpuCount; x++) {
66 		BRect r(progressLeft, PROGRESS_MTOP + ITEM_OFFSET * x,
67 			progressLeft + ProgressBar::PROGRESS_WIDTH,
68 			PROGRESS_MTOP + ITEM_OFFSET * x + ProgressBar::PROGRESS_HEIGHT);
69 		char* str2 = (char *)B_TRANSLATE("CPU progress bar");
70 		fProgressBars[x] = new ProgressBar(r, str2);
71 		AddChild(fProgressBars[x]);
72 
73 		r.Set(cpuLeft, CPUBUTTON_MTOP + ITEM_OFFSET * x,
74 			cpuLeft + CPUBUTTON_WIDTH + 7,
75 			CPUBUTTON_MTOP + ITEM_OFFSET * x + CPUBUTTON_HEIGHT + 7);
76 		char temp[4];
77 		snprintf(temp, sizeof(temp), "%hhd", int8(x + 1));
78 		fCpuButtons[x] = new CPUButton(r, B_TRANSLATE("Pulse"), temp, NULL);
79 		AddChild(fCpuButtons[x]);
80 	}
81 
82 	if (fCpuCount == 1) {
83 		fProgressBars[0]->MoveBy(-3, 12);
84 		fCpuButtons[0]->Hide();
85 	}
86 
87 	ResizeTo(progressLeft + ProgressBar::PROGRESS_WIDTH + 10, rect.Height());
88 }
89 
90 
91 NormalPulseView::~NormalPulseView()
92 {
93 	delete fBrandLogo;
94 	delete[] fCpuButtons;
95 	delete[] fProgressBars;
96 }
97 
98 
99 void
100 NormalPulseView::DetermineVendorAndProcessor()
101 {
102 	system_info sys_info;
103 	get_system_info(&sys_info);
104 
105 	// Initialize logo
106 
107 	const unsigned char* logo = NULL;
108 	size_t logoSize = 0;
109 	uint32 topologyNodeCount = 0;
110 	cpu_topology_node_info* topology = NULL;
111 
112 	get_cpu_topology_info(NULL, &topologyNodeCount);
113 	if (topologyNodeCount != 0)
114 		topology = new cpu_topology_node_info[topologyNodeCount];
115 	get_cpu_topology_info(topology, &topologyNodeCount);
116 
117 	for (uint32 i = 0; i < topologyNodeCount; i++) {
118 		// Use less specific platform logo only if no vendor specific one is
119 		// available
120 		if (logo == NULL && topology[i].type == B_TOPOLOGY_ROOT) {
121 			switch (topology[i].data.root.platform) {
122 				case B_CPU_RISC_V:
123 					logo = kRiscVLogo;
124 					logoSize = sizeof(kRiscVLogo);
125 					break;
126 				default:
127 					break;
128 			}
129 		}
130 
131 		if (topology[i].type == B_TOPOLOGY_PACKAGE) {
132 			switch (topology[i].data.package.vendor) {
133 				case B_CPU_VENDOR_AMD:
134 					logo = kAmdLogo;
135 					logoSize = sizeof(kAmdLogo);
136 					break;
137 
138 				case B_CPU_VENDOR_CYRIX:
139 					logo = kCyrixLogo;
140 					logoSize = sizeof(kCyrixLogo);
141 					break;
142 
143 				case B_CPU_VENDOR_INTEL:
144 					logo = kIntelLogo;
145 					logoSize = sizeof(kIntelLogo);
146 					break;
147 
148 				case B_CPU_VENDOR_MOTOROLA:
149 					logo = kPowerPCLogo;
150 					logoSize = sizeof(kPowerPCLogo);
151 					break;
152 
153 				case B_CPU_VENDOR_VIA:
154 					logo = kViaLogo;
155 					logoSize = sizeof(kViaLogo);
156 					break;
157 
158 				default:
159 					break;
160 			}
161 
162 			break;
163 		}
164 	}
165 
166 	delete[] topology;
167 
168 	if (logo != NULL) {
169 		fBrandLogo = new BBitmap(BRect(0, 0, 47, 47), B_RGBA32);
170 		if (BIconUtils::GetVectorIcon(logo, logoSize, fBrandLogo) != B_OK) {
171 			delete fBrandLogo;
172 			fBrandLogo = NULL;
173 		}
174 	} else
175 		fBrandLogo = NULL;
176 
177 	get_cpu_type(fVendor, sizeof(fVendor), fProcessor, sizeof(fProcessor));
178 }
179 
180 
181 void
182 NormalPulseView::DrawChip(BRect r)
183 {
184 	SetDrawingMode(B_OP_COPY);
185 	BRect innerRect = r.InsetByCopy(7, 7);
186 	SetHighColor(0x20, 0x20, 0x20);
187 	FillRect(innerRect);
188 
189 	innerRect.InsetBy(-1, -1);
190 	SetHighColor(0x40, 0x40, 0x40);
191 	SetLowColor(0x48, 0x48, 0x48);
192 	StrokeRect(innerRect, B_MIXED_COLORS);
193 
194 	innerRect.InsetBy(-1, -1);
195 	SetHighColor(0x78, 0x78, 0x78);
196 	StrokeRect(innerRect);
197 
198 	innerRect.InsetBy(-1, -1);
199 	SetHighColor(0x08, 0x08, 0x08);
200 	SetLowColor(0x20, 0x20, 0x20);
201 	StrokeLine(BPoint(innerRect.left, innerRect.top + 1),
202 		BPoint(innerRect.left, innerRect.bottom - 1), B_MIXED_COLORS);
203 	StrokeLine(BPoint(innerRect.right, innerRect.top + 1),
204 		BPoint(innerRect.right, innerRect.bottom - 1), B_MIXED_COLORS);
205 	StrokeLine(BPoint(innerRect.left + 1, innerRect.top),
206 		BPoint(innerRect.right - 1, innerRect.top), B_MIXED_COLORS);
207 	StrokeLine(BPoint(innerRect.left + 1, innerRect.bottom),
208 		BPoint(innerRect.right - 1, innerRect.bottom), B_MIXED_COLORS);
209 
210 	innerRect.InsetBy(-1, -1);
211 	SetLowColor(0xff, 0xff, 0xff);
212 	SetHighColor(0x20, 0x20, 0x20);
213 	StrokeLine(BPoint(innerRect.left, innerRect.top + 6),
214 		BPoint(innerRect.left, innerRect.bottom - 6), B_MIXED_COLORS);
215 	StrokeLine(BPoint(innerRect.right, innerRect.top + 6),
216 		BPoint(innerRect.right, innerRect.bottom - 6), B_MIXED_COLORS);
217 	StrokeLine(BPoint(innerRect.left + 6, innerRect.top),
218 		BPoint(innerRect.right - 6, innerRect.top), B_MIXED_COLORS);
219 	StrokeLine(BPoint(innerRect.left + 6, innerRect.bottom),
220 		BPoint(innerRect.right - 6, innerRect.bottom), B_MIXED_COLORS);
221 
222 	innerRect.InsetBy(-1, -1);
223 	SetHighColor(0xa8, 0xa8, 0xa8);
224 	SetLowColor(0x20, 0x20, 0x20);
225 	StrokeLine(BPoint(innerRect.left, innerRect.top + 7),
226 		BPoint(innerRect.left, innerRect.bottom - 7), B_MIXED_COLORS);
227 	StrokeLine(BPoint(innerRect.right, innerRect.top + 7),
228 		BPoint(innerRect.right, innerRect.bottom - 7), B_MIXED_COLORS);
229 	StrokeLine(BPoint(innerRect.left + 7, innerRect.top),
230 		BPoint(innerRect.right - 7, innerRect.top), B_MIXED_COLORS);
231 	StrokeLine(BPoint(innerRect.left + 7, innerRect.bottom),
232 		BPoint(innerRect.right - 7, innerRect.bottom), B_MIXED_COLORS);
233 
234 	innerRect.InsetBy(-1, -1);
235 	SetLowColor(0x58, 0x58, 0x58);
236 	SetHighColor(0x20, 0x20, 0x20);
237 	StrokeLine(BPoint(innerRect.left, innerRect.top + 8),
238 		BPoint(innerRect.left, innerRect.bottom - 8), B_MIXED_COLORS);
239 	StrokeLine(BPoint(innerRect.right, innerRect.top + 8),
240 		BPoint(innerRect.right, innerRect.bottom - 8), B_MIXED_COLORS);
241 	StrokeLine(BPoint(innerRect.left + 8, innerRect.top),
242 		BPoint(innerRect.right - 8, innerRect.top), B_MIXED_COLORS);
243 	StrokeLine(BPoint(innerRect.left + 8, innerRect.bottom),
244 		BPoint(innerRect.right - 8, innerRect.bottom), B_MIXED_COLORS);
245 
246 	SetDrawingMode(B_OP_OVER);
247 }
248 
249 
250 void
251 NormalPulseView::Draw(BRect rect)
252 {
253 	PushState();
254 
255 	SetDrawingMode(B_OP_OVER);
256 	// Processor picture
257 	DrawChip(fChipRect);
258 
259 	if (fBrandLogo != NULL) {
260 		DrawBitmap(fBrandLogo, BPoint(
261 			9 + (fChipRect.Width() - fBrandLogo->Bounds().Width()) / 2,
262 			fChipRect.top + 6));
263 	} else {
264 		SetHighColor(240, 240, 240);
265 		float width = StringWidth(fVendor);
266 		MovePenTo(10 + (fChipRect.Width() - width) / 2, fChipRect.top + 20);
267 		DrawString(fVendor);
268 	}
269 
270 	// Draw processor type and speed
271 	SetHighColor(240, 240, 240);
272 
273 	float width = StringWidth(fProcessor);
274 	MovePenTo(10 + (fChipRect.Width() - width) / 2, fChipRect.top + 53);
275 	DrawString(fProcessor);
276 
277 	char buffer[64];
278 	int32 cpuSpeed = get_rounded_cpu_speed();
279 	if (cpuSpeed > 1000 && (cpuSpeed % 10) == 0)
280 		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%.2f GHz"), cpuSpeed / 1000.0f);
281 	else
282 		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%ld MHz"), (long int)cpuSpeed);
283 
284 	// We can't assume anymore that a CPU clock speed is always static.
285 	// Let's compute the best font size for the CPU speed string each time...
286 	width = StringWidth(buffer);
287 	MovePenTo(10 + (fChipRect.Width() - width) / 2, fChipRect.top + 62);
288 	DrawString(buffer);
289 
290 	PopState();
291 }
292 
293 
294 void
295 NormalPulseView::Pulse()
296 {
297 	// Don't recalculate and redraw if this view is hidden
298 	if (!IsHidden()) {
299 		Update();
300 		if (Window()->Lock()) {
301 			// Set the value of each CPU bar
302 			for (int x = 0; x < fCpuCount; x++) {
303 				fProgressBars[x]->Set((int32)max_c(0, cpu_times[x] * 100));
304 			}
305 
306 			Sync();
307 			Window()->Unlock();
308 		}
309 	}
310 }
311 
312 
313 void
314 NormalPulseView::AttachedToWindow()
315 {
316 	fPreviousTime = system_time();
317 
318 	BMessenger messenger(Window());
319 	mode1->SetTarget(messenger);
320 	mode2->SetTarget(messenger);
321 	preferences->SetTarget(messenger);
322 	about->SetTarget(messenger);
323 
324 	system_info sys_info;
325 	get_system_info(&sys_info);
326 	if (sys_info.cpu_count >= 2) {
327 		for (unsigned int x = 0; x < sys_info.cpu_count; x++)
328 			cpu_menu_items[x]->SetTarget(messenger);
329 	}
330 }
331 
332 
333 void
334 NormalPulseView::UpdateColors(BMessage *message)
335 {
336 	int32 color = message->FindInt32("color");
337 	bool fade = message->FindBool("fade");
338 	system_info sys_info;
339 	get_system_info(&sys_info);
340 
341 	for (unsigned int x = 0; x < sys_info.cpu_count; x++) {
342 		fProgressBars[x]->UpdateColors(color, fade);
343 		fCpuButtons[x]->UpdateColors(color);
344 	}
345 }
346 
347