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