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// DiagramWire.cpp
33
34#include "DiagramWire.h"
35#include "DiagramDefs.h"
36#include "DiagramEndPoint.h"
37#include "DiagramView.h"
38
39#include <Message.h>
40#include <Messenger.h>
41
42__USE_CORTEX_NAMESPACE
43
44#include <Debug.h>
45#define D_METHOD(x) //PRINT (x)
46#define D_MESSAGE(x) //PRINT (x)
47
48// -------------------------------------------------------- //
49// *** ctor/dtor
50// -------------------------------------------------------- //
51
52DiagramWire::DiagramWire(
53	DiagramEndPoint *fromWhich,
54	DiagramEndPoint *toWhich)
55	: DiagramItem(DiagramItem::M_WIRE),
56	  m_fromEndPoint(fromWhich),
57	  m_toEndPoint(toWhich),
58	  m_temporary(false)
59{
60	D_METHOD(("DiagramWire::DiagramWire()\n"));
61	makeDraggable(false);
62	ASSERT(m_fromEndPoint);
63	m_fromEndPoint->connect(this);
64	ASSERT(m_toEndPoint);
65	m_toEndPoint->connect(this);
66}
67
68DiagramWire::DiagramWire(
69	DiagramEndPoint *fromWhich,
70	bool isStartPoint)
71	: DiagramItem(DiagramItem::M_WIRE),
72	  m_fromEndPoint(isStartPoint ? fromWhich : 0),
73	  m_toEndPoint(isStartPoint ? 0 : fromWhich),
74	  m_temporary(true),
75	  m_dragEndPoint(fromWhich->connectionPoint())
76{
77	D_METHOD(("DiagramWire::DiagramWire(temp)\n"));
78	makeDraggable(false);
79	ASSERT(fromWhich);
80	if (m_fromEndPoint)
81	{
82		m_fromEndPoint->connect(this);
83	}
84	else if (m_toEndPoint)
85	{
86		m_toEndPoint->connect(this);
87	}
88}
89
90DiagramWire::~DiagramWire()
91{
92	D_METHOD(("DiagramWire::~DiagramWire()\n"));
93	if (m_fromEndPoint)
94	{
95		m_fromEndPoint->disconnect();
96	}
97	if (m_toEndPoint)
98	{
99		m_toEndPoint->disconnect();
100	}
101}
102
103// -------------------------------------------------------- //
104// *** accessors
105// -------------------------------------------------------- //
106
107BPoint DiagramWire::startConnectionPoint() const
108{
109	D_METHOD(("DiagramWire::startConnectionPoint()\n"));
110	if (m_fromEndPoint)
111	{
112		return m_fromEndPoint->connectionPoint();
113	}
114	else if (m_temporary)
115	{
116		return m_dragEndPoint;
117	}
118	return BPoint(-1.0, -1.0);
119}
120
121BPoint DiagramWire::endConnectionPoint() const
122{
123	D_METHOD(("DiagramWire::endConnectionPoint()\n"));
124	if (m_toEndPoint)
125	{
126		return m_toEndPoint->connectionPoint();
127	}
128	else if (m_temporary)
129	{
130		return m_dragEndPoint;
131	}
132	return BPoint(-1.0, -1.0);
133}
134
135// -------------------------------------------------------- //
136// *** derived from DiagramItem
137// -------------------------------------------------------- //
138
139float DiagramWire::howCloseTo(
140	BPoint point) const
141{
142	D_METHOD(("DiagramWire::howCloseTo()\n"));
143	BPoint a = startConnectionPoint();
144	BPoint b = endConnectionPoint();
145	float length, result;
146	length = sqrt(pow(b.x - a.x, 2) + pow(b.y - a.y, 2));
147	result = ((a.y - point.y) * (b.x - a.x)) - ((a.x - point.x) * (b.y - a.y));
148	result = 3.0 - fabs(result / length);
149	return result;
150}
151
152void DiagramWire::Draw(
153	BRect updateRect)
154{
155	D_METHOD(("DiagramWire::Draw()\n"));
156	if (view())
157	{
158		view()->PushState();
159		{
160			BRegion region, clipping;
161			region.Include(Frame() & updateRect);
162			if (view()->GetClippingAbove(this, &clipping))
163				region.Exclude(&clipping);
164			view()->ConstrainClippingRegion(&region);
165			drawWire();
166		}
167		view()->PopState();
168	}
169}
170
171void DiagramWire::MouseDown(
172	BPoint point,
173	uint32 buttons,
174	uint32 clicks)
175{
176	D_METHOD(("DiagramWire::MouseDown()\n"));
177	if (clicks == 1)
178	{
179		if (isSelectable())
180		{
181			BMessage selectMsg(M_SELECTION_CHANGED);
182			if (modifiers() & B_SHIFT_KEY)
183			{
184				selectMsg.AddBool("replace", false);
185			}
186			else
187			{
188				selectMsg.AddBool("replace", true);
189			}
190			selectMsg.AddPointer("item", reinterpret_cast<void *>(this));
191			DiagramView* v = view();
192			BMessenger(v).SendMessage(&selectMsg);
193		}
194	}
195}
196
197void DiagramWire::MessageDragged(
198	BPoint point,
199	uint32 transit,
200	const BMessage *message)
201{
202	D_METHOD(("DiagramWire::MessageDragged()\n"));
203	switch (message->what)
204	{
205		case M_WIRE_DRAGGED:
206		{
207			view()->trackWire(point);
208			break;
209		}
210		default:
211		{
212			DiagramItem::MessageDragged(point, transit, message);
213		}
214	}
215}
216
217// END -- DiagramWire.cpp --
218