1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered 30 trademarks of Be Incorporated in the United States and other countries. Other 31 brand product names are registered trademarks or trademarks of their respective 32 holders. 33 All rights reserved. 34 */ 35 36 #include <Debug.h> 37 38 #include "BarView.h" 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include <AppFileInfo.h> 45 #include <Bitmap.h> 46 #include <Directory.h> 47 #include <NodeInfo.h> 48 #include <Roster.h> 49 #include <Screen.h> 50 #include <String.h> 51 52 #include "icons.h" 53 #include "BarApp.h" 54 #include "BarMenuBar.h" 55 #include "BarWindow.h" 56 #include "DeskbarMenu.h" 57 #include "DeskbarUtils.h" 58 #include "ExpandoMenuBar.h" 59 #include "FSUtils.h" 60 #include "ResourceSet.h" 61 #include "StatusView.h" 62 #include "TeamMenuItem.h" 63 64 65 const int32 kDefaultRecentDocCount = 10; 66 const int32 kDefaultRecentFolderCount = 10; 67 const int32 kDefaultRecentAppCount = 10; 68 69 const int32 kMenuTrackMargin = 20; 70 71 TBarView::TBarView(BRect frame, bool vertical, bool left, bool top, 72 bool showInterval, uint32 state, float, bool showTime) 73 : BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), 74 fBarMenuBar(NULL), 75 fExpando(NULL), 76 fTrayLocation(1), 77 fShowInterval(showInterval), 78 fShowClock(showTime), 79 fVertical(vertical), 80 fTop(top), 81 fLeft(left), 82 fState(static_cast<int32>(state)), 83 fRefsRcvdOnly(true), 84 fDragMessage(NULL), 85 fCachedTypesList(NULL), 86 fMaxRecentDocs(kDefaultRecentDocCount), 87 fMaxRecentApps(kDefaultRecentAppCount), 88 fLastDragItem(NULL) 89 { 90 fReplicantTray = new TReplicantTray(this, fVertical); 91 fDragRegion = new TDragRegion(this, fReplicantTray); 92 fDragRegion->AddChild(fReplicantTray); 93 if (fTrayLocation != 0) 94 AddChild(fDragRegion); 95 } 96 97 98 TBarView::~TBarView() 99 { 100 delete fDragMessage; 101 delete fCachedTypesList; 102 } 103 104 105 void 106 TBarView::AttachedToWindow() 107 { 108 BView::AttachedToWindow(); 109 110 SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR)); 111 SetFont(be_plain_font); 112 113 UpdateEventMask(); 114 UpdatePlacement(); 115 116 fTrackingHookData.fTrackingHook = MenuTrackingHook; 117 fTrackingHookData.fTarget = BMessenger(this); 118 fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED); 119 } 120 121 122 void 123 TBarView::DetachedFromWindow() 124 { 125 delete fTrackingHookData.fDragMessage; 126 fTrackingHookData.fDragMessage = NULL; 127 } 128 129 130 void 131 TBarView::Draw(BRect) 132 { 133 BRect bounds(Bounds()); 134 135 rgb_color hilite = tint_color(ViewColor(), B_DARKEN_1_TINT); 136 rgb_color light = tint_color(ViewColor(), B_LIGHTEN_2_TINT); 137 138 SetHighColor(hilite); 139 if (AcrossTop()) 140 StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); 141 else if (AcrossBottom()) 142 StrokeLine(bounds.LeftTop(), bounds.RightTop()); 143 144 if (Vertical() && Expando()) { 145 SetHighColor(hilite); 146 BRect frame(fExpando->Frame()); 147 StrokeLine(BPoint(frame.left, frame.top - 1), 148 BPoint(frame.right, frame.top -1)); 149 } 150 } 151 152 153 void 154 TBarView::MessageReceived(BMessage* message) 155 { 156 switch (message->what) { 157 case B_REFS_RECEIVED: 158 // received when an item is selected during DnD 159 // message is targeted here from Be menu 160 HandleDeskbarMenu(message); 161 break; 162 163 case B_ARCHIVED_OBJECT: 164 { 165 // this message has been retargeted to here 166 // instead of directly to the replicant tray 167 // so that I can follow the common pathway 168 // for adding icons to the tray 169 int32 id; 170 AddItem(new BMessage(*message), B_DESKBAR_TRAY, &id); 171 break; 172 } 173 174 default: 175 BView::MessageReceived(message); 176 } 177 } 178 179 180 void 181 TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) 182 { 183 if (Window() == NULL || EventMask() == 0) 184 return; 185 186 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 187 bool alwaysOnTop = settings->alwaysOnTop; 188 bool autoRaise = settings->autoRaise; 189 bool autoHide = settings->autoHide; 190 191 if (!autoRaise && !autoHide) 192 return; 193 194 if (DragRegion()->IsDragging()) 195 return; 196 197 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL; 198 199 // Auto-Raise 200 where = ConvertToScreen(where); 201 BScreen screen(Window()); 202 BRect screenFrame = screen.Frame(); 203 if ((where.x == screenFrame.left || where.x == screenFrame.right 204 || where.y == screenFrame.top || where.y == screenFrame.bottom) 205 && Window()->Frame().Contains(where)) { 206 // cursor is on a screen edge within the window frame 207 208 if (!alwaysOnTop && autoRaise && !isTopMost) 209 RaiseDeskbar(true); 210 211 if (autoHide && IsHidden()) 212 HideDeskbar(false); 213 } else { 214 // cursor is not on screen edge 215 BRect preventHideArea = Window()->Frame().InsetByCopy( 216 -kMaxPreventHidingDist, -kMaxPreventHidingDist); 217 218 if (preventHideArea.Contains(where)) 219 return; 220 221 // cursor to bar distance above threshold 222 if (!alwaysOnTop && autoRaise && isTopMost) 223 RaiseDeskbar(false); 224 225 if (autoHide && !IsHidden()) 226 HideDeskbar(true); 227 } 228 } 229 230 231 void 232 TBarView::MouseDown(BPoint where) 233 { 234 where = ConvertToScreen(where); 235 236 if (Window()->Frame().Contains(where)) { 237 Window()->Activate(); 238 239 if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY 240 | B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) { 241 // The window key was pressed - enter dragging code 242 DragRegion()->MouseDown( 243 DragRegion()->DragRegion().LeftTop()); 244 return; 245 } 246 } else { 247 // hide deskbar if required 248 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 249 bool alwaysOnTop = settings->alwaysOnTop; 250 bool autoRaise = settings->autoRaise; 251 bool autoHide = settings->autoHide; 252 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL; 253 254 if (!alwaysOnTop && autoRaise && isTopMost) 255 RaiseDeskbar(false); 256 257 if (autoHide && !IsHidden()) 258 HideDeskbar(true); 259 } 260 } 261 262 263 void 264 TBarView::PlaceDeskbarMenu() 265 { 266 // top or bottom, full 267 if (!fVertical && fBarMenuBar) { 268 fBarMenuBar->RemoveSelf(); 269 delete fBarMenuBar; 270 fBarMenuBar = NULL; 271 } 272 273 // top or bottom expando mode has Be menu built in for tracking 274 // only for vertical mini or expanded 275 // mini mode will have team menu added as part of BarMenuBar 276 if (fVertical && !fBarMenuBar) { 277 // create the Be menu 278 BRect mbarFrame(Bounds()); 279 mbarFrame.bottom = mbarFrame.top + kMenuBarHeight; 280 fBarMenuBar = new TBarMenuBar(this, mbarFrame, "BarMenuBar"); 281 AddChild(fBarMenuBar); 282 } 283 284 // if there isn't a bemenu at this point, 285 // DB should be in top/bottom mode, else error 286 if (!fBarMenuBar) 287 return; 288 289 float width = sMinimumWindowWidth; 290 BPoint loc(B_ORIGIN); 291 BRect menuFrame(fBarMenuBar->Frame()); 292 if (fState == kFullState) { 293 fBarMenuBar->RemoveTeamMenu(); 294 width = 8 + 16 + 8; 295 loc = Bounds().LeftTop(); 296 } else if (fState == kExpandoState) { 297 // shows apps below tray 298 fBarMenuBar->RemoveTeamMenu(); 299 if (fVertical) 300 width += 1; 301 else 302 width = floorf(width) / 2; 303 loc = Bounds().LeftTop(); 304 } else { 305 // mini mode, DeskbarMenu next to team menu 306 fBarMenuBar->AddTeamMenu(); 307 } 308 309 fBarMenuBar->SmartResize(width, menuFrame.Height()); 310 fBarMenuBar->MoveTo(loc); 311 } 312 313 314 void 315 TBarView::PlaceTray(bool, bool, BRect screenFrame) 316 { 317 BPoint statusLoc; 318 if (fState == kFullState) { 319 fDragRegion->ResizeTo(fBarMenuBar->Frame().Width(), kMenuBarHeight); 320 statusLoc.y = fBarMenuBar->Frame().bottom + 1; 321 statusLoc.x = 0; 322 fDragRegion->MoveTo(statusLoc); 323 324 if (!fReplicantTray->IsHidden()) 325 fReplicantTray->Hide(); 326 327 return; 328 } 329 330 if (fReplicantTray->IsHidden()) 331 fReplicantTray->Show(); 332 333 if (fTrayLocation != 0) { 334 fReplicantTray->SetMultiRow(fVertical); 335 fReplicantTray->RealignReplicants(); 336 fDragRegion->ResizeToPreferred(); 337 338 if (fVertical) { 339 statusLoc.y = fBarMenuBar->Frame().bottom + 1; 340 statusLoc.x = 0; 341 if (Left() && Vertical()) 342 fReplicantTray->MoveTo(5, 2); 343 else 344 fReplicantTray->MoveTo(2, 2); 345 } else { 346 statusLoc.x = screenFrame.right - fDragRegion->Bounds().Width(); 347 statusLoc.y = -1; 348 } 349 350 fDragRegion->MoveTo(statusLoc); 351 } 352 } 353 354 355 void 356 TBarView::PlaceApplicationBar(BRect screenFrame) 357 { 358 if (fExpando != NULL) { 359 fExpando->RemoveSelf(); 360 delete fExpando; 361 fExpando = NULL; 362 } 363 if (fState == kMiniState) 364 return; 365 366 BRect expandoFrame(0, 0, 0, 0); 367 if (fVertical) { 368 // top left/right 369 if (fTrayLocation != 0) 370 expandoFrame.top = fDragRegion->Frame().bottom + 1; 371 else 372 expandoFrame.top = fBarMenuBar->Frame().bottom + 1; 373 374 expandoFrame.bottom = expandoFrame.top + 1; 375 if (fState == kFullState) 376 expandoFrame.right = fBarMenuBar->Frame().Width(); 377 else 378 expandoFrame.right = sMinimumWindowWidth; 379 } else { 380 // top or bottom 381 expandoFrame.top = 0; 382 expandoFrame.bottom = kHModeHeight; 383 if (fTrayLocation != 0) 384 expandoFrame.right = fDragRegion->Frame().left - 1; 385 else 386 expandoFrame.right = screenFrame.Width(); 387 } 388 389 fExpando = new TExpandoMenuBar(this, expandoFrame, "ExpandoMenuBar", 390 fVertical, fState != kFullState); 391 AddChild(fExpando); 392 } 393 394 395 void 396 TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* height) 397 { 398 float windowHeight = 0; 399 float windowWidth = sMinimumWindowWidth; 400 bool calcHiddenSize = ((TBarApp*)be_app)->Settings()->autoHide 401 && IsHidden() && !DragRegion()->IsDragging(); 402 403 if (!calcHiddenSize) { 404 if (fState == kFullState) { 405 windowHeight = screenFrame.bottom; 406 windowWidth = fBarMenuBar->Frame().Width(); 407 } else if (fState == kExpandoState) { 408 if (fVertical) 409 // top left or right 410 windowHeight = fExpando->Frame().bottom; 411 else { 412 // top or bottom, full 413 fExpando->CheckItemSizes(0); 414 windowHeight = kHModeHeight; 415 windowWidth = screenFrame.Width(); 416 } 417 } else { 418 // four corners 419 if (fTrayLocation != 0) 420 windowHeight = fDragRegion->Frame().bottom; 421 else 422 windowHeight = fBarMenuBar->Frame().bottom; 423 } 424 } else { 425 windowHeight = kHModeHiddenHeight; 426 427 if (fState == kExpandoState && !fVertical) { 428 // top or bottom, full 429 fExpando->CheckItemSizes(0); 430 windowWidth = screenFrame.Width(); 431 } else 432 windowWidth = kHModeHiddenHeight; 433 } 434 435 *width = windowWidth; 436 *height = windowHeight; 437 } 438 439 440 void 441 TBarView::SizeWindow(BRect screenFrame) 442 { 443 float windowWidth, windowHeight; 444 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight); 445 Window()->ResizeTo(windowWidth, windowHeight); 446 if (fExpando) 447 fExpando->CheckForSizeOverrun(); 448 } 449 450 451 void 452 TBarView::PositionWindow(BRect screenFrame) 453 { 454 float windowWidth, windowHeight; 455 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight); 456 457 BPoint moveLoc(0, 0); 458 // right, expanded 459 if (!fLeft && fVertical) { 460 if (fState == kFullState) 461 moveLoc.x = screenFrame.right - fBarMenuBar->Frame().Width(); 462 else 463 moveLoc.x = screenFrame.right - windowWidth; 464 } 465 466 // bottom, full or corners 467 if (!fTop) 468 moveLoc.y = screenFrame.bottom - windowHeight; 469 470 Window()->MoveTo(moveLoc); 471 } 472 473 474 void 475 TBarView::SaveSettings() 476 { 477 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 478 479 settings->vertical = Vertical(); 480 settings->left = Left(); 481 settings->top = Top(); 482 settings->ampmMode = MilTime(); 483 settings->state = (uint32)State(); 484 settings->width = 0; 485 settings->showTime = ShowingClock(); 486 487 fReplicantTray->RememberClockSettings(); 488 } 489 490 491 void 492 TBarView::UpdateEventMask() 493 { 494 if (((TBarApp*)be_app)->Settings()->autoRaise 495 || ((TBarApp*)be_app)->Settings()->autoHide) 496 SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 497 else 498 SetEventMask(0); 499 } 500 501 502 void 503 TBarView::UpdatePlacement() 504 { 505 ChangeState(fState, fVertical, fLeft, fTop); 506 } 507 508 509 void 510 TBarView::ChangeState(int32 state, bool vertical, bool left, bool top) 511 { 512 bool vertSwap = (fVertical != vertical); 513 bool leftSwap = (fLeft != left); 514 bool stateChanged = (fState != state); 515 516 fState = state; 517 fVertical = vertical; 518 fLeft = left; 519 fTop = top; 520 521 // Send a message to the preferences window to let it know to enable 522 // or disable preference items 523 if (stateChanged || vertSwap) 524 be_app->PostMessage(kStateChanged); 525 526 BRect screenFrame = (BScreen(Window())).Frame(); 527 528 PlaceDeskbarMenu(); 529 PlaceTray(vertSwap, leftSwap, screenFrame); 530 531 // We need to keep track of what apps are expanded. 532 BList expandedItems; 533 BString* signature = NULL; 534 if (fVertical && Expando() 535 && static_cast<TBarApp*>(be_app)->Settings()->superExpando) { 536 // Get a list of the signatures of expanded apps. Can't use 537 // team_id because there can be more than one team per application 538 if (fVertical && Expando() && vertical && fExpando) { 539 for (int index = 0; index < fExpando->CountItems(); index++) { 540 TTeamMenuItem* item 541 = dynamic_cast<TTeamMenuItem*>(fExpando->ItemAt(index)); 542 if (item != NULL && item->IsExpanded()) { 543 signature = new BString(item->Signature()); 544 expandedItems.AddItem((void*)signature); 545 } 546 } 547 } 548 } 549 550 PlaceApplicationBar(screenFrame); 551 SizeWindow(screenFrame); 552 PositionWindow(screenFrame); 553 Window()->UpdateIfNeeded(); 554 555 // Re-expand those apps. 556 if (expandedItems.CountItems() > 0) { 557 for (int sigIndex = expandedItems.CountItems(); sigIndex-- > 0;) { 558 signature = static_cast<BString*>(expandedItems.ItemAt(sigIndex)); 559 if (signature == NULL) 560 continue; 561 562 // Start at the 'bottom' of the list working up. 563 // Prevents being thrown off by expanding items. 564 for (int teamIndex = fExpando->CountItems(); teamIndex-- > 0;) { 565 TTeamMenuItem* item 566 = dynamic_cast<TTeamMenuItem*>(fExpando->ItemAt(teamIndex)); 567 if (item != NULL && !signature->Compare(item->Signature())) { 568 item->ToggleExpandState(false); 569 break; 570 } 571 } 572 } 573 574 // Clean up expanded signature list. 575 while (!expandedItems.IsEmpty()) { 576 delete static_cast<BString*>(expandedItems.RemoveItem((int32)0)); 577 } 578 579 fExpando->SizeWindow(); 580 } 581 582 Invalidate(); 583 } 584 585 586 void 587 TBarView::RaiseDeskbar(bool raise) 588 { 589 if (raise) 590 Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 591 else 592 Window()->SetFeel(B_NORMAL_WINDOW_FEEL); 593 } 594 595 596 void 597 TBarView::HideDeskbar(bool hide) 598 { 599 BScreen screen(Window()); 600 BRect screenFrame = screen.Frame(); 601 602 if (hide) { 603 Hide(); 604 PositionWindow(screenFrame); 605 SizeWindow(screenFrame); 606 } else { 607 Show(); 608 SizeWindow(screenFrame); 609 PositionWindow(screenFrame); 610 } 611 } 612 613 614 // window placement functions 615 616 bool 617 TBarView::Vertical() const 618 { 619 return fVertical; 620 } 621 622 623 bool 624 TBarView::Left() const 625 { 626 return fLeft; 627 } 628 629 630 bool 631 TBarView::AcrossTop() const 632 { 633 return fTop && !fVertical; 634 } 635 636 637 bool 638 TBarView::AcrossBottom() const 639 { 640 return !fTop && !fVertical; 641 } 642 643 644 bool 645 TBarView::Expando() const 646 { 647 return fState == kExpandoState; 648 } 649 650 651 bool 652 TBarView::Top() const 653 { 654 return fTop; 655 } 656 657 658 int32 659 TBarView::State() const 660 { 661 return fState; 662 } 663 664 665 // optional functionality functions 666 667 bool 668 TBarView::MilTime() const 669 { 670 return fShowInterval; 671 } 672 673 674 void 675 TBarView::ShowClock(bool on) 676 { 677 fShowClock = on; 678 } 679 680 681 bool 682 TBarView::ShowingClock() const 683 { 684 return fShowClock; 685 } 686 687 688 // #pragma mark - Drag and Drop 689 690 691 void 692 TBarView::CacheDragData(const BMessage* incoming) 693 { 694 if (!incoming) 695 return; 696 697 if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage)) 698 return; 699 700 // disposes then fills cached drag message and 701 // mimetypes list 702 SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList); 703 } 704 705 706 static void 707 init_tracking_hook(BMenuItem* item, 708 bool (*hookFunction)(BMenu*, void*), void* state) 709 { 710 if (!item) 711 return; 712 713 BMenu* windowMenu = item->Submenu(); 714 if (windowMenu) { 715 // have a menu, set the tracking hook 716 windowMenu->SetTrackingHook(hookFunction, state); 717 } 718 } 719 720 721 status_t 722 TBarView::DragStart() 723 { 724 if (!Dragging()) 725 return B_OK; 726 727 BPoint loc; 728 uint32 buttons; 729 GetMouse(&loc, &buttons); 730 731 if (fExpando && fExpando->Frame().Contains(loc)) { 732 ConvertToScreen(&loc); 733 BPoint expandoLocation = fExpando->ConvertFromScreen(loc); 734 TTeamMenuItem* item = fExpando->TeamItemAtPoint(expandoLocation); 735 736 if (fLastDragItem) 737 init_tracking_hook(fLastDragItem, NULL, NULL); 738 739 if (item) { 740 if (item == fLastDragItem) 741 return B_OK; 742 743 fLastDragItem = item; 744 } 745 } 746 747 return B_OK; 748 } 749 750 751 bool 752 TBarView::MenuTrackingHook(BMenu* menu, void* castToThis) 753 { 754 // return true if the menu should go away 755 TrackingHookData* data = static_cast<TrackingHookData*>(castToThis); 756 if (!data) 757 return false; 758 759 TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL)); 760 if (!barview || !menu->LockLooper()) 761 return false; 762 763 uint32 buttons; 764 BPoint location; 765 menu->GetMouse(&location, &buttons); 766 767 bool endMenu = true; 768 BRect frame(menu->Bounds()); 769 frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin); 770 771 if (frame.Contains(location)) { 772 // if current loc is still in the menu 773 // keep tracking 774 endMenu = false; 775 } else { 776 // see if the mouse is in the team/deskbar menu item 777 menu->ConvertToScreen(&location); 778 if (barview->LockLooper()) { 779 TExpandoMenuBar* expando = barview->ExpandoMenuBar(); 780 TDeskbarMenu* bemenu 781 = (dynamic_cast<TBarWindow*>(barview->Window()))->DeskbarMenu(); 782 783 if (bemenu && bemenu->LockLooper()) { 784 bemenu->ConvertFromScreen(&location); 785 if (bemenu->Frame().Contains(location)) 786 endMenu = false; 787 788 bemenu->UnlockLooper(); 789 } 790 791 if (endMenu && expando) { 792 expando->ConvertFromScreen(&location); 793 BMenuItem* item = expando->TeamItemAtPoint(location); 794 if (item) 795 endMenu = false; 796 } 797 barview->UnlockLooper(); 798 } 799 } 800 801 menu->UnlockLooper(); 802 return endMenu; 803 } 804 805 806 // used by WindowMenu and TeamMenu to 807 // set the tracking hook for dragging 808 TrackingHookData* 809 TBarView::GetTrackingHookData() 810 { 811 // all tracking hook data is 812 // preset in AttachedToWindow 813 // data should never change 814 return &fTrackingHookData; 815 } 816 817 818 void 819 TBarView::DragStop(bool full) 820 { 821 if (!Dragging()) 822 return; 823 824 if (fExpando) { 825 if (fLastDragItem) { 826 init_tracking_hook(fLastDragItem, NULL, NULL); 827 fLastDragItem = NULL; 828 } 829 } 830 831 if (full) { 832 delete fDragMessage; 833 fDragMessage = NULL; 834 835 delete fCachedTypesList; 836 fCachedTypesList = NULL; 837 } 838 } 839 840 841 bool 842 TBarView::AppCanHandleTypes(const char* signature) 843 { 844 // used for filtering apps/teams in the ExpandoMenuBar and TeamMenu 845 846 if (modifiers() & B_CONTROL_KEY) { 847 // control key forces acceptance, just like drag&drop on icons 848 return true; 849 } 850 851 if (!signature || strlen(signature) == 0 852 || !fCachedTypesList || fCachedTypesList->CountItems() == 0) 853 return false; 854 855 if (strcmp(signature, kTrackerSignature) == 0) { 856 // tracker should support all types 857 // and should pass them on to the appropriate application 858 return true; 859 } 860 861 entry_ref hintref; 862 BMimeType appmime(signature); 863 if (appmime.GetAppHint(&hintref) != B_OK) 864 return false; 865 866 // an app was found, now see if it supports any of 867 // the refs in the message 868 BFile file(&hintref, O_RDONLY); 869 BAppFileInfo fileinfo(&file); 870 871 // scan the cached mimetype list and see if this app 872 // supports anything in the list 873 // only one item needs to match in the list of refs 874 875 int32 count = fCachedTypesList->CountItems(); 876 for (int32 i = 0 ; i < count ; i++) { 877 if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String())) 878 return true; 879 } 880 881 return false; 882 } 883 884 885 void 886 TBarView::SetDragOverride(bool on) 887 { 888 fRefsRcvdOnly = on; 889 } 890 891 892 bool 893 TBarView::DragOverride() 894 { 895 return fRefsRcvdOnly; 896 } 897 898 899 status_t 900 TBarView::SendDragMessage(const char* signature, entry_ref* ref) 901 { 902 status_t err = B_ERROR; 903 if (fDragMessage) { 904 if (fRefsRcvdOnly) { 905 // current message sent to apps is only B_REFS_RECEIVED 906 fDragMessage->what = B_REFS_RECEIVED; 907 } 908 909 BRoster roster; 910 if (signature && strlen(signature) > 0 && roster.IsRunning(signature)) { 911 BMessenger mess(signature); 912 // drag message is still owned by DB, copy is sent 913 // can toss it after send 914 err = mess.SendMessage(fDragMessage); 915 } else if (ref) { 916 FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage, 917 true, true); 918 } else if (signature && strlen(signature) > 0) { 919 roster.Launch(signature, fDragMessage); 920 } 921 } 922 return err; 923 } 924 925 926 bool 927 TBarView::InvokeItem(const char* signature) 928 { 929 // sent from TeamMenuItem 930 if (Dragging() && AppCanHandleTypes(signature)) { 931 SendDragMessage(signature); 932 // invoking okay to toss memory 933 DragStop(true); 934 return true; 935 } 936 937 return false; 938 } 939 940 941 void 942 TBarView::HandleDeskbarMenu(BMessage* messagewithdestination) 943 { 944 if (!Dragging()) 945 return; 946 947 // in mini-mode 948 if (Vertical() && !Expando()) { 949 // if drop is in the team menu, bail 950 if (fBarMenuBar->CountItems() >= 2) { 951 uint32 buttons; 952 BPoint location; 953 GetMouse(&location, &buttons); 954 if (fBarMenuBar->ItemAt(1)->Frame().Contains(location)) 955 return; 956 } 957 } 958 959 if (messagewithdestination) { 960 entry_ref ref; 961 if (messagewithdestination->FindRef("refs", &ref) == B_OK) { 962 BEntry entry(&ref, true); 963 if (entry.IsDirectory()) { 964 // if the ref received (should only be 1) is a directory 965 // then add the drag refs to the directory 966 AddRefsToDeskbarMenu(DragMessage(), &ref); 967 } else 968 SendDragMessage(NULL, &ref); 969 } 970 } else { 971 // adds drag refs to top level in deskbar menu 972 AddRefsToDeskbarMenu(DragMessage(), NULL); 973 } 974 975 // clean up drag message and types list 976 DragStop(true); 977 } 978 979 980 // #pragma mark - Add-ons 981 982 983 // shelf is ignored for now, 984 // it exists in anticipation of having other 'shelves' for 985 // storing items 986 987 status_t 988 TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf) 989 { 990 *shelf = B_DESKBAR_TRAY; 991 return fReplicantTray->ItemInfo(id, name); 992 } 993 994 995 status_t 996 TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf) 997 { 998 *shelf = B_DESKBAR_TRAY; 999 return fReplicantTray->ItemInfo(name, id); 1000 } 1001 1002 1003 bool 1004 TBarView::ItemExists(int32 id, DeskbarShelf) 1005 { 1006 return fReplicantTray->IconExists(id); 1007 } 1008 1009 1010 bool 1011 TBarView::ItemExists(const char* name, DeskbarShelf) 1012 { 1013 return fReplicantTray->IconExists(name); 1014 } 1015 1016 1017 int32 1018 TBarView::CountItems(DeskbarShelf) 1019 { 1020 return fReplicantTray->IconCount(); 1021 } 1022 1023 1024 status_t 1025 TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id) 1026 { 1027 return fReplicantTray->AddIcon(item, id); 1028 } 1029 1030 1031 void 1032 TBarView::RemoveItem(int32 id) 1033 { 1034 fReplicantTray->RemoveIcon(id); 1035 } 1036 1037 1038 void 1039 TBarView::RemoveItem(const char* name, DeskbarShelf) 1040 { 1041 fReplicantTray->RemoveIcon(name); 1042 } 1043 1044 1045 BRect 1046 TBarView::OffsetIconFrame(BRect rect) const 1047 { 1048 BRect frame(Frame()); 1049 frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left 1050 + rect.left; 1051 frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top 1052 + rect.top; 1053 1054 frame.right = frame.left + rect.Width(); 1055 frame.bottom = frame.top + rect.Height(); 1056 1057 return frame; 1058 } 1059 1060 1061 BRect 1062 TBarView::IconFrame(int32 id) const 1063 { 1064 return OffsetIconFrame(fReplicantTray->IconFrame(id)); 1065 } 1066 1067 1068 BRect 1069 TBarView::IconFrame(const char* name) const 1070 { 1071 return OffsetIconFrame(fReplicantTray->IconFrame(name)); 1072 } 1073 1074