xref: /haiku/src/apps/cortex/MediaRoutingView/MediaWire.cpp (revision 2ca1376080f866aafba1edc95eaa036b92ed2078)
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 // MediaWire.cpp
33 
34 #include "MediaWire.h"
35 // InfoWindow
36 #include "InfoWindowManager.h"
37 // MediaRoutingView
38 #include "MediaJack.h"
39 #include "MediaRoutingDefs.h"
40 #include "MediaRoutingView.h"
41 // Support
42 #include "cortex_ui.h"
43 #include "MediaString.h"
44 // TipManager
45 #include "TipManager.h"
46 
47 // Application Kit
48 #include <Application.h>
49 // Interface Kit
50 #include <MenuItem.h>
51 #include <PopUpMenu.h>
52 // Media Kit
53 #include <MediaDefs.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 "MediaRoutingView"
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 const float MediaWire::M_WIRE_OFFSET		= 4.0;
76 
77 // -------------------------------------------------------- //
78 // *** ctor/dtor
79 // -------------------------------------------------------- //
80 
81 MediaWire::MediaWire(
82 	Connection connection,
83 	MediaJack *outputJack,
84 	MediaJack *inputJack)
85 	: DiagramWire(outputJack, inputJack),
86 	  connection(connection)
87 {
88 	D_METHOD(("MediaWire::MediaWire()\n"));
89 }
90 
91 MediaWire::MediaWire(
92 	MediaJack *jack,
93 	bool isStartPoint)
94 	: DiagramWire(jack, isStartPoint)
95 {
96 	D_METHOD(("MediaWire::MediaWire(temp)\n"));
97 }
98 
99 MediaWire::~MediaWire()
100 {
101 	D_METHOD(("MediaWire::~MediaWire()\n"));
102 }
103 
104 // -------------------------------------------------------- //
105 // *** derived from DiagramWire (public)
106 // -------------------------------------------------------- //
107 
108 void MediaWire::attachedToDiagram()
109 {
110 	D_METHOD(("MediaWire::detachedFromDiagram()\n"));
111 
112 	endPointMoved(startPoint());
113 	endPointMoved(endPoint());
114 }
115 
116 void MediaWire::detachedFromDiagram()
117 {
118 	D_METHOD(("MediaWire::detachedFromDiagram()\n"));
119 
120 	// make sure we're no longer displaying a tooltip
121 	TipManager *tips = TipManager::Instance();
122 	tips->hideTip(view()->ConvertToScreen(Frame()));
123 }
124 
125 BRect MediaWire::Frame() const
126 {
127 	D_DRAW(("MediaWire::Frame()\n"));
128 	return m_frame;
129 }
130 
131 float MediaWire::howCloseTo(
132 	BPoint point) const
133 {
134 	D_MOUSE(("MediaWire::howCloseTo()\n"));
135 	if (Frame().Contains(point))
136 	{
137 		BPoint sp = m_startPoint;
138 		BPoint ep = m_endPoint;
139 		BPoint so = m_startOffset;
140 		BPoint eo = m_endOffset;
141 		BRect wireFrame, startFrame, endFrame;
142 		wireFrame.left = so.x < eo.x ? so.x : eo.x;
143 		wireFrame.top = so.y < eo.y ? so.y : eo.y;
144 		wireFrame.right = so.x > eo.x ? so.x : eo.x;
145 		wireFrame.bottom = so.y > eo.y ? so.y : eo.y;
146 		startFrame.Set(sp.x, sp.y, so.x, so.y);
147 		endFrame.Set(ep.x, ep.y, eo.x, eo.y);
148 		wireFrame.InsetBy(-1.0, -1.0);
149 		startFrame.InsetBy(-1.0, -1.0);
150 		endFrame.InsetBy(-1.0, -1.0);
151 		if ((wireFrame.Width() <= 5.0) || (wireFrame.Height() <= 5.0) || startFrame.Contains(point) || endFrame.Contains(point))
152 		{
153 			return 1.0;
154 		}
155 		else
156 		{
157 			float length, result;
158 			length = sqrt(pow(eo.x - so.x, 2) + pow(eo.y - so.y, 2));
159  			result = ((so.y - point.y) * (eo.x - so.x)) - ((so.x - point.x) * (eo.y - so.y));
160 			result = 3.0 - fabs(result / length);
161 			return result;
162 		}
163 	}
164 	return 0.0;
165 }
166 
167 void MediaWire::drawWire()
168 {
169 	D_DRAW(("MediaWire::drawWire()\n"));
170 
171 	rgb_color border = isSelected() ? M_BLUE_COLOR : M_DARK_GRAY_COLOR;
172 	rgb_color fill = isSelected() ? M_LIGHT_BLUE_COLOR : M_LIGHT_GRAY_COLOR;
173 	view()->SetPenSize(3.0);
174 	view()->BeginLineArray(3);
175 		view()->AddLine(m_startPoint, m_startOffset, border);
176 		view()->AddLine(m_startOffset, m_endOffset, border);
177 		view()->AddLine(m_endOffset, m_endPoint, border);
178 	view()->EndLineArray();
179 	view()->SetPenSize(1.0);
180 	view()->BeginLineArray(3);
181 		view()->AddLine(m_startPoint, m_startOffset, fill);
182 		view()->AddLine(m_startOffset, m_endOffset, fill);
183 		view()->AddLine(m_endOffset, m_endPoint, fill);
184 	view()->EndLineArray();
185 }
186 
187 void MediaWire::MouseDown(
188 	BPoint point,
189 	uint32 buttons,
190 	uint32 clicks)
191 {
192 	D_MOUSE(("MediaWire::MouseDown()\n"));
193 	_inherited::MouseDown(point, buttons, clicks);
194 
195 	switch (buttons)
196 	{
197 		case B_SECONDARY_MOUSE_BUTTON:
198 		{
199 			if (clicks == 1)
200 			{
201 				showContextMenu(point);
202 			}
203 		}
204 	}
205 }
206 
207 void MediaWire::MouseOver(
208 	BPoint point,
209 	uint32 transit)
210 {
211 	D_MOUSE(("MediaWire::MouseOver()\n"));
212 
213 	if (isDragging())
214 	{
215 		return;
216 	}
217 	switch (transit)
218 	{
219 		case B_ENTERED_VIEW:
220 		{
221 			TipManager *tips = TipManager::Instance();
222 			BString tipText = MediaString::getStringFor(connection.format(), false);
223 			tips->showTip(tipText.String(), view()->ConvertToScreen(Frame()),
224 						  TipManager::LEFT_OFFSET_FROM_POINTER, BPoint(12.0, 8.0));
225 			be_app->SetCursor(M_CABLE_CURSOR);
226 			break;
227 		}
228 		case B_EXITED_VIEW:
229 		{
230 			be_app->SetCursor(B_HAND_CURSOR);
231 			TipManager *tips = TipManager::Instance();
232 			tips->hideTip(view()->ConvertToScreen(Frame()));
233 			break;
234 		}
235 	}
236 }
237 
238 void MediaWire::selected()
239 {
240 	D_METHOD(("MediaWire::selected()\n"));
241 	if (startPoint())
242 	{
243 		MediaJack *outputJack = static_cast<MediaJack *>(startPoint());
244 		outputJack->select();
245 	}
246 	if (endPoint())
247 	{
248 		MediaJack *inputJack = static_cast<MediaJack *>(endPoint());
249 		inputJack->select();
250 	}
251 }
252 
253 void MediaWire::deselected()
254 {
255 	D_METHOD(("MediaWire::deselected()\n"));
256 	if (startPoint())
257 	{
258 		MediaJack *outputJack = static_cast<MediaJack *>(startPoint());
259 		outputJack->deselect();
260 	}
261 	if (endPoint())
262 	{
263 		MediaJack *inputJack = static_cast<MediaJack *>(endPoint());
264 		inputJack->deselect();
265 	}
266 }
267 
268 void MediaWire::endPointMoved(
269 	DiagramEndPoint *which)
270 {
271 	if (which == startPoint())
272 	{
273 		m_startPoint = startConnectionPoint();
274 		switch (dynamic_cast<MediaRoutingView *>(view())->getLayout())
275 		{
276 			case MediaRoutingView::M_ICON_VIEW:
277 			{
278 				m_startOffset = m_startPoint + BPoint(M_WIRE_OFFSET, 0.0);
279 				break;
280 			}
281 			case MediaRoutingView::M_MINI_ICON_VIEW:
282 			{
283 				m_startOffset = m_startPoint + BPoint(0.0, M_WIRE_OFFSET);
284 				break;
285 			}
286 		}
287 		m_frame.left = m_startPoint.x < m_endOffset.x ? m_startPoint.x - 2.0: m_endOffset.x - 2.0;
288 		m_frame.top = m_startPoint.y < m_endOffset.y ? m_startPoint.y - 2.0 : m_endOffset.y - 2.0;
289 		m_frame.right = m_startOffset.x > m_endPoint.x ? m_startOffset.x + 2.0 : m_endPoint.x + 2.0;
290 		m_frame.bottom = m_startOffset.y > m_endPoint.y ? m_startOffset.y + 2.0 : m_endPoint.y + 2.0;
291 	}
292 	else if (which == endPoint())
293 	{
294 		m_endPoint = endConnectionPoint();
295 		switch (dynamic_cast<MediaRoutingView *>(view())->getLayout())
296 		{
297 			case MediaRoutingView::M_ICON_VIEW:
298 			{
299 				m_endOffset = m_endPoint - BPoint(M_WIRE_OFFSET, 0.0);
300 				break;
301 			}
302 			case MediaRoutingView::M_MINI_ICON_VIEW:
303 			{
304 				m_endOffset = m_endPoint - BPoint(0.0, M_WIRE_OFFSET);
305 				break;
306 			}
307 		}
308 		m_frame.left = m_startPoint.x < m_endOffset.x ? m_startPoint.x - 2.0: m_endOffset.x - 2.0;
309 		m_frame.top = m_startPoint.y < m_endOffset.y ? m_startPoint.y - 2.0 : m_endOffset.y - 2.0;
310 		m_frame.right = m_startOffset.x > m_endPoint.x ? m_startOffset.x + 2.0 : m_endPoint.x + 2.0;
311 		m_frame.bottom = m_startOffset.y > m_endPoint.y ? m_startOffset.y + 2.0 : m_endPoint.y + 2.0;
312 	}
313 }
314 
315 // -------------------------------------------------------- //
316 // *** internal operations (protected)
317 // -------------------------------------------------------- //
318 
319 void MediaWire::showContextMenu(
320 	BPoint point)
321 {
322 	D_METHOD(("MediaWire::showContextMenu()\n"));
323 
324 	BPopUpMenu *menu = new BPopUpMenu("MediaWire PopUp", false, false, B_ITEMS_IN_COLUMN);
325 	menu->SetFont(be_plain_font);
326 	BMenuItem *item;
327 
328 	// add the "Get Info" item
329 	media_output output;
330 	connection.getOutput(&output);
331 	BMessage *message = new BMessage(InfoWindowManager::M_INFO_WINDOW_REQUESTED);
332 	message->AddData("connection", B_RAW_TYPE,
333 					 reinterpret_cast<const void *>(&output), sizeof(output));
334 	menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), message, 'I'));
335 
336 	// add the "Disconnect" item
337 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Disconnect"),
338 		new BMessage(MediaRoutingView::M_DELETE_SELECTION), 'T'));
339 	if (connection.flags() & Connection::LOCKED)
340 	{
341 		item->SetEnabled(false);
342 	}
343 
344 	menu->SetTargetForItems(view());
345 	view()->ConvertToScreen(&point);
346 	point -= BPoint(1.0, 1.0);
347 	menu->Go(point, true, true, true);
348 }
349 
350 // END -- MediaWire.cpp --
351