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