Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50 //== INCLUDES =================================================================
51 #include <QGraphicsSceneMouseEvent>
52 #include <QGraphicsScene>
53
54 #include "elementInOut.hh"
55 #include "elementInput.hh"
56 #include "elementOutput.hh"
57 #include "connection.hh"
58 #include "connectionPoint.hh"
59 #include "graphicsScene.hh"
60 #include "elementArea.hh"
61 #include "wayfind.hh"
62
63 //== NAMESPACES ===============================================================
64 namespace VSI {
65
66 //=============================================================================
67 //
68 // CLASS VSI::Connection - IMPLEMENTATION
69 //
70 //=============================================================================
71
73 Connection::Connection (ConnectionPoint *_start, QGraphicsScene *_scene) :
74 QGraphicsPathItem (dynamic_cast<GraphicsScene *>(_scene)->elementArea ()),
75 scene_ (dynamic_cast<GraphicsScene *>(_scene)),
76 p1_ (_start),
77 p2_ (0),
78 old_ (0)
79 {
80
81 elementArea_ = scene_->elementArea ();
82
83 QPen p = pen ();
84
85 p.setCapStyle (Qt::RoundCap);
86 p.setColor (QColor (128, 128, 128));
87
88 if (p1_->inOut ()->inOut ()->typeString () == "data")
89 p.setWidth (4);
90 else
91 p.setWidth (2);
92 setPen (p);
93 }
94
96 Connection::Connection (ConnectionPoint *_start, ConnectionPoint *_end, QGraphicsScene *_scene) :
97 QGraphicsPathItem (dynamic_cast<GraphicsScene *>(_scene)->elementArea ()),
98 scene_ (dynamic_cast<GraphicsScene *>(_scene)),
99 p1_ (_start),
100 p2_ (_end)
101 {
102 elementArea_ = scene_->elementArea ();
103
104 QPen p = pen ();
105
106 p.setCapStyle (Qt::RoundCap);
107
108 if (p1_->inOut ()->inOut ()->typeString () == "data")
109 p.setWidth (4);
110 else
111 p.setWidth (2);
112 setPen (p);
113
114 if (!p1_->inOut ()->validConnection (p2_->inOut ()))
115 {
116 deleteLater ();
117 p1_ = p2_ = 0;
118 return;
119 }
120
121 way_ = QPolygonF ();
122
123 p.setColor (QColor (0, 0, 0));
124 setPen (p);
125
126 p1_->inOut ()->addConnection (this);
127 p2_->inOut ()->addConnection (this);
128 }
129
131 Connection::~Connection ()
132 {
133 if (p1_)
134 p1_->inOut ()->removeConnection (this);
135 if (p2_)
136 p2_->inOut ()->removeConnection (this);
137 }
138
139 // handle mouse movement
140 void Connection::mouseMoveEvent (QGraphicsSceneMouseEvent *_event)
141 {
142 QPen p = pen ();
143
144 ConnectionPoint *pnt = cPointAt (_event->scenePos ());
145
146 if (pnt)
147 { if (p1_->inOut ()->validConnection (pnt->inOut ()))
148 p.setColor (QColor (0, 255, 0));
149 else
150 p.setColor (QColor (255, 0, 0));
151 }
152 else
153 p.setColor (QColor (128, 128, 128));
154 setPen (p);
155
156 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), elementArea_->mapFromScene (_event->scenePos ()).toPoint ());
157 updateLine ();
158 }
159
160 // Start new connection on mouse press
161 void Connection::mousePressEvent (QGraphicsSceneMouseEvent *_event)
162 {
163 if (p1_)
164 p1_->inOut ()->removeConnection (this);
165 if (p2_)
166 p2_->inOut ()->removeConnection (this);
167
168 QPointF p = p1_->connectPos () - _event->scenePos ();
169 qreal d1 = (p.x () * p.x()) + (p.y () * p.y ());
170 p = p2_->connectPos () - _event->scenePos ();
171 qreal d2 = (p.x () * p.x()) + (p.y () * p.y ());
172
173 if (d2 > d1)
174 {
175 old_ = p1_;
176 p1_ = p2_;
177 }
178
179 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), elementArea_->mapFromScene (_event->scenePos ()).toPoint ());
180 updateLine ();
181 }
182
183 // make a connection on relase at a valid connection point
184 void Connection::mouseReleaseEvent (QGraphicsSceneMouseEvent *_event)
185 {
186 scene_->setActiveConnection (0);
187
188 p2_ = cPointAt (_event->scenePos ());
189
190 if (!p2_ || !p1_->inOut ()->validConnection (p2_->inOut ()))
191 {
192 if (old_)
193 scene_->contentChange ();
194
195 deleteLater ();
196 p1_ = p2_ = 0;
197 return;
198 }
199
200 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), p2_->connectPos ().toPoint ());
201 updateLine ();
202
203 QPen p = pen ();
204
205 p.setColor (QColor (0, 0, 0));
206 setPen (p);
207
208 if (old_ != p2_)
209 scene_->contentChange ();
210
211 old_ = p2_;
212
213 p1_->inOut ()->addConnection (this);
214 p2_->inOut ()->addConnection (this);
215
216 }
217
218 // helper to localize a connection point
219 ConnectionPoint *Connection::cPointAt (QPointF _pnt)
220 {
221
222 ConnectionPoint *pnt = 0;
223
224 foreach (QGraphicsItem *i, scene ()->items (_pnt))
225 {
226 ConnectionPoint *pt = dynamic_cast<ConnectionPoint *>(i);
227
228 if (pt)
229 {
230 pnt = pt;
231 }
232 }
233
234 return pnt;
235 }
236
238 void Connection::updatePositions ()
239 {
240 way_ = scene_->wayFind ()->findWay (this, p1_->connectPos ().toPoint (), p2_->connectPos ().toPoint ());
241 updateLine ();
242 }
243
245 ElementInput *Connection::input ()
246 {
247 ElementInput *i = dynamic_cast<ElementInput *> (p1_->inOut ());
248 if (!i)
249 i = dynamic_cast<ElementInput *> (p2_->inOut ());
250 return i;
251 }
252
254 ElementOutput *Connection::output ()
255 {
256 ElementOutput *o = dynamic_cast<ElementOutput *> (p1_->inOut ());
257 if (!o && p2_)
258 o = dynamic_cast<ElementOutput *> (p2_->inOut ());
259 return o;
260 }
261
263 const QPolygonF & VSI::Connection::way () const
264 {
265 return way_;
266 }
267
269 void Connection::invalidate()
270 {
271 way_ = QPolygonF ();
272 setPath (QPainterPath ());
273 }
274
275 // generates a curved line out of the way polygon
276 void Connection::updateLine()
277 {
278 QPainterPath path;
279
280 if (way_.size () <= 1)
281 {
282 setPath (path);
283 return;
284 }
285 else if (way_.size () == 2)
286 {
287 path.addPolygon(way_);
288 setPath (path);
289 return;
290 }
291
292 path.moveTo (way_[0]);
293
294 QPointF a,b,c;
295
296 for (int i = 2; i < way_.size (); i++)
297 {
298 a = way_[i-2];
299 b = way_[i-1];
300 c = way_[i];
301
302 QLineF l1 (a,b), l2 (b,c);
303
304 int rad = qMin (40.0, qMin (l1.length() / 2, l2.length() / 2));
305
306 if (rad > 5)
307 rad -= rad % 5;
308
309 if (a.x () == b.x ())
310 {
311 if (a.y () > b.y ())
312 {
313 path.lineTo (b.x (), b.y () + rad);
314 if (c.x () > b.x ())
315 {
316 path.arcTo (b.x (), b.y (), 2 * rad, 2 * rad, 180, -90);
317 }
318 else
319 {
320 path.arcTo (b.x () - (rad * 2), b.y (), 2 * rad, 2 * rad, 0, 90);
321 }
322 }
323 else
324 {
325 path.lineTo (b.x (), b.y () - rad);
326 if (c.x () > b.x ())
327 {
328 path.arcTo (b.x (), b.y () - (rad * 2), 2 * rad, 2 * rad, 180, 90);
329 }
330 else
331 {
332 path.arcTo (b.x () - (rad * 2), b.y () - (rad * 2), 2 * rad, 2 * rad, 0, -90);
333 }
334 }
335 }
336 else
337 {
338 if (a.x () > b.x ())
339 {
340 path.lineTo (b.x () + rad, b.y ());
341 if (c.y () > b.y ())
342 {
343 path.arcTo (b.x (), b.y (), 2 * rad, 2 * rad, 90, 90);
344 }
345 else
346 {
347 path.arcTo (b.x (), b.y () - (rad * 2), 2 * rad, 2 * rad, 270, -90);
348 }
349 }
350 else
351 {
352 path.lineTo (b.x () - rad, b.y ());
353 if (c.y () > b.y ())
354 {
355 path.arcTo (b.x () - (rad * 2), b.y (), 2 * rad, 2 * rad, 90, -90);
356 }
357 else
358 {
359 path.arcTo (b.x () - (rad * 2), b.y () - (rad * 2), 2 * rad, 2 * rad, 270, 90);
360 }
361 }
362 }
363 }
364
365 path.lineTo (c);
366
367 setPath (path);
368 }
369
370 }
VSI
Definition: baseWidget.cc:78
VSI::ElementInOut::validConnection
bool validConnection(ElementInOut *_e)
Can this input/output be connected to _e.
Definition: elementInOut.cc:127
VSI::ElementInOut::removeConnection
virtual void removeConnection(Connection *_conn)
Remove the Connection.
Definition: elementInOut.cc:170
VSI::ElementOutput
Definition: elementOutput.hh:66
VSI::ElementInOut::inOut
InOut * inOut() const
InOut context object.
Definition: elementInOut.hh:116
VSI::ConnectionPoint::inOut
ElementInOut * inOut() const
Input/output element.
Definition: connectionPoint.hh:97
VSI::Connection::Connection
Connection(ConnectionPoint *_start, QGraphicsScene *_scene)
Constructor.
Definition: connection.cc:73
VSI::Connection::input
ElementInput * input()
Input of this connection.
Definition: connection.cc:245
VSI::GraphicsScene
Definition: graphicsScene.hh:86
VSI::ConnectionPoint::connectPos
QPointF connectPos()
Position for connections.
Definition: connectionPoint.cc:147
VSI::ElementInput
Definition: elementInput.hh:73
VSI::ElementInOut::addConnection
virtual void addConnection(Connection *_conn)
Add the connection.
Definition: elementInOut.cc:162
VSI::GraphicsScene::contentChange
void contentChange()
handle content changes
Definition: graphicsScene.cc:1113
VSI::ConnectionPoint
Definition: connectionPoint.hh:73
VSI::Connection::way
const QPolygonF & way() const
way of the connection
Definition: connection.cc:263
VSI::Connection::output
ElementOutput * output()
Output of this connection.
Definition: connection.cc:254
VSI::InOut::typeString
QString typeString() const
Type.
Definition: inout.cc:71
VSI::GraphicsScene::setActiveConnection
void setActiveConnection(Connection *_conn)
Sets the active connection.
Definition: graphicsScene.hh:150
VSI::GraphicsScene::wayFind
WayFind * wayFind()
WayFind object.
Definition: graphicsScene.hh:138
VSI::Connection::updatePositions
void updatePositions()
called to update position on element movement
Definition: connection.cc:238
VSI::GraphicsScene::elementArea
ElementArea * elementArea() const
Element area.
Definition: graphicsScene.hh:129
VSI::Connection::invalidate
void invalidate()
invalidate way
Definition: connection.cc:269
VSI::WayFind::findWay
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:101
VSI::Connection::~Connection
~Connection()
Destructor.
Definition: connection.cc:131