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