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