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