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 fReplicantTray->fTime->SetOrientation(fVertical); 737 if (fExpandoMenuBar != NULL) { 738 if (fVertical) { 739 fInlineScrollView->SetOrientation(B_VERTICAL); 740 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN); 741 fExpandoMenuBar->StartMonitoringWindows(); 742 } else { 743 fInlineScrollView->SetOrientation(B_HORIZONTAL); 744 fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW); 745 fExpandoMenuBar->StopMonitoringWindows(); 746 } 747 } 748 } 749 } 750 751 PlaceDeskbarMenu(); 752 PlaceTray(vertSwap, leftSwap); 753 PlaceApplicationBar(); 754 } 755 756 757 void 758 TBarView::RaiseDeskbar(bool raise) 759 { 760 if (raise) 761 Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 762 else 763 Window()->SetFeel(B_NORMAL_WINDOW_FEEL); 764 } 765 766 767 void 768 TBarView::HideDeskbar(bool hide) 769 { 770 BRect screenFrame = (BScreen(Window())).Frame(); 771 772 if (hide) { 773 Hide(); 774 PositionWindow(screenFrame); 775 SizeWindow(screenFrame); 776 } else { 777 Show(); 778 SizeWindow(screenFrame); 779 PositionWindow(screenFrame); 780 } 781 } 782 783 784 // #pragma mark - Drag and Drop 785 786 787 void 788 TBarView::CacheDragData(const BMessage* incoming) 789 { 790 if (!incoming) 791 return; 792 793 if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage)) 794 return; 795 796 // disposes then fills cached drag message and 797 // mimetypes list 798 SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList); 799 } 800 801 802 static void 803 init_tracking_hook(BMenuItem* item, 804 bool (*hookFunction)(BMenu*, void*), void* state) 805 { 806 if (!item) 807 return; 808 809 BMenu* windowMenu = item->Submenu(); 810 if (windowMenu) { 811 // have a menu, set the tracking hook 812 windowMenu->SetTrackingHook(hookFunction, state); 813 } 814 } 815 816 817 status_t 818 TBarView::DragStart() 819 { 820 if (!Dragging()) 821 return B_OK; 822 823 BPoint loc; 824 uint32 buttons; 825 GetMouse(&loc, &buttons); 826 827 if (fExpandoMenuBar != NULL && fExpandoMenuBar->Frame().Contains(loc)) { 828 ConvertToScreen(&loc); 829 BPoint expandoLocation = fExpandoMenuBar->ConvertFromScreen(loc); 830 TTeamMenuItem* item = fExpandoMenuBar->TeamItemAtPoint(expandoLocation); 831 832 if (fLastDragItem) 833 init_tracking_hook(fLastDragItem, NULL, NULL); 834 835 if (item != NULL) { 836 if (item == fLastDragItem) 837 return B_OK; 838 839 fLastDragItem = item; 840 } 841 } 842 843 return B_OK; 844 } 845 846 847 bool 848 TBarView::MenuTrackingHook(BMenu* menu, void* castToThis) 849 { 850 // return true if the menu should go away 851 TrackingHookData* data = static_cast<TrackingHookData*>(castToThis); 852 if (!data) 853 return false; 854 855 TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL)); 856 if (!barview || !menu->LockLooper()) 857 return false; 858 859 uint32 buttons; 860 BPoint location; 861 menu->GetMouse(&location, &buttons); 862 863 bool endMenu = true; 864 BRect frame(menu->Bounds()); 865 frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin); 866 867 if (frame.Contains(location)) { 868 // if current loc is still in the menu 869 // keep tracking 870 endMenu = false; 871 } else { 872 // see if the mouse is in the team/deskbar menu item 873 menu->ConvertToScreen(&location); 874 if (barview->LockLooper()) { 875 TExpandoMenuBar* expando = barview->ExpandoMenuBar(); 876 TDeskbarMenu* bemenu 877 = (dynamic_cast<TBarWindow*>(barview->Window()))->DeskbarMenu(); 878 879 if (bemenu && bemenu->LockLooper()) { 880 bemenu->ConvertFromScreen(&location); 881 if (bemenu->Frame().Contains(location)) 882 endMenu = false; 883 884 bemenu->UnlockLooper(); 885 } 886 887 if (endMenu && expando) { 888 expando->ConvertFromScreen(&location); 889 BMenuItem* item = expando->TeamItemAtPoint(location); 890 if (item) 891 endMenu = false; 892 } 893 barview->UnlockLooper(); 894 } 895 } 896 897 menu->UnlockLooper(); 898 return endMenu; 899 } 900 901 902 // used by WindowMenu and TeamMenu to 903 // set the tracking hook for dragging 904 TrackingHookData* 905 TBarView::GetTrackingHookData() 906 { 907 // all tracking hook data is 908 // preset in AttachedToWindow 909 // data should never change 910 return &fTrackingHookData; 911 } 912 913 914 void 915 TBarView::DragStop(bool full) 916 { 917 if (!Dragging()) 918 return; 919 920 if (fExpandoMenuBar != NULL) { 921 if (fLastDragItem != NULL) { 922 init_tracking_hook(fLastDragItem, NULL, NULL); 923 fLastDragItem = NULL; 924 } 925 } 926 927 if (full) { 928 delete fDragMessage; 929 fDragMessage = NULL; 930 931 delete fCachedTypesList; 932 fCachedTypesList = NULL; 933 } 934 } 935 936 937 bool 938 TBarView::AppCanHandleTypes(const char* signature) 939 { 940 // used for filtering apps/teams in the ExpandoMenuBar and TeamMenu 941 942 if (modifiers() & B_CONTROL_KEY) { 943 // control key forces acceptance, just like drag&drop on icons 944 return true; 945 } 946 947 if (!signature || strlen(signature) == 0 948 || !fCachedTypesList || fCachedTypesList->CountItems() == 0) 949 return false; 950 951 if (strcasecmp(signature, kTrackerSignature) == 0) { 952 // tracker should support all types 953 // and should pass them on to the appropriate application 954 return true; 955 } 956 957 entry_ref hintref; 958 BMimeType appmime(signature); 959 if (appmime.GetAppHint(&hintref) != B_OK) 960 return false; 961 962 // an app was found, now see if it supports any of 963 // the refs in the message 964 BFile file(&hintref, O_RDONLY); 965 BAppFileInfo fileinfo(&file); 966 967 // scan the cached mimetype list and see if this app 968 // supports anything in the list 969 // only one item needs to match in the list of refs 970 971 int32 count = fCachedTypesList->CountItems(); 972 for (int32 i = 0 ; i < count ; i++) { 973 if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String())) 974 return true; 975 } 976 977 return false; 978 } 979 980 981 void 982 TBarView::SetDragOverride(bool on) 983 { 984 fRefsRcvdOnly = on; 985 } 986 987 988 bool 989 TBarView::DragOverride() 990 { 991 return fRefsRcvdOnly; 992 } 993 994 995 status_t 996 TBarView::SendDragMessage(const char* signature, entry_ref* ref) 997 { 998 status_t err = B_ERROR; 999 if (fDragMessage != NULL) { 1000 if (fRefsRcvdOnly) { 1001 // current message sent to apps is only B_REFS_RECEIVED 1002 fDragMessage->what = B_REFS_RECEIVED; 1003 } 1004 1005 BRoster roster; 1006 if (signature != NULL && *signature != '\0' 1007 && roster.IsRunning(signature)) { 1008 BMessenger messenger(signature); 1009 // drag message is still owned by DB, copy is sent 1010 // can toss it after send 1011 err = messenger.SendMessage(fDragMessage); 1012 } else if (ref != NULL) { 1013 FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage, 1014 true, true); 1015 } else if (signature != NULL && *signature != '\0') 1016 roster.Launch(signature, fDragMessage); 1017 } 1018 1019 return err; 1020 } 1021 1022 1023 bool 1024 TBarView::InvokeItem(const char* signature) 1025 { 1026 // sent from TeamMenuItem 1027 if (Dragging() && AppCanHandleTypes(signature)) { 1028 SendDragMessage(signature); 1029 // invoking okay to toss memory 1030 DragStop(true); 1031 return true; 1032 } 1033 1034 return false; 1035 } 1036 1037 1038 void 1039 TBarView::HandleDeskbarMenu(BMessage* messagewithdestination) 1040 { 1041 if (!Dragging()) 1042 return; 1043 1044 // in mini-mode 1045 if (fVertical && fState != kExpandoState) { 1046 // if drop is in the team menu, bail 1047 if (fBarMenuBar->CountItems() >= 2) { 1048 uint32 buttons; 1049 BPoint location; 1050 GetMouse(&location, &buttons); 1051 if (fBarMenuBar->ItemAt(1)->Frame().Contains(location)) 1052 return; 1053 } 1054 } 1055 1056 if (messagewithdestination) { 1057 entry_ref ref; 1058 if (messagewithdestination->FindRef("refs", &ref) == B_OK) { 1059 BEntry entry(&ref, true); 1060 if (entry.IsDirectory()) { 1061 // if the ref received (should only be 1) is a directory 1062 // then add the drag refs to the directory 1063 AddRefsToDeskbarMenu(DragMessage(), &ref); 1064 } else 1065 SendDragMessage(NULL, &ref); 1066 } 1067 } else { 1068 // adds drag refs to top level in deskbar menu 1069 AddRefsToDeskbarMenu(DragMessage(), NULL); 1070 } 1071 1072 // clean up drag message and types list 1073 DragStop(true); 1074 } 1075 1076 1077 // #pragma mark - Add-ons 1078 1079 1080 // shelf is ignored for now, 1081 // it exists in anticipation of having other 'shelves' for 1082 // storing items 1083 1084 status_t 1085 TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf) 1086 { 1087 *shelf = B_DESKBAR_TRAY; 1088 return fReplicantTray->ItemInfo(id, name); 1089 } 1090 1091 1092 status_t 1093 TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf) 1094 { 1095 *shelf = B_DESKBAR_TRAY; 1096 return fReplicantTray->ItemInfo(name, id); 1097 } 1098 1099 1100 bool 1101 TBarView::ItemExists(int32 id, DeskbarShelf) 1102 { 1103 return fReplicantTray->IconExists(id); 1104 } 1105 1106 1107 bool 1108 TBarView::ItemExists(const char* name, DeskbarShelf) 1109 { 1110 return fReplicantTray->IconExists(name); 1111 } 1112 1113 1114 int32 1115 TBarView::CountItems(DeskbarShelf) 1116 { 1117 return fReplicantTray->ReplicantCount(); 1118 } 1119 1120 1121 BSize 1122 TBarView::MaxItemSize(DeskbarShelf shelf) 1123 { 1124 return BSize(fReplicantTray->MaxReplicantWidth(), 1125 fReplicantTray->MaxReplicantHeight()); 1126 } 1127 1128 1129 status_t 1130 TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id) 1131 { 1132 return fReplicantTray->AddIcon(item, id); 1133 } 1134 1135 1136 status_t 1137 TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id) 1138 { 1139 return fReplicantTray->LoadAddOn(entry, id); 1140 } 1141 1142 1143 void 1144 TBarView::RemoveItem(int32 id) 1145 { 1146 fReplicantTray->RemoveIcon(id); 1147 } 1148 1149 1150 void 1151 TBarView::RemoveItem(const char* name, DeskbarShelf) 1152 { 1153 fReplicantTray->RemoveIcon(name); 1154 } 1155 1156 1157 BRect 1158 TBarView::OffsetIconFrame(BRect rect) const 1159 { 1160 BRect frame(Frame()); 1161 1162 frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left 1163 + rect.left; 1164 frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top 1165 + rect.top; 1166 1167 frame.right = frame.left + rect.Width(); 1168 frame.bottom = frame.top + rect.Height(); 1169 1170 return frame; 1171 } 1172 1173 1174 BRect 1175 TBarView::IconFrame(int32 id) const 1176 { 1177 return OffsetIconFrame(fReplicantTray->IconFrame(id)); 1178 } 1179 1180 1181 BRect 1182 TBarView::IconFrame(const char* name) const 1183 { 1184 return OffsetIconFrame(fReplicantTray->IconFrame(name)); 1185 } 1186