Salome HOME
A new dialog class for edition of Ports of an InLine nodes is introduced. This funct...
[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()->StreamLink(aOut->getStreamPort(), aIn->getStreamPort());
465       SUPERV_StreamGraph aSGraph = myGraph->getMain()->getDataflow()->ToStreamGraph();
466       if (!SUPERV_isNull(aSGraph))
467         myEngine = aSGraph->StreamLink(aOut->getStreamPort(), aIn->getStreamPort());
468     } else
469       myEngine = myGraph->getMain()->getDataflow()->
470         Link(myPortOut->getPort(), myPortIn->getPort());
471   } else
472     myEngine = myGraph->getMain()->getDataflow()->
473       Link(myPortOut->getPort(), myPortInES->getPort());
474
475   if (SUPERV_isNull(myEngine)) return false;
476
477   // remember all points
478   QPoint aPnt;
479   if (myStartPort == myPortOut) {
480     int aSize = myTmpPoints.size();
481     for (int i = aSize; i > 0; i--) {
482       aPnt = myTmpPoints[i-1];
483       myEngine->AddCoord(aSize+1-i, aPnt.x(), aPnt.y());
484     }
485   } else {
486     for (int i = 0; i < myTmpPoints.size(); i++) {
487       aPnt = myTmpPoints[i];
488       myEngine->AddCoord(i+1, aPnt.x(), aPnt.y());
489     }
490   }
491   LinkIsMoving = false;
492
493   // empty temporary resources
494   myTmpPoints.clear();
495   myStartPort = 0;
496   connectToEvents();
497   paint(false);
498   return true;
499 }
500
501
502
503 //**********************************************************************
504 void SUPERVGUI_Link::onMouseMove(QMouseEvent * theEvent) {
505   if (myPntMovingState) {
506     drawSegments();
507
508     QPoint aPos = myGraph->contentsToViewport(theEvent->pos());
509     int aX = (aPos.x() > 0)? aPos.x(): 1;
510     int aY = (aPos.y() > 0)? aPos.y(): 1;
511     aX = (aX < myGraph->contentsWidth())? aX: myGraph->contentsWidth()-1;
512     aY = (aY < myGraph->contentsHeight())? aY: myGraph->contentsHeight()-1;
513
514     myMovedPnt = QPoint(aX, aY);
515     drawSegments();
516     return;
517   }
518
519   if (LinkIsMoving) return;
520
521   // Points highlighting
522   QPoint aPos = theEvent->pos();
523   if (myEngine->CoordsSize() > 0 ) {
524     long aX, aY;
525     bool aIsFound = false;
526     for (int i=0; i < myEngine->CoordsSize(); i++) {
527       myEngine->Coords(i+1, aX, aY);
528       if (distance(aX, aY, 
529                    aPos.x(), 
530                    aPos.y()) < (PNT_SIZE+2)) {
531         myHltPnt = i+1;
532         aIsFound = true;
533         break;
534       }
535     }
536     if (!aIsFound) myHltPnt = -1;
537   }
538
539   // Highlight line
540   if (isSelected(aPos)) {
541     if (SelectedLink==0) {
542       QPen aNewPen(HLT_CLR, LINE_WIDTH);
543       QPainter aPainter(myGraph->viewport());
544       aPainter.setPen(aNewPen);
545       drawLink(&aPainter);
546       myIsSelected = true;
547       SelectedLink = this;
548     }
549   } else if (myIsSelected) {
550     myIsSelected = false;
551     if (SelectedLink == this) SelectedLink = 0;
552     paint(false);
553   }
554 }
555
556
557 //**********************************************************************
558 /**
559  * For internal using only
560  * Draws segments by current Pen when point is moving
561  */
562 void SUPERVGUI_Link::drawSegments() {
563   myPainter->drawLine(myBeforePnt, myMovedPnt);
564   myPainter->drawLine(myMovedPnt, myAfterPnt);
565   myPainter->drawEllipse(myMovedPnt.x()-PNT_SIZE/2, 
566                          myMovedPnt.y()-PNT_SIZE/2, 
567                          PNT_SIZE, PNT_SIZE);
568 }
569
570
571 //**********************************************************************
572 void SUPERVGUI_Link::onMousePress(QMouseEvent * theEvent) {
573   if (LinkIsMoving) {
574     return;
575   }
576   if (theEvent->button() != Qt::LeftButton) {
577     SelectedLink = 0;
578     myHltPnt = -1;
579     return;
580   }
581   if (myHltPnt > -1) { // start point moving
582     if (myHltPnt == 1) {
583       if (!isESInputPort()) {
584         myBeforePnt = myPortIn->getConnectPnt();
585       }
586       else {
587         myBeforePnt = myPortInES->getConnectPnt();      
588       }
589     }
590     else {
591       long aX, aY;
592       myEngine->Coords(myHltPnt-1, aX, aY);
593       myBeforePnt = myGraph->contentsToViewport(QPoint(aX, aY));
594     }
595     if (myHltPnt == myEngine->CoordsSize()) 
596       myAfterPnt = myPortOut->getConnectPnt();
597     else {
598       long aX, aY;
599       myEngine->Coords(myHltPnt+1, aX, aY);
600       myAfterPnt = myGraph->contentsToViewport(QPoint(aX, aY));
601     }
602     long aX, aY;
603     myEngine->Coords(myHltPnt, aX, aY);
604     myMovedPnt = myGraph->contentsToViewport(QPoint(aX, aY));
605
606     myPainter = new QPainter(myGraph->viewport());
607     QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
608
609     myPainter->setPen(aOldPen); 
610     drawSegments();
611
612     myPainter->setPen(myTmpPen);
613     myPainter->setRasterOp(Qt::XorROP);
614     drawSegments();
615
616     myPntMovingState = true;
617     LinkIsMoving = true;
618   } else if (myHltPnt > -1)
619     paint(false);
620 }
621
622 //**********************************************************************
623 void SUPERVGUI_Link::onMouseRelease(QMouseEvent * theEvent){
624   if (theEvent->button() != Qt::LeftButton) return;
625
626   if (myPntMovingState) {
627     myPntMovingState = false;
628     LinkIsMoving = false;
629     drawSegments();
630     delete myPainter;
631     myPainter = 0;
632
633     int aX = (theEvent->pos().x() > 0)? theEvent->pos().x(): 1;
634     int aY = (theEvent->pos().y() > 0)? theEvent->pos().y(): 1;
635     aX = (aX < myGraph->contentsWidth())? aX: myGraph->contentsWidth()-1;
636     aY = (aY < myGraph->contentsHeight())? aY: myGraph->contentsHeight()-1;
637     myEngine->ChangeCoord(myHltPnt, aX, aY);
638
639     paint(false);
640   }  
641 }
642
643 //**********************************************************************
644 /**
645  * Connects to the Graph mouse events
646  */
647 void SUPERVGUI_Link::connectToEvents() {
648   connect(myGraph, SIGNAL(mouseMoved(QMouseEvent*)),
649           this, SLOT(onMouseMove(QMouseEvent*)));
650
651   connect(myGraph, SIGNAL(mousePressed(QMouseEvent*)),
652           this, SLOT(onMousePress(QMouseEvent*)));
653
654   connect(myGraph, SIGNAL(mouseReleased(QMouseEvent*)),
655           this, SLOT(onMouseRelease(QMouseEvent*)));
656 }
657
658
659 //**********************************************************************
660 bool SUPERVGUI_Link::isSelected(QPoint thePnt) {
661   if (myEngine->CoordsSize() == 0) {
662     if (!isESInputPort()) {
663       return (distance(thePnt,  myGraph->viewportToContents(myPortOut->getConnectPnt()), 
664                        myGraph->viewportToContents(myPortIn->getConnectPnt())) <= 0); 
665     }
666     else {
667       return (distance(thePnt,  myGraph->viewportToContents(myPortOut->getConnectPnt()), 
668                        myGraph->viewportToContents(myPortInES->getConnectPnt())) <= 0); 
669     }
670   }
671   else {
672     long aX, aY;
673     myEngine->Coords(1, aX, aY);    
674     if (!isESInputPort()) { 
675       if (distance(thePnt, myGraph->viewportToContents(myPortIn->getConnectPnt()), 
676                    QPoint(aX, aY)) <= 0) {
677         return true;
678       }
679     }
680     else {
681       if (distance(thePnt, myGraph->viewportToContents(myPortInES->getConnectPnt()), 
682                    QPoint(aX, aY)) <= 0) {
683         return true;
684       }
685     }
686         
687     int i = 2;
688     long aNextX, aNextY;
689     for (i = 2; i <= myEngine->CoordsSize(); i++) {
690       myEngine->Coords(i, aNextX, aNextY);    
691       if (distance(thePnt,  QPoint(aX, aY), 
692                    QPoint(aNextX, aNextY)) <= 0) {
693         return true;
694       }
695       aX = aNextX;
696       aY = aNextY;
697     }
698     if (distance(thePnt, QPoint(aX, aY), 
699                  myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
700       return true;
701     }
702   }
703   return false;
704 }
705
706
707 //**********************************************************************
708 /**
709  * Returns true if at least one point is within the rect.
710  * Rect must be in contents coordinate space
711  */
712 bool SUPERVGUI_Link::isInRect(int theX, int theY, int theW, int theH) {
713   QRect aRect(theX, theY, theW, theH);
714   if (aRect.contains(myGraph->viewportToContents(myPortOut->getConnectPnt()), true))
715     return true;
716
717   if (!isESInputPort()) {
718     if (aRect.contains(myGraph->viewportToContents(myPortIn->getConnectPnt()), true)) {
719       return true;
720     }
721   }
722   else {
723     if (aRect.contains(myGraph->viewportToContents(myPortInES->getConnectPnt()), true)) {
724       return true;
725     }
726   }
727   
728   long aX, aY;
729   QPoint aPrevPnt;
730   if (!isESInputPort())
731     aPrevPnt = myGraph->viewportToContents(myPortIn->getConnectPnt());
732   else
733     aPrevPnt = myGraph->viewportToContents(myPortInES->getConnectPnt());    
734   for (int i = 1; i <= myEngine->CoordsSize(); i++) {
735     myEngine->Coords(i, aX, aY);   
736     if (aRect.contains(aX, aY, true))
737       return true;
738     else {
739       QRect aTmpRect(QPoint(QMIN(aPrevPnt.x(), aX), 
740                             QMIN(aPrevPnt.y(), aY)),
741                      QPoint(QMAX(aPrevPnt.x(), aX),
742                             QMAX(aPrevPnt.y(), aY)));
743       if (aRect.intersects(aTmpRect))
744         return true;
745       aPrevPnt = QPoint(aX, aY);
746     }
747   }
748   QPoint aLastPnt = myGraph->viewportToContents(myPortOut->getConnectPnt());
749   QRect aLastRect(QPoint(QMIN(aPrevPnt.x(), aLastPnt.x()), 
750                          QMIN(aPrevPnt.y(), aLastPnt.y())),
751                   QPoint(QMAX(aPrevPnt.x(), aLastPnt.x()),
752                          QMAX(aPrevPnt.y(), aLastPnt.y())));
753   if (aRect.intersects(aLastRect))
754     return true;
755
756   return false;
757 }
758
759
760 //**********************************************************************
761 /**
762  * Calculates distance between points
763  */
764 int distance(int x1, int y1, int x2, int y2) {
765   int x = x2 - x1;
766   x = x * x;
767   int y = y2 - y1;
768   y = y * y;
769   return (int) sqrt((double)(x + y));
770 }
771
772
773 //**********************************************************************
774 /**
775  * Finds distance between thePnt and line(thePntLn1, thePntLn2)
776  * Returned value is not an mathematical value - this is only estimation of
777  * of closing point to the line. 0 - means that point belongs to the line
778  */
779 int distance(QPoint thePnt, QPoint thePntLn1, QPoint thePntLn2) {
780   int r, s;
781   int a, b, c;
782   
783   int px = thePnt.x();
784   int py = thePnt.y();
785   int lx = thePntLn1.x();
786   int ly = thePntLn1.y();
787   int nx = thePntLn2.x();
788   int ny = thePntLn2.y();
789   
790   r = px - lx;
791   r = r * r;
792   s = py - ly;
793   s = s * s;
794   a = (int) sqrt((double)(r + s));
795
796   r = px - nx;
797   r = r * r;
798   s = py - ny;
799   s = s * s;
800   b = (int) sqrt((double)(r + s));
801   
802   r = nx - lx;
803   r = r * r;
804   s = ny - ly;
805   s = s * s;
806   c = (int) sqrt((double)(r + s));
807
808   return (a+b-c);
809 }
810
811 void SUPERVGUI_Link::setBeginPort(SUPERVGUI_Port* theBeginPort) {
812   myBeginPort = theBeginPort;
813 }
814
815 SUPERVGUI_Port* SUPERVGUI_Link::getBeginPort() {
816   return myBeginPort;
817 }
818
819