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