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()->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());
469 myEngine = myGraph->getMain()->getDataflow()->
470 Link(myPortOut->getPort(), myPortIn->getPort());
472 myEngine = myGraph->getMain()->getDataflow()->
473 Link(myPortOut->getPort(), myPortInES->getPort());
475 if (SUPERV_isNull(myEngine)) return false;
477 // remember all points
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());
486 for (int i = 0; i < myTmpPoints.size(); i++) {
487 aPnt = myTmpPoints[i];
488 myEngine->AddCoord(i+1, aPnt.x(), aPnt.y());
491 LinkIsMoving = false;
493 // empty temporary resources
503 //**********************************************************************
504 void SUPERVGUI_Link::onMouseMove(QMouseEvent * theEvent) {
505 if (myPntMovingState) {
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;
514 myMovedPnt = QPoint(aX, aY);
519 if (LinkIsMoving) return;
521 // Points highlighting
522 QPoint aPos = theEvent->pos();
523 if (myEngine->CoordsSize() > 0 ) {
525 bool aIsFound = false;
526 for (int i=0; i < myEngine->CoordsSize(); i++) {
527 myEngine->Coords(i+1, aX, aY);
530 aPos.y()) < (PNT_SIZE+2)) {
536 if (!aIsFound) myHltPnt = -1;
540 if (isSelected(aPos)) {
541 if (SelectedLink==0) {
542 QPen aNewPen(HLT_CLR, LINE_WIDTH);
543 QPainter aPainter(myGraph->viewport());
544 aPainter.setPen(aNewPen);
549 } else if (myIsSelected) {
550 myIsSelected = false;
551 if (SelectedLink == this) SelectedLink = 0;
557 //**********************************************************************
559 * For internal using only
560 * Draws segments by current Pen when point is moving
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,
571 //**********************************************************************
572 void SUPERVGUI_Link::onMousePress(QMouseEvent * theEvent) {
576 if (theEvent->button() != Qt::LeftButton) {
581 if (myHltPnt > -1) { // start point moving
583 if (!isESInputPort()) {
584 myBeforePnt = myPortIn->getConnectPnt();
587 myBeforePnt = myPortInES->getConnectPnt();
592 myEngine->Coords(myHltPnt-1, aX, aY);
593 myBeforePnt = myGraph->contentsToViewport(QPoint(aX, aY));
595 if (myHltPnt == myEngine->CoordsSize())
596 myAfterPnt = myPortOut->getConnectPnt();
599 myEngine->Coords(myHltPnt+1, aX, aY);
600 myAfterPnt = myGraph->contentsToViewport(QPoint(aX, aY));
603 myEngine->Coords(myHltPnt, aX, aY);
604 myMovedPnt = myGraph->contentsToViewport(QPoint(aX, aY));
606 myPainter = new QPainter(myGraph->viewport());
607 QPen aOldPen(myGraph->viewport()->paletteBackgroundColor(), LINE_WIDTH);
609 myPainter->setPen(aOldPen);
612 myPainter->setPen(myTmpPen);
613 myPainter->setRasterOp(Qt::XorROP);
616 myPntMovingState = true;
618 } else if (myHltPnt > -1)
622 //**********************************************************************
623 void SUPERVGUI_Link::onMouseRelease(QMouseEvent * theEvent){
624 if (theEvent->button() != Qt::LeftButton) return;
626 if (myPntMovingState) {
627 myPntMovingState = false;
628 LinkIsMoving = false;
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);
643 //**********************************************************************
645 * Connects to the Graph mouse events
647 void SUPERVGUI_Link::connectToEvents() {
648 connect(myGraph, SIGNAL(mouseMoved(QMouseEvent*)),
649 this, SLOT(onMouseMove(QMouseEvent*)));
651 connect(myGraph, SIGNAL(mousePressed(QMouseEvent*)),
652 this, SLOT(onMousePress(QMouseEvent*)));
654 connect(myGraph, SIGNAL(mouseReleased(QMouseEvent*)),
655 this, SLOT(onMouseRelease(QMouseEvent*)));
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);
667 return (distance(thePnt, myGraph->viewportToContents(myPortOut->getConnectPnt()),
668 myGraph->viewportToContents(myPortInES->getConnectPnt())) <= 0);
673 myEngine->Coords(1, aX, aY);
674 if (!isESInputPort()) {
675 if (distance(thePnt, myGraph->viewportToContents(myPortIn->getConnectPnt()),
676 QPoint(aX, aY)) <= 0) {
681 if (distance(thePnt, myGraph->viewportToContents(myPortInES->getConnectPnt()),
682 QPoint(aX, aY)) <= 0) {
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) {
698 if (distance(thePnt, QPoint(aX, aY),
699 myGraph->viewportToContents(myPortOut->getConnectPnt())) <= 0) {
707 //**********************************************************************
709 * Returns true if at least one point is within the rect.
710 * Rect must be in contents coordinate space
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))
717 if (!isESInputPort()) {
718 if (aRect.contains(myGraph->viewportToContents(myPortIn->getConnectPnt()), true)) {
723 if (aRect.contains(myGraph->viewportToContents(myPortInES->getConnectPnt()), true)) {
730 if (!isESInputPort())
731 aPrevPnt = myGraph->viewportToContents(myPortIn->getConnectPnt());
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))
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))
745 aPrevPnt = QPoint(aX, aY);
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))
760 //**********************************************************************
762 * Calculates distance between points
764 int distance(int x1, int y1, int x2, int y2) {
769 return (int) sqrt((double)(x + y));
773 //**********************************************************************
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
779 int distance(QPoint thePnt, QPoint thePntLn1, QPoint thePntLn2) {
785 int lx = thePntLn1.x();
786 int ly = thePntLn1.y();
787 int nx = thePntLn2.x();
788 int ny = thePntLn2.y();
794 a = (int) sqrt((double)(r + s));
800 b = (int) sqrt((double)(r + s));
806 c = (int) sqrt((double)(r + s));
811 void SUPERVGUI_Link::setBeginPort(SUPERVGUI_Port* theBeginPort) {
812 myBeginPort = theBeginPort;
815 SUPERVGUI_Port* SUPERVGUI_Link::getBeginPort() {