1 /* 2 * Copyright (c) 1999-2000, Eric Moon. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions, and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 // RouteWindow.cpp 33 // e.moon 14may99 34 35 #include "RouteApp.h" 36 #include "RouteWindow.h" 37 #include "MediaRoutingView.h" 38 #include "StatusView.h" 39 40 #include "DormantNodeWindow.h" 41 #include "TransportWindow.h" 42 43 #include "RouteAppNodeManager.h" 44 #include "NodeGroup.h" 45 #include "TipManager.h" 46 47 #include <Alert.h> 48 #include <Autolock.h> 49 #include <Debug.h> 50 #include <Font.h> 51 #include <MenuBar.h> 52 #include <Menu.h> 53 #include <MenuItem.h> 54 #include <Message.h> 55 #include <Messenger.h> 56 #include <Roster.h> 57 #include <Screen.h> 58 #include <ScrollView.h> 59 #include <StringView.h> 60 61 #include <algorithm> 62 63 #include "debug_tools.h" 64 #define D_HOOK(x) //PRINT (x) 65 #define D_INTERNAL(x) //PRINT (x) 66 67 __USE_CORTEX_NAMESPACE 68 69 70 const char* const RouteWindow::s_windowName = "Cortex"; 71 72 const BRect RouteWindow::s_initFrame(100,100,700,550); 73 74 const char* const g_aboutText = 75 "Cortex/Route 2.1.2\n\n" 76 "Copyright 1999-2000 Eric Moon\n" 77 "All rights reserved.\n\n" 78 "The Cortex Team:\n\n" 79 "Christopher Lenz: UI\n" 80 "Eric Moon: UI, back-end\n\n" 81 "Thanks to:\nJohn Ashmun\nJon Watte\nDoug Wright\n<your name here>\n\n" 82 "Certain icons used herein are the property of\n" 83 "Be, Inc. and are used by permission."; 84 85 86 RouteWindow::~RouteWindow() 87 { 88 } 89 90 91 RouteWindow::RouteWindow(RouteAppNodeManager* manager) 92 : 93 BWindow(s_initFrame, s_windowName, B_DOCUMENT_WINDOW, 0), 94 m_hScrollBar(0), 95 m_vScrollBar(0), 96 m_transportWindow(0), 97 m_dormantNodeWindow(0), 98 m_selectedGroupID(0), 99 m_zoomed(false), 100 m_zooming(false) 101 { 102 BRect b = Bounds(); 103 104 // initialize the menu bar: add all menus that target this window 105 BMenuBar* pMenuBar = new BMenuBar(b, "menuBar"); 106 BMenu* pFileMenu = new BMenu("File"); 107 BMenuItem* item = new BMenuItem("Open" B_UTF8_ELLIPSIS, 108 new BMessage(RouteApp::M_SHOW_OPEN_PANEL), 'O'); 109 item->SetTarget(be_app); 110 pFileMenu->AddItem(item); 111 pFileMenu->AddItem(new BSeparatorItem()); 112 item = new BMenuItem("Save nodes" B_UTF8_ELLIPSIS, 113 new BMessage(RouteApp::M_SHOW_SAVE_PANEL), 'S'); 114 item->SetTarget(be_app); 115 pFileMenu->AddItem(item); 116 pFileMenu->AddItem(new BSeparatorItem()); 117 pFileMenu->AddItem(new BMenuItem("About Cortex/Route" B_UTF8_ELLIPSIS, 118 new BMessage(B_ABOUT_REQUESTED))); 119 pFileMenu->AddItem(new BSeparatorItem()); 120 pFileMenu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); 121 pMenuBar->AddItem(pFileMenu); 122 AddChild(pMenuBar); 123 124 // build the routing view 125 BRect rvBounds = b; 126 rvBounds.top = pMenuBar->Frame().bottom+1; 127 rvBounds.right -= B_V_SCROLL_BAR_WIDTH; 128 rvBounds.bottom -= B_H_SCROLL_BAR_HEIGHT; 129 m_routingView = new MediaRoutingView(manager, rvBounds, "routingView"); 130 131 BRect hsBounds = rvBounds; 132 hsBounds.left = rvBounds.left + 199; 133 hsBounds.top = hsBounds.bottom + 1; 134 hsBounds.right++; 135 hsBounds.bottom = b.bottom + 1; 136 137 m_hScrollBar = new BScrollBar(hsBounds, "hScrollBar", m_routingView, 138 0, 0, B_HORIZONTAL); 139 AddChild(m_hScrollBar); 140 141 BRect vsBounds = rvBounds; 142 vsBounds.left = vsBounds.right + 1; 143 vsBounds.top--; 144 vsBounds.right = b.right + 1; 145 vsBounds.bottom++; 146 147 m_vScrollBar = new BScrollBar(vsBounds, "vScrollBar", m_routingView, 148 0, 0, B_VERTICAL); 149 AddChild(m_vScrollBar); 150 151 BRect svBounds = rvBounds; 152 svBounds.left -= 1; 153 svBounds.right = hsBounds.left - 1; 154 svBounds.top = svBounds.bottom + 1; 155 svBounds.bottom = b.bottom + 1; 156 157 m_statusView = new StatusView(svBounds, manager, m_hScrollBar); 158 AddChild(m_statusView); 159 160 AddChild(m_routingView); 161 162 float minWidth, maxWidth, minHeight, maxHeight; 163 GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); 164 minWidth = m_statusView->Frame().Width() + 6 * B_V_SCROLL_BAR_WIDTH; 165 minHeight = 6 * B_H_SCROLL_BAR_HEIGHT; 166 SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight); 167 168 // construct the Window menu 169 BMenu* windowMenu = new BMenu("Window"); 170 m_transportWindowItem = new BMenuItem( 171 "Show transport", 172 new BMessage(M_TOGGLE_TRANSPORT_WINDOW)); 173 windowMenu->AddItem(m_transportWindowItem); 174 175 m_dormantNodeWindowItem = new BMenuItem( 176 "Show add-ons", 177 new BMessage(M_TOGGLE_DORMANT_NODE_WINDOW)); 178 windowMenu->AddItem(m_dormantNodeWindowItem); 179 180 windowMenu->AddItem(new BSeparatorItem()); 181 182 m_pullPalettesItem = new BMenuItem( 183 "Pull palettes", 184 new BMessage(M_TOGGLE_PULLING_PALETTES)); 185 windowMenu->AddItem(m_pullPalettesItem); 186 187 pMenuBar->AddItem(windowMenu); 188 189 // create the dormant-nodes palette 190 _toggleDormantNodeWindow(); 191 192 // display group inspector 193 _toggleTransportWindow(); 194 } 195 196 197 // #pragma mark - operations 198 199 200 /*! Enable/disable palette position-locking (when the main 201 window is moved, all palettes follow). 202 */ 203 bool 204 RouteWindow::isPullPalettes() const 205 { 206 return m_pullPalettesItem->IsMarked(); 207 } 208 209 210 void 211 RouteWindow::setPullPalettes(bool enabled) 212 { 213 m_pullPalettesItem->SetMarked(enabled); 214 } 215 216 217 void 218 RouteWindow::constrainToScreen() 219 { 220 BScreen screen(this); 221 222 const BRect sr = screen.Frame(); 223 224 // [c.lenz 1mar2000] this should be handled by every window 225 // itself. will probably change soon ;-) 226 _constrainToScreen(); 227 /* // main window 228 BRect r = Frame(); 229 BPoint offset(0.0, 0.0); 230 if(r.left < 0.0) 231 offset.x = -r.left; 232 if(r.top < 0.0) 233 offset.y = -r.top; 234 if(r.left >= (sr.right - 20.0)) 235 offset.x -= (r.left - (sr.Width()/2)); 236 if(r.top >= (sr.bottom - 20.0)) 237 offset.y -= (r.top - (sr.Height()/2)); 238 if(offset.x != 0.0 || offset.y != 0.0) { 239 setPullPalettes(false); 240 MoveBy(offset.x, offset.y); 241 }*/ 242 243 // transport window 244 BPoint offset = BPoint(0.0, 0.0); 245 BRect r = (m_transportWindow) ? 246 m_transportWindow->Frame() : 247 m_transportWindowFrame; 248 if(r.left < 0.0) 249 offset.x = (sr.Width()*.75) - r.left; 250 if(r.top < 0.0) 251 offset.y = (sr.Height()*.25) - r.top; 252 if(r.left >= (sr.right - 20.0)) 253 offset.x -= (r.left - (sr.Width()/2)); 254 if(r.top >= (sr.bottom - 20.0)) 255 offset.y -= (r.top - (sr.Height()/2)); 256 257 if(offset.x != 0.0 || offset.y != 0.0) { 258 if(m_transportWindow) 259 m_transportWindow->MoveBy(offset.x, offset.y); 260 else 261 m_transportWindowFrame.OffsetBy(offset.x, offset.y); 262 } 263 264 // addon palette 265 offset = BPoint(0.0, 0.0); 266 r = (m_dormantNodeWindow) ? 267 m_dormantNodeWindow->Frame() : 268 m_dormantNodeWindowFrame; 269 if(r.left < 0.0) 270 offset.x = (sr.Width()*.25) - r.left; 271 if(r.top < 0.0) 272 offset.y = (sr.Height()*.125) - r.top; 273 if(r.left >= (sr.right - 20.0)) 274 offset.x -= (r.left - (sr.Width()/2)); 275 if(r.top >= (sr.bottom - 20.0)) 276 offset.y -= (r.top - (sr.Height()/2)); 277 278 if(offset.x != 0.0 || offset.y != 0.0) { 279 if(m_dormantNodeWindow) 280 m_dormantNodeWindow->MoveBy(offset.x, offset.y); 281 else 282 m_dormantNodeWindowFrame.OffsetBy(offset.x, offset.y); 283 } 284 285 } 286 287 288 // #pragma mark - BWindow implementation 289 290 291 void 292 RouteWindow::FrameMoved(BPoint point) 293 { 294 // ignore notification if the window isn't yet visible 295 if(IsHidden()) 296 return; 297 298 BPoint delta = point - m_lastFramePosition; 299 m_lastFramePosition = point; 300 301 302 if (m_pullPalettesItem->IsMarked()) 303 _movePalettesBy(delta.x, delta.y); 304 } 305 306 307 void 308 RouteWindow::FrameResized(float width, float height) 309 { 310 D_HOOK(("RouteWindow::FrameResized()\n")); 311 312 if (!m_zooming) { 313 m_zoomed = false; 314 } 315 else { 316 m_zooming = false; 317 } 318 } 319 320 321 bool 322 RouteWindow::QuitRequested() 323 { 324 be_app->PostMessage(B_QUIT_REQUESTED); 325 return false; // [e.moon 20oct99] app now quits window 326 } 327 328 329 void 330 RouteWindow::Zoom(BPoint origin, float width, float height) 331 { 332 D_HOOK(("RouteWindow::Zoom()\n")); 333 334 m_zooming = true; 335 336 BScreen screen(this); 337 if (!screen.Frame().Contains(Frame())) { 338 m_zoomed = false; 339 } 340 341 if (!m_zoomed) { 342 // resize to the ideal size 343 m_manualSize = Bounds(); 344 float width, height; 345 m_routingView->GetPreferredSize(&width, &height); 346 width += B_V_SCROLL_BAR_WIDTH; 347 height += B_H_SCROLL_BAR_HEIGHT; 348 if (KeyMenuBar()) { 349 height += KeyMenuBar()->Frame().Height(); 350 } 351 ResizeTo(width, height); 352 _constrainToScreen(); 353 m_zoomed = true; 354 } 355 else { 356 // resize to the most recent manual size 357 ResizeTo(m_manualSize.Width(), m_manualSize.Height()); 358 m_zoomed = false; 359 } 360 } 361 362 363 // #pragma mark - BHandler implemenation 364 365 366 void 367 RouteWindow::MessageReceived(BMessage* pMsg) 368 { 369 // PRINT(( 370 // "RouteWindow::MessageReceived()\n")); 371 // pMsg->PrintToStream(); 372 // 373 switch (pMsg->what) { 374 case B_ABOUT_REQUESTED: 375 { 376 BAlert* alert = new BAlert("About", g_aboutText, "OK"); 377 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 378 alert->Go(); 379 break; 380 } 381 case MediaRoutingView::M_GROUP_SELECTED: 382 _handleGroupSelected(pMsg); 383 break; 384 385 case MediaRoutingView::M_SHOW_ERROR_MESSAGE: 386 _handleShowErrorMessage(pMsg); 387 break; 388 389 case M_TOGGLE_TRANSPORT_WINDOW: 390 _toggleTransportWindow(); 391 break; 392 393 case M_REFRESH_TRANSPORT_SETTINGS: 394 _refreshTransportSettings(pMsg); 395 break; 396 397 case M_TOGGLE_PULLING_PALETTES: 398 _togglePullPalettes(); 399 break; 400 401 case M_TOGGLE_DORMANT_NODE_WINDOW: 402 _toggleDormantNodeWindow(); 403 break; 404 405 case M_TOGGLE_GROUP_ROLLING: 406 _toggleGroupRolling(); 407 break; 408 409 default: 410 _inherited::MessageReceived(pMsg); 411 break; 412 } 413 } 414 415 416 // #pragma mark - IStateArchivable 417 418 419 status_t 420 RouteWindow::importState(const BMessage* archive) 421 { 422 status_t err; 423 424 // frame rect 425 BRect r; 426 err = archive->FindRect("frame", &r); 427 if(err == B_OK) { 428 MoveTo(r.LeftTop()); 429 ResizeTo(r.Width(), r.Height()); 430 m_lastFramePosition = r.LeftTop(); 431 } 432 433 // status view width 434 int32 i; 435 err = archive->FindInt32("statusViewWidth", &i); 436 if (err == B_OK) { 437 float diff = i - m_statusView->Bounds().IntegerWidth(); 438 m_statusView->ResizeBy(diff, 0.0); 439 m_hScrollBar->ResizeBy(-diff, 0.0); 440 m_hScrollBar->MoveBy(diff, 0.0); 441 } 442 443 // settings 444 bool b; 445 err = archive->FindBool("pullPalettes", &b); 446 if(err == B_OK) 447 m_pullPalettesItem->SetMarked(b); 448 449 // const char* p; 450 // err = archive->FindString("saveDir", &p); 451 // if(err == B_OK) { 452 // m_openPanel.SetPanelDirectory(p); 453 // m_savePanel.SetPanelDirectory(p); 454 // } 455 // 456 // dormant-node window 457 err = archive->FindRect("addonPaletteFrame", &r); 458 if (err == B_OK) 459 m_dormantNodeWindowFrame = r; 460 err = archive->FindBool("addonPaletteVisible", &b); 461 if (err == B_OK && (b != (m_dormantNodeWindow != 0))) { 462 _toggleDormantNodeWindow(); 463 if(!m_dormantNodeWindow) 464 m_dormantNodeWindowFrame = r; 465 } 466 467 if (m_dormantNodeWindow) { 468 m_dormantNodeWindow->MoveTo(m_dormantNodeWindowFrame.LeftTop()); 469 m_dormantNodeWindow->ResizeTo( 470 m_dormantNodeWindowFrame.Width(), 471 m_dormantNodeWindowFrame.Height()); 472 } 473 474 // transport window 475 err = archive->FindRect("transportFrame", &r); 476 if (err == B_OK) 477 m_transportWindowFrame = r; 478 err = archive->FindBool("transportVisible", &b); 479 if (err == B_OK && (b != (m_transportWindow != 0))) { 480 _toggleTransportWindow(); 481 if (!m_transportWindow) 482 m_transportWindowFrame = r; 483 } 484 485 if (m_transportWindow) { 486 m_transportWindow->MoveTo(m_transportWindowFrame.LeftTop()); 487 m_transportWindow->ResizeTo( 488 m_transportWindowFrame.Width(), 489 m_transportWindowFrame.Height()); 490 } 491 492 return B_OK; 493 } 494 495 496 status_t 497 RouteWindow::exportState(BMessage* archive) const 498 { 499 BRect r = Frame(); 500 archive->AddRect("frame", r); 501 archive->AddBool("pullPalettes", m_pullPalettesItem->IsMarked()); 502 503 bool b = (m_dormantNodeWindow != 0); 504 r = b ? m_dormantNodeWindow->Frame() : m_dormantNodeWindowFrame; 505 archive->AddRect("addonPaletteFrame", r); 506 archive->AddBool("addonPaletteVisible", b); 507 508 b = (m_transportWindow != 0); 509 r = b ? m_transportWindow->Frame() : m_transportWindowFrame; 510 511 archive->AddRect("transportFrame", r); 512 archive->AddBool("transportVisible", b); 513 514 // [c.lenz 23may00] remember status view width 515 int i = m_statusView->Bounds().IntegerWidth(); 516 archive->AddInt32("statusViewWidth", i); 517 518 // entry_ref saveRef; 519 // m_savePanel.GetPanelDirectory(&saveRef); 520 // BEntry saveEntry(&saveRef); 521 // if(saveEntry.InitCheck() == B_OK) { 522 // BPath p; 523 // saveEntry.GetPath(&p); 524 // archive->AddString("saveDir", p.Path()); 525 // } 526 527 return B_OK; 528 } 529 530 531 // #pragma mark - implementation 532 533 534 void 535 RouteWindow::_constrainToScreen() 536 { 537 D_INTERNAL(("RouteWindow::_constrainToScreen()\n")); 538 539 BScreen screen(this); 540 BRect screenRect = screen.Frame(); 541 BRect windowRect = Frame(); 542 543 // if the window is outside the screen rect 544 // move it to the default position 545 if (!screenRect.Intersects(windowRect)) { 546 windowRect.OffsetTo(screenRect.LeftTop()); 547 MoveTo(windowRect.LeftTop()); 548 windowRect = Frame(); 549 } 550 551 // if the window is larger than the screen rect 552 // resize it to fit at each side 553 if (!screenRect.Contains(windowRect)) { 554 if (windowRect.left < screenRect.left) { 555 windowRect.left = screenRect.left + 5.0; 556 MoveTo(windowRect.LeftTop()); 557 windowRect = Frame(); 558 } 559 if (windowRect.top < screenRect.top) { 560 windowRect.top = screenRect.top + 5.0; 561 MoveTo(windowRect.LeftTop()); 562 windowRect = Frame(); 563 } 564 if (windowRect.right > screenRect.right) { 565 windowRect.right = screenRect.right - 5.0; 566 } 567 if (windowRect.bottom > screenRect.bottom) { 568 windowRect.bottom = screenRect.bottom - 5.0; 569 } 570 ResizeTo(windowRect.Width(), windowRect.Height()); 571 } 572 } 573 574 575 void 576 RouteWindow::_toggleTransportWindow() 577 { 578 if (m_transportWindow) { 579 m_transportWindowFrame = m_transportWindow->Frame(); 580 m_transportWindow->Lock(); 581 m_transportWindow->Quit(); 582 m_transportWindow = 0; 583 m_transportWindowItem->SetMarked(false); 584 } else { 585 m_transportWindow = new TransportWindow(m_routingView->manager, 586 this, "Transport"); 587 588 // ask for a selection update 589 BMessenger(m_routingView).SendMessage( 590 MediaRoutingView::M_BROADCAST_SELECTION); 591 592 // place & display the window 593 if (m_transportWindowFrame.IsValid()) { 594 m_transportWindow->MoveTo(m_transportWindowFrame.LeftTop()); 595 m_transportWindow->ResizeTo(m_transportWindowFrame.Width(), 596 m_transportWindowFrame.Height()); 597 } 598 599 m_transportWindow->Show(); 600 m_transportWindowItem->SetMarked(true); 601 } 602 } 603 604 605 void 606 RouteWindow::_togglePullPalettes() 607 { 608 m_pullPalettesItem->SetMarked(!m_pullPalettesItem->IsMarked()); 609 } 610 611 612 void 613 RouteWindow::_toggleDormantNodeWindow() 614 { 615 if (m_dormantNodeWindow) { 616 m_dormantNodeWindowFrame = m_dormantNodeWindow->Frame(); 617 m_dormantNodeWindow->Lock(); 618 m_dormantNodeWindow->Quit(); 619 m_dormantNodeWindow = 0; 620 m_dormantNodeWindowItem->SetMarked(false); 621 } else { 622 m_dormantNodeWindow = new DormantNodeWindow(this); 623 if (m_dormantNodeWindowFrame.IsValid()) { 624 m_dormantNodeWindow->MoveTo(m_dormantNodeWindowFrame.LeftTop()); 625 m_dormantNodeWindow->ResizeTo(m_dormantNodeWindowFrame.Width(), 626 m_dormantNodeWindowFrame.Height()); 627 } 628 m_dormantNodeWindow->Show(); 629 m_dormantNodeWindowItem->SetMarked(true); 630 } 631 } 632 633 634 void 635 RouteWindow::_handleGroupSelected(BMessage* message) 636 { 637 status_t err; 638 uint32 groupID; 639 640 err = message->FindInt32("groupID", (int32*)&groupID); 641 if (err < B_OK) { 642 PRINT(( 643 "! RouteWindow::_handleGroupSelected(): no groupID in message!\n")); 644 return; 645 } 646 647 if (!m_transportWindow) 648 return; 649 650 BMessage m(TransportWindow::M_SELECT_GROUP); 651 m.AddInt32("groupID", groupID); 652 BMessenger(m_transportWindow).SendMessage(&m); 653 654 m_selectedGroupID = groupID; 655 } 656 657 658 void 659 RouteWindow::_handleShowErrorMessage(BMessage* message) 660 { 661 status_t err; 662 BString text; 663 664 err = message->FindString("text", &text); 665 if (err < B_OK) { 666 PRINT(( 667 "! RouteWindow::_handleShowErrorMessage(): no text in message!\n")); 668 return; 669 } 670 671 m_statusView->setErrorMessage(text.String(), message->HasBool("error")); 672 } 673 674 675 //! Refresh the transport window for the given group, if any 676 void 677 RouteWindow::_refreshTransportSettings(BMessage* message) 678 { 679 status_t err; 680 uint32 groupID; 681 682 err = message->FindInt32("groupID", (int32*)&groupID); 683 if (err < B_OK) { 684 PRINT(( 685 "! RouteWindow::_refreshTransportSettings(): no groupID in message!\n")); 686 return; 687 } 688 689 if(m_transportWindow) { 690 // relay the message 691 BMessenger(m_transportWindow).SendMessage(message); 692 } 693 } 694 695 696 void 697 RouteWindow::_closePalettes() 698 { 699 BAutolock _l(this); 700 701 if (m_transportWindow) { 702 m_transportWindow->Lock(); 703 m_transportWindow->Quit(); 704 m_transportWindow = 0; 705 } 706 } 707 708 709 //! Move all palette windows by the specified amounts 710 void RouteWindow::_movePalettesBy(float xDelta, float yDelta) 711 { 712 if (m_transportWindow) 713 m_transportWindow->MoveBy(xDelta, yDelta); 714 715 if (m_dormantNodeWindow) 716 m_dormantNodeWindow->MoveBy(xDelta, yDelta); 717 } 718 719 720 //! Toggle group playback 721 void 722 RouteWindow::_toggleGroupRolling() 723 { 724 if (!m_selectedGroupID) 725 return; 726 727 NodeGroup* g; 728 status_t err = m_routingView->manager->findGroup(m_selectedGroupID, &g); 729 if (err < B_OK) 730 return; 731 732 Autolock _l(g); 733 uint32 startAction = (g->runMode() == BMediaNode::B_OFFLINE) 734 ? NodeGroup::M_ROLL : NodeGroup::M_START; 735 736 BMessenger m(g); 737 switch (g->transportState()) { 738 case NodeGroup::TRANSPORT_STOPPED: 739 m.SendMessage(startAction); 740 break; 741 742 case NodeGroup::TRANSPORT_RUNNING: 743 case NodeGroup::TRANSPORT_ROLLING: 744 m.SendMessage(NodeGroup::M_STOP); 745 break; 746 747 default: 748 break; 749 } 750 } 751