BPicture: Fix archive constructor.
[haiku.git] / src / apps / deskbar / BarView.cpp
blob863420724324c618e0abac1f85bf8cc940a3af2b
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
37 #include "BarView.h"
39 #include <AppFileInfo.h>
40 #include <Bitmap.h>
41 #include <Debug.h>
42 #include <Directory.h>
43 #include <LocaleRoster.h>
44 #include <NodeInfo.h>
45 #include <Roster.h>
46 #include <Screen.h>
47 #include <String.h>
49 #include "icons.h"
50 #include "BarApp.h"
51 #include "BarMenuBar.h"
52 #include "BarWindow.h"
53 #include "DeskbarMenu.h"
54 #include "DeskbarUtils.h"
55 #include "ExpandoMenuBar.h"
56 #include "FSUtils.h"
57 #include "InlineScrollView.h"
58 #include "ResourceSet.h"
59 #include "StatusView.h"
60 #include "TeamMenuItem.h"
63 const int32 kDefaultRecentDocCount = 10;
64 const int32 kDefaultRecentFolderCount = 10;
65 const int32 kDefaultRecentAppCount = 10;
67 const int32 kMenuTrackMargin = 20;
69 const uint32 kUpdateOrientation = 'UpOr';
70 const float kSepItemWidth = 5.0f;
73 class BarViewMessageFilter : public BMessageFilter
75 public:
76 BarViewMessageFilter(TBarView* barView);
77 virtual ~BarViewMessageFilter();
79 virtual filter_result Filter(BMessage* message, BHandler** target);
81 private:
82 TBarView* fBarView;
86 BarViewMessageFilter::BarViewMessageFilter(TBarView* barView)
88 BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
89 fBarView(barView)
94 BarViewMessageFilter::~BarViewMessageFilter()
99 filter_result
100 BarViewMessageFilter::Filter(BMessage* message, BHandler** target)
102 if (message->what == B_MOUSE_DOWN || message->what == B_MOUSE_MOVED) {
103 BPoint where = message->FindPoint("be:view_where");
104 uint32 transit = message->FindInt32("be:transit");
105 BMessage* dragMessage = NULL;
106 if (message->HasMessage("be:drag_message")) {
107 dragMessage = new BMessage();
108 message->FindMessage("be:drag_message", dragMessage);
111 switch (message->what) {
112 case B_MOUSE_DOWN:
113 fBarView->MouseDown(where);
114 break;
116 case B_MOUSE_MOVED:
117 fBarView->MouseMoved(where, transit, dragMessage);
118 break;
121 delete dragMessage;
124 return B_DISPATCH_MESSAGE;
128 // #pragma mark - TBarView
131 TBarView::TBarView(BRect frame, bool vertical, bool left, bool top,
132 int32 state, float)
134 BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
135 fBarApp(static_cast<TBarApp*>(be_app)),
136 fInlineScrollView(NULL),
137 fBarMenuBar(NULL),
138 fExpandoMenuBar(NULL),
139 fTrayLocation(1),
140 fVertical(vertical),
141 fTop(top),
142 fLeft(left),
143 fState(state),
144 fRefsRcvdOnly(true),
145 fDragMessage(NULL),
146 fCachedTypesList(NULL),
147 fMaxRecentDocs(kDefaultRecentDocCount),
148 fMaxRecentApps(kDefaultRecentAppCount),
149 fLastDragItem(NULL),
150 fMouseFilter(NULL)
152 // determine the initial Be menu size
153 BRect menuFrame(frame);
154 if (fVertical)
155 menuFrame.bottom = menuFrame.top + kMenuBarHeight;
156 else
157 menuFrame.bottom = menuFrame.top + fBarApp->IconSize() + 4;
159 // create and add the Be menu
160 fBarMenuBar = new TBarMenuBar(menuFrame, "BarMenuBar", this);
161 AddChild(fBarMenuBar);
163 // create and add the status tray
164 fReplicantTray = new TReplicantTray(this, fVertical);
165 fDragRegion = new TDragRegion(this, fReplicantTray);
166 fDragRegion->AddChild(fReplicantTray);
167 if (fTrayLocation != 0)
168 AddChild(fDragRegion);
170 // create and add the application menubar
171 fExpandoMenuBar = new TExpandoMenuBar(this, fVertical);
172 fInlineScrollView = new TInlineScrollView(fExpandoMenuBar,
173 fVertical ? B_VERTICAL : B_HORIZONTAL);
174 AddChild(fInlineScrollView);
176 // If mini mode, hide the application menubar
177 if (state == kMiniState)
178 fInlineScrollView->Hide();
182 TBarView::~TBarView()
184 delete fDragMessage;
185 delete fCachedTypesList;
186 delete fBarMenuBar;
190 void
191 TBarView::AttachedToWindow()
193 BView::AttachedToWindow();
195 SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
196 SetFont(be_plain_font);
198 fMouseFilter = new BarViewMessageFilter(this);
199 Window()->AddCommonFilter(fMouseFilter);
201 fTrackingHookData.fTrackingHook = MenuTrackingHook;
202 fTrackingHookData.fTarget = BMessenger(this);
203 fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED);
207 void
208 TBarView::DetachedFromWindow()
210 Window()->RemoveCommonFilter(fMouseFilter);
211 delete fMouseFilter;
212 fMouseFilter = NULL;
213 delete fTrackingHookData.fDragMessage;
214 fTrackingHookData.fDragMessage = NULL;
218 void
219 TBarView::Draw(BRect)
221 BRect bounds(Bounds());
223 rgb_color hilite = tint_color(ViewColor(), B_DARKEN_1_TINT);
225 SetHighColor(hilite);
226 if (AcrossTop())
227 StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
228 else if (AcrossBottom())
229 StrokeLine(bounds.LeftTop(), bounds.RightTop());
231 if (fVertical && fState == kExpandoState) {
232 SetHighColor(hilite);
233 BRect frame(fExpandoMenuBar->Frame());
234 StrokeLine(BPoint(frame.left, frame.top - 1),
235 BPoint(frame.right, frame.top -1));
240 void
241 TBarView::MessageReceived(BMessage* message)
243 switch (message->what) {
244 case B_LOCALE_CHANGED:
245 case kShowHideTime:
246 case kShowSeconds:
247 case kShowDayOfWeek:
248 case kShowTimeZone:
249 case kGetClockSettings:
250 fReplicantTray->MessageReceived(message);
251 break;
253 case B_REFS_RECEIVED:
254 // received when an item is selected during DnD
255 // message is targeted here from Be menu
256 HandleDeskbarMenu(message);
257 break;
259 case B_ARCHIVED_OBJECT:
261 // this message has been retargeted to here
262 // instead of directly to the replicant tray
263 // so that I can follow the common pathway
264 // for adding icons to the tray
265 int32 id;
266 if (AddItem(message, B_DESKBAR_TRAY, &id) == B_OK)
267 Looper()->DetachCurrentMessage();
268 break;
271 case kUpdateOrientation:
273 _ChangeState(message);
274 break;
277 default:
278 BView::MessageReceived(message);
283 void
284 TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
286 if (fDragRegion->IsDragging()) {
287 fDragRegion->MouseMoved(where, transit, dragMessage);
288 return;
291 if (transit == B_ENTERED_VIEW && EventMask() == 0)
292 SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
294 desk_settings* settings = fBarApp->Settings();
295 bool alwaysOnTop = settings->alwaysOnTop;
296 bool autoRaise = settings->autoRaise;
297 bool autoHide = settings->autoHide;
299 if (!autoRaise && !autoHide) {
300 if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)
301 SetEventMask(0);
302 return;
305 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
307 // Auto-Raise
308 where = ConvertToScreen(where);
309 BRect screenFrame = (BScreen(Window())).Frame();
310 if ((where.x == screenFrame.left || where.x == screenFrame.right
311 || where.y == screenFrame.top || where.y == screenFrame.bottom)
312 && Window()->Frame().Contains(where)) {
313 // cursor is on a screen edge within the window frame
315 if (!alwaysOnTop && autoRaise && !isTopMost)
316 RaiseDeskbar(true);
318 if (autoHide && IsHidden())
319 HideDeskbar(false);
321 } else {
322 TBarWindow* window = (TBarWindow*)Window();
323 if (window->IsShowingMenu())
324 return;
326 // cursor is not on screen edge
327 BRect preventHideArea = Window()->Frame().InsetByCopy(
328 -kMaxPreventHidingDist, -kMaxPreventHidingDist);
330 if (preventHideArea.Contains(where))
331 return;
333 // cursor to bar distance above threshold
334 if (!alwaysOnTop && autoRaise && isTopMost) {
335 RaiseDeskbar(false);
336 SetEventMask(0);
339 if (autoHide && !IsHidden())
340 HideDeskbar(true);
345 void
346 TBarView::MouseDown(BPoint where)
348 where = ConvertToScreen(where);
350 if (Window()->Frame().Contains(where)) {
351 Window()->Activate();
353 if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY
354 | B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) {
355 // The window key was pressed - enter dragging code
356 fDragRegion->MouseDown(fDragRegion->DragRegion().LeftTop());
357 return;
359 } else {
360 // hide deskbar if required
361 desk_settings* settings = fBarApp->Settings();
362 bool alwaysOnTop = settings->alwaysOnTop;
363 bool autoRaise = settings->autoRaise;
364 bool autoHide = settings->autoHide;
365 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
367 if (!alwaysOnTop && autoRaise && isTopMost)
368 RaiseDeskbar(false);
370 if (autoHide && !IsHidden())
371 HideDeskbar(true);
376 void
377 TBarView::PlaceDeskbarMenu()
379 float height;
380 height = fVertical ? kMenuBarHeight : fBarApp->IconSize() + 4;
382 BPoint loc(B_ORIGIN);
383 float width = gMinimumWindowWidth;
385 if (fState == kFullState) {
386 fBarMenuBar->RemoveTeamMenu();
387 fBarMenuBar->RemoveSeperatorItem();
388 loc = Bounds().LeftTop();
389 } else if (fState == kExpandoState) {
390 fBarMenuBar->RemoveTeamMenu();
391 if (fVertical) {
392 // shows apps below tray
393 fBarMenuBar->RemoveSeperatorItem();
394 width += 1;
395 } else {
396 // shows apps to the right of bemenu
397 fBarMenuBar->AddSeparatorItem();
398 width = floorf(width) / 2 + kSepItemWidth;
400 loc = Bounds().LeftTop();
401 } else {
402 // mini mode, DeskbarMenu next to team menu
403 fBarMenuBar->RemoveSeperatorItem();
404 fBarMenuBar->AddTeamMenu();
407 fBarMenuBar->SmartResize(width, height);
408 fBarMenuBar->MoveTo(loc);
412 void
413 TBarView::PlaceTray(bool vertSwap, bool leftSwap)
415 BPoint statusLoc;
416 if (fState == kFullState) {
417 fDragRegion->ResizeTo(fBarMenuBar->Frame().Width(), kMenuBarHeight);
418 statusLoc.y = fBarMenuBar->Frame().bottom + 1;
419 statusLoc.x = 0;
420 fDragRegion->MoveTo(statusLoc);
422 if (!fReplicantTray->IsHidden())
423 fReplicantTray->Hide();
425 return;
428 if (fReplicantTray->IsHidden())
429 fReplicantTray->Show();
431 if (fTrayLocation != 0) {
432 fReplicantTray->SetMultiRow(fVertical);
433 fReplicantTray->RealignReplicants();
434 fDragRegion->ResizeToPreferred();
436 if (fVertical) {
437 statusLoc.y = fBarMenuBar->Frame().bottom + 1;
438 statusLoc.x = 0;
439 if (fLeft && fVertical)
440 fReplicantTray->MoveTo(5, 2);
441 else
442 fReplicantTray->MoveTo(2, 2);
443 } else {
444 BRect screenFrame = (BScreen(Window())).Frame();
445 statusLoc.x = screenFrame.right - fDragRegion->Bounds().Width();
446 statusLoc.y = -1;
449 fDragRegion->MoveTo(statusLoc);
454 void
455 TBarView::PlaceApplicationBar()
457 BRect screenFrame = (BScreen(Window())).Frame();
458 if (fState == kMiniState) {
459 if (!fInlineScrollView->IsHidden())
460 fInlineScrollView->Hide();
461 SizeWindow(screenFrame);
462 PositionWindow(screenFrame);
463 Window()->UpdateIfNeeded();
464 Invalidate();
465 return;
468 if (fInlineScrollView->IsHidden())
469 fInlineScrollView->Show();
471 BRect expandoFrame(0, 0, 0, 0);
472 if (fVertical) {
473 // left or right
474 expandoFrame.top = fTrayLocation != 0 ? fDragRegion->Frame().bottom + 1
475 : fBarMenuBar->Frame().bottom + 1;
476 expandoFrame.left = fDragRegion->Frame().left;
477 expandoFrame.right = expandoFrame.left + gMinimumWindowWidth;
478 expandoFrame.bottom = fState == kFullState ? screenFrame.bottom
479 : expandoFrame.top + 1;
480 } else {
481 // top or bottom
482 expandoFrame.top = 0;
483 expandoFrame.bottom = fBarApp->IconSize() + 4;
485 if (fBarMenuBar != NULL)
486 expandoFrame.left = fBarMenuBar->Frame().Width() + 1;
488 if (fTrayLocation != 0 && fDragRegion != NULL) {
489 expandoFrame.right = screenFrame.Width()
490 - fDragRegion->Frame().Width() - 1;
491 } else
492 expandoFrame.right = screenFrame.Width();
495 fInlineScrollView->DetachScrollers();
496 fInlineScrollView->MoveTo(expandoFrame.LeftTop());
497 fInlineScrollView->ResizeTo(expandoFrame.Width(), fVertical
498 ? screenFrame.bottom - expandoFrame.top
499 : expandoFrame.Height());
500 fExpandoMenuBar->MoveTo(0, 0);
501 fExpandoMenuBar->ResizeTo(expandoFrame.Width(), expandoFrame.Height());
503 if (!fVertical) {
504 // Set the max item width based on icon size
505 fExpandoMenuBar->SetMaxItemWidth();
508 if (fState == kExpandoState)
509 fExpandoMenuBar->BuildItems();
511 SizeWindow(screenFrame);
512 PositionWindow(screenFrame);
513 fExpandoMenuBar->DoLayout();
514 // force menu to resize
515 CheckForScrolling();
516 Window()->UpdateIfNeeded();
517 Invalidate();
521 void
522 TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* height)
524 float windowHeight = 0;
525 float windowWidth = gMinimumWindowWidth;
526 bool setToHiddenSize = fBarApp->Settings()->autoHide && IsHidden()
527 && !fDragRegion->IsDragging();
529 if (setToHiddenSize) {
530 windowHeight = kHiddenDimension;
532 if (fState == kExpandoState && !fVertical) {
533 // top or bottom, full
534 fExpandoMenuBar->CheckItemSizes(0);
535 windowWidth = screenFrame.Width();
536 } else
537 windowWidth = kHiddenDimension;
538 } else {
539 if (fState == kFullState) {
540 windowHeight = screenFrame.bottom;
541 windowWidth = fBarMenuBar->Frame().Width();
542 } else if (fState == kExpandoState) {
543 if (fVertical) {
544 // top left or right
545 if (fTrayLocation != 0)
546 windowHeight = fDragRegion->Frame().bottom + 1;
547 else
548 windowHeight = fBarMenuBar->Frame().bottom + 1;
550 windowHeight += fExpandoMenuBar->Bounds().Height();
551 } else {
552 // top or bottom, full
553 fExpandoMenuBar->CheckItemSizes(0);
554 windowHeight = fBarApp->IconSize() + 4;
555 windowWidth = screenFrame.Width();
557 } else {
558 // four corners
559 if (fTrayLocation != 0)
560 windowHeight = fDragRegion->Frame().bottom;
561 else
562 windowHeight = fBarMenuBar->Frame().bottom;
566 *width = windowWidth;
567 *height = windowHeight;
571 void
572 TBarView::SizeWindow(BRect screenFrame)
574 float windowWidth;
575 float windowHeight;
576 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
577 Window()->ResizeTo(windowWidth, windowHeight);
581 void
582 TBarView::PositionWindow(BRect screenFrame)
584 float windowWidth;
585 float windowHeight;
586 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
588 BPoint moveLoc(0, 0);
589 // right, expanded
590 if (!fLeft && fVertical) {
591 if (fState == kFullState)
592 moveLoc.x = screenFrame.right - fBarMenuBar->Frame().Width();
593 else
594 moveLoc.x = screenFrame.right - windowWidth;
597 // bottom, full or corners
598 if (!fTop)
599 moveLoc.y = screenFrame.bottom - windowHeight;
601 Window()->MoveTo(moveLoc);
605 void
606 TBarView::CheckForScrolling()
608 if (fInlineScrollView != NULL && fExpandoMenuBar != NULL) {
609 if (fExpandoMenuBar->CheckForSizeOverrun())
610 fInlineScrollView->AttachScrollers();
611 else
612 fInlineScrollView->DetachScrollers();
617 void
618 TBarView::SaveSettings()
620 desk_settings* settings = fBarApp->Settings();
622 settings->vertical = fVertical;
623 settings->left = fLeft;
624 settings->top = fTop;
625 settings->state = fState;
626 settings->width = 0;
628 fReplicantTray->SaveTimeSettings();
632 void
633 TBarView::UpdatePlacement()
635 ChangeState(fState, fVertical, fLeft, fTop);
639 void
640 TBarView::ChangeState(int32 state, bool vertical, bool left, bool top,
641 bool async)
643 BMessage message(kUpdateOrientation);
644 message.AddInt32("state", state);
645 message.AddBool("vertical", vertical);
646 message.AddBool("left", left);
647 message.AddBool("top", top);
649 if (async)
650 BMessenger(this).SendMessage(&message);
651 else
652 _ChangeState(&message);
656 void
657 TBarView::_ChangeState(BMessage* message)
659 int32 state = message->FindInt32("state");
660 bool vertical = message->FindBool("vertical");
661 bool left = message->FindBool("left");
662 bool top = message->FindBool("top");
664 bool vertSwap = (fVertical != vertical);
665 bool leftSwap = (fLeft != left);
666 bool stateChanged = (fState != state);
668 fState = state;
669 fVertical = vertical;
670 fLeft = left;
671 fTop = top;
673 if (stateChanged || vertSwap) {
674 be_app->PostMessage(kStateChanged);
675 // Send a message to the preferences window to let it know to
676 // enable or disable preference items.
678 if (vertSwap && fExpandoMenuBar != NULL) {
679 if (fVertical) {
680 fInlineScrollView->SetOrientation(B_VERTICAL);
681 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN);
682 fExpandoMenuBar->StartMonitoringWindows();
683 } else {
684 fInlineScrollView->SetOrientation(B_HORIZONTAL);
685 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW);
686 fExpandoMenuBar->StopMonitoringWindows();
691 PlaceDeskbarMenu();
692 PlaceTray(vertSwap, leftSwap);
693 PlaceApplicationBar();
697 void
698 TBarView::RaiseDeskbar(bool raise)
700 if (raise)
701 Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
702 else
703 Window()->SetFeel(B_NORMAL_WINDOW_FEEL);
707 void
708 TBarView::HideDeskbar(bool hide)
710 BRect screenFrame = (BScreen(Window())).Frame();
712 if (hide) {
713 Hide();
714 PositionWindow(screenFrame);
715 SizeWindow(screenFrame);
716 } else {
717 Show();
718 SizeWindow(screenFrame);
719 PositionWindow(screenFrame);
724 // #pragma mark - Drag and Drop
727 void
728 TBarView::CacheDragData(const BMessage* incoming)
730 if (!incoming)
731 return;
733 if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage))
734 return;
736 // disposes then fills cached drag message and
737 // mimetypes list
738 SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList);
742 static void
743 init_tracking_hook(BMenuItem* item,
744 bool (*hookFunction)(BMenu*, void*), void* state)
746 if (!item)
747 return;
749 BMenu* windowMenu = item->Submenu();
750 if (windowMenu) {
751 // have a menu, set the tracking hook
752 windowMenu->SetTrackingHook(hookFunction, state);
757 status_t
758 TBarView::DragStart()
760 if (!Dragging())
761 return B_OK;
763 BPoint loc;
764 uint32 buttons;
765 GetMouse(&loc, &buttons);
767 if (fExpandoMenuBar != NULL && fExpandoMenuBar->Frame().Contains(loc)) {
768 ConvertToScreen(&loc);
769 BPoint expandoLocation = fExpandoMenuBar->ConvertFromScreen(loc);
770 TTeamMenuItem* item = fExpandoMenuBar->TeamItemAtPoint(expandoLocation);
772 if (fLastDragItem)
773 init_tracking_hook(fLastDragItem, NULL, NULL);
775 if (item != NULL) {
776 if (item == fLastDragItem)
777 return B_OK;
779 fLastDragItem = item;
783 return B_OK;
787 bool
788 TBarView::MenuTrackingHook(BMenu* menu, void* castToThis)
790 // return true if the menu should go away
791 TrackingHookData* data = static_cast<TrackingHookData*>(castToThis);
792 if (!data)
793 return false;
795 TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL));
796 if (!barview || !menu->LockLooper())
797 return false;
799 uint32 buttons;
800 BPoint location;
801 menu->GetMouse(&location, &buttons);
803 bool endMenu = true;
804 BRect frame(menu->Bounds());
805 frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin);
807 if (frame.Contains(location)) {
808 // if current loc is still in the menu
809 // keep tracking
810 endMenu = false;
811 } else {
812 // see if the mouse is in the team/deskbar menu item
813 menu->ConvertToScreen(&location);
814 if (barview->LockLooper()) {
815 TExpandoMenuBar* expando = barview->ExpandoMenuBar();
816 TDeskbarMenu* bemenu
817 = (dynamic_cast<TBarWindow*>(barview->Window()))->DeskbarMenu();
819 if (bemenu && bemenu->LockLooper()) {
820 bemenu->ConvertFromScreen(&location);
821 if (bemenu->Frame().Contains(location))
822 endMenu = false;
824 bemenu->UnlockLooper();
827 if (endMenu && expando) {
828 expando->ConvertFromScreen(&location);
829 BMenuItem* item = expando->TeamItemAtPoint(location);
830 if (item)
831 endMenu = false;
833 barview->UnlockLooper();
837 menu->UnlockLooper();
838 return endMenu;
842 // used by WindowMenu and TeamMenu to
843 // set the tracking hook for dragging
844 TrackingHookData*
845 TBarView::GetTrackingHookData()
847 // all tracking hook data is
848 // preset in AttachedToWindow
849 // data should never change
850 return &fTrackingHookData;
854 void
855 TBarView::DragStop(bool full)
857 if (!Dragging())
858 return;
860 if (fExpandoMenuBar != NULL) {
861 if (fLastDragItem != NULL) {
862 init_tracking_hook(fLastDragItem, NULL, NULL);
863 fLastDragItem = NULL;
867 if (full) {
868 delete fDragMessage;
869 fDragMessage = NULL;
871 delete fCachedTypesList;
872 fCachedTypesList = NULL;
877 bool
878 TBarView::AppCanHandleTypes(const char* signature)
880 // used for filtering apps/teams in the ExpandoMenuBar and TeamMenu
882 if (modifiers() & B_CONTROL_KEY) {
883 // control key forces acceptance, just like drag&drop on icons
884 return true;
887 if (!signature || strlen(signature) == 0
888 || !fCachedTypesList || fCachedTypesList->CountItems() == 0)
889 return false;
891 if (strcasecmp(signature, kTrackerSignature) == 0) {
892 // tracker should support all types
893 // and should pass them on to the appropriate application
894 return true;
897 entry_ref hintref;
898 BMimeType appmime(signature);
899 if (appmime.GetAppHint(&hintref) != B_OK)
900 return false;
902 // an app was found, now see if it supports any of
903 // the refs in the message
904 BFile file(&hintref, O_RDONLY);
905 BAppFileInfo fileinfo(&file);
907 // scan the cached mimetype list and see if this app
908 // supports anything in the list
909 // only one item needs to match in the list of refs
911 int32 count = fCachedTypesList->CountItems();
912 for (int32 i = 0 ; i < count ; i++) {
913 if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String()))
914 return true;
917 return false;
921 void
922 TBarView::SetDragOverride(bool on)
924 fRefsRcvdOnly = on;
928 bool
929 TBarView::DragOverride()
931 return fRefsRcvdOnly;
935 status_t
936 TBarView::SendDragMessage(const char* signature, entry_ref* ref)
938 status_t err = B_ERROR;
939 if (fDragMessage != NULL) {
940 if (fRefsRcvdOnly) {
941 // current message sent to apps is only B_REFS_RECEIVED
942 fDragMessage->what = B_REFS_RECEIVED;
945 BRoster roster;
946 if (signature != NULL && *signature != '\0'
947 && roster.IsRunning(signature)) {
948 BMessenger messenger(signature);
949 // drag message is still owned by DB, copy is sent
950 // can toss it after send
951 err = messenger.SendMessage(fDragMessage);
952 } else if (ref != NULL) {
953 FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage,
954 true, true);
955 } else if (signature != NULL && *signature != '\0')
956 roster.Launch(signature, fDragMessage);
959 return err;
963 bool
964 TBarView::InvokeItem(const char* signature)
966 // sent from TeamMenuItem
967 if (Dragging() && AppCanHandleTypes(signature)) {
968 SendDragMessage(signature);
969 // invoking okay to toss memory
970 DragStop(true);
971 return true;
974 return false;
978 void
979 TBarView::HandleDeskbarMenu(BMessage* messagewithdestination)
981 if (!Dragging())
982 return;
984 // in mini-mode
985 if (fVertical && fState != kExpandoState) {
986 // if drop is in the team menu, bail
987 if (fBarMenuBar->CountItems() >= 2) {
988 uint32 buttons;
989 BPoint location;
990 GetMouse(&location, &buttons);
991 if (fBarMenuBar->ItemAt(1)->Frame().Contains(location))
992 return;
996 if (messagewithdestination) {
997 entry_ref ref;
998 if (messagewithdestination->FindRef("refs", &ref) == B_OK) {
999 BEntry entry(&ref, true);
1000 if (entry.IsDirectory()) {
1001 // if the ref received (should only be 1) is a directory
1002 // then add the drag refs to the directory
1003 AddRefsToDeskbarMenu(DragMessage(), &ref);
1004 } else
1005 SendDragMessage(NULL, &ref);
1007 } else {
1008 // adds drag refs to top level in deskbar menu
1009 AddRefsToDeskbarMenu(DragMessage(), NULL);
1012 // clean up drag message and types list
1013 DragStop(true);
1017 // #pragma mark - Add-ons
1020 // shelf is ignored for now,
1021 // it exists in anticipation of having other 'shelves' for
1022 // storing items
1024 status_t
1025 TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf)
1027 *shelf = B_DESKBAR_TRAY;
1028 return fReplicantTray->ItemInfo(id, name);
1032 status_t
1033 TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf)
1035 *shelf = B_DESKBAR_TRAY;
1036 return fReplicantTray->ItemInfo(name, id);
1040 bool
1041 TBarView::ItemExists(int32 id, DeskbarShelf)
1043 return fReplicantTray->IconExists(id);
1047 bool
1048 TBarView::ItemExists(const char* name, DeskbarShelf)
1050 return fReplicantTray->IconExists(name);
1054 int32
1055 TBarView::CountItems(DeskbarShelf)
1057 return fReplicantTray->IconCount();
1061 status_t
1062 TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id)
1064 return fReplicantTray->AddIcon(item, id);
1068 status_t
1069 TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id)
1071 return fReplicantTray->LoadAddOn(entry, id);
1075 void
1076 TBarView::RemoveItem(int32 id)
1078 fReplicantTray->RemoveIcon(id);
1082 void
1083 TBarView::RemoveItem(const char* name, DeskbarShelf)
1085 fReplicantTray->RemoveIcon(name);
1089 BRect
1090 TBarView::OffsetIconFrame(BRect rect) const
1092 BRect frame(Frame());
1094 frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left
1095 + rect.left;
1096 frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top
1097 + rect.top;
1099 frame.right = frame.left + rect.Width();
1100 frame.bottom = frame.top + rect.Height();
1102 return frame;
1106 BRect
1107 TBarView::IconFrame(int32 id) const
1109 return OffsetIconFrame(fReplicantTray->IconFrame(id));
1113 BRect
1114 TBarView::IconFrame(const char* name) const
1116 return OffsetIconFrame(fReplicantTray->IconFrame(name));