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