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 MethodMenuItem *item = (MethodMenuItem*)fMenu.Go(where, true, true, BRect(where - BPoint(4, 4), 186 where + BPoint(4, 4))); 187 if (item) { 188 BMessage msg(IS_SET_METHOD); 189 msg.AddInt32("cookie", item->Cookie()); 190 BMessenger messenger(fSignature); 191 messenger.SendMessage(&msg); 192 } 193 } 194 195 196 void 197 MethodReplicant::MouseUp(BPoint point) 198 { 199 /* don't Quit() ! thanks for FFM users */ 200 } 201 202 203 void 204 MethodReplicant::UpdateMethod(BMessage *message) 205 { 206 CALLED(); 207 int32 cookie; 208 if (message->FindInt32("cookie", &cookie)!=B_OK) { 209 fprintf(stderr, "can't find cookie in message\n"); 210 return; 211 } 212 213 MethodMenuItem *item = FindItemByCookie(cookie); 214 if (item == NULL) { 215 fprintf(stderr, "can't find item with cookie %lx\n", cookie); 216 return; 217 } 218 item->SetMarked(true); 219 220 fSegments->SetBits(item->Icon(), kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace); 221 Invalidate(); 222 } 223 224 225 void 226 MethodReplicant::UpdateMethodIcon(BMessage *message) 227 { 228 CALLED(); 229 int32 cookie; 230 if (message->FindInt32("cookie", &cookie)!=B_OK) { 231 fprintf(stderr, "can't find cookie in message\n"); 232 return; 233 } 234 235 const uchar *data; 236 ssize_t numBytes; 237 if (message->FindData("icon", B_ANY_TYPE, (const void**)&data, &numBytes)!=B_OK) { 238 fprintf(stderr, "can't find icon in message\n"); 239 return; 240 } 241 242 MethodMenuItem *item = FindItemByCookie(cookie); 243 if (item == NULL) { 244 fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); 245 return; 246 } 247 248 item->SetIcon(data); 249 } 250 251 252 void 253 MethodReplicant::UpdateMethodMenu(BMessage *message) 254 { 255 CALLED(); 256 int32 cookie; 257 if (message->FindInt32("cookie", &cookie)!=B_OK) { 258 fprintf(stderr, "can't find cookie in message\n"); 259 return; 260 } 261 262 BMessage msg; 263 if (message->FindMessage("menu", &msg)!=B_OK) { 264 fprintf(stderr, "can't find menu in message\n"); 265 return; 266 } 267 PRINT_OBJECT(msg); 268 269 BMessenger messenger; 270 if (message->FindMessenger("target", &messenger)!=B_OK) { 271 fprintf(stderr, "can't find target in message\n"); 272 return; 273 } 274 275 BMenu *menu = (BMenu *)BMenu::Instantiate(&msg); 276 if (menu == NULL) { 277 PRINT(("can't instantiate menu\n")); 278 } else 279 menu->SetTargetForItems(messenger); 280 281 MethodMenuItem *item = FindItemByCookie(cookie); 282 if (item == NULL) { 283 fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); 284 return; 285 } 286 int32 index = fMenu.IndexOf(item); 287 288 MethodMenuItem *item2 = NULL; 289 if (menu) 290 item2 = new MethodMenuItem(cookie, item->Label(), item->Icon(), 291 menu, messenger); 292 else 293 item2 = new MethodMenuItem(cookie, item->Label(), item->Icon()); 294 item = (MethodMenuItem*)fMenu.RemoveItem(index); 295 fMenu.AddItem(item2, index); 296 item2->SetMarked(item->IsMarked()); 297 delete item; 298 } 299 300 301 void 302 MethodReplicant::UpdateMethodName(BMessage *message) 303 { 304 CALLED(); 305 int32 cookie; 306 if (message->FindInt32("cookie", &cookie)!=B_OK) { 307 fprintf(stderr, "can't find cookie in message\n"); 308 return; 309 } 310 311 const char *name; 312 if (message->FindString("name", &name)!=B_OK) { 313 fprintf(stderr, "can't find name in message\n"); 314 return; 315 } 316 317 MethodMenuItem *item = FindItemByCookie(cookie); 318 if (item == NULL) { 319 fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); 320 return; 321 } 322 323 item->SetName(name); 324 } 325 326 327 MethodMenuItem * 328 MethodReplicant::FindItemByCookie(int32 cookie) 329 { 330 for (int32 i=0; i<fMenu.CountItems(); i++) { 331 MethodMenuItem *item = (MethodMenuItem *)fMenu.ItemAt(i); 332 PRINT(("cookie : 0x%lx\n", item->Cookie())); 333 if (item->Cookie()==cookie) 334 return item; 335 } 336 337 return NULL; 338 } 339 340 341 void 342 MethodReplicant::AddMethod(BMessage *message) 343 { 344 CALLED(); 345 int32 cookie; 346 if (message->FindInt32("cookie", &cookie)!=B_OK) { 347 fprintf(stderr, "can't find cookie in message\n"); 348 return; 349 } 350 351 const char *name; 352 if (message->FindString("name", &name)!=B_OK) { 353 fprintf(stderr, "can't find name in message\n"); 354 return; 355 } 356 357 const uchar *icon; 358 ssize_t numBytes; 359 if (message->FindData("icon", B_ANY_TYPE, (const void**)&icon, &numBytes)!=B_OK) { 360 fprintf(stderr, "can't find icon in message\n"); 361 return; 362 } 363 364 MethodMenuItem *item = FindItemByCookie(cookie); 365 if (item != NULL) { 366 fprintf(stderr, "item with cookie %lx already exists\n", cookie); 367 return; 368 } 369 370 item = new MethodMenuItem(cookie, name, icon); 371 fMenu.AddItem(item); 372 item->SetTarget(this); 373 374 if (fMenu.CountItems() == 1) 375 item->SetMarked(true); 376 } 377 378 379 void 380 MethodReplicant::RemoveMethod(BMessage *message) 381 { 382 CALLED(); 383 int32 cookie; 384 if (message->FindInt32("cookie", &cookie)!=B_OK) { 385 fprintf(stderr, "can't find cookie in message\n"); 386 return; 387 } 388 389 MethodMenuItem *item = FindItemByCookie(cookie); 390 if (item == NULL) { 391 fprintf(stderr, "can't find item with cookie %lx\n", cookie); 392 return; 393 } 394 fMenu.RemoveItem(item); 395 delete item; 396 } 397