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