xref: /haiku/src/apps/deskbar/BarView.cpp (revision 0e50eab75e25d0d82090e22dbff766dfaa6f5e86)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <AppFileInfo.h>
40 #include <Bitmap.h>
41 #include <Debug.h>
42 #include <Directory.h>
43 #include <NodeInfo.h>
44 #include <Roster.h>
45 #include <Screen.h>
46 #include <String.h>
47 
48 #include "icons.h"
49 #include "BarApp.h"
50 #include "BarView.h"
51 #include "BarMenuBar.h"
52 #include "BarWindow.h"
53 #include "BeMenu.h"
54 #include "DeskBarUtils.h"
55 #include "ExpandoMenuBar.h"
56 #include "FSUtils.h"
57 #include "ResourceSet.h"
58 #include "StatusView.h"
59 #include "TeamMenuItem.h"
60 
61 
62 extern menu_info *_menu_info_ptr_;
63 
64 const int32 kDefaultRecentDocCount = 10;
65 const int32 kDefaultRecentFolderCount = 10;
66 const int32 kDefaultRecentAppCount = 10;
67 
68 const int32 kMenuTrackMargin = 20;
69 
70 
71 TBarView::TBarView(BRect frame, bool vertical, bool left, bool top,
72 		bool showInterval, uint32 state, float, bool showTime)
73 	: BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
74 	fBarMenuBar(NULL),
75 	fExpando(NULL),
76 	fTrayLocation(1),
77 	fShowInterval(showInterval),
78 	fShowClock(showTime),
79 	fVertical(vertical),
80 	fTop(top),
81 	fLeft(left),
82 	fState(static_cast<int32>(state)),
83 	fRefsRcvdOnly(true),
84 	fDragMessage(NULL),
85 	fCachedTypesList(NULL),
86 	fMaxRecentDocs(kDefaultRecentDocCount),
87 	fMaxRecentApps(kDefaultRecentAppCount),
88 	fLastDragItem(NULL),
89 	fClickToOpen(_menu_info_ptr_->click_to_open)
90 		// init click to open to current local setting
91 {
92 }
93 
94 
95 TBarView::~TBarView()
96 {
97 	delete fDragMessage;
98 	delete fCachedTypesList;
99 
100 	// !! this should be done in DetachedFromWindow
101 	// to be symetric
102 	delete fTrackingHookData.fDragMessage;
103 }
104 
105 
106 void
107 TBarView::AttachedToWindow()
108 {
109 	BView::AttachedToWindow();
110 
111 	SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
112 	SetFont(be_plain_font);
113 
114 	fReplicantTray = new TReplicantTray(this, fVertical);
115 	fDragRegion = new TDragRegion(this, fReplicantTray);
116 	fDragRegion->AddChild(fReplicantTray);
117 	if (fTrayLocation != 0)
118 		AddChild(fDragRegion);
119 
120 	UpdatePlacement();
121 
122 	fTrackingHookData.fTrackingHook = MenuTrackingHook;
123 	fTrackingHookData.fTarget = BMessenger(this);
124 	fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED);
125 }
126 
127 
128 void
129 TBarView::Draw(BRect)
130 {
131 	BRect bounds(Bounds());
132 
133 	rgb_color hilite = tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT);
134 	rgb_color light = tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_LIGHTEN_2_TINT);
135 
136 	SetHighColor(hilite);
137 	if (AcrossTop())
138 		StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
139 	else if (AcrossBottom())
140 		StrokeLine(bounds.LeftTop(), bounds.RightTop());
141 
142 	if (Vertical() && Expando()) {
143 		SetHighColor(hilite);
144 		BRect frame(fExpando->Frame());
145 		StrokeLine(frame.LeftTop() + BPoint(0, -1), frame.RightTop() + BPoint(0, -1));
146 	}
147 }
148 
149 
150 void
151 TBarView::MessageReceived(BMessage *message)
152 {
153 	switch (message->what) {
154 		case B_REFS_RECEIVED:
155 			// received when an item is selected during DnD
156 			// message is targeted here from Be menu
157 			HandleBeMenu(message);
158 			break;
159 
160 		case B_ARCHIVED_OBJECT:
161 		{
162 			// this message has been retargeted to here
163 			// instead of directly to the replicant tray
164 			// so that I can follow the common pathway
165 			// for adding icons to the tray
166 			int32 id;
167 			AddItem(new BMessage(*message), B_DESKBAR_TRAY, &id);
168 			break;
169 		}
170 
171 		default:
172 			BView::MessageReceived(message);
173 	}
174 }
175 
176 
177 void
178 TBarView::PlaceBeMenu()
179 {
180 	// top or bottom, full
181 	if (!fVertical && fBarMenuBar) {
182 		fBarMenuBar->RemoveSelf();
183 		delete fBarMenuBar;
184 		fBarMenuBar = NULL;
185 	}
186 
187 	//	top or bottom expando mode has Be menu built in for tracking
188 	//	only for vertical mini or expanded
189 	//	mini mode will have team menu added as part of BarMenuBar
190 	if (fVertical && !fBarMenuBar) {
191 		//	create the Be menu
192 		BRect mbarFrame(Bounds());
193 		mbarFrame.bottom = mbarFrame.top + kMenuBarHeight;
194 		fBarMenuBar = new TBarMenuBar(this, mbarFrame, "BarMenuBar");
195 		AddChild(fBarMenuBar);
196 	}
197 
198 	//	if there isn't a bemenu at this point,
199 	//	DB should be in top/bottom mode, else error
200 	if (!fBarMenuBar)
201 		return;
202 
203 	float width = kMinimumWindowWidth;
204 	BPoint loc(B_ORIGIN);
205 	BRect menuFrame(fBarMenuBar->Frame());
206 	if (fState == kFullState) {
207 		fBarMenuBar->RemoveTeamMenu();
208 		width = 8 + 16 + 8;
209 		loc = Bounds().LeftTop();
210 	} else if (fState == kExpandoState) {
211 		// shows apps below tray
212 		fBarMenuBar->RemoveTeamMenu();
213 		if (fVertical)
214 			width += 1;
215 		else
216 			width = floorf(width) / 2;
217 		loc = Bounds().LeftTop();
218 	} else
219 		// mini mode, BeMenu next to team menu
220 		fBarMenuBar->AddTeamMenu();
221 
222 	fBarMenuBar->SmartResize(width, menuFrame.Height());
223 	fBarMenuBar->MoveTo(loc);
224 }
225 
226 
227 void
228 TBarView::PlaceTray(bool, bool, BRect screenFrame)
229 {
230 	BPoint statusLoc;
231 	if (fState == kFullState) {
232 		fDragRegion->ResizeTo(fBarMenuBar->Frame().Width(), kMenuBarHeight);
233 		statusLoc.y = fBarMenuBar->Frame().bottom + 1;
234 		statusLoc.x = 0;
235 		fDragRegion->MoveTo(statusLoc);
236 
237 		if (!fReplicantTray->IsHidden())
238 			fReplicantTray->Hide();
239 
240 		return;
241 	}
242 
243 	if (fReplicantTray->IsHidden())
244 		fReplicantTray->Show();
245 
246 	if (fTrayLocation != 0) {
247 		fReplicantTray->SetMultiRow(fVertical);
248 		fReplicantTray->RealignReplicants();
249 		fDragRegion->ResizeToPreferred();
250 
251 		if (fVertical) {
252 			statusLoc.y = fBarMenuBar->Frame().bottom + 1;
253 			statusLoc.x = 0;
254 			if (Left() && Vertical())
255 				fReplicantTray->MoveTo(5, 2);
256 			else
257 				fReplicantTray->MoveTo(2, 2);
258 		} else {
259 			statusLoc.x = screenFrame.Width() - fDragRegion->Bounds().Width();
260 			statusLoc.y = -1;
261 		}
262 
263 		fDragRegion->MoveTo(statusLoc);
264 	}
265 }
266 
267 
268 void
269 TBarView::PlaceApplicationBar(BRect screenFrame)
270 {
271 	if (fExpando != NULL) {
272 		fExpando->RemoveSelf();
273 		delete fExpando;
274 		fExpando = NULL;
275 	}
276 	if (fState == kMiniState)
277 		return;
278 
279 	BRect expandoFrame(0, 0, 0, 0);
280 	if (fVertical) {
281 		// top left/right
282 		if (fTrayLocation != 0)
283 			expandoFrame.top = fDragRegion->Frame().bottom + 2;
284 		else
285 			expandoFrame.top = fBarMenuBar->Frame().bottom + 2;
286 
287 		expandoFrame.bottom = expandoFrame.top + 1;
288 		if (fState == kFullState)
289 			expandoFrame.right = fBarMenuBar->Frame().Width();
290 		else
291 			expandoFrame.right = kMinimumWindowWidth;
292 	} else {
293 		// top or bottom
294 		expandoFrame.top = -1;
295 		expandoFrame.bottom = kHModeHeight;
296 		if (fTrayLocation != 0)
297 			expandoFrame.right = fDragRegion->Frame().left;
298 		else
299 			expandoFrame.right = screenFrame.Width();
300 	}
301 
302 	fExpando = new TExpandoMenuBar(this, expandoFrame, "ExpandoMenuBar",
303 		fVertical, fState != kFullState);
304 	AddChild(fExpando);
305 }
306 
307 
308 void
309 TBarView::GetPreferredWindowSize(BRect screenFrame, float *width, float *height)
310 {
311 	float windowHeight = 0;
312 	float windowWidth = kMinimumWindowWidth;
313 	if (fState == kFullState) {
314 		windowHeight = screenFrame.bottom;
315 		windowWidth = fBarMenuBar->Frame().Width();
316 	} else if (fState == kExpandoState) {
317 		if (fVertical) {
318 			// top left or right
319 			windowHeight = fExpando->Frame().bottom - 1;
320 		} else {
321 			// top or bottom, full
322 			fExpando->CheckItemSizes(0);
323 			windowHeight = kHModeHeight;
324 			windowWidth = screenFrame.Width();
325 		}
326 	} else {
327 		// four corners
328 		if (fTrayLocation != 0)
329 			windowHeight = fDragRegion->Frame().bottom;
330 		else
331 			windowHeight = fBarMenuBar->Frame().bottom;
332 	}
333 
334 	*width = windowWidth;
335 	*height = windowHeight;
336 }
337 
338 
339 void
340 TBarView::SizeWindow(BRect screenFrame)
341 {
342 	float windowWidth, windowHeight;
343 	GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
344 	Window()->ResizeTo(windowWidth, windowHeight);
345 	if (fExpando)
346 		fExpando->CheckForSizeOverrun();
347 }
348 
349 
350 void
351 TBarView::PositionWindow(BRect screenFrame)
352 {
353 	float windowWidth, windowHeight;
354 	GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
355 
356 	BPoint moveLoc(0, 0);
357 	// right, expanded
358 	if (!fLeft && fVertical) {
359 		if (fState == kFullState)
360 			moveLoc.x = screenFrame.right - fBarMenuBar->Frame().Width();
361 		else
362 			moveLoc.x = screenFrame.right - kMinimumWindowWidth;
363 	}
364 
365 	// bottom, full or corners
366 	if (!fTop)
367 		moveLoc.y = screenFrame.bottom - windowHeight;
368 
369 	Window()->MoveTo(moveLoc);
370 }
371 
372 
373 void
374 TBarView::SaveSettings()
375 {
376 	desk_settings *settings = ((TBarApp *)be_app)->Settings();
377 
378 	settings->vertical = Vertical();
379 	settings->left = Left();
380 	settings->top = Top();
381 	settings->ampmMode = MilTime();
382 	settings->state = (uint32)State();
383 	settings->width = 0;
384 	settings->showTime = ShowingClock();
385 
386 	fReplicantTray->RememberClockSettings();
387 	settings->alwaysOnTop = (Window()->Feel() & B_FLOATING_ALL_WINDOW_FEEL) != 0;
388 }
389 
390 
391 void
392 TBarView::UpdatePlacement()
393 {
394 	ChangeState(fState, fVertical, fLeft, fTop);
395 }
396 
397 
398 void
399 TBarView::ChangeState(int32 state, bool vertical, bool left, bool top)
400 {
401 	bool vertSwap = (fVertical != vertical);
402 	bool leftSwap = (fLeft != left);
403 
404 	fState = state;
405 	fVertical = vertical;
406 	fLeft = left;
407 	fTop = top;
408 
409 	BRect screenFrame = (BScreen(Window())).Frame();
410 
411 	PlaceBeMenu();
412 	PlaceTray(vertSwap, leftSwap, screenFrame);
413 
414 	// We need to keep track of what apps are expanded.
415 	BList expandedItems;
416 	BString *signature = NULL;
417 	if (fVertical && Expando() && static_cast<TBarApp *>(be_app)->Settings()->superExpando) {
418 		// Get a list of the Signatures of expanded apps - Can't use team_id because
419 		// there can be more than one team per application
420 		if (fVertical && Expando() && vertical && fExpando) {
421 			for (int index = 0; index < fExpando->CountItems(); index++) {
422 				TTeamMenuItem *item = dynamic_cast<TTeamMenuItem *>(fExpando->ItemAt(index));
423 				if (item != NULL && item->IsExpanded()) {
424 					signature = new BString(item->Signature());
425 					expandedItems.AddItem((void *)signature);
426 				}
427 			}
428 		}
429 	}
430 
431  	PlaceApplicationBar(screenFrame);
432  	SizeWindow(screenFrame);
433  	PositionWindow(screenFrame);
434  	Window()->UpdateIfNeeded();
435 
436 	// Re-expand those apps.
437 	if (expandedItems.CountItems() > 0) {
438 		for (int sigIndex = expandedItems.CountItems(); sigIndex-- > 0;) {
439 			signature = static_cast<BString *>(expandedItems.ItemAt(sigIndex));
440 			if (signature == NULL)
441 				continue;
442 
443 			// Start at the 'bottom' of the list working up.
444 			// Prevents being thrown off by expanding items.
445 			for (int teamIndex = fExpando->CountItems(); teamIndex-- > 0;) {
446 				TTeamMenuItem *item = dynamic_cast<TTeamMenuItem *>(fExpando->ItemAt(teamIndex));
447 				if (item != NULL && !signature->Compare(item->Signature())) {
448 					item->ToggleExpandState(false);
449 					break;
450 				}
451 			}
452 		}
453 
454 		// Clean up expanded signature list.
455 		while (!expandedItems.IsEmpty()) {
456 			delete static_cast<BString *>(expandedItems.RemoveItem((int32)0));
457 		}
458 
459 		fExpando->SizeWindow();
460 	}
461 
462 	Invalidate();
463 }
464 
465 
466 //	window placement functions
467 
468 bool
469 TBarView::Vertical() const
470 {
471 	return fVertical;
472 }
473 
474 
475 bool
476 TBarView::Left() const
477 {
478 	return fLeft;
479 }
480 
481 
482 bool
483 TBarView::AcrossTop() const
484 {
485 	return fTop && !fVertical;
486 }
487 
488 
489 bool
490 TBarView::AcrossBottom() const
491 {
492 	return !fTop && !fVertical;
493 }
494 
495 
496 bool
497 TBarView::Expando() const
498 {
499 	return fState == kExpandoState;
500 }
501 
502 
503 bool
504 TBarView::Top() const
505 {
506 	return fTop;
507 }
508 
509 
510 int32
511 TBarView::State() const
512 {
513 	return fState;
514 }
515 
516 
517 // optional functionality functions
518 
519 bool
520 TBarView::MilTime() const
521 {
522 	return fShowInterval;
523 }
524 
525 
526 void
527 TBarView::ShowClock(bool on)
528 {
529 	fShowClock = on;
530 }
531 
532 
533 bool
534 TBarView::ShowingClock() const
535 {
536 	return fShowClock;
537 }
538 
539 
540 //	#pragma mark - Drag and Drop
541 
542 void
543 TBarView::CacheDragData(const BMessage *incoming)
544 {
545 	if (!incoming)
546 		return;
547 
548 	if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage))
549 		return;
550 
551 	// disposes then fills cached drag message and
552 	// mimetypes list
553 	SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList);
554 }
555 
556 
557 static void
558 init_tracking_hook(BMenuItem *item,
559 	bool (*hookFunction)(BMenu *, void *), void *state)
560 {
561 	if (!item)
562 		return;
563 
564 	BMenu *windowMenu = item->Submenu();
565 	if (windowMenu) {
566 		// have a menu, set the tracking hook
567 		windowMenu->SetTrackingHook(hookFunction, state);
568 	}
569 }
570 
571 
572 status_t
573 TBarView::DragStart()
574 {
575 	// always set the click to open state
576 	// to false during a drag
577 	// so that a release on a menu/menubar will not
578 	// leave the menu open (ExpandoMenuBar, BarMenuBar)
579 	// will get reset to actual initial system
580 	// state on DragStop
581 	_menu_info_ptr_->click_to_open = false;
582 
583 	if (!Dragging())
584 		return B_OK;
585 
586 	BPoint loc;
587 	uint32 buttons;
588 	GetMouse(&loc, &buttons);
589 
590 	if (fExpando && fExpando->Frame().Contains(loc)) {
591 		ConvertToScreen(&loc);
592 		BPoint expandoLocation = fExpando->ConvertFromScreen(loc);
593 		TTeamMenuItem *item = fExpando->TeamItemAtPoint(expandoLocation);
594 
595 		if (fLastDragItem)
596 			init_tracking_hook(fLastDragItem, NULL, NULL);
597 
598 		if (item) {
599 			if (item == fLastDragItem)
600 				return B_OK;
601 
602 			fLastDragItem = item;
603 		}
604 	}
605 
606 	return B_OK;
607 }
608 
609 
610 bool
611 TBarView::MenuTrackingHook(BMenu *menu, void *castToThis)
612 {
613 	// return true if the menu should go away
614 	TrackingHookData *data = static_cast<TrackingHookData *>(castToThis);
615 	if (!data)
616 		return false;
617 
618 	TBarView *barview = dynamic_cast<TBarView *>(data->fTarget.Target(NULL));
619 	if (!barview || !menu->LockLooper())
620 		return false;
621 
622 	uint32 buttons;
623 	BPoint location;
624 	menu->GetMouse(&location, &buttons);
625 
626 	bool endMenu = true;
627 	BRect frame(menu->Bounds());
628 	frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin);
629 
630 	if (frame.Contains(location)) {
631 		// if current loc is still in the menu
632 		// keep tracking
633 		endMenu = false;
634 	} else {
635 		// see if the mouse is in the team/be menu item
636 		menu->ConvertToScreen(&location);
637 		if (barview->LockLooper()) {
638 			TExpandoMenuBar *expando = barview->ExpandoMenuBar();
639 			TBeMenu *bemenu = (dynamic_cast<TBarWindow*>(barview->Window()))->BeMenu();
640 
641 			if (bemenu && bemenu->LockLooper()) {
642 				bemenu->ConvertFromScreen(&location);
643 				if (bemenu->Frame().Contains(location))
644 					endMenu = false;
645 
646 				bemenu->UnlockLooper();
647 			}
648 
649 			if (endMenu && expando) {
650 				expando->ConvertFromScreen(&location);
651 				BMenuItem *item = expando->TeamItemAtPoint(location);
652 				if (item)
653 					endMenu = false;
654 			}
655 			barview->UnlockLooper();
656 		}
657 	}
658 
659 	menu->UnlockLooper();
660 	return endMenu;
661 }
662 
663 
664 // used by WindowMenu and TeamMenu to
665 // set the tracking hook for dragging
666 TrackingHookData *
667 TBarView::GetTrackingHookData()
668 {
669 	// all tracking hook data is
670 	// preset in AttachedToWindow
671 	// data should never change
672 	return &fTrackingHookData;
673 }
674 
675 
676 void
677 TBarView::DragStop(bool full)
678 {
679 	if (!Dragging())
680 		return;
681 
682 	// revert the local click to open to
683 	// the launch state, cached in constructor
684 	_menu_info_ptr_->click_to_open = fClickToOpen;
685 
686 	if (fExpando) {
687 		if (fLastDragItem) {
688 			init_tracking_hook(fLastDragItem, NULL, NULL);
689 			fLastDragItem = NULL;
690 		}
691 	}
692 
693 	if (full) {
694 		delete fDragMessage;
695 		fDragMessage = NULL;
696 
697 		delete fCachedTypesList;
698 		fCachedTypesList = NULL;
699 	}
700 }
701 
702 
703 bool
704 TBarView::AppCanHandleTypes(const char *signature)
705 {
706 	// used for filtering apps/teams in the ExpandoMenuBar and TeamMenu
707 
708 	if (modifiers() & B_CONTROL_KEY) {
709 		// control key forces acceptance, just like drag&drop on icons
710 		return true;
711 	}
712 
713 	if (!signature || strlen(signature) == 0
714 		|| !fCachedTypesList || fCachedTypesList->CountItems() == 0)
715 		return false;
716 
717 	if (strcmp(signature, kTrackerSignature) == 0) {
718 		// tracker should support all types
719 		// and should pass them on to the appropriate application
720 		return true;
721 	}
722 
723 	entry_ref hintref;
724 	BMimeType appmime(signature);
725 	if (appmime.GetAppHint(&hintref) != B_OK)
726 		return false;
727 
728 	// an app was found, now see if it supports any of
729 	// the refs in the message
730 	BFile file(&hintref, O_RDONLY);
731 	BAppFileInfo fileinfo(&file);
732 
733 	// scan the cached mimetype list and see if this app
734 	// supports anything in the list
735 	// only one item needs to match in the list of refs
736 
737 	int32 count = fCachedTypesList->CountItems();
738 	for (int32 i = 0 ; i < count ; i++) {
739 		if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String()))
740 			return true;
741 	}
742 
743 	return false;
744 }
745 
746 
747 void
748 TBarView::SetDragOverride(bool on)
749 {
750 	fRefsRcvdOnly = on;
751 }
752 
753 
754 bool
755 TBarView::DragOverride()
756 {
757 	return fRefsRcvdOnly;
758 }
759 
760 
761 status_t
762 TBarView::SendDragMessage(const char *signature, entry_ref *ref)
763 {
764 	status_t err = B_ERROR;
765 	if (fDragMessage) {
766 		if (fRefsRcvdOnly) {
767 			// current message sent to apps is only B_REFS_RECEIVED
768 			fDragMessage->what = B_REFS_RECEIVED;
769 		}
770 
771 		BRoster roster;
772 		if (signature && strlen(signature) > 0 && roster.IsRunning(signature)) {
773 			BMessenger mess(signature);
774 			// drag message is still owned by DB, copy is sent
775 			// can toss it after send
776 			err = mess.SendMessage(fDragMessage);
777 		} else if (ref) {
778 			FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage,
779 				true, true);
780 		} else if (signature && strlen(signature) > 0) {
781 			roster.Launch(signature, fDragMessage);
782 		}
783 	}
784 	return err;
785 }
786 
787 
788 bool
789 TBarView::InvokeItem(const char *signature)
790 {
791 	// sent from TeamMenuItem
792 	if (Dragging() && AppCanHandleTypes(signature)) {
793 		SendDragMessage(signature);
794 		// invoking okay to toss memory
795 		DragStop(true);
796 		return true;
797 	}
798 
799 	return false;
800 }
801 
802 
803 void
804 TBarView::HandleBeMenu(BMessage *messagewithdestination)
805 {
806 	if (!Dragging())
807 		return;
808 
809 	// in mini-mode
810 	if (Vertical() && !Expando()) {
811 		// if drop is in the team menu, bail
812 		if (fBarMenuBar->CountItems() >= 2) {
813 			uint32 buttons;
814 			BPoint location;
815 			GetMouse(&location, &buttons);
816 			if (fBarMenuBar->ItemAt(1)->Frame().Contains(location))
817 				return;
818 		}
819 	}
820 
821 	if (messagewithdestination) {
822 		entry_ref ref;
823 		if (messagewithdestination->FindRef("refs", &ref) == B_OK) {
824 			BEntry entry(&ref, true);
825 			if (entry.IsDirectory()) {
826 				// if the ref received (should only be 1) is a directory
827 				// then add the drag refs to the directory
828 				AddRefsToBeMenu(DragMessage(), &ref);
829 			} else
830 				SendDragMessage(NULL, &ref);
831 		}
832 	} else {
833 		// adds drag refs to top level in be menu
834 		AddRefsToBeMenu(DragMessage(), NULL);
835 	}
836 
837 	// clean up drag message and types list
838 	DragStop(true);
839 }
840 
841 
842 //	#pragma mark - Add-ons
843 
844 
845 // shelf is ignored for now,
846 // it exists in anticipation of having other 'shelves' for
847 // storing items
848 
849 status_t
850 TBarView::ItemInfo(int32 id, const char **name, DeskbarShelf *shelf)
851 {
852 	*shelf = B_DESKBAR_TRAY;
853 	return fReplicantTray->ItemInfo(id, name);
854 }
855 
856 
857 status_t
858 TBarView::ItemInfo(const char *name, int32 *id, DeskbarShelf *shelf)
859 {
860 	*shelf = B_DESKBAR_TRAY;
861 	return fReplicantTray->ItemInfo(name, id);
862 }
863 
864 
865 bool
866 TBarView::ItemExists(int32 id, DeskbarShelf)
867 {
868 	return fReplicantTray->IconExists(id);
869 }
870 
871 
872 bool
873 TBarView::ItemExists(const char *name, DeskbarShelf)
874 {
875 	return fReplicantTray->IconExists(name);
876 }
877 
878 
879 int32
880 TBarView::CountItems(DeskbarShelf)
881 {
882 	return fReplicantTray->IconCount();
883 }
884 
885 
886 status_t
887 TBarView::AddItem(BMessage *item, DeskbarShelf, int32 *id)
888 {
889 	return fReplicantTray->AddIcon(item, id);
890 }
891 
892 
893 void
894 TBarView::RemoveItem(int32 id)
895 {
896 	fReplicantTray->RemoveIcon(id);
897 }
898 
899 
900 void
901 TBarView::RemoveItem(const char *name, DeskbarShelf)
902 {
903 	fReplicantTray->RemoveIcon(name);
904 }
905 
906 
907 BRect
908 TBarView::OffsetIconFrame(BRect rect) const
909 {
910 	BRect frame(Frame());
911 	frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left + rect.left;
912 	frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top + rect.top;
913 
914 	frame.right = frame.left + rect.Width();
915 	frame.bottom = frame.top + rect.Height();
916 
917 	return frame;
918 }
919 
920 
921 BRect
922 TBarView::IconFrame(int32 id) const
923 {
924 	return OffsetIconFrame(fReplicantTray->IconFrame(id));
925 }
926 
927 
928 BRect
929 TBarView::IconFrame(const char *name) const
930 {
931 	return OffsetIconFrame(fReplicantTray->IconFrame(name));
932 }
933 
934