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