1 // SUPERV SUPERVGUI : GUI for Supervisor component
3 // Copyright (C) 2003 CEA/DEN, EDF R&D
7 // File : SUPERVGUI_Link.cxx
8 // Author : Vitaly SMETANNIKOV
12 #include "SUPERVGUI_Graph.h"
13 #include "SUPERVGUI_Main.h"
14 #include "SUPERVGUI_Link.h"
18 #define SKETCH_CLR Qt::green
19 #define DRAW_CLR Qt::black
20 #define HLT_CLR Qt::magenta
21 #define CTRL_CLR Qt::red
27 // Prevents moving of several links at once
28 bool SUPERVGUI_Link::LinkIsMoving=false;
30 bool SUPERVGUI_Link::OrthoMode = false;
32 SUPERVGUI_Link* SUPERVGUI_Link::SelectedLink=0;
36 * If link is NULL - this must be defined later
38 SUPERVGUI_Link::SUPERVGUI_Link(SUPERVGUI_Graph* theGraph, SUPERV_Link theLink) {
46 myPntMovingState = false;
49 myTmpPen.setColor(SKETCH_CLR);
50 myTmpPen.setWidth(LINE_WIDTH);
54 if (!SUPERV_isNull(myEngine))
59 //**********************************************************************
60 SUPERVGUI_Link::~SUPERVGUI_Link() {
61 if (!SUPERV_isNull(myEngine)) {
62 disconnect(myGraph, 0, this, 0);
64 if (SelectedLink == this) SelectedLink=0;
65 emit linkDeleted(this);
69 //**********************************************************************
70 void SUPERVGUI_Link::setInputPort(SUPERVGUI_PortIn* thePortIn) {
72 myPortIn->setLinkPrs(this);
76 //**********************************************************************
77 void SUPERVGUI_Link::setInputPortES(SUPERVGUI_PortInESNode* thePortInES) {
78 myPortInES = thePortInES;
79 myPortInES->setLinkPrs(this);
82 //**********************************************************************
83 bool SUPERVGUI_Link::isESInputPort() {
90 //**********************************************************************
91 void SUPERVGUI_Link::destroyEngine() {
92 if (!SUPERV_isNull(myEngine)) {
97 //**********************************************************************
98 void SUPERVGUI_Link::setOutputPort(SUPERVGUI_PortOut* thePortOut){
99 myPortOut = thePortOut;
100 myPortOut->addLinkPrs(this);
104 //**********************************************************************
105 void SUPERVGUI_Link::addPoint(long theX, long theY) {
106 if (SUPERV_isNull(myEngine)) return;
108 if (myEngine->CoordsSize() <= 0) {
109 myEngine->AddCoord(1, theX, theY);
112 QPoint aPnt(theX, theY);
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);
123 if (distance(aPnt, myGraph->viewportToContents(myPortInES->getConnectPnt()),
124 QPoint(aX, aY)) <= 0) {
125 myEngine->AddCoord(1, theX, theY);
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);
142 if (distance(aPnt, QPoint(aX, aY),
143 myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
144 myEngine->AddCoord(myEngine->CoordsSize()+1, theX, theY);
152 //**********************************************************************
154 * Can be used only in Sketching mode
156 void SUPERVGUI_Link::addTmpPoint(QPoint thePnt) {
158 int aSize = myTmpPoints.size();
162 aPrevPnt = myTmpPoints[aSize-1];
164 aPrevPnt = myStartPort->getConnectPnt();
168 if (Abs(thePnt.x() - aPrevPnt.x()) >
169 Abs(thePnt.y() - aPrevPnt.y())) {
170 aNewPoint = QPoint(thePnt.x(), aPrevPnt.y());
172 aNewPoint = QPoint(aPrevPnt.x(), thePnt.y());
176 myPainter->drawLine(aPrevPnt, thePnt);
177 myPainter->moveTo(aPrevPnt);
178 myPainter->lineTo(aNewPoint);
179 myPainter->lineTo(thePnt);
181 myTmpPoints.push_back(aNewPoint);
183 myTmpPoints.push_back(thePnt);
187 //**********************************************************************
189 * Can be used only in Sketching mode
191 void SUPERVGUI_Link::delLastTmpPoint() {
192 int aSize = myTmpPoints.size();
194 QPoint aRemPnt = myTmpPoints[aSize-1];
198 aLastPnt = myTmpPoints[aSize-2];
200 aLastPnt = myStartPort->getConnectPnt();
202 myPainter->moveTo(aLastPnt);
203 myPainter->lineTo(aRemPnt);
204 myPainter->lineTo(myPrevPoint);
206 myPainter->drawLine(aLastPnt, myPrevPoint);
208 myTmpPoints.pop_back();
213 //**********************************************************************
214 void SUPERVGUI_Link::removeLastPoint() {
215 if (myEngine && (!SUPERV_isNull(myEngine)))
216 myEngine->RemoveCoord(myEngine->CoordsSize());
220 //**********************************************************************
221 void SUPERVGUI_Link::removePoint(int thePnt) {
222 if ((thePnt > -1) && (!SUPERV_isNull(myEngine))) {
224 myEngine->RemoveCoord(thePnt);
229 //**********************************************************************
233 void SUPERVGUI_Link::repaint() {
239 //**********************************************************************
241 * Paints or erases the link
242 * if toErase = true then it draws link by background color
244 void SUPERVGUI_Link::paint(bool toErase) {
245 if ((!myGraph) || (!myIsVisible)) return;
246 if (!myEngine && SUPERV_isNull(myEngine)) return;
247 // if (!isCreationComplete()) return;
249 QPainter aPainter(myGraph->viewport());
251 aDataPen.setWidth(LINE_WIDTH);
254 aDataPen.setColor(myGraph->viewport()->paletteBackgroundColor());
256 if ((strcmp(myEngine->InPort()->Name(), "InVoid")==0) ||
257 (myEngine->InPort()->Kind() == SUPERV::DataStreamParameter ))
258 aDataPen.setColor(CTRL_CLR);
260 aDataPen.setColor(DRAW_CLR);
262 aPainter.setPen(aDataPen);
267 //**********************************************************************
269 * Defines a pen and draws link using given painter
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;
278 aDataPen.setWidth(LINE_WIDTH);
281 aDataPen.setColor(myGraph->viewport()->paletteBackgroundColor());
283 if ((strcmp(myEngine->InPort()->Name(), "InVoid")==0)||
284 (myEngine->InPort()->Kind() == SUPERV::DataStreamParameter ))
285 aDataPen.setColor(CTRL_CLR);
287 aDataPen.setColor(DRAW_CLR);
289 thePainter->setPen(aDataPen);
290 drawLink(thePainter);
291 thePainter->restore();
295 //**********************************************************************
297 * Draws link using given painter
299 void SUPERVGUI_Link::drawLink(QPainter* thePainter) {
300 if (!myIsVisible) return;
301 if (!isESInputPort())
302 thePainter->moveTo(myPortIn->getConnectPnt());
304 thePainter->moveTo(myPortInES->getConnectPnt());
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,
314 thePainter->lineTo(myPortOut->getConnectPnt());
318 //**********************************************************************
320 * Repaints whole link when it is sketching
322 void SUPERVGUI_Link::repaintSketch() {
323 if (!myStartPort) return;
324 if (!myPainter) return;
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]));
332 myPainter->lineTo(myPrevPoint);
333 //myPainter->restore();
337 //**********************************************************************
339 * Drawing of non created link following to mouse pointer
341 void SUPERVGUI_Link::drawTo(QPoint thePnt) {
344 myStartPort = myPortIn;
346 myStartPort = myPortInES;
348 myStartPort = myPortOut;
353 myPainter = new QPainter(myGraph->viewport());
354 myPainter->setPen(myTmpPen);
355 myPainter->setRasterOp(Qt::XorROP);
356 myPrevPoint = myStartPort->getConnectPnt();
363 if (myTmpPoints.size() > 0)
364 aStartPnt = myGraph->contentsToViewport(myTmpPoints[myTmpPoints.size()-1]);
366 aStartPnt = myStartPort->getConnectPnt();
369 myPainter->drawLine(aStartPnt, myPrevPoint);
372 QPoint aNewPoint = myGraph->contentsToViewport(thePnt);
373 myPainter->drawLine(aStartPnt, aNewPoint);
374 myPrevPoint = aNewPoint;
379 //**********************************************************************
381 * Set link non visible
383 void SUPERVGUI_Link::setVisible(bool theVisible) {
384 myIsVisible = theVisible;
388 disconnect(myGraph, 0, this, 0);
393 //**********************************************************************
395 * Checks full definition of the link
397 bool SUPERVGUI_Link::isCreationComplete() {
398 bool aIsBoth = myPortIn && myPortOut;
399 if (myPortIn && myPortOut) {
400 SUPERV_Port aInPort = myPortIn->getPort();
401 QString aInNodeName(aInPort->Node()->Name());
402 SUPERV_Port aOutPort = myPortOut->getPort();
403 QString aOutNodeName(aOutPort->Node()->Name());
405 return (aInNodeName != aOutNodeName);
407 else if (myPortInES && myPortOut) {
408 SUPERV_Port aInPortES = myPortInES->getPort();
409 QString aInNodeName(aInPortES->Node()->Name());
410 SUPERV_Port aOutPort = myPortOut->getPort();
411 QString aOutNodeName(aOutPort->Node()->Name());
413 return (aInNodeName != aOutNodeName);
419 //**********************************************************************
421 * Abort creation of link
423 void SUPERVGUI_Link::abortCreation() {
424 LinkIsMoving = false;
427 //**********************************************************************
429 * Final procedure of link creation
431 bool SUPERVGUI_Link::createEngine() {
432 // clear temporary drawing
433 QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
434 //check if myPainter not null
436 myPainter->setPen(aOldPen);
437 myPainter->setRasterOp(Qt::CopyROP);
440 if (myTmpPoints.size() > 0)
441 aStartPnt = myGraph->contentsToViewport(myTmpPoints[myTmpPoints.size()-1]);
443 aStartPnt = myStartPort->getConnectPnt();
445 myPainter->drawLine(aStartPnt, myPrevPoint);
452 if (!isESInputPort())
453 myEngine = myGraph->getMain()->getDataflow()->
454 Link(myPortOut->getPort(), myPortIn->getPort());
456 myEngine = myGraph->getMain()->getDataflow()->
457 Link(myPortOut->getPort(), myPortInES->getPort());
459 if (SUPERV_isNull(myEngine)) return false;
461 // remember all points
463 if (myStartPort == myPortOut) {
464 int aSize = myTmpPoints.size();
465 for (int i = aSize; i > 0; i--) {
466 aPnt = myTmpPoints[i-1];
467 myEngine->AddCoord(aSize+1-i, aPnt.x(), aPnt.y());
470 for (int i = 0; i < myTmpPoints.size(); i++) {
471 aPnt = myTmpPoints[i];
472 myEngine->AddCoord(i+1, aPnt.x(), aPnt.y());
475 LinkIsMoving = false;
477 // empty temporary resources
487 //**********************************************************************
488 void SUPERVGUI_Link::onMouseMove(QMouseEvent * theEvent) {
489 if (myPntMovingState) {
492 QPoint aPos = myGraph->contentsToViewport(theEvent->pos());
493 int aX = (aPos.x() > 0)? aPos.x(): 1;
494 int aY = (aPos.y() > 0)? aPos.y(): 1;
495 aX = (aX < myGraph->contentsWidth())? aX: myGraph->contentsWidth()-1;
496 aY = (aY < myGraph->contentsHeight())? aY: myGraph->contentsHeight()-1;
498 myMovedPnt = QPoint(aX, aY);
503 if (LinkIsMoving) return;
505 // Points highlighting
506 QPoint aPos = theEvent->pos();
507 if (myEngine->CoordsSize() > 0 ) {
509 bool aIsFound = false;
510 for (int i=0; i < myEngine->CoordsSize(); i++) {
511 myEngine->Coords(i+1, aX, aY);
514 aPos.y()) < (PNT_SIZE+2)) {
520 if (!aIsFound) myHltPnt = -1;
524 if (isSelected(aPos)) {
525 if (SelectedLink==0) {
526 QPen aNewPen(HLT_CLR, LINE_WIDTH);
527 QPainter aPainter(myGraph->viewport());
528 aPainter.setPen(aNewPen);
533 } else if (myIsSelected) {
534 myIsSelected = false;
535 if (SelectedLink == this) SelectedLink = 0;
541 //**********************************************************************
543 * For internal using only
544 * Draws segments by current Pen when point is moving
546 void SUPERVGUI_Link::drawSegments() {
547 myPainter->drawLine(myBeforePnt, myMovedPnt);
548 myPainter->drawLine(myMovedPnt, myAfterPnt);
549 myPainter->drawEllipse(myMovedPnt.x()-PNT_SIZE/2,
550 myMovedPnt.y()-PNT_SIZE/2,
555 //**********************************************************************
556 void SUPERVGUI_Link::onMousePress(QMouseEvent * theEvent) {
560 if (theEvent->button() != Qt::LeftButton) {
564 if (myHltPnt > -1) { // start point moving
566 if (!isESInputPort()) {
567 myBeforePnt = myPortIn->getConnectPnt();
570 myBeforePnt = myPortInES->getConnectPnt();
575 myEngine->Coords(myHltPnt-1, aX, aY);
576 myBeforePnt = myGraph->contentsToViewport(QPoint(aX, aY));
578 if (myHltPnt == myEngine->CoordsSize())
579 myAfterPnt = myPortOut->getConnectPnt();
582 myEngine->Coords(myHltPnt+1, aX, aY);
583 myAfterPnt = myGraph->contentsToViewport(QPoint(aX, aY));
586 myEngine->Coords(myHltPnt, aX, aY);
587 myMovedPnt = myGraph->contentsToViewport(QPoint(aX, aY));
589 myPainter = new QPainter(myGraph->viewport());
590 QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
592 myPainter->setPen(aOldPen);
595 myPainter->setPen(myTmpPen);
596 myPainter->setRasterOp(Qt::XorROP);
599 myPntMovingState = true;
601 } else if (myHltPnt > -1)
605 //**********************************************************************
606 void SUPERVGUI_Link::onMouseRelease(QMouseEvent * theEvent){
607 if (theEvent->button() != Qt::LeftButton) return;
609 if (myPntMovingState) {
610 myPntMovingState = false;
611 LinkIsMoving = false;
616 int aX = (theEvent->pos().x() > 0)? theEvent->pos().x(): 1;
617 int aY = (theEvent->pos().y() > 0)? theEvent->pos().y(): 1;
618 aX = (aX < myGraph->contentsWidth())? aX: myGraph->contentsWidth()-1;
619 aY = (aY < myGraph->contentsHeight())? aY: myGraph->contentsHeight()-1;
620 myEngine->ChangeCoord(myHltPnt, aX, aY);
626 //**********************************************************************
628 * Connects to the Graph mouse events
630 void SUPERVGUI_Link::connectToEvents() {
631 connect(myGraph, SIGNAL(mouseMoved(QMouseEvent*)),
632 this, SLOT(onMouseMove(QMouseEvent*)));
634 connect(myGraph, SIGNAL(mousePressed(QMouseEvent*)),
635 this, SLOT(onMousePress(QMouseEvent*)));
637 connect(myGraph, SIGNAL(mouseReleased(QMouseEvent*)),
638 this, SLOT(onMouseRelease(QMouseEvent*)));
642 //**********************************************************************
643 bool SUPERVGUI_Link::isSelected(QPoint thePnt) {
644 if (myEngine->CoordsSize() == 0) {
645 if (!isESInputPort()) {
646 return (distance(thePnt, myGraph->viewportToContents(myPortOut->getConnectPnt()),
647 myGraph->viewportToContents(myPortIn->getConnectPnt())) <= 0);
650 return (distance(thePnt, myGraph->viewportToContents(myPortOut->getConnectPnt()),
651 myGraph->viewportToContents(myPortInES->getConnectPnt())) <= 0);
656 myEngine->Coords(1, aX, aY);
657 if (!isESInputPort()) {
658 if (distance(thePnt, myGraph->viewportToContents(myPortIn->getConnectPnt()),
659 QPoint(aX, aY)) <= 0) {
664 if (distance(thePnt, myGraph->viewportToContents(myPortInES->getConnectPnt()),
665 QPoint(aX, aY)) <= 0) {
672 for (i = 2; i <= myEngine->CoordsSize(); i++) {
673 myEngine->Coords(i, aNextX, aNextY);
674 if (distance(thePnt, QPoint(aX, aY),
675 QPoint(aNextX, aNextY)) <= 0) {
681 if (distance(thePnt, QPoint(aX, aY),
682 myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
690 //**********************************************************************
692 * Returns true if at least one point is within the rect.
693 * Rect must be in contents coordinate space
695 bool SUPERVGUI_Link::isInRect(int theX, int theY, int theW, int theH) {
696 QRect aRect(theX, theY, theW, theH);
697 if (aRect.contains(myGraph->viewportToContents(myPortOut->getConnectPnt()), true))
700 if (!isESInputPort()) {
701 if (aRect.contains(myGraph->viewportToContents(myPortIn->getConnectPnt()), true)) {
706 if (aRect.contains(myGraph->viewportToContents(myPortInES->getConnectPnt()), true)) {
713 if (!isESInputPort())
714 aPrevPnt = myGraph->viewportToContents(myPortIn->getConnectPnt());
716 aPrevPnt = myGraph->viewportToContents(myPortInES->getConnectPnt());
717 for (int i = 1; i <= myEngine->CoordsSize(); i++) {
718 myEngine->Coords(i, aX, aY);
719 if (aRect.contains(aX, aY, true))
722 QRect aTmpRect(QPoint(QMIN(aPrevPnt.x(), aX),
723 QMIN(aPrevPnt.y(), aY)),
724 QPoint(QMAX(aPrevPnt.x(), aX),
725 QMAX(aPrevPnt.y(), aY)));
726 if (aRect.intersects(aTmpRect))
728 aPrevPnt = QPoint(aX, aY);
731 QPoint aLastPnt = myGraph->viewportToContents(myPortOut->getConnectPnt());
732 QRect aLastRect(QPoint(QMIN(aPrevPnt.x(), aLastPnt.x()),
733 QMIN(aPrevPnt.y(), aLastPnt.y())),
734 QPoint(QMAX(aPrevPnt.x(), aLastPnt.x()),
735 QMAX(aPrevPnt.y(), aLastPnt.y())));
736 if (aRect.intersects(aLastRect))
743 //**********************************************************************
745 * Calculates distance between points
747 int distance(int x1, int y1, int x2, int y2) {
752 return (int) sqrt((double)(x + y));
756 //**********************************************************************
758 * Finds distance between thePnt and line(thePntLn1, thePntLn2)
759 * Returned value is not an mathematical value - this is only estimation of
760 * of closing point to the line. 0 - means that point belongs to the line
762 int distance(QPoint thePnt, QPoint thePntLn1, QPoint thePntLn2) {
768 int lx = thePntLn1.x();
769 int ly = thePntLn1.y();
770 int nx = thePntLn2.x();
771 int ny = thePntLn2.y();
777 a = (int) sqrt((double)(r + s));
783 b = (int) sqrt((double)(r + s));
789 c = (int) sqrt((double)(r + s));
794 void SUPERVGUI_Link::setBeginPort(SUPERVGUI_Port* theBeginPort) {
795 myBeginPort = theBeginPort;
798 SUPERVGUI_Port* SUPERVGUI_Link::getBeginPort() {