1 // SUPERV SUPERVGUI : GUI for Supervisor component
3 // Copyright (C) 2003 OPEN CASCADE
5 // File : SUPERVGUI_GanvasNodePrs.cxx
6 // Author : Natalia KOPNOVA
10 #include "SUPERVGUI_CanvasLink.h"
11 #include "SUPERVGUI_Canvas.h"
12 #include "SUPERVGUI_CanvasPort.h"
13 #include "SUPERVGUI_Main.h"
18 #include <sys/timeb.h>
21 #define DRAW_COLOR Qt::black
22 #define SELECT_COLOR Qt::magenta
23 #define SKETCH_COLOR Qt::darkGreen
24 #define STREAM_COLOR Qt::darkRed // QColor(0, 64, 128) // Qt::blue
29 SUPERVGUI_CanvasLink::SUPERVGUI_CanvasLink(QObject* theParent, SUPERVGUI_Main* theMain, SUPERV::Link_ptr theLink):
38 if (theLink && !SUPERV_isNull(theLink)) {
39 myLink = SUPERV::Link::_duplicate(theLink);
41 SUPERVGUI_Canvas* aCanvas = myMain->getCanvas();
42 setName(aCanvas->getLinkName(theLink));
44 myInputPort = aCanvas->getPort(myLink->InPort());
45 if (myInputPort) myInputPort->addLink(this);
47 myOutputPort = aCanvas->getPort(myLink->OutPort());
48 if (myOutputPort) myOutputPort->addLink(this);
50 if (myInputPort->isStream())
51 myColor = STREAM_COLOR;
57 SUPERVGUI_CanvasLink::~SUPERVGUI_CanvasLink()
59 for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
63 if (myInputPort) myInputPort->removeLink(this);
64 if (myOutputPort) myOutputPort->removeLink(this);
67 void SUPERVGUI_CanvasLink::createPrs()
69 if (myLink && !SUPERV_isNull(myLink)) {
71 addPoint(myInputPort->getConnectionPoint());
73 if (!myMain->getCanvas()->isControlView()) {
75 for (int i = 0; i < myLink->CoordsSize(); i++) {
76 myLink->Coords(i+1, x, y);
77 addPoint(QPoint(x, y), i+1);
81 addPoint(myOutputPort->getConnectionPoint());
84 setColor(myHilighted ? SELECT_COLOR : myColor);
87 void SUPERVGUI_CanvasLink::addPoint(const QPoint& thePoint, const int& theIndex)
89 SUPERVGUI_CanvasPointPrs* aPoint;
91 aPoint = new SUPERVGUI_CanvasPointPrs(myMain->getCanvas(), this, theIndex);
92 aPoint->setColor(myColor);
93 aPoint->move(thePoint.x(), thePoint.y());
96 SUPERVGUI_CanvasPointPrs* aPrev = (SUPERVGUI_CanvasPointPrs*) myPrs.last();
98 SUPERVGUI_CanvasEdgePrs* anEdge = new SUPERVGUI_CanvasEdgePrs(myMain->getCanvas(), this);
99 anEdge->setColor(myColor);
100 myPrs.append(anEdge);
102 aPoint = new SUPERVGUI_CanvasPointPrs(myMain->getCanvas(), this, theIndex);
103 aPoint->setColor(myColor);
104 aPoint->move(thePoint.x(), thePoint.y());
106 aPrev->setOutEdge(anEdge);
107 aPoint->setInEdge(anEdge);
109 myPrs.append(aPoint);
112 void SUPERVGUI_CanvasLink::setSelectedObject(QCanvasItem* theItem, const QPoint& thePoint)
114 mySelectedItem = theItem;
115 mySelectedPoint = thePoint;
118 QPopupMenu* SUPERVGUI_CanvasLink::getPopupMenu(QWidget* theParent)
120 QPopupMenu* popup = new QPopupMenu(theParent);
122 anItem = popup->insertItem(tr("MSG_DELLINK"), this, SLOT(remove()));
124 (myInputPort->getEngine()->Kind() != SUPERV::EndSwitchParameter ||
125 myInputPort->getEngine()->Node()->Kind() != SUPERV::EndSwitchNode))
126 if (myInputPort->getEngine()->Kind() == SUPERV::LoopParameter ||
127 myOutputPort && myOutputPort->getEngine()->Kind() == SUPERV::LoopParameter)
128 popup->setItemEnabled(anItem, false);
130 popup->insertSeparator();
131 if (mySelectedItem) {
132 anItem = popup->insertItem(tr("MSG_ADD_POINT"), this, SLOT(addPoint()));
133 if (mySelectedItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint)
134 popup->setItemEnabled(anItem, false);
136 anItem = popup->insertItem(tr("MSG_DEL_POINT"), this, SLOT(removePoint()));
137 if (mySelectedItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge)
138 popup->setItemEnabled(anItem, false);
143 void SUPERVGUI_CanvasLink::show()
145 if (myPrs.isEmpty()) createPrs();
147 for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
152 void SUPERVGUI_CanvasLink::merge()
154 // remove old presentation
155 for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
164 void SUPERVGUI_CanvasLink::setHilighted(bool state)
167 setColor(myHilighted ? SELECT_COLOR : myColor);
168 if (!myPrs.isEmpty()) {
169 bool disp = myPrs.first()->isVisible();
171 for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
172 (*it)->hide(); (*it)->show();
174 myMain->getCanvas()->update();
179 void SUPERVGUI_CanvasLink::moveByPort(SUPERVGUI_CanvasPort* thePort, int dx, int dy)
181 if (myInputPort && myInputPort == thePort) {
182 myPrs.first()->moveBy(dx, dy);
185 if (myOutputPort && myOutputPort == thePort) {
186 myPrs.last()->moveBy(dx, dy);
191 void SUPERVGUI_CanvasLink::moveByPort(SUPERVGUI_CanvasPort* thePort)
193 QPoint p = thePort->getConnectionPoint();
194 if (myInputPort && myInputPort == thePort) {
195 myPrs.first()->move(p.x(), p.y());
198 if (myOutputPort && myOutputPort == thePort) {
199 myPrs.last()->move(p.x(), p.y());
204 void SUPERVGUI_CanvasLink::setColor(const QColor& theColor)
206 for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
207 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
208 ((SUPERVGUI_CanvasPointPrs*)(*it))->setColor(theColor);
210 else if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
211 ((SUPERVGUI_CanvasEdgePrs*)(*it))->setColor(theColor);
216 void SUPERVGUI_CanvasLink::remove() {
217 // IPAL9369 : check the dataflow readiness to modify
218 if ( !myMain->ReadyToModify() ) // null dataflow or executing, ..
221 myMain->Editing(); // PAL6170: GUI->Engine: setting "Editing" flag
224 SUPERVGUI_CanvasPortIn* aPort = 0;
225 SUPERVGUI_Canvas* aCanvas = myMain->getCanvas();
226 if (myLink && !SUPERV_isNull(myLink)) {
228 if (myInputPort->getEngine()->IsParam() || myInputPort->getEngine()->IsInLine()) {
229 aValue = QString(myInputPort->getEngine()->ToString());
230 aPort = (SUPERVGUI_CanvasPortIn*) myInputPort;
236 if (aPort && !aValue.isEmpty() && myMain->getDataflow()->GraphLevel() == 0) {
237 aPort->setValue(aValue);
242 void SUPERVGUI_CanvasLink::addPoint() {
243 if (mySelectedItem && mySelectedItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
244 SUPERVGUI_CanvasEdgePrs* anEdge = (SUPERVGUI_CanvasEdgePrs*) mySelectedItem;
247 QCanvasItemList::Iterator it;
248 for (it = myPrs.begin(); it != myPrs.end(); ++it) {
249 if ((*it) == anEdge) break;
251 if (it != myPrs.begin()) {
253 SUPERVGUI_CanvasPointPrs* aPoint = (SUPERVGUI_CanvasPointPrs*) (*it);
254 anIndex = aPoint->getIndex()+1;
255 if (anIndex < 1) anIndex = 1;
257 if (myLink && !SUPERV_isNull(myLink))
258 myLink->AddCoord(anIndex, mySelectedPoint.x(), mySelectedPoint.y());
260 myMain->getCanvas()->update();
264 void SUPERVGUI_CanvasLink::removePoint() {
265 if (mySelectedItem && mySelectedItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
266 SUPERVGUI_CanvasPointPrs* aPoint = (SUPERVGUI_CanvasPointPrs*) mySelectedItem;
267 if (myLink && !SUPERV_isNull(myLink))
268 myLink->RemoveCoord(aPoint->getIndex());
270 myMain->getCanvas()->update();
275 //===============================================================================
276 // SUPERVGUI_CanvasStreamLink: new link to be created
277 //===============================================================================
278 SUPERVGUI_CanvasStreamLink::SUPERVGUI_CanvasStreamLink(QObject* theParent, SUPERVGUI_Main* theMain,
279 SUPERV::StreamLink_ptr theLink):
280 SUPERVGUI_CanvasLink(theParent, theMain, theLink)
282 if (theLink && !SUPERV_isNull(theLink)) {
283 myStreamLink = SUPERV::StreamLink::_duplicate(theLink);
288 void SUPERVGUI_CanvasStreamLink::remove() {
290 SUPERVGUI_CanvasPortIn* aPort = 0;
291 SUPERVGUI_Canvas* aCanvas = getMain()->getCanvas();
292 if (myStreamLink && !SUPERV_isNull(myStreamLink)) {
293 if (getInputPort()) {
294 if (getInputPort()->getEngine()->IsParam() || getInputPort()->getEngine()->IsInLine()) {
295 aPort = (SUPERVGUI_CanvasPortIn*) getInputPort();
296 aValue = QString(aPort->getEngine()->ToString());
299 myStreamLink->destroy();
302 if (aPort && !aValue.isEmpty()) {
303 aPort->setValue(aValue);
309 //===============================================================================
310 // SUPERVGUI_CanvasLinkBuilder: new link to be created
311 //===============================================================================
312 SUPERVGUI_CanvasLinkBuilder::SUPERVGUI_CanvasLinkBuilder(QObject* theParent, SUPERVGUI_Main* theMain,
313 SUPERVGUI_CanvasPort* thePort):
314 SUPERVGUI_CanvasLink(theParent, theMain),
319 myPort->addLink(this);
320 addPoint(myPort->getConnectionPoint());
322 myColor = SKETCH_COLOR;
325 SUPERVGUI_CanvasLinkBuilder::~SUPERVGUI_CanvasLinkBuilder()
327 if (myFloatingEdge) delete myFloatingEdge;
328 if (myPort) myPort->removeLink(this);
331 bool SUPERVGUI_CanvasLinkBuilder::canCreateEngine(SUPERVGUI_CanvasPort* thePort)
333 if (thePort && myPort) {
334 SUPERVGUI_CanvasPort* aInPort;
335 SUPERVGUI_CanvasPort* aOutPort;
337 // check if ports are couple of input and output
338 if (myPort->getEngine()->IsInput()) {
340 if (thePort->getEngine()->IsInput())
346 if (!thePort->getEngine()->IsInput())
351 // control if nodes are different, not the same node
352 QString aInNode(aInPort->getEngine()->Node()->Name());
353 QString aOutNode(aOutPort->getEngine()->Node()->Name());
354 if (aInNode.compare(aOutNode) == 0) // linking outport and inport of the same node
357 // control types of ports
358 int aInKind = aInPort->getEngine()->Kind();
359 int aOutKind = aOutPort->getEngine()->Kind();
361 // connect stream port with stream port only
362 if ((aInKind == SUPERV::DataStreamParameter && aOutKind != SUPERV::DataStreamParameter) ||
363 (aOutKind == SUPERV::DataStreamParameter && aInKind != SUPERV::DataStreamParameter))
366 // asv : 15.12.04 : NOT allow to connect Gate-to-InLine --> it does not make sence!
367 // Out Gate port can be connected only to In Gate port
368 if ( aOutKind == SUPERV::GateParameter && aInKind != SUPERV::GateParameter )
371 // In Gate can be connected to (receive links from) Gate port and InLine ports (important for Switch nodes)
372 if ( aInKind == SUPERV::GateParameter && aOutKind != SUPERV::GateParameter && aOutKind != SUPERV::InLineParameter )
375 // asv : 15.12.04 : PAL7374, p.2.2 "Bugs and Improvements": multiple links into Gate port
376 // for InGate it's OK to accept more than 1 link
377 // THESE NEEDS REVISION, ALSO DON'T ALLOW MANY LINKS TO "DEFAULT" PORT OF EndSwitch
378 //if ( aInPort->getEngine()->IsLinked() && aInKind != SUPERV::GateParameter )
380 // control if port is already linked except for input inline ports of end switch node (check for EndSwitchParameter)
381 // and "Default" port of Switch node (check for aNode->isEndSwitch()). "Default" port is linked by default, but we
382 // let it to be "re-linked" to another port.
383 const bool isEndSwitch = ( aInKind == SUPERV::EndSwitchParameter || aInPort->getEngine()->Node()->IsEndSwitch() );
384 if ( !isEndSwitch && aInPort->getEngine()->IsLinked() )
392 void SUPERVGUI_CanvasLinkBuilder::setCoords(SUPERV::Link_ptr theLink)
395 QCanvasItemList::Iterator it;
397 if (myPort->getEngine()->IsInput()) {
398 it = myPrs.begin(); ++it; // ignore the first point
399 for (; it != myPrs.end(); ++it) {
400 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
401 theLink->AddCoord(anIndex++, (int)(*it)->x(), (int)(*it)->y());
406 it = myPrs.end(); --it;
407 for (; it != myPrs.begin(); --it) {
408 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
409 theLink->AddCoord(anIndex++, (int)(*it)->x(), (int)(*it)->y());
416 void SUPERVGUI_CanvasLinkBuilder::addNextPoint(const QPoint& thePoint, bool theOrtho)
418 if (myFloatingEdge) myFloatingEdge->hide();
420 if (!theOrtho || myPrs.empty()) {
424 SUPERVGUI_CanvasPointPrs* aPrev = (SUPERVGUI_CanvasPointPrs*) myPrs.last();
425 int x = (int)aPrev->x(); int y = (int)aPrev->y();
426 if (thePoint.x() != x && thePoint.y() != y) {
427 addPoint(QPoint(thePoint.x(), y), -2);
434 void SUPERVGUI_CanvasLinkBuilder::setFloatPoint(const QPoint& thePoint)
436 if (!myFloatingEdge) {
437 myFloatingEdge = new QCanvasLine(getMain()->getCanvas());
438 myFloatingEdge->setPen(QPen(myColor, LINE_WIDTH));
440 if (!myPrs.empty()) {
441 myFloatingEdge->setPoints((int)myPrs.last()->x(), (int)myPrs.last()->y(),
442 thePoint.x(), thePoint.y());
443 myFloatingEdge->show();
447 void SUPERVGUI_CanvasLinkBuilder::removeLastPoint()
449 if (myPrs.count() > 1) {
450 QPoint aLast((int)myPrs.last()->x(), (int)myPrs.last()->y());
451 QCanvasItemList::Iterator it = myPrs.end();
452 bool removed = false;
454 for (; it != myPrs.begin(); --it) {
455 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
456 SUPERVGUI_CanvasPointPrs* aPoint = (SUPERVGUI_CanvasPointPrs*) (*it);
457 if (aPoint->getIndex() == -1 && removed) break;
459 QCanvasItem* anItem = (*it);
460 it = myPrs.remove(it);
465 if (myFloatingEdge) {
466 QPoint aPoint = myFloatingEdge->endPoint();
467 myFloatingEdge->setPoints((int)myPrs.last()->x(), (int)myPrs.last()->y(),
468 aPoint.x(), aPoint.y());
471 setFloatPoint(aLast);
476 void SUPERVGUI_CanvasLinkBuilder::moveByPort(SUPERVGUI_CanvasPort* thePort, int dx, int dy)
478 if (myPort && myPort == thePort) {
479 myPrs.first()->moveBy(dx, dy);
484 void SUPERVGUI_CanvasLinkBuilder::moveByPort(SUPERVGUI_CanvasPort* thePort)
486 QPoint p = thePort->getConnectionPoint();
487 if (myPort && myPort == thePort) {
488 myPrs.first()->move(p.x(), p.y());
494 //===============================================================================
495 // SUPERVGUI_CanvasPointPrs: link point presentation
496 //===============================================================================
497 SUPERVGUI_CanvasPointPrs::SUPERVGUI_CanvasPointPrs(QCanvas* theCanvas,
498 SUPERVGUI_CanvasLink* theLink,
499 const int& theIndex):
500 QCanvasEllipse(theCanvas),
501 myLink(theLink), myIndex(theIndex),
502 myInEdge(0), myOutEdge(0), myMoving(false)
504 setSize(POINT_SIZE, POINT_SIZE);
508 int SUPERVGUI_CanvasPointPrs::rtti() const
510 return SUPERVGUI_Canvas::Rtti_LinkPoint;
513 void SUPERVGUI_CanvasPointPrs::setInEdge(SUPERVGUI_CanvasEdgePrs* theEdge)
516 theEdge->setFromPoint(this);
519 void SUPERVGUI_CanvasPointPrs::setOutEdge(SUPERVGUI_CanvasEdgePrs* theEdge)
522 theEdge->setToPoint(this);
525 void SUPERVGUI_CanvasPointPrs::moveBy(double dx, double dy)
527 QCanvasEllipse::moveBy(dx, dy);
528 if (myInEdge) myInEdge->setFromPoint(this);
529 if (myOutEdge) myOutEdge->setToPoint(this);
530 //resize canvas view if mouse is outside
531 int w = (int)(x()+dx) + width() + GRAPH_MARGIN;
532 int h = (int)(y()+dy) + height() + GRAPH_MARGIN;
533 if (canvas()->width() > w) w = canvas()->width();
534 if (canvas()->height() > h) h = canvas()->height();
535 if (canvas()->width() < w || canvas()->height() < h) canvas()->resize(w, h);
536 if (myIndex > 0 && isMoving()) {
537 myLink->getEngine()->ChangeCoord(myIndex, (int)x(), (int)y());
541 void SUPERVGUI_CanvasPointPrs::setColor(const QColor& theColor)
546 //===============================================================================
547 // SUPERVGUI_CanvasEdgePrs: link edge presentation
548 //===============================================================================
549 SUPERVGUI_CanvasEdgePrs::SUPERVGUI_CanvasEdgePrs(QCanvas* theCanvas,
550 SUPERVGUI_CanvasLink* theLink):
551 QCanvasLine(theCanvas),
557 int SUPERVGUI_CanvasEdgePrs::rtti() const
559 return SUPERVGUI_Canvas::Rtti_LinkEdge;
562 void SUPERVGUI_CanvasEdgePrs::setFromPoint(SUPERVGUI_CanvasPointPrs* thePoint)
564 myStartPoint = thePoint;
565 setPoints((int)(thePoint->x()), (int)(thePoint->y()), endPoint().x(), endPoint().y());
568 void SUPERVGUI_CanvasEdgePrs::setToPoint(SUPERVGUI_CanvasPointPrs* thePoint)
570 myEndPoint = thePoint;
571 setPoints(startPoint().x(), startPoint().y(), (int)(thePoint->x()), (int)(thePoint->y()));
574 void SUPERVGUI_CanvasEdgePrs::setColor(const QColor& theColor)
576 setPen(QPen(theColor, LINE_WIDTH));
579 void SUPERVGUI_CanvasEdgePrs::moveBy(double dx, double dy)
581 //mkr: for moving segment of link
582 if (myStartPoint && myEndPoint) {
583 myStartPoint->setMoving(true);
584 myStartPoint->moveBy(dx, dy);
586 myEndPoint->setMoving(true);
587 myEndPoint->moveBy(dx,dy);