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