]> SALOME platform Git repositories - modules/superv.git/blob - src/SUPERVGUI/SUPERVGUI_Graph.cxx
Salome HOME
NRI : Merge from V1_2.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Graph.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SUPERVGUI_Graph.cxx
25 //  Author : Francis KLOSS
26 //  Module : SUPERV
27
28 using namespace std;
29 #include "SUPERVGUI_Def.h"
30 #include "SUPERVGUI_Graph.h"
31 #include "SUPERVGUI_Main.h"
32 #include "SUPERVGUI_ComputeNode.h"
33 #include "SUPERVGUI_ControlNode.h"
34
35
36 //#define CHECKTIME
37
38 #ifdef CHECKTIME
39 #include <sys/timeb.h>
40 #endif
41
42
43 #define UPDATECONTROLNODES(NodesName)  \
44     n = nodes->NodesName.length(); \
45     for (int i=0; i<n; i++) { \
46       SUPERV_CNode aCNode = SUPERV::CNode::_narrow(nodes->NodesName[i]); \
47       SUPERV_CNode aCNodeEnd = SUPERV::CNode::_narrow(nodes->NodesName[i]->Coupled()); \
48       ihmNode = (SUPERVGUI_Node *)child(aCNode->Name(), "SUPERVGUI_Node"); \
49       if (ihmNode == NULL) { \
50         main->addControlNode(aCNode, aCNodeEnd, false); \
51       } else { \
52         ResizeGraph(ihmNode, aCNode->X(), aCNode->Y()); \
53         moveChild(ihmNode, aCNode->X(), aCNode->Y());  \
54         ihmList->removeRef(ihmNode); \
55         ihmNode->sync(); \
56         aEndNodePrs = (SUPERVGUI_EndControlNode*)child(aCNodeEnd->Name(), "SUPERVGUI_EndControlNode"); \
57         ResizeGraph(aEndNodePrs, aCNodeEnd->X(), aCNodeEnd->Y()); \
58         moveChild(aEndNodePrs, aCNodeEnd->X(), aCNodeEnd->Y());  \
59         ihmList->removeRef(aEndNodePrs); \
60         aEndNodePrs->sync(); \
61       } \
62     }
63
64
65 #define UPDATENODES(NodesName, FuncName)   \
66     n = nodes->NodesName.length(); \
67     for (int i=0; i<n; i++) { \
68       SUPERV_CNode aCNode = SUPERV::CNode::_narrow(nodes->NodesName[i]); \
69       ihmNode = (SUPERVGUI_Node *)child(aCNode->Name(), "SUPERVGUI_Node"); \
70       if (ihmNode == NULL) { \
71           main->FuncName(aCNode); \
72       } else { \
73         ResizeGraph(ihmNode, aCNode->X(), aCNode->Y()); \
74         moveChild(ihmNode, aCNode->X(), aCNode->Y()); \
75         ihmList->removeRef(ihmNode); \
76         ihmNode->sync(); \
77       } \
78     }
79
80
81 SUPERVGUI_Graph::SUPERVGUI_Graph(SUPERVGUI_Main* m):
82     SUPERVGUI_View(m),
83     myNewLink(0)
84 {
85   Trace("SUPERVGUI_Graph::SUPERVGUI_Graph");
86   myIsControlView = false;
87   myLinksList.setAutoDelete(true);
88   viewport()->setMouseTracking(true);
89
90   resizeContents(GRAPH_WIDTH, GRAPH_HEIGHT);
91   
92   if (SUPERV_isNull(main->getDataflow())) return;
93   
94  
95   //create sketching popup menu
96   mySketchPopup = new QPopupMenu(viewport());
97   if (!mySketchPopup->isCheckable())
98     mySketchPopup->setCheckable(true);
99   myDelPntItem = mySketchPopup->insertItem(tr("MSG_DEL_LAST_PNT"), this, SLOT(delLastPnt()));
100   mySketchPopup->insertItem(tr("MSG_DEL_LINK"), this, SLOT(delCreatingLink()));
101   myOrtoItem = mySketchPopup->insertItem(tr("MSG_ORTHO_LINE"), this, SLOT(setOrtho()));
102
103   //create link popup menu
104   myLinkPopup = new QPopupMenu(viewport());
105   myDelLinkItem = myLinkPopup->insertItem(tr("MSG_DELLINK"), this, SLOT(deleteLink()));
106   myAddLinkPntItem = myLinkPopup->insertItem(tr("MSG_ADD_POINT"), this, SLOT(addPoint()));
107   myDelLinkPntItem = myLinkPopup->insertItem(tr("MSG_DEL_POINT"), this, SLOT(deletePoint()));
108 }
109
110
111
112 SUPERVGUI_Graph::~SUPERVGUI_Graph() {
113 }
114
115 /** 
116  * Synchronizes Graph presentation with internal graph structure
117  */
118 void SUPERVGUI_Graph::sync() {
119     if (SUPERV_isNull(main->getDataflow())) return;
120       
121     myLinksList.clear();
122
123     SUPERVGUI_Node* ihmNode;
124     QObjectList* ihmList = queryList("SUPERVGUI_Node");
125     SUPERV_Nodes nodes = main->getDataflow()->Nodes();
126
127     MESSAGE("CNodes="<<nodes->CNodes.length());
128     MESSAGE("FNodes="<<nodes->FNodes.length());
129     MESSAGE("INodes="<<nodes->INodes.length());
130     MESSAGE("GNodes="<<nodes->GNodes.length());
131     MESSAGE("LNodes="<<nodes->LNodes.length());
132     MESSAGE("SNodes="<<nodes->SNodes.length());
133
134     int n;
135     UPDATENODES(CNodes, addComputeNode);
136     UPDATENODES(FNodes, addComputeNode);
137     UPDATENODES(INodes, addComputeNode);
138     UPDATENODES(GNodes, addGOTONode);
139
140     SUPERVGUI_EndControlNode* aEndNodePrs;
141     UPDATECONTROLNODES(LNodes);    
142     UPDATECONTROLNODES(SNodes);
143
144     QObjectListIt i(*ihmList);
145     while ((ihmNode=(SUPERVGUI_Node*)i.current()) != 0) {
146       ++i;
147       ihmNode->close(true);
148     }
149     delete ihmList;
150
151     ihmList = queryList("SUPERVGUI_GraphNode");
152     i=(*ihmList);
153     SUPERVGUI_GraphNode* aGraphNode;
154     while ((aGraphNode=(SUPERVGUI_GraphNode*)i.current()) != 0) {
155       ++i;
156       aGraphNode->updateLinksPrs();
157     }
158     delete ihmList;
159
160     draw();
161 }
162
163
164 /**
165  * Reimplemented for repainting links
166  */
167 bool SUPERVGUI_Graph::eventFilter(QObject* object, QEvent* event) {
168   if (event->type() == QEvent::Paint) {
169     draw();
170     return true;
171   }
172   return QScrollView::eventFilter(object, event);
173 }
174
175
176 /**
177  * Clears content of Graph (links)
178  */
179 void SUPERVGUI_Graph::clearView() {
180   QPainter aPainter(viewport());
181   aPainter.eraseRect(viewport()->rect());    
182 }
183
184
185 /**
186  * Draws links using off screen buffer
187  */
188 void SUPERVGUI_Graph::draw() {
189 #ifdef CHECKTIME
190   struct timeb aTm1;
191   ftime(&aTm1);
192 #endif
193   if (myLinksList.count() == 0) {
194     return;
195   }
196   int aWidth = viewport()->width();
197   int aHeight = viewport()->height();
198   QPixmap aPixmap(aWidth, aHeight);
199   aPixmap.setOptimization(QPixmap::BestOptim);
200   aPixmap.fill(viewport()->paletteBackgroundColor());
201   
202   QPainter aPainter(&aPixmap);
203   QPoint aPos = viewportToContents(viewport()->pos());
204
205   if (myIsControlView) {
206     SUPERVGUI_CtrlLink* aLink;
207     QMap<QString, SUPERVGUI_CtrlLink>::Iterator it;    
208     for ( it = myCtrlLinks.begin(); it != myCtrlLinks.end(); ++it ) {
209       it.data().paint(&aPainter, false);
210     }
211   } else {
212     SUPERVGUI_Link* aLink;
213     for (aLink = myLinksList.first(); aLink; aLink = myLinksList.next()) {
214       aLink->isInRect(aPos.x(), aPos.y(), aWidth, aHeight);
215       if (aLink->isInRect(aPos.x(), aPos.y(), aWidth, aHeight)) {
216         aLink->paint(&aPainter, false);
217       }
218     }    
219   }
220   bitBlt(viewport(), 0, 0, 
221              &aPixmap, 0, 0, aWidth, aHeight, 
222              Qt::CopyROP, true);
223   
224   if (myNewLink) {
225     myNewLink->repaintSketch();
226   }
227 #ifdef CHECKTIME
228   struct timeb aTm2;
229   ftime(&aTm2);
230   ulong aTm = 1000*(aTm2.time-aTm1.time)+(aTm2.millitm-aTm1.millitm);
231   cout<<"### Time="<<aTm<<endl;
232 #endif
233 }
234
235
236 void SUPERVGUI_Graph::contentsMousePressEvent(QMouseEvent* e) {
237   Trace("SUPERVGUI_Graph::contentsMousePressEvent");
238   if ( e->button() == Qt::RightButton) {
239     if (myNewLink) {
240       main->showPopup(mySketchPopup, e);
241     } else {
242       SUPERVGUI_Link* aLink = SUPERVGUI_Link::getSelectedLink();
243       if (aLink && main->isEditable()) {
244         myLinkPopup->setItemEnabled(myAddLinkPntItem, 
245                                     !aLink->haveSelectedPoint());
246         myLinkPopup->setItemEnabled(myDelLinkPntItem, 
247                                     aLink->haveSelectedPoint());
248
249
250         if (!aLink->isESInputPort()) {
251           SUPERV::KindOfPort aOutType = aLink->getOutputPort()->getPort()->Kind();
252           SUPERV::KindOfPort aInType = aLink->getInputPort()->getPort()->Kind();
253           myLinkPopup->setItemEnabled(myDelLinkItem,
254                                       ((aOutType != SUPERV::LoopParameter) 
255                                        && 
256                                        (aInType != SUPERV::LoopParameter)));
257         }
258         
259         myMousePos = e->pos();
260         mySelectedLink = aLink;
261         mySelectedPoint = mySelectedLink->getSelectedPoint();
262         main->showPopup(myLinkPopup, e);
263       } else {
264         mySelectedLink = 0;
265         main->showPopup(myPopup, e);
266       }
267     }
268   } 
269   emit mousePressed(e);
270     
271   SUPERVGUI_View::contentsMousePressEvent(e);  
272 }
273
274
275 void SUPERVGUI_Graph::contentsMouseReleaseEvent(QMouseEvent* e) {
276   Trace("SUPERVGUI_Graph::contentsMouseReleaseEvent");
277   if (myNewLink && (e->button() == Qt::LeftButton)) {
278     myNewLink->addTmpPoint(e->pos());
279     mySketchPopup->setItemEnabled(myDelPntItem, true);      
280   } 
281   emit mouseReleased(e);
282   SUPERVGUI_View::contentsMouseReleaseEvent(e);
283 }
284
285
286 void SUPERVGUI_Graph::contentsMouseMoveEvent(QMouseEvent* e) {
287   Trace("SUPERVGUI_Graph::contentsMouseMoveEvent");
288   if (myNewLink) {
289     myNewLink->drawTo(e->pos());
290   } 
291   emit mouseMoved(e);
292   SUPERVGUI_View::contentsMouseMoveEvent(e);
293 }
294
295
296 void SUPERVGUI_Graph::addPoint() {
297   mySelectedLink->addPoint(myMousePos.x(), myMousePos.y());
298 }
299
300
301 void SUPERVGUI_Graph::deletePoint() {
302   mySelectedLink->removePoint(mySelectedPoint);
303 }
304
305
306 void SUPERVGUI_Graph::deleteLink() {
307   QString aName;
308   if (mySelectedLink->isESInputPort())
309     aName = mySelectedLink->getInputPortES()->getPort()->Name();
310   else
311     aName = mySelectedLink->getInputPort()->getPort()->Name();
312
313   if (aName != "Default") {
314     deleteLink(mySelectedLink);
315     mySelectedLink = 0;
316     repaintContents();
317   }
318 }
319
320
321 void SUPERVGUI_Graph::deleteLink(SUPERVGUI_Link* theLink) {
322   theLink->destroyEngine();
323   myLinksList.removeRef(theLink);
324   if (myLinksList.count() == 0) clearView();
325 }
326
327
328 void SUPERVGUI_Graph::setAsFromStudy(bool theToStudy) {
329   SUPERVGUI_View::setAsFromStudy(theToStudy);
330   if (theToStudy) return;
331
332   SUPERVGUI_PortOut* aPortOut;
333   QObjectList* aPortsList = queryList("SUPERVGUI_PortOut");
334   QObjectListIt aPortIt(*aPortsList);
335   while ((aPortOut=(SUPERVGUI_PortOut*)aPortIt.current()) != 0) {
336     ++aPortIt;
337     if (aPortOut->isInStudy()) {
338       aPortOut->setStudyState(false);
339       aPortOut->sync();
340     }
341   }
342   delete aPortsList;
343 }
344
345
346 /**
347  * Begins Link sketching
348  */
349 void SUPERVGUI_Graph::sketchBegin(SUPERVGUI_Port* thePort) {
350   if (thePort == 0) return;
351
352   SUPERV_Port aPort = thePort->getPort();
353   myNewLink = new SUPERVGUI_Link(this);
354   mySketchPopup->setItemEnabled(myDelPntItem, false);      
355   mySketchPopup->setItemChecked(myOrtoItem, myNewLink->isOrthoMode());
356
357   myNewLink->setBeginPort(thePort);
358
359   if (aPort->IsInput()) {
360     if (aPort->Kind() == SUPERV::EndSwitchParameter
361         ||
362         aPort->Node()->Kind() == SUPERV::EndSwitchNode) {
363       myNewLink->setInputPortES(dynamic_cast<SUPERVGUI_PortInESNode*>(thePort));
364     }
365     else
366       myNewLink->setInputPort(dynamic_cast<SUPERVGUI_PortIn*>(thePort));
367   }
368   else
369     myNewLink->setOutputPort(dynamic_cast<SUPERVGUI_PortOut*>(thePort));    
370 }
371
372
373 void SUPERVGUI_Graph::sketchEnd(SUPERVGUI_Port* thePort) {
374   if (!myNewLink) return;
375
376   bool aIsInput = myNewLink->getBeginPort()->getPort()->IsInput();
377   if (aIsInput && thePort->getPort()->IsInput()
378       ||
379       !aIsInput && !thePort->getPort()->IsInput()) {
380     return;
381   }
382   
383
384   SUPERV_Port aPort = thePort->getPort();
385   if (aPort->IsInput()) {
386
387     int aKind = myNewLink->getOutputPort()->getPort()->Kind();
388
389     if ((aPort->Kind() == SUPERV::EndSwitchParameter
390          ||
391          aPort->Node()->Kind() == SUPERV::EndSwitchNode)
392         &&
393         (aKind == SUPERV::InLineParameter || aKind == SUPERV::ServiceParameter))
394       {
395         QString aName(aPort->Name());
396         if (aName != "Default")
397           myNewLink->setInputPortES(dynamic_cast<SUPERVGUI_PortInESNode*>(thePort));
398       }
399     else{ 
400       if (aPort->IsLinked()) return;
401     
402       if (aKind == SUPERV::GateParameter || aPort->Kind() == SUPERV::GateParameter) {
403         if (aKind != aPort->Kind() && aKind != SUPERV::InLineParameter 
404             && aPort->Kind() != SUPERV::InLineParameter) {
405           return;
406         }
407         else { //connection like Gate <--> Gate
408           myNewLink->setInputPort(dynamic_cast<SUPERVGUI_PortIn*>(thePort));
409         }
410       } else {
411         myNewLink->setInputPort(dynamic_cast<SUPERVGUI_PortIn*>(thePort));
412       }
413     }
414
415   } else {
416     if (myNewLink->isESInputPort()) {
417       if(aPort->Kind() == SUPERV::InLineParameter || aPort->Kind() == SUPERV::ServiceParameter)
418         {
419           myNewLink->setOutputPort(dynamic_cast<SUPERVGUI_PortOut*>(thePort));
420         }
421       else
422         return;
423     }
424     else {
425       int aKind = myNewLink->getInputPort()->getPort()->Kind();
426
427       if (aKind == SUPERV::GateParameter || aPort->Kind() == SUPERV::GateParameter) {
428         if (aKind != aPort->Kind() && aKind != SUPERV::InLineParameter 
429                                    && aPort->Kind() != SUPERV::InLineParameter) {
430           return;
431         }
432       else  //connection like Gate <--> Gate
433         myNewLink->setOutputPort(dynamic_cast<SUPERVGUI_PortOut*>(thePort));
434       } else 
435         myNewLink->setOutputPort(dynamic_cast<SUPERVGUI_PortOut*>(thePort));    
436     }
437   }
438
439   if (myNewLink->isCreationComplete()) {  // if everything is defined
440     if (myNewLink->createEngine()) {
441       myLinksList.append(myNewLink);
442       myNewLink = 0;
443     } else {
444       QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_LINK")); 
445       delete myNewLink;
446     }
447   }
448 }
449
450
451 /**
452  * Returns true if presentation of link exists
453  */
454 bool SUPERVGUI_Graph::isLinkPrsExists(SUPERV_Link theLink) {
455   SUPERVGUI_Link* aTmpLink;
456   for (aTmpLink = myLinksList.first(); aTmpLink; aTmpLink = myLinksList.next()) {
457     SUPERVGUI_PortOut* aOutPort = aTmpLink->getOutputPort();
458     if (strcmp(aOutPort->getPort()->Node()->Name(), 
459                theLink->OutPort()->Node()->Name()) == 0) {
460       QString aName(theLink->OutPort()->Name());
461       aName += "Output";
462       if (aOutPort->name() == aName) {
463         return true;
464       }
465     }
466   }
467   return false;
468 }
469
470
471 /**
472  * Creates link presentation from link engine
473  * Returns false if fails
474  */
475 bool SUPERVGUI_Graph::createLinkPrs(SUPERV_Link theLink) {
476   SUPERVGUI_Link* aNewLink = new SUPERVGUI_Link(this, theLink);
477   
478   // Find output node
479   SUPERVGUI_Node* aOutNode = (SUPERVGUI_Node*) 
480     child(theLink->OutPort()->Node()->Name(), "SUPERVGUI_Node");
481   if (aOutNode) {
482     QString aName(theLink->OutPort()->Name());
483     aName += "Output";
484     SUPERVGUI_PortOut* aOutPort = (SUPERVGUI_PortOut*)
485       aOutNode->child(aName, "SUPERVGUI_PortOut");
486     if (aOutPort)
487       aNewLink->setOutputPort(aOutPort);
488     else {
489       delete aNewLink;
490       return false;
491     }
492   } else {
493     delete aNewLink;
494     return false;
495   }
496   // Find input node
497   SUPERVGUI_Node* aInNode = (SUPERVGUI_Node*)
498     child(theLink->InPort()->Node()->Name(), "SUPERVGUI_Node");
499   if (aInNode) {
500     QString aName(theLink->InPort()->Name());
501     aName += "Input";
502     if (theLink->InPort()->Kind() == SUPERV::EndSwitchParameter) {
503       //If input port is EndSwitchParameter
504       SUPERVGUI_PortInESNode* aInPortES =(SUPERVGUI_PortInESNode*)
505         aInNode->child(aName, "SUPERVGUI_PortInESNode");        //returns null
506       if (aInPortES)
507         aNewLink->setInputPortES(aInPortES);
508       else {
509         delete aNewLink;
510         return false;
511       }
512     } else {
513       SUPERVGUI_PortIn* aInPort =(SUPERVGUI_PortIn*)
514         aInNode->child(aName, "SUPERVGUI_PortIn");
515       if (aInPort) 
516         aNewLink->setInputPort(aInPort);
517       else {
518         delete aNewLink;
519         return false;
520       }
521     }
522   } else {
523     delete aNewLink;
524     return false;
525   }
526   aNewLink->setVisible(!myIsControlView);
527   myLinksList.append(aNewLink);
528   return true;
529 }
530
531
532 void SUPERVGUI_Graph::delLastPnt() {
533   if (myNewLink) { 
534     myNewLink->delLastTmpPoint();
535   }
536 }
537
538 void SUPERVGUI_Graph::delCreatingLink() {
539   myNewLink->abortCreation();
540   delete myNewLink;
541   myNewLink=0;
542   repaintContents();
543 }
544
545 void SUPERVGUI_Graph::setOrtho() {
546   if (myNewLink) { 
547     bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
548     myNewLink->setOrthoMode(aIsOrtho);
549     mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
550   }
551 }
552
553
554
555 void SUPERVGUI_Graph::setFullView() {
556   QObjectList* aNodeList = queryList("SUPERVGUI_Node");
557   QObjectListIt aIt(*aNodeList);
558   SUPERVGUI_Node* aNode;
559   while ((aNode=(SUPERVGUI_Node*)aIt.current()) != 0) {
560     ++aIt;
561     aNode->showAll();
562   }
563   delete aNodeList;
564
565   myCtrlLinks.clear();
566   SUPERVGUI_Link* aLink;
567   for (aLink = myLinksList.first(); aLink; aLink = myLinksList.next()) {
568     aLink->setVisible(true);
569   }
570   draw();
571   myIsControlView = false;
572 }
573
574
575 void SUPERVGUI_Graph::setControlView() {
576   QObjectList* aNodeList = queryList("SUPERVGUI_Node");
577   QObjectListIt aIt(*aNodeList);
578   SUPERVGUI_Node* aNode;
579   while ((aNode=(SUPERVGUI_Node*)aIt.current()) != 0) {
580     ++aIt;
581     aNode->hideAll();
582   }
583   delete aNodeList;
584   myCtrlLinks.clear();
585   SUPERVGUI_Link* aLink;
586   for (aLink = myLinksList.first(); aLink; aLink = myLinksList.next()) {
587     aLink->setVisible(false);
588
589     QString aOutName(aLink->getEngineLink()->OutPort()->Node()->Name());
590     QString aInName(aLink->getEngineLink()->InPort()->Node()->Name());
591     QString aKey = aOutName + aInName;
592
593     if (!myCtrlLinks.contains(aKey)) {
594       SUPERVGUI_GraphNode* aOutNode = (SUPERVGUI_GraphNode*)
595         child(aOutName, "SUPERVGUI_GraphNode");
596       if (!aOutNode) continue;
597       SUPERVGUI_GraphNode* aInNode = (SUPERVGUI_GraphNode*)
598         child(aInName, "SUPERVGUI_GraphNode");
599       if (!aInNode) continue;
600
601       myCtrlLinks[aKey] = SUPERVGUI_CtrlLink(this, aOutNode, aInNode);
602     }
603   }
604   draw();
605   myIsControlView = true;
606 }
607
608
609 void SUPERVGUI_Graph::deleteNode(SUPERVGUI_Node* theNode) { 
610   theNode->close(true); 
611   draw(); 
612 }
613