Salome HOME
DCQ : Merge with Ecole_Ete_a6.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Link.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : SUPERVGUI_Link.cxx
8 //  Author : Vitaly SMETANNIKOV
9 //  Module : SUPERV
10
11 using namespace std;
12 #include "SUPERVGUI_Graph.h"
13 #include "SUPERVGUI_Main.h"
14 #include "SUPERVGUI_Link.h"
15
16
17
18 #define SKETCH_CLR Qt::green
19 #define DRAW_CLR Qt::black
20 #define HLT_CLR Qt::magenta
21 #define CTRL_CLR Qt::red
22
23 #define LINE_WIDTH 2
24 #define PNT_SIZE 6
25
26
27 // Prevents moving of several links at once
28 bool SUPERVGUI_Link::LinkIsMoving=false;
29
30 bool SUPERVGUI_Link::OrthoMode = false;
31
32 SUPERVGUI_Link* SUPERVGUI_Link::SelectedLink=0;
33
34 /**
35  * Consructor:
36  * If link is NULL - this must be defined later
37  */
38 SUPERVGUI_Link::SUPERVGUI_Link(SUPERVGUI_Graph* theGraph, SUPERV_Link theLink) {
39   myGraph = theGraph;
40   myEngine = theLink;
41   myPortIn = 0;
42   myPortInES = 0;
43   myPortOut = 0;
44   myStartPort = 0;
45   myHltPnt = -1;
46   myPntMovingState = false;
47   myPainter = 0;
48   myIsVisible = true;
49   myTmpPen.setColor(SKETCH_CLR);
50   myTmpPen.setWidth(LINE_WIDTH);
51   myIsSelected = false;
52   myTmpPoints.clear();
53
54   if (!SUPERV_isNull(myEngine))
55     connectToEvents();
56 }
57
58
59 //**********************************************************************
60 SUPERVGUI_Link::~SUPERVGUI_Link() {
61   if (!SUPERV_isNull(myEngine)) {
62     disconnect(myGraph, 0, this, 0);
63   }
64   if (SelectedLink == this) SelectedLink=0;
65   emit linkDeleted(this);
66 }
67
68
69 //**********************************************************************
70 void SUPERVGUI_Link::setInputPort(SUPERVGUI_PortIn* thePortIn) {
71   myPortIn = thePortIn;
72   myPortIn->setLinkPrs(this);
73 }
74
75
76 //**********************************************************************
77 void SUPERVGUI_Link::setInputPortES(SUPERVGUI_PortInESNode* thePortInES) {
78   myPortInES = thePortInES;
79   myPortInES->setLinkPrs(this);
80 }
81
82 //**********************************************************************
83 bool SUPERVGUI_Link::isESInputPort() {
84   if (myPortInES)
85     return true;
86   else
87     return false;
88 }
89
90 //**********************************************************************
91 void SUPERVGUI_Link::destroyEngine() {
92   if (!SUPERV_isNull(myEngine)) {
93     myEngine->destroy();
94   }
95 }
96
97 //**********************************************************************
98 void SUPERVGUI_Link::setOutputPort(SUPERVGUI_PortOut* thePortOut){
99   myPortOut = thePortOut;
100   myPortOut->addLinkPrs(this);
101 }
102
103
104 //**********************************************************************
105 void SUPERVGUI_Link::addPoint(long theX, long theY) {
106   if (SUPERV_isNull(myEngine)) return;
107
108   if (myEngine->CoordsSize() <= 0) {
109     myEngine->AddCoord(1, theX, theY);
110     return;
111   } else {
112     QPoint aPnt(theX, theY);
113     long aX, aY;
114     myEngine->Coords(1, aX, aY);
115     if (!isESInputPort()) {
116       if (distance(aPnt, myGraph->viewportToContents(myPortIn->getConnectPnt()), 
117                    QPoint(aX, aY)) <= 0) {
118         myEngine->AddCoord(1, theX, theY);
119         return;
120       }
121     }
122     else {
123       if (distance(aPnt, myGraph->viewportToContents(myPortInES->getConnectPnt()), 
124                    QPoint(aX, aY)) <= 0) {
125         myEngine->AddCoord(1, theX, theY);
126         return;
127       }
128     }
129
130     int i = 2;
131     long aNextX, aNextY;
132     for (i = 2; i <= myEngine->CoordsSize(); i++) {
133       myEngine->Coords(i, aNextX, aNextY);    
134       if (distance(aPnt,  QPoint(aX, aY), 
135                    QPoint(aNextX, aNextY)) <= 0) {
136         myEngine->AddCoord(i, theX, theY);
137         return;
138       }
139       aX = aNextX;
140       aY = aNextY;
141     }
142     if (distance(aPnt, QPoint(aX, aY), 
143                 myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
144       myEngine->AddCoord(myEngine->CoordsSize()+1, theX, theY);
145       return;
146     }
147   }
148   repaint();
149 }
150
151
152 //**********************************************************************
153 /**
154  * Can be used only in Sketching mode
155  */
156 void SUPERVGUI_Link::addTmpPoint(QPoint thePnt) { 
157   if (OrthoMode) {
158     int aSize = myTmpPoints.size();
159     QPoint aPrevPnt;
160     // Previous point
161     if (aSize > 0)
162       aPrevPnt = myTmpPoints[aSize-1];
163     else
164       aPrevPnt = myStartPort->getConnectPnt();
165
166     // Next point
167     QPoint aNewPoint;
168     if (Abs(thePnt.x() - aPrevPnt.x()) >
169         Abs(thePnt.y() - aPrevPnt.y())) {
170       aNewPoint = QPoint(thePnt.x(), aPrevPnt.y());
171     } else {
172       aNewPoint = QPoint(aPrevPnt.x(), thePnt.y());
173     }
174     // repaint last line
175    
176     myPainter->drawLine(aPrevPnt, thePnt);
177     myPainter->moveTo(aPrevPnt);
178     myPainter->lineTo(aNewPoint);
179     myPainter->lineTo(thePnt);
180     
181     myTmpPoints.push_back(aNewPoint);
182   } else 
183     myTmpPoints.push_back(thePnt); 
184 }
185
186
187 //**********************************************************************
188 /**
189  * Can be used only in Sketching mode
190  */
191 void SUPERVGUI_Link::delLastTmpPoint() { 
192   int aSize = myTmpPoints.size();
193   if (aSize > 0) {
194     QPoint aRemPnt = myTmpPoints[aSize-1];
195     
196     QPoint aLastPnt;
197     if (aSize > 1)
198       aLastPnt = myTmpPoints[aSize-2];
199     else
200       aLastPnt = myStartPort->getConnectPnt();
201
202     myPainter->moveTo(aLastPnt);
203     myPainter->lineTo(aRemPnt);
204     myPainter->lineTo(myPrevPoint);
205
206     myPainter->drawLine(aLastPnt, myPrevPoint);
207
208     myTmpPoints.pop_back();
209   }
210 }
211
212
213 //**********************************************************************
214 void SUPERVGUI_Link::removeLastPoint() {
215   if (myEngine && (!SUPERV_isNull(myEngine)))
216     myEngine->RemoveCoord(myEngine->CoordsSize());
217 }
218
219
220 //**********************************************************************
221 void SUPERVGUI_Link::removePoint(int thePnt) {
222   if ((thePnt > -1) && (!SUPERV_isNull(myEngine))) {
223     paint(true);
224     myEngine->RemoveCoord(thePnt);
225     paint(false);
226   }
227 }
228
229 //**********************************************************************
230 /**
231  * Repaints the link
232  */
233 void SUPERVGUI_Link::repaint() {
234   paint(true);
235   paint(false);
236 }
237
238
239 //**********************************************************************
240 /**
241  * Paints or erases the link
242  * if toErase = true then it draws link by background color
243  */
244 void SUPERVGUI_Link::paint(bool toErase) {
245   if ((!myGraph) || (!myIsVisible)) return;
246   if (!myEngine && SUPERV_isNull(myEngine)) return;
247   //  if (!isCreationComplete()) return;
248
249   QPainter aPainter(myGraph->viewport());
250   QPen aDataPen;
251   aDataPen.setWidth(LINE_WIDTH);
252
253   if (toErase) {
254     aDataPen.setColor(myGraph->viewport()->paletteBackgroundColor());
255   } else {
256     if ((strcmp(myEngine->InPort()->Name(), "InVoid")==0) || 
257         (myEngine->InPort()->Kind() == SUPERV::DataStreamParameter ))
258       aDataPen.setColor(CTRL_CLR);
259     else
260       aDataPen.setColor(DRAW_CLR);
261   }
262   aPainter.setPen(aDataPen);
263   drawLink(&aPainter);
264 }
265
266
267 //**********************************************************************
268 /**
269  * Defines a pen and draws link using given painter
270  */
271 void SUPERVGUI_Link::paint(QPainter* thePainter, bool toErase) {
272   if ((!myGraph) || (!myIsVisible)) return;
273   if (!myEngine && SUPERV_isNull(myEngine)) return;
274   //  if (!isCreationComplete()) return;
275   thePainter->save();
276
277   QPen aDataPen;
278   aDataPen.setWidth(LINE_WIDTH);
279
280   if (toErase) {
281     aDataPen.setColor(myGraph->viewport()->paletteBackgroundColor());
282   } else {
283     if ((strcmp(myEngine->InPort()->Name(), "InVoid")==0)|| 
284         (myEngine->InPort()->Kind() == SUPERV::DataStreamParameter ))
285       aDataPen.setColor(CTRL_CLR);
286     else
287       aDataPen.setColor(DRAW_CLR);
288   }
289   thePainter->setPen(aDataPen);
290   drawLink(thePainter);
291   thePainter->restore();
292 }
293
294
295 //**********************************************************************
296 /**
297  * Draws link using given painter
298  */
299 void SUPERVGUI_Link::drawLink(QPainter* thePainter) {
300   if (!myIsVisible) return;
301   if (!isESInputPort())
302     thePainter->moveTo(myPortIn->getConnectPnt());
303   else
304     thePainter->moveTo(myPortInES->getConnectPnt());    
305   long aX, aY;
306   QPoint aPnt;
307   for (int i=0; i < myEngine->CoordsSize(); i++) {
308     myEngine->Coords(i+1, aX, aY);
309     aPnt = myGraph->contentsToViewport(QPoint(aX, aY));
310     thePainter->lineTo(aPnt);
311     thePainter->drawEllipse(aPnt.x()-PNT_SIZE/2, aPnt.y()-PNT_SIZE/2, 
312                             PNT_SIZE, PNT_SIZE);
313   }
314   thePainter->lineTo(myPortOut->getConnectPnt());
315 }
316
317
318 //**********************************************************************
319 /**
320  * Repaints whole link when it is sketching
321  */
322 void SUPERVGUI_Link::repaintSketch() {
323   if (!myStartPort) return;
324   if (!myPainter) return;
325
326   //  myPainter->save();
327   //myPainter->setRasterOp(Qt::CopyROP);
328   myPainter->moveTo(myStartPort->getConnectPnt());
329   for (int i = 0; i< myTmpPoints.size(); i++) {
330     myPainter->lineTo(myGraph->contentsToViewport(myTmpPoints[i]));
331   }
332   myPainter->lineTo(myPrevPoint);
333   //myPainter->restore();
334 }
335
336
337 //**********************************************************************
338 /**
339  * Drawing of non created link following to mouse pointer
340  */
341 void SUPERVGUI_Link::drawTo(QPoint thePnt) {
342   if (!myStartPort) {
343     if (myPortIn)
344       myStartPort = myPortIn;
345     else if (myPortInES)
346       myStartPort = myPortInES;
347     else if (myPortOut)
348       myStartPort = myPortOut;
349     else
350       return;
351   }
352   if (!myPainter) {
353     myPainter = new QPainter(myGraph->viewport());
354     myPainter->setPen(myTmpPen);
355     myPainter->setRasterOp(Qt::XorROP);
356     myPrevPoint = myStartPort->getConnectPnt();
357     LinkIsMoving = true;
358   }
359
360   long aX, aY;
361
362   QPoint aStartPnt;
363   if (myTmpPoints.size() > 0) 
364     aStartPnt = myGraph->contentsToViewport(myTmpPoints[myTmpPoints.size()-1]);
365   else
366     aStartPnt = myStartPort->getConnectPnt();
367
368   // erase old line
369   myPainter->drawLine(aStartPnt, myPrevPoint);
370
371   // draw new line
372   QPoint aNewPoint = myGraph->contentsToViewport(thePnt);
373   myPainter->drawLine(aStartPnt, aNewPoint);
374   myPrevPoint = aNewPoint;
375
376 }
377
378
379 //**********************************************************************
380 /**
381  * Set link non visible
382  */
383 void SUPERVGUI_Link::setVisible(bool theVisible) {
384   myIsVisible = theVisible;
385   if (myIsVisible) {
386     connectToEvents();
387   } else {
388     disconnect(myGraph, 0, this, 0);
389   }
390 }
391
392
393 //**********************************************************************
394 /**
395  * Checks full definition of the link
396  */
397 bool SUPERVGUI_Link::isCreationComplete() {
398   bool aIsBoth = myPortIn && myPortOut;
399   if (myPortIn && myPortOut) {
400     // Check: is the same node?
401     SUPERV_Port aInPort = myPortIn->getPort();
402     QString aInNodeName(aInPort->Node()->Name());
403     SUPERV_Port aOutPort = myPortOut->getPort();
404     QString aOutNodeName(aOutPort->Node()->Name());
405
406     bool aCanCreate = true;
407     // Stream port can be connected only with stream port
408     if (myPortIn->getPort()->Kind() == SUPERV::DataStreamParameter)
409       aCanCreate = (myPortOut->getPort()->Kind() == SUPERV::DataStreamParameter);
410     else if (myPortOut->getPort()->Kind() == SUPERV::DataStreamParameter)
411       aCanCreate = (myPortIn->getPort()->Kind() == SUPERV::DataStreamParameter);
412     
413     return aCanCreate && (aInNodeName != aOutNodeName);
414   }
415   else if (myPortInES && myPortOut) {
416     SUPERV_Port aInPortES = myPortInES->getPort();
417     QString aInNodeName(aInPortES->Node()->Name());
418     SUPERV_Port aOutPort = myPortOut->getPort();
419     QString aOutNodeName(aOutPort->Node()->Name());
420     
421     return (aInNodeName != aOutNodeName);
422   }
423   else 
424     return false;
425 }
426
427 //**********************************************************************
428 /** 
429  * Abort creation of link
430  */
431 void SUPERVGUI_Link::abortCreation() {
432   LinkIsMoving = false;
433 }
434
435 //**********************************************************************
436 /** 
437  * Final procedure of link creation
438  */
439 bool SUPERVGUI_Link::createEngine() {
440   // clear temporary drawing
441   QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
442   //check if myPainter not null
443   if (myPainter) {
444     myPainter->setPen(aOldPen);
445     myPainter->setRasterOp(Qt::CopyROP);
446     
447     QPoint aStartPnt;
448     if (myTmpPoints.size() > 0) 
449       aStartPnt = myGraph->contentsToViewport(myTmpPoints[myTmpPoints.size()-1]);
450     else
451       aStartPnt = myStartPort->getConnectPnt();
452     
453     myPainter->drawLine(aStartPnt, myPrevPoint);
454
455     delete myPainter;
456     myPainter = 0;
457   }
458     
459   // Create engine
460   if (!isESInputPort()) {
461     if (myStartPort->getPort()->Kind() == SUPERV::DataStreamParameter) {
462       SUPERVGUI_StreamPortOut* aOut = dynamic_cast<SUPERVGUI_StreamPortOut*>(myPortOut);
463       SUPERVGUI_StreamPortIn* aIn = dynamic_cast<SUPERVGUI_StreamPortIn*>(myPortIn);
464       myEngine = myGraph->getMain()->getDataflow()->
465         StreamLink(aOut->getStreamPort(), aIn->getStreamPort());
466     } else
467       myEngine = myGraph->getMain()->getDataflow()->
468         Link(myPortOut->getPort(), myPortIn->getPort());
469   } else
470     myEngine = myGraph->getMain()->getDataflow()->
471       Link(myPortOut->getPort(), myPortInES->getPort());
472
473   if (SUPERV_isNull(myEngine)) return false;
474
475   // remember all points
476   QPoint aPnt;
477   if (myStartPort == myPortOut) {
478     int aSize = myTmpPoints.size();
479     for (int i = aSize; i > 0; i--) {
480       aPnt = myTmpPoints[i-1];
481       myEngine->AddCoord(aSize+1-i, aPnt.x(), aPnt.y());
482     }
483   } else {
484     for (int i = 0; i < myTmpPoints.size(); i++) {
485       aPnt = myTmpPoints[i];
486       myEngine->AddCoord(i+1, aPnt.x(), aPnt.y());
487     }
488   }
489   LinkIsMoving = false;
490
491   // empty temporary resources
492   myTmpPoints.clear();
493   myStartPort = 0;
494   connectToEvents();
495   paint(false);
496   return true;
497 }
498
499
500
501 //**********************************************************************
502 void SUPERVGUI_Link::onMouseMove(QMouseEvent * theEvent) {
503   if (myPntMovingState) {
504     drawSegments();
505
506     QPoint aPos = myGraph->contentsToViewport(theEvent->pos());
507     int aX = (aPos.x() > 0)? aPos.x(): 1;
508     int aY = (aPos.y() > 0)? aPos.y(): 1;
509     aX = (aX < myGraph->contentsWidth())? aX: myGraph->contentsWidth()-1;
510     aY = (aY < myGraph->contentsHeight())? aY: myGraph->contentsHeight()-1;
511
512     myMovedPnt = QPoint(aX, aY);
513     drawSegments();
514     return;
515   }
516
517   if (LinkIsMoving) return;
518
519   // Points highlighting
520   QPoint aPos = theEvent->pos();
521   if (myEngine->CoordsSize() > 0 ) {
522     long aX, aY;
523     bool aIsFound = false;
524     for (int i=0; i < myEngine->CoordsSize(); i++) {
525       myEngine->Coords(i+1, aX, aY);
526       if (distance(aX, aY, 
527                    aPos.x(), 
528                    aPos.y()) < (PNT_SIZE+2)) {
529         myHltPnt = i+1;
530         aIsFound = true;
531         break;
532       }
533     }
534     if (!aIsFound) myHltPnt = -1;
535   }
536
537   // Highlight line
538   if (isSelected(aPos)) {
539     if (SelectedLink==0) {
540       QPen aNewPen(HLT_CLR, LINE_WIDTH);
541       QPainter aPainter(myGraph->viewport());
542       aPainter.setPen(aNewPen);
543       drawLink(&aPainter);
544       myIsSelected = true;
545       SelectedLink = this;
546     }
547   } else if (myIsSelected) {
548     myIsSelected = false;
549     if (SelectedLink == this) SelectedLink = 0;
550     paint(false);
551   }
552 }
553
554
555 //**********************************************************************
556 /**
557  * For internal using only
558  * Draws segments by current Pen when point is moving
559  */
560 void SUPERVGUI_Link::drawSegments() {
561   myPainter->drawLine(myBeforePnt, myMovedPnt);
562   myPainter->drawLine(myMovedPnt, myAfterPnt);
563   myPainter->drawEllipse(myMovedPnt.x()-PNT_SIZE/2, 
564                          myMovedPnt.y()-PNT_SIZE/2, 
565                          PNT_SIZE, PNT_SIZE);
566 }
567
568
569 //**********************************************************************
570 void SUPERVGUI_Link::onMousePress(QMouseEvent * theEvent) {
571   if (LinkIsMoving) {
572     return;
573   }
574   if (theEvent->button() != Qt::LeftButton) {
575     SelectedLink = 0;
576     myHltPnt = -1;
577     return;
578   }
579   if (myHltPnt > -1) { // start point moving
580     if (myHltPnt == 1) {
581       if (!isESInputPort()) {
582         myBeforePnt = myPortIn->getConnectPnt();
583       }
584       else {
585         myBeforePnt = myPortInES->getConnectPnt();      
586       }
587     }
588     else {
589       long aX, aY;
590       myEngine->Coords(myHltPnt-1, aX, aY);
591       myBeforePnt = myGraph->contentsToViewport(QPoint(aX, aY));
592     }
593     if (myHltPnt == myEngine->CoordsSize()) 
594       myAfterPnt = myPortOut->getConnectPnt();
595     else {
596       long aX, aY;
597       myEngine->Coords(myHltPnt+1, aX, aY);
598       myAfterPnt = myGraph->contentsToViewport(QPoint(aX, aY));
599     }
600     long aX, aY;
601     myEngine->Coords(myHltPnt, aX, aY);
602     myMovedPnt = myGraph->contentsToViewport(QPoint(aX, aY));
603
604     myPainter = new QPainter(myGraph->viewport());
605     QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
606
607     myPainter->setPen(aOldPen); 
608     drawSegments();
609
610     myPainter->setPen(myTmpPen);
611     myPainter->setRasterOp(Qt::XorROP);
612     drawSegments();
613
614     myPntMovingState = true;
615     LinkIsMoving = true;
616   } else if (myHltPnt > -1)
617     paint(false);
618 }
619
620 //**********************************************************************
621 void SUPERVGUI_Link::onMouseRelease(QMouseEvent * theEvent){
622   if (theEvent->button() != Qt::LeftButton) return;
623
624   if (myPntMovingState) {
625     myPntMovingState = false;
626     LinkIsMoving = false;
627     drawSegments();
628     delete myPainter;
629     myPainter = 0;
630
631     int aX = (theEvent->pos().x() > 0)? theEvent->pos().x(): 1;
632     int aY = (theEvent->pos().y() > 0)? theEvent->pos().y(): 1;
633     aX = (aX < myGraph->contentsWidth())? aX: myGraph->contentsWidth()-1;
634     aY = (aY < myGraph->contentsHeight())? aY: myGraph->contentsHeight()-1;
635     myEngine->ChangeCoord(myHltPnt, aX, aY);
636
637     paint(false);
638   }  
639 }
640
641 //**********************************************************************
642 /**
643  * Connects to the Graph mouse events
644  */
645 void SUPERVGUI_Link::connectToEvents() {
646   connect(myGraph, SIGNAL(mouseMoved(QMouseEvent*)),
647           this, SLOT(onMouseMove(QMouseEvent*)));
648
649   connect(myGraph, SIGNAL(mousePressed(QMouseEvent*)),
650           this, SLOT(onMousePress(QMouseEvent*)));
651
652   connect(myGraph, SIGNAL(mouseReleased(QMouseEvent*)),
653           this, SLOT(onMouseRelease(QMouseEvent*)));
654 }
655
656
657 //**********************************************************************
658 bool SUPERVGUI_Link::isSelected(QPoint thePnt) {
659   if (myEngine->CoordsSize() == 0) {
660     if (!isESInputPort()) {
661       return (distance(thePnt,  myGraph->viewportToContents(myPortOut->getConnectPnt()), 
662                        myGraph->viewportToContents(myPortIn->getConnectPnt())) <= 0); 
663     }
664     else {
665       return (distance(thePnt,  myGraph->viewportToContents(myPortOut->getConnectPnt()), 
666                        myGraph->viewportToContents(myPortInES->getConnectPnt())) <= 0); 
667     }
668   }
669   else {
670     long aX, aY;
671     myEngine->Coords(1, aX, aY);    
672     if (!isESInputPort()) { 
673       if (distance(thePnt, myGraph->viewportToContents(myPortIn->getConnectPnt()), 
674                    QPoint(aX, aY)) <= 0) {
675         return true;
676       }
677     }
678     else {
679       if (distance(thePnt, myGraph->viewportToContents(myPortInES->getConnectPnt()), 
680                    QPoint(aX, aY)) <= 0) {
681         return true;
682       }
683     }
684         
685     int i = 2;
686     long aNextX, aNextY;
687     for (i = 2; i <= myEngine->CoordsSize(); i++) {
688       myEngine->Coords(i, aNextX, aNextY);    
689       if (distance(thePnt,  QPoint(aX, aY), 
690                    QPoint(aNextX, aNextY)) <= 0) {
691         return true;
692       }
693       aX = aNextX;
694       aY = aNextY;
695     }
696     if (distance(thePnt, QPoint(aX, aY), 
697                  myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
698       return true;
699     }
700   }
701   return false;
702 }
703
704
705 //**********************************************************************
706 /**
707  * Returns true if at least one point is within the rect.
708  * Rect must be in contents coordinate space
709  */
710 bool SUPERVGUI_Link::isInRect(int theX, int theY, int theW, int theH) {
711   QRect aRect(theX, theY, theW, theH);
712   if (aRect.contains(myGraph->viewportToContents(myPortOut->getConnectPnt()), true))
713     return true;
714
715   if (!isESInputPort()) {
716     if (aRect.contains(myGraph->viewportToContents(myPortIn->getConnectPnt()), true)) {
717       return true;
718     }
719   }
720   else {
721     if (aRect.contains(myGraph->viewportToContents(myPortInES->getConnectPnt()), true)) {
722       return true;
723     }
724   }
725   
726   long aX, aY;
727   QPoint aPrevPnt;
728   if (!isESInputPort())
729     aPrevPnt = myGraph->viewportToContents(myPortIn->getConnectPnt());
730   else
731     aPrevPnt = myGraph->viewportToContents(myPortInES->getConnectPnt());    
732   for (int i = 1; i <= myEngine->CoordsSize(); i++) {
733     myEngine->Coords(i, aX, aY);   
734     if (aRect.contains(aX, aY, true))
735       return true;
736     else {
737       QRect aTmpRect(QPoint(QMIN(aPrevPnt.x(), aX), 
738                             QMIN(aPrevPnt.y(), aY)),
739                      QPoint(QMAX(aPrevPnt.x(), aX),
740                             QMAX(aPrevPnt.y(), aY)));
741       if (aRect.intersects(aTmpRect))
742         return true;
743       aPrevPnt = QPoint(aX, aY);
744     }
745   }
746   QPoint aLastPnt = myGraph->viewportToContents(myPortOut->getConnectPnt());
747   QRect aLastRect(QPoint(QMIN(aPrevPnt.x(), aLastPnt.x()), 
748                          QMIN(aPrevPnt.y(), aLastPnt.y())),
749                   QPoint(QMAX(aPrevPnt.x(), aLastPnt.x()),
750                          QMAX(aPrevPnt.y(), aLastPnt.y())));
751   if (aRect.intersects(aLastRect))
752     return true;
753
754   return false;
755 }
756
757
758 //**********************************************************************
759 /**
760  * Calculates distance between points
761  */
762 int distance(int x1, int y1, int x2, int y2) {
763   int x = x2 - x1;
764   x = x * x;
765   int y = y2 - y1;
766   y = y * y;
767   return (int) sqrt((double)(x + y));
768 }
769
770
771 //**********************************************************************
772 /**
773  * Finds distance between thePnt and line(thePntLn1, thePntLn2)
774  * Returned value is not an mathematical value - this is only estimation of
775  * of closing point to the line. 0 - means that point belongs to the line
776  */
777 int distance(QPoint thePnt, QPoint thePntLn1, QPoint thePntLn2) {
778   int r, s;
779   int a, b, c;
780   
781   int px = thePnt.x();
782   int py = thePnt.y();
783   int lx = thePntLn1.x();
784   int ly = thePntLn1.y();
785   int nx = thePntLn2.x();
786   int ny = thePntLn2.y();
787   
788   r = px - lx;
789   r = r * r;
790   s = py - ly;
791   s = s * s;
792   a = (int) sqrt((double)(r + s));
793
794   r = px - nx;
795   r = r * r;
796   s = py - ny;
797   s = s * s;
798   b = (int) sqrt((double)(r + s));
799   
800   r = nx - lx;
801   r = r * r;
802   s = ny - ly;
803   s = s * s;
804   c = (int) sqrt((double)(r + s));
805
806   return (a+b-c);
807 }
808
809 void SUPERVGUI_Link::setBeginPort(SUPERVGUI_Port* theBeginPort) {
810   myBeginPort = theBeginPort;
811 }
812
813 SUPERVGUI_Port* SUPERVGUI_Link::getBeginPort() {
814   return myBeginPort;
815 }
816
817