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
12 #include "SUPERVGUI_CanvasView.h"
13 #include "SUPERVGUI_Main.h"
14 #include "SUPERVGUI_CanvasNode.h"
15 #include "SUPERVGUI_CanvasPort.h"
16 #include "SUPERVGUI_CanvasLink.h"
17 #include "SUPERVGUI_CanvasNodePrs.h"
18 #include "QAD_Config.h"
21 #include <qcolordialog.h>
27 const char* imageZoomCursor[] = {
32 "................................",
33 "................................",
34 ".#######........................",
35 "..aaaaaaa.......................",
36 "................................",
37 ".............#####..............",
38 "...........##.aaaa##............",
39 "..........#.aa.....a#...........",
40 ".........#.a.........#..........",
41 ".........#a..........#a.........",
42 "........#.a...........#.........",
43 "........#a............#a........",
44 "........#a............#a........",
45 "........#a............#a........",
46 "........#a............#a........",
47 ".........#...........#.a........",
48 ".........#a..........#a.........",
49 ".........##.........#.a.........",
50 "........#####.....##.a..........",
51 ".......###aaa#####.aa...........",
52 "......###aa...aaaaa.......#.....",
53 ".....###aa................#a....",
54 "....###aa.................#a....",
55 "...###aa...............#######..",
56 "....#aa.................aa#aaaa.",
57 ".....a....................#a....",
58 "..........................#a....",
59 "...........................a....",
60 "................................",
61 "................................",
62 "................................",
63 "................................"};
65 QPixmap zoomPix(imageZoomCursor);
66 QCursor zoom2Cursor(zoomPix);
68 #if QT_VERSION >= 0x030005
69 QCursor pan2Cursor(Qt::SizeAllCursor);
71 QCursor pan2Cursor(SizeAllCursor);
74 SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGUI_Main* theMain):
75 QCanvasView(theCanvas, theMain),
76 myMain(theMain), myCurrentItem(0), myHilighted(0), myLinkBuilder(0)
78 setName("CanvasView");
80 myIsPanBtnClicked = false;
81 myIsPanActivated = false;
82 myIsZoomActivated = false;
83 myIsLinkCreating = false;
88 myTimer = new QTimer(this);
89 connect(myTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
91 myPopup = new QPopupMenu(viewport());
93 if (myMain->isEditable()) {
94 myPopup->insertItem(tr("MSG_ADD_NODE"), myMain, SLOT(addNode()));
95 myPopup->insertItem(tr("MSG_INS_FILE"), myMain, SLOT(insertFile()));
96 myPopup->insertSeparator();
99 QPopupMenu* aViewPopup = new QPopupMenu(viewport());
100 // aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showFullGraph()));
101 aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showCanvas()));
102 aViewPopup->insertItem(tr("POP_CONTROLVIEW"), myMain, SLOT(showContolFlow()));
103 aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showTable()));
104 // aViewPopup->insertItem("Previous Full View", myMain, SLOT(showFullGraph()));
105 // aViewPopup->insertItem(tr("POP_CANVASVIEW"), myMain, SLOT(showCanvas()));
107 myPopup->insertItem(tr("POP_VIEW"), aViewPopup);
108 myPopup->insertSeparator();
110 QPopupMenu* aZoomPopup = new QPopupMenu(viewport());
111 aZoomPopup->insertItem("200%", this, SLOT(zoomIn()));
112 aZoomPopup->insertItem("100%", this, SLOT(zoomReset()));
113 aZoomPopup->insertItem("50%", this, SLOT(zoomOut()));
114 aZoomPopup->insertSeparator();
115 aZoomPopup->insertItem("Fit All", this, SLOT(fitAll()));
117 myPopup->insertItem("Zoom", aZoomPopup);
118 myPopup->insertSeparator();
120 myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), this, SLOT(addToStudy()));
121 myPopup->insertItem(tr("MSG_CHANGE_INFO"), myMain, SLOT(changeInformation()));
122 myPopup->insertSeparator();
124 myPopup->insertItem(tr("MSG_COPY_DATAFLOW"), myMain, SLOT(copy()));
125 myPopup->insertItem(tr("MSG_FILTER_NOTIFY"), myMain, SLOT(filterNotification()));
127 myPopup->insertSeparator();
128 myPopup->insertItem(tr("MSG_CHANGE_BACKGROUND"), this, SLOT(changeBackground()));
130 viewport()->setMouseTracking(true);
132 //create sketching popup menu
133 mySketchPopup = new QPopupMenu(viewport());
134 mySketchPopup->setCheckable(true);
135 myDelPntItem = mySketchPopup->insertItem(tr("MSG_DEL_LAST_PNT"), this, SLOT(deletePoint()));
136 mySketchPopup->insertItem(tr("MSG_DEL_LINK"), this, SLOT(cancelSketch()));
137 myOrtoItem = mySketchPopup->insertItem(tr("MSG_ORTHO_LINE"), this, SLOT(setOrthoMode()));
141 SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
145 void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
147 // MESSAGE("===> SUPERVGUI_CanvasView::contentsMousePressEvent(...) ");
148 myPoint = inverseWorldMatrix().map(theEvent->pos());
149 myGlobalPoint = theEvent->globalPos();
152 // compute collision rectangle
153 QRect aSel(myPoint.x()-MARGIN, myPoint.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
155 if (((theEvent->button() == Qt::MidButton) &&
156 (theEvent->state() == Qt::ControlButton)) ||
158 myIsPanActivated = true;
160 setCursor(pan2Cursor);
164 if (((theEvent->button() == Qt::LeftButton) &&
165 (theEvent->state() == Qt::ControlButton)) ||
167 myIsZoomActivated = true;
169 setCursor(zoom2Cursor);
173 if ( theEvent->button() == Qt::RightButton) {
174 if (myIsLinkCreating) {
175 myMain->showPopup(mySketchPopup, theEvent);
179 QCanvasItemList l = canvas()->collisions(aSel);
180 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
181 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
182 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
183 QObject* anObj = aNodePrs->getObject(myPoint);
184 if (anObj->inherits("SUPERVGUI_CanvasNode")) {
185 myMain->showPopup(((SUPERVGUI_CanvasNode*)anObj)->getPopupMenu(viewport()),
189 else if (anObj->inherits("SUPERVGUI_CanvasPort")) {
190 myMain->showPopup(((SUPERVGUI_CanvasPort*)anObj)->getPopupMenu(viewport()),
195 if (myMain->isEditable() && !myMain->getCanvas()->isControlView()) {
196 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
197 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
198 aPrs->getLink()->setSelectedObject(aPrs, myPoint);
199 myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
202 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
203 SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
204 aPrs->getLink()->setSelectedObject(aPrs, myPoint);
205 myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
211 myPopup->setItemEnabled(myAddStudyItem, !myMain->isFromStudy());
212 myMain->showPopup(myPopup, theEvent);
216 if (theEvent->button() == Qt::LeftButton) {
217 QCanvasItemList l = canvas()->collisions(myPoint);
218 if (myIsLinkCreating) {
219 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
220 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
221 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
222 QObject* anObj = aNodePrs->getObject(myPoint);
223 if (anObj->inherits("SUPERVGUI_CanvasPort")) {
224 endSketch((SUPERVGUI_CanvasPort*)anObj);
229 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
230 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
234 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
235 SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
236 QObject* anObj = aHookPrs->getObject();
237 if (anObj->inherits("SUPERVGUI_CanvasPort")) {
238 endSketch((SUPERVGUI_CanvasPort*)anObj);
244 myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
246 mySketchPopup->setItemEnabled(myDelPntItem, true);
251 // if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
252 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
253 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
255 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
256 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
259 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
260 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
261 if (aPrs->getIndex() > 0) {
263 aPrs->setMoving(true);
274 void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
279 QPoint p = inverseWorldMatrix().map(theEvent->pos());
280 QPoint g = theEvent->globalPos();
282 if (myTimer->isActive()) myTimer->stop();
284 if (myIsLinkCreating && myLinkBuilder) {
285 myLinkBuilder->setFloatPoint(p);
291 double cx = myCurrentItem->x() - myPoint.x();
292 double cy = myCurrentItem->y() - myPoint.y();
293 if (p.x()+cx < 0) p.setX(-(int)cx);
294 if (p.y()+cy < 0) p.setY(-(int)cy);
295 myCurrentItem->moveBy(p.x() - myPoint.x(),
296 p.y() - myPoint.y());
300 // scroll contents if mouse is outside
301 QRect r(contentsX(), contentsY(), visibleWidth(), visibleHeight());
302 if (!r.contains(theEvent->pos())) {
304 if (theEvent->pos().x() < r.left()) dx = theEvent->pos().x() - r.left();
305 if (theEvent->pos().x() > r.right()) dx = theEvent->pos().x() - r.right();
306 if (theEvent->pos().y() < r.top()) dy = theEvent->pos().y() - r.top();
307 if (theEvent->pos().y() > r.bottom()) dy = theEvent->pos().y() - r.bottom();
309 // start timer to scroll in silent mode
310 myDX = dx; myDY = dy;
317 if (myIsPanActivated) {
319 scrollBy(myGlobalPoint.x() - g.x(),
320 myGlobalPoint.y() - g.y());
326 if (myIsZoomActivated) {
328 double dx = g.x() - myGlobalPoint.x();
329 double s = 1. + fabs(dx)/10.;
330 if (dx < 0) s = 1./s;
332 QWMatrix m = worldMatrix();
341 if (!myIsLinkCreating && myMain->isEditable() &&
342 !myMain->getCanvas()->isControlView()) {
343 // compute collision rectangle
344 QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
345 QCanvasItemList l = canvas()->collisions(aSel);
346 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
347 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
348 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
349 setHilighted(aPrs->getLink());
353 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
354 SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
355 setHilighted(aPrs->getLink());
366 void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent)
368 // MESSAGE("===> SUPERVGUI_CanvasView::contentsMouseReleaseEvent(...) ");
369 if (myTimer->isActive()) myTimer->stop();
372 if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
373 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(0);
374 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(false);
377 if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
378 ((SUPERVGUI_CanvasPointPrs*)myCurrentItem)->setMoving(false);
383 if (myIsPanActivated) {
384 myIsPanActivated = false;
385 myIsPanBtnClicked = false;
389 if (myIsZoomActivated) {
390 myIsZoomActivated = false;
395 void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
397 // MESSAGE("===> SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(...) ");
398 QPoint p = inverseWorldMatrix().map(theEvent->pos());
400 // compute collision rectangle
401 QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
403 if (theEvent->button() == Qt::LeftButton) {
404 QCanvasItemList l = canvas()->collisions(p);
405 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
406 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
407 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
408 SUPERVGUI_CanvasNode* aNode = aNodePrs->getNode();
409 if (aNode->getEngine()->IsMacro() && !myIsLinkCreating) {
410 myMain->openSubGraph(aNode->getEngine(), true);
418 void SUPERVGUI_CanvasView::onDestroyed(QObject* theObject)
420 if (theObject == myHilighted)
424 void SUPERVGUI_CanvasView::setHilighted(SUPERVGUI_CanvasLink* theLink)
426 if (theLink == myHilighted) return;
428 disconnect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
429 myHilighted->setHilighted(false);
433 myHilighted = theLink;
434 myHilighted->setHilighted(true);
435 connect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
439 void SUPERVGUI_CanvasView::onTimeout()
442 scrollBy(myDX, myDY);
445 inverseWorldMatrix().map((double)myDX, (double)myDY, &cx, &cy);
446 if (myCurrentItem->x()+cx < 0) cx = -myCurrentItem->x();
447 if (myCurrentItem->y()+cy < 0) cy = -myCurrentItem->y();
448 myCurrentItem->moveBy(cx, cy);
449 myPoint.setX(myPoint.x()+(int)cx);
450 myPoint.setY(myPoint.y()+(int)cy);
455 void SUPERVGUI_CanvasView::changeBackground()
457 QColor aColor = QColorDialog::getColor(canvas()->backgroundColor(), this );
458 if ( aColor.isValid() ) {
459 canvas()->setBackgroundColor(aColor);
460 setPaletteBackgroundColor(aColor.light(120));
464 void SUPERVGUI_CanvasView::ActivatePanning()
466 myIsPanBtnClicked = true;
469 void SUPERVGUI_CanvasView::ResetView()
476 void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
478 if (myIsLinkCreating) return;
480 myIsLinkCreating = true;
481 myLinkBuilder = new SUPERVGUI_CanvasLinkBuilder(canvas(), myMain, thePort);
482 mySketchPopup->setItemEnabled(myDelPntItem, false);
485 void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
487 // MESSAGE("===> SUPERVGUI_CanvasView::endSketch(" << thePort->name() << ")");
488 if (!myIsLinkCreating) return;
490 if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
491 bool input = thePort->getEngine()->IsInput();
492 SUPERV_Link aLinkEngine;
493 if (thePort->getEngine()->Kind() == SUPERV::DataStreamParameter) {
494 SUPERVGUI_CanvasStreamPortIn* aInPort = (SUPERVGUI_CanvasStreamPortIn*)
495 (input ? thePort : myLinkBuilder->getStartPort());
496 SUPERVGUI_CanvasStreamPortOut* aOutPort = (SUPERVGUI_CanvasStreamPortOut*)
497 (input ? myLinkBuilder->getStartPort() : thePort);
498 // aLinkEngine = myMain->getDataflow()->StreamLink(aOutPort->getStreamEngine(),
499 // aInPort->getStreamEngine());
500 if (myMain->getDataflow()->IsStreamGraph()) {
501 SUPERV_StreamGraph aSGraph = myMain->getDataflow()->ToStreamGraph();
502 if (!SUPERV_isNull(aSGraph))
503 aLinkEngine = aSGraph->StreamLink(aOutPort->getStreamEngine(),
504 aInPort->getStreamEngine());
508 SUPERVGUI_CanvasPort* aInPort = (input ? thePort : myLinkBuilder->getStartPort());
509 SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
510 aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
512 if (SUPERV_isNull(aLinkEngine)) return;
514 myLinkBuilder->setCoords(aLinkEngine.in());
516 delete myLinkBuilder;
519 SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(canvas(), myMain, aLinkEngine);
523 myIsLinkCreating = false;
527 void SUPERVGUI_CanvasView::cancelSketch()
530 delete myLinkBuilder;
534 myIsLinkCreating = false;
537 void SUPERVGUI_CanvasView::deletePoint()
539 if (myIsLinkCreating && myLinkBuilder) {
540 myLinkBuilder->removeLastPoint();
542 mySketchPopup->setItemEnabled(myDelPntItem, myLinkBuilder->getPointCount());
546 void SUPERVGUI_CanvasView::setOrthoMode()
548 bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
549 mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
553 void SUPERVGUI_CanvasView::addToStudy()
555 if (myMain->addStudy()) myMain->setAsFromStudy(true);
558 void SUPERVGUI_CanvasView::zoomIn()
566 void SUPERVGUI_CanvasView::zoomReset()
574 void SUPERVGUI_CanvasView::zoomOut()
582 void SUPERVGUI_CanvasView::fitAll()
585 QCanvasItemList l = canvas()->allItems();
586 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
587 QRect r = (*it)->boundingRect();
588 if (w < r.right()) w = r.right();
589 if (h < r.bottom()) h = r.bottom();
591 w += GRAPH_MARGIN; h += GRAPH_MARGIN;
592 double s = ((double)visibleWidth())/((double)w);
593 double s1 = ((double)visibleHeight())/((double)h);