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 // 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());
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);
413 return aCanCreate && (aInNodeName != aOutNodeName);
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());
421 return (aInNodeName != aOutNodeName);
427 //**********************************************************************
429 * Abort creation of link
431 void SUPERVGUI_Link::abortCreation() {
432 LinkIsMoving = false;
435 //**********************************************************************
437 * Final procedure of link creation
439 bool SUPERVGUI_Link::createEngine() {
440 // clear temporary drawing
441 QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
442 //check if myPainter not null
444 myPainter->setPen(aOldPen);
445 myPainter->setRasterOp(Qt::CopyROP);
448 if (myTmpPoints.size() > 0)
449 aStartPnt = myGraph->contentsToViewport(myTmpPoints[myTmpPoints.size()-1]);
451 aStartPnt = myStartPort->getConnectPnt();
453 myPainter->drawLine(aStartPnt, myPrevPoint);
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());
467 myEngine = myGraph->getMain()->getDataflow()->
468 Link(myPortOut->getPort(), myPortIn->getPort());
470 myEngine = myGraph->getMain()->getDataflow()->
471 Link(myPortOut->getPort(), myPortInES->getPort());
473 if (SUPERV_isNull(myEngine)) return false;
475 // remember all points
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());
484 for (int i = 0; i < myTmpPoints.size(); i++) {
485 aPnt = myTmpPoints[i];
486 myEngine->AddCoord(i+1, aPnt.x(), aPnt.y());
489 LinkIsMoving = false;
491 // empty temporary resources
501 //**********************************************************************
502 void SUPERVGUI_Link::onMouseMove(QMouseEvent * theEvent) {
503 if (myPntMovingState) {
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;
512 myMovedPnt = QPoint(aX, aY);
517 if (LinkIsMoving) return;
519 // Points highlighting
520 QPoint aPos = theEvent->pos();
521 if (myEngine->CoordsSize() > 0 ) {
523 bool aIsFound = false;
524 for (int i=0; i < myEngine->CoordsSize(); i++) {
525 myEngine->Coords(i+1, aX, aY);
528 aPos.y()) < (PNT_SIZE+2)) {
534 if (!aIsFound) myHltPnt = -1;
538 if (isSelected(aPos)) {
539 if (SelectedLink==0) {
540 QPen aNewPen(HLT_CLR, LINE_WIDTH);
541 QPainter aPainter(myGraph->viewport());
542 aPainter.setPen(aNewPen);
547 } else if (myIsSelected) {
548 myIsSelected = false;
549 if (SelectedLink == this) SelectedLink = 0;
555 //**********************************************************************
557 * For internal using only
558 * Draws segments by current Pen when point is moving
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,
569 //**********************************************************************
570 void SUPERVGUI_Link::onMousePress(QMouseEvent * theEvent) {
574 if (theEvent->button() != Qt::LeftButton) {
579 if (myHltPnt > -1) { // start point moving
581 if (!isESInputPort()) {
582 myBeforePnt = myPortIn->getConnectPnt();
585 myBeforePnt = myPortInES->getConnectPnt();
590 myEngine->Coords(myHltPnt-1, aX, aY);
591 myBeforePnt = myGraph->contentsToViewport(QPoint(aX, aY));
593 if (myHltPnt == myEngine->CoordsSize())
594 myAfterPnt = myPortOut->getConnectPnt();
597 myEngine->Coords(myHltPnt+1, aX, aY);
598 myAfterPnt = myGraph->contentsToViewport(QPoint(aX, aY));
601 myEngine->Coords(myHltPnt, aX, aY);
602 myMovedPnt = myGraph->contentsToViewport(QPoint(aX, aY));
604 myPainter = new QPainter(myGraph->viewport());
605 QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
607 myPainter->setPen(aOldPen);
610 myPainter->setPen(myTmpPen);
611 myPainter->setRasterOp(Qt::XorROP);
614 myPntMovingState = true;
616 } else if (myHltPnt > -1)
620 //**********************************************************************
621 void SUPERVGUI_Link::onMouseRelease(QMouseEvent * theEvent){
622 if (theEvent->button() != Qt::LeftButton) return;
624 if (myPntMovingState) {
625 myPntMovingState = false;
626 LinkIsMoving = false;
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);
641 //**********************************************************************
643 * Connects to the Graph mouse events
645 void SUPERVGUI_Link::connectToEvents() {
646 connect(myGraph, SIGNAL(mouseMoved(QMouseEvent*)),
647 this, SLOT(onMouseMove(QMouseEvent*)));
649 connect(myGraph, SIGNAL(mousePressed(QMouseEvent*)),
650 this, SLOT(onMousePress(QMouseEvent*)));
652 connect(myGraph, SIGNAL(mouseReleased(QMouseEvent*)),
653 this, SLOT(onMouseRelease(QMouseEvent*)));
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);
665 return (distance(thePnt, myGraph->viewportToContents(myPortOut->getConnectPnt()),
666 myGraph->viewportToContents(myPortInES->getConnectPnt())) <= 0);
671 myEngine->Coords(1, aX, aY);
672 if (!isESInputPort()) {
673 if (distance(thePnt, myGraph->viewportToContents(myPortIn->getConnectPnt()),
674 QPoint(aX, aY)) <= 0) {
679 if (distance(thePnt, myGraph->viewportToContents(myPortInES->getConnectPnt()),
680 QPoint(aX, aY)) <= 0) {
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) {
696 if (distance(thePnt, QPoint(aX, aY),
697 myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
705 //**********************************************************************
707 * Returns true if at least one point is within the rect.
708 * Rect must be in contents coordinate space
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))
715 if (!isESInputPort()) {
716 if (aRect.contains(myGraph->viewportToContents(myPortIn->getConnectPnt()), true)) {
721 if (aRect.contains(myGraph->viewportToContents(myPortInES->getConnectPnt()), true)) {
728 if (!isESInputPort())
729 aPrevPnt = myGraph->viewportToContents(myPortIn->getConnectPnt());
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))
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))
743 aPrevPnt = QPoint(aX, aY);
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))
758 //**********************************************************************
760 * Calculates distance between points
762 int distance(int x1, int y1, int x2, int y2) {
767 return (int) sqrt((double)(x + y));
771 //**********************************************************************
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
777 int distance(QPoint thePnt, QPoint thePntLn1, QPoint thePntLn2) {
783 int lx = thePntLn1.x();
784 int ly = thePntLn1.y();
785 int nx = thePntLn2.x();
786 int ny = thePntLn2.y();
792 a = (int) sqrt((double)(r + s));
798 b = (int) sqrt((double)(r + s));
804 c = (int) sqrt((double)(r + s));
809 void SUPERVGUI_Link::setBeginPort(SUPERVGUI_Port* theBeginPort) {
810 myBeginPort = theBeginPort;
813 SUPERVGUI_Port* SUPERVGUI_Link::getBeginPort() {