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 myIsPanActivated = false;
81 myIsZoomActivated = false;
82 myIsLinkCreating = false;
87 myTimer = new QTimer(this);
88 connect(myTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
90 myPopup = new QPopupMenu(viewport());
92 if (myMain->isEditable()) {
93 myPopup->insertItem(tr("MSG_ADD_NODE"), myMain, SLOT(addNode()));
94 myPopup->insertItem(tr("MSG_INS_FILE"), myMain, SLOT(insertFile()));
95 myPopup->insertSeparator();
98 QPopupMenu* aViewPopup = new QPopupMenu(viewport());
99 // aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showFullGraph()));
100 aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showCanvas()));
101 aViewPopup->insertItem(tr("POP_CONTROLVIEW"), myMain, SLOT(showContolFlow()));
102 aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showTable()));
103 // aViewPopup->insertItem("Previous Full View", myMain, SLOT(showFullGraph()));
104 // aViewPopup->insertItem(tr("POP_CANVASVIEW"), myMain, SLOT(showCanvas()));
106 myPopup->insertItem(tr("POP_VIEW"), aViewPopup);
107 myPopup->insertSeparator();
109 QPopupMenu* aZoomPopup = new QPopupMenu(viewport());
110 aZoomPopup->insertItem("200%", this, SLOT(zoomIn()));
111 aZoomPopup->insertItem("100%", this, SLOT(zoomReset()));
112 aZoomPopup->insertItem("50%", this, SLOT(zoomOut()));
113 aZoomPopup->insertSeparator();
114 aZoomPopup->insertItem("Fit All", this, SLOT(fitAll()));
116 myPopup->insertItem("Zoom", aZoomPopup);
117 myPopup->insertSeparator();
119 myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), this, SLOT(addToStudy()));
120 myPopup->insertItem(tr("MSG_CHANGE_INFO"), myMain, SLOT(changeInformation()));
121 myPopup->insertSeparator();
123 myPopup->insertItem(tr("MSG_COPY_DATAFLOW"), myMain, SLOT(copy()));
124 myPopup->insertItem(tr("MSG_FILTER_NOTIFY"), myMain, SLOT(filterNotification()));
126 myPopup->insertSeparator();
127 myPopup->insertItem(tr("MSG_CHANGE_BACKGROUND"), this, SLOT(changeBackground()));
129 viewport()->setMouseTracking(true);
131 //create sketching popup menu
132 mySketchPopup = new QPopupMenu(viewport());
133 mySketchPopup->setCheckable(true);
134 myDelPntItem = mySketchPopup->insertItem(tr("MSG_DEL_LAST_PNT"), this, SLOT(deletePoint()));
135 mySketchPopup->insertItem(tr("MSG_DEL_LINK"), this, SLOT(cancelSketch()));
136 myOrtoItem = mySketchPopup->insertItem(tr("MSG_ORTHO_LINE"), this, SLOT(setOrthoMode()));
140 SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
144 void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
146 // cout << "===> SUPERVGUI_CanvasView::contentsMousePressEvent(...) " << endl;
147 myPoint = inverseWorldMatrix().map(theEvent->pos());
148 myGlobalPoint = theEvent->globalPos();
151 // compute collision rectangle
152 QRect aSel(myPoint.x()-MARGIN, myPoint.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
154 if (((theEvent->button() == Qt::MidButton) &&
155 (theEvent->state() == Qt::ControlButton)) ||
157 myIsPanActivated = true;
159 setCursor(pan2Cursor);
163 if (((theEvent->button() == Qt::LeftButton) &&
164 (theEvent->state() == Qt::ControlButton)) ||
166 myIsZoomActivated = true;
168 setCursor(zoom2Cursor);
172 if ( theEvent->button() == Qt::RightButton) {
173 if (myIsLinkCreating) {
174 myMain->showPopup(mySketchPopup, theEvent);
178 QCanvasItemList l = canvas()->collisions(aSel);
179 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
180 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
181 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
182 QObject* anObj = aNodePrs->getObject(myPoint);
183 if (anObj->inherits("SUPERVGUI_CanvasNode")) {
184 myMain->showPopup(((SUPERVGUI_CanvasNode*)anObj)->getPopupMenu(viewport()),
188 else if (anObj->inherits("SUPERVGUI_CanvasPort")) {
189 myMain->showPopup(((SUPERVGUI_CanvasPort*)anObj)->getPopupMenu(viewport()),
194 if (myMain->isEditable() && !myMain->getCanvas()->isControlView()) {
195 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
196 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
197 aPrs->getLink()->setSelectedObject(aPrs, myPoint);
198 myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
201 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
202 SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
203 aPrs->getLink()->setSelectedObject(aPrs, myPoint);
204 myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
210 myPopup->setItemEnabled(myAddStudyItem, !myMain->isFromStudy());
211 myMain->showPopup(myPopup, theEvent);
215 if (theEvent->button() == Qt::LeftButton) {
216 QCanvasItemList l = canvas()->collisions(myPoint);
217 if (myIsLinkCreating) {
218 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
219 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
220 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
221 QObject* anObj = aNodePrs->getObject(myPoint);
222 if (anObj->inherits("SUPERVGUI_CanvasPort")) {
223 endSketch((SUPERVGUI_CanvasPort*)anObj);
228 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
229 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
233 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
234 SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
235 QObject* anObj = aHookPrs->getObject();
236 if (anObj->inherits("SUPERVGUI_CanvasPort")) {
237 endSketch((SUPERVGUI_CanvasPort*)anObj);
243 myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
245 mySketchPopup->setItemEnabled(myDelPntItem, true);
250 // if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
251 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
252 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
254 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
255 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
258 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
259 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
260 if (aPrs->getIndex() > 0) {
262 aPrs->setMoving(true);
273 void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
278 QPoint p = inverseWorldMatrix().map(theEvent->pos());
279 QPoint g = theEvent->globalPos();
281 if (myTimer->isActive()) myTimer->stop();
283 if (myIsLinkCreating && myLinkBuilder) {
284 myLinkBuilder->setFloatPoint(p);
290 double cx = myCurrentItem->x() - myPoint.x();
291 double cy = myCurrentItem->y() - myPoint.y();
292 if (p.x()+cx < 0) p.setX(-(int)cx);
293 if (p.y()+cy < 0) p.setY(-(int)cy);
294 myCurrentItem->moveBy(p.x() - myPoint.x(),
295 p.y() - myPoint.y());
299 // scroll contents if mouse is outside
300 QRect r(contentsX(), contentsY(), visibleWidth(), visibleHeight());
301 if (!r.contains(theEvent->pos())) {
303 if (theEvent->pos().x() < r.left()) dx = theEvent->pos().x() - r.left();
304 if (theEvent->pos().x() > r.right()) dx = theEvent->pos().x() - r.right();
305 if (theEvent->pos().y() < r.top()) dy = theEvent->pos().y() - r.top();
306 if (theEvent->pos().y() > r.bottom()) dy = theEvent->pos().y() - r.bottom();
308 // start timer to scroll in silent mode
309 myDX = dx; myDY = dy;
316 if (myIsPanActivated) {
318 scrollBy(myGlobalPoint.x() - g.x(),
319 myGlobalPoint.y() - g.y());
325 if (myIsZoomActivated) {
327 double dx = g.x() - myGlobalPoint.x();
328 double s = 1. + fabs(dx)/10.;
329 if (dx < 0) s = 1./s;
331 QWMatrix m = worldMatrix();
340 if (!myIsLinkCreating && myMain->isEditable() &&
341 !myMain->getCanvas()->isControlView()) {
342 // compute collision rectangle
343 QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
344 QCanvasItemList l = canvas()->collisions(aSel);
345 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
346 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
347 SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
348 setHilighted(aPrs->getLink());
352 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
353 SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
354 setHilighted(aPrs->getLink());
365 void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent)
367 // cout << "===> SUPERVGUI_CanvasView::contentsMouseReleaseEvent(...) " << endl;
368 if (myTimer->isActive()) myTimer->stop();
371 if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
372 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(0);
373 ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(false);
376 if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
377 ((SUPERVGUI_CanvasPointPrs*)myCurrentItem)->setMoving(false);
382 if (myIsPanActivated) {
383 myIsPanActivated = false;
387 if (myIsZoomActivated) {
388 myIsZoomActivated = false;
393 void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
395 // cout << "===> SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(...) " << endl;
396 QPoint p = inverseWorldMatrix().map(theEvent->pos());
398 // compute collision rectangle
399 QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
401 if (theEvent->button() == Qt::LeftButton) {
402 QCanvasItemList l = canvas()->collisions(p);
403 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
404 if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
405 SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
406 SUPERVGUI_CanvasNode* aNode = aNodePrs->getNode();
407 if (aNode->getEngine()->IsMacro() && !myIsLinkCreating) {
408 myMain->openSubGraph(aNode->getEngine(), true);
416 void SUPERVGUI_CanvasView::onDestroyed(QObject* theObject)
418 if (theObject == myHilighted)
422 void SUPERVGUI_CanvasView::setHilighted(SUPERVGUI_CanvasLink* theLink)
424 if (theLink == myHilighted) return;
426 disconnect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
427 myHilighted->setHilighted(false);
431 myHilighted = theLink;
432 myHilighted->setHilighted(true);
433 connect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
437 void SUPERVGUI_CanvasView::onTimeout()
440 scrollBy(myDX, myDY);
443 inverseWorldMatrix().map((double)myDX, (double)myDY, &cx, &cy);
444 if (myCurrentItem->x()+cx < 0) cx = -myCurrentItem->x();
445 if (myCurrentItem->y()+cy < 0) cy = -myCurrentItem->y();
446 myCurrentItem->moveBy(cx, cy);
447 myPoint.setX(myPoint.x()+(int)cx);
448 myPoint.setY(myPoint.y()+(int)cy);
453 void SUPERVGUI_CanvasView::changeBackground()
455 QColor aColor = QColorDialog::getColor(canvas()->backgroundColor(), this );
456 if ( aColor.isValid() ) {
457 canvas()->setBackgroundColor(aColor);
458 setPaletteBackgroundColor(aColor.light(120));
462 void SUPERVGUI_CanvasView::ActivatePanning()
464 myIsPanActivated = true;
467 void SUPERVGUI_CanvasView::ResetView()
474 void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
476 if (myIsLinkCreating) return;
478 myIsLinkCreating = true;
479 myLinkBuilder = new SUPERVGUI_CanvasLinkBuilder(canvas(), myMain, thePort);
480 mySketchPopup->setItemEnabled(myDelPntItem, false);
483 void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
485 // cout << "===> SUPERVGUI_CanvasView::endSketch(" << thePort->name() << ")" << endl;
486 if (!myIsLinkCreating) return;
488 if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
489 bool input = thePort->getEngine()->IsInput();
490 SUPERV_Link aLinkEngine;
491 if (thePort->getEngine()->Kind() == SUPERV::DataStreamParameter) {
492 SUPERVGUI_CanvasStreamPortIn* aInPort = (SUPERVGUI_CanvasStreamPortIn*)
493 (input ? thePort : myLinkBuilder->getStartPort());
494 SUPERVGUI_CanvasStreamPortOut* aOutPort = (SUPERVGUI_CanvasStreamPortOut*)
495 (input ? myLinkBuilder->getStartPort() : thePort);
496 // aLinkEngine = myMain->getDataflow()->StreamLink(aOutPort->getStreamEngine(),
497 // aInPort->getStreamEngine());
498 if (myMain->getDataflow()->IsStreamGraph()) {
499 SUPERV_StreamGraph aSGraph = myMain->getDataflow()->ToStreamGraph();
500 if (!SUPERV_isNull(aSGraph))
501 aLinkEngine = aSGraph->StreamLink(aOutPort->getStreamEngine(),
502 aInPort->getStreamEngine());
506 SUPERVGUI_CanvasPort* aInPort = (input ? thePort : myLinkBuilder->getStartPort());
507 SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
508 aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
510 if (SUPERV_isNull(aLinkEngine)) return;
512 myLinkBuilder->setCoords(aLinkEngine.in());
514 delete myLinkBuilder;
517 SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(canvas(), myMain, aLinkEngine);
521 myIsLinkCreating = false;
525 void SUPERVGUI_CanvasView::cancelSketch()
528 delete myLinkBuilder;
532 myIsLinkCreating = false;
535 void SUPERVGUI_CanvasView::deletePoint()
537 if (myIsLinkCreating && myLinkBuilder) {
538 myLinkBuilder->removeLastPoint();
540 mySketchPopup->setItemEnabled(myDelPntItem, myLinkBuilder->getPointCount());
544 void SUPERVGUI_CanvasView::setOrthoMode()
546 bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
547 mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
551 void SUPERVGUI_CanvasView::addToStudy()
553 if (myMain->addStudy()) myMain->setAsFromStudy(true);
556 void SUPERVGUI_CanvasView::zoomIn()
564 void SUPERVGUI_CanvasView::zoomReset()
572 void SUPERVGUI_CanvasView::zoomOut()
580 void SUPERVGUI_CanvasView::fitAll()
583 QCanvasItemList l = canvas()->allItems();
584 for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
585 QRect r = (*it)->boundingRect();
586 if (w < r.right()) w = r.right();
587 if (h < r.bottom()) h = r.bottom();
589 w += GRAPH_MARGIN; h += GRAPH_MARGIN;
590 double s = ((double)visibleWidth())/((double)w);
591 double s1 = ((double)visibleHeight())/((double)h);