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