btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / deskbar / BarView.cpp
blob9f46a53e61f67e94601e55be77c1e2bf8c52d9b6
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 the status tray
164 fReplicantTray = new TReplicantTray(this, fVertical);
166 // create the resize control
167 fResizeControl = new TResizeControl(this);
169 // create the drag region and add the resize control
170 // and replicant tray to it
171 fDragRegion = new TDragRegion(this, fReplicantTray);
172 fDragRegion->AddChild(fResizeControl);
173 fDragRegion->AddChild(fReplicantTray);
175 // Add the drag region
176 if (fTrayLocation != 0)
177 AddChild(fDragRegion);
179 // create and add the application menubar
180 fExpandoMenuBar = new TExpandoMenuBar(this, fVertical);
181 fInlineScrollView = new TInlineScrollView(fExpandoMenuBar,
182 fVertical ? B_VERTICAL : B_HORIZONTAL);
183 AddChild(fInlineScrollView);
185 // If mini mode, hide the application menubar
186 if (state == kMiniState)
187 fInlineScrollView->Hide();
191 TBarView::~TBarView()
193 delete fDragMessage;
194 delete fCachedTypesList;
195 delete fBarMenuBar;
199 void
200 TBarView::AttachedToWindow()
202 BView::AttachedToWindow();
204 SetViewUIColor(B_MENU_BACKGROUND_COLOR);
205 SetFont(be_plain_font);
207 fMouseFilter = new BarViewMessageFilter(this);
208 Window()->AddCommonFilter(fMouseFilter);
210 fTrackingHookData.fTrackingHook = MenuTrackingHook;
211 fTrackingHookData.fTarget = BMessenger(this);
212 fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED);
216 void
217 TBarView::DetachedFromWindow()
219 Window()->RemoveCommonFilter(fMouseFilter);
220 delete fMouseFilter;
221 fMouseFilter = NULL;
222 delete fTrackingHookData.fDragMessage;
223 fTrackingHookData.fDragMessage = NULL;
227 void
228 TBarView::Draw(BRect)
230 BRect bounds(Bounds());
232 rgb_color hilite = tint_color(ViewColor(), B_DARKEN_1_TINT);
234 SetHighColor(hilite);
235 if (AcrossTop())
236 StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
237 else if (AcrossBottom())
238 StrokeLine(bounds.LeftTop(), bounds.RightTop());
240 if (fVertical && fState == kExpandoState) {
241 SetHighColor(hilite);
242 BRect frame(fExpandoMenuBar->Frame());
243 StrokeLine(BPoint(frame.left, frame.top - 1),
244 BPoint(frame.right, frame.top -1));
249 void
250 TBarView::MessageReceived(BMessage* message)
252 switch (message->what) {
253 case B_LOCALE_CHANGED:
254 case kRealignReplicants:
255 case kShowHideTime:
256 case kShowSeconds:
257 case kShowDayOfWeek:
258 case kShowTimeZone:
259 case kGetClockSettings:
260 fReplicantTray->MessageReceived(message);
261 break;
263 case B_REFS_RECEIVED:
264 // received when an item is selected during DnD
265 // message is targeted here from Be menu
266 HandleDeskbarMenu(message);
267 break;
269 case B_ARCHIVED_OBJECT:
271 // this message has been retargeted to here
272 // instead of directly to the replicant tray
273 // so that I can follow the common pathway
274 // for adding icons to the tray
275 int32 id;
276 if (AddItem(message, B_DESKBAR_TRAY, &id) == B_OK)
277 Looper()->DetachCurrentMessage();
278 break;
281 case kUpdateOrientation:
283 _ChangeState(message);
284 break;
287 default:
288 BView::MessageReceived(message);
293 void
294 TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
296 if (fDragRegion->IsDragging()) {
297 fDragRegion->MouseMoved(where, transit, dragMessage);
298 return;
301 if (transit == B_ENTERED_VIEW && EventMask() == 0)
302 SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
304 BPoint whereScreen = ConvertToScreen(where);
306 desk_settings* settings = fBarApp->Settings();
307 bool alwaysOnTop = settings->alwaysOnTop;
308 bool autoRaise = settings->autoRaise;
309 bool autoHide = settings->autoHide;
311 if (!autoRaise && !autoHide) {
312 if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)
313 SetEventMask(0);
314 return;
317 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
319 // Auto-Raise
320 BRect screenFrame = (BScreen(Window())).Frame();
321 if ((whereScreen.x == screenFrame.left
322 || whereScreen.x == screenFrame.right
323 || whereScreen.y == screenFrame.top
324 || whereScreen.y == screenFrame.bottom)
325 && Window()->Frame().Contains(whereScreen)) {
326 // cursor is on a screen edge within the window frame
328 if (!alwaysOnTop && autoRaise && !isTopMost)
329 RaiseDeskbar(true);
331 if (autoHide && IsHidden())
332 HideDeskbar(false);
333 } else {
334 TBarWindow* window = (TBarWindow*)Window();
335 if (window->IsShowingMenu())
336 return;
338 // cursor is not on screen edge
339 BRect preventHideArea = Window()->Frame().InsetByCopy(
340 -kMaxPreventHidingDist, -kMaxPreventHidingDist);
342 if (preventHideArea.Contains(whereScreen))
343 return;
345 // cursor to bar distance above threshold
346 if (!alwaysOnTop && autoRaise && isTopMost) {
347 RaiseDeskbar(false);
348 SetEventMask(0);
351 if (autoHide && !IsHidden())
352 HideDeskbar(true);
357 void
358 TBarView::MouseDown(BPoint where)
360 BPoint whereScreen = ConvertToScreen(where);
362 if (Window()->Frame().Contains(whereScreen)) {
363 Window()->Activate();
365 if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY
366 | B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) {
367 // The window key was pressed - enter dragging code
368 fDragRegion->MouseDown(fDragRegion->DragRegion().LeftTop());
369 return;
371 } else {
372 // hide deskbar if required
373 desk_settings* settings = fBarApp->Settings();
374 bool alwaysOnTop = settings->alwaysOnTop;
375 bool autoRaise = settings->autoRaise;
376 bool autoHide = settings->autoHide;
377 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
379 if (!alwaysOnTop && autoRaise && isTopMost)
380 RaiseDeskbar(false);
382 if (autoHide && !IsHidden())
383 HideDeskbar(true);
388 void
389 TBarView::PlaceDeskbarMenu()
391 float width = 0;
392 float height = 0;
394 // Calculate the size of the deskbar menu
395 BRect menuFrame(Bounds());
396 if (fVertical) {
397 width = static_cast<TBarApp*>(be_app)->Settings()->width;
398 height = kMenuBarHeight;
399 menuFrame.bottom = menuFrame.top + height;
400 } else {
401 width = gMinimumWindowWidth;
402 height = fBarApp->IconSize() + 4;
403 menuFrame.bottom = menuFrame.top + height;
406 if (fBarMenuBar == NULL) {
407 // create the Be menu
408 fBarMenuBar = new TBarMenuBar(menuFrame, "BarMenuBar", this);
409 AddChild(fBarMenuBar);
410 } else
411 fBarMenuBar->SmartResize(-1, -1);
413 BPoint loc(B_ORIGIN);
414 if (fState == kFullState) {
415 fBarMenuBar->RemoveTeamMenu();
416 fBarMenuBar->RemoveSeperatorItem();
417 loc = Bounds().LeftTop();
418 } else if (fState == kExpandoState) {
419 fBarMenuBar->RemoveTeamMenu();
420 if (fVertical) {
421 // shows apps below tray
422 fBarMenuBar->RemoveSeperatorItem();
423 width += 1;
424 } else {
425 // shows apps to the right of bemenu
426 fBarMenuBar->AddSeparatorItem();
427 width = floorf(width) / 2 + kSepItemWidth;
429 loc = Bounds().LeftTop();
430 } else {
431 // mini mode, DeskbarMenu next to team menu
432 fBarMenuBar->RemoveSeperatorItem();
433 fBarMenuBar->AddTeamMenu();
436 fBarMenuBar->SmartResize(width, height);
437 fBarMenuBar->MoveTo(loc);
441 void
442 TBarView::PlaceTray(bool vertSwap, bool leftSwap)
444 BPoint statusLoc;
445 if (fState == kFullState) {
446 fDragRegion->ResizeTo(fBarMenuBar->Frame().Width(), kMenuBarHeight);
447 statusLoc.y = fBarMenuBar->Frame().bottom + 1;
448 statusLoc.x = 0;
449 fDragRegion->MoveTo(statusLoc);
450 fDragRegion->Invalidate();
452 if (!fReplicantTray->IsHidden())
453 fReplicantTray->Hide();
455 return;
458 if (fReplicantTray->IsHidden())
459 fReplicantTray->Show();
461 if (fTrayLocation != 0) {
462 fReplicantTray->SetMultiRow(fVertical);
463 fReplicantTray->RealignReplicants();
464 fDragRegion->ResizeToPreferred();
465 // also resizes replicant tray
467 fResizeControl->ResizeTo(kDragWidth, fDragRegion->Bounds().Height()
468 - 2); // make room for top and bottom border
470 if (fVertical) {
471 if (fResizeControl->IsHidden())
472 fResizeControl->Show();
474 if (fLeft) {
475 // move replicant tray past dragger width on left
476 // also down 1px so it won't cover the border
477 fReplicantTray->MoveTo(kDragWidth + kGutter, kGutter);
479 // shrink width by same amount
480 fReplicantTray->ResizeBy(-(kDragWidth + kGutter), 0);
481 } else {
482 // move replicant tray down 1px so it won't cover the border
483 fReplicantTray->MoveTo(0, kGutter);
486 statusLoc.x = 0;
487 statusLoc.y = fBarMenuBar->Frame().bottom + 1;
488 } else {
489 if (!fResizeControl->IsHidden())
490 fResizeControl->Hide();
492 // move right and down to not cover border then resize to fit
493 fReplicantTray->MoveTo(kGutter, kGutter);
494 fReplicantTray->ResizeBy(-kGutter, -kGutter);
495 BRect screenFrame = (BScreen(Window())).Frame();
496 statusLoc.x = screenFrame.right - fDragRegion->Bounds().Width();
497 statusLoc.y = -1;
500 fDragRegion->MoveTo(statusLoc);
501 fDragRegion->Invalidate();
503 if (fVertical && fLeft)
504 fResizeControl->MoveTo(fDragRegion->Bounds().right - kDragWidth, 1);
505 else
506 fResizeControl->MoveTo(0, 1);
508 fResizeControl->Invalidate();
513 void
514 TBarView::PlaceApplicationBar()
516 BRect screenFrame = (BScreen(Window())).Frame();
517 if (fState == kMiniState) {
518 if (!fInlineScrollView->IsHidden())
519 fInlineScrollView->Hide();
520 SizeWindow(screenFrame);
521 PositionWindow(screenFrame);
522 Window()->UpdateIfNeeded();
523 Invalidate();
524 return;
527 if (fInlineScrollView->IsHidden())
528 fInlineScrollView->Show();
530 BRect expandoFrame(0, 0, 0, 0);
531 if (fVertical) {
532 // left or right
533 expandoFrame.left = fDragRegion->Frame().left;
534 expandoFrame.top = fTrayLocation != 0 ? fDragRegion->Frame().bottom + 1
535 : fBarMenuBar->Frame().bottom + 1;
536 expandoFrame.right = fBarMenuBar->Frame().right;
537 expandoFrame.bottom = fState == kFullState ? screenFrame.bottom
538 : Frame().bottom;
539 } else {
540 // top or bottom
541 expandoFrame.top = 0;
542 expandoFrame.bottom = fBarApp->IconSize() + 4;
544 if (fBarMenuBar != NULL)
545 expandoFrame.left = fBarMenuBar->Frame().Width() + 1;
547 if (fTrayLocation != 0 && fDragRegion != NULL) {
548 expandoFrame.right = screenFrame.Width()
549 - fDragRegion->Frame().Width() - 1;
550 } else
551 expandoFrame.right = screenFrame.Width();
554 fInlineScrollView->DetachScrollers();
555 fInlineScrollView->MoveTo(expandoFrame.LeftTop());
556 fInlineScrollView->ResizeTo(expandoFrame.Width(), fVertical
557 ? screenFrame.bottom - expandoFrame.top
558 : expandoFrame.Height());
559 fExpandoMenuBar->MoveTo(0, 0);
560 fExpandoMenuBar->ResizeTo(expandoFrame.Width(), expandoFrame.Height());
562 if (!fVertical) {
563 // Set the max item width based on icon size
564 fExpandoMenuBar->SetMaxItemWidth();
567 if (fState == kExpandoState)
568 fExpandoMenuBar->BuildItems();
570 SizeWindow(screenFrame);
571 PositionWindow(screenFrame);
572 fExpandoMenuBar->DoLayout();
573 // force menu to resize
574 CheckForScrolling();
575 Window()->UpdateIfNeeded();
576 Invalidate();
580 void
581 TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* height)
583 float windowHeight = 0;
584 float windowWidth = fBarApp->Settings()->width;
585 bool setToHiddenSize = fBarApp->Settings()->autoHide && IsHidden()
586 && !fDragRegion->IsDragging();
588 if (setToHiddenSize) {
589 windowHeight = kHiddenDimension;
591 if (fState == kExpandoState && !fVertical) {
592 // top or bottom, full
593 fExpandoMenuBar->CheckItemSizes(0);
594 windowWidth = screenFrame.Width();
595 } else
596 windowWidth = kHiddenDimension;
597 } else {
598 if (fState == kFullState) {
599 windowHeight = screenFrame.bottom;
600 windowWidth = fBarMenuBar->Frame().Width();
601 } else if (fState == kExpandoState) {
602 if (fVertical) {
603 // top left or right
604 if (fTrayLocation != 0)
605 windowHeight = fDragRegion->Frame().bottom + 1;
606 else
607 windowHeight = fBarMenuBar->Frame().bottom + 1;
609 windowHeight += fExpandoMenuBar->Bounds().Height();
610 } else {
611 // top or bottom, full
612 fExpandoMenuBar->CheckItemSizes(0);
613 windowHeight = fBarApp->IconSize() + 4;
614 windowWidth = screenFrame.Width();
616 } else {
617 // four corners
618 if (fTrayLocation != 0)
619 windowHeight = fDragRegion->Frame().bottom;
620 else
621 windowHeight = fBarMenuBar->Frame().bottom;
625 *width = windowWidth;
626 *height = windowHeight;
630 void
631 TBarView::SizeWindow(BRect screenFrame)
633 float windowWidth;
634 float windowHeight;
635 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
636 Window()->ResizeTo(windowWidth, windowHeight);
640 void
641 TBarView::PositionWindow(BRect screenFrame)
643 float windowWidth;
644 float windowHeight;
645 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
647 BPoint moveLoc(0, 0);
648 // right, expanded
649 if (!fLeft && fVertical) {
650 if (fState == kFullState)
651 moveLoc.x = screenFrame.right - fBarMenuBar->Frame().Width();
652 else
653 moveLoc.x = screenFrame.right - windowWidth;
656 // bottom, full or corners
657 if (!fTop)
658 moveLoc.y = screenFrame.bottom - windowHeight;
660 Window()->MoveTo(moveLoc);
664 void
665 TBarView::CheckForScrolling()
667 if (fInlineScrollView != NULL && fExpandoMenuBar != NULL) {
668 if (fExpandoMenuBar->CheckForSizeOverrun())
669 fInlineScrollView->AttachScrollers();
670 else
671 fInlineScrollView->DetachScrollers();
676 void
677 TBarView::SaveSettings()
679 desk_settings* settings = fBarApp->Settings();
681 settings->vertical = fVertical;
682 settings->left = fLeft;
683 settings->top = fTop;
684 settings->state = fState;
686 fReplicantTray->SaveTimeSettings();
690 void
691 TBarView::UpdatePlacement()
693 ChangeState(fState, fVertical, fLeft, fTop);
697 void
698 TBarView::ChangeState(int32 state, bool vertical, bool left, bool top,
699 bool async)
701 BMessage message(kUpdateOrientation);
702 message.AddInt32("state", state);
703 message.AddBool("vertical", vertical);
704 message.AddBool("left", left);
705 message.AddBool("top", top);
707 if (async)
708 BMessenger(this).SendMessage(&message);
709 else
710 _ChangeState(&message);
714 void
715 TBarView::_ChangeState(BMessage* message)
717 int32 state = message->FindInt32("state");
718 bool vertical = message->FindBool("vertical");
719 bool left = message->FindBool("left");
720 bool top = message->FindBool("top");
722 bool vertSwap = (fVertical != vertical);
723 bool leftSwap = (fLeft != left);
724 bool stateChanged = (fState != state);
726 fState = state;
727 fVertical = vertical;
728 fLeft = left;
729 fTop = top;
731 if (stateChanged || vertSwap) {
732 be_app->PostMessage(kStateChanged);
733 // Send a message to the preferences window to let it know to
734 // enable or disable preference items.
736 if (vertSwap && fExpandoMenuBar != NULL) {
737 if (fVertical) {
738 fInlineScrollView->SetOrientation(B_VERTICAL);
739 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN);
740 fExpandoMenuBar->StartMonitoringWindows();
741 } else {
742 fInlineScrollView->SetOrientation(B_HORIZONTAL);
743 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW);
744 fExpandoMenuBar->StopMonitoringWindows();
749 PlaceDeskbarMenu();
750 PlaceTray(vertSwap, leftSwap);
751 PlaceApplicationBar();
755 void
756 TBarView::RaiseDeskbar(bool raise)
758 if (raise)
759 Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
760 else
761 Window()->SetFeel(B_NORMAL_WINDOW_FEEL);
765 void
766 TBarView::HideDeskbar(bool hide)
768 BRect screenFrame = (BScreen(Window())).Frame();
770 if (hide) {
771 Hide();
772 PositionWindow(screenFrame);
773 SizeWindow(screenFrame);
774 } else {
775 Show();
776 SizeWindow(screenFrame);
777 PositionWindow(screenFrame);
782 // #pragma mark - Drag and Drop
785 void
786 TBarView::CacheDragData(const BMessage* incoming)
788 if (!incoming)
789 return;
791 if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage))
792 return;
794 // disposes then fills cached drag message and
795 // mimetypes list
796 SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList);
800 static void
801 init_tracking_hook(BMenuItem* item,
802 bool (*hookFunction)(BMenu*, void*), void* state)
804 if (!item)
805 return;
807 BMenu* windowMenu = item->Submenu();
808 if (windowMenu) {
809 // have a menu, set the tracking hook
810 windowMenu->SetTrackingHook(hookFunction, state);
815 status_t
816 TBarView::DragStart()
818 if (!Dragging())
819 return B_OK;
821 BPoint loc;
822 uint32 buttons;
823 GetMouse(&loc, &buttons);
825 if (fExpandoMenuBar != NULL && fExpandoMenuBar->Frame().Contains(loc)) {
826 ConvertToScreen(&loc);
827 BPoint expandoLocation = fExpandoMenuBar->ConvertFromScreen(loc);
828 TTeamMenuItem* item = fExpandoMenuBar->TeamItemAtPoint(expandoLocation);
830 if (fLastDragItem)
831 init_tracking_hook(fLastDragItem, NULL, NULL);
833 if (item != NULL) {
834 if (item == fLastDragItem)
835 return B_OK;
837 fLastDragItem = item;
841 return B_OK;
845 bool
846 TBarView::MenuTrackingHook(BMenu* menu, void* castToThis)
848 // return true if the menu should go away
849 TrackingHookData* data = static_cast<TrackingHookData*>(castToThis);
850 if (!data)
851 return false;
853 TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL));
854 if (!barview || !menu->LockLooper())
855 return false;
857 uint32 buttons;
858 BPoint location;
859 menu->GetMouse(&location, &buttons);
861 bool endMenu = true;
862 BRect frame(menu->Bounds());
863 frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin);
865 if (frame.Contains(location)) {
866 // if current loc is still in the menu
867 // keep tracking
868 endMenu = false;
869 } else {
870 // see if the mouse is in the team/deskbar menu item
871 menu->ConvertToScreen(&location);
872 if (barview->LockLooper()) {
873 TExpandoMenuBar* expando = barview->ExpandoMenuBar();
874 TDeskbarMenu* bemenu
875 = (dynamic_cast<TBarWindow*>(barview->Window()))->DeskbarMenu();
877 if (bemenu && bemenu->LockLooper()) {
878 bemenu->ConvertFromScreen(&location);
879 if (bemenu->Frame().Contains(location))
880 endMenu = false;
882 bemenu->UnlockLooper();
885 if (endMenu && expando) {
886 expando->ConvertFromScreen(&location);
887 BMenuItem* item = expando->TeamItemAtPoint(location);
888 if (item)
889 endMenu = false;
891 barview->UnlockLooper();
895 menu->UnlockLooper();
896 return endMenu;
900 // used by WindowMenu and TeamMenu to
901 // set the tracking hook for dragging
902 TrackingHookData*
903 TBarView::GetTrackingHookData()
905 // all tracking hook data is
906 // preset in AttachedToWindow
907 // data should never change
908 return &fTrackingHookData;
912 void
913 TBarView::DragStop(bool full)
915 if (!Dragging())
916 return;
918 if (fExpandoMenuBar != NULL) {
919 if (fLastDragItem != NULL) {
920 init_tracking_hook(fLastDragItem, NULL, NULL);
921 fLastDragItem = NULL;
925 if (full) {
926 delete fDragMessage;
927 fDragMessage = NULL;
929 delete fCachedTypesList;
930 fCachedTypesList = NULL;
935 bool
936 TBarView::AppCanHandleTypes(const char* signature)
938 // used for filtering apps/teams in the ExpandoMenuBar and TeamMenu
940 if (modifiers() & B_CONTROL_KEY) {
941 // control key forces acceptance, just like drag&drop on icons
942 return true;
945 if (!signature || strlen(signature) == 0
946 || !fCachedTypesList || fCachedTypesList->CountItems() == 0)
947 return false;
949 if (strcasecmp(signature, kTrackerSignature) == 0) {
950 // tracker should support all types
951 // and should pass them on to the appropriate application
952 return true;
955 entry_ref hintref;
956 BMimeType appmime(signature);
957 if (appmime.GetAppHint(&hintref) != B_OK)
958 return false;
960 // an app was found, now see if it supports any of
961 // the refs in the message
962 BFile file(&hintref, O_RDONLY);
963 BAppFileInfo fileinfo(&file);
965 // scan the cached mimetype list and see if this app
966 // supports anything in the list
967 // only one item needs to match in the list of refs
969 int32 count = fCachedTypesList->CountItems();
970 for (int32 i = 0 ; i < count ; i++) {
971 if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String()))
972 return true;
975 return false;
979 void
980 TBarView::SetDragOverride(bool on)
982 fRefsRcvdOnly = on;
986 bool
987 TBarView::DragOverride()
989 return fRefsRcvdOnly;
993 status_t
994 TBarView::SendDragMessage(const char* signature, entry_ref* ref)
996 status_t err = B_ERROR;
997 if (fDragMessage != NULL) {
998 if (fRefsRcvdOnly) {
999 // current message sent to apps is only B_REFS_RECEIVED
1000 fDragMessage->what = B_REFS_RECEIVED;
1003 BRoster roster;
1004 if (signature != NULL && *signature != '\0'
1005 && roster.IsRunning(signature)) {
1006 BMessenger messenger(signature);
1007 // drag message is still owned by DB, copy is sent
1008 // can toss it after send
1009 err = messenger.SendMessage(fDragMessage);
1010 } else if (ref != NULL) {
1011 FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage,
1012 true, true);
1013 } else if (signature != NULL && *signature != '\0')
1014 roster.Launch(signature, fDragMessage);
1017 return err;
1021 bool
1022 TBarView::InvokeItem(const char* signature)
1024 // sent from TeamMenuItem
1025 if (Dragging() && AppCanHandleTypes(signature)) {
1026 SendDragMessage(signature);
1027 // invoking okay to toss memory
1028 DragStop(true);
1029 return true;
1032 return false;
1036 void
1037 TBarView::HandleDeskbarMenu(BMessage* messagewithdestination)
1039 if (!Dragging())
1040 return;
1042 // in mini-mode
1043 if (fVertical && fState != kExpandoState) {
1044 // if drop is in the team menu, bail
1045 if (fBarMenuBar->CountItems() >= 2) {
1046 uint32 buttons;
1047 BPoint location;
1048 GetMouse(&location, &buttons);
1049 if (fBarMenuBar->ItemAt(1)->Frame().Contains(location))
1050 return;
1054 if (messagewithdestination) {
1055 entry_ref ref;
1056 if (messagewithdestination->FindRef("refs", &ref) == B_OK) {
1057 BEntry entry(&ref, true);
1058 if (entry.IsDirectory()) {
1059 // if the ref received (should only be 1) is a directory
1060 // then add the drag refs to the directory
1061 AddRefsToDeskbarMenu(DragMessage(), &ref);
1062 } else
1063 SendDragMessage(NULL, &ref);
1065 } else {
1066 // adds drag refs to top level in deskbar menu
1067 AddRefsToDeskbarMenu(DragMessage(), NULL);
1070 // clean up drag message and types list
1071 DragStop(true);
1075 // #pragma mark - Add-ons
1078 // shelf is ignored for now,
1079 // it exists in anticipation of having other 'shelves' for
1080 // storing items
1082 status_t
1083 TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf)
1085 *shelf = B_DESKBAR_TRAY;
1086 return fReplicantTray->ItemInfo(id, name);
1090 status_t
1091 TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf)
1093 *shelf = B_DESKBAR_TRAY;
1094 return fReplicantTray->ItemInfo(name, id);
1098 bool
1099 TBarView::ItemExists(int32 id, DeskbarShelf)
1101 return fReplicantTray->IconExists(id);
1105 bool
1106 TBarView::ItemExists(const char* name, DeskbarShelf)
1108 return fReplicantTray->IconExists(name);
1112 int32
1113 TBarView::CountItems(DeskbarShelf)
1115 return fReplicantTray->ReplicantCount();
1119 status_t
1120 TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id)
1122 return fReplicantTray->AddIcon(item, id);
1126 status_t
1127 TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id)
1129 return fReplicantTray->LoadAddOn(entry, id);
1133 void
1134 TBarView::RemoveItem(int32 id)
1136 fReplicantTray->RemoveIcon(id);
1140 void
1141 TBarView::RemoveItem(const char* name, DeskbarShelf)
1143 fReplicantTray->RemoveIcon(name);
1147 BRect
1148 TBarView::OffsetIconFrame(BRect rect) const
1150 BRect frame(Frame());
1152 frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left
1153 + rect.left;
1154 frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top
1155 + rect.top;
1157 frame.right = frame.left + rect.Width();
1158 frame.bottom = frame.top + rect.Height();
1160 return frame;
1164 BRect
1165 TBarView::IconFrame(int32 id) const
1167 return OffsetIconFrame(fReplicantTray->IconFrame(id));
1171 BRect
1172 TBarView::IconFrame(const char* name) const
1174 return OffsetIconFrame(fReplicantTray->IconFrame(name));