Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / prs / YACSPrs_ForEachLoopNode.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_ForEachLoopNode.h"
21 #include "YACSPrs_Def.h"
22
23 #include "SUIT_ResourceMgr.h"
24
25 #include <qpainter.h>
26
27 #include <ForEachLoop.hxx>
28
29 using namespace YACS::ENGINE;
30
31 /*!
32   Constructor
33 */
34 YACSPrs_ForEachLoopNode::YACSPrs_ForEachLoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::HMI::SubjectNode* theSNode ):
35   YACSPrs_LoopNode(theMgr, theCanvas, theSNode, false)
36 {
37   //updatePorts(); // will be called in moveBy(...) function
38   moveBy(3*TITLE_HEIGHT/2+NODEBOUNDARY_MARGIN, 3*TITLE_HEIGHT/2+NODEBOUNDARY_MARGIN);
39 }
40
41 /*!
42   Destructor
43 */
44 YACSPrs_ForEachLoopNode::~YACSPrs_ForEachLoopNode()
45 {
46 }
47
48 int YACSPrs_ForEachLoopNode::rtti() const
49 {
50   return 0;//YACSPrs_Canvas::Rtti_ForEachLoopNode;
51 }
52
53 void YACSPrs_ForEachLoopNode::updatePorts(bool theForce)
54 {
55   bool aDisp = isVisible();
56   if (aDisp) hide();
57   
58   bool withCreate = theForce;
59
60   if (theForce)
61   {
62     if ( isFullDMode() )
63       myPortHeight = 2*PORT_MARGIN;
64     else
65       myPortHeight = 0;
66
67     myPortList.setAutoDelete(true);
68     //myPortList.clear();
69
70     QPtrList<YACSPrs_LabelPort> aDeletePortList;
71     for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next())
72     {
73       if( YACSPrs_LabelPort* aLabelPort = dynamic_cast<YACSPrs_LabelPort*>( aPort ) )
74       {
75         aDeletePortList.append( aLabelPort );
76         withCreate = true;
77       }
78     }
79
80     for (YACSPrs_Port* aPort = aDeletePortList.first(); aPort; aPort = aDeletePortList.next())
81       myPortList.remove( aPort );
82   }
83
84   // ForEachLoop has 2 input ports and 2 output ports.
85   // Input ports : 1) 'nbBranches' port, its type is 'int', its value is a number of iterations;
86   //               2) 'SmplsCollection' port, its type is 'sequence' of elelmnts of the given type,
87   //                  it is a list of values of the given type.
88   // Output ports : 1) 'SmplPrt' port, its type is the given type, its value is a value of the
89   //                   list item, which is processed at the current moment.
90   //                2) 'Body' label port, this 'label' port connects with help of label link to 
91   //                   'Master' hook of the node, which is set as an internal node of the loop.
92
93   if ( myPortList.isEmpty() ) withCreate = true;
94
95   if ( isFullDMode() )
96   {
97     QRect r = getBodyRect();
98     int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN;
99     if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH;
100     
101     int ix = r.x() + PORT_MARGIN + 1;
102     int iy = r.y() + PORT_MARGIN;// + 1;
103     int ox = ix + aPRectWidth + 2*PORT_MARGIN;
104     int oy = r.y() + PORT_MARGIN;// + 1;
105     
106     if ( withCreate )
107     { // create (and update)
108       ForEachLoop* aFELoop = dynamic_cast<ForEachLoop*>( getEngine() );
109       if ( aFELoop )
110       { // create 2 input and 1 output ports
111         bool isBranchesPortCreated = false;
112         bool isSeqOfSamplesPortCreated = false;
113         bool isSamplePortCreated = false;
114         InputPort* aBranchesPort = aFELoop->edGetNbOfBranchesPort();
115         InputPort* aSeqOfSamplesPort = aFELoop->edGetSeqOfSamplesPort();
116         OutputPort* aSamplePort = aFELoop->edGetSamplePort();
117
118         for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next())
119         {
120           if( !aPort->getName().compare( QString( aBranchesPort->getName() ) ) )
121             isBranchesPortCreated = true;
122           else if( !aPort->getName().compare( QString( aSeqOfSamplesPort->getName() ) ) )
123             isSeqOfSamplesPortCreated = true;
124           else if( !aPort->getName().compare( QString( aSamplePort->getName() ) ) )
125             isSamplePortCreated = true;
126         }
127  
128         if( !isBranchesPortCreated )
129         {
130           // 'nbBranches'
131           YACSPrs_InOutPort* anIn1Port = new YACSPrs_InOutPort(myMgr,canvas(),aBranchesPort,this);
132           anIn1Port->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT));
133           anIn1Port->setColor(nodeSubColor());
134           anIn1Port->setStoreColor(nodeSubColor());
135           myPortList.append(anIn1Port);
136         }
137         if( !isSeqOfSamplesPortCreated )
138         {
139           // 'SmplsCollection'
140           YACSPrs_InOutPort* anIn2Port = new YACSPrs_InOutPort(myMgr,canvas(),aSeqOfSamplesPort,this);
141           anIn2Port->setPortRect(QRect(ix, iy+PORT_HEIGHT+PORT_SPACE, aPRectWidth, PORT_HEIGHT));
142           anIn2Port->setColor(nodeSubColor());
143           anIn2Port->setStoreColor(nodeSubColor());
144           myPortList.append(anIn2Port);
145         }
146         
147         myPortHeight += 2*PORT_HEIGHT;
148         myPortHeight += PORT_SPACE;
149         
150         if( !isSamplePortCreated )
151         {
152           // 'SmplPtr'
153           YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),aSamplePort,this);
154           anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT));
155           anOutPort->setColor(nodeSubColor());
156           anOutPort->setStoreColor(nodeSubColor());
157           myPortList.append(anOutPort);
158         }
159         
160         // get a set of internal loop nodes (in fact ForEachLoop has 2 internal nodes: _node and _initNode,
161         // but only _node was initialized in engine, in all examples _initNode is null)
162         std::list<Node*> aNodes = aFELoop->edGetDirectDescendants();
163         std::list<Node*>::iterator aNodesIter = aNodes.begin();
164         for (; aNodesIter != aNodes.end(); aNodesIter++)
165         { // output label port
166           YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aNodesIter,this);
167           anOutPort->setPortRect(QRect(ox, oy+PORT_HEIGHT+PORT_SPACE, aPRectWidth, PORT_HEIGHT));
168           anOutPort->setColor(nodeSubColor().dark(140));
169           anOutPort->setStoreColor(nodeSubColor().dark(140));
170           myPortList.append(anOutPort);
171         }
172       }
173     }
174     else
175     { // only update
176       YACSPrs_Port* aPort;
177       for (aPort = myPortList.first(); aPort; aPort = myPortList.next())
178       { 
179         YACSPrs_InOutPort* anIOPort = dynamic_cast<YACSPrs_InOutPort*>( aPort );
180         if ( anIOPort )
181         {
182           if ( !anIOPort->isGate() )
183           {  
184             if ( anIOPort->isInput() )
185             { // input data (i.e. not Gate) ports
186               anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
187               iy += PORT_HEIGHT+PORT_SPACE;
188             }
189             else
190             { // output data (i.e. not Gate) ports
191               anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
192               oy += PORT_HEIGHT+PORT_SPACE;
193             }
194           }
195         }
196         else
197         { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort (output!) => we not need to dynamic cast
198           aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea);
199           oy += PORT_HEIGHT+PORT_SPACE;
200         }
201       }
202     }
203   }
204   
205   // can update gates only after body height will be defined
206   bool createGates = withCreate;
207   for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next())
208   {
209     if( YACSPrs_InOutPort* anIOPort = dynamic_cast<YACSPrs_InOutPort*>( aPort ) )
210     {
211       if ( anIOPort->isGate() ) 
212       { // gate ports are already created - we should only update them
213         createGates = false;
214         break;
215       }
216     }
217   }
218   updateGates(createGates);
219
220   if (theForce && myPointMaster)
221   {
222     QPoint aPnt = getConnectionMasterPoint();
223     myPointMaster->setCoords(aPnt.x(), aPnt.y());
224   }
225
226   if (aDisp) show();
227 }
228
229 //! Increments time iteration.
230 /*!
231  *  Note : use not null argument of this function only for update original body node of ForEachLoop node.
232  *
233  * \param theEngine : the engine of clone node from which we have to update presentation of this node.
234  */
235 void YACSPrs_ForEachLoopNode::nextTimeIteration(YACS::ENGINE::Node* theEngine)
236 {
237   bool nullifyOnToActivate = false;
238   if ( !theEngine ) theEngine = getEngine();
239   else nullifyOnToActivate = true;
240   
241   if ( theEngine
242        &&
243        ( theEngine->getState() == YACS::READY /*|| theEngine->getEffectiveState() == YACS::READY*/
244          ||
245          ( nullifyOnToActivate && ( theEngine->getState() == YACS::TOACTIVATE || theEngine->getEffectiveState() == YACS::TOACTIVATE) ) ) )
246     setTimeIteration( 0. );
247   else if ( theEngine &&
248             theEngine->getState() != YACS::READY /*&& theEngine->getEffectiveState() != YACS::READY*/ &&
249             !isFinished() ) {
250     if ( ForEachLoop* aLoop = dynamic_cast<ForEachLoop*>( theEngine ) )
251       setTimeIteration( aLoop->getExecCurrentId()-1. >= 0 ? aLoop->getExecCurrentId()-1. : 0. );
252   }
253 }
254
255 //! Returns the progress bar percentage.
256 /*!
257  *  Note : use not null argument of this function only for update original body node of ForEachLoop node.
258  *
259  * \param theEngine : the engine of clone node from which we have to update presentation of this node.
260  */
261 int YACSPrs_ForEachLoopNode::getPercentage(YACS::ENGINE::Node* theEngine) const
262 {
263   if ( !theEngine ) theEngine = getEngine();
264   
265   if ( !theEngine ) return 0;
266
267   if ( theEngine->getState() == YACS::READY || /*theEngine->getEffectiveState() == YACS::READY ||*/
268        theEngine->getState() == YACS::TOLOAD || theEngine->getEffectiveState() == YACS::TOLOAD )
269     return 0;
270   if ( theEngine->getState() == YACS::DONE )
271     return 100;
272   if ( ForEachLoop* aLoop = dynamic_cast<ForEachLoop*>( theEngine ) ) {
273     SeqAnyInputPort* aCollection = dynamic_cast<SeqAnyInputPort*>( aLoop->edGetSeqOfSamplesPort() );
274     if ( aCollection && !aCollection->isEmpty() )
275       return (int)( 100. / aCollection->getNumberOfElements() * getTimeIteration() );
276   }
277   return 0;
278 }