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