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