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
33NormalPulseView::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
91NormalPulseView::~NormalPulseView()
92{
93	delete fBrandLogo;
94	delete[] fCpuButtons;
95	delete[] fProgressBars;
96}
97
98
99void
100NormalPulseView::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
181void
182NormalPulseView::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
250void
251NormalPulseView::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"), 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
294void
295NormalPulseView::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
313void
314NormalPulseView::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
333void
334NormalPulseView::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