Developer Documentation
Loading...
Searching...
No Matches
connection.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44//== INCLUDES =================================================================
45#include <QGraphicsSceneMouseEvent>
46#include <QGraphicsScene>
47
48#include "elementInOut.hh"
49#include "elementInput.hh"
50#include "elementOutput.hh"
51#include "connection.hh"
52#include "connectionPoint.hh"
53#include "graphicsScene.hh"
54#include "elementArea.hh"
55#include "wayfind.hh"
56
57//== NAMESPACES ===============================================================
58namespace VSI {
59
60//=============================================================================
61//
62// CLASS VSI::Connection - IMPLEMENTATION
63//
64//=============================================================================
65
67Connection::Connection (ConnectionPoint *_start, QGraphicsScene *_scene) :
68 QGraphicsPathItem (dynamic_cast<GraphicsScene *>(_scene)->elementArea ()),
69 scene_ (dynamic_cast<GraphicsScene *>(_scene)),
70 p1_ (_start),
71 p2_ (0),
72 old_ (0)
73{
74
75 elementArea_ = scene_->elementArea ();
76
77 QPen p = pen ();
78
79 p.setCapStyle (Qt::RoundCap);
80 p.setColor (QColor (128, 128, 128));
81
82 if (p1_->inOut ()->inOut ()->typeString () == "data")
83 p.setWidth (4);
84 else
85 p.setWidth (2);
86 setPen (p);
87}
88
90Connection::Connection (ConnectionPoint *_start, ConnectionPoint *_end, QGraphicsScene *_scene) :
91 QGraphicsPathItem (dynamic_cast<GraphicsScene *>(_scene)->elementArea ()),
92 scene_ (dynamic_cast<GraphicsScene *>(_scene)),
93 p1_ (_start),
94 p2_ (_end)
95{
96 elementArea_ = scene_->elementArea ();
97
98 QPen p = pen ();
99
100 p.setCapStyle (Qt::RoundCap);
101
102 if (p1_->inOut ()->inOut ()->typeString () == "data")
103 p.setWidth (4);
104 else
105 p.setWidth (2);
106 setPen (p);
107
108 if (!p1_->inOut ()->validConnection (p2_->inOut ()))
109 {
110 deleteLater ();
111 p1_ = p2_ = 0;
112 return;
113 }
114
115 way_ = QPolygonF ();
116
117 p.setColor (QColor (0, 0, 0));
118 setPen (p);
119
120 p1_->inOut ()->addConnection (this);
121 p2_->inOut ()->addConnection (this);
122}
123
126{
127 if (p1_)
128 p1_->inOut ()->removeConnection (this);
129 if (p2_)
130 p2_->inOut ()->removeConnection (this);
131}
132
133// handle mouse movement
134void Connection::mouseMoveEvent (QGraphicsSceneMouseEvent *_event)
135{
136 QPen p = pen ();
137
138 ConnectionPoint *pnt = cPointAt (_event->scenePos ());
139
140 if (pnt)
141 { if (p1_->inOut ()->validConnection (pnt->inOut ()))
142 p.setColor (QColor (0, 255, 0));
143 else
144 p.setColor (QColor (255, 0, 0));
145 }
146 else
147 p.setColor (QColor (128, 128, 128));
148 setPen (p);
149
150 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), elementArea_->mapFromScene (_event->scenePos ()).toPoint ());
151 updateLine ();
152}
153
154// Start new connection on mouse press
155void Connection::mousePressEvent (QGraphicsSceneMouseEvent *_event)
156{
157 if (p1_)
158 p1_->inOut ()->removeConnection (this);
159 if (p2_)
160 p2_->inOut ()->removeConnection (this);
161
162 QPointF p = p1_->connectPos () - _event->scenePos ();
163 qreal d1 = (p.x () * p.x()) + (p.y () * p.y ());
164 p = p2_->connectPos () - _event->scenePos ();
165 qreal d2 = (p.x () * p.x()) + (p.y () * p.y ());
166
167 if (d2 > d1)
168 {
169 old_ = p1_;
170 p1_ = p2_;
171 }
172
173 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), elementArea_->mapFromScene (_event->scenePos ()).toPoint ());
174 updateLine ();
175}
176
177// make a connection on relase at a valid connection point
178void Connection::mouseReleaseEvent (QGraphicsSceneMouseEvent *_event)
179{
180 scene_->setActiveConnection (0);
181
182 p2_ = cPointAt (_event->scenePos ());
183
184 if (!p2_ || !p1_->inOut ()->validConnection (p2_->inOut ()))
185 {
186 if (old_)
187 scene_->contentChange ();
188
189 deleteLater ();
190 p1_ = p2_ = 0;
191 return;
192 }
193
194 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), p2_->connectPos ().toPoint ());
195 updateLine ();
196
197 QPen p = pen ();
198
199 p.setColor (QColor (0, 0, 0));
200 setPen (p);
201
202 if (old_ != p2_)
203 scene_->contentChange ();
204
205 old_ = p2_;
206
207 p1_->inOut ()->addConnection (this);
208 p2_->inOut ()->addConnection (this);
209
210}
211
212// helper to localize a connection point
213ConnectionPoint *Connection::cPointAt (QPointF _pnt)
214{
215
216 ConnectionPoint *pnt = 0;
217
218 foreach (QGraphicsItem *i, scene ()->items (_pnt))
219 {
220 ConnectionPoint *pt = dynamic_cast<ConnectionPoint *>(i);
221
222 if (pt)
223 {
224 pnt = pt;
225 }
226 }
227
228 return pnt;
229}
230
233{
234 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), p2_->connectPos ().toPoint ());
235 updateLine ();
236}
237
240{
241 ElementInput *i = dynamic_cast<ElementInput *> (p1_->inOut ());
242 if (!i)
243 i = dynamic_cast<ElementInput *> (p2_->inOut ());
244 return i;
245}
246
249{
250 ElementOutput *o = dynamic_cast<ElementOutput *> (p1_->inOut ());
251 if (!o && p2_)
252 o = dynamic_cast<ElementOutput *> (p2_->inOut ());
253 return o;
254}
255
257const QPolygonF & VSI::Connection::way () const
258{
259 return way_;
260}
261
264{
265 way_ = QPolygonF ();
266 setPath (QPainterPath ());
267}
268
269// generates a curved line out of the way polygon
270void Connection::updateLine()
271{
272 QPainterPath path;
273
274 if (way_.size () <= 1)
275 {
276 setPath (path);
277 return;
278 }
279 else if (way_.size () == 2)
280 {
281 path.addPolygon(way_);
282 setPath (path);
283 return;
284 }
285
286 path.moveTo (way_[0]);
287
288 QPointF a,b,c;
289
290 for (int i = 2; i < way_.size (); i++)
291 {
292 a = way_[i-2];
293 b = way_[i-1];
294 c = way_[i];
295
296 QLineF l1 (a,b), l2 (b,c);
297
298 int rad = qMin (40.0, qMin (l1.length() / 2, l2.length() / 2));
299
300 if (rad > 5)
301 rad -= rad % 5;
302
303 if (a.x () == b.x ())
304 {
305 if (a.y () > b.y ())
306 {
307 path.lineTo (b.x (), b.y () + rad);
308 if (c.x () > b.x ())
309 {
310 path.arcTo (b.x (), b.y (), 2 * rad, 2 * rad, 180, -90);
311 }
312 else
313 {
314 path.arcTo (b.x () - (rad * 2), b.y (), 2 * rad, 2 * rad, 0, 90);
315 }
316 }
317 else
318 {
319 path.lineTo (b.x (), b.y () - rad);
320 if (c.x () > b.x ())
321 {
322 path.arcTo (b.x (), b.y () - (rad * 2), 2 * rad, 2 * rad, 180, 90);
323 }
324 else
325 {
326 path.arcTo (b.x () - (rad * 2), b.y () - (rad * 2), 2 * rad, 2 * rad, 0, -90);
327 }
328 }
329 }
330 else
331 {
332 if (a.x () > b.x ())
333 {
334 path.lineTo (b.x () + rad, b.y ());
335 if (c.y () > b.y ())
336 {
337 path.arcTo (b.x (), b.y (), 2 * rad, 2 * rad, 90, 90);
338 }
339 else
340 {
341 path.arcTo (b.x (), b.y () - (rad * 2), 2 * rad, 2 * rad, 270, -90);
342 }
343 }
344 else
345 {
346 path.lineTo (b.x () - rad, b.y ());
347 if (c.y () > b.y ())
348 {
349 path.arcTo (b.x () - (rad * 2), b.y (), 2 * rad, 2 * rad, 90, -90);
350 }
351 else
352 {
353 path.arcTo (b.x () - (rad * 2), b.y () - (rad * 2), 2 * rad, 2 * rad, 270, 90);
354 }
355 }
356 }
357 }
358
359 path.lineTo (c);
360
361 setPath (path);
362}
363
364}
QPointF connectPos()
Position for connections.
ElementInOut * inOut() const
Input/output element.
ElementInput * input()
Input of this connection.
void updatePositions()
called to update position on element movement
void invalidate()
invalidate way
~Connection()
Destructor.
ElementOutput * output()
Output of this connection.
const QPolygonF & way() const
way of the connection
Connection(ConnectionPoint *_start, QGraphicsScene *_scene)
Constructor.
Definition connection.cc:67
InOut * inOut() const
InOut context object.
virtual void removeConnection(Connection *_conn)
Remove the Connection.
bool validConnection(ElementInOut *_e)
Can this input/output be connected to _e.
virtual void addConnection(Connection *_conn)
Add the connection.
void contentChange()
handle content changes
WayFind * wayFind()
WayFind object.
void setActiveConnection(Connection *_conn)
Sets the active connection.
ElementArea * elementArea() const
Element area.
QString typeString() const
Type.
Definition inout.cc:65
QPolygonF findWay(Connection *_conn, QPoint _from, QPoint _to)
Finds a way from _from to _to ignoring any already existent connections from _conn.
Definition wayfind.cc:94