1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "YACSPrs_LoopNode.h"
21 #include "YACSPrs_Def.h"
23 #include "SUIT_ResourceMgr.h"
27 #include <ForLoop.hxx>
28 #include <WhileLoop.hxx>
30 using namespace YACS::ENGINE;
35 YACSPrs_LoopNode::YACSPrs_LoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode, const bool& thePortUpdate ):
36 YACSPrs_InlineNode(theMgr, theCanvas, theNode, false)
38 setNodeColor(LOOPNODE_COLOR);
39 setNodeSubColor(LOOPNODE_SUBCOLOR);
40 setBracketColor(LOOPNODE_BRACKETCOLOR);
42 setStoreColor(nodeColor());
43 setStoreSubColor(nodeSubColor());
44 myStoreBracketColor = myBracketColor;
46 myTopPixmap = myMgr->loadPixmap( "YACSPrs", QObject::tr( "ICON_TITLE_RARROW" ));
47 myBottomPixmap = myMgr->loadPixmap( "YACSPrs", QObject::tr( "ICON_TITLE_LARROW" ));
49 if ( thePortUpdate ) {
50 //updatePorts(); // will be called in moveBy(...) function
51 moveBy(3*TITLE_HEIGHT/2, 3*TITLE_HEIGHT/2);
58 YACSPrs_LoopNode::~YACSPrs_LoopNode()
62 void YACSPrs_LoopNode::select(const QPoint& theMousePos, const bool toSelect)
66 // unhilight the item under the mouse cursor
67 hilight(theMousePos, false);
69 bool isOnPort = false;
70 if (getBodyRect().contains(theMousePos, true) || getGateRect().contains(theMousePos, true))
73 QPtrList<YACSPrs_Port> aPortList = getPortList();
74 for (YACSPrs_Port* aPort = aPortList.first(); aPort; aPort = aPortList.next()) {
75 if (aPort->getPortRect().contains(theMousePos, true)) {
77 if ( aPort != mySelectedPort )
81 mySelectedPort->setSelected(false);
82 mySelectedPort->setColor(mySelectedPort->storeColor(), false, true, true);
87 setBracketColor( myStoreBracketColor );
88 setNodeSubColor( storeSubColor(), true );
90 aPort->setSelected(true);
91 aPort->setColor(aPort->Color().dark(130), false, true, true);
92 mySelectedPort = aPort;
101 if ( mySelectedPort )
103 mySelectedPort->setSelected(false);
107 if ( storeSubColor().dark(130) != nodeSubColor() )
109 myStoreBracketColor = myBracketColor;
110 setStoreSubColor( nodeSubColor() );
113 setBracketColor( bracketColor().dark(130) );
114 setNodeSubColor( nodeSubColor().dark(130), true );
120 if ( mySelectedPort ) {
121 mySelectedPort->setSelected(false);
122 mySelectedPort->setColor(mySelectedPort->storeColor(), false, true, true);
127 setBracketColor( myStoreBracketColor );
128 setNodeSubColor( storeSubColor(), true );
133 int YACSPrs_LoopNode::rtti() const
135 return 0;//YACSPrs_Canvas::Rtti_LoopNode;
138 QPointArray YACSPrs_LoopNode::constructAreaPoints(int theW, int theH) const
142 int aCorner = 3*TITLE_HEIGHT/2;
144 QPointArray aPnts(8);
145 QPoint p((int)x(), (int)y());
146 p = p + QPoint(-NODEBOUNDARY_MARGIN,0);
148 aPnts[1] = p + QPoint(aCorner, -aCorner) + QPoint(NODEBOUNDARY_MARGIN,-NODEBOUNDARY_MARGIN);
149 aPnts[2] = aPnts[1] + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0);
150 aPnts[3] = p + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0);
151 aPnts[4] = aPnts[3] + QPoint(0, h) + QPoint(0,-NODEBOUNDARY_MARGIN/2);
152 aPnts[5] = aPnts[4] + QPoint(-aCorner, aCorner) + QPoint(-NODEBOUNDARY_MARGIN,NODEBOUNDARY_MARGIN);
153 aPnts[6] = aPnts[5] + QPoint(-theW, 0) + QPoint(-NODEBOUNDARY_MARGIN,0);
154 aPnts[7] = p + QPoint(0, h) + QPoint(0,-NODEBOUNDARY_MARGIN/2);
158 void YACSPrs_LoopNode::setBracketColor(const QColor& theColor, bool theUpdate)
160 myBracketColor = theColor;
161 if ( canvas() && theUpdate )
163 canvas()->setChanged(boundingRect());
168 void YACSPrs_LoopNode::updatePorts()
170 bool aDisp = isVisible();
173 // ForLoop and WhileLoop nodes have only 1 input port.
174 // ForLoop : its name is 'nsteps' ,
175 // its type is 'int',
176 // its value is a number of iterations.
177 // WhileLoop : its name is 'condition' ,
178 // its type is 'bool',
179 // its value is a while condition, iteration process breaks when condition switch to false.
180 // ForLoop and WhileLoop nodes have no output ports, but in presentation we want to display a 'label' port with
181 // name 'Body'. This 'label' port connects with help of 'case' link to 'Master' hook
182 // of the node, which is set as an internal node of the loop.
184 bool withCreate = false;
185 if ( myPortList.isEmpty() ) withCreate = true;
187 QRect r = getBodyRect();
188 int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN;
189 if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH;
191 int ix = r.x() + PORT_MARGIN + 1;
192 int iy = r.y() + PORT_MARGIN;// + 1;
193 int ox = ix + aPRectWidth + 2*PORT_MARGIN;
194 int oy = r.y() + PORT_MARGIN;// + 1;
196 ForLoop* aFLoop = dynamic_cast<ForLoop*>( myEngine );
197 WhileLoop* aWLoop = 0;
200 { // create (and update)
201 // 'nsteps'/'condition' input port (name, type (and value) of the port will set in YACSPrs_InOutPort from port engine)
202 YACSPrs_InOutPort* anInPort = 0;
205 anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aFLoop->edGetNbOfTimesInputPort(),this);
208 aWLoop = dynamic_cast<WhileLoop*>( myEngine );
210 anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aWLoop->edGetConditionPort(),this);
215 anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT));
216 anInPort->setColor(nodeSubColor());
217 anInPort->setStoreColor(nodeSubColor());
218 myPortList.append(anInPort);
221 if ( aFLoop || aWLoop )
223 // get a set of internal loop nodes (in fact in ForLoop and WhileLoop we have only one internal node)
224 std::set<Node*> aNodes = aFLoop ? aFLoop->edGetDirectDescendants() : aWLoop->edGetDirectDescendants();
225 std::set<Node*>::iterator aNodesIter = aNodes.begin();
226 for (; aNodesIter != aNodes.end(); aNodesIter++)
227 { // output label port
228 YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aNodesIter,this);
229 anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT));
230 anOutPort->setColor(nodeSubColor().dark(140));
231 anOutPort->setStoreColor(nodeSubColor().dark(140));
232 myPortList.append(anOutPort);
233 myPortHeight += PORT_HEIGHT;
240 for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
242 YACSPrs_InOutPort* anInPort = dynamic_cast<YACSPrs_InOutPort*>( aPort );
245 if ( !anInPort->isGate() && anInPort->isInput() )
246 { // input data (i.e. not Gate) ports
247 anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
248 iy += PORT_HEIGHT+PORT_SPACE;
252 { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort => we not need to dynamic cast
253 aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
254 oy += PORT_HEIGHT+PORT_SPACE;
259 // can update gates only after body height will be defined
260 updateGates(withCreate);
265 int YACSPrs_LoopNode::maxWidth() const
267 return YACSPrs_ElementaryNode::maxWidth() - 4*HOOKPOINT_SIZE + ( ( 4*HOOKPOINT_SIZE > 3*TITLE_HEIGHT ) ? 4*HOOKPOINT_SIZE-3*TITLE_HEIGHT : 0 );
270 void YACSPrs_LoopNode::drawPort(QPainter& thePainter)
272 QRect r = getBodyRect();
273 r.setHeight(r.height()+1);
275 thePainter.drawRect(r);
276 int x0 = (r.left() + r.right())/2;
277 thePainter.drawLine(x0, r.top(), x0, r.bottom());
279 int aRRectWidth = (x0 - r.left() - 2*PORT_MARGIN - 2*PORT_SPACE)/3;
280 int aRRectWidthLabel = x0 - r.left() - 2*PORT_MARGIN;
281 QRect aTRect = getTitleRect();
282 int aXRnd = aTRect.width()*myXRnd/aRRectWidth;
283 int aXRndLabel = aTRect.width()*myXRnd/aRRectWidthLabel;
284 int aYRnd = aTRect.height()*myYRnd/PORT_HEIGHT;
287 for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
289 YACSPrs_InOutPort* anInPort = dynamic_cast<YACSPrs_InOutPort*>( aPort );
290 YACSPrs_LabelPort* anOutPort = dynamic_cast<YACSPrs_LabelPort*>( aPort );
291 if ( anInPort && !anInPort->isGate() )
292 aPort->draw(thePainter, aXRnd, aYRnd);
294 aPort->draw(thePainter, aXRndLabel, aYRnd);
298 void YACSPrs_LoopNode::drawFrame(QPainter& thePainter)
300 QRect aRect = getRect();
301 QRect aTRect = getTitleRect();
303 thePainter.drawRect(aRect);
305 QBrush savedB = thePainter.brush();
306 thePainter.setBrush(bracketColor());
308 int aCorner = 3*TITLE_HEIGHT/2;
309 QPoint aP1(aRect.x(), aRect.y());
310 QPoint aP2(aRect.x()+aCorner, aRect.y()-aCorner);
311 QPoint aP3(aRect.right()+aCorner,aRect.y()-aCorner);
312 QPoint aP4(aRect.right(), aRect.y());
313 QPoint aP5(aRect.x(), aRect.bottom());
314 QPoint aP6(aRect.x()-aCorner, aRect.bottom()+aCorner);
315 QPoint aP7(aRect.right()-aCorner,aRect.bottom()+aCorner);
316 QPoint aP8(aRect.right(), aRect.bottom());
317 QPointArray aPAUp(4);
318 aPAUp.putPoints(0, 4, aP1.x(),aP1.y(), aP2.x(),aP2.y(), aP3.x(),aP3.y(), aP4.x(),aP4.y());
319 thePainter.drawPolygon( aPAUp );
320 QPointArray aPADown(4);
321 aPADown.putPoints(0, 4, aP5.x(),aP5.y(), aP6.x(),aP6.y(), aP7.x(),aP7.y(), aP8.x(),aP8.y());
322 thePainter.drawPolygon( aPADown );
324 thePainter.setBrush(savedB);
327 QRect aTPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.y()-aCorner/2-aCorner/3,
328 2*aCorner/3, 2*aCorner/3);
329 thePainter.drawPixmap(aTPRect,myTopPixmap);
331 // draw bottom pixmap
332 QRect aBPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.bottom()+aCorner/2-aCorner/3,
333 2*aCorner/3, 2*aCorner/3);
334 thePainter.drawPixmap(aBPRect,myBottomPixmap);
336 // draw bounding nodes' polygon if node is currently selected
337 if ( isSelected() ) drawBoundary(thePainter,5);
340 QPoint YACSPrs_LoopNode::getConnectionMasterPoint()
342 QRect aRect = getRect();
343 return QPoint(aRect.left()+aRect.width()/2, aRect.bottom()+3*TITLE_HEIGHT/2);
346 bool YACSPrs_LoopNode::checkArea(double dx, double dy)
348 // for constraint nodes' moving inside the Bloc-->
349 if ( !myIsInBloc ) return true;
351 QRect aRect = boundingRect();
352 aRect.moveBy((int)dx, (int)dy);
353 aRect.setRect(aRect.x() - ( ( 2*HOOKPOINT_SIZE > 3*TITLE_HEIGHT/2 ) ? 2*HOOKPOINT_SIZE-3*TITLE_HEIGHT/2 : 0 ) + NODEBOUNDARY_MARGIN,
354 aRect.y(), maxWidth(), maxHeight());
355 if ( myArea.isValid() && myArea.contains(aRect) )