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 <Window.h>
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24
25#include <cpu_type.h>
26
27#undef B_TRANSLATION_CONTEXT
28#define B_TRANSLATION_CONTEXT "NormalPulseView"
29
30
31float
32max_font_size(BFont font, const char* text, float maxSize, float maxWidth)
33{
34	const float steps = 0.5f;
35
36	for (float size = maxSize; size > 4; size -= steps) {
37		font.SetSize(size);
38		if (font.StringWidth(text) <= maxWidth)
39			return size;
40	}
41
42	return 4;
43}
44
45
46//	#pragma mark -
47
48
49NormalPulseView::NormalPulseView(BRect rect)
50	: PulseView(rect, "NormalPulseView"),
51	fHasBrandLogo(false)
52{
53	rgb_color color = { 168, 168, 168, 0xff };
54	SetViewColor(color);
55	SetLowColor(color);
56
57	mode1->SetLabel(B_TRANSLATE("Mini mode"));
58	mode1->SetMessage(new BMessage(PV_MINI_MODE));
59	mode2->SetLabel(B_TRANSLATE("Deskbar mode"));
60	mode2->SetMessage(new BMessage(PV_DESKBAR_MODE));
61
62	DetermineVendorAndProcessor();
63
64	// Allocate progress bars and button pointers
65	system_info systemInfo;
66	get_system_info(&systemInfo);
67	fCpuCount = systemInfo.cpu_count;
68	fProgressBars = new ProgressBar *[fCpuCount];
69	fCpuButtons = new CPUButton *[fCpuCount];
70
71	// Set up the CPU activity bars and buttons
72	for (int x = 0; x < fCpuCount; x++) {
73		BRect r(PROGRESS_MLEFT, PROGRESS_MTOP + ITEM_OFFSET * x,
74			PROGRESS_MLEFT + ProgressBar::PROGRESS_WIDTH,
75			PROGRESS_MTOP + ITEM_OFFSET * x + ProgressBar::PROGRESS_HEIGHT);
76		char* str2 = (char *)B_TRANSLATE("CPU progress bar");
77		fProgressBars[x] = new ProgressBar(r, str2);
78		AddChild(fProgressBars[x]);
79
80		r.Set(CPUBUTTON_MLEFT, CPUBUTTON_MTOP + ITEM_OFFSET * x,
81			CPUBUTTON_MLEFT + CPUBUTTON_WIDTH + 7,
82			CPUBUTTON_MTOP + ITEM_OFFSET * x + CPUBUTTON_HEIGHT + 7);
83		char temp[4];
84		sprintf(temp, "%d", x + 1);
85		fCpuButtons[x] = new CPUButton(r, B_TRANSLATE("Pulse"), temp, NULL);
86		AddChild(fCpuButtons[x]);
87	}
88
89	if (fCpuCount == 1) {
90		fProgressBars[0]->MoveBy(-3, 12);
91		fCpuButtons[0]->Hide();
92	}
93}
94
95
96NormalPulseView::~NormalPulseView()
97{
98	delete fCpuLogo;
99	delete[] fCpuButtons;
100	delete[] fProgressBars;
101}
102
103
104void
105NormalPulseView::CalculateFontSizes()
106{
107	BFont font;
108	GetFont(&font);
109
110	fProcessorFontSize = max_font_size(font, fProcessor, 11.0f, 46.0f);
111
112	if (!fHasBrandLogo)
113		fVendorFontSize = max_font_size(font, fVendor, 13.0f, 46.0f);
114}
115
116
117void
118NormalPulseView::DetermineVendorAndProcessor()
119{
120	system_info sys_info;
121	get_system_info(&sys_info);
122
123	// Initialize logo
124
125	fCpuLogo = new BBitmap(BRect(0, 0, 63, 62), B_CMAP8);
126	unsigned char *logo = BlankLogo;
127
128#if __POWERPC__
129	logo = PowerPCLogo;
130#endif
131#if __INTEL__
132
133	switch (sys_info.cpu_type & B_CPU_x86_VENDOR_MASK) {
134	case B_CPU_INTEL_x86:
135		logo = IntelLogo;
136		break;
137
138	case B_CPU_AMD_x86:
139		logo = AmdLogo;
140		break;
141	};
142#endif
143
144	fCpuLogo->SetBits(logo, fCpuLogo->BitsLength(), 0, B_CMAP8);
145	fHasBrandLogo = (logo != BlankLogo);
146
147	get_cpu_type(fVendor, sizeof(fVendor), fProcessor, sizeof(fProcessor));
148}
149
150
151void
152NormalPulseView::Draw(BRect rect)
153{
154	PushState();
155
156	// Black frame
157	SetHighColor(0, 0, 0);
158	BRect frame = Bounds();
159	frame.right--;
160	frame.bottom--;
161	StrokeRect(frame);
162
163	// Bevelled edges
164	SetHighColor(255, 255, 255);
165	StrokeLine(BPoint(1, 1), BPoint(frame.right - 1, 1));
166	StrokeLine(BPoint(1, 1), BPoint(1, frame.bottom - 1));
167	SetHighColor(80, 80, 80);
168	StrokeLine(BPoint(frame.right, 1), BPoint(frame.right, frame.bottom));
169	StrokeLine(BPoint(2, frame.bottom), BPoint(frame.right - 1, frame.bottom));
170
171	// Dividing line
172	SetHighColor(96, 96, 96);
173	StrokeLine(BPoint(1, frame.bottom + 1), BPoint(frame.right, frame.bottom + 1));
174	SetHighColor(255, 255, 255);
175	StrokeLine(BPoint(1, frame.bottom + 2), BPoint(frame.right, frame.bottom + 2));
176
177	// Processor picture
178	DrawBitmap(fCpuLogo, BPoint(10, 10));
179
180#if __INTEL__
181	// Do nothing in the case of non-Intel CPUs - they already have a logo
182	if (!fHasBrandLogo) {
183		SetDrawingMode(B_OP_OVER);
184		SetHighColor(240, 240, 240);
185		SetFontSize(fVendorFontSize);
186
187		float width = StringWidth(fVendor);
188		MovePenTo(10 + (32 - width / 2), 30);
189		DrawString(fVendor);
190	}
191#endif
192
193	// Draw processor type and speed
194	SetDrawingMode(B_OP_OVER);
195	SetHighColor(240, 240, 240);
196
197	SetFontSize(fProcessorFontSize);
198	float width = StringWidth(fProcessor);
199	MovePenTo(10 + (32 - width / 2), 48);
200	DrawString(fProcessor);
201
202	char buffer[64];
203	int32 cpuSpeed = get_rounded_cpu_speed();
204	if (cpuSpeed > 1000 && (cpuSpeed % 10) == 0)
205		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%.2f GHz"), cpuSpeed / 1000.0f);
206	else
207		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%ld MHz"), cpuSpeed);
208
209	// We can't assume anymore that a CPU clock speed is always static.
210	// Let's compute the best font size for the CPU speed string each time...
211	BFont font;
212	GetFont(&font);
213	SetFontSize(max_font_size(font, buffer, fProcessorFontSize, 46.0f));
214	width = StringWidth(buffer);
215	MovePenTo(10 + (32 - width / 2), 60);
216	DrawString(buffer);
217
218	PopState();
219}
220
221
222void
223NormalPulseView::Pulse()
224{
225	// Don't recalculate and redraw if this view is hidden
226	if (!IsHidden()) {
227		Update();
228		if (Window()->Lock()) {
229			// Set the value of each CPU bar
230			for (int x = 0; x < fCpuCount; x++) {
231				fProgressBars[x]->Set((int32)max_c(0, cpu_times[x] * 100));
232			}
233
234			Sync();
235			Window()->Unlock();
236		}
237	}
238}
239
240
241void
242NormalPulseView::AttachedToWindow()
243{
244	SetFont(be_bold_font);
245	CalculateFontSizes();
246
247	fPreviousTime = system_time();
248
249	BMessenger messenger(Window());
250	mode1->SetTarget(messenger);
251	mode2->SetTarget(messenger);
252	preferences->SetTarget(messenger);
253	about->SetTarget(messenger);
254
255	system_info sys_info;
256	get_system_info(&sys_info);
257	if (sys_info.cpu_count >= 2) {
258		for (int x = 0; x < sys_info.cpu_count; x++) {
259			cpu_menu_items[x]->SetTarget(messenger);
260		}
261	}
262}
263
264
265void
266NormalPulseView::UpdateColors(BMessage *message)
267{
268	int32 color = message->FindInt32("color");
269	bool fade = message->FindBool("fade");
270	system_info sys_info;
271	get_system_info(&sys_info);
272
273	for (int x = 0; x < sys_info.cpu_count; x++) {
274		fProgressBars[x]->UpdateColors(color, fade);
275		fCpuButtons[x]->UpdateColors(color);
276	}
277}
278
279