xref: /haiku/src/apps/pulse/NormalPulseView.cpp (revision ae0a10cad3999b13cbfa47a3d947a5219d2d90f4)
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 		if (topology[i].type == B_TOPOLOGY_PACKAGE) {
119 			switch (topology[i].data.package.vendor) {
120 				case B_CPU_VENDOR_AMD:
121 					logo = kAmdLogo;
122 					logoSize = sizeof(kAmdLogo);
123 					break;
124 
125 				case B_CPU_VENDOR_CYRIX:
126 					logo = kCyrixLogo;
127 					logoSize = sizeof(kCyrixLogo);
128 					break;
129 
130 				case B_CPU_VENDOR_INTEL:
131 					logo = kIntelLogo;
132 					logoSize = sizeof(kIntelLogo);
133 					break;
134 
135 				case B_CPU_VENDOR_MOTOROLA:
136 					logo = kPowerPCLogo;
137 					logoSize = sizeof(kPowerPCLogo);
138 					break;
139 
140 				case B_CPU_VENDOR_VIA:
141 					logo = kViaLogo;
142 					logoSize = sizeof(kViaLogo);
143 					break;
144 
145 				default:
146 					break;
147 			}
148 
149 			break;
150 		}
151 	}
152 
153 	delete[] topology;
154 
155 	if (logo != NULL) {
156 		fBrandLogo = new BBitmap(BRect(0, 0, 47, 47), B_RGBA32);
157 		if (BIconUtils::GetVectorIcon(logo, logoSize, fBrandLogo) != B_OK) {
158 			delete fBrandLogo;
159 			fBrandLogo = NULL;
160 		}
161 	} else
162 		fBrandLogo = NULL;
163 
164 	get_cpu_type(fVendor, sizeof(fVendor), fProcessor, sizeof(fProcessor));
165 }
166 
167 
168 void
169 NormalPulseView::DrawChip(BRect r)
170 {
171 	SetDrawingMode(B_OP_COPY);
172 	BRect innerRect = r.InsetByCopy(7, 7);
173 	SetHighColor(0x20, 0x20, 0x20);
174 	FillRect(innerRect);
175 
176 	innerRect.InsetBy(-1, -1);
177 	SetHighColor(0x40, 0x40, 0x40);
178 	SetLowColor(0x48, 0x48, 0x48);
179 	StrokeRect(innerRect, B_MIXED_COLORS);
180 
181 	innerRect.InsetBy(-1, -1);
182 	SetHighColor(0x78, 0x78, 0x78);
183 	StrokeRect(innerRect);
184 
185 	innerRect.InsetBy(-1, -1);
186 	SetHighColor(0x08, 0x08, 0x08);
187 	SetLowColor(0x20, 0x20, 0x20);
188 	StrokeLine(BPoint(innerRect.left, innerRect.top + 1),
189 		BPoint(innerRect.left, innerRect.bottom - 1), B_MIXED_COLORS);
190 	StrokeLine(BPoint(innerRect.right, innerRect.top + 1),
191 		BPoint(innerRect.right, innerRect.bottom - 1), B_MIXED_COLORS);
192 	StrokeLine(BPoint(innerRect.left + 1, innerRect.top),
193 		BPoint(innerRect.right - 1, innerRect.top), B_MIXED_COLORS);
194 	StrokeLine(BPoint(innerRect.left + 1, innerRect.bottom),
195 		BPoint(innerRect.right - 1, innerRect.bottom), B_MIXED_COLORS);
196 
197 	innerRect.InsetBy(-1, -1);
198 	SetLowColor(0xff, 0xff, 0xff);
199 	SetHighColor(0x20, 0x20, 0x20);
200 	StrokeLine(BPoint(innerRect.left, innerRect.top + 6),
201 		BPoint(innerRect.left, innerRect.bottom - 6), B_MIXED_COLORS);
202 	StrokeLine(BPoint(innerRect.right, innerRect.top + 6),
203 		BPoint(innerRect.right, innerRect.bottom - 6), B_MIXED_COLORS);
204 	StrokeLine(BPoint(innerRect.left + 6, innerRect.top),
205 		BPoint(innerRect.right - 6, innerRect.top), B_MIXED_COLORS);
206 	StrokeLine(BPoint(innerRect.left + 6, innerRect.bottom),
207 		BPoint(innerRect.right - 6, innerRect.bottom), B_MIXED_COLORS);
208 
209 	innerRect.InsetBy(-1, -1);
210 	SetHighColor(0xa8, 0xa8, 0xa8);
211 	SetLowColor(0x20, 0x20, 0x20);
212 	StrokeLine(BPoint(innerRect.left, innerRect.top + 7),
213 		BPoint(innerRect.left, innerRect.bottom - 7), B_MIXED_COLORS);
214 	StrokeLine(BPoint(innerRect.right, innerRect.top + 7),
215 		BPoint(innerRect.right, innerRect.bottom - 7), B_MIXED_COLORS);
216 	StrokeLine(BPoint(innerRect.left + 7, innerRect.top),
217 		BPoint(innerRect.right - 7, innerRect.top), B_MIXED_COLORS);
218 	StrokeLine(BPoint(innerRect.left + 7, innerRect.bottom),
219 		BPoint(innerRect.right - 7, innerRect.bottom), B_MIXED_COLORS);
220 
221 	innerRect.InsetBy(-1, -1);
222 	SetLowColor(0x58, 0x58, 0x58);
223 	SetHighColor(0x20, 0x20, 0x20);
224 	StrokeLine(BPoint(innerRect.left, innerRect.top + 8),
225 		BPoint(innerRect.left, innerRect.bottom - 8), B_MIXED_COLORS);
226 	StrokeLine(BPoint(innerRect.right, innerRect.top + 8),
227 		BPoint(innerRect.right, innerRect.bottom - 8), B_MIXED_COLORS);
228 	StrokeLine(BPoint(innerRect.left + 8, innerRect.top),
229 		BPoint(innerRect.right - 8, innerRect.top), B_MIXED_COLORS);
230 	StrokeLine(BPoint(innerRect.left + 8, innerRect.bottom),
231 		BPoint(innerRect.right - 8, innerRect.bottom), B_MIXED_COLORS);
232 
233 	SetDrawingMode(B_OP_OVER);
234 }
235 
236 
237 void
238 NormalPulseView::Draw(BRect rect)
239 {
240 	PushState();
241 
242 	SetDrawingMode(B_OP_OVER);
243 	// Processor picture
244 	DrawChip(fChipRect);
245 
246 	if (fBrandLogo != NULL) {
247 		DrawBitmap(fBrandLogo, BPoint(
248 			9 + (fChipRect.Width() - fBrandLogo->Bounds().Width()) / 2,
249 			fChipRect.top + 8));
250 	} else {
251 		SetHighColor(240, 240, 240);
252 		float width = StringWidth(fVendor);
253 		MovePenTo(10 + (fChipRect.Width() - width) / 2, fChipRect.top + 20);
254 		DrawString(fVendor);
255 	}
256 
257 	// Draw processor type and speed
258 	SetHighColor(240, 240, 240);
259 
260 	float width = StringWidth(fProcessor);
261 	MovePenTo(10 + (fChipRect.Width() - width) / 2, fChipRect.top + 48);
262 	DrawString(fProcessor);
263 
264 	char buffer[64];
265 	int32 cpuSpeed = get_rounded_cpu_speed();
266 	if (cpuSpeed > 1000 && (cpuSpeed % 10) == 0)
267 		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%.2f GHz"), cpuSpeed / 1000.0f);
268 	else
269 		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%ld MHz"), cpuSpeed);
270 
271 	// We can't assume anymore that a CPU clock speed is always static.
272 	// Let's compute the best font size for the CPU speed string each time...
273 	width = StringWidth(buffer);
274 	MovePenTo(10 + (fChipRect.Width() - width) / 2, fChipRect.top + 58);
275 	DrawString(buffer);
276 
277 	PopState();
278 }
279 
280 
281 void
282 NormalPulseView::Pulse()
283 {
284 	// Don't recalculate and redraw if this view is hidden
285 	if (!IsHidden()) {
286 		Update();
287 		if (Window()->Lock()) {
288 			// Set the value of each CPU bar
289 			for (int x = 0; x < fCpuCount; x++) {
290 				fProgressBars[x]->Set((int32)max_c(0, cpu_times[x] * 100));
291 			}
292 
293 			Sync();
294 			Window()->Unlock();
295 		}
296 	}
297 }
298 
299 
300 void
301 NormalPulseView::AttachedToWindow()
302 {
303 	fPreviousTime = system_time();
304 
305 	BMessenger messenger(Window());
306 	mode1->SetTarget(messenger);
307 	mode2->SetTarget(messenger);
308 	preferences->SetTarget(messenger);
309 	about->SetTarget(messenger);
310 
311 	system_info sys_info;
312 	get_system_info(&sys_info);
313 	if (sys_info.cpu_count >= 2) {
314 		for (unsigned int x = 0; x < sys_info.cpu_count; x++)
315 			cpu_menu_items[x]->SetTarget(messenger);
316 	}
317 }
318 
319 
320 void
321 NormalPulseView::UpdateColors(BMessage *message)
322 {
323 	int32 color = message->FindInt32("color");
324 	bool fade = message->FindBool("fade");
325 	system_info sys_info;
326 	get_system_info(&sys_info);
327 
328 	for (unsigned int x = 0; x < sys_info.cpu_count; x++) {
329 		fProgressBars[x]->UpdateColors(color, fade);
330 		fCpuButtons[x]->UpdateColors(color);
331 	}
332 }
333 
334