1 // SUPERV SUPERVGUI : GUI for Supervisor component
3 // Copyright (C) 2003 CEA/DEN, EDF R&D
7 // File : SUPERVGUI_CanvasView.cxx
8 // Author : Natalia KOPNOVA
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"
20 #include "QAD_Config.h"
21 #include "QAD_MessageBox.h"
24 #include <qcolordialog.h>
30 const char* imageZoomCursor[] = {
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 "................................"};
68 QPixmap zoomPix(imageZoomCursor);
69 QCursor zoom2Cursor(zoomPix);
71 #if QT_VERSION >= 0x030005
72 QCursor pan2Cursor(Qt::SizeAllCursor);
74 QCursor pan2Cursor(SizeAllCursor);
77 SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGUI_Main* theMain):
78 QCanvasView(theCanvas, theMain),
79 myMain(theMain), myCurrentItem(0), myHilighted(0), myLinkBuilder(0)
81 setName("CanvasView");
83 myIsPanBtnClicked = false;
84 myIsPanActivated = false;
85 myIsZoomActivated = false;
86 myIsLinkCreating = false;
91 myTimer = new QTimer(this);
92 connect(myTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
94 myPopup = new QPopupMenu(viewport());
96 const bool isEdit = myMain->isEditable();
98 myPopup->insertItem(tr("MSG_ADD_NODE"), myMain, SLOT(addNode()));
99 myPopup->insertItem(tr("MSG_INS_FILE"), myMain, SLOT(insertFile()));
100 myPopup->insertSeparator();
103 QPopupMenu* aViewPopup = new QPopupMenu(viewport());
104 aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showCanvas()));
105 aViewPopup->insertItem(tr("POP_CONTROLVIEW"), myMain, SLOT(showContolFlow()));
106 aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showCanvasTable()));
108 myPopup->insertItem(tr("POP_VIEW"), aViewPopup);
109 myPopup->insertSeparator();
111 QPopupMenu* aZoomPopup = new QPopupMenu(viewport());
112 aZoomPopup->insertItem("200%", this, SLOT(zoomIn()));
113 aZoomPopup->insertItem("100%", this, SLOT(zoomReset()));
114 aZoomPopup->insertItem("50%", this, SLOT(zoomOut()));
115 aZoomPopup->insertSeparator();
116 aZoomPopup->insertItem("Fit All", this, SLOT(fitAll()));
118 myPopup->insertItem("Zoom", aZoomPopup);
119 myPopup->insertSeparator();
121 myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), this, SLOT(addToStudy()));
122 myPopup->insertItem(tr(isEdit ? "MSG_CHANGE_INFO" : "MSG_INFO"), myMain, SLOT(changeInformation()));
123 myPopup->insertSeparator();
125 myPopup->insertItem(tr("MSG_COPY_DATAFLOW"), myMain, SLOT(copy()));
126 myPopup->insertItem(tr("MSG_FILTER_NOTIFY"), myMain, SLOT(filterNotification()));
128 myPopup->insertSeparator();
129 myPopup->insertItem(tr("MSG_CHANGE_BACKGROUND"), this, SLOT(changeBackground()));
131 viewport()->setMouseTracking(true);
133 //create sketching popup menu
134 mySketchPopup = new QPopupMenu(viewport());
135 mySketchPopup->setCheckable(true);
136 myDelPntItem = mySketchPopup->insertItem(tr("MSG_DEL_LAST_PNT"), this, SLOT(deletePoint()));
137 mySketchPopup->insertItem(tr("MSG_DEL_LINK"), this, SLOT(cancelSketch()));
138 myOrtoItem = mySketchPopup->insertItem(tr("MSG_ORTHO_LINE"), this, SLOT(setOrthoMode()));
142 SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
146 void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
148 // MESSAGE("===> SUPERVGUI_CanvasView::contentsMousePressEvent(...) ");
149 myPoint = inverseWorldMatrix().map(theEvent->pos());
150 myGlobalPoint = theEvent->globalPos();
153 // compute collision rectangle
154 QRect aSel(myPoint.x()-MARGIN, myPoint.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
156 if (((theEvent->button() == Qt::MidButton) &&
157 (theEvent->state() == Qt::ControlButton)) ||
159 myIsPanActivated = true;
161 setCursor(pan2Cursor);
165 if (((theEvent->button() == Qt::LeftButton) &&
166 (theEvent->state() == Qt::ControlButton)) ||
168 myIsZoomActivated = true;
170 setCursor(zoom2Cursor);
174 if ( theEvent->button() == Qt::RightButton) {
175 if (myIsLinkCreating) {
176 myMain->showPopup(mySketchPopup, theEvent);
180 QCanvasItemList l = canvas()->collisions(aSel);
181 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
182 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
183 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
184 QObject* anObj = aNodePrs->getObject(myPoint);
185 if (anObj->inherits("SUPERVGUI_CanvasNode")) {
186 myMain->showPopup(((SUPERVGUI_CanvasNode*)anObj)->getPopupMenu(viewport()),
190 else if (anObj->inherits("SUPERVGUI_CanvasPort")) {
191 myMain->showPopup(((SUPERVGUI_CanvasPort*)anObj)->getPopupMenu(viewport()),
196 if (myMain->isEditable() && !myMain->getCanvas()->isControlView()) {
197 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
198 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
199 aPrs->getLink()->setSelectedObject(aPrs, myPoint);
200 myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
203 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
204 SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
205 aPrs->getLink()->setSelectedObject(aPrs, myPoint);
206 myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
212 myPopup->setItemEnabled(myAddStudyItem, !myMain->isFromStudy());
213 myMain->showPopup(myPopup, theEvent);
217 if (theEvent->button() == Qt::LeftButton) {
218 QCanvasItemList l = canvas()->collisions(myPoint);
219 if (myIsLinkCreating) {
220 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
221 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
222 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
223 QObject* anObj = aNodePrs->getObject(myPoint);
224 if (anObj->inherits("SUPERVGUI_CanvasPort")) {
225 endSketch((SUPERVGUI_CanvasPort*)anObj);
230 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
231 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
235 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
236 SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
237 QObject* anObj = aHookPrs->getObject();
238 if (anObj->inherits("SUPERVGUI_CanvasPort")) {
239 endSketch((SUPERVGUI_CanvasPort*)anObj);
245 myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
247 mySketchPopup->setItemEnabled(myDelPntItem, true);
252 // if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
253 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
254 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
256 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
257 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
260 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
261 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
262 if (aPrs->getIndex() > 0) {
264 aPrs->setMoving(true);
275 void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
280 QPoint p = inverseWorldMatrix().map(theEvent->pos());
281 QPoint g = theEvent->globalPos();
283 if (myTimer->isActive()) myTimer->stop();
285 if (myIsLinkCreating && myLinkBuilder) {
286 myLinkBuilder->setFloatPoint(p);
292 double cx = myCurrentItem->x() - myPoint.x();
293 double cy = myCurrentItem->y() - myPoint.y();
294 if (p.x()+cx < 0) p.setX(-(int)cx);
295 if (p.y()+cy < 0) p.setY(-(int)cy);
296 myCurrentItem->moveBy(p.x() - myPoint.x(),
297 p.y() - myPoint.y());
301 // scroll contents if mouse is outside
302 QRect r(contentsX(), contentsY(), visibleWidth(), visibleHeight());
303 if (!r.contains(theEvent->pos())) {
305 if (theEvent->pos().x() < r.left()) dx = theEvent->pos().x() - r.left();
306 if (theEvent->pos().x() > r.right()) dx = theEvent->pos().x() - r.right();
307 if (theEvent->pos().y() < r.top()) dy = theEvent->pos().y() - r.top();
308 if (theEvent->pos().y() > r.bottom()) dy = theEvent->pos().y() - r.bottom();
310 // start timer to scroll in silent mode
311 myDX = dx; myDY = dy;
318 if (myIsPanActivated) {
320 scrollBy(myGlobalPoint.x() - g.x(),
321 myGlobalPoint.y() - g.y());
327 if (myIsZoomActivated) {
329 double dx = g.x() - myGlobalPoint.x();
330 double s = 1. + fabs(dx)/10.;
331 if (dx < 0) s = 1./s;
333 QWMatrix m = worldMatrix();
342 if (!myIsLinkCreating && myMain->isEditable() &&
343 !myMain->getCanvas()->isControlView()) {
344 // compute collision rectangle
345 QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
346 QCanvasItemList l = canvas()->collisions(aSel);
347 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
348 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
349 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
350 setHilighted(aPrs->getLink());
354 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
355 SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
356 setHilighted(aPrs->getLink());
367 void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent)
369 // MESSAGE("===> SUPERVGUI_CanvasView::contentsMouseReleaseEvent(...) ");
370 if (myTimer->isActive()) myTimer->stop();
373 if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
374 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(0);
375 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(false);
378 if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
379 ((SUPERVGUI_CanvasPointPrs*)myCurrentItem)->setMoving(false);
384 if (myIsPanActivated) {
385 myIsPanActivated = false;
386 myIsPanBtnClicked = false;
390 if (myIsZoomActivated) {
391 myIsZoomActivated = false;
396 void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
398 // MESSAGE("===> SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(...) ");
399 QPoint p = inverseWorldMatrix().map(theEvent->pos());
401 // compute collision rectangle
402 QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
404 if (theEvent->button() == Qt::LeftButton) {
405 QCanvasItemList l = canvas()->collisions(p);
406 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
407 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
408 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
409 SUPERVGUI_CanvasNode* aNode = aNodePrs->getNode();
410 if (aNode->getEngine()->IsMacro() && !myIsLinkCreating) {
411 myMain->openSubGraph(aNode->getEngine(), true);
419 void SUPERVGUI_CanvasView::onDestroyed(QObject* theObject)
421 if (theObject == myHilighted)
425 void SUPERVGUI_CanvasView::setHilighted(SUPERVGUI_CanvasLink* theLink)
427 if (theLink == myHilighted) return;
429 disconnect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
430 myHilighted->setHilighted(false);
434 myHilighted = theLink;
435 myHilighted->setHilighted(true);
436 connect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
440 void SUPERVGUI_CanvasView::onTimeout()
443 scrollBy(myDX, myDY);
446 inverseWorldMatrix().map((double)myDX, (double)myDY, &cx, &cy);
447 if (myCurrentItem->x()+cx < 0) cx = -myCurrentItem->x();
448 if (myCurrentItem->y()+cy < 0) cy = -myCurrentItem->y();
449 myCurrentItem->moveBy(cx, cy);
450 myPoint.setX(myPoint.x()+(int)cx);
451 myPoint.setY(myPoint.y()+(int)cy);
456 void SUPERVGUI_CanvasView::changeBackground()
458 QColor aColor = QColorDialog::getColor(canvas()->backgroundColor(), this );
459 if ( aColor.isValid() ) {
460 canvas()->setBackgroundColor(aColor);
461 setPaletteBackgroundColor(aColor.light(120));
465 void SUPERVGUI_CanvasView::ActivatePanning()
467 myIsPanBtnClicked = true;
470 void SUPERVGUI_CanvasView::ResetView()
477 void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
479 if (myIsLinkCreating) return;
481 myIsLinkCreating = true;
482 myLinkBuilder = new SUPERVGUI_CanvasLinkBuilder(canvas(), myMain, thePort);
483 mySketchPopup->setItemEnabled(myDelPntItem, false);
486 void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
488 // MESSAGE("===> SUPERVGUI_CanvasView::endSketch(" << thePort->name() << ")");
489 if (!myIsLinkCreating) return;
491 if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
492 bool input = thePort->getEngine()->IsInput();
493 SUPERV_Link aLinkEngine;
494 if (thePort->getEngine()->Kind() == SUPERV::DataStreamParameter) {
495 SUPERVGUI_CanvasStreamPortIn* aInPort = (SUPERVGUI_CanvasStreamPortIn*)
496 (input ? thePort : myLinkBuilder->getStartPort());
497 SUPERVGUI_CanvasStreamPortOut* aOutPort = (SUPERVGUI_CanvasStreamPortOut*)
498 (input ? myLinkBuilder->getStartPort() : thePort);
499 // aLinkEngine = myMain->getDataflow()->StreamLink(aOutPort->getStreamEngine(),
500 // aInPort->getStreamEngine());
501 if (myMain->getDataflow()->IsStreamGraph()) {
502 SUPERV_StreamGraph aSGraph = myMain->getDataflow()->ToStreamGraph();
503 if (!SUPERV_isNull(aSGraph))
504 aLinkEngine = aSGraph->StreamLink(aOutPort->getStreamEngine(),
505 aInPort->getStreamEngine());
509 SUPERVGUI_CanvasPort* aInPort = (input ? thePort : myLinkBuilder->getStartPort());
510 SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
511 aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
513 if (SUPERV_isNull(aLinkEngine))
516 myLinkBuilder->setCoords(aLinkEngine.in());
518 delete myLinkBuilder;
521 SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(canvas(), myMain, aLinkEngine);
525 myIsLinkCreating = false;
527 // asv : 13.12.04 : introducing a check for ports' types compatibility (Bugs and Improvements p.1.16, PAL7380)
528 if ( !aLinkEngine->IsValid() ) {
529 const int id = QAD_MessageBox::warn2( this, tr( "TLT_INVALID_LINK" ), tr( "MSG_INVALID_LINK" ),
530 tr( "Keep" ), tr( "Remove" ), 0, 1, 0 );
531 if ( id == 1 ) { // Remove selected
532 aLink->remove(); // it did not live long...
538 void SUPERVGUI_CanvasView::cancelSketch()
541 delete myLinkBuilder;
545 myIsLinkCreating = false;
548 void SUPERVGUI_CanvasView::deletePoint()
550 if (myIsLinkCreating && myLinkBuilder) {
551 myLinkBuilder->removeLastPoint();
553 mySketchPopup->setItemEnabled(myDelPntItem, myLinkBuilder->getPointCount());
557 void SUPERVGUI_CanvasView::setOrthoMode()
559 bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
560 mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
564 void SUPERVGUI_CanvasView::addToStudy()
566 if (myMain->addStudy()) myMain->setAsFromStudy(true);
569 void SUPERVGUI_CanvasView::zoomIn()
577 void SUPERVGUI_CanvasView::zoomReset()
585 void SUPERVGUI_CanvasView::zoomOut()
593 void SUPERVGUI_CanvasView::fitAll()
596 QCanvasItemList l = canvas()->allItems();
597 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
598 QRect r = (*it)->boundingRect();
599 if (w < r.right()) w = r.right();
600 if (h < r.bottom()) h = r.bottom();
602 w += GRAPH_MARGIN; h += GRAPH_MARGIN;
603 double s = ((double)visibleWidth())/((double)w);
604 double s1 = ((double)visibleHeight())/((double)h);