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