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