Salome HOME
copy tag mergefrom_BR_V0_1_CC_Salome_04oct07
[modules/yacs.git] / src / prs / YACSPrs_BlocNode.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_BlocNode.h"
21
22 #include "YACSPrs_Def.h"
23 #include "YACSPrs_LoopNode.h"
24 #include "YACSPrs_SwitchNode.h"
25 #include "YACSPrs_Link.h"
26
27 #include "SUIT_ResourceMgr.h"
28
29 #include <qpainter.h>
30
31 using namespace YACS::ENGINE;
32
33 void drawText4(QPainter& thePainter, const QString& theText, 
34                const QRect& theRect, int theHAlign = Qt::AlignAuto)
35 {
36   int flags = theHAlign | Qt::AlignVCenter;
37   QRect r(theRect.x() + TEXT_MARGIN, theRect.y(), 
38           theRect.width() - 2*TEXT_MARGIN, theRect.height());
39
40   QWMatrix aMat = thePainter.worldMatrix();
41   if (aMat.m11() != 1.0) { 
42     // for scaled picture only
43     QRect r1 = aMat.mapRect(r);
44     QFont saved = thePainter.font();
45     QFont f(saved);
46     if (f.pointSize() == -1) {
47       f.setPixelSize((int)(f.pixelSize()*aMat.m11()));
48     }
49     else {
50       f.setPointSize((int)(f.pointSize()*aMat.m11()));
51     }
52     thePainter.save();
53     QWMatrix m;
54     thePainter.setWorldMatrix(m);
55     thePainter.setFont(f);
56     thePainter.drawText(r1, flags, theText);
57     thePainter.setFont(saved);
58     thePainter.restore();
59   }
60   else {
61     thePainter.drawText(r, flags, theText);
62   }
63 }
64
65 /*!
66  * =========================== YACSPrs_BlocNode ===========================
67  !*/
68
69 YACSPrs_BlocNode::YACSPrs_BlocNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode,
70                                    DisplayMode theDisplayMode, int theZ,
71                                    int theLeft, int theTop, int theWidth, int theHeight):
72   YACSPrs_ElementaryNode(theMgr, theCanvas, theNode),
73   myDisplayMode(theDisplayMode)
74 {
75   printf("YACSPrs_BlocNode::YACSPrs_BlocNode\n");
76   setX(theLeft);
77   setY(theTop);
78
79   setNodeColor(BLOCNODE_COLOR);
80   setNodeSubColor(BLOCNODE_SUBCOLOR);
81
82   setStoreColor(nodeColor());
83   setStoreSubColor(nodeSubColor());
84
85   myResizing = false;
86   myResizeDirection = No;
87
88   myWidth = theWidth;
89   myHeight = theHeight;
90
91   if ( myDisplayMode == Expanded )
92   {
93     if ( myPointMaster ) myWidth = myPointMaster->width() > theWidth ? myPointMaster->width() : theWidth;
94     else myWidth = theWidth;
95     
96     int anEmptyHeight = getTitleHeight() + getGateHeight() + 2*BLOCNODE_MARGIN;
97     myHeight = ( (anEmptyHeight > theHeight) ? anEmptyHeight : theHeight);
98     
99     setTitleHeight(getTitleHeight()+2*PORT_MARGIN);
100     
101     myContentMoving = true;
102     myBoundColor = BLOCNODERECT_COLOR;
103
104     setZ(theZ);
105     
106     updateGates();
107   }
108   else
109   {
110     myContentMoving = false;
111     setZ(2);
112
113     update();
114
115     // not yet implemented
116   }
117 }
118
119 YACSPrs_BlocNode::~YACSPrs_BlocNode() 
120 {
121   for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
122     delete (*it);
123   myChildren.clear();
124 }
125
126 void YACSPrs_BlocNode::setChildren(std::set<YACSPrs_ElementaryNode*>& theChildren)
127
128   if ( myDisplayMode == Expanded )
129   { 
130     myChildren = theChildren;
131     // resize bounding rectangle if needed
132     int aMaxWidth=0, aMaxHeight=0;
133     int aX = (int)x();
134     int aY = (int)y() + getTitleHeight();
135     bool hasBlocChild = false;
136     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
137     {  
138       if ( aMaxWidth < (*it)->maxWidth() ) aMaxWidth = (*it)->maxWidth();
139       if ( aMaxHeight < (*it)->maxHeight() ) aMaxHeight = (*it)->maxHeight();
140       YACSPrs_LoopNode* aLoop = dynamic_cast<YACSPrs_LoopNode*>( *it );
141       if ( aLoop )
142         (*it)->moveBy( aX - (*it)->boundingRect().x() + (( 2*HOOKPOINT_SIZE > 3*TITLE_HEIGHT/2 ) ? ( 2*HOOKPOINT_SIZE - 3*TITLE_HEIGHT/2 ) : 0) + BLOCNODE_MARGIN, 
143                        aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN );
144       else
145       {
146         YACSPrs_BlocNode* aBloc = dynamic_cast<YACSPrs_BlocNode*>( *it );
147         if ( aBloc ) {
148           (*it)->moveBy( aX - (*it)->boundingRect().x() + HOOKPOINTGATE_SIZE + BLOCNODE_MARGIN, aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN );
149           hasBlocChild = true;
150         }
151         else
152           (*it)->moveBy( aX - (*it)->boundingRect().x() + 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN,
153                          aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN );
154       }
155       (*it)->setIsInBloc(true);
156     }
157     if ( aMaxWidth > myWidth ) myWidth = aMaxWidth + 2*BLOCNODE_MARGIN;
158     if ( aMaxHeight > myHeight ) myHeight = aMaxHeight + getTitleHeight() + getGateHeight() + 2*BLOCNODE_MARGIN;
159
160     setZ(z());
161
162     updateGates();
163     printf("Parent : %s. Number of children : %d\n",myEngine->getName().c_str(),myChildren.size());
164   }  
165 }
166
167 void YACSPrs_BlocNode::setCanvas(QCanvas* theCanvas)
168 {
169   QCanvasItem::setCanvas(theCanvas);
170   
171   if ( myDisplayMode == Expanded )
172   {
173     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
174     {
175       (*it)->setCanvas(theCanvas);
176       (*it)->setArea(getAreaRect());
177     }
178   }
179   else
180   {
181     // not yet implemented
182   }
183
184   // set canvas to all ports
185   YACSPrs_Port* aPort;
186   for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
187     aPort->setCanvas(theCanvas);
188
189   // set canvas to master point
190   if (myPointMaster)
191   {
192     myPointMaster->setCanvas(theCanvas);
193     QPoint aPnt = getConnectionMasterPoint();
194     myPointMaster->setCoords(aPnt.x(), aPnt.y());
195   }
196 }
197
198 bool YACSPrs_BlocNode::isResizable(QPoint thePoint, int& theCursorType)
199 {
200   if ( myDisplayMode == Expanded )
201   {
202     theCursorType = 0;
203     QRect aRect = getRect();
204
205     int aM11 = (int)( getTMatrix().m11() < 1 ? 1/getTMatrix().m11() : 1 );
206     int aM22 = (int)( getTMatrix().m22() < 1 ? 1/getTMatrix().m22() : 1 );
207     
208     int aW = 8*aM11; int aShiftX = (aW-2)/2;
209     int aH = 8*aM22; int aShiftY = (aH-2)/2;
210     
211     QRect aLeft(  (int)x()-aShiftX,        (int)y()-aShiftY,         aW,        height()+aH);
212     QRect aRight( (int)x()+width()-aShiftX,(int)y()-aShiftY,         aW,        height()+aH);
213     QRect aTop(   (int)x()-aShiftX,        (int)y()-aShiftY,         width()+aW,aH);
214     QRect aBottom((int)x()-aShiftX,        (int)y()+height()-aShiftY,width()+aW,aH);
215     
216     if ( aTop.contains(thePoint) && aRight.contains(thePoint) ) {
217       theCursorType = Direction(TopRight); // 6
218       return true;
219     }
220     if ( aBottom.contains(thePoint) && aLeft.contains(thePoint) ) {
221       theCursorType = Direction(BottomLeft); // 8
222       return true;
223     }
224     if ( aTop.contains(thePoint) && aLeft.contains(thePoint) ) {
225       theCursorType = Direction(LeftTop); // 5
226       return true;
227     }
228     if ( aBottom.contains(thePoint) && aRight.contains(thePoint) ) {
229       theCursorType = Direction(RightBottom); // 7
230       return true;
231     }
232     if ( aTop.contains(thePoint) ) {
233       theCursorType = Direction(Top); // 2
234       return true;
235     }
236     if ( aBottom.contains(thePoint) ) {
237       theCursorType = Direction(Bottom); // 4
238       return true;
239     }
240     if ( aLeft.contains(thePoint) ) {
241       theCursorType = Direction(Left); // 1
242       return true;
243     }
244     if ( aRight.contains(thePoint) ) {
245       theCursorType = Direction(Right); // 3
246       return true;
247     }
248     return false;
249   }
250   else return false;
251 }
252
253 bool YACSPrs_BlocNode::isResizing()
254
255   if ( myDisplayMode == Expanded ) return myResizing;
256   else return false;
257 }
258
259 void YACSPrs_BlocNode::beforeResizing(int theCursorType)
260
261   if ( myDisplayMode == Expanded )
262   {
263     myResizing = true; 
264     myResizeDirection = Direction(theCursorType);
265   }
266 }
267   
268 void YACSPrs_BlocNode::resize(QPoint thePoint)
269 {
270   if ( myDisplayMode == Expanded )
271   {
272     if ( !checkArea(0,0,thePoint) ) return;
273
274     QPoint aBottomP = thePoint + QPoint(0, ( myPointMaster ? myPointMaster->height()/2 : 0 ));
275     QPoint aLeftP = thePoint + QPoint(-HOOKPOINTGATE_SIZE, 0);
276     QPoint aRightP = thePoint + QPoint(HOOKPOINTGATE_SIZE, 0);
277
278     myContentMoving = false;
279     int xP = thePoint.x();
280     int yP = thePoint.y();
281     switch (myResizeDirection)
282       {
283       case 1: // left edge
284         if ( xP < minXContent() && checkArea(0,0,aLeftP) ) {
285           myWidth += (int)x() - xP;
286           setX(xP);
287         }
288         break;
289       case 2: // top edge
290         if ( yP < minYContent() ) {
291           myHeight += (int)y() - yP;
292           setY(yP);
293         }
294         break;
295       case 3: // right edge
296         if ( xP > maxXContent() && checkArea(0,0,aRightP) )
297           myWidth += xP - (int)x() - myWidth;
298         break;
299       case 4: // bottom edge
300         if ( yP > maxYContent() && checkArea(0,0,aBottomP) )
301           myHeight += yP - (int)y() - myHeight;
302         break;
303       case 5: // left and top edges
304         if ( checkArea(0,0,aLeftP) )
305         {
306           if ( xP < minXContent() ) {
307             myWidth += (int)x() - xP;
308             setX(xP);
309           }
310           if ( yP < minYContent() ) {
311             myHeight += (int)y() - yP;
312             setY(yP);
313           }
314         }
315         break;
316       case 6: // right and top edges
317         if ( checkArea(0,0,aRightP) )
318         {
319           if ( xP > maxXContent() )
320             myWidth += xP - (int)x() - myWidth;
321           if ( yP < minYContent() ) {
322             myHeight += (int)y() - yP;
323             setY(yP);
324           }
325         }
326         break;
327       case 7: // right and bottom edges
328         if ( checkArea(0,0,aBottomP) && checkArea(0,0,aRightP) )
329         {
330           if ( xP > maxXContent() )
331             myWidth += xP - (int)x() - myWidth;
332           if ( yP > maxYContent() )
333             myHeight += yP - (int)y() - myHeight;
334         }
335         break;
336       case 8: // left and bottom edges
337         if ( checkArea(0,0,aLeftP) && checkArea(0,0,aBottomP) )
338         {
339           if ( xP < minXContent() ) {
340             myWidth += (int)x() - xP;
341             setX(xP);
342           }
343           if ( yP > maxYContent() )
344             myHeight += yP - (int)y() - myHeight;
345         }
346         break;
347       default:
348         break;
349       }
350     QPoint aPnt = getConnectionMasterPoint();
351     myPointMaster->setCoords(aPnt.x(), aPnt.y());
352
353     updateGates();
354
355     if ( canvas() ) {
356       
357       QRect aChangedRect = getRect();
358       aChangedRect.setRect(aChangedRect.x()-2, aChangedRect.y()-2, 
359                            aChangedRect.width()*2/*+4*/, aChangedRect.height()*2/*+4*/);
360       canvas()->setChanged(aChangedRect);
361       canvas()->update();
362     }
363
364     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
365       (*it)->setArea(getAreaRect());
366
367     myContentMoving = true;
368   }
369 }
370
371 void YACSPrs_BlocNode::afterResizing()
372
373   if ( myDisplayMode == Expanded ) myResizing = false; 
374 }
375
376 void YACSPrs_BlocNode::showPopup(QWidget* theParent, QMouseEvent* theEvent, const QPoint& theMousePos)
377 {
378 }
379
380 int YACSPrs_BlocNode::rtti() const
381 {
382   return 0;//YACSPrs_Canvas::Rtti_BlocNode;
383 }
384
385 void YACSPrs_BlocNode::setVisible(bool b)
386 {
387   QCanvasPolygonalItem::setVisible(b);
388
389   if ( myDisplayMode == Expanded )
390   {
391     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
392       (*it)->setVisible(b);
393     // set visibility to all ports
394     YACSPrs_Port* aPort;
395     for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
396       aPort->setVisible(b);
397   }
398   else
399   {
400     // not yet implemented
401     // set visibility to all ports
402     YACSPrs_Port* aPort;
403     for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
404       if (aPort->isVisible()) aPort->setVisible(b);
405   }
406   
407   // set visibility to master point
408   myPointMaster->setVisible(b);
409   updateLabelLink();
410 }
411
412 QPointArray YACSPrs_BlocNode::constructAreaPoints(int theW, int theH) const
413 {
414   int w = theW+2;
415   int h = theH+1; // add width of pen
416
417   if ( myDisplayMode == Expanded )
418   {
419     QPointArray aPnts(4);
420     aPnts[0] = QPoint((int)x()-2, (int)y()-2) + QPoint(-NODEBOUNDARY_MARGIN/2,-NODEBOUNDARY_MARGIN/2);
421     aPnts[1] = aPnts[0] + QPoint(w, 0) + QPoint(NODEBOUNDARY_MARGIN,0);
422     aPnts[2] = aPnts[1] + QPoint(0, h) + QPoint(0,NODEBOUNDARY_MARGIN);
423     aPnts[3] = aPnts[0] + QPoint(0, h) + QPoint(0,NODEBOUNDARY_MARGIN);
424     return aPnts;
425   }
426   else
427   {
428     return QPointArray(); // not yet implemented
429   }
430 }
431
432 void YACSPrs_BlocNode::moveBy(double dx, double dy)
433 {
434   // for constraint nodes' moving inside the Bloc-->
435   if ( isCheckAreaNeeded() && !checkArea(dx,dy) ) return;
436   // <--
437
438   int aX = (int) (x()+dx);
439   int aY = (int) (y()+dy);
440   int xx = aX - (int)x();
441   int yy = aY - (int)y();
442
443   if ( canvas() )
444   {  
445     int w = aX + width() + GRAPH_MARGIN;
446     int h = aY + height() + GRAPH_MARGIN;
447     if (canvas()->width() > w) w = canvas()->width();
448     if (canvas()->height() > h) h = canvas()->height();
449     if (canvas()->width() < w || canvas()->height() < h)
450       canvas()->resize(w, h);
451   }
452
453   if ( myDisplayMode == Expanded )
454   {
455     // move all children if mouse is in background of Bloc node in expanded mode
456     QCanvasPolygonalItem::moveBy(dx, dy); // move the bounding rectangle
457     if ( myContentMoving ) {
458       for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
459         (*it)->setSelfMoving(false); // for move link's points as a content of moving Bloc node
460       for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
461       {
462         (*it)->setArea(getAreaRect());
463         (*it)->moveBy(xx, yy);
464       }
465       for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
466         (*it)->setSelfMoving(true); // for move link's points as a content of moving Bloc node
467     }
468     
469     // update port's rectangle
470     updateGates();
471     //YACSPrs_Port* aPort;
472     //for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
473     //  aPort->moveBy(xx, yy);
474   }
475   else
476   {
477     QCanvasPolygonalItem::moveBy(dx, dy);
478
479     // not yet implemented
480
481     // update port's rectangle
482     YACSPrs_Port* aPort;
483     for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
484       aPort->moveBy(xx, yy);
485   }
486
487   myPointMaster->moveBy(dx, dy);
488   if ( myLabelLink ) myLabelLink->moveByNode(this, (int)dx, (int)dy);
489   
490   if ( isSelected() && canvas() && isMoving() )
491   {
492     QRect aRect = boundingRect();
493     QPoint aShift(20,20);
494     aRect.setTopLeft(aRect.topLeft()-aShift);
495     aRect.setBottomRight(aRect.bottomRight()+aShift);
496     canvas()->setChanged(aRect);
497     canvas()->update();
498   }
499 }
500
501 void YACSPrs_BlocNode::setZ(double z)
502 {
503   QCanvasItem::setZ(z);
504
505   if ( myDisplayMode == Expanded )
506     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ ) {
507       if ( dynamic_cast<YACSPrs_BlocNode*>( *it ) ) (*it)->setZ(z+4);
508       else (*it)->setZ(z+3);
509     }
510   else
511   {
512     // not yet implemented
513   }
514
515   // update port's 
516   YACSPrs_Port* aPort;
517   for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
518     aPort->setZ(z,false);
519   
520   if ( myPointMaster ) myPointMaster->setZ(z);
521 }
522
523 void YACSPrs_BlocNode::updateGates()
524 {
525   bool aDisp = isVisible();
526   if (aDisp) hide();
527  
528   if ( myDisplayMode == Expanded )
529   {
530     QRect aRect = getRect();
531     int aPRectWidth = (int)(aRect.width()/2) - 2*PORT_MARGIN;
532     
533     int ix = aRect.left() + PORT_MARGIN;// + 1;
534     int iy = aRect.bottom()-getGateHeight() + PORT_MARGIN;// + 1;
535     int ox = ix + aPRectWidth + 2*PORT_MARGIN + 2; // add pen width
536     int oy = aRect.bottom()-getGateHeight() + PORT_MARGIN;// + 1;
537     
538     if ( myPortList.isEmpty() )
539     { // create (and update)
540       // input Gate
541       YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),myEngine->getInGate(),this);
542       anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT));
543       anInPort->setColor(nodeSubColor());
544       anInPort->setStoreColor(nodeSubColor());
545       myPortList.append(anInPort);
546       
547       // output Gate
548       YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),myEngine->getOutGate(),this);
549       anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT));
550       anOutPort->setColor(nodeSubColor());
551       anOutPort->setStoreColor(nodeSubColor());
552       myPortList.append(anOutPort);
553     }
554     else
555     { // only update
556       YACSPrs_Port* aPort;
557       for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
558       { 
559         YACSPrs_InOutPort* anIOPort = dynamic_cast<YACSPrs_InOutPort*>( aPort );
560         if ( anIOPort && anIOPort->isGate() )
561         {
562           anIOPort->setStoreColor(nodeSubColor());
563           if ( anIOPort->isInput() ) // test input ports
564             anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
565           else // test output ports
566             anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
567         }
568       }
569     }
570   }
571   else
572   {
573     // not yet implemented
574   }
575
576   if (aDisp) show();  
577 }
578
579 int YACSPrs_BlocNode::width() const
580 {
581   if ( myDisplayMode == Expanded ) return myWidth;
582   else return 0; // not yet implemented
583 }
584
585 int YACSPrs_BlocNode::height() const
586 {
587   if ( myDisplayMode == Expanded ) return myHeight;
588   else return 0; // not yet implemented
589 }
590
591 void YACSPrs_BlocNode::resize(int theWidth, int theHeight)
592 {
593   if ( myDisplayMode == Expanded )
594   {
595     myContentMoving = false;
596
597     myWidth = theWidth;
598     myHeight = theHeight;
599
600     QPoint aPnt = getConnectionMasterPoint();
601     myPointMaster->setCoords(aPnt.x(), aPnt.y());
602
603     updateGates();
604
605     if ( canvas() ) {
606       
607       QRect aChangedRect = getRect();
608       aChangedRect.setRect(aChangedRect.x()-2, aChangedRect.y()-2, 
609                            aChangedRect.width()*2/*+4*/, aChangedRect.height()*2/*+4*/);
610       canvas()->setChanged(aChangedRect);
611       canvas()->update();
612     }
613
614     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
615       (*it)->setArea(getAreaRect());
616
617     myContentMoving = true;
618   }
619 }
620
621 int YACSPrs_BlocNode::minXContent()
622 {
623   if ( myDisplayMode == Expanded )
624   {
625     int aMinX = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().left()) : boundingRect().left() + 2*BLOCNODE_MARGIN;
626     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
627       if ( aMinX > (*it)->boundingRect().left() ) aMinX = (int)( (*it)->boundingRect().left() );
628     
629     aMinX -= 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN;
630     return aMinX;
631   }
632   return 0;
633 }
634
635 int YACSPrs_BlocNode::maxXContent()
636 {
637   if ( myDisplayMode == Expanded )
638   {
639     int aMaxX = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().right()) : boundingRect().right() - 2*BLOCNODE_MARGIN;
640     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
641       if ( aMaxX < (*it)->boundingRect().right() ) aMaxX = (int)( (*it)->boundingRect().right() );
642     
643     aMaxX += 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN;
644     return aMaxX;
645   }
646   return 0;
647 }
648
649 int YACSPrs_BlocNode::minYContent()
650 {
651   if ( myDisplayMode == Expanded )
652   {
653     int aMinY = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().top()) : (int)x();
654     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
655       if ( aMinY > (*it)->boundingRect().top() ) aMinY = (int)( (*it)->boundingRect().top() );
656     
657     aMinY -= getTitleHeight() + BLOCNODE_MARGIN;
658     return aMinY;
659   }
660   return 0;
661 }
662
663 int YACSPrs_BlocNode::maxYContent()
664 {
665   if ( myDisplayMode == Expanded )
666   {
667     int aMaxY = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().bottom()) : (int)x();
668     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
669       if ( aMaxY < (*it)->boundingRect().bottom() ) aMaxY = (int)( (*it)->boundingRect().bottom() );
670     
671     aMaxY += getGateHeight() + (myPointMaster ? myPointMaster->height()/2 : 0 ) + BLOCNODE_MARGIN;
672     return aMaxY;
673   }
674   return 0;
675 }
676
677 int YACSPrs_BlocNode::minWidth() const
678 {
679   if ( myDisplayMode == Expanded )
680   {
681     int aMinWidth = myPointMaster ? myPointMaster->width() : 0;
682     int aMinX = (!myChildren.empty()) ? (int)((*myChildren.begin())->x()) : (int)x();
683     int aMaxX = aMinX;
684     int aChildMaxWidth = 0;
685     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
686     {  
687       if ( aMinX > (*it)->x() ) aMinX = (int)( (*it)->x() );
688       if ( aMaxX < (*it)->x() ) aMaxX = (int)( (*it)->x() );
689       if ( aChildMaxWidth < (*it)->maxWidth() ) aChildMaxWidth = (*it)->maxWidth();
690     }
691     if ( aMinWidth < aMaxX - aMinX + aChildMaxWidth ) aMinWidth = aMaxX - aMinX + aChildMaxWidth + 2*BLOCNODE_MARGIN;
692     return aMinWidth;
693   }
694   else
695   {
696     return width();// + sliseWidth; // not yet implemented
697   }
698 }
699
700 int YACSPrs_BlocNode::minHeight() const
701 {
702   if ( myDisplayMode == Expanded )
703   {
704     int aMinHeight =  getTitleHeight() + getGateHeight() + 2*BLOCNODE_MARGIN;
705     int aMinY = (!myChildren.empty()) ? (int)((*myChildren.begin())->y()) : (int)y();
706     int aMaxY = aMinY;
707     int aChildMaxHeight = 0;
708     for ( std::set<YACSPrs_ElementaryNode*>::iterator it = myChildren.begin(); it != myChildren.end(); it++ )
709     {  
710       if ( aMinY > (*it)->y() ) aMinY = (int)( (*it)->y() );
711       if ( aMaxY < (*it)->y() ) aMaxY = (int)( (*it)->y() );
712       if ( aChildMaxHeight < (*it)->maxHeight() ) aChildMaxHeight = (*it)->maxHeight();
713       
714       YACSPrs_LoopNode* aLoop = dynamic_cast<YACSPrs_LoopNode*>( *it );
715       if ( aLoop ) aChildMaxHeight -= 3*TITLE_HEIGHT/2;
716       else
717       {
718         YACSPrs_SwitchNode* aSwitch = dynamic_cast<YACSPrs_SwitchNode*>( *it );
719         if ( aSwitch ) aChildMaxHeight -= 2*TITLE_HEIGHT;
720       }
721       
722     }
723     if ( aMinHeight < aMaxY - aMinY + aChildMaxHeight ) aMinHeight += aMaxY - aMinY + aChildMaxHeight;
724     return aMinHeight;
725   }
726   else
727   {
728     return height();// + sliseWidth; // not yet implemented
729   }
730 }
731
732 int YACSPrs_BlocNode::maxWidth() const
733 {
734   if ( myDisplayMode == Expanded )
735   {
736     return boundingRect().width() + 2*HOOKPOINTGATE_SIZE;
737   }
738   else
739   {
740     return width();// + sliseWidth; // not yet implemented
741   }
742 }
743
744 int YACSPrs_BlocNode::maxHeight() const
745 {
746   if ( myDisplayMode == Expanded )
747   {
748     return YACSPrs_ElementaryNode::maxHeight();
749   }
750   else
751   {
752     return YACSPrs_ElementaryNode::maxHeight();// + sliseWidth; // not yet implemented
753   }
754 }
755
756 QRect YACSPrs_BlocNode::getTitleRect() const
757 {
758   if ( myDisplayMode == Expanded )
759     return QRect((int)x(), (int)y(), width(), getTitleHeight());
760   else
761     return YACSPrs_ElementaryNode::getTitleRect();
762 }
763
764 QRect YACSPrs_BlocNode::getGateRect() const
765 {
766   if ( myDisplayMode == Expanded )
767     return QRect((int)x(), getRect().bottom()-getGateHeight(), width(), getGateHeight());
768   else
769     return YACSPrs_ElementaryNode::getGateRect();
770 }
771
772 QRect YACSPrs_BlocNode::getAreaRect() const
773 {
774   if ( myDisplayMode == Expanded )
775   {
776     QPoint aShift(BLOCNODE_MARGIN/2, BLOCNODE_MARGIN/2);
777     QPoint aTopLeft = getTitleRect().bottomLeft() + aShift;
778     QPoint aBottomRight = getGateRect().topRight() - aShift;
779     QRect anArea(aTopLeft, aBottomRight);
780     return anArea;
781   }
782   return QRect();
783 }
784
785 bool YACSPrs_BlocNode::checkArea(double dx, double dy, QPoint thePoint)
786 {
787   if ( myDisplayMode == Expanded )
788   {
789     // for constraint nodes' moving inside the Bloc-->
790     if ( !myIsInBloc ) return true;
791     
792     if ( !thePoint.isNull() )
793       if ( myArea.isValid() && myArea.contains(thePoint,true) ) return true;
794       else return false;
795     
796     QRect aRect = boundingRect();
797     aRect.moveBy((int)dx, (int)dy);
798     aRect.setRect(aRect.x()-HOOKPOINTGATE_SIZE, aRect.y() + NODEBOUNDARY_MARGIN/2, maxWidth(), maxHeight());
799     if ( myArea.isValid() && myArea.contains(aRect) )
800       return true;
801     return false;
802     // <--
803   }
804   return true;
805 }
806
807 void YACSPrs_BlocNode::drawShape(QPainter& thePainter)
808 {
809   if ( myDisplayMode == Expanded )
810   {
811     drawFrame(thePainter);
812     drawTitle(thePainter);
813     drawGate(thePainter);
814   }
815   else
816   { 
817     // not yet implemented
818   }
819 }
820
821 void YACSPrs_BlocNode::drawTitle(QPainter& thePainter)
822 {
823   QPen savedP = thePainter.pen();
824   thePainter.setPen(QPen(myBoundColor, 2, Qt::SolidLine));
825   thePainter.drawLine((int)x(), (int)(y()+getTitleHeight()), (int)(x()+width()), (int)(y()+getTitleHeight()));
826
827   QBrush savedB = thePainter.brush();
828   thePainter.setBrush(nodeSubColor());
829   thePainter.setPen(thePainter.brush().color().dark(140));
830
831   QRect aRoundRect = getTitleRect();
832   aRoundRect.setRect(aRoundRect.x() + PORT_MARGIN, aRoundRect.y() + PORT_MARGIN,
833                      aRoundRect.width() - 2*PORT_MARGIN, aRoundRect.height() - 2*PORT_MARGIN);
834   thePainter.drawRoundRect(aRoundRect,myXRnd,myYRnd);
835
836   thePainter.setPen(Qt::white);
837   drawText4(thePainter, QString(myEngine->getName()), aRoundRect, Qt::AlignHCenter);
838
839   thePainter.setBrush(savedB);
840   thePainter.setPen(savedP);
841 }
842
843 void YACSPrs_BlocNode::drawGate(QPainter& thePainter)
844 {
845   if ( myDisplayMode == Expanded )
846   {
847     QPen savedP = thePainter.pen();
848     thePainter.setPen(QPen(myBoundColor, 2, Qt::SolidLine));
849     
850     QRect aRect = getRect();
851     int aGateTop = aRect.bottom()-getGateHeight();
852     thePainter.drawLine(aRect.left(), aGateTop, aRect.right(), aGateTop);
853     
854     int x0 = (aRect.left() + aRect.right())/2;
855     thePainter.drawLine(x0, aGateTop, x0, aRect.bottom());
856     
857     int aRRectWidth = x0 - aRect.left() - 2*PORT_MARGIN;
858     //QRect aTRect = getTitleRect();
859     //int aXRnd = aTRect.width()*myXRnd/aRRectWidth;
860     //int aYRnd = aTRect.height()*myYRnd/PORT_HEIGHT;
861
862     thePainter.setPen(nodeSubColor());
863     YACSPrs_Port* aPort;
864     for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
865       if ( (YACSPrs_InOutPort*)aPort && ((YACSPrs_InOutPort*)aPort)->isGate() )
866         aPort->draw(thePainter,myXRnd,myYRnd);//aXRnd,aYRnd);
867
868     thePainter.setPen(savedP);
869   }
870   else
871   {
872     // not yet implemented
873   }
874 }
875
876 void YACSPrs_BlocNode::drawFrame(QPainter& thePainter)
877 {
878   if ( myDisplayMode == Expanded )
879   {
880     QBrush savedB = thePainter.brush();
881     thePainter.setBrush(nodeColor());/*NoBrush*/
882
883     QPen savedP = thePainter.pen();
884     thePainter.setPen(QPen(myBoundColor, 2, Qt::DashLine));
885     
886     thePainter.drawRect(getRect());
887     
888     thePainter.setPen(savedP);
889     thePainter.setBrush(savedB);
890
891     // draw bounding nodes' polygon if node is currently selected
892     if ( isSelected() ) drawBoundary(thePainter,2);
893   }
894   else
895   { 
896     // not yet implemented
897   }
898 }
899
900 QString YACSPrs_BlocNode::getToolTipText(const QPoint& theMousePos, QRect& theRect) const
901 {
902   // Check if the tooltip for ports is needed
903   if (getBodyRect().contains(theMousePos, true) || getGateRect().contains(theMousePos, true))
904     return YACSPrs_ElementaryNode::getToolTipText(theMousePos,theRect);
905
906   QString aText = QString("");
907   aText += QString("Name: %1\n").arg(getEngine()->getName());
908   aText += QString("Type: %1\n").arg("Block node");
909   theRect = getTitleRect();
910   theRect = theRect.unite(getAreaRect());
911   return aText;
912 }