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 37 #include "BarView.h" 38 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> 48 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" 61 62 63 const int32 kDefaultRecentDocCount = 10; 64 const int32 kDefaultRecentFolderCount = 10; 65 const int32 kDefaultRecentAppCount = 10; 66 67 const int32 kMenuTrackMargin = 20; 68 69 const uint32 kUpdateOrientation = 'UpOr'; 70 const float kSepItemWidth = 5.0f; 71 72 73 class BarViewMessageFilter : public BMessageFilter 74 { 75 public: 76 BarViewMessageFilter(TBarView* barView); 77 virtual ~BarViewMessageFilter(); 78 79 virtual filter_result Filter(BMessage* message, BHandler** target); 80 81 private: 82 TBarView* fBarView; 83 }; 84 85 86 BarViewMessageFilter::BarViewMessageFilter(TBarView* barView) 87 : 88 BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), 89 fBarView(barView) 90 { 91 } 92 93 94 BarViewMessageFilter::~BarViewMessageFilter() 95 { 96 } 97 98 99 filter_result 100 BarViewMessageFilter::Filter(BMessage* message, BHandler** target) 101 { 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); 109 } 110 111 switch (message->what) { 112 case B_MOUSE_DOWN: 113 fBarView->MouseDown(where); 114 break; 115 116 case B_MOUSE_MOVED: 117 fBarView->MouseMoved(where, transit, dragMessage); 118 break; 119 } 120 121 delete dragMessage; 122 } 123 124 return B_DISPATCH_MESSAGE; 125 } 126 127 128 // #pragma mark - TBarView 129 130 131 TBarView::TBarView(BRect frame, bool vertical, bool left, bool top, 132 int32 state, float) 133 : 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) 151 { 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; 158 159 // create and add the Be menu 160 fBarMenuBar = new TBarMenuBar(menuFrame, "BarMenuBar", this); 161 AddChild(fBarMenuBar); 162 163 // create the status tray 164 fReplicantTray = new TReplicantTray(this, fVertical); 165 166 // create the resize control 167 fResizeControl = new TResizeControl(this); 168 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); 174 175 // Add the drag region 176 if (fTrayLocation != 0) 177 AddChild(fDragRegion); 178 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); 184 185 // If mini mode, hide the application menubar 186 if (state == kMiniState) 187 fInlineScrollView->Hide(); 188 } 189 190 191 TBarView::~TBarView() 192 { 193 delete fDragMessage; 194 delete fCachedTypesList; 195 delete fBarMenuBar; 196 } 197 198 199 void 200 TBarView::AttachedToWindow() 201 { 202 BView::AttachedToWindow(); 203 204 SetViewUIColor(B_MENU_BACKGROUND_COLOR); 205 SetFont(be_plain_font); 206 207 fMouseFilter = new BarViewMessageFilter(this); 208 Window()->AddCommonFilter(fMouseFilter); 209 210 fTrackingHookData.fTrackingHook = MenuTrackingHook; 211 fTrackingHookData.fTarget = BMessenger(this); 212 fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED); 213 } 214 215 216 void 217 TBarView::DetachedFromWindow() 218 { 219 Window()->RemoveCommonFilter(fMouseFilter); 220 delete fMouseFilter; 221 fMouseFilter = NULL; 222 delete fTrackingHookData.fDragMessage; 223 fTrackingHookData.fDragMessage = NULL; 224 } 225 226 227 void 228 TBarView::Draw(BRect) 229 { 230 BRect bounds(Bounds()); 231 232 rgb_color hilite = tint_color(ViewColor(), B_DARKEN_1_TINT); 233 234 SetHighColor(hilite); 235 if (AcrossTop()) 236 StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); 237 else if (AcrossBottom()) 238 StrokeLine(bounds.LeftTop(), bounds.RightTop()); 239 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)); 245 } 246 } 247 248 249 void 250 TBarView::MessageReceived(BMessage* message) 251 { 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; 262 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; 268 269 case B_ARCHIVED_OBJECT: 270 { 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; 279 } 280 281 case kUpdateOrientation: 282 { 283 _ChangeState(message); 284 break; 285 } 286 287 default: 288 BView::MessageReceived(message); 289 } 290 } 291 292 293 void 294 TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) 295 { 296 if (fDragRegion->IsDragging()) { 297 fDragRegion->MouseMoved(where, transit, dragMessage); 298 return; 299 } 300 301 if (transit == B_ENTERED_VIEW && EventMask() == 0) 302 SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 303 304 BPoint whereScreen = ConvertToScreen(where); 305 306 desk_settings* settings = fBarApp->Settings(); 307 bool alwaysOnTop = settings->alwaysOnTop; 308 bool autoRaise = settings->autoRaise; 309 bool autoHide = settings->autoHide; 310 311 if (!autoRaise && !autoHide) { 312 if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW) 313 SetEventMask(0); 314 return; 315 } 316 317 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL; 318 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 327 328 if (!alwaysOnTop && autoRaise && !isTopMost) 329 RaiseDeskbar(true); 330 331 if (autoHide && IsHidden()) 332 HideDeskbar(false); 333 } else { 334 TBarWindow* window = (TBarWindow*)Window(); 335 if (window->IsShowingMenu()) 336 return; 337 338 // cursor is not on screen edge 339 BRect preventHideArea = Window()->Frame().InsetByCopy( 340 -kMaxPreventHidingDist, -kMaxPreventHidingDist); 341 342 if (preventHideArea.Contains(whereScreen)) 343 return; 344 345 // cursor to bar distance above threshold 346 if (!alwaysOnTop && autoRaise && isTopMost) { 347 RaiseDeskbar(false); 348 SetEventMask(0); 349 } 350 351 if (autoHide && !IsHidden()) 352 HideDeskbar(true); 353 } 354 } 355 356 357 void 358 TBarView::MouseDown(BPoint where) 359 { 360 BPoint whereScreen = ConvertToScreen(where); 361 362 if (Window()->Frame().Contains(whereScreen)) { 363 Window()->Activate(); 364 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; 370 } 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; 378 379 if (!alwaysOnTop && autoRaise && isTopMost) 380 RaiseDeskbar(false); 381 382 if (autoHide && !IsHidden()) 383 HideDeskbar(true); 384 } 385 } 386 387 388 void 389 TBarView::PlaceDeskbarMenu() 390 { 391 float width = 0; 392 float height = 0; 393 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; 404 } 405 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); 412 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; 428 } 429 loc = Bounds().LeftTop(); 430 } else { 431 // mini mode, DeskbarMenu next to team menu 432 fBarMenuBar->RemoveSeperatorItem(); 433 fBarMenuBar->AddTeamMenu(); 434 } 435 436 fBarMenuBar->SmartResize(width, height); 437 fBarMenuBar->MoveTo(loc); 438 } 439 440 441 void 442 TBarView::PlaceTray(bool vertSwap, bool leftSwap) 443 { 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(); 451 452 if (!fReplicantTray->IsHidden()) 453 fReplicantTray->Hide(); 454 455 return; 456 } 457 458 if (fReplicantTray->IsHidden()) 459 fReplicantTray->Show(); 460 461 if (fTrayLocation != 0) { 462 fReplicantTray->SetMultiRow(fVertical); 463 fReplicantTray->RealignReplicants(); 464 fDragRegion->ResizeToPreferred(); 465 // also resizes replicant tray 466 467 fResizeControl->ResizeTo(kDragWidth, fDragRegion->Bounds().Height() 468 - 2); // make room for top and bottom border 469 470 if (fVertical) { 471 if (fResizeControl->IsHidden()) 472 fResizeControl->Show(); 473 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); 478 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); 484 } 485 486 statusLoc.x = 0; 487 statusLoc.y = fBarMenuBar->Frame().bottom + 1; 488 } else { 489 if (!fResizeControl->IsHidden()) 490 fResizeControl->Hide(); 491 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; 498 } 499 500 fDragRegion->MoveTo(statusLoc); 501 fDragRegion->Invalidate(); 502 503 if (fVertical && fLeft) 504 fResizeControl->MoveTo(fDragRegion->Bounds().right - kDragWidth, 1); 505 else 506 fResizeControl->MoveTo(0, 1); 507 508 fResizeControl->Invalidate(); 509 } 510 } 511 512 513 void 514 TBarView::PlaceApplicationBar() 515 { 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; 525 } 526 527 if (fInlineScrollView->IsHidden()) 528 fInlineScrollView->Show(); 529 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; 543 544 if (fBarMenuBar != NULL) 545 expandoFrame.left = fBarMenuBar->Frame().Width() + 1; 546 547 if (fTrayLocation != 0 && fDragRegion != NULL) { 548 expandoFrame.right = screenFrame.Width() 549 - fDragRegion->Frame().Width() - 1; 550 } else 551 expandoFrame.right = screenFrame.Width(); 552 } 553 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()); 561 562 if (!fVertical) { 563 // Set the max item width based on icon size 564 fExpandoMenuBar->SetMaxItemWidth(); 565 } 566 567 if (fState == kExpandoState) 568 fExpandoMenuBar->BuildItems(); 569 570 SizeWindow(screenFrame); 571 PositionWindow(screenFrame); 572 fExpandoMenuBar->DoLayout(); 573 // force menu to resize 574 CheckForScrolling(); 575 Window()->UpdateIfNeeded(); 576 Invalidate(); 577 } 578 579 580 void 581 TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* height) 582 { 583 float windowHeight = 0; 584 float windowWidth = fBarApp->Settings()->width; 585 bool setToHiddenSize = fBarApp->Settings()->autoHide && IsHidden() 586 && !fDragRegion->IsDragging(); 587 588 if (setToHiddenSize) { 589 windowHeight = kHiddenDimension; 590 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; 608 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(); 615 } 616 } else { 617 // four corners 618 if (fTrayLocation != 0) 619 windowHeight = fDragRegion->Frame().bottom; 620 else 621 windowHeight = fBarMenuBar->Frame().bottom; 622 } 623 } 624 625 *width = windowWidth; 626 *height = windowHeight; 627 } 628 629 630 void 631 TBarView::SizeWindow(BRect screenFrame) 632 { 633 float windowWidth; 634 float windowHeight; 635 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight); 636 Window()->ResizeTo(windowWidth, windowHeight); 637 } 638 639 640 void 641 TBarView::PositionWindow(BRect screenFrame) 642 { 643 float windowWidth; 644 float windowHeight; 645 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight); 646 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; 654 } 655 656 // bottom, full or corners 657 if (!fTop) 658 moveLoc.y = screenFrame.bottom - windowHeight; 659 660 Window()->MoveTo(moveLoc); 661 } 662 663 664 void 665 TBarView::CheckForScrolling() 666 { 667 if (fInlineScrollView != NULL && fExpandoMenuBar != NULL) { 668 if (fExpandoMenuBar->CheckForSizeOverrun()) 669 fInlineScrollView->AttachScrollers(); 670 else 671 fInlineScrollView->DetachScrollers(); 672 } 673 } 674 675 676 void 677 TBarView::SaveSettings() 678 { 679 desk_settings* settings = fBarApp->Settings(); 680 681 settings->vertical = fVertical; 682 settings->left = fLeft; 683 settings->top = fTop; 684 settings->state = fState; 685 686 fReplicantTray->SaveTimeSettings(); 687 } 688 689 690 void 691 TBarView::UpdatePlacement() 692 { 693 ChangeState(fState, fVertical, fLeft, fTop); 694 } 695 696 697 void 698 TBarView::ChangeState(int32 state, bool vertical, bool left, bool top, 699 bool async) 700 { 701 BMessage message(kUpdateOrientation); 702 message.AddInt32("state", state); 703 message.AddBool("vertical", vertical); 704 message.AddBool("left", left); 705 message.AddBool("top", top); 706 707 if (async) 708 BMessenger(this).SendMessage(&message); 709 else 710 _ChangeState(&message); 711 } 712 713 714 void 715 TBarView::_ChangeState(BMessage* message) 716 { 717 int32 state = message->FindInt32("state"); 718 bool vertical = message->FindBool("vertical"); 719 bool left = message->FindBool("left"); 720 bool top = message->FindBool("top"); 721 722 bool vertSwap = (fVertical != vertical); 723 bool leftSwap = (fLeft != left); 724 bool stateChanged = (fState != state); 725 726 fState = state; 727 fVertical = vertical; 728 fLeft = left; 729 fTop = top; 730 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. 735 736 if (vertSwap) { 737 fReplicantTray->fTime->SetOrientation(fVertical); 738 if (fExpandoMenuBar != NULL) { 739 if (fVertical) { 740 fInlineScrollView->SetOrientation(B_VERTICAL); 741 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN); 742 fExpandoMenuBar->StartMonitoringWindows(); 743 } else { 744 fInlineScrollView->SetOrientation(B_HORIZONTAL); 745 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW); 746 fExpandoMenuBar->StopMonitoringWindows(); 747 } 748 } 749 } 750 } 751 752 PlaceDeskbarMenu(); 753 PlaceTray(vertSwap, leftSwap); 754 PlaceApplicationBar(); 755 } 756 757 758 void 759 TBarView::RaiseDeskbar(bool raise) 760 { 761 if (raise) 762 Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 763 else 764 Window()->SetFeel(B_NORMAL_WINDOW_FEEL); 765 } 766 767 768 void 769 TBarView::HideDeskbar(bool hide) 770 { 771 BRect screenFrame = (BScreen(Window())).Frame(); 772 773 if (hide) { 774 Hide(); 775 PositionWindow(screenFrame); 776 SizeWindow(screenFrame); 777 } else { 778 Show(); 779 SizeWindow(screenFrame); 780 PositionWindow(screenFrame); 781 } 782 } 783 784 785 // #pragma mark - Drag and Drop 786 787 788 void 789 TBarView::CacheDragData(const BMessage* incoming) 790 { 791 if (!incoming) 792 return; 793 794 if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage)) 795 return; 796 797 // disposes then fills cached drag message and 798 // mimetypes list 799 SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList); 800 } 801 802 803 static void 804 init_tracking_hook(BMenuItem* item, 805 bool (*hookFunction)(BMenu*, void*), void* state) 806 { 807 if (!item) 808 return; 809 810 BMenu* windowMenu = item->Submenu(); 811 if (windowMenu) { 812 // have a menu, set the tracking hook 813 windowMenu->SetTrackingHook(hookFunction, state); 814 } 815 } 816 817 818 status_t 819 TBarView::DragStart() 820 { 821 if (!Dragging()) 822 return B_OK; 823 824 BPoint loc; 825 uint32 buttons; 826 GetMouse(&loc, &buttons); 827 828 if (fExpandoMenuBar != NULL && fExpandoMenuBar->Frame().Contains(loc)) { 829 ConvertToScreen(&loc); 830 BPoint expandoLocation = fExpandoMenuBar->ConvertFromScreen(loc); 831 TTeamMenuItem* item = fExpandoMenuBar->TeamItemAtPoint(expandoLocation); 832 833 if (fLastDragItem) 834 init_tracking_hook(fLastDragItem, NULL, NULL); 835 836 if (item != NULL) { 837 if (item == fLastDragItem) 838 return B_OK; 839 840 fLastDragItem = item; 841 } 842 } 843 844 return B_OK; 845 } 846 847 848 bool 849 TBarView::MenuTrackingHook(BMenu* menu, void* castToThis) 850 { 851 // return true if the menu should go away 852 TrackingHookData* data = static_cast<TrackingHookData*>(castToThis); 853 if (!data) 854 return false; 855 856 TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL)); 857 if (!barview || !menu->LockLooper()) 858 return false; 859 860 uint32 buttons; 861 BPoint location; 862 menu->GetMouse(&location, &buttons); 863 864 bool endMenu = true; 865 BRect frame(menu->Bounds()); 866 frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin); 867 868 if (frame.Contains(location)) { 869 // if current loc is still in the menu 870 // keep tracking 871 endMenu = false; 872 } else { 873 // see if the mouse is in the team/deskbar menu item 874 menu->ConvertToScreen(&location); 875 if (barview->LockLooper()) { 876 TExpandoMenuBar* expando = barview->ExpandoMenuBar(); 877 TDeskbarMenu* bemenu 878 = (dynamic_cast<TBarWindow*>(barview->Window()))->DeskbarMenu(); 879 880 if (bemenu && bemenu->LockLooper()) { 881 bemenu->ConvertFromScreen(&location); 882 if (bemenu->Frame().Contains(location)) 883 endMenu = false; 884 885 bemenu->UnlockLooper(); 886 } 887 888 if (endMenu && expando) { 889 expando->ConvertFromScreen(&location); 890 BMenuItem* item = expando->TeamItemAtPoint(location); 891 if (item) 892 endMenu = false; 893 } 894 barview->UnlockLooper(); 895 } 896 } 897 898 menu->UnlockLooper(); 899 return endMenu; 900 } 901 902 903 // used by WindowMenu and TeamMenu to 904 // set the tracking hook for dragging 905 TrackingHookData* 906 TBarView::GetTrackingHookData() 907 { 908 // all tracking hook data is 909 // preset in AttachedToWindow 910 // data should never change 911 return &fTrackingHookData; 912 } 913 914 915 void 916 TBarView::DragStop(bool full) 917 { 918 if (!Dragging()) 919 return; 920 921 if (fExpandoMenuBar != NULL) { 922 if (fLastDragItem != NULL) { 923 init_tracking_hook(fLastDragItem, NULL, NULL); 924 fLastDragItem = NULL; 925 } 926 } 927 928 if (full) { 929 delete fDragMessage; 930 fDragMessage = NULL; 931 932 delete fCachedTypesList; 933 fCachedTypesList = NULL; 934 } 935 } 936 937 938 bool 939 TBarView::AppCanHandleTypes(const char* signature) 940 { 941 // used for filtering apps/teams in the ExpandoMenuBar and TeamMenu 942 943 if (modifiers() & B_CONTROL_KEY) { 944 // control key forces acceptance, just like drag&drop on icons 945 return true; 946 } 947 948 if (!signature || strlen(signature) == 0 949 || !fCachedTypesList || fCachedTypesList->CountItems() == 0) 950 return false; 951 952 if (strcasecmp(signature, kTrackerSignature) == 0) { 953 // tracker should support all types 954 // and should pass them on to the appropriate application 955 return true; 956 } 957 958 entry_ref hintref; 959 BMimeType appmime(signature); 960 if (appmime.GetAppHint(&hintref) != B_OK) 961 return false; 962 963 // an app was found, now see if it supports any of 964 // the refs in the message 965 BFile file(&hintref, O_RDONLY); 966 BAppFileInfo fileinfo(&file); 967 968 // scan the cached mimetype list and see if this app 969 // supports anything in the list 970 // only one item needs to match in the list of refs 971 972 int32 count = fCachedTypesList->CountItems(); 973 for (int32 i = 0 ; i < count ; i++) { 974 if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String())) 975 return true; 976 } 977 978 return false; 979 } 980 981 982 void 983 TBarView::SetDragOverride(bool on) 984 { 985 fRefsRcvdOnly = on; 986 } 987 988 989 bool 990 TBarView::DragOverride() 991 { 992 return fRefsRcvdOnly; 993 } 994 995 996 status_t 997 TBarView::SendDragMessage(const char* signature, entry_ref* ref) 998 { 999 status_t err = B_ERROR; 1000 if (fDragMessage != NULL) { 1001 if (fRefsRcvdOnly) { 1002 // current message sent to apps is only B_REFS_RECEIVED 1003 fDragMessage->what = B_REFS_RECEIVED; 1004 } 1005 1006 BRoster roster; 1007 if (signature != NULL && *signature != '\0' 1008 && roster.IsRunning(signature)) { 1009 BMessenger messenger(signature); 1010 // drag message is still owned by DB, copy is sent 1011 // can toss it after send 1012 err = messenger.SendMessage(fDragMessage); 1013 } else if (ref != NULL) { 1014 FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage, 1015 true, true); 1016 } else if (signature != NULL && *signature != '\0') 1017 roster.Launch(signature, fDragMessage); 1018 } 1019 1020 return err; 1021 } 1022 1023 1024 bool 1025 TBarView::InvokeItem(const char* signature) 1026 { 1027 // sent from TeamMenuItem 1028 if (Dragging() && AppCanHandleTypes(signature)) { 1029 SendDragMessage(signature); 1030 // invoking okay to toss memory 1031 DragStop(true); 1032 return true; 1033 } 1034 1035 return false; 1036 } 1037 1038 1039 void 1040 TBarView::HandleDeskbarMenu(BMessage* messagewithdestination) 1041 { 1042 if (!Dragging()) 1043 return; 1044 1045 // in mini-mode 1046 if (fVertical && fState != kExpandoState) { 1047 // if drop is in the team menu, bail 1048 if (fBarMenuBar->CountItems() >= 2) { 1049 uint32 buttons; 1050 BPoint location; 1051 GetMouse(&location, &buttons); 1052 if (fBarMenuBar->ItemAt(1)->Frame().Contains(location)) 1053 return; 1054 } 1055 } 1056 1057 if (messagewithdestination) { 1058 entry_ref ref; 1059 if (messagewithdestination->FindRef("refs", &ref) == B_OK) { 1060 BEntry entry(&ref, true); 1061 if (entry.IsDirectory()) { 1062 // if the ref received (should only be 1) is a directory 1063 // then add the drag refs to the directory 1064 AddRefsToDeskbarMenu(DragMessage(), &ref); 1065 } else 1066 SendDragMessage(NULL, &ref); 1067 } 1068 } else { 1069 // adds drag refs to top level in deskbar menu 1070 AddRefsToDeskbarMenu(DragMessage(), NULL); 1071 } 1072 1073 // clean up drag message and types list 1074 DragStop(true); 1075 } 1076 1077 1078 // #pragma mark - Add-ons 1079 1080 1081 // shelf is ignored for now, 1082 // it exists in anticipation of having other 'shelves' for 1083 // storing items 1084 1085 status_t 1086 TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf) 1087 { 1088 *shelf = B_DESKBAR_TRAY; 1089 return fReplicantTray->ItemInfo(id, name); 1090 } 1091 1092 1093 status_t 1094 TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf) 1095 { 1096 *shelf = B_DESKBAR_TRAY; 1097 return fReplicantTray->ItemInfo(name, id); 1098 } 1099 1100 1101 bool 1102 TBarView::ItemExists(int32 id, DeskbarShelf) 1103 { 1104 return fReplicantTray->IconExists(id); 1105 } 1106 1107 1108 bool 1109 TBarView::ItemExists(const char* name, DeskbarShelf) 1110 { 1111 return fReplicantTray->IconExists(name); 1112 } 1113 1114 1115 int32 1116 TBarView::CountItems(DeskbarShelf) 1117 { 1118 return fReplicantTray->ReplicantCount(); 1119 } 1120 1121 1122 status_t 1123 TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id) 1124 { 1125 return fReplicantTray->AddIcon(item, id); 1126 } 1127 1128 1129 status_t 1130 TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id) 1131 { 1132 return fReplicantTray->LoadAddOn(entry, id); 1133 } 1134 1135 1136 void 1137 TBarView::RemoveItem(int32 id) 1138 { 1139 fReplicantTray->RemoveIcon(id); 1140 } 1141 1142 1143 void 1144 TBarView::RemoveItem(const char* name, DeskbarShelf) 1145 { 1146 fReplicantTray->RemoveIcon(name); 1147 } 1148 1149 1150 BRect 1151 TBarView::OffsetIconFrame(BRect rect) const 1152 { 1153 BRect frame(Frame()); 1154 1155 frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left 1156 + rect.left; 1157 frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top 1158 + rect.top; 1159 1160 frame.right = frame.left + rect.Width(); 1161 frame.bottom = frame.top + rect.Height(); 1162 1163 return frame; 1164 } 1165 1166 1167 BRect 1168 TBarView::IconFrame(int32 id) const 1169 { 1170 return OffsetIconFrame(fReplicantTray->IconFrame(id)); 1171 } 1172 1173 1174 BRect 1175 TBarView::IconFrame(const char* name) const 1176 { 1177 return OffsetIconFrame(fReplicantTray->IconFrame(name)); 1178 } 1179