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