1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 /*! BShelf stores replicant views that are dropped onto it */ 11 12 13 #include <Beep.h> 14 #include <Dragger.h> 15 #include <Entry.h> 16 #include <File.h> 17 #include <Looper.h> 18 #include <Message.h> 19 #include <MessageFilter.h> 20 #include <Messenger.h> 21 #include <Point.h> 22 #include <Rect.h> 23 #include <Shelf.h> 24 #include <View.h> 25 26 #include <ZombieReplicantView.h> 27 28 #include <stdio.h> 29 #include <string.h> 30 31 32 extern "C" void _ReservedShelf1__6BShelfFv(BShelf *const, int32, 33 const BMessage*, const BView*); 34 35 36 class _rep_data_ { 37 private: 38 friend class BShelf; 39 40 _rep_data_(BMessage *message, BView *view, BDragger *dragger, 41 BDragger::relation relation, unsigned long id, image_id image); 42 _rep_data_(); 43 44 static _rep_data_* find(BList const *list, BMessage const *msg); 45 static _rep_data_* find(BList const *list, BView const *view, bool allowZombie); 46 static _rep_data_* find(BList const *list, unsigned long id); 47 48 static int32 index_of(BList const *list, BMessage const *msg); 49 static int32 index_of(BList const *list, BView const *view, bool allowZombie); 50 static int32 index_of(BList const *list, unsigned long id); 51 52 BMessage *fMessage; 53 BView *fView; 54 BDragger *fDragger; 55 BDragger::relation fRelation; 56 unsigned long fId; 57 image_id fImage; 58 status_t fError; 59 BView *fZombieView; 60 }; 61 62 63 class _TContainerViewFilter_ : public BMessageFilter { 64 public: 65 _TContainerViewFilter_(BShelf *shelf, BView *view); 66 virtual ~_TContainerViewFilter_(); 67 68 filter_result Filter(BMessage *msg, BHandler **handler); 69 filter_result ObjectDropFilter(BMessage *msg, BHandler **handler); 70 71 protected: 72 BShelf *fShelf; 73 BView *fView; 74 }; 75 76 77 // #pragma mark - 78 79 80 /*! \brief Helper function for BShelf::_AddReplicant() 81 */ 82 static status_t 83 send_reply(BMessage* message, status_t status, uint32 uniqueID) 84 { 85 if (message->IsSourceWaiting()) { 86 BMessage reply(B_REPLY); 87 reply.AddInt32("id", uniqueID); 88 reply.AddInt32("error", status); 89 message->SendReply(&reply); 90 } 91 92 return status; 93 } 94 95 96 // #pragma mark - 97 98 99 _rep_data_::_rep_data_(BMessage *message, BView *view, BDragger *dragger, 100 BDragger::relation relation, unsigned long id, image_id image) 101 : 102 fMessage(message), 103 fView(view), 104 fDragger(NULL), 105 fRelation(relation), 106 fId(id), 107 fImage(image), 108 fError(B_OK), 109 fZombieView(NULL) 110 { 111 } 112 113 114 _rep_data_::_rep_data_() 115 : 116 fMessage(NULL), 117 fView(NULL), 118 fDragger(NULL), 119 fRelation(BDragger::TARGET_UNKNOWN), 120 fId(0), 121 fImage(-1), 122 fError(B_ERROR), 123 fZombieView(NULL) 124 { 125 } 126 127 128 //static 129 _rep_data_ * 130 _rep_data_::find(BList const *list, BMessage const *msg) 131 { 132 int32 i = 0; 133 _rep_data_ *item; 134 while ((item = (_rep_data_*)list->ItemAt(i++)) != NULL) { 135 if (item->fMessage == msg) 136 return item; 137 } 138 139 return NULL; 140 } 141 142 143 //static 144 _rep_data_ * 145 _rep_data_::find(BList const *list, BView const *view, bool allowZombie) 146 { 147 int32 i = 0; 148 _rep_data_ *item; 149 while ((item = (_rep_data_*)list->ItemAt(i++)) != NULL) { 150 if (item->fView == view) 151 return item; 152 153 if (allowZombie && item->fZombieView == view) 154 return item; 155 } 156 157 return NULL; 158 } 159 160 161 //static 162 _rep_data_ * 163 _rep_data_::find(BList const *list, unsigned long id) 164 { 165 int32 i = 0; 166 _rep_data_ *item; 167 while ((item = (_rep_data_*)list->ItemAt(i++)) != NULL) { 168 if (item->fId == id) 169 return item; 170 } 171 172 return NULL; 173 } 174 175 176 //static 177 int32 178 _rep_data_::index_of(BList const *list, BMessage const *msg) 179 { 180 int32 i = 0; 181 _rep_data_ *item; 182 while ((item = (_rep_data_*)list->ItemAt(i)) != NULL) { 183 if (item->fMessage == msg) 184 return i; 185 i++; 186 } 187 188 return -1; 189 } 190 191 192 //static 193 int32 194 _rep_data_::index_of(BList const *list, BView const *view, bool allowZombie) 195 { 196 int32 i = 0; 197 _rep_data_ *item; 198 while ((item = (_rep_data_*)list->ItemAt(i)) != NULL) { 199 if (item->fView == view) 200 return i; 201 202 if (allowZombie && item->fZombieView == view) 203 return i; 204 i++; 205 } 206 207 return -1; 208 } 209 210 211 //static 212 int32 213 _rep_data_::index_of(BList const *list, unsigned long id) 214 { 215 int32 i = 0; 216 _rep_data_ *item; 217 while ((item = (_rep_data_*)list->ItemAt(i)) != NULL) { 218 if (item->fId == id) 219 return i; 220 i++; 221 } 222 223 return -1; 224 } 225 226 227 // #pragma mark - 228 229 230 _TContainerViewFilter_::_TContainerViewFilter_(BShelf *shelf, BView *view) 231 : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) 232 { 233 fShelf = shelf; 234 fView = view; 235 } 236 237 238 _TContainerViewFilter_::~_TContainerViewFilter_() 239 { 240 } 241 242 243 filter_result 244 _TContainerViewFilter_::Filter(BMessage *msg, BHandler **handler) 245 { 246 filter_result filter = B_DISPATCH_MESSAGE; 247 248 if (msg->what == B_ARCHIVED_OBJECT || 249 msg->what == B_ABOUT_REQUESTED) 250 return ObjectDropFilter(msg, handler); 251 252 return filter; 253 } 254 255 256 filter_result 257 _TContainerViewFilter_::ObjectDropFilter(BMessage *msg, BHandler **_handler) 258 { 259 BView *mouseView; 260 261 if (*_handler) 262 mouseView = dynamic_cast<BView*>(*_handler); 263 else 264 mouseView = NULL; 265 266 if (msg->WasDropped()) { 267 if (!fShelf->fAllowDragging) { 268 printf("Dragging replicants isn't allowed to this shelf."); 269 beep(); 270 return B_SKIP_MESSAGE; 271 } 272 } 273 274 BPoint point; 275 BPoint offset; 276 277 if (msg->WasDropped()) { 278 point = msg->DropPoint(&offset); 279 280 point = mouseView->ConvertFromScreen(point - offset); 281 } 282 283 BLooper *looper; 284 BHandler *handler = msg->ReturnAddress().Target(&looper); 285 286 BDragger *dragger; 287 288 if (Looper() == looper) { 289 if (handler) 290 dragger = dynamic_cast<BDragger*>(handler); 291 else 292 dragger = NULL; 293 294 if (dragger->fRelation == BDragger::TARGET_IS_CHILD) { 295 BRect rect = dragger->Frame(); 296 rect.OffsetTo(point); 297 point = fShelf->AdjustReplicantBy(rect, msg); 298 299 } else { 300 BRect rect = dragger->fTarget->Frame(); 301 rect.OffsetTo(point); 302 point = fShelf->AdjustReplicantBy(rect, msg); 303 } 304 305 if (dragger->fRelation == BDragger::TARGET_IS_PARENT) 306 dragger->fTarget->MoveTo(point); 307 else if (dragger->fRelation == BDragger::TARGET_IS_CHILD) 308 dragger->MoveTo(point); 309 else { 310 //TODO: TARGET_UNKNOWN/TARGET_SIBLING 311 } 312 313 } else { 314 if (fShelf->_AddReplicant(msg, &point, 0) == B_OK) 315 Looper()->DetachCurrentMessage(); 316 } 317 318 return B_SKIP_MESSAGE; 319 } 320 321 322 // #pragma mark - 323 324 325 class _TReplicantViewFilter_ : public BMessageFilter { 326 public: 327 _TReplicantViewFilter_(BShelf *shelf, BView *view) 328 : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) 329 { 330 fShelf = shelf; 331 fView = view; 332 } 333 334 virtual ~_TReplicantViewFilter_() 335 { 336 } 337 338 filter_result Filter(BMessage *, BHandler **) 339 { 340 return B_DISPATCH_MESSAGE; 341 } 342 343 protected: 344 BShelf *fShelf; 345 BView *fView; 346 }; 347 348 349 // #pragma mark - 350 351 352 BShelf::BShelf(BView *view, bool allowDrags, const char *shelfType) 353 : BHandler(shelfType) 354 { 355 _InitData(NULL, NULL, view, allowDrags); 356 } 357 358 359 BShelf::BShelf(const entry_ref *ref, BView *view, bool allowDrags, 360 const char *shelfType) 361 : BHandler(shelfType) 362 { 363 _InitData(new BEntry(ref), NULL, view, allowDrags); 364 } 365 366 367 BShelf::BShelf(BDataIO *stream, BView *view, bool allowDrags, 368 const char *shelfType) 369 : BHandler(shelfType) 370 { 371 _InitData(NULL, stream, view, allowDrags); 372 } 373 374 375 BShelf::BShelf(BMessage *data) 376 : BHandler(data) 377 { 378 // TODO: Implement ? 379 } 380 381 382 BShelf::~BShelf() 383 { 384 Save(); 385 386 delete fEntry; 387 } 388 389 390 status_t 391 BShelf::Archive(BMessage *data, bool deep) const 392 { 393 return B_ERROR; 394 } 395 396 397 BArchivable * 398 BShelf::Instantiate(BMessage *data) 399 { 400 return NULL; 401 } 402 403 404 void 405 BShelf::MessageReceived(BMessage *msg) 406 { 407 //TODO: Implement 408 } 409 410 411 status_t 412 BShelf::Save() 413 { 414 status_t status = B_ERROR; 415 if (fEntry != NULL) { 416 BFile *file = new BFile(fEntry, B_READ_WRITE); 417 status = file->InitCheck(); 418 if (status < B_OK) { 419 delete file; 420 return status; 421 } 422 fStream = file; 423 } 424 425 if (fStream != NULL) { 426 BMessage message; 427 status = _Archive(&message); 428 if (status == B_OK) 429 status = message.Flatten(fStream); 430 } 431 432 return status; 433 } 434 435 436 void 437 BShelf::SetDirty(bool state) 438 { 439 fDirty = state; 440 } 441 442 443 bool 444 BShelf::IsDirty() const 445 { 446 return fDirty; 447 } 448 449 450 BHandler * 451 BShelf::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, 452 int32 form, const char *property) 453 { 454 //TODO 455 return NULL; 456 } 457 458 459 status_t 460 BShelf::GetSupportedSuites(BMessage *data) 461 { 462 //TODO 463 return B_ERROR; 464 } 465 466 467 status_t 468 BShelf::Perform(perform_code d, void *arg) 469 { 470 return BHandler::Perform(d, arg); 471 } 472 473 474 bool 475 BShelf::AllowsDragging() const 476 { 477 return fAllowDragging; 478 } 479 480 481 void 482 BShelf::SetAllowsDragging(bool state) 483 { 484 fAllowDragging = state; 485 } 486 487 488 bool 489 BShelf::AllowsZombies() const 490 { 491 return fAllowZombies; 492 } 493 494 495 void 496 BShelf::SetAllowsZombies(bool state) 497 { 498 fAllowZombies = state; 499 } 500 501 502 bool 503 BShelf::DisplaysZombies() const 504 { 505 return fDisplayZombies; 506 } 507 508 509 void 510 BShelf::SetDisplaysZombies(bool state) 511 { 512 fDisplayZombies = state; 513 } 514 515 516 bool 517 BShelf::IsTypeEnforced() const 518 { 519 return fTypeEnforced; 520 } 521 522 523 void 524 BShelf::SetTypeEnforced(bool state) 525 { 526 fTypeEnforced = state; 527 } 528 529 530 status_t 531 BShelf::SetSaveLocation(BDataIO *data_io) 532 { 533 fDirty = true; 534 535 if (fEntry) { 536 delete fEntry; 537 fEntry = NULL; 538 } 539 540 fStream = data_io; 541 542 return B_OK; 543 } 544 545 546 status_t 547 BShelf::SetSaveLocation(const entry_ref *ref) 548 { 549 fDirty = true; 550 551 if (fEntry) 552 delete fEntry; 553 else 554 fStream = NULL; 555 556 fEntry = new BEntry(ref); 557 558 return B_OK; 559 } 560 561 562 BDataIO * 563 BShelf::SaveLocation(entry_ref *ref) const 564 { 565 entry_ref entry; 566 567 if (fStream && ref) { 568 *ref = entry; 569 return fStream; 570 } 571 if (fEntry) { 572 fEntry->GetRef(&entry); 573 574 if (ref) 575 *ref = entry; 576 577 return NULL; 578 } 579 580 *ref = entry; 581 return NULL; 582 } 583 584 585 status_t 586 BShelf::AddReplicant(BMessage *data, BPoint location) 587 { 588 return _AddReplicant(data, &location, 0); 589 } 590 591 592 status_t 593 BShelf::DeleteReplicant(BView *replicant) 594 { 595 int32 index = _rep_data_::index_of(&fReplicants, replicant, true); 596 597 _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); 598 if (item == NULL) 599 return B_BAD_VALUE; 600 601 return _DeleteReplicant(item); 602 } 603 604 605 status_t 606 BShelf::DeleteReplicant(BMessage *data) 607 { 608 int32 index = _rep_data_::index_of(&fReplicants, data); 609 610 _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); 611 if (!item) 612 return B_BAD_VALUE; 613 614 return _DeleteReplicant(item); 615 } 616 617 618 status_t 619 BShelf::DeleteReplicant(int32 index) 620 { 621 _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); 622 if (!item) 623 return B_BAD_INDEX; 624 625 return _DeleteReplicant(item); 626 } 627 628 629 int32 630 BShelf::CountReplicants() const 631 { 632 return fReplicants.CountItems(); 633 } 634 635 636 BMessage * 637 BShelf::ReplicantAt(int32 index, BView **_view, uint32 *_uniqueID, 638 status_t *_error) const 639 { 640 _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); 641 if (item == NULL) { 642 // no replicant found 643 if (_view) 644 *_view = NULL; 645 if (_uniqueID) 646 *_uniqueID = ~0UL; 647 if (_error) 648 *_error = B_BAD_INDEX; 649 650 return NULL; 651 } 652 653 if (_view) 654 *_view = item->fView; 655 if (_uniqueID) 656 *_uniqueID = item->fId; 657 if (_error) 658 *_error = item->fError; 659 660 return item->fMessage; 661 } 662 663 664 int32 665 BShelf::IndexOf(const BView *replicant_view) const 666 { 667 return _rep_data_::index_of(&fReplicants, replicant_view, false); 668 } 669 670 671 int32 672 BShelf::IndexOf(const BMessage *archive) const 673 { 674 return _rep_data_::index_of(&fReplicants, archive); 675 } 676 677 678 int32 679 BShelf::IndexOf(uint32 id) const 680 { 681 return _rep_data_::index_of(&fReplicants, id); 682 } 683 684 685 bool 686 BShelf::CanAcceptReplicantMessage(BMessage*) const 687 { 688 return true; 689 } 690 691 692 bool 693 BShelf::CanAcceptReplicantView(BRect, BView*, BMessage*) const 694 { 695 return true; 696 } 697 698 699 BPoint 700 BShelf::AdjustReplicantBy(BRect, BMessage*) const 701 { 702 return B_ORIGIN; 703 } 704 705 706 void 707 BShelf::ReplicantDeleted(int32 index, const BMessage *archive, 708 const BView *replicant) 709 { 710 } 711 712 713 void 714 _ReservedShelf1__6BShelfFv(BShelf *const, int32, const BMessage*, 715 const BView*) 716 { 717 } 718 719 720 void BShelf::_ReservedShelf2() {} 721 void BShelf::_ReservedShelf3() {} 722 void BShelf::_ReservedShelf4() {} 723 void BShelf::_ReservedShelf5() {} 724 void BShelf::_ReservedShelf6() {} 725 void BShelf::_ReservedShelf7() {} 726 void BShelf::_ReservedShelf8() {} 727 728 729 BShelf::BShelf(const BShelf&) 730 { 731 } 732 733 734 BShelf & 735 BShelf::operator=(const BShelf &) 736 { 737 return *this; 738 } 739 740 741 status_t 742 BShelf::_Archive(BMessage *data) const 743 { 744 BHandler::Archive(data); 745 746 data->AddBool("_zom_dsp", DisplaysZombies()); 747 data->AddBool("_zom_alw", AllowsZombies()); 748 data->AddInt32("_sg_cnt", fGenCount); 749 750 BMessage archive('ARCV'); 751 752 // TODO archive replicants 753 754 return B_ERROR; 755 } 756 757 758 void 759 BShelf::_InitData(BEntry *entry, BDataIO *stream, BView *view, 760 bool allowDrags) 761 { 762 fContainerView = view; 763 fStream = NULL; 764 fEntry = entry; 765 fFilter = NULL; 766 fGenCount = 1; 767 fAllowDragging = allowDrags; 768 fDirty = true; 769 fDisplayZombies = false; 770 fAllowZombies = true; 771 fTypeEnforced = false; 772 773 if (entry) 774 fStream = new BFile(entry, B_READ_ONLY); 775 else 776 fStream = stream; 777 778 fFilter = new _TContainerViewFilter_(this, fContainerView); 779 780 fContainerView->AddFilter(fFilter); 781 fContainerView->_SetShelf(this); 782 783 if (fStream) { 784 BMessage archive; 785 786 if (archive.Unflatten(fStream) == B_OK) { 787 bool allowZombies; 788 if (archive.FindBool("_zom_dsp", &allowZombies) != B_OK) 789 allowZombies = false; 790 791 SetDisplaysZombies(allowZombies); 792 793 if (archive.FindBool("_zom_alw", &allowZombies) != B_OK) 794 allowZombies = true; 795 796 SetAllowsZombies(allowZombies); 797 798 int32 genCount; 799 if (!archive.FindInt32("_sg_cnt", &genCount)) 800 genCount = 1; 801 802 // TODO find archived replicants 803 } 804 } 805 } 806 807 808 status_t 809 BShelf::_DeleteReplicant(_rep_data_* item) 810 { 811 bool loadedImage = item->fMessage->FindBool(""); 812 813 BView *view = item->fView; 814 if (view == NULL) 815 view = item->fZombieView; 816 817 if (view) 818 view->RemoveSelf(); 819 820 if (item->fDragger) 821 item->fDragger->RemoveSelf(); 822 823 int32 index = _rep_data_::index_of(&fReplicants, item->fMessage); 824 825 // TODO: Test if it's ok here 826 ReplicantDeleted(index, item->fMessage, view); 827 828 fReplicants.RemoveItem(item); 829 830 if (loadedImage && item->fImage >= 0) 831 unload_add_on(item->fImage); 832 833 delete item; 834 835 return B_OK; 836 } 837 838 839 status_t 840 BShelf::_AddReplicant(BMessage *data, BPoint *location, uint32 uniqueID) 841 { 842 // Check shelf types if needed 843 if (fTypeEnforced) { 844 const char *shelfType = NULL; 845 if (data->FindString("shelf_type", &shelfType) == B_OK && shelfType != NULL) { 846 if (Name() && strcmp(shelfType, Name()) != 0) { 847 printf("Replicant was rejected by BShelf: The BShelf's type and the Replicant's type don't match."); 848 return send_reply(data, B_ERROR, uniqueID); 849 } else { 850 printf("Replicant was rejected by BShelf: Replicant indicated a <type> (%s), but the shelf does not.", shelfType); 851 return send_reply(data, B_ERROR, uniqueID); 852 } 853 } else { 854 printf("Replicant was rejected by BShelf: Replicant did not have a <type>"); 855 return send_reply(data, B_ERROR, uniqueID); 856 } 857 } 858 859 // Check if we can accept this message 860 if (!CanAcceptReplicantMessage(data)) { 861 printf("Replicant was rejected by BShelf: CanAcceptReplicant() returned false"); 862 return send_reply(data, B_ERROR, uniqueID); 863 } 864 865 // Check if we can create multiple instances 866 if (data->FindBool("be:load_each_time")) { 867 const char *_class = NULL; 868 const char *add_on = NULL; 869 870 if (data->FindString("class", &_class) == B_OK 871 && data->FindString("add_on", &add_on) == B_OK) { 872 int32 i = 0; 873 _rep_data_ *item; 874 const char *rep_class = NULL; 875 const char *rep_add_on = NULL; 876 877 while ((item = (_rep_data_*)fReplicants.ItemAt(i++)) != NULL) { 878 if (item->fMessage->FindString("class", &rep_class) == B_OK 879 && item->fMessage->FindString("add_on", &rep_add_on) == B_OK 880 && !strcmp(_class, rep_class) && add_on && rep_add_on 881 && !strcmp(add_on, rep_add_on)) { 882 printf("Replicant was rejected. Unique replicant already exists. class=%s, signature=%s", 883 rep_class, rep_add_on); 884 return send_reply(data, B_ERROR, uniqueID); 885 } 886 } 887 } 888 } 889 890 BDragger* dragger = NULL; 891 BView* replicant = NULL; 892 BDragger::relation relation = BDragger::TARGET_UNKNOWN; 893 _BZombieReplicantView_* zombie = NULL; 894 895 // Instantiate the object, if this fails we have a zombie 896 image_id image; 897 BArchivable *archivable = instantiate_object(data, &image); 898 if (archivable) { 899 BView *view = dynamic_cast<BView*>(archivable); 900 BPoint point; 901 902 if (location) 903 point = *location; 904 else 905 point = view->Frame().LeftTop(); 906 907 // TODO: test me -- there seems to be lots of bugs parked here! 908 909 // Check if we have a dragger archived as "__widget" inside the message 910 BMessage widget; 911 if (data->FindMessage("__widget", &widget) == B_OK) { 912 image_id draggerImage = B_ERROR; 913 replicant = view; 914 dragger = dynamic_cast<BDragger*>(instantiate_object(&widget, &draggerImage)); 915 if (dragger != NULL) { 916 // Replicant is either a sibling or unknown 917 dragger->SetViewToDrag(replicant); 918 relation = BDragger::TARGET_IS_SIBLING; 919 } 920 921 } else { 922 // Replicant is child of the dragger 923 if ((dragger = dynamic_cast<BDragger*>(view)) != NULL) { 924 replicant = dragger->ChildAt(0); 925 dragger->SetViewToDrag(replicant); 926 relation = BDragger::TARGET_IS_CHILD; 927 } else { 928 // Replicant is parent of the dragger 929 replicant = view; 930 dragger = dynamic_cast<BDragger*>(replicant->FindView("_dragger_")); 931 932 if (dragger) 933 dragger->SetViewToDrag(replicant); 934 935 relation = BDragger::TARGET_IS_PARENT; 936 } 937 } 938 939 if (dragger != NULL) 940 dragger->SetShelf(this); 941 942 BRect frame; 943 if (relation != BDragger::TARGET_IS_CHILD) { 944 frame = replicant->Frame().OffsetToCopy(point); 945 fContainerView->AddChild(replicant); 946 } else 947 frame = dragger->Frame().OffsetToCopy(point); 948 949 BPoint adjust = AdjustReplicantBy(frame, data); 950 951 // TODO: that's probably not correct for all relations (or any?) 952 view->MoveTo(point + adjust); 953 954 // if it's a sibling or a child, we need to add the dragger 955 if (relation == BDragger::TARGET_IS_SIBLING || relation == BDragger::TARGET_IS_CHILD) 956 fContainerView->AddChild(dragger); 957 958 AddFilter(new _TReplicantViewFilter_(this, replicant)); 959 960 } else if (fDisplayZombies && fAllowZombies) { 961 // TODO: the zombies must be adjusted and moved as well! 962 BRect frame; 963 if (data->FindRect("_frame", &frame) != B_OK) 964 frame = BRect(); 965 966 if (data->WasDropped()) { 967 BPoint dropPoint, offset; 968 dropPoint = data->DropPoint(&offset); 969 970 frame.OffsetTo(B_ORIGIN); 971 frame.OffsetTo(fContainerView->ConvertFromScreen(dropPoint) - offset); 972 973 zombie = new _BZombieReplicantView_(frame, B_ERROR); 974 975 frame.OffsetTo(B_ORIGIN); 976 977 dragger = new BDragger(frame, zombie); 978 dragger->SetShelf(this); 979 dragger->SetZombied(true); 980 981 zombie->AddChild(dragger); 982 zombie->SetArchive(data); 983 984 AddFilter(new _TReplicantViewFilter_(this, zombie)); 985 986 fContainerView->AddChild(zombie); 987 } 988 } 989 990 data->RemoveName("_drop_point_"); 991 data->RemoveName("_drop_offset_"); 992 993 _rep_data_ *item = new _rep_data_(data, replicant, dragger, relation, 994 uniqueID, image); 995 996 item->fError = B_OK; 997 item->fZombieView = zombie; 998 999 fReplicants.AddItem(item); 1000 1001 return send_reply(data, B_OK, uniqueID); 1002 } 1003 1004 1005 status_t 1006 BShelf::_GetProperty(BMessage *msg, BMessage *reply) 1007 { 1008 //TODO: Implement 1009 return B_ERROR; 1010 } 1011