Salome HOME
SMH: 3.0.0 preparation = merged version (POLYWORK + RTVDEBUG01) + adopation for new GUI
[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
154 SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
155 {
156 }
157
158 void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent) 
159 {
160   myPoint = inverseWorldMatrix().map(theEvent->pos());
161   myGlobalPoint = theEvent->globalPos();
162   myCurrentItem = 0;
163
164   // compute collision rectangle
165   QRect aSel(myPoint.x()-MARGIN, myPoint.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
166
167   if (((theEvent->button() == Qt::MidButton) &&
168        (theEvent->state() == Qt::ControlButton)) || 
169       myIsPanBtnClicked) {
170     myIsPanActivated = true;
171     myCursor = cursor();
172     setCursor(pan2Cursor);
173     return;
174   }
175
176   if (((theEvent->button() == Qt::LeftButton) &&
177        (theEvent->state() == Qt::ControlButton)) || 
178       myIsZoomActivated) {
179     myIsZoomActivated = true;
180     myCursor = cursor();
181     setCursor(zoom2Cursor);
182     return;
183   }
184
185   if ( theEvent->button() == Qt::RightButton) {
186     if (myIsLinkCreating) {
187       myMain->showPopup(mySketchPopup, theEvent);
188       return;
189     }
190
191     QCanvasItemList l = canvas()->collisions(aSel);
192     for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
193       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
194         SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
195         QObject* anObj = aNodePrs->getObject(myPoint);
196         if (anObj->inherits("SUPERVGUI_CanvasNode")) {
197           myMain->showPopup(((SUPERVGUI_CanvasNode*)anObj)->getPopupMenu(viewport()), 
198                             theEvent);
199           return;
200         }
201         else if (anObj->inherits("SUPERVGUI_CanvasPort")) {
202           myMain->showPopup(((SUPERVGUI_CanvasPort*)anObj)->getPopupMenu(viewport()), 
203                             theEvent);
204           return;
205         }
206       }
207       if (myMain->isEditable() && !myMain->getCanvas()->isControlView()) {
208         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
209           SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
210           aPrs->getLink()->setSelectedObject(aPrs, myPoint);
211           myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
212           return;
213         }
214         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
215           SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
216           aPrs->getLink()->setSelectedObject(aPrs, myPoint);
217           myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
218           return;
219         }
220       }
221     }
222         
223     myPopup->setItemEnabled(myAddStudyItem, !myMain->isDataflowInStudy());
224     // Paste Node functionality
225     SUPERVGUI_Clipboard* aCB = SUPERVGUI_Clipboard::getClipboard(); 
226     myPopup->setItemEnabled(myPasteNodeItem, aCB->isCopyNode() );
227     myMain->showPopup(myPopup, theEvent);
228     return;
229   }
230
231   if (theEvent->button() == Qt::LeftButton) {
232     if (!myIsFitWRActivated) {//not moving items if fit within rectangle 
233                               //functionality is enable
234       QCanvasItemList l = canvas()->collisions(myPoint);
235       if (myIsLinkCreating) {
236         for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
237           if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
238             SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
239             QObject* anObj = aNodePrs->getObject(myPoint);
240             if (anObj->inherits("SUPERVGUI_CanvasPort")) {
241               endSketch((SUPERVGUI_CanvasPort*)anObj);
242               return;
243             }
244             else {
245               myCurrentItem = *it;
246               ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
247               ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
248               return;
249             }
250           }
251           if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
252             SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
253             QObject* anObj = aHookPrs->getObject();
254             if (anObj->inherits("SUPERVGUI_CanvasPort")) {
255               endSketch((SUPERVGUI_CanvasPort*)anObj);
256               return;
257             }
258           }
259         }
260         if (myLinkBuilder) {
261           myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
262           canvas()->update();
263           mySketchPopup->setItemEnabled(myDelPntItem, true);
264           return;
265         }
266       }
267       
268 //  if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
269       for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
270         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
271           myCurrentItem = *it;
272           ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
273           ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
274           return;
275         }
276         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
277           SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
278           if (aPrs->getIndex() > 0) {
279             myCurrentItem = *it;
280             aPrs->setMoving(true);
281             return;
282           }
283         }
284         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
285           //mkr: for moving segment of link
286           SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
287           if (aPrs->getLink()->getInputPort()->getConnectionPoint() == aPrs->startPoint()
288               ||
289             aPrs->getLink()->getInputPort()->getConnectionPoint() == aPrs->endPoint()
290               ||
291               aPrs->getLink()->getOutputPort()->getConnectionPoint() == aPrs->startPoint()
292               ||
293               aPrs->getLink()->getOutputPort()->getConnectionPoint() == aPrs->endPoint()) {
294             return;
295           }
296           myCurrentItem = *it;
297           aPrs->setMoving(true);
298           return;
299         }
300       }
301 //  }
302     } 
303   }
304 }
305
306 bool busy = false;
307
308 void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent) 
309 {
310   if (busy) return;
311       
312   busy = true;
313   QPoint p = inverseWorldMatrix().map(theEvent->pos());
314   QPoint g = theEvent->globalPos();
315       
316   if (myTimer->isActive()) myTimer->stop();
317
318   if (myIsLinkCreating && myLinkBuilder) {
319     myLinkBuilder->setFloatPoint(p);
320     canvas()->update();
321   }
322       
323   if (myCurrentItem) {
324     //    setHilighted(0);
325     if (myCurrentItem->x() && myCurrentItem->y()) {
326       double cx = myCurrentItem->x() - myPoint.x();
327       double cy = myCurrentItem->y() - myPoint.y();
328       
329       if (p.x()+cx < 0) p.setX(-(int)cx);
330       if (p.y()+cy < 0) p.setY(-(int)cy);
331     }
332     myCurrentItem->moveBy(p.x() - myPoint.x(), 
333                           p.y() - myPoint.y());
334     myPoint = p;
335     canvas()->update();
336         
337     // scroll contents if mouse is outside
338     QRect r(contentsX(), contentsY(), visibleWidth(), visibleHeight());
339     if (!r.contains(theEvent->pos())) {
340       int dx = 0, dy = 0;
341       if (theEvent->pos().x() < r.left()) dx = theEvent->pos().x() - r.left();
342       if (theEvent->pos().x() > r.right()) dx = theEvent->pos().x() - r.right();
343       if (theEvent->pos().y() < r.top()) dy = theEvent->pos().y() - r.top();
344       if (theEvent->pos().y() > r.bottom()) dy = theEvent->pos().y() - r.bottom();
345       scrollBy(dx, dy);
346       // start timer to scroll in silent mode
347       myDX = dx; myDY = dy;
348       myTimer->start(100);
349     }
350     busy = false;
351     return;
352   }
353
354   if (myIsPanActivated) {
355     setHilighted(0);
356     scrollBy(myGlobalPoint.x() - g.x(),
357              myGlobalPoint.y() - g.y());
358     myGlobalPoint = g;
359     busy = false;
360     return;
361   }
362       
363   if (myIsZoomActivated) {
364     setHilighted(0);
365     double dx = g.x() - myGlobalPoint.x();
366     double s = 1. + fabs(dx)/10.;
367     if (dx < 0) s = 1./s;
368     
369     QWMatrix m = worldMatrix();
370     m.scale(s, s);
371     setWorldMatrix(m);
372         
373     myGlobalPoint = g;
374     busy = false;
375     return;
376   }
377
378   //mkr: "Fit within rectangle" functionality
379   if (myIsFitWRActivated) {
380     int aLX, aTY; //left x and top y
381     if (myPoint.x() < p.x()) aLX = myPoint.x();
382     else aLX = p.x();
383     if (myPoint.y() < p.y()) aTY = myPoint.y();
384     else aTY = p.y();
385     QRect aRect(aLX, aTY, abs(myPoint.x()-p.x()), abs(myPoint.y()-p.y()));
386     QCanvasRectangle* aRect1 = new QCanvasRectangle(aRect, canvas());
387
388     //hide old selected rectangle
389     if (mySelectedRect)
390       mySelectedRect->hide();
391     //draw new selected rectangle
392     QPen pen(Qt::SolidLine);
393     pen.setWidth(1);
394     aRect1->setPen(pen);
395     aRect1->setZ(3);
396     aRect1->show();
397
398     mySelectedRect = aRect1;
399     canvas()->update();
400   }
401   
402   if (!myIsLinkCreating && myMain->isEditable() &&
403       !myMain->getCanvas()->isControlView()) {
404     // compute collision rectangle
405     QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
406     QCanvasItemList l = canvas()->collisions(aSel);
407     for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
408       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
409         SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
410         setHilighted(aPrs->getLink());
411         busy = false;
412         return;
413       }
414       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
415         SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
416         setHilighted(aPrs->getLink());
417         busy = false;
418         return;
419       }
420     }
421     setHilighted(0);
422   }
423
424   busy = false;
425 }
426
427 void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent) 
428 {
429   if (myTimer->isActive()) myTimer->stop();
430
431   if (myCurrentItem) {
432     if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
433       ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(0);
434       ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(false);
435       canvas()->update();
436     }
437     if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
438       ((SUPERVGUI_CanvasPointPrs*)myCurrentItem)->setMoving(false);
439     }
440   }
441   myCurrentItem = 0;
442
443   if (myIsPanActivated) {
444     myIsPanActivated = false;
445     myIsPanBtnClicked = false;
446     setCursor(myCursor);
447   }
448
449   if (myIsZoomActivated) {
450     myIsZoomActivated = false;
451     setCursor(myCursor);
452   }
453
454   //mkr: "Fit within rectangle" functionality
455   if (myIsFitWRActivated) {
456     if (mySelectedRect) {
457       mySelectedRect->hide();
458       mySelectedRect = 0;
459       canvas()->update();
460     }
461
462     //myPoint is the start point for selecting rectangle now
463     QPoint anEndPoint = inverseWorldMatrix().map(theEvent->pos());
464     int aLX, aTY; //left x and top y
465     if (myPoint.x() < anEndPoint.x()) aLX = myPoint.x();
466     else aLX = anEndPoint.x();
467     if (myPoint.y() < anEndPoint.y()) aTY = myPoint.y();
468     else aTY = anEndPoint.y();
469
470     //calculate width and height for new view and new zoom factor
471     double aXzoom = ((double)visibleWidth())/((double)(abs(myPoint.x()-anEndPoint.x())));
472     double aYzoom = ((double)visibleHeight())/((double)(abs(myPoint.y()-anEndPoint.y())));
473     if (aXzoom > aYzoom) aXzoom = aYzoom;
474     
475     QWMatrix m;
476     m.scale(aXzoom, aXzoom);
477     setWorldMatrix(m);
478     setContentsPos((int)(aLX*aXzoom), (int)(aTY*aYzoom));
479
480     canvas()->update();
481     
482     myIsFitWRActivated = false;
483     viewport()->setMouseTracking(true);
484     setCursor(myCursor);
485   }
486 }
487
488 void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
489 {
490   QPoint p = inverseWorldMatrix().map(theEvent->pos());
491
492   // compute collision rectangle
493   //QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
494
495   if (theEvent->button() == Qt::LeftButton) {
496     QCanvasItemList l = canvas()->collisions(p);
497     for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
498       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
499         SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
500         SUPERVGUI_CanvasNode* aNode = aNodePrs->getNode();
501         if (aNode->getEngine()->IsMacro() && !myIsLinkCreating) {
502           myMain->openSubGraph(aNode->getEngine(), true);
503           return;
504         }
505       }
506     }
507   }
508 }
509
510 void SUPERVGUI_CanvasView::onDestroyed(QObject* theObject)
511 {
512   if (theObject == myHilighted)
513     myHilighted = 0;
514 }
515
516 void SUPERVGUI_CanvasView::setHilighted(SUPERVGUI_CanvasLink* theLink)
517 {
518   if (theLink == myHilighted) return;
519   if (myHilighted) {
520     disconnect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
521     myHilighted->setHilighted(false);
522     myHilighted = 0;
523   }
524   if (theLink) {
525     myHilighted = theLink;
526     myHilighted->setHilighted(true);
527     connect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
528   }
529 }
530
531 void SUPERVGUI_CanvasView::onTimeout() 
532 {
533   if (myCurrentItem) {
534     scrollBy(myDX, myDY);
535
536     double cx, cy;
537     inverseWorldMatrix().map((double)myDX, (double)myDY, &cx, &cy);
538     if (myCurrentItem->x()+cx < 0) cx = -myCurrentItem->x();
539     if (myCurrentItem->y()+cy < 0) cy = -myCurrentItem->y();
540     myCurrentItem->moveBy(cx, cy);
541     myPoint.setX(myPoint.x()+(int)cx);
542     myPoint.setY(myPoint.y()+(int)cy);
543     canvas()->update();
544   }
545 }
546
547 void SUPERVGUI_CanvasView::changeBackground()
548 {
549   QColor aColor = QColorDialog::getColor(canvas()->backgroundColor(), this );
550   if ( aColor.isValid() ) {
551     canvas()->setBackgroundColor(aColor);
552     setPaletteBackgroundColor(aColor.light(120));
553   }
554 }
555
556 void SUPERVGUI_CanvasView::ActivatePanning()
557 {
558   myIsPanBtnClicked = true;
559 }
560
561 void SUPERVGUI_CanvasView::ResetView()
562 {
563   setContentsPos(0,0);
564   QWMatrix m;
565   setWorldMatrix(m);
566 }
567
568 void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
569 {
570   if (myIsLinkCreating) return;
571
572   myIsLinkCreating = true;
573   myLinkBuilder = new SUPERVGUI_CanvasLinkBuilder(canvas(), myMain, thePort);
574   mySketchPopup->setItemEnabled(myDelPntItem, false);
575 }
576
577 void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
578 {
579   if (!myIsLinkCreating) return;
580
581   if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
582     bool input = thePort->getEngine()->IsInput();
583     SUPERV_Link aLinkEngine;
584     if (thePort->getEngine()->Kind() == SUPERV::DataStreamParameter) {
585       SUPERVGUI_CanvasStreamPortIn* aInPort = (SUPERVGUI_CanvasStreamPortIn*) 
586         (input ? thePort : myLinkBuilder->getStartPort());
587       SUPERVGUI_CanvasStreamPortOut* aOutPort = (SUPERVGUI_CanvasStreamPortOut*) 
588         (input ? myLinkBuilder->getStartPort() : thePort);
589 //       aLinkEngine = myMain->getDataflow()->StreamLink(aOutPort->getStreamEngine(), 
590 //                                                    aInPort->getStreamEngine());
591       if (myMain->getDataflow()->IsStreamGraph()) {
592         SUPERV_StreamGraph aSGraph = myMain->getDataflow()->ToStreamGraph();
593         if (!SUPERV_isNull(aSGraph))
594           aLinkEngine = aSGraph->StreamLink(aOutPort->getStreamEngine(), 
595                                             aInPort->getStreamEngine());
596       }
597     }
598     else {
599       SUPERVGUI_CanvasPort* aInPort = (input ? thePort : myLinkBuilder->getStartPort());
600       SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
601       aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
602     }
603     if (SUPERV_isNull(aLinkEngine)) 
604       return;    
605
606     // here, in fact, aLinkEngine may NOT be a newly created link.  If a link already existed between the
607     // the 2 given ports - it will be return (NOT created again).
608     // this should be checked and new presentation should NOT be created for existing link.
609     // Solution 1: NOT to allow creation of a link if it already exists between the ports in 
610     //             myLinkBuilder->canCreateEngine()
611     // Solution 2: check here if aLinkEngine is "new" or "old"
612     // Implement 2nd solution, because canCreateEngine() checks for types of ports, etc.. - it's another thing
613     // THE CHECK:
614     QObjectList* canvasLinks = canvas()->queryList("SUPERVGUI_CanvasLink");
615     SUPERVGUI_CanvasLink* canvasLink = 0;
616     QObjectListIt it(*canvasLinks);
617     bool prsAlreadyExists = false;
618     while ( (canvasLink=(SUPERVGUI_CanvasLink*)it.current()) ) {
619       ++it;
620       SUPERV_Link existingLinkWithPrs = canvasLink->getEngine();
621       if ( !SUPERV_isNull( existingLinkWithPrs ) ) {
622         if ( existingLinkWithPrs->IsEqual( aLinkEngine ) ) {
623           prsAlreadyExists = true;
624           break;
625         }       
626       }
627     }
628     delete canvasLinks;
629     if ( prsAlreadyExists ) { // aLinkEngine is already bound with a SUPERVGUI_CanvasLink object
630       //return;  // -> if return here, than the old CanvasLink is kept
631
632       // we want to delete old and create a new CanvasLink for this Link
633       delete canvasLink;
634       canvasLink = 0;
635       // clear old corrdinates in Engine link
636       for ( int i = 1; i <= aLinkEngine->CoordsSize(); i++ )
637         aLinkEngine->RemoveCoord( i );
638       // now we are ready to set coords for a link and create a new CanvasLink presentation that will use them.
639     }
640
641     myLinkBuilder->setCoords(aLinkEngine.in());
642
643     delete myLinkBuilder;
644     myLinkBuilder = 0;
645
646     SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(canvas(), myMain, aLinkEngine);
647     aLink->show();
648
649     canvas()->update();
650     myIsLinkCreating = false;
651
652     // asv : 13.12.04 : introducing a check for ports' types compatibility (Bugs and Improvements p.1.16, PAL7380)
653     if ( !aLinkEngine->IsValid() ) { 
654       const int id = SUIT_MessageBox::warn2( this, tr( "TLT_INVALID_LINK" ), tr( "MSG_INVALID_LINK" ), 
655                                              tr( "Keep" ), tr( "Remove" ), 0, 1, 0 );
656       if ( id == 1 ) { // "Remove" was selected in Message Box
657         aLink->remove(); // the new link did not live long...
658       }
659     }
660   }
661 }
662
663 void SUPERVGUI_CanvasView::cancelSketch()
664 {
665   if (myLinkBuilder) {
666     delete myLinkBuilder;
667     myLinkBuilder = 0;
668     canvas()->update();
669   }
670   myIsLinkCreating = false;
671 }
672
673 void SUPERVGUI_CanvasView::deletePoint()
674 {
675   if (myIsLinkCreating && myLinkBuilder) {
676     myLinkBuilder->removeLastPoint();
677     canvas()->update();
678     mySketchPopup->setItemEnabled(myDelPntItem, myLinkBuilder->getPointCount());
679   }
680 }
681
682 void SUPERVGUI_CanvasView::setOrthoMode()
683 {
684   bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
685   mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
686 }
687
688 void SUPERVGUI_CanvasView::zoomIn() 
689 {
690   QWMatrix m;
691   m.scale(2.0, 2.0);
692   setWorldMatrix(m);
693   canvas()->update();
694 }
695
696 void SUPERVGUI_CanvasView::zoomReset() 
697 {
698   QWMatrix m;
699   m.scale(1.0, 1.0);
700   setWorldMatrix(m);
701   canvas()->update();
702 }
703
704 void SUPERVGUI_CanvasView::zoomOut() 
705 {
706   QWMatrix m;
707   m.scale(0.5, 0.5);
708   setWorldMatrix(m);
709   canvas()->update();
710 }
711
712 void SUPERVGUI_CanvasView::fitAll() 
713 {
714   int w = 0, h = 0;
715   QCanvasItemList l = canvas()->allItems();
716   for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
717     QRect r = (*it)->boundingRect();
718     if (w < r.right()) w = r.right();
719     if (h < r.bottom()) h = r.bottom();
720   }
721   w += GRAPH_MARGIN; h += GRAPH_MARGIN;
722   double s = ((double)visibleWidth())/((double)w);
723   double s1 = ((double)visibleHeight())/((double)h);
724   if (s > s1) s = s1;
725
726   setContentsPos(0,0);
727   QWMatrix m;
728   m.scale(s, s);
729   setWorldMatrix(m);
730   canvas()->update();
731 }
732
733 void SUPERVGUI_CanvasView::fitWithinRect() 
734 {
735   //mkr: "Fit within rectangle" functionality
736   myIsFitWRActivated = true;
737   viewport()->setMouseTracking(false);
738   myCursor = cursor();
739   setCursor(handCursor);
740 }