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
NormalPulseView(BRect rect)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
~NormalPulseView()91 NormalPulseView::~NormalPulseView()
92 {
93 delete fBrandLogo;
94 delete[] fCpuButtons;
95 delete[] fProgressBars;
96 }
97
98
99 void
DetermineVendorAndProcessor()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
DrawChip(BRect r)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
Draw(BRect rect)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
Pulse()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
AttachedToWindow()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
UpdateColors(BMessage * message)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