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