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