1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 2 // 3 // Copyright (c) 2004, Haiku 4 // 5 // This software is part of the Haiku distribution and is covered 6 // by the Haiku license. 7 // 8 // 9 // File: MethodReplicant.cpp 10 // Authors: Jérôme Duval, 11 // 12 // Description: Input Server 13 // Created: October 13, 2004 14 // 15 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 16 17 #include <Alert.h> 18 #include <AppDefs.h> 19 #include <Debug.h> 20 #include <Dragger.h> 21 #include <Bitmap.h> 22 #include <MenuItem.h> 23 #include <Message.h> 24 #include <Messenger.h> 25 #include <PopUpMenu.h> 26 27 #include <string.h> 28 #include "MethodReplicant.h" 29 #include "remote_icon.h" 30 31 #include "InputServerTypes.h" 32 33 #ifdef DEBUG 34 #define CALLED() PRINT(("CALLED %s \n", __PRETTY_FUNCTION__)); 35 #else 36 #define CALLED() 37 #endif 38 39 40 MethodReplicant::MethodReplicant(const char* signature) 41 : BView(BRect(0, 0, 15, 15), REPLICANT_CTL_NAME, B_FOLLOW_ALL, B_WILL_DRAW), 42 fMenu("", false, false) 43 { 44 // Background Bitmap 45 fSegments = new BBitmap(BRect(0, 0, kRemoteWidth - 1, kRemoteHeight - 1), kRemoteColorSpace); 46 fSegments->SetBits(kRemoteBits, kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace); 47 // Background Color 48 SetViewColor(184,184,184); 49 50 //add dragger 51 BRect rect(Bounds()); 52 rect.left = rect.right-7.0; 53 rect.top = rect.bottom-7.0; 54 BDragger *dragger = new BDragger(rect, this, B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 55 AddChild(dragger); 56 dragger->SetViewColor(B_TRANSPARENT_32_BIT); 57 58 ASSERT(signature!=NULL); 59 fSignature = strdup(signature); 60 61 fMenu.SetFont(be_plain_font); 62 fMenu.SetRadioMode(true); 63 } 64 65 66 MethodReplicant::MethodReplicant(BMessage *message) 67 : BView(message), 68 fMenu("", false, false) 69 { 70 // Background Bitmap 71 fSegments = new BBitmap(BRect(0, 0, kRemoteWidth - 1, kRemoteHeight - 1), kRemoteColorSpace); 72 fSegments->SetBits(kRemoteBits, kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace); 73 74 const char *signature = NULL; 75 message->FindString("add_on", &signature); 76 ASSERT(signature!=NULL); 77 fSignature = strdup(signature); 78 79 fMenu.SetFont(be_plain_font); 80 fMenu.SetRadioMode(true); 81 } 82 83 84 MethodReplicant::~MethodReplicant() 85 { 86 delete fSegments; 87 delete fSignature; 88 } 89 90 91 // archiving overrides 92 MethodReplicant * 93 MethodReplicant::Instantiate(BMessage *data) 94 { 95 CALLED(); 96 if (!validate_instantiation(data, REPLICANT_CTL_NAME)) 97 return NULL; 98 return new MethodReplicant(data); 99 } 100 101 102 status_t 103 MethodReplicant::Archive(BMessage *data, bool deep) const 104 { 105 BView::Archive(data, deep); 106 107 data->AddString("add_on", fSignature); 108 return B_NO_ERROR; 109 } 110 111 112 void 113 MethodReplicant::AttachedToWindow() 114 { 115 CALLED(); 116 BMessenger messenger(this); 117 BMessage msg(IS_METHOD_REGISTER); 118 msg.AddMessenger("address", messenger); 119 120 BMessenger inputMessenger(fSignature); 121 if (inputMessenger.SendMessage(&msg)!=B_OK) { 122 printf("error when contacting input_server\n"); 123 } 124 } 125 126 127 void 128 MethodReplicant::MessageReceived(BMessage *message) 129 { 130 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what>>24, message->what>>16, message->what>>8, message->what)); 131 PRINT_OBJECT(*message); 132 switch (message->what) { 133 case B_ABOUT_REQUESTED: 134 (new BAlert("About Method Replicant", "Method Replicant (Replicant)\n" 135 " Brought to you by Jérôme DUVAL.\n\n" 136 "Haiku, 2004","OK"))->Go(); 137 break; 138 case IS_UPDATE_NAME: 139 UpdateMethodName(message); 140 break; 141 case IS_UPDATE_ICON: 142 UpdateMethodIcon(message); 143 break; 144 case IS_UPDATE_MENU: 145 UpdateMethodMenu(message); 146 break; 147 case IS_UPDATE_METHOD: 148 UpdateMethod(message); 149 break; 150 case IS_ADD_METHOD: 151 AddMethod(message); 152 break; 153 case IS_REMOVE_METHOD: 154 RemoveMethod(message); 155 break; 156 157 default: 158 BView::MessageReceived(message); 159 break; 160 } 161 } 162 163 164 void 165 MethodReplicant::Draw(BRect rect) 166 { 167 BView::Draw(rect); 168 169 SetDrawingMode(B_OP_OVER); 170 DrawBitmap(fSegments); 171 } 172 173 174 void 175 MethodReplicant::MouseDown(BPoint point) 176 { 177 CALLED(); 178 uint32 mouseButtons; 179 BPoint where; 180 GetMouse(&where, &mouseButtons, true); 181 182 where = ConvertToScreen(point); 183 184 fMenu.SetTargetForItems(this); 185 BMenuItem *item = fMenu.Go(where, true, true, 186 BRect(where - BPoint(4, 4), where + BPoint(4, 4))); 187 188 if (item && dynamic_cast<MethodMenuItem *>(item)) { 189 BMessage msg(IS_SET_METHOD); 190 msg.AddInt32("cookie", ((MethodMenuItem*)item)->Cookie()); 191 BMessenger messenger(fSignature); 192 messenger.SendMessage(&msg); 193 } 194 } 195 196 197 void 198 MethodReplicant::MouseUp(BPoint point) 199 { 200 /* don't Quit() ! thanks for FFM users */ 201 } 202 203 204 void 205 MethodReplicant::UpdateMethod(BMessage *message) 206 { 207 CALLED(); 208 int32 cookie; 209 if (message->FindInt32("cookie", &cookie)!=B_OK) { 210 fprintf(stderr, "can't find cookie in message\n"); 211 return; 212 } 213 214 MethodMenuItem *item = FindItemByCookie(cookie); 215 if (item == NULL) { 216 fprintf(stderr, "can't find item with cookie %lx\n", cookie); 217 return; 218 } 219 item->SetMarked(true); 220 221 fSegments->SetBits(item->Icon(), kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace); 222 Invalidate(); 223 } 224 225 226 void 227 MethodReplicant::UpdateMethodIcon(BMessage *message) 228 { 229 CALLED(); 230 int32 cookie; 231 if (message->FindInt32("cookie", &cookie)!=B_OK) { 232 fprintf(stderr, "can't find cookie in message\n"); 233 return; 234 } 235 236 const uchar *data; 237 ssize_t numBytes; 238 if (message->FindData("icon", B_ANY_TYPE, (const void**)&data, &numBytes)!=B_OK) { 239 fprintf(stderr, "can't find icon in message\n"); 240 return; 241 } 242 243 MethodMenuItem *item = FindItemByCookie(cookie); 244 if (item == NULL) { 245 fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); 246 return; 247 } 248 249 item->SetIcon(data); 250 } 251 252 253 void 254 MethodReplicant::UpdateMethodMenu(BMessage *message) 255 { 256 CALLED(); 257 int32 cookie; 258 if (message->FindInt32("cookie", &cookie)!=B_OK) { 259 fprintf(stderr, "can't find cookie in message\n"); 260 return; 261 } 262 263 BMessage msg; 264 if (message->FindMessage("menu", &msg)!=B_OK) { 265 fprintf(stderr, "can't find menu in message\n"); 266 return; 267 } 268 PRINT_OBJECT(msg); 269 270 BMessenger messenger; 271 if (message->FindMessenger("target", &messenger)!=B_OK) { 272 fprintf(stderr, "can't find target in message\n"); 273 return; 274 } 275 276 BMenu *menu = (BMenu *)BMenu::Instantiate(&msg); 277 if (menu == NULL) { 278 PRINT(("can't instantiate menu\n")); 279 } else 280 menu->SetTargetForItems(messenger); 281 282 MethodMenuItem *item = FindItemByCookie(cookie); 283 if (item == NULL) { 284 fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); 285 return; 286 } 287 int32 index = fMenu.IndexOf(item); 288 289 MethodMenuItem *item2 = NULL; 290 if (menu) 291 item2 = new MethodMenuItem(cookie, item->Label(), item->Icon(), 292 menu, messenger); 293 else 294 item2 = new MethodMenuItem(cookie, item->Label(), item->Icon()); 295 item = (MethodMenuItem*)fMenu.RemoveItem(index); 296 fMenu.AddItem(item2, index); 297 item2->SetMarked(item->IsMarked()); 298 delete item; 299 } 300 301 302 void 303 MethodReplicant::UpdateMethodName(BMessage *message) 304 { 305 CALLED(); 306 int32 cookie; 307 if (message->FindInt32("cookie", &cookie)!=B_OK) { 308 fprintf(stderr, "can't find cookie in message\n"); 309 return; 310 } 311 312 const char *name; 313 if (message->FindString("name", &name)!=B_OK) { 314 fprintf(stderr, "can't find name in message\n"); 315 return; 316 } 317 318 MethodMenuItem *item = FindItemByCookie(cookie); 319 if (item == NULL) { 320 fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); 321 return; 322 } 323 324 item->SetName(name); 325 } 326 327 328 MethodMenuItem * 329 MethodReplicant::FindItemByCookie(int32 cookie) 330 { 331 for (int32 i=0; i<fMenu.CountItems(); i++) { 332 MethodMenuItem *item = (MethodMenuItem *)fMenu.ItemAt(i); 333 PRINT(("cookie : 0x%lx\n", item->Cookie())); 334 if (item->Cookie()==cookie) 335 return item; 336 } 337 338 return NULL; 339 } 340 341 342 void 343 MethodReplicant::AddMethod(BMessage *message) 344 { 345 CALLED(); 346 int32 cookie; 347 if (message->FindInt32("cookie", &cookie)!=B_OK) { 348 fprintf(stderr, "can't find cookie in message\n"); 349 return; 350 } 351 352 const char *name; 353 if (message->FindString("name", &name)!=B_OK) { 354 fprintf(stderr, "can't find name in message\n"); 355 return; 356 } 357 358 const uchar *icon; 359 ssize_t numBytes; 360 if (message->FindData("icon", B_ANY_TYPE, (const void**)&icon, &numBytes)!=B_OK) { 361 fprintf(stderr, "can't find icon in message\n"); 362 return; 363 } 364 365 MethodMenuItem *item = FindItemByCookie(cookie); 366 if (item != NULL) { 367 fprintf(stderr, "item with cookie %lx already exists\n", cookie); 368 return; 369 } 370 371 item = new MethodMenuItem(cookie, name, icon); 372 fMenu.AddItem(item); 373 item->SetTarget(this); 374 375 if (fMenu.CountItems() == 1) 376 item->SetMarked(true); 377 } 378 379 380 void 381 MethodReplicant::RemoveMethod(BMessage *message) 382 { 383 CALLED(); 384 int32 cookie; 385 if (message->FindInt32("cookie", &cookie)!=B_OK) { 386 fprintf(stderr, "can't find cookie in message\n"); 387 return; 388 } 389 390 MethodMenuItem *item = FindItemByCookie(cookie); 391 if (item == NULL) { 392 fprintf(stderr, "can't find item with cookie %lx\n", cookie); 393 return; 394 } 395 fMenu.RemoveItem(item); 396 delete item; 397 } 398