]> SALOME platform Git repositories - modules/yacs.git/blob - src/prs/YACSPrs_Link.cxx
Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / prs / YACSPrs_Link.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "YACSPrs_ElementaryNode.h"
21
22 #include "YACSPrs_Link.h"
23 #include "YACSPrs_Def.h"
24
25 #include "guiContext.hxx"
26
27 #include "SUIT_ResourceMgr.h"
28 #include "SUIT_Session.h"
29
30 #include "CAM_Application.h"
31
32 #include "InGate.hxx"
33 #include "InPort.hxx"
34 #include "OutGate.hxx"
35 #include "OutPort.hxx"
36 #include <DataStreamPort.hxx>
37
38 #include <qpopupmenu.h>
39 #include <math.h>
40
41 //#define _DEVDEBUG_
42 #include "YacsTrace.hxx"
43
44 using namespace YACS::HMI;
45 using namespace YACS::ENGINE;
46
47 using namespace std;
48
49 /*!
50  * =========================== YACSPrs_Link ===========================
51  !*/
52
53 YACSPrs_Link::YACSPrs_Link( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas ):
54   QObject(theCanvas),
55   myMgr(theMgr),
56   myCanvas(theCanvas),
57   myHilighted(false),
58   mySelected(false),
59   mySelectedItem(0)
60 {
61   myColor = myMgr->colorValue("YACSGui", "link_draw_color", LINKDRAW_COLOR);
62   myZ = 0;
63 }
64
65 YACSPrs_Link::~YACSPrs_Link()
66 {
67   DEBTRACE("YACSPrs_Link::~YACSPrs_Link");
68   // remove presentation objects (points and edges)
69   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
70     (*it)->setCanvas(0);
71     delete *it;
72   }
73   myPrs.clear();
74   
75   myPoints.clear();
76 }
77
78 void YACSPrs_Link::show()
79 {
80   DEBTRACE("YACSPrs_Link::show");
81   if (myPrs.isEmpty()) createPrs();
82
83   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
84     (*it)->show();
85   }
86 }
87
88 void YACSPrs_Link::hide()
89 {
90   DEBTRACE("YACSPrs_Link::hide");
91   if (myPrs.isEmpty()) return;
92
93   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
94     (*it)->hide();
95   }
96 }
97
98 void YACSPrs_Link::merge()
99 {
100   DEBTRACE("YACSPrs_Link::merge");
101   // save z of the link
102   double aZ = ( !myPrs.isEmpty() ? myPrs.first()->z()-1 : 0 ); // the first item is a point
103
104   // remove old presentation
105   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
106     (*it)->setCanvas(0);
107     delete *it;
108   }
109   myPrs.clear();
110
111   // display a new one
112   show();
113
114   // restore z of the link
115   setZ(aZ);
116 }
117
118 void YACSPrs_Link::setCanvas(QCanvas* theCanvas)
119 {
120   myCanvas = theCanvas;
121
122   // set canvas for all prs items
123   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it)
124     (*it)->setCanvas(theCanvas);
125 }
126
127 void YACSPrs_Link::updatePoints(QCanvasItem* thePointItem)
128 {
129   if ( thePointItem == myPrs.first() || thePointItem == myPrs.last() ) return;
130   
131   YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( thePointItem );
132   if ( aPoint )
133   {
134     list<QPoint>::iterator it;
135     int id = 1;
136     for ( it = myPoints.begin(); it != myPoints.end(); it++, id++ )
137       if ( id == aPoint->getIndex() ) {
138         (*it).setX((int)(aPoint->x()));
139         (*it).setY((int)(aPoint->y()));
140         break;
141       }
142   }
143 }
144
145 void YACSPrs_Link::setHilighted(bool state)
146 {
147   myHilighted = state;
148   QColor aHilightColor = myMgr->colorValue("YACSGui", "link_hilight_color", LINK_HILIGHT_COLOR);
149   setColor(myHilighted ? aHilightColor : myColor);
150   if (!myPrs.isEmpty()) {
151     bool disp = myPrs.first()->isVisible();
152     if (disp) {
153       for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
154         (*it)->hide(); (*it)->show();
155       }
156       if (myCanvas) myCanvas->update();
157     }
158   }
159 }
160
161 void YACSPrs_Link::setSelected(bool state)
162 {
163   mySelected = state;
164   setColor(mySelected ? LINK_SELECT_COLOR : myColor);
165   if (!myPrs.isEmpty()) {
166     bool disp = myPrs.first()->isVisible();
167     if (disp) {
168       for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
169         if ( YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( *it ) ) aPoint->setSelected(state);
170         else if ( YACSPrs_Edge* anEdge = dynamic_cast<YACSPrs_Edge*>( *it ) ) anEdge->setSelected(state);
171         (*it)->hide(); (*it)->show();
172       }
173       if (myCanvas) myCanvas->update();
174     }
175   }
176 }
177
178 void YACSPrs_Link::setColor(const QColor& theColor)
179 {
180   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) {
181     YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( *it );
182     if ( aPoint ) { //if ((*it)->rtti() == YACSPrs_Canvas::Rtti_Point) {
183       aPoint->setColor(theColor);
184     }
185     YACSPrs_Edge* anEdge = dynamic_cast<YACSPrs_Edge*>( *it );
186     if ( anEdge ) { //if ((*it)->rtti() == YACSPrs_Canvas::Rtti_Edge) {
187       anEdge->setColor(theColor);
188     }
189   }
190 }
191
192 void YACSPrs_Link::setSelectedObject(QCanvasItem* theItem, const QPoint& thePoint)
193 {
194   mySelectedItem = theItem;
195   mySelectedPoint = thePoint;
196 }
197
198 QString YACSPrs_Link::getToolTipText() const {
199   return QString();
200 }
201
202 void YACSPrs_Link::remove() {
203   delete this;
204 }
205
206 void YACSPrs_Link::addPoint() {
207   DEBTRACE("YACSPrs_Link::addPoint");
208   if ( mySelected ) setSelected(false);
209
210   YACSPrs_Edge* anEdge = dynamic_cast<YACSPrs_Edge*>( mySelectedItem );
211   if ( anEdge ) {
212     int anIndex = 1;
213     QCanvasItemList::Iterator it;
214     for (it = myPrs.begin(); it != myPrs.end(); ++it) {
215       if ((*it) == anEdge) break;
216     }
217     if (it != myPrs.begin()) {
218       --it;
219       YACSPrs_Point* aPoint = (YACSPrs_Point*) (*it);
220       anIndex = aPoint->getIndex()+1;
221       if (anIndex < 1) anIndex = 1;
222     }
223     // TO DO : add point coordinates to link engine
224     if ( myPoints.empty() )
225       myPoints.push_back(mySelectedPoint);
226     else {
227       list<QPoint>::iterator it;
228       int id = 0;
229       for ( it = myPoints.begin(); it != myPoints.end(); it++, id++ )
230         if ( id == anIndex-1 ) break;
231       myPoints.insert(it, mySelectedPoint);
232     }
233
234     merge();
235     if (myCanvas) myCanvas->update();
236
237     /*
238     GuiContext* aContext = GuiContext::getCurrent();
239     if ( aContext )
240       if ( aContext->getSubjectProc() )
241         aContext->getSubjectProc()->update( EDIT, DATALINK, 0 );
242     */
243   }
244 }
245
246 void YACSPrs_Link::removePoint() {
247   if ( mySelected ) setSelected(false);
248
249   YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( mySelectedItem );
250   if ( aPoint ) {
251     // TO DO : remove point coordinates from link engine
252     QPoint aP((int)(aPoint->x()), (int)(aPoint->y()));
253     myPoints.remove(aP);
254
255     merge();
256     if (myCanvas) myCanvas->update();
257
258     /*
259     GuiContext* aContext = GuiContext::getCurrent();
260     if ( aContext )
261       if ( aContext->getSubjectProc() )
262         aContext->getSubjectProc()->update( EDIT, DATALINK, 0 );
263     */
264   }
265 }
266
267 bool YACSPrs_Link::isFirst(QCanvasEllipse* thePoint)
268 {
269   bool aRet = false;
270   if ( !myPrs.empty() 
271        && 
272        myPrs.first()->x() == thePoint->x() && myPrs.first()->y() == thePoint->y() ) aRet = true;
273   return aRet;
274 }
275
276 bool YACSPrs_Link::isLast(QCanvasEllipse* thePoint)
277 {
278   bool aRet = false;
279   if ( !myPrs.empty() 
280        && 
281        myPrs.last()->x() == thePoint->x() && myPrs.last()->y() == thePoint->y() ) aRet = true;
282   return aRet;
283 }
284
285 void YACSPrs_Link::setMyZ(double z)
286 {
287   myZ = z;
288 }
289
290 double YACSPrs_Link::getMyZ()
291 {
292   return myZ;
293 }
294
295 void YACSPrs_Link::setZ(double z)
296 {
297   DEBTRACE("YACSPrs_Link::setZ: " << z);
298   for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it)
299     if ( YACSPrs_Point* pt=dynamic_cast<YACSPrs_Point*>( *it ) )
300       {
301         DEBTRACE("YACSPrs_Link::setZ: " << z);
302         pt->setZ(z+1);
303       }
304     else if (YACSPrs_Edge* ed= dynamic_cast<YACSPrs_Edge*>( *it ) ) 
305       {
306         DEBTRACE("YACSPrs_Link::setZ: " << z);
307         ed->setZ(z);
308       }
309 }
310
311 double YACSPrs_Link::z()
312 {
313   if ( !myPrs.empty() ) return myPrs.first()->z();
314   return 0;                       
315 }
316
317 QPoint YACSPrs_Link::getConnectionPoint(YACSPrs_Port* thePort)
318 {
319   DEBTRACE("YACSPrs_Link::getConnectionPoint");
320   QPoint aCP;
321
322   YACSPrs_InOutPort* anIOPort = dynamic_cast<YACSPrs_InOutPort*>( thePort );
323   if ( anIOPort )
324   {
325     aCP = anIOPort->getConnectionPoint();
326     if ( anIOPort->isGate() )
327       aCP += QPoint( ( anIOPort->isInput() ? -LINKPOINT_SIZE/2-(NODEBOUNDARY_MARGIN+1) : 
328                                               LINKPOINT_SIZE/2+(NODEBOUNDARY_MARGIN+1) ), 0 );
329   }
330   else
331   {
332     YACSPrs_LabelPort* aLPort = dynamic_cast<YACSPrs_LabelPort*>( thePort );
333     if ( aLPort ) aCP = aLPort->getConnectionPoint();
334   }
335
336   return aCP;
337 }
338
339 void YACSPrs_Link::addPoint(const QPoint& thePoint, const int& theIndex)
340 {
341   DEBTRACE("YACSPrs_Link::addPoint");
342   YACSPrs_Point* aPoint;
343   if (myPrs.empty()) {
344     aPoint = new YACSPrs_Point(myCanvas, this, theIndex);
345     aPoint->setColor(myColor);
346     aPoint->move(thePoint.x(), thePoint.y());
347   }
348   else {
349     YACSPrs_Point* aPrev = (YACSPrs_Point*) myPrs.last();
350     
351     YACSPrs_Edge* anEdge = new YACSPrs_Edge(myCanvas, this);
352     anEdge->setColor(myColor);
353     myPrs.append(anEdge);
354     
355     aPoint = new YACSPrs_Point(myCanvas, this, theIndex);
356     aPoint->setColor(myColor);
357     aPoint->move(thePoint.x(), thePoint.y());
358     
359     aPrev->setOutEdge(anEdge);
360     aPoint->setInEdge(anEdge);
361   }
362   myPrs.append(aPoint);
363 }
364
365 void YACSPrs_Link::createPrs()
366 {
367   QColor aHilightColor = myMgr->colorValue("YACSGui", "link_hilight_color", LINK_HILIGHT_COLOR);
368   setColor(myHilighted ? aHilightColor : myColor);
369 }
370
371 /*!
372  * =========================== YACSPrs_PortLink ===========================
373  !*/
374
375 YACSPrs_PortLink::YACSPrs_PortLink( SUIT_ResourceMgr* theMgr,
376                                     QCanvas* theCanvas, 
377                                     YACSPrs_InOutPort* theInputPort, 
378                                     YACSPrs_InOutPort* theOutputPort ):
379   GuiObserver(),
380   YACSPrs_Link(theMgr, theCanvas),
381   myInputPort(theInputPort),
382   myOutputPort(theOutputPort)
383 {
384   DEBTRACE("Construct YACSPrs_PortLink");
385   //change color if datastream link
386   if ( dynamic_cast<DataStreamPort*>(theInputPort->getEngine()))
387     myColor = myMgr->colorValue("YACSGui", "stream_link_draw_color", STREAMLINKDRAW_COLOR);
388
389   if (myInputPort) myInputPort->addLink(this);
390   if (myOutputPort) myOutputPort->addLink(this);
391
392   // attach to HMI myself
393   Subject* aSub = getSubject();
394   if ( aSub )
395     aSub->attach( this );
396 }
397
398 YACSPrs_PortLink::~YACSPrs_PortLink()
399 {
400   // detach from HMI
401   YACS::HMI::Subject* aSub = getSubject();
402   if ( aSub )
403     aSub->detach(this);
404
405   if (myInputPort) {
406     myInputPort->removeLink(this);
407     myInputPort = 0;
408   }
409   if (myOutputPort) {
410     myOutputPort->removeLink(this);
411     myOutputPort = 0;
412   }
413 }
414
415 void YACSPrs_PortLink::select( bool isSelected )
416 {
417   DEBTRACE(">> YACSPrs_PortLink::select");
418   setSelected(isSelected);
419 }
420
421 void YACSPrs_PortLink::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son)
422 {
423   DEBTRACE(">> YACSPrs_PortLink::update");
424 }
425
426 YACS::HMI::Subject* YACSPrs_PortLink::getSubject() const
427 {
428   Subject* aSub = 0;
429
430   if ( !myOutputPort || !myInputPort ) return aSub;
431
432   if ( !myOutputPort->isGate() && !myInputPort->isGate() ) // data link
433   {
434     OutPort* anOP = dynamic_cast<OutPort*>( myOutputPort->getEngine() );
435     InPort* anIP = dynamic_cast<InPort*>( myInputPort->getEngine() );
436     if ( anOP && anIP )
437     {
438       GuiContext* aContext = GuiContext::getCurrent();
439       if ( aContext )
440       {
441         pair<OutPort*,InPort*> aPair(anOP,anIP);
442         if ( aContext->_mapOfSubjectLink.find( aPair ) != aContext->_mapOfSubjectLink.end() )
443           aSub = aContext->_mapOfSubjectLink[ aPair ];
444       }
445     }
446   }
447   else // control link
448   {
449     OutGate* anOG = dynamic_cast<OutGate*>( myOutputPort->getEngine() );
450     InGate* anIG = dynamic_cast<InGate*>( myInputPort->getEngine() );
451     if ( anOG && anIG )
452     {
453       Node* anON = anOG->getNode();
454       Node* anIN = anIG->getNode();
455       if ( anON && anIN )
456       {
457         GuiContext* aContext = GuiContext::getCurrent();
458         if ( aContext )
459         {
460           pair<Node*,Node*> aPair(anON,anIN);
461           if ( aContext->_mapOfSubjectControlLink.find( aPair ) != aContext->_mapOfSubjectControlLink.end() )
462             aSub = aContext->_mapOfSubjectControlLink[ aPair ];
463         }
464       }
465     }
466   }
467
468   return aSub;
469 }
470
471 void YACSPrs_PortLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLinkPoints, QRect theArea)
472 {
473   DEBTRACE("YACSPrs_PortLink::moveByPort");
474   YACSPrs_InOutPort* aPort = dynamic_cast<YACSPrs_InOutPort*>( thePort );
475   if ( aPort )
476   {
477     QPoint p = getConnectionPoint(aPort);
478     
479     if ( theMoveInternalLinkPoints )
480     {
481       // choose and collect only those points from myPoints, which is inside of theArea
482       map<int,QPoint> anIndex2MovePointMap;
483       int id = 1;
484       for ( list<QPoint>::iterator it = myPoints.begin(); it != myPoints.end(); it++, id++)
485         if ( theArea.contains(*it,true) ) anIndex2MovePointMap.insert(make_pair(id,*it));
486
487       if ( !anIndex2MovePointMap.empty() )
488       {
489         QCanvasItemList::Iterator it = myPrs.begin();
490         for (it++; it != myPrs.end(); ++it) {
491           if ( YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( *it ) ) {
492             if ( anIndex2MovePointMap.find(aPoint->getIndex()) != anIndex2MovePointMap.end() ) {
493               int dx=0,dy=0;
494               if ( myInputPort && myInputPort == aPort ) {
495                 dx = p.x() - (int)(myPrs.first()->x());
496                 dy = p.y() - (int)(myPrs.first()->y());
497               }
498               if ( myOutputPort && myOutputPort == aPort ) {
499                 if ( getInputPort()->getNode()->isSelfMoving() ) {
500                   // move internal points if moveByPort function didn't call yet for the input port of this link
501                   // (because we have to move internal points only once on moving link by input or output port)
502                   dx = p.x() - (int)(myPrs.last()->x());
503                   dy = p.y() - (int)(myPrs.last()->y());
504                 }
505               }
506               aPoint->moveBy( dx, dy );
507             }
508           }
509         }
510       }
511     }
512
513     if ( myInputPort && myInputPort == aPort ) {
514       myPrs.first()->move(p.x(), p.y());
515       return;
516     }
517     if ( myOutputPort && myOutputPort == aPort ) {
518       myPrs.last()->move(p.x(), p.y());
519       return;
520     }
521   }
522 }
523
524 void YACSPrs_PortLink::moveByPort(YACSPrs_Port* thePort, int dx, int dy)
525 {
526   DEBTRACE("YACSPrs_PortLink::moveByPort " << dx << "," << dy);
527   YACSPrs_InOutPort* aPort = dynamic_cast<YACSPrs_InOutPort*>( thePort );
528   if ( aPort )
529   {
530     if ( myInputPort && myInputPort == aPort ) {
531       myPrs.first()->moveBy(dx, dy);
532       return;
533     }
534     if ( myOutputPort && myOutputPort == aPort ) {
535       myPrs.last()->moveBy(dx, dy);
536       return;
537     }
538   }
539 }
540
541 QString YACSPrs_PortLink::getToolTipText() const {
542   QString aText;
543   if (myInputPort && myOutputPort)
544     aText = myOutputPort->getEngine()->getNode()->getName() + QString(" : ") + 
545       myOutputPort->getName() + QString(" => ") +
546       myInputPort->getEngine()->getNode()->getName() + QString(" : ") + 
547       myInputPort->getName();
548   return aText;
549 }
550
551 void YACSPrs_PortLink::remove() {
552   // for update ports' value after link deletion (only for YACSPrs_InOutPort, i.e. YACSPrs_PortLink)
553   /*QString aValue;
554   YACSPrs_InOutPort* aPort = dynamic_cast<YACSPrs_InOutPort*>( myInputPort );
555   if ( aPort ) {
556     if (aPort->getEngine()->IsParam() || myInputPort->getEngine()->IsInLine()) {
557       aValue = QString(aPort->getEngine()->ToString());
558     }
559   }*/
560
561   YACSPrs_Link::remove();
562
563   // for update ports' value after link deletion (only for YACSPrs_InOutPort, i.e. YACSPrs_PortLink)
564   /*if ( aPort && !aValue.isEmpty() ) { //&& GraphLevel() == 0
565     aPort->setValue(aValue);
566   }*/
567
568   if (myCanvas) myCanvas->update();
569 }
570
571 void YACSPrs_PortLink::createPrs()
572 {
573   DEBTRACE("YACSPrs_PortLink::createPrs");
574   // create without internal points now
575   if ( myInputPort ) addPoint(getConnectionPoint(myInputPort),0);
576
577   int i = 1;
578   for ( list<QPoint>::iterator it = myPoints.begin(); it != myPoints.end(); it++, i++ )
579     addPoint(*it, i);
580
581   if ( myOutputPort ) addPoint(getConnectionPoint(myOutputPort),myPoints.size()+1);
582
583   // the first and last points is smaller than an internal points
584   if ( QCanvasEllipse* aFP = dynamic_cast<QCanvasEllipse*>( getFirstPoint() ) ) aFP->setSize(LINKPOINT_SIZE/2, LINKPOINT_SIZE/2);
585   if ( QCanvasEllipse* aLP = dynamic_cast<QCanvasEllipse*>( getLastPoint() ) ) aLP->setSize(LINKPOINT_SIZE/2, LINKPOINT_SIZE/2);
586
587   YACSPrs_Link::createPrs();
588 }
589
590 void YACSPrs_PortLink::setHilighted(bool state)
591 {
592   QColor aHilightColor = myMgr->colorValue("YACSGui", "hook_hilight_color", HOOK_HILIGHT_COLOR);
593   QColor aDrawColor = myMgr->colorValue("YACSGui", "hook_color", HOOK_COLOR);
594   QColor aColor = state?aHilightColor:aDrawColor;
595
596   // hilight hooks
597   if (getInputPort()) {
598     YACSPrs_Hook* aHook = getInputPort()->GetHook();
599     if (aHook) aHook->setColor(aColor);
600   }
601   if (getOutputPort()) {
602     YACSPrs_Hook* aHook = getOutputPort()->GetHook();
603     if (aHook) aHook->setColor(aColor);
604   }
605
606   // hilight link
607   YACSPrs_Link::setHilighted(state);
608 }
609
610 void YACSPrs_PortLink::setSelected(bool state)
611 {
612   QColor aSelectColor = myMgr->colorValue("YACSGui", "hook_select_color", HOOK_SELECT_COLOR);
613   QColor aDrawColor = myMgr->colorValue("YACSGui", "hook_color", HOOK_COLOR);
614   QColor aColor = state?aSelectColor:aDrawColor;
615
616   // select hooks
617   if (getInputPort()) {
618     YACSPrs_Hook* aHook = getInputPort()->GetHook();
619     if (aHook) {
620       aHook->setSelected(state);
621       aHook->setColor(aColor);
622     }
623   }
624   if (getOutputPort()) {
625     YACSPrs_Hook* aHook = getOutputPort()->GetHook();
626     if (aHook) {
627       aHook->setSelected(state);
628       aHook->setColor(aColor);
629     }
630   }
631
632   // select link
633   YACSPrs_Link::setSelected(state);
634 }
635
636 /*!
637  * =========================== YACSPrs_LabelLink ===========================
638  !*/
639
640 YACSPrs_LabelLink::YACSPrs_LabelLink( SUIT_ResourceMgr* theMgr,
641                                       QCanvas* theCanvas,
642                                       YACSPrs_LabelPort* theOutputPort,
643                                       YACSPrs_ElementaryNode* theSlaveNode ):
644   YACSPrs_Link(theMgr, theCanvas),
645   myOutputPort(theOutputPort),
646   mySlaveNode(theSlaveNode)
647 {
648   DEBTRACE("Construct YACSPrs_LabelLink");
649   if (myOutputPort) myOutputPort->addLink(this);
650   if (mySlaveNode)
651   {
652     mySlaveNode->addLabelLink(this);
653     mySlaveNode->setMasterPointColor(theOutputPort->Color());
654   }
655   myColor = theOutputPort->Color();//LABELLINKDRAW_COLOR;
656 }
657
658 YACSPrs_LabelLink::~YACSPrs_LabelLink()
659 {
660   if (myOutputPort) {
661     myOutputPort->removeLink(this);
662     myOutputPort = 0;
663   }
664   if (mySlaveNode) {
665     mySlaveNode->removeLabelLink();
666     mySlaveNode = 0;
667   }
668 }
669
670 void YACSPrs_LabelLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLinkPoints, QRect theArea)
671 {
672   DEBTRACE("YACSPrs_LabelLink::moveByPort");
673   YACSPrs_LabelPort* aPort = dynamic_cast<YACSPrs_LabelPort*>( thePort );
674   if ( aPort )
675   {
676     QPoint p = getConnectionPoint(aPort);
677     
678     if ( theMoveInternalLinkPoints )
679     {
680       // choose and collect only those points from myPoints, which is inside of theArea
681       map<int,QPoint> anIndex2MovePointMap;
682       int id = 1;
683       for ( list<QPoint>::iterator it = myPoints.begin(); it != myPoints.end(); it++, id++)
684         if ( theArea.contains(*it,true) ) anIndex2MovePointMap.insert(make_pair(id,*it));
685
686       if ( !anIndex2MovePointMap.empty() )
687       {
688         QCanvasItemList::Iterator it = myPrs.begin();
689         for (it++; it != myPrs.end(); ++it) {
690           if ( YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( *it ) ) {
691             if ( anIndex2MovePointMap.find(aPoint->getIndex()) != anIndex2MovePointMap.end() ) {
692               int dx=0,dy=0;
693               if ( myOutputPort && myOutputPort == aPort ) {
694                 dx = p.x() - (int)(myPrs.last()->x());
695                 dy = p.y() - (int)(myPrs.last()->y());
696               }
697               aPoint->moveBy( dx, dy );
698             }
699           }
700         }
701       }
702     }
703
704     if ( myOutputPort && myOutputPort == aPort ) {
705       myPrs.last()->move(p.x(), p.y());
706       return;
707     }
708   }
709 }
710
711 void YACSPrs_LabelLink::moveByPort(YACSPrs_Port* thePort, int dx, int dy)
712 {
713   DEBTRACE("YACSPrs_LabelLink::moveByPort " << dx << "," << dy);
714   YACSPrs_LabelPort* aPort = dynamic_cast<YACSPrs_LabelPort*>( thePort );
715   if ( aPort )
716   {
717     if ( myOutputPort && myOutputPort == aPort ) {
718       myPrs.last()->moveBy(dx, dy);
719       return;
720     }
721   }
722 }
723
724 void YACSPrs_LabelLink::moveByNode(YACSPrs_ElementaryNode* theNode)
725 {
726   if ( mySlaveNode && mySlaveNode == theNode ) {
727     QPoint p = getConnectionMasterPoint();
728     myPrs.first()->move(p.x(), p.y());
729     return;
730   }
731 }
732
733 void YACSPrs_LabelLink::moveByNode(YACSPrs_ElementaryNode* theNode, int dx, int dy)
734 {
735   if ( mySlaveNode && mySlaveNode == theNode ) {
736     myPrs.first()->moveBy(dx, dy);
737     return;
738   }
739 }
740
741 QString YACSPrs_LabelLink::getToolTipText() const {
742   QString aText;
743   if (myOutputPort)
744     aText = /*<name of node> + QString(" : ") + */
745             myOutputPort->getName() + QString(" => ") +
746             QString("node \"") +
747             mySlaveNode->getEngine()->getName() + QString("\"");
748   return aText;
749 }
750
751 void YACSPrs_LabelLink::remove() {
752   // TO DO : remove slave node from the switch case or loop body
753
754   YACSPrs_Link::remove();
755   if (myCanvas) myCanvas->update();
756 }
757
758 QPoint YACSPrs_LabelLink::getConnectionMasterPoint()
759 {
760   if ( mySlaveNode )
761     return mySlaveNode->getConnectionMasterPoint() + QPoint(0,HOOKPOINTMASTER_SIZE/4-LINKPOINT_SIZE/2);
762   else
763     return QPoint();
764 }
765
766 void YACSPrs_LabelLink::createPrs()
767 {
768   // create without internal points now
769   if ( mySlaveNode ) addPoint(getConnectionMasterPoint(),0);
770
771   int i = 1;
772   for ( list<QPoint>::iterator it = myPoints.begin(); it != myPoints.end(); it++, i++ )
773     addPoint(*it, i);
774
775   if ( myOutputPort ) addPoint(getConnectionPoint(myOutputPort),myPoints.size()+1);
776
777   // the first and last points is smaller than an internal points
778   if ( QCanvasEllipse* aFP = dynamic_cast<QCanvasEllipse*>( getFirstPoint() ) ) aFP->setSize(LINKPOINT_SIZE/2, LINKPOINT_SIZE/2);
779   if ( QCanvasEllipse* aLP = dynamic_cast<QCanvasEllipse*>( getLastPoint() ) ) aLP->setSize(LINKPOINT_SIZE/2, LINKPOINT_SIZE/2);
780
781   YACSPrs_Link::createPrs();
782 }
783
784 void YACSPrs_LabelLink::setHilighted(bool state)
785 {
786   QColor aHilightColor = myMgr->colorValue("YACSGui", "hook_hilight_color", HOOK_HILIGHT_COLOR);
787
788   YACSPrs_LabelPort* anOutputPort = getOutputPort();
789   if (anOutputPort) {
790     QColor aHookColor = state?aHilightColor:anOutputPort->storeColor();
791     YACSPrs_Hook* aHook = anOutputPort->GetHook();
792     if (aHook) aHook->setColor(aHookColor);
793   }
794   
795   if (getSlaveNode()) {
796     QColor aMasterColor = state?aHilightColor:anOutputPort->storeColor();
797     getSlaveNode()->setMasterPointColor(aMasterColor);
798   }
799   
800   YACSPrs_Link::setHilighted(state);
801 }
802
803 void YACSPrs_LabelLink::setSelected(bool state)
804 {
805   QColor aSelectColor = myMgr->colorValue("YACSGui", "hook_select_color", HOOK_SELECT_COLOR);
806
807   YACSPrs_LabelPort* anOutputPort = getOutputPort();
808   if (anOutputPort) {
809     QColor aHookColor = state?aSelectColor:anOutputPort->storeColor();
810     YACSPrs_Hook* aHook = anOutputPort->GetHook();
811     if (aHook) {
812       aHook->setSelected(state);
813       aHook->setColor(aHookColor);
814     }
815   }
816   
817   if (getSlaveNode()) {
818     if ( getSlaveNode()->getMasterPoint() ) getSlaveNode()->getMasterPoint()->setSelected(state);
819     QColor aMasterColor = state?aSelectColor:anOutputPort->storeColor();
820     getSlaveNode()->setMasterPointColor(aMasterColor);
821   }
822   
823   YACSPrs_Link::setSelected(state);
824 }
825
826 /*!
827  * =========================== YACSPrs_Point ===========================
828  !*/
829
830 YACSPrs_Point::YACSPrs_Point(QCanvas* theCanvas, 
831                              YACSPrs_Link* theLink,
832                              const int& theIndex):
833   QCanvasEllipse(theCanvas),
834   myLink(theLink), myIndex(theIndex),
835   myInEdge(0), myOutEdge(0), myMoving(false), mySelected(false)
836 {
837   setSize(LINKPOINT_SIZE, LINKPOINT_SIZE);
838   setZ(-1);
839 }
840
841 bool YACSPrs_Point::isMoveable()
842 {
843   if ( !myInEdge || !myOutEdge ) return false;
844   return true;
845 }
846
847 void YACSPrs_Point::hilight(const QPoint& theMousePos, const bool toHilight)
848 {
849   if ( mySelected ) return;
850
851   // process the hilighting depending on mouse position
852   if (YACSPrs_Link* aLink = getLink())
853     aLink->setHilighted(toHilight);
854 }
855
856 void YACSPrs_Point::select(const QPoint& theMousePos, const bool toSelect)
857 {
858   // unhilight the item under the mouse cursor
859   hilight(theMousePos, false);
860
861   if (YACSPrs_Link* aLink = getLink())
862   {
863     aLink->setSelected(toSelect);
864     
865     YACSPrs_PortLink* aPLink = dynamic_cast<YACSPrs_PortLink*>(aLink);
866     if ( !aPLink ) return;
867
868     Subject* aSub = aPLink->getSubject();
869     if ( aSub )
870       aSub->select(toSelect);
871   }
872 }
873
874 void YACSPrs_Point::showPopup(QWidget* theParent, QMouseEvent* theEvent, const QPoint& theMousePos)
875 {
876   if ( !getLink() ) return;
877
878   getLink()->setSelectedObject(this, theMousePos);
879
880   // construct popup menu
881   QPopupMenu* aPopup = new QPopupMenu(theParent);
882   aPopup->insertItem(QObject::tr("MSG_DEL_POINT"), getLink(), SLOT(removePoint()));
883   
884   CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
885   if ( !anApp->activeModule() ) return;
886   if ( anApp->activeModule()->moduleName().compare( anApp->moduleTitle( "YACSGui" ) ) !=0 ) return;
887
888   if (theEvent->button() == RightButton) aPopup->exec(theEvent->globalPos());
889 }
890
891 QString YACSPrs_Point::getToolTipText(const QPoint& theMousePos, QRect& theRect) const
892 {
893   if (YACSPrs_Link* aLink = getLink())
894     {
895       theRect = QRect(theMousePos.x(), theMousePos.y(), MARGIN, MARGIN);
896       return aLink->getToolTipText();
897     }
898 }
899
900 bool YACSPrs_Point::arePartsOfOtherItem(QxGraph_ActiveItem* theSecondItem)
901 {
902   if ( YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( theSecondItem ) ) {
903     if ( getLink() == aPoint->getLink() ) return true;
904   }
905   else if ( YACSPrs_Edge* anEdge = dynamic_cast<YACSPrs_Edge*>( theSecondItem ) ) {
906     if ( getLink() == anEdge->getLink() ) return true;
907   }
908   return false;
909 }
910
911 int YACSPrs_Point::rtti() const
912 {
913   return 0;//YACSPrs_Canvas::Rtti_Point;
914 }
915
916 void YACSPrs_Point::setInEdge(YACSPrs_Edge* theEdge)
917 {
918   myInEdge = theEdge;
919   theEdge->setFromPoint(this);
920 }
921
922 void YACSPrs_Point::setOutEdge(YACSPrs_Edge* theEdge)
923 {
924   myOutEdge = theEdge;
925   theEdge->setToPoint(this); 
926 }
927
928 void YACSPrs_Point::moveBy(double dx, double dy)
929 {
930   QCanvasEllipse::moveBy(dx, dy);
931   
932   if ( getLink() ) getLink()->updatePoints(this);
933
934   if (myInEdge) myInEdge->setFromPoint(this);
935   if (myOutEdge) myOutEdge->setToPoint(this);
936   
937   if ( canvas() && getLink() && !getLink()->isEmptyPrs() ) {
938     //resize canvas view if mouse is outside
939     int w = (int)(x()+dx) + width() + GRAPH_MARGIN;
940     int h = (int)(y()+dy) + height() + GRAPH_MARGIN;
941     if (canvas()->width() > w) w = canvas()->width();
942     if (canvas()->height() > h) h = canvas()->height();
943     if (canvas()->width() < w || canvas()->height() < h) canvas()->resize(w, h);
944   }
945   //if (myIndex > 0 && isMoving()) {
946   //  myLink->getEngine()->ChangeCoord(myIndex, (int)x(), (int)y());
947   //}
948 }
949
950 void YACSPrs_Point::setColor(const QColor& theColor)
951 {
952   setBrush(theColor);
953 }
954
955 /*!
956  * =========================== YACSPrs_Edge ===========================
957  !*/
958
959 YACSPrs_Edge::YACSPrs_Edge(QCanvas* theCanvas, 
960                            YACSPrs_Link* theLink):
961   QCanvasLine(theCanvas),
962   myLink(theLink),
963   myStartPoint(0), myEndPoint(0), mySelected(false)
964 {
965   myArrow=new QCanvasPolygon(theCanvas);
966   setZ(-2);
967 }
968
969 YACSPrs_Edge::~YACSPrs_Edge()
970 {
971   DEBTRACE("YACSPrs_Edge::~YACSPrs_Edge");
972   myArrow->setCanvas(0);
973   delete myArrow;
974 }
975
976 bool YACSPrs_Edge::isMoveable()
977 {
978   if ( myStartPoint && ( myLink->isFirst(myStartPoint) || myLink->isLast(myStartPoint) )
979        ||
980        myEndPoint && ( myLink->isFirst(myEndPoint) || myLink->isLast(myEndPoint) ) )
981     return false;
982   return true;
983 }
984
985 void YACSPrs_Edge::hilight(const QPoint& theMousePos, const bool toHilight)
986 {
987   if ( mySelected ) return;
988
989   // process the hilighting depending on mouse position
990   if (YACSPrs_Link* aLink = getLink())
991     aLink->setHilighted(toHilight);
992 }
993
994 void YACSPrs_Edge::select(const QPoint& theMousePos, const bool toSelect)
995 {
996   // unhilight the item under the mouse cursor
997   hilight(theMousePos, false);
998
999   if (YACSPrs_Link* aLink = getLink())
1000   {
1001     aLink->setSelected(toSelect);
1002     
1003     YACSPrs_PortLink* aPLink = dynamic_cast<YACSPrs_PortLink*>(aLink);
1004     if ( !aPLink ) return;
1005
1006     Subject* aSub = aPLink->getSubject();
1007     if ( aSub )
1008       aSub->select(toSelect);
1009   }
1010 }
1011
1012 void YACSPrs_Edge::showPopup(QWidget* theParent, QMouseEvent* theEvent, const QPoint& theMousePos)
1013 {
1014   if ( !getLink() ) return;
1015
1016   getLink()->setSelectedObject(this, theMousePos);
1017
1018   // construct popup menu
1019   QPopupMenu* aPopup = new QPopupMenu(theParent);
1020   aPopup->insertItem(QObject::tr("MSG_ADD_POINT"), getLink(), SLOT(addPoint()));
1021   
1022   CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
1023   if ( !anApp->activeModule() ) return;
1024   if ( anApp->activeModule()->moduleName().compare( anApp->moduleTitle( "YACSGui" ) ) !=0 ) return;
1025
1026   if (theEvent->button() == RightButton) aPopup->exec(theEvent->globalPos());
1027 }
1028
1029 QString YACSPrs_Edge::getToolTipText(const QPoint& theMousePos, QRect& theRect) const
1030 {
1031   if (YACSPrs_Link* aLink = getLink())
1032     {
1033       theRect = boundingRect();
1034       return aLink->getToolTipText();
1035     }
1036 }
1037
1038 bool YACSPrs_Edge::arePartsOfOtherItem(QxGraph_ActiveItem* theSecondItem)
1039 {
1040   if ( YACSPrs_Point* aPoint = dynamic_cast<YACSPrs_Point*>( theSecondItem ) ) {
1041     if ( getLink() == aPoint->getLink() ) return true;
1042   }
1043   else if ( YACSPrs_Edge* anEdge = dynamic_cast<YACSPrs_Edge*>( theSecondItem ) ) {
1044     if ( getLink() == anEdge->getLink() ) return true;
1045   }
1046   return false;
1047 }
1048
1049 int YACSPrs_Edge::rtti() const
1050 {
1051   return 0;//YACSPrs_Canvas::Rtti_Edge;
1052 }
1053
1054 void YACSPrs_Edge::setFromPoint(YACSPrs_Point* thePoint)
1055 {
1056   DEBTRACE("YACSPrs_Edge::setFromPoint");
1057   myStartPoint = thePoint;
1058   setPoints((int)(thePoint->x()), (int)(thePoint->y()), endPoint().x(), endPoint().y());
1059   setArrow();
1060 }
1061
1062 void YACSPrs_Edge::setToPoint(YACSPrs_Point* thePoint)
1063 {
1064   DEBTRACE("YACSPrs_Edge::setToPoint");
1065   myEndPoint = thePoint;
1066   setPoints(startPoint().x(), startPoint().y(), (int)(thePoint->x()), (int)(thePoint->y()));
1067   setArrow();
1068 }
1069
1070 void YACSPrs_Edge::setColor(const QColor& theColor)
1071 {
1072   setPen(QPen(theColor, LINKEDGE_WIDTH));
1073   myArrow->setBrush(theColor);
1074 }
1075
1076 void YACSPrs_Edge::moveBy(double dx, double dy)
1077 {
1078   DEBTRACE("YACSPrs_Edge::moveBy " << dx << "," << dy);
1079   // for moving segment of link
1080   if (myStartPoint && myEndPoint) {
1081     myStartPoint->setMoving(true);
1082     myStartPoint->moveBy(dx, dy);
1083     
1084     myEndPoint->setMoving(true);
1085     myEndPoint->moveBy(dx,dy);
1086   }
1087   setArrow();
1088 }
1089
1090 void YACSPrs_Edge::setZ(double z)
1091 {
1092   DEBTRACE("YACSPrs_Edge::setZ: " << z);
1093   QCanvasLine::setZ(z);
1094   myArrow->setZ(z);
1095 }
1096
1097 void YACSPrs_Edge::setVisible(bool on)
1098 {
1099   DEBTRACE("YACSPrs_Edge::setVisible " << this << ","<<on);
1100   QCanvasLine::setVisible(on);
1101   myArrow->setVisible(on);
1102 }
1103
1104 void YACSPrs_Edge::setArrow()
1105 {
1106   DEBTRACE("YACSPrs_Edge::setArrow");
1107   int x1=startPoint().x();
1108   int y1=startPoint().y();
1109   int x2=endPoint().x();
1110   int y2=endPoint().y();
1111   DEBTRACE(x1 << "," << y1 << "," << x2 << "," << y2 );
1112   double d=hypot(x2-x1,y2-y1);
1113   double x=(x1+x2)/2.;
1114   double y=(y1+y2)/2.;
1115
1116   //size of arrow
1117   double l=0.,e=0.;
1118   double sina=0.;
1119   double cosa=1.;
1120   if(d > 12)
1121     {
1122       l=12.;
1123       e=6.;
1124       sina=(y2-y1)/d;
1125       cosa=(x2-x1)/d;
1126     }
1127   DEBTRACE(x << "," << y << "," << sina << "," << cosa );
1128
1129   QPointArray pa=QPointArray(3);
1130   pa.setPoint(0, QPoint((int)(x+l*cosa),(int)(y+l*sina)));
1131   pa.setPoint(1, QPoint((int)(x-e*sina),(int)(y+e*cosa)));
1132   pa.setPoint(2, QPoint((int)(x+e*sina),(int)(y-e*cosa)));
1133   myArrow->setPoints(pa);
1134   myArrow->setZ(z());
1135 }
1136
1137 void YACSPrs_Edge::setCanvas(QCanvas* theCanvas)
1138 {
1139   DEBTRACE("YACSPrs_Edge::setCanvas");
1140   QCanvasLine::setCanvas(theCanvas);
1141   myArrow->setCanvas(theCanvas);
1142 }