xref: /haiku/src/apps/cortex/MediaRoutingView/MediaJack.cpp (revision 3af8011358bd4c624a0979336d48dabb466171ed)
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 // MediaJack.cpp
33 // c.lenz 10oct99
34 
35 #include "MediaJack.h"
36 // MediaRoutingView
37 #include "MediaRoutingDefs.h"
38 #include "MediaRoutingView.h"
39 #include "MediaWire.h"
40 // InfoWindow
41 #include "InfoWindowManager.h"
42 // Support
43 #include "cortex_ui.h"
44 #include "MediaString.h"
45 // TipManager
46 #include "TipManager.h"
47 
48 // Application Kit
49 #include <Application.h>
50 // Interface Kit
51 #include <Bitmap.h>
52 #include <MenuItem.h>
53 #include <PopUpMenu.h>
54 // Locale Kit
55 #undef B_CATALOG
56 #define B_CATALOG (&sCatalog)
57 #include <Catalog.h>
58 
59 #undef B_TRANSLATION_CONTEXT
60 #define B_TRANSLATION_CONTEXT "MediaJack"
61 
62 __USE_CORTEX_NAMESPACE
63 
64 #include <Debug.h>
65 #define D_METHOD(x) //PRINT (x)
66 #define D_DRAW(x) //PRINT (x)
67 #define D_MOUSE(x) //PRINT (x)
68 
69 static BCatalog sCatalog("x-vnd.Cortex.MediaRoutingView");
70 
71 // -------------------------------------------------------- //
72 // constants
73 // -------------------------------------------------------- //
74 
75 float MediaJack::M_DEFAULT_WIDTH				= 5.0;
76 float MediaJack::M_DEFAULT_HEIGHT				= 10.0;
77 const float MediaJack::M_DEFAULT_GAP			= 5.0;
78 const int32 MediaJack::M_MAX_ABBR_LENGTH		= 3;
79 
80 // -------------------------------------------------------- //
81 // *** ctor/dtor
82 // -------------------------------------------------------- //
83 
84 MediaJack::MediaJack(
85 	media_input input)
86 	: DiagramEndPoint(BRect(0.0, 0.0, M_DEFAULT_WIDTH, M_DEFAULT_HEIGHT)),
87 	  m_jackType(M_INPUT),
88 	  m_bitmap(0),
89 	  m_index(input.destination.id),
90 	  m_node(input.node),
91 	  m_source(input.source),
92 	  m_destination(input.destination),
93 	  m_format(input.format),
94 	  m_label(input.name),
95 	  m_abbreviation("")
96 {
97 	D_METHOD(("MediaJack::MediaJack()\n"));
98 	makeSelectable(false);
99 	if (m_label == "")
100 		m_label = B_TRANSLATE("Input");
101 	_updateAbbreviation();
102 }
103 
104 MediaJack::MediaJack(
105 	media_output output)
106 	: DiagramEndPoint(BRect(0.0, 0.0, M_DEFAULT_WIDTH, M_DEFAULT_HEIGHT)),
107 	  m_jackType(M_OUTPUT),
108 	  m_bitmap(0),
109 	  m_index(output.source.id),
110 	  m_node(output.node),
111 	  m_source(output.source),
112 	  m_destination(output.destination),
113 	  m_format(output.format),
114 	  m_label(output.name),
115 	  m_abbreviation("")
116 {
117 	D_METHOD(("MediaJack::MediaJack()\n"));
118 	makeSelectable(false);
119 	if (m_label == "")
120 		m_label = B_TRANSLATE("Output");
121 	_updateAbbreviation();
122 }
123 
124 MediaJack::~MediaJack()
125 {
126 	D_METHOD(("MediaJack::~MediaJack()\n"));
127 	delete m_bitmap;
128 }
129 
130 // -------------------------------------------------------- //
131 // *** accessors
132 // -------------------------------------------------------- //
133 
134 status_t MediaJack::getInput(
135 	media_input *input) const
136 {
137 	D_METHOD(("MediaJack::getInput()\n"));
138 	if (isInput())
139 	{
140 		input->node = m_node;
141 		input->source = m_source;
142 		input->destination = m_destination;
143 		input->format = m_format;
144 		strlcpy(input->name, m_label.String(), B_MEDIA_NAME_LENGTH);
145 		return B_OK;
146 	}
147 	return B_ERROR;
148 }
149 
150 status_t MediaJack::getOutput(
151 	media_output *output) const
152 {
153 	D_METHOD(("MediaJack::getOutput()\n"));
154 	if (isOutput())
155 	{
156 		output->node = m_node;
157 		output->source = m_source;
158 		output->destination = m_destination;
159 		output->format = m_format;
160 		strlcpy(output->name, m_label.String(), B_MEDIA_NAME_LENGTH);
161 		return B_OK;
162 	}
163 	return B_ERROR;
164 }
165 
166 // -------------------------------------------------------- //
167 // *** derived from DiagramEndPoint (public)
168 // -------------------------------------------------------- //
169 
170 void MediaJack::attachedToDiagram()
171 {
172 	D_METHOD(("MediaJack::attachedToDiagram()\n"));
173 	_updateBitmap();
174 }
175 
176 void MediaJack::detachedFromDiagram()
177 {
178 	D_METHOD(("MediaJack::detachedFromDiagram()\n"));
179 
180 	// make sure we're no longer displaying a tooltip
181 	TipManager *tips = TipManager::Instance();
182 	tips->hideTip(view()->ConvertToScreen(Frame()));
183 }
184 
185 void MediaJack::drawEndPoint()
186 {
187 	D_DRAW(("MediaJack::drawEndPoint()\n"));
188 
189 	if (m_bitmap)
190 	{
191 		view()->DrawBitmap(m_bitmap, Frame().LeftTop());
192 	}
193 }
194 
195 BPoint MediaJack::connectionPoint() const
196 {
197 	D_METHOD(("MediaJack::connectionPoint()\n"));
198 
199 	switch (dynamic_cast<MediaRoutingView *>(view())->getLayout())
200 	{
201 		case MediaRoutingView::M_ICON_VIEW:
202 		{
203 			if (isInput())
204 			{
205 				return BPoint(Frame().left - 1.0, Frame().top + Frame().Height() / 2.0);
206 			}
207 			else if (isOutput())
208 			{
209 				return BPoint(Frame().right + 1.0, Frame().top + Frame().Height() / 2.0);
210 			}
211 			break;
212 		}
213 		case MediaRoutingView::M_MINI_ICON_VIEW:
214 		{
215 			if (isInput())
216 			{
217 				return BPoint(Frame().left + Frame().Width() / 2.0, Frame().top - 1.0);
218 			}
219 			else if (isOutput())
220 			{
221 				return BPoint(Frame().left + Frame().Width() / 2.0, Frame().bottom + 1.0);
222 			}
223 			break;
224 		}
225 	}
226 	return BPoint(-1.0, -1.0);
227 }
228 
229 bool MediaJack::connectionRequested(
230 	DiagramEndPoint *which)
231 {
232 	D_METHOD(("MediaJack::connectionRequested()\n"));
233 
234 	MediaJack *otherJack = dynamic_cast<MediaJack *>(which);
235 	if (otherJack && (otherJack->m_jackType != m_jackType) && !isConnected())
236 	{
237 		return true;
238 	}
239 	return false;
240 }
241 
242 void MediaJack::MouseDown(
243 	BPoint point,
244 	uint32 buttons,
245 	uint32 clicks)
246 {
247 	D_MOUSE(("MediaJack::MouseOver()\n"));
248 
249 	// if connected, redirect to the wire
250 	if (isConnected())
251 	{
252 		dynamic_cast<MediaWire *>(wire())->MouseDown(point, buttons, clicks);
253 		return;
254 	}
255 
256 	// else we handle the mouse event ourselves
257 	switch (buttons)
258 	{
259 		case B_SECONDARY_MOUSE_BUTTON:
260 		{
261 			showContextMenu(point);
262 			break;
263 		}
264 		default:
265 		{
266 			DiagramEndPoint::MouseDown(point, buttons, clicks);
267 		}
268 	}
269 }
270 
271 void MediaJack::MouseOver(
272 	BPoint point,
273 	uint32 transit)
274 {
275 	D_MOUSE(("MediaJack::MouseOver()\n"));
276 	switch (transit)
277 	{
278 		case B_ENTERED_VIEW:
279 		{
280 			be_app->SetCursor(M_CABLE_CURSOR);
281 			TipManager *tips = TipManager::Instance();
282 			BString tipText = m_label.String();
283 			tipText << " (" << MediaString::getStringFor(m_format.type) << ")";
284 			tips->showTip(tipText.String(),view()->ConvertToScreen(Frame()),
285 						  TipManager::LEFT_OFFSET_FROM_POINTER, BPoint(12.0, 8.0));
286 			break;
287 		}
288 		case B_EXITED_VIEW:
289 		{
290 			if (!view()->isWireTracking())
291 			{
292 				be_app->SetCursor(B_HAND_CURSOR);
293 			}
294 			break;
295 		}
296 	}
297 }
298 
299 void MediaJack::MessageDragged(
300 	BPoint point,
301 	uint32 transit,
302 	const BMessage *message)
303 {
304 	D_MOUSE(("MediaJack::MessageDragged()\n"));
305 	switch (transit)
306 	{
307 		case B_ENTERED_VIEW:
308 		{
309 			be_app->SetCursor(M_CABLE_CURSOR);
310 			break;
311 		}
312 		case B_EXITED_VIEW:
313 		{
314 			if (!view()->isWireTracking())
315 			{
316 				be_app->SetCursor(B_HAND_CURSOR);
317 			}
318 			break;
319 		}
320 	}
321 	DiagramEndPoint::MessageDragged(point, transit, message);
322 }
323 
324 void MediaJack::selected()
325 {
326 	D_METHOD(("MediaJack::selected()\n"));
327 	_updateBitmap();
328 	view()->Invalidate(Frame());
329 }
330 
331 void MediaJack::deselected()
332 {
333 	D_METHOD(("MediaJack::deselected()\n"));
334 	_updateBitmap();
335 	view()->Invalidate(Frame());
336 }
337 
338 void MediaJack::connected()
339 {
340 	D_METHOD(("MediaJack::connected()\n"));
341 	_updateBitmap();
342 	view()->Invalidate(Frame());
343 }
344 
345 void MediaJack::disconnected()
346 {
347 	D_METHOD(("MediaJack::disconnected()\n"));
348 	_updateBitmap();
349 	view()->Invalidate(Frame());
350 }
351 
352 // -------------------------------------------------------- //
353 // *** operations (public)
354 // -------------------------------------------------------- //
355 
356 void MediaJack::layoutChanged(
357 	int32 layout)
358 {
359 	D_METHOD(("MediaJack::layoutChanged\n"));
360 	resizeTo(M_DEFAULT_WIDTH, M_DEFAULT_HEIGHT);
361 	_updateBitmap();
362 }
363 
364 void MediaJack::setPosition(
365 	float offset,
366 	float leftTopBoundary,
367 	float rightBottomBoundary,
368 	BRegion *updateRegion)
369 {
370 	D_METHOD(("MediaJack::setPosition\n"));
371 	switch (dynamic_cast<MediaRoutingView *>(view())->getLayout())
372 	{
373 		case MediaRoutingView::M_ICON_VIEW:
374 		{
375 			if (isInput())
376 			{
377 				moveTo(BPoint(leftTopBoundary, offset), updateRegion);
378 			}
379 			else if (isOutput())
380 			{
381 				moveTo(BPoint(rightBottomBoundary - Frame().Width(), offset), updateRegion);
382 			}
383 			break;
384 		}
385 		case MediaRoutingView::M_MINI_ICON_VIEW:
386 		{
387 			if (isInput())
388 			{
389 				moveTo(BPoint(offset, leftTopBoundary), updateRegion);
390 			}
391 			else if (isOutput())
392 			{
393 				moveTo(BPoint(offset, rightBottomBoundary - Frame().Height()), updateRegion);
394 			}
395 			break;
396 		}
397 	}
398 }
399 
400 // -------------------------------------------------------- //
401 // *** internal methods (private)
402 // -------------------------------------------------------- //
403 
404 void MediaJack::_updateBitmap()
405 {
406 	D_METHOD(("MediaJack::_updateBitmap()\n"));
407 
408 	if (m_bitmap)
409 	{
410 		delete m_bitmap;
411 	}
412 	BBitmap *tempBitmap = new BBitmap(Frame().OffsetToCopy(0.0, 0.0), B_RGBA32, true);
413 	tempBitmap->Lock();
414 	{
415 		BView *tempView = new BView(tempBitmap->Bounds(), "", B_FOLLOW_NONE, 0);
416 		tempBitmap->AddChild(tempView);
417 		tempView->SetOrigin(0.0, 0.0);
418 
419 		MediaRoutingView* mediaView = dynamic_cast<MediaRoutingView*>(view());
420 		int32 layout = mediaView ? mediaView->getLayout() : MediaRoutingView::M_ICON_VIEW;
421 
422 		_drawInto(tempView, tempView->Bounds(), layout);
423 
424 		tempView->Sync();
425 		tempBitmap->RemoveChild(tempView);
426 		delete tempView;
427 	}
428 	tempBitmap->Unlock();
429 	m_bitmap = new BBitmap(tempBitmap);
430 	delete tempBitmap;
431 }
432 
433 void MediaJack::_drawInto(
434 	BView *target,
435 	BRect targetRect,
436 	int32 layout)
437 {
438 	D_METHOD(("MediaJack::_drawInto()\n"));
439 
440 	bool selected = isConnecting() || isSelected();
441 	switch (layout)
442 	{
443 		case MediaRoutingView::M_ICON_VIEW:
444 		{
445 			if (isInput())
446 			{
447 				BRect r;
448 				BPoint p;
449 
450 				// fill rect
451 				r = targetRect;
452 				target->SetLowColor(M_GRAY_COLOR);
453 				r.left += 2.0;
454 				target->FillRect(r, B_SOLID_LOW);
455 
456 				// draw connection point
457 				r = targetRect;
458 				p.Set(0.0, Frame().Height() / 2.0 - 2.0);
459 				target->BeginLineArray(4);
460 				{
461 					target->AddLine(r.LeftTop(),
462 									p,
463 									M_DARK_GRAY_COLOR);
464 					target->AddLine(r.LeftTop() + BPoint(1.0, 0.0),
465 									p + BPoint(1.0, 0.0),
466 									M_LIGHT_GRAY_COLOR);
467 					target->AddLine(p + BPoint(0.0, 5.0),
468 									r.LeftBottom(),
469 									M_DARK_GRAY_COLOR);
470 					target->AddLine(p + BPoint(1.0, 5.0),
471 									r.LeftBottom() + BPoint(1.0, 0.0),
472 									M_LIGHT_GRAY_COLOR);
473 				}
474 				target->EndLineArray();
475 
476 				if (isConnected() || isConnecting())
477 				{
478 					target->BeginLineArray(11);
479 					{
480 						target->AddLine(p, p, M_DARK_GRAY_COLOR);
481 						target->AddLine(p + BPoint(0.0, 4.0), p + BPoint(0.0, 4.0), M_DARK_GRAY_COLOR);
482 						target->AddLine(p + BPoint(1.0, 0.0), p + BPoint(4.0, 0.0), M_DARK_GRAY_COLOR);
483 						target->AddLine(p + BPoint(1.0, 4.0), p + BPoint(4.0, 4.0), M_LIGHT_GRAY_COLOR);
484 						target->AddLine(p + BPoint(4.0, 1.0), p + BPoint(4.0, 3.0), M_LIGHT_GRAY_COLOR);
485 						target->AddLine(p + BPoint(0.0, 1.0), p + BPoint(2.0, 1.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
486 						target->AddLine(p + BPoint(3.0, 1.0), p + BPoint(3.0, 1.0), M_MED_GRAY_COLOR);
487 						target->AddLine(p + BPoint(0.0, 2.0), p + BPoint(2.0, 2.0), selected ? M_LIGHT_BLUE_COLOR : M_LIGHT_GRAY_COLOR);
488 						target->AddLine(p + BPoint(3.0, 2.0), p + BPoint(3.0, 2.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
489 						target->AddLine(p + BPoint(0.0, 3.0), p + BPoint(2.0, 3.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
490 						target->AddLine(p + BPoint(3.0, 3.0), p + BPoint(3.0, 3.0), M_MED_GRAY_COLOR);
491 					}
492 					target->EndLineArray();
493 				}
494 				else
495 				{
496 					target->BeginLineArray(7);
497 					{
498 						target->AddLine(p, p + BPoint(0.0, 4.0), M_DARK_GRAY_COLOR);
499 						target->AddLine(p + BPoint(1.0, 0.0), p + BPoint(4.0, 0.0), M_DARK_GRAY_COLOR);
500 						target->AddLine(p + BPoint(1.0, 4.0), p + BPoint(4.0, 4.0), M_LIGHT_GRAY_COLOR);
501 						target->AddLine(p + BPoint(4.0, 1.0), p + BPoint(4.0, 3.0), M_LIGHT_GRAY_COLOR);
502 						target->AddLine(p + BPoint(1.0, 1.0), p + BPoint(3.0, 1.0), M_MED_GRAY_COLOR);
503 						target->AddLine(p + BPoint(1.0, 2.0), p + BPoint(3.0, 2.0), M_MED_GRAY_COLOR);
504 						target->AddLine(p + BPoint(1.0, 3.0), p + BPoint(3.0, 3.0), M_MED_GRAY_COLOR);
505 					}
506 					target->EndLineArray();
507 				}
508 
509 				// draw abbreviation string
510 				BFont font(be_plain_font);
511 				font_height fh;
512 				font.SetSize(font.Size() - 2.0);
513 				font.GetHeight(&fh);
514 				p.x += 7.0;
515 				p.y = (Frame().Height() / 2.0) + (fh.ascent / 2.0);
516 				target->SetFont(&font);
517 				target->SetDrawingMode(B_OP_OVER);
518 				target->SetHighColor((isConnected() || isConnecting()) ?
519 									  M_MED_GRAY_COLOR :
520 									  M_DARK_GRAY_COLOR);
521 				target->DrawString(m_abbreviation.String(), p);
522 			}
523 			else if (isOutput())
524 			{
525 				BRect r;
526 				BPoint p;
527 
528 				// fill rect
529 				r = targetRect;
530 				target->SetLowColor(M_GRAY_COLOR);
531 				r.right -= 2.0;
532 				target->FillRect(r, B_SOLID_LOW);
533 
534 				// draw connection point
535 				r = targetRect;
536 				p.Set(targetRect.right - 4.0, Frame().Height() / 2.0 - 2.0);
537 				target->BeginLineArray(4);
538 				{
539 					target->AddLine(r.RightTop(),
540 									p + BPoint(4.0, 0.0),
541 									M_DARK_GRAY_COLOR);
542 					target->AddLine(r.RightTop() + BPoint(-1.0, 0.0),
543 									p + BPoint(3.0, 0.0),
544 									M_MED_GRAY_COLOR);
545 					target->AddLine(p + BPoint(4.0, 5.0),
546 									r.RightBottom(),
547 									M_DARK_GRAY_COLOR);
548 					target->AddLine(p + BPoint(3.0, 5.0),
549 									r.RightBottom() + BPoint(-1.0, 0.0),
550 									M_MED_GRAY_COLOR);
551 				}
552 				target->EndLineArray();
553 
554 				if (isConnected() || isConnecting())
555 				{
556 					target->BeginLineArray(11);
557 					target->AddLine(p + BPoint(4.0, 0.0), p + BPoint(4.0, 0.0), M_DARK_GRAY_COLOR);
558 					target->AddLine(p + BPoint(4.0, 4.0), p + BPoint(4.0, 4.0), M_DARK_GRAY_COLOR);
559 					target->AddLine(p, p + BPoint(3.0, 0.0), M_DARK_GRAY_COLOR);
560 					target->AddLine(p + BPoint(0.0, 1.0), p + BPoint(0.0, 3.0), M_DARK_GRAY_COLOR);
561 					target->AddLine(p + BPoint(0.0, 4.0), p + BPoint(3.0, 4.0), M_LIGHT_GRAY_COLOR);
562 					target->AddLine(p + BPoint(1.0, 1.0), p + BPoint(1.0, 1.0), M_MED_GRAY_COLOR);
563 					target->AddLine(p + BPoint(2.0, 1.0), p + BPoint(4.0, 1.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
564 					target->AddLine(p + BPoint(1.0, 2.0), p + BPoint(1.0, 2.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
565 					target->AddLine(p + BPoint(2.0, 2.0), p + BPoint(4.0, 2.0), selected ? M_LIGHT_BLUE_COLOR : M_LIGHT_GRAY_COLOR);
566 					target->AddLine(p + BPoint(1.0, 3.0), p + BPoint(1.0, 3.0), M_MED_GRAY_COLOR);
567 					target->AddLine(p + BPoint(2.0, 3.0), p + BPoint(4.0, 3.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
568 					target->EndLineArray();
569 				}
570 				else
571 				{
572 					target->BeginLineArray(7);
573 					target->AddLine(p + BPoint(4.0, 0.0), p + BPoint(4.0, 4.0), M_DARK_GRAY_COLOR);
574 					target->AddLine(p, p + BPoint(3.0, 0.0), M_DARK_GRAY_COLOR);
575 					target->AddLine(p + BPoint(0.0, 1.0), p + BPoint(0.0, 3.0), M_DARK_GRAY_COLOR);
576 					target->AddLine(p + BPoint(0.0, 4.0), p + BPoint(3.0, 4.0), M_LIGHT_GRAY_COLOR);
577 					target->AddLine(p + BPoint(1.0, 1.0), p + BPoint(3.0, 1.0), M_MED_GRAY_COLOR);
578 					target->AddLine(p + BPoint(1.0, 2.0), p + BPoint(3.0, 2.0), M_MED_GRAY_COLOR);
579 					target->AddLine(p + BPoint(1.0, 3.0), p + BPoint(3.0, 3.0), M_MED_GRAY_COLOR);
580 					target->EndLineArray();
581 				}
582 
583 				// draw abbreviation string
584 				BFont font(be_plain_font);
585 				font_height fh;
586 				font.SetSize(font.Size() - 2.0);
587 				font.GetHeight(&fh);
588 				p.x -= font.StringWidth(m_abbreviation.String()) + 2.0;
589 				p.y = (Frame().Height() / 2.0) + (fh.ascent / 2.0);
590 				target->SetFont(&font);
591 				target->SetDrawingMode(B_OP_OVER);
592 				target->SetHighColor((isConnected() || isConnecting()) ?
593 									  M_MED_GRAY_COLOR :
594 									  M_DARK_GRAY_COLOR);
595 				target->DrawString(m_abbreviation.String(), p);
596 			}
597 			break;
598 		}
599 		case MediaRoutingView::M_MINI_ICON_VIEW:
600 		{
601 			if (isInput())
602 			{
603 				BRect r;
604 				BPoint p;
605 
606 				// fill rect
607 				r = targetRect;
608 				target->SetLowColor(M_GRAY_COLOR);
609 				r.top += 2.0;
610 				target->FillRect(r, B_SOLID_LOW);
611 
612 				// draw connection point
613 				r = targetRect;
614 				p.Set(Frame().Width() / 2.0 - 2.0, 0.0);
615 				target->BeginLineArray(4);
616 				{
617 					target->AddLine(r.LeftTop(),
618 									p,
619 									M_DARK_GRAY_COLOR);
620 					target->AddLine(r.LeftTop() + BPoint(0.0, 1.0),
621 									p + BPoint(0.0, 1.0),
622 									M_LIGHT_GRAY_COLOR);
623 					target->AddLine(p + BPoint(5.0, 0.0),
624 									r.RightTop(),
625 									M_DARK_GRAY_COLOR);
626 					target->AddLine(p + BPoint(5.0, 1.0),
627 									r.RightTop() + BPoint(0.0, 1.0),
628 									M_LIGHT_GRAY_COLOR);
629 				}
630 				target->EndLineArray();
631 				if (isConnected() || isConnecting())
632 				{
633 					target->BeginLineArray(11);
634 					target->AddLine(p, p, M_DARK_GRAY_COLOR);
635 					target->AddLine(p + BPoint(4.0, 0.0), p + BPoint(4.0, 0.0), M_DARK_GRAY_COLOR);
636 					target->AddLine(p + BPoint(0.0, 1.0), p + BPoint(0.0, 4.0), M_DARK_GRAY_COLOR);
637 					target->AddLine(p + BPoint(4.0, 1.0), p + BPoint(4.0, 4.0), M_LIGHT_GRAY_COLOR);
638 					target->AddLine(p + BPoint(1.0, 4.0), p + BPoint(3.0, 4.0), M_LIGHT_GRAY_COLOR);
639 					target->AddLine(p + BPoint(1.0, 0.0), p + BPoint(1.0, 2.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
640 					target->AddLine(p + BPoint(1.0, 3.0), p + BPoint(1.0, 3.0), M_MED_GRAY_COLOR);
641 					target->AddLine(p + BPoint(2.0, 0.0), p + BPoint(2.0, 2.0), selected ? M_LIGHT_BLUE_COLOR : M_LIGHT_GRAY_COLOR);
642 					target->AddLine(p + BPoint(2.0, 3.0), p + BPoint(2.0, 3.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
643 					target->AddLine(p + BPoint(3.0, 0.0), p + BPoint(3.0, 2.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
644 					target->AddLine(p + BPoint(3.0, 3.0), p + BPoint(3.0, 3.0), M_MED_GRAY_COLOR);
645 					target->EndLineArray();
646 				}
647 				else
648 				{
649 					target->BeginLineArray(7);
650 					target->AddLine(p, p + BPoint(4.0, 0.0), M_DARK_GRAY_COLOR);
651 					target->AddLine(p + BPoint(0.0, 1.0), p + BPoint(0.0, 4.0), M_DARK_GRAY_COLOR);
652 					target->AddLine(p + BPoint(4.0, 1.0), p + BPoint(4.0, 4.0), M_LIGHT_GRAY_COLOR);
653 					target->AddLine(p + BPoint(1.0, 4.0), p + BPoint(3.0, 4.0), M_LIGHT_GRAY_COLOR);
654 					target->AddLine(p + BPoint(1.0, 1.0), p + BPoint(1.0, 3.0), M_MED_GRAY_COLOR);
655 					target->AddLine(p + BPoint(2.0, 1.0), p + BPoint(2.0, 3.0), M_MED_GRAY_COLOR);
656 					target->AddLine(p + BPoint(3.0, 1.0), p + BPoint(3.0, 3.0), M_MED_GRAY_COLOR);
657 					target->EndLineArray();
658 				}
659 			}
660 			else if (isOutput())
661 			{
662 				BRect r;
663 				BPoint p;
664 
665 				// fill rect
666 				r = targetRect;
667 				target->SetLowColor(M_GRAY_COLOR);
668 				r.bottom -= 2.0;
669 				target->FillRect(r, B_SOLID_LOW);
670 
671 				// draw connection point
672 				r = targetRect;
673 				p.Set(Frame().Width() / 2.0 - 2.0, targetRect.bottom - 4.0);
674 				target->BeginLineArray(4);
675 				{
676 					target->AddLine(r.LeftBottom(),
677 									p + BPoint(0.0, 4.0),
678 									M_DARK_GRAY_COLOR);
679 					target->AddLine(r.LeftBottom() + BPoint(0.0, -1.0),
680 									p + BPoint(0.0, 3.0),
681 									M_MED_GRAY_COLOR);
682 					target->AddLine(p + BPoint(5.0, 4.0),
683 									r.RightBottom(),
684 									M_DARK_GRAY_COLOR);
685 					target->AddLine(p + BPoint(5.0, 3.0),
686 									r.RightBottom() + BPoint(0.0, -1.0),
687 									M_MED_GRAY_COLOR);
688 				}
689 				target->EndLineArray();
690 				if (isConnected() || isConnecting())
691 				{
692 					target->BeginLineArray(11);
693 					target->AddLine(p + BPoint(0.0, 4.0), p + BPoint(0.0, 4.0), M_DARK_GRAY_COLOR);
694 					target->AddLine(p + BPoint(4.0, 4.0), p + BPoint(4.0, 4.0), M_DARK_GRAY_COLOR);
695 					target->AddLine(p, p + BPoint(0.0, 3.0), M_DARK_GRAY_COLOR);
696 					target->AddLine(p + BPoint(1.0, 0.0), p + BPoint(3.0, 0.0), M_DARK_GRAY_COLOR);
697 					target->AddLine(p + BPoint(4.0, 0.0), p + BPoint(4.0, 3.0), M_LIGHT_GRAY_COLOR);
698 					target->AddLine(p + BPoint(1.0, 1.0), p + BPoint(1.0, 1.0), M_MED_GRAY_COLOR);
699 					target->AddLine(p + BPoint(1.0, 2.0), p + BPoint(1.0, 4.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
700 					target->AddLine(p + BPoint(2.0, 1.0), p + BPoint(2.0, 1.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
701 					target->AddLine(p + BPoint(2.0, 2.0), p + BPoint(2.0, 4.0), selected ? M_LIGHT_BLUE_COLOR : M_LIGHT_GRAY_COLOR);
702 					target->AddLine(p + BPoint(3.0, 1.0), p + BPoint(3.0, 1.0), M_MED_GRAY_COLOR);
703 					target->AddLine(p + BPoint(3.0, 2.0), p + BPoint(3.0, 4.0), selected ? M_BLUE_COLOR : M_DARK_GRAY_COLOR);
704 					target->EndLineArray();
705 				}
706 				else
707 				{
708 					target->BeginLineArray(7);
709 					target->AddLine(p + BPoint(0.0, 4.0), p + BPoint(4.0, 4.0), M_DARK_GRAY_COLOR);
710 					target->AddLine(p, p + BPoint(0.0, 3.0), M_DARK_GRAY_COLOR);
711 					target->AddLine(p + BPoint(1.0, 0.0), p + BPoint(3.0, 0.0), M_DARK_GRAY_COLOR);
712 					target->AddLine(p + BPoint(4.0, 0.0), p + BPoint(4.0, 3.0), M_LIGHT_GRAY_COLOR);
713 					target->AddLine(p + BPoint(1.0, 1.0), p + BPoint(1.0, 3.0), M_MED_GRAY_COLOR);
714 					target->AddLine(p + BPoint(2.0, 1.0), p + BPoint(2.0, 3.0), M_MED_GRAY_COLOR);
715 					target->AddLine(p + BPoint(3.0, 1.0), p + BPoint(3.0, 3.0), M_MED_GRAY_COLOR);
716 					target->EndLineArray();
717 				}
718 			}
719 			break;
720 		}
721 	}
722 }
723 
724 void MediaJack::_updateAbbreviation()
725 {
726 	D_METHOD(("MediaJack::_updateAbbreviation()\n"));
727 
728 	int32 offset;
729 	m_abbreviation = "";
730 	m_abbreviation += m_label[0];
731 	offset = m_label.FindFirst(" ") + 1;
732 	if ((offset > 1) && (offset < m_label.CountChars() - 1))
733 		m_abbreviation += m_label[offset];
734 	else
735 		m_abbreviation += m_label[1];
736 	offset = m_label.CountChars() - 1;
737 	m_abbreviation += m_label[offset];
738 }
739 
740 // -------------------------------------------------------- //
741 // *** internal operations (protected)
742 // -------------------------------------------------------- //
743 
744 void MediaJack::showContextMenu(
745 	BPoint point)
746 {
747 	D_METHOD(("MediaJack::showContextMenu()\n"));
748 
749 	BPopUpMenu *menu = new BPopUpMenu("MediaJack PopUp", false, false, B_ITEMS_IN_COLUMN);
750 	menu->SetFont(be_plain_font);
751 
752 	// add the "Get Info" item
753 	if (isInput())
754 	{
755 		media_input input;
756 		getInput(&input);
757 		BMessage *message = new BMessage(InfoWindowManager::M_INFO_WINDOW_REQUESTED);
758 		message->AddData("input", B_RAW_TYPE,
759 						 reinterpret_cast<const void *>(&input), sizeof(input));
760 		menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), message));
761 	}
762 	else if (isOutput())
763 	{
764 		media_output output;
765 		getOutput(&output);
766 		BMessage *message = new BMessage(InfoWindowManager::M_INFO_WINDOW_REQUESTED);
767 		message->AddData("output", B_RAW_TYPE,
768 						 reinterpret_cast<const void *>(&output), sizeof(output));
769 		menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), message));
770 	}
771 
772 	menu->SetTargetForItems(view());
773 	view()->ConvertToScreen(&point);
774 	point -= BPoint(1.0, 1.0);
775 	menu->Go(point, true, true, true);
776 }
777 
778 // -------------------------------------------------------- //
779 // *** sorting methods (friend)
780 // -------------------------------------------------------- //
781 
782 int __CORTEX_NAMESPACE__ compareTypeAndID(
783 	const void *lValue,
784 	const void *rValue)
785 {
786 	int retValue = 0;
787 	const MediaJack *lJack = *(reinterpret_cast<MediaJack * const*>(reinterpret_cast<void * const*>(lValue)));
788 	const MediaJack *rJack = *(reinterpret_cast<MediaJack * const*>(reinterpret_cast<void * const*>(rValue)));
789 	if (lJack && rJack)
790 	{
791 		if (lJack->m_jackType < rJack->m_jackType)
792 		{
793 			return -1;
794 		}
795 		if (lJack->m_jackType == rJack->m_jackType)
796 		{
797 			if (lJack->m_index < rJack->m_index)
798 			{
799 				return -1;
800 			}
801 			else
802 			{
803 				return 1;
804 			}
805 		}
806 		else if (lJack->m_jackType > rJack->m_jackType)
807 		{
808 			retValue = 1;
809 		}
810 	}
811 	return retValue;
812 }
813 
814 // END -- LiveNodeView.cpp --
815