Salome HOME
Fix PAL8912 in SUIT-based version of SUPERVISOR.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_CanvasView.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : SUPERVGUI_CanvasView.cxx
8 //  Author : Natalia KOPNOVA
9 //  Module : SUPERV
10
11 using namespace std;
12
13 #include "SUPERVGUI_CanvasView.h"
14 #include "SUPERVGUI_Main.h"
15 #include "SUPERVGUI_CanvasNode.h"
16 #include "SUPERVGUI_CanvasPort.h"
17 #include "SUPERVGUI_CanvasLink.h"
18 #include "SUPERVGUI_CanvasNodePrs.h"
19 #include "SUPERVGUI_Clipboard.h"
20
21 #include "SUIT_MessageBox.h"
22
23 #include <qpixmap.h>
24 #include <qcolordialog.h>
25
26 #define MARGIN 2
27
28
29 /* XPM */
30 const char* imageZoomCursor[] = { 
31 "32 32 3 1",
32 ". c None",
33 "a c #000000",
34 "# c #ffffff",
35 "................................",
36 "................................",
37 ".#######........................",
38 "..aaaaaaa.......................",
39 "................................",
40 ".............#####..............",
41 "...........##.aaaa##............",
42 "..........#.aa.....a#...........",
43 ".........#.a.........#..........",
44 ".........#a..........#a.........",
45 "........#.a...........#.........",
46 "........#a............#a........",
47 "........#a............#a........",
48 "........#a............#a........",
49 "........#a............#a........",
50 ".........#...........#.a........",
51 ".........#a..........#a.........",
52 ".........##.........#.a.........",
53 "........#####.....##.a..........",
54 ".......###aaa#####.aa...........",
55 "......###aa...aaaaa.......#.....",
56 ".....###aa................#a....",
57 "....###aa.................#a....",
58 "...###aa...............#######..",
59 "....#aa.................aa#aaaa.",
60 ".....a....................#a....",
61 "..........................#a....",
62 "...........................a....",
63 "................................",
64 "................................",
65 "................................",
66 "................................"};
67
68 QPixmap zoomPix(imageZoomCursor);
69 QCursor zoom2Cursor(zoomPix);
70 QCursor handCursor(Qt::PointingHandCursor);
71
72 #if QT_VERSION >= 0x030005
73 QCursor pan2Cursor(Qt::SizeAllCursor);
74 #else
75 QCursor pan2Cursor(SizeAllCursor);
76 #endif
77
78 SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGUI_Main* theMain):
79   QCanvasView(theCanvas, theMain),
80   myMain(theMain), myCurrentItem(0), myHilighted(0), myLinkBuilder(0)
81 {
82   setName("CanvasView");
83
84   myIsPanBtnClicked = false;
85   myIsPanActivated = false;
86   myIsFitWRActivated = false;
87   myIsZoomActivated = false;
88   myIsLinkCreating = false;
89
90   myAddStudyItem = 0;
91   mySelectedRect = 0;
92   myCursor = cursor();
93
94   myTimer = new QTimer(this);
95   connect(myTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
96
97   myPopup = new QPopupMenu(viewport());
98
99   const bool isEdit = myMain->isEditable();
100   if (isEdit) {
101     myPopup->insertItem(tr("MSG_ADD_NODE"), myMain, SLOT(addNode()));
102
103     // Paste Node functionality
104     SUPERVGUI_Clipboard* aCB = SUPERVGUI_Clipboard::getClipboard();
105     myPasteNodeItem = myPopup->insertItem(tr("ITM_PASTE_NODE"), aCB, SLOT(pasteNode()));
106
107     myPopup->insertItem(tr("MSG_INS_FILE"), myMain, SLOT(insertFile()));
108     myPopup->insertSeparator();
109   }
110
111   QPopupMenu* aViewPopup = new QPopupMenu(viewport());
112   aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showCanvas()));
113   aViewPopup->insertItem(tr("POP_CONTROLVIEW"), myMain, SLOT(showContolFlow()));
114   aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showCanvasTable()));
115
116   myPopup->insertItem(tr("POP_VIEW"), aViewPopup);
117   myPopup->insertSeparator();
118
119   QPopupMenu* aZoomPopup = new QPopupMenu(viewport());
120   aZoomPopup->insertItem("200%", this, SLOT(zoomIn()));
121   aZoomPopup->insertItem("100%", this, SLOT(zoomReset()));
122   aZoomPopup->insertItem("50%", this, SLOT(zoomOut()));
123   aZoomPopup->insertSeparator();
124   //mkr: "Fit within rectangle" functionality
125   aZoomPopup->insertItem(tr("POP_FITWITHINRECT"), this, SLOT(fitWithinRect()));
126   aZoomPopup->insertSeparator();
127   aZoomPopup->insertItem(tr("POP_FITALL"), this, SLOT(fitAll()));
128   
129
130   myPopup->insertItem(tr("POP_ZOOM"), aZoomPopup);
131   myPopup->insertSeparator();
132
133   myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), myMain, SLOT(addDataflowToStudy()));
134   myPopup->insertItem(tr(isEdit ? "MSG_CHANGE_INFO" : "MSG_INFO"), myMain, SLOT(changeInformation()));
135   myPopup->insertSeparator();
136
137   myPopup->insertItem(tr("MSG_COPY_DATAFLOW"), myMain, SLOT(copy()));
138   myPopup->insertItem(tr("MSG_FILTER_NOTIFY"), myMain, SLOT(filterNotification()));
139
140   myPopup->insertSeparator();
141   myPopup->insertItem(tr("MSG_CHANGE_BACKGROUND"), this, SLOT(changeBackground()));
142
143   viewport()->setMouseTracking(true);
144
145   //create sketching popup menu
146   mySketchPopup = new QPopupMenu(viewport());
147   mySketchPopup->setCheckable(true);
148   myDelPntItem = mySketchPopup->insertItem(tr("MSG_DEL_LAST_PNT"), this, SLOT(deletePoint()));
149   mySketchPopup->insertItem(tr("MSG_DEL_LINK"), this, SLOT(cancelSketch()));
150   myOrtoItem = mySketchPopup->insertItem(tr("MSG_ORTHO_LINE"), this, SLOT(setOrthoMode()));
151
152   
153   // add "change dataflow parameters" popup item
154   myPopup->insertSeparator();
155   myDSParamsItem = myPopup->insertItem( tr( "MSG_SET_GRAPHPARAMS" ), myMain, SLOT( changeDSGraphParameters() ) );
156 }
157  
158
159 SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
160 {
161 }
162
163 void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent) 
164 {
165   myPoint = inverseWorldMatrix().map(theEvent->pos());
166   myGlobalPoint = theEvent->globalPos();
167   myCurrentItem = 0;
168
169   // compute collision rectangle
170   QRect aSel(myPoint.x()-MARGIN, myPoint.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
171
172   if (((theEvent->button() == Qt::MidButton) &&
173        (theEvent->state() == Qt::ControlButton)) || 
174       myIsPanBtnClicked) {
175     myIsPanActivated = true;
176     myCursor = cursor();
177     setCursor(pan2Cursor);
178     return;
179   }
180
181   if (((theEvent->button() == Qt::LeftButton) &&
182        (theEvent->state() == Qt::ControlButton)) || 
183       myIsZoomActivated) {
184     myIsZoomActivated = true;
185     myCursor = cursor();
186     setCursor(zoom2Cursor);
187     return;
188   }
189
190   if ( theEvent->button() == Qt::RightButton) {
191     if (myIsLinkCreating) {
192       myMain->showPopup(mySketchPopup, theEvent);
193       return;
194     }
195
196     QCanvasItemList l = canvas()->collisions(aSel);
197     for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
198       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
199         SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
200         QObject* anObj = aNodePrs->getObject(myPoint);
201         if (anObj->inherits("SUPERVGUI_CanvasNode")) {
202           myMain->showPopup(((SUPERVGUI_CanvasNode*)anObj)->getPopupMenu(viewport()), 
203                             theEvent);
204           return;
205         }
206         else if (anObj->inherits("SUPERVGUI_CanvasPort")) {
207           myMain->showPopup(((SUPERVGUI_CanvasPort*)anObj)->getPopupMenu(viewport()), 
208                             theEvent);
209           return;
210         }
211       }
212       if (myMain->isEditable() && !myMain->getCanvas()->isControlView()) {
213         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
214           SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
215           aPrs->getLink()->setSelectedObject(aPrs, myPoint);
216           myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
217           return;
218         }
219         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
220           SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
221           aPrs->getLink()->setSelectedObject(aPrs, myPoint);
222           myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
223           return;
224         }
225       }
226     }
227         
228     myPopup->setItemEnabled(myAddStudyItem, !myMain->isDataflowInStudy());
229     // Paste Node functionality
230     SUPERVGUI_Clipboard* aCB = SUPERVGUI_Clipboard::getClipboard(); 
231     myPopup->setItemEnabled(myPasteNodeItem, aCB->isCopyNode() );
232        
233     myPopup->setItemEnabled( myDSParamsItem, isHavingStreamPort()/*myMain->getDataflow()->IsStreamGraph()*/ );
234
235     myMain->showPopup(myPopup, theEvent);
236     return;
237   }
238
239   if (theEvent->button() == Qt::LeftButton) {
240     if (!myIsFitWRActivated) {//not moving items if fit within rectangle 
241                               //functionality is enable
242       QCanvasItemList l = canvas()->collisions(myPoint);
243       if (myIsLinkCreating) {
244         for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
245           if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
246             SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
247             QObject* anObj = aNodePrs->getObject(myPoint);
248             if (anObj->inherits("SUPERVGUI_CanvasPort")) {
249               endSketch((SUPERVGUI_CanvasPort*)anObj);
250               return;
251             }
252             else {
253               myCurrentItem = *it;
254               ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
255               ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
256               return;
257             }
258           }
259           if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
260             SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
261             QObject* anObj = aHookPrs->getObject();
262             if (anObj->inherits("SUPERVGUI_CanvasPort")) {
263               endSketch((SUPERVGUI_CanvasPort*)anObj);
264               return;
265             }
266           }
267         }
268         if (myLinkBuilder) {
269           myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
270           canvas()->update();
271           mySketchPopup->setItemEnabled(myDelPntItem, true);
272           return;
273         }
274       }
275       
276 //  if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
277       for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
278         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
279           myCurrentItem = *it;
280           ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
281           ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
282           return;
283         }
284         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
285           SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
286           if (aPrs->getIndex() > 0) {
287             myCurrentItem = *it;
288             aPrs->setMoving(true);
289             return;
290           }
291         }
292         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
293           //mkr: for moving segment of link
294           SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
295           if (aPrs->getLink()->getInputPort()->getConnectionPoint() == aPrs->startPoint()
296               ||
297             aPrs->getLink()->getInputPort()->getConnectionPoint() == aPrs->endPoint()
298               ||
299               aPrs->getLink()->getOutputPort()->getConnectionPoint() == aPrs->startPoint()
300               ||
301               aPrs->getLink()->getOutputPort()->getConnectionPoint() == aPrs->endPoint()) {
302             return;
303           }
304           myCurrentItem = *it;
305           aPrs->setMoving(true);
306           return;
307         }
308       }
309 //  }
310     } 
311   }
312 }
313
314 bool busy = false;
315
316 void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent) 
317 {
318   if (busy) return;
319       
320   busy = true;
321   QPoint p = inverseWorldMatrix().map(theEvent->pos());
322   QPoint g = theEvent->globalPos();
323       
324   if (myTimer->isActive()) myTimer->stop();
325
326   if (myIsLinkCreating && myLinkBuilder) {
327     myLinkBuilder->setFloatPoint(p);
328     canvas()->update();
329   }
330       
331   if (myCurrentItem) {
332     //    setHilighted(0);
333     if (myCurrentItem->x() && myCurrentItem->y()) {
334       double cx = myCurrentItem->x() - myPoint.x();
335       double cy = myCurrentItem->y() - myPoint.y();
336       
337       if (p.x()+cx < 0) p.setX(-(int)cx);
338       if (p.y()+cy < 0) p.setY(-(int)cy);
339     }
340     myCurrentItem->moveBy(p.x() - myPoint.x(), 
341                           p.y() - myPoint.y());
342     myPoint = p;
343     canvas()->update();
344         
345     // scroll contents if mouse is outside
346     QRect r(contentsX(), contentsY(), visibleWidth(), visibleHeight());
347     if (!r.contains(theEvent->pos())) {
348       int dx = 0, dy = 0;
349       if (theEvent->pos().x() < r.left()) dx = theEvent->pos().x() - r.left();
350       if (theEvent->pos().x() > r.right()) dx = theEvent->pos().x() - r.right();
351       if (theEvent->pos().y() < r.top()) dy = theEvent->pos().y() - r.top();
352       if (theEvent->pos().y() > r.bottom()) dy = theEvent->pos().y() - r.bottom();
353       scrollBy(dx, dy);
354       // start timer to scroll in silent mode
355       myDX = dx; myDY = dy;
356       myTimer->start(100);
357     }
358     busy = false;
359     return;
360   }
361
362   if (myIsPanActivated) {
363     setHilighted(0);
364     scrollBy(myGlobalPoint.x() - g.x(),
365              myGlobalPoint.y() - g.y());
366     myGlobalPoint = g;
367     busy = false;
368     return;
369   }
370       
371   if (myIsZoomActivated) {
372     setHilighted(0);
373     double dx = g.x() - myGlobalPoint.x();
374     double s = 1. + fabs(dx)/10.;
375     if (dx < 0) s = 1./s;
376     
377     QWMatrix m = worldMatrix();
378     m.scale(s, s);
379     setWorldMatrix(m);
380         
381     myGlobalPoint = g;
382     busy = false;
383     return;
384   }
385
386   //mkr: "Fit within rectangle" functionality
387   if (myIsFitWRActivated) {
388     int aLX, aTY; //left x and top y
389     if (myPoint.x() < p.x()) aLX = myPoint.x();
390     else aLX = p.x();
391     if (myPoint.y() < p.y()) aTY = myPoint.y();
392     else aTY = p.y();
393     QRect aRect(aLX, aTY, abs(myPoint.x()-p.x()), abs(myPoint.y()-p.y()));
394     QCanvasRectangle* aRect1 = new QCanvasRectangle(aRect, canvas());
395
396     //hide old selected rectangle
397     if (mySelectedRect)
398       mySelectedRect->hide();
399     //draw new selected rectangle
400     QPen pen(Qt::SolidLine);
401     pen.setWidth(1);
402     aRect1->setPen(pen);
403     aRect1->setZ(3);
404     aRect1->show();
405
406     mySelectedRect = aRect1;
407     canvas()->update();
408   }
409   
410   if (!myIsLinkCreating && myMain->isEditable() &&
411       !myMain->getCanvas()->isControlView()) {
412     // compute collision rectangle
413     QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
414     QCanvasItemList l = canvas()->collisions(aSel);
415     for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
416       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
417         SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
418         setHilighted(aPrs->getLink());
419         busy = false;
420         return;
421       }
422       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
423         SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
424         setHilighted(aPrs->getLink());
425         busy = false;
426         return;
427       }
428     }
429     setHilighted(0);
430   }
431
432   busy = false;
433 }
434
435 void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent) 
436 {
437   if (myTimer->isActive()) myTimer->stop();
438
439   if (myCurrentItem) {
440     if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
441       ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(0);
442       ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(false);
443       canvas()->update();
444     }
445     if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
446       ((SUPERVGUI_CanvasPointPrs*)myCurrentItem)->setMoving(false);
447     }
448   }
449   myCurrentItem = 0;
450
451   if (myIsPanActivated) {
452     myIsPanActivated = false;
453     myIsPanBtnClicked = false;
454     setCursor(myCursor);
455   }
456
457   if (myIsZoomActivated) {
458     myIsZoomActivated = false;
459     setCursor(myCursor);
460   }
461
462   //mkr: "Fit within rectangle" functionality
463   if (myIsFitWRActivated) {
464     if (mySelectedRect) {
465       mySelectedRect->hide();
466       mySelectedRect = 0;
467       canvas()->update();
468     }
469
470     //myPoint is the start point for selecting rectangle now
471     QPoint anEndPoint = inverseWorldMatrix().map(theEvent->pos());
472     int aLX, aTY; //left x and top y
473     if (myPoint.x() < anEndPoint.x()) aLX = myPoint.x();
474     else aLX = anEndPoint.x();
475     if (myPoint.y() < anEndPoint.y()) aTY = myPoint.y();
476     else aTY = anEndPoint.y();
477
478     //calculate width and height for new view and new zoom factor
479     double aXzoom = ((double)visibleWidth())/((double)(abs(myPoint.x()-anEndPoint.x())));
480     double aYzoom = ((double)visibleHeight())/((double)(abs(myPoint.y()-anEndPoint.y())));
481     if (aXzoom > aYzoom) aXzoom = aYzoom;
482     
483     QWMatrix m;
484     m.scale(aXzoom, aXzoom);
485     setWorldMatrix(m);
486     setContentsPos((int)(aLX*aXzoom), (int)(aTY*aYzoom));
487
488     canvas()->update();
489     
490     myIsFitWRActivated = false;
491     viewport()->setMouseTracking(true);
492     setCursor(myCursor);
493   }
494 }
495
496 void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
497 {
498   QPoint p = inverseWorldMatrix().map(theEvent->pos());
499
500   // compute collision rectangle
501   //QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
502
503   if (theEvent->button() == Qt::LeftButton) {
504     QCanvasItemList l = canvas()->collisions(p);
505     for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
506       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
507         SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
508         SUPERVGUI_CanvasNode* aNode = aNodePrs->getNode();
509         if (aNode->getEngine()->IsMacro() && !myIsLinkCreating) {
510           myMain->openSubGraph(aNode->getEngine(), true);
511           return;
512         }
513       }
514     }
515   }
516 }
517
518 void SUPERVGUI_CanvasView::onDestroyed(QObject* theObject)
519 {
520   if (theObject == myHilighted)
521     myHilighted = 0;
522 }
523
524 void SUPERVGUI_CanvasView::setHilighted(SUPERVGUI_CanvasLink* theLink)
525 {
526   if (theLink == myHilighted) return;
527   if (myHilighted) {
528     disconnect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
529     myHilighted->setHilighted(false);
530     myHilighted = 0;
531   }
532   if (theLink) {
533     myHilighted = theLink;
534     myHilighted->setHilighted(true);
535     connect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
536   }
537 }
538
539 void SUPERVGUI_CanvasView::onTimeout() 
540 {
541   if (myCurrentItem) {
542     scrollBy(myDX, myDY);
543
544     double cx, cy;
545     inverseWorldMatrix().map((double)myDX, (double)myDY, &cx, &cy);
546     if (myCurrentItem->x()+cx < 0) cx = -myCurrentItem->x();
547     if (myCurrentItem->y()+cy < 0) cy = -myCurrentItem->y();
548     myCurrentItem->moveBy(cx, cy);
549     myPoint.setX(myPoint.x()+(int)cx);
550     myPoint.setY(myPoint.y()+(int)cy);
551     canvas()->update();
552   }
553 }
554
555 void SUPERVGUI_CanvasView::changeBackground()
556 {
557   QColor aColor = QColorDialog::getColor(canvas()->backgroundColor(), this );
558   if ( aColor.isValid() ) {
559     canvas()->setBackgroundColor(aColor);
560     setPaletteBackgroundColor(aColor.light(120));
561   }
562 }
563
564 void SUPERVGUI_CanvasView::ActivatePanning()
565 {
566   myIsPanBtnClicked = true;
567 }
568
569 void SUPERVGUI_CanvasView::ResetView()
570 {
571   setContentsPos(0,0);
572   QWMatrix m;
573   setWorldMatrix(m);
574 }
575
576 void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
577 {
578   if (myIsLinkCreating) return;
579
580   myIsLinkCreating = true;
581   myLinkBuilder = new SUPERVGUI_CanvasLinkBuilder(canvas(), myMain, thePort);
582   mySketchPopup->setItemEnabled(myDelPntItem, false);
583 }
584
585 void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
586 {
587   if (!myIsLinkCreating) return;
588
589   if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
590     bool input = thePort->getEngine()->IsInput();
591     SUPERV_Link aLinkEngine;
592     if (thePort->getEngine()->Kind() == SUPERV::DataStreamParameter) {
593       SUPERVGUI_CanvasStreamPortIn* aInPort = (SUPERVGUI_CanvasStreamPortIn*) 
594         (input ? thePort : myLinkBuilder->getStartPort());
595       SUPERVGUI_CanvasStreamPortOut* aOutPort = (SUPERVGUI_CanvasStreamPortOut*) 
596         (input ? myLinkBuilder->getStartPort() : thePort);
597 //       aLinkEngine = myMain->getDataflow()->StreamLink(aOutPort->getStreamEngine(), 
598 //                                                    aInPort->getStreamEngine());
599       if (myMain->getDataflow()->IsStreamGraph()) {
600         SUPERV_StreamGraph aSGraph = myMain->getDataflow()->ToStreamGraph();
601         if (!SUPERV_isNull(aSGraph))
602           aLinkEngine = aSGraph->StreamLink(aOutPort->getStreamEngine(), 
603                                             aInPort->getStreamEngine());
604       }
605     }
606     else {
607       SUPERVGUI_CanvasPort* aInPort = (input ? thePort : myLinkBuilder->getStartPort());
608       SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
609       aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
610     }
611     if (SUPERV_isNull(aLinkEngine)) 
612       return;    
613
614     // here, in fact, aLinkEngine may NOT be a newly created link.  If a link already existed between the
615     // the 2 given ports - it will be return (NOT created again).
616     // this should be checked and new presentation should NOT be created for existing link.
617     // Solution 1: NOT to allow creation of a link if it already exists between the ports in 
618     //             myLinkBuilder->canCreateEngine()
619     // Solution 2: check here if aLinkEngine is "new" or "old"
620     // Implement 2nd solution, because canCreateEngine() checks for types of ports, etc.. - it's another thing
621     // THE CHECK:
622     QObjectList* canvasLinks = canvas()->queryList("SUPERVGUI_CanvasLink");
623     SUPERVGUI_CanvasLink* canvasLink = 0;
624     QObjectListIt it(*canvasLinks);
625     bool prsAlreadyExists = false;
626     while ( (canvasLink=(SUPERVGUI_CanvasLink*)it.current()) ) {
627       ++it;
628       SUPERV_Link existingLinkWithPrs = canvasLink->getEngine();
629       if ( !SUPERV_isNull( existingLinkWithPrs ) ) {
630         if ( existingLinkWithPrs->IsEqual( aLinkEngine ) ) {
631           prsAlreadyExists = true;
632           break;
633         }       
634       }
635     }
636     delete canvasLinks;
637     if ( prsAlreadyExists ) { // aLinkEngine is already bound with a SUPERVGUI_CanvasLink object
638       //return;  // -> if return here, than the old CanvasLink is kept
639
640       // we want to delete old and create a new CanvasLink for this Link
641       delete canvasLink;
642       canvasLink = 0;
643       // clear old corrdinates in Engine link
644       for ( int i = 1; i <= aLinkEngine->CoordsSize(); i++ )
645         aLinkEngine->RemoveCoord( i );
646       // now we are ready to set coords for a link and create a new CanvasLink presentation that will use them.
647     }
648
649     myLinkBuilder->setCoords(aLinkEngine.in());
650
651     delete myLinkBuilder;
652     myLinkBuilder = 0;
653
654     SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(canvas(), myMain, aLinkEngine);
655     aLink->show();
656
657     canvas()->update();
658     myIsLinkCreating = false;
659
660     // asv : 13.12.04 : introducing a check for ports' types compatibility (Bugs and Improvements p.1.16, PAL7380)
661     if ( !aLinkEngine->IsValid() ) { 
662       const int id = SUIT_MessageBox::warn2( this, tr( "TLT_INVALID_LINK" ), tr( "MSG_INVALID_LINK" ), 
663                                              tr( "Keep" ), tr( "Remove" ), 0, 1, 0 );
664       if ( id == 1 ) { // "Remove" was selected in Message Box
665         aLink->remove(); // the new link did not live long...
666       }
667     }
668   }
669 }
670
671 void SUPERVGUI_CanvasView::cancelSketch()
672 {
673   if (myLinkBuilder) {
674     delete myLinkBuilder;
675     myLinkBuilder = 0;
676     canvas()->update();
677   }
678   myIsLinkCreating = false;
679 }
680
681 void SUPERVGUI_CanvasView::deletePoint()
682 {
683   if (myIsLinkCreating && myLinkBuilder) {
684     myLinkBuilder->removeLastPoint();
685     canvas()->update();
686     mySketchPopup->setItemEnabled(myDelPntItem, myLinkBuilder->getPointCount());
687   }
688 }
689
690 void SUPERVGUI_CanvasView::setOrthoMode()
691 {
692   bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
693   mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
694 }
695
696 void SUPERVGUI_CanvasView::zoomIn() 
697 {
698   QWMatrix m;
699   m.scale(2.0, 2.0);
700   setWorldMatrix(m);
701   canvas()->update();
702 }
703
704 void SUPERVGUI_CanvasView::zoomReset() 
705 {
706   QWMatrix m;
707   m.scale(1.0, 1.0);
708   setWorldMatrix(m);
709   canvas()->update();
710 }
711
712 void SUPERVGUI_CanvasView::zoomOut() 
713 {
714   QWMatrix m;
715   m.scale(0.5, 0.5);
716   setWorldMatrix(m);
717   canvas()->update();
718 }
719
720 void SUPERVGUI_CanvasView::fitAll() 
721 {
722   int w = 0, h = 0;
723   QCanvasItemList l = canvas()->allItems();
724   for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
725     QRect r = (*it)->boundingRect();
726     if (w < r.right()) w = r.right();
727     if (h < r.bottom()) h = r.bottom();
728   }
729   w += GRAPH_MARGIN; h += GRAPH_MARGIN;
730   double s = ((double)visibleWidth())/((double)w);
731   double s1 = ((double)visibleHeight())/((double)h);
732   if (s > s1) s = s1;
733
734   setContentsPos(0,0);
735   QWMatrix m;
736   m.scale(s, s);
737   setWorldMatrix(m);
738   canvas()->update();
739 }
740
741 void SUPERVGUI_CanvasView::fitWithinRect() 
742 {
743   //mkr: "Fit within rectangle" functionality
744   myIsFitWRActivated = true;
745   viewport()->setMouseTracking(false);
746   myCursor = cursor();
747   setCursor(handCursor);
748 }
749
750 bool SUPERVGUI_CanvasView::isHavingStreamPort() const
751 {
752   SUPERV::ListOfNodes* aNodesList = myMain->getDataflow()->Nodes();
753
754   //Computing Nodes
755   for ( int i = 0 ; i < (int) aNodesList->CNodes.length() ; i++ ) {
756     SUPERV::ListOfStreamPorts aStrPortsList = *( (aNodesList->CNodes)[i]->StreamPorts() );
757     if ((int) aStrPortsList.length() > 0) {
758       return true;
759     }
760   }
761    
762   //FactoryNodes
763   for ( int i = 0 ; i < (int) aNodesList->FNodes.length() ; i++ ) {
764     SUPERV::ListOfStreamPorts aStrPortsList = *( (aNodesList->FNodes)[i]->StreamPorts() );
765     if ((int) aStrPortsList.length() > 0) {
766       return true;
767     }
768   }
769         
770   //InLineNodes
771   for ( int i = 0 ; i < (int) aNodesList->INodes.length() ; i++ ) {
772     SUPERV::ListOfStreamPorts aStrPortsList = *( (aNodesList->INodes)[i]->StreamPorts() );
773     if ((int) aStrPortsList.length() > 0) {
774       return true;
775     }
776   }
777         
778   //GOTONodes
779   for ( int i = 0 ; i < (int) aNodesList->GNodes.length() ; i++ ) {
780     SUPERV::ListOfStreamPorts aStrPortsList = *( (aNodesList->GNodes)[i]->StreamPorts() );
781     if ((int) aStrPortsList.length() > 0) {
782       return true;
783     }
784   }
785         
786   //LoopNodes
787   for ( int i = 0 ; i < (int) aNodesList->LNodes.length() ; i++ ) {
788     SUPERV::ListOfStreamPorts aStrPortsList = *( (aNodesList->LNodes)[i]->StreamPorts() );
789     if ((int) aStrPortsList.length() > 0) {
790      return true;
791     }
792   }
793         
794   //SwitchNodes
795   for ( int i = 0 ; i < (int) aNodesList->SNodes.length() ; i++ ) {
796     SUPERV::ListOfStreamPorts aStrPortsList = *( (aNodesList->SNodes)[i]->StreamPorts() );
797     if ((int) aStrPortsList.length() > 0) {
798       return true;
799     }
800   }
801         
802   return false;
803 }