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