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