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