1 //***************************************************************************** 2 // 3 // File: CPUButton.cpp 4 // 5 // Written by: Daniel Switkin 6 // 7 // Copyright 1999, Be Incorporated 8 // 9 //***************************************************************************** 10 11 #include "CPUButton.h" 12 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include <Alert.h> 17 #include <Catalog.h> 18 #include <Dragger.h> 19 #include <Locale.h> 20 #include <PopUpMenu.h> 21 22 #include <ViewPrivate.h> 23 24 #include <syscalls.h> 25 26 #include "PulseApp.h" 27 #include "PulseView.h" 28 #include "Common.h" 29 30 #undef B_TRANSLATE_CONTEXT 31 #define B_TRANSLATE_CONTEXT "CPUButton" 32 33 34 CPUButton::CPUButton(BRect rect, const char *name, const char *label, BMessage *message) 35 : BControl(rect, name, label, message, B_FOLLOW_NONE, B_WILL_DRAW) 36 { 37 SetValue(B_CONTROL_ON); 38 SetViewColor(B_TRANSPARENT_COLOR); 39 fReplicant = false; 40 41 _InitData(); 42 } 43 44 45 CPUButton::CPUButton(BMessage *message) 46 : BControl(message) 47 { 48 fReplicant = true; 49 50 /* We remove the dragger if we are in deskbar */ 51 if (CountChildren() > 1) 52 RemoveChild(ChildAt(1)); 53 54 ResizeTo(CPUBUTTON_WIDTH, CPUBUTTON_HEIGHT); 55 56 _InitData(); 57 } 58 59 60 CPUButton::~CPUButton() 61 { 62 } 63 64 65 void 66 CPUButton::_InitData() 67 { 68 fOffColor.red = fOffColor.green = fOffColor.blue = 184; 69 fOffColor.alpha = 255; 70 71 fCPU = atoi(Label()) - 1; 72 } 73 74 75 void 76 CPUButton::_AddDragger() 77 { 78 BRect rect(Bounds()); 79 rect.top = rect.bottom - 7; 80 rect.left = rect.right - 7; 81 BDragger* dragger = new BDragger(rect, this, 82 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 83 AddChild(dragger); 84 } 85 86 87 //! Redraw the button depending on whether it's up or down 88 void 89 CPUButton::Draw(BRect rect) 90 { 91 bool value = (bool)Value(); 92 SetHighColor(value ? fOnColor : fOffColor); 93 94 if (!fReplicant) { 95 SetLowColor(Parent()->LowColor()); 96 FillRect(Bounds(), B_SOLID_LOW); 97 } 98 99 BRect bounds = Bounds(); 100 if (fReplicant && !fReplicantInDeskbar) { 101 bounds.bottom -= 4; 102 bounds.right -= 4; 103 } else if (!fReplicant) { 104 bounds.bottom -= 7; 105 bounds.right -= 7; 106 } 107 BRect color_rect(bounds); 108 color_rect.InsetBy(2, 2); 109 if (value) { 110 color_rect.bottom -= 1; 111 color_rect.right -= 1; 112 } 113 FillRect(bounds); 114 115 if (value) 116 SetHighColor(80, 80, 80); 117 else 118 SetHighColor(255, 255, 255); 119 120 BPoint start(0, 0); 121 BPoint end(bounds.right, 0); 122 StrokeLine(start, end); 123 end.Set(0, bounds.bottom); 124 StrokeLine(start, end); 125 126 if (value) 127 SetHighColor(32, 32, 32); 128 else 129 SetHighColor(216, 216, 216); 130 131 start.Set(1, 1); 132 end.Set(bounds.right - 1, 1); 133 StrokeLine(start, end); 134 end.Set(1, bounds.bottom - 1); 135 StrokeLine(start, end); 136 137 if (value) 138 SetHighColor(216, 216, 216); 139 else 140 SetHighColor(80, 80, 80); 141 142 start.Set(bounds.left + 1, bounds.bottom - 1); 143 end.Set(bounds.right - 1, bounds.bottom - 1); 144 StrokeLine(start, end); 145 start.Set(bounds.right - 1, bounds.top + 1); 146 StrokeLine(start, end); 147 148 if (value) 149 SetHighColor(255, 255, 255); 150 else 151 SetHighColor(32, 32, 32); 152 153 start.Set(bounds.left, bounds.bottom); 154 end.Set(bounds.right, bounds.bottom); 155 StrokeLine(start, end); 156 start.Set(bounds.right, bounds.top); 157 StrokeLine(start, end); 158 159 if (value) { 160 SetHighColor(0, 0, 0); 161 start.Set(bounds.left + 2, bounds.bottom - 2); 162 end.Set(bounds.right - 2, bounds.bottom - 2); 163 StrokeLine(start, end); 164 start.Set(bounds.right - 2, bounds.top + 2); 165 StrokeLine(start, end); 166 } 167 168 // Try to keep the text centered 169 BFont font; 170 GetFont(&font); 171 int label_width = (int)font.StringWidth(Label()); 172 int rect_width = bounds.IntegerWidth() - 1; 173 int rect_height = bounds.IntegerHeight(); 174 font_height fh; 175 font.GetHeight(&fh); 176 int label_height = (int)fh.ascent; 177 int x_pos = (int)(((double)(rect_width - label_width) / 2.0) + 0.5); 178 int y_pos = (rect_height - label_height) / 2 + label_height; 179 180 MovePenTo(x_pos, y_pos); 181 SetHighColor(0, 0, 0); 182 SetDrawingMode(B_OP_OVER); 183 DrawString(Label()); 184 } 185 186 187 //! Track the mouse without blocking the window 188 void 189 CPUButton::MouseDown(BPoint point) 190 { 191 BPoint mousePosition; 192 uint32 mouseButtons; 193 194 GetMouse(&mousePosition, &mouseButtons); 195 196 if ((B_PRIMARY_MOUSE_BUTTON & mouseButtons) != 0) { 197 SetValue(!Value()); 198 SetTracking(true); 199 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 200 } else if ((B_SECONDARY_MOUSE_BUTTON & mouseButtons) != 0 201 && fReplicantInDeskbar) { 202 BPopUpMenu *menu = new BPopUpMenu(B_TRANSLATE("Deskbar menu")); 203 menu->AddItem(new BMenuItem(B_TRANSLATE("About Pulse" B_UTF8_ELLIPSIS), 204 new BMessage(B_ABOUT_REQUESTED))); 205 menu->AddSeparatorItem(); 206 menu->AddItem(new BMenuItem(B_TRANSLATE("Remove replicant"), 207 new BMessage(kDeleteReplicant))); 208 menu->SetTargetForItems(this); 209 210 ConvertToScreen(&point); 211 menu->Go(point, true, true, true); 212 } 213 } 214 215 216 void 217 CPUButton::MouseUp(BPoint point) 218 { 219 if (IsTracking()) { 220 if (Bounds().Contains(point)) 221 Invoke(); 222 223 SetTracking(false); 224 } 225 } 226 227 228 void 229 CPUButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 230 { 231 if (IsTracking()) { 232 if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW) 233 SetValue(!Value()); 234 } 235 } 236 237 238 status_t 239 CPUButton::Invoke(BMessage *message) 240 { 241 if (!LastEnabledCPU(fCPU)) { 242 _kern_set_cpu_enabled(fCPU, Value()); 243 } else { 244 BAlert *alert = new BAlert(NULL, B_TRANSLATE("You can't disable the " 245 "last active CPU."), B_TRANSLATE("OK")); 246 alert->Go(NULL); 247 SetValue(!Value()); 248 } 249 250 return B_OK; 251 } 252 253 254 CPUButton * 255 CPUButton::Instantiate(BMessage *data) 256 { 257 if (!validate_instantiation(data, "CPUButton")) 258 return NULL; 259 260 return new CPUButton(data); 261 } 262 263 264 status_t 265 CPUButton::Archive(BMessage *data, bool deep) const 266 { 267 BControl::Archive(data, deep); 268 data->AddString("add_on", APP_SIGNATURE); 269 data->AddString("class", "CPUButton"); 270 return B_OK; 271 } 272 273 274 void 275 CPUButton::MessageReceived(BMessage *message) 276 { 277 switch (message->what) { 278 case B_ABOUT_REQUESTED: { 279 BAlert *alert = new BAlert(B_TRANSLATE("Info"), 280 B_TRANSLATE("Pulse\n\nBy David Ramsey and Arve Hjønnevåg\n" 281 "Revised by Daniel Switkin"), B_TRANSLATE("OK")); 282 // Use the asynchronous version so we don't block the window's thread 283 alert->Go(NULL); 284 break; 285 } 286 case PV_REPLICANT_PULSE: { 287 // Make sure we're consistent with our CPU 288 if (_kern_cpu_enabled(fCPU) != Value() && !IsTracking()) 289 SetValue(!Value()); 290 break; 291 } 292 case kDeleteReplicant: { 293 Window()->PostMessage(kDeleteReplicant, this, NULL); 294 break; 295 } 296 default: 297 BControl::MessageReceived(message); 298 break; 299 } 300 } 301 302 303 void 304 CPUButton::UpdateColors(int32 color) 305 { 306 fOnColor.red = (color & 0xff000000) >> 24; 307 fOnColor.green = (color & 0x00ff0000) >> 16; 308 fOnColor.blue = (color & 0x0000ff00) >> 8; 309 Draw(Bounds()); 310 } 311 312 313 void 314 CPUButton::AttachedToWindow() 315 { 316 SetTarget(this); 317 SetFont(be_plain_font); 318 SetFontSize(10); 319 320 fReplicantInDeskbar = false; 321 322 if (fReplicant) { 323 if (strcmp(Window()->Title(), B_TRANSLATE("Deskbar")) == 0) { 324 // Make room for dragger 325 ResizeBy(4, 4); 326 327 _AddDragger(); 328 } else 329 fReplicantInDeskbar = true; 330 331 Prefs *prefs = new Prefs(); 332 UpdateColors(prefs->normal_bar_color); 333 delete prefs; 334 } else { 335 PulseApp *pulseapp = (PulseApp *)be_app; 336 UpdateColors(pulseapp->prefs->normal_bar_color); 337 _AddDragger(); 338 } 339 340 BMessenger messenger(this); 341 fPulseRunner = new BMessageRunner(messenger, new BMessage(PV_REPLICANT_PULSE), 342 200000, -1); 343 } 344 345 346 void 347 CPUButton::DetachedFromWindow() 348 { 349 delete fPulseRunner; 350 } 351