]> SALOME platform Git repositories - modules/visu.git/blob - src/VISUGUI/VisuGUI_TimeAnimation.cxx
Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/visu.git] / src / VISUGUI / VisuGUI_TimeAnimation.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either 
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details. 
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //  File   : VisuGUI_TimeAnimation.cxx
21 //  Author : Vitaly SMETANNIKOV
22 //  Module : VISU
23
24 #include "VisuGUI_TimeAnimation.h"
25
26 #include "VisuGUI.h"
27 #include "VisuGUI_Tools.h"
28 #include "VisuGUI_ViewTools.h"
29 #include "VisuGUI_DeformedShapeDlg.h"
30 #include "VisuGUI_CutPlanesDlg.h"
31 #include "VisuGUI_CutLinesDlg.h"
32 #include "VisuGUI_Plot3DDlg.h"
33 #include "VisuGUI_VectorsDlg.h"
34 #include "VisuGUI_IsoSurfacesDlg.h"
35 #include "VisuGUI_StreamLinesDlg.h"
36 #include "VisuGUI_ScalarMapOnDeformedShapeDlg.h"
37 #include "VisuGUI_GaussPointsDlg.h"
38
39 #include "VISU_TimeAnimation.h"
40
41 #include "VISU_ScalarMap_i.hh"
42 #include "VISU_IsoSurfaces_i.hh"
43 #include "VISU_DeformedShape_i.hh"
44 #include "VISU_CutPlanes_i.hh"
45 #include "VISU_Plot3D_i.hh"
46 #include "VISU_CutLines_i.hh"
47 #include "VISU_Vectors_i.hh"
48 #include "VISU_StreamLines_i.hh"
49 #include "VISU_ScalarMapOnDeformedShape_i.hh"
50 #include "VISU_GaussPoints_i.hh"
51
52 #include "VISU_ViewManager_i.hh"
53
54 #include "VISU_ScalarBarActor.hxx"
55 #include "VISU_Actor.h"
56
57 #include "SalomeApp_Study.h"
58 #include "LightApp_Application.h"
59
60 #include "SVTK_ViewWindow.h"
61
62 #include "SUIT_OverrideCursor.h"
63 #include "SUIT_MessageBox.h"
64 #include "SUIT_ResourceMgr.h"
65 #include "SUIT_Session.h"
66 #include "SUIT_Desktop.h"
67 #include "SUIT_FileDlg.h"
68
69 #include <vtkRenderer.h>
70 #include <vtkMapper.h>
71
72 #include <qhbox.h>
73 #include <qgrid.h>
74 #include <qimage.h>
75 #include <qlayout.h>
76 #include <qslider.h>
77 #include <qthread.h>
78 #include <qlistbox.h>
79 #include <qwt_wheel.h>
80 #include <qhgroupbox.h>
81 #include <qlcdnumber.h>
82 #include <qvgroupbox.h>
83
84 #define  MAXVAL 1e10
85
86 ArrangeDlg::ArrangeDlg(QWidget* theParent, VISU_TimeAnimation* theAnimator)
87   : QDialog(theParent, "ArrangeDlg", true,
88             WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
89     myAnimator(theAnimator),
90     myViewWindow(theAnimator->getViewer())
91 {
92   myCurrent = 0;
93   init();
94   QStringList aFieldNames;
95   // Find names of fields
96   for (int i = 0; i < myAnimator->getNbFields(); i++) {
97     aFieldNames.append(VISU::getValue(myAnimator->getFieldData(i).myField, "myName"));
98     Offset aOffs;
99     aOffs.myOffset[0] = myAnimator->getFieldData(i).myOffset[0];
100     aOffs.myOffset[1] = myAnimator->getFieldData(i).myOffset[1];
101     aOffs.myOffset[2] = myAnimator->getFieldData(i).myOffset[2];
102     myOffsets.append(aOffs);
103   }
104   myFieldLst->insertStringList(aFieldNames);
105   myFieldLst->setSelected(0, true);
106 }
107
108 ArrangeDlg::ArrangeDlg(QWidget* theParent, SVTK_ViewWindow* theViewWindow)
109   : QDialog(theParent, "ArrangeDlg", true, WStyle_Customize |
110             WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
111     myAnimator(NULL), myViewWindow(theViewWindow)
112 {
113   myCurrent = 0;
114   init();
115   QStringList aPrsNames;
116   vtkActor* anActor;
117   vtkActorCollection *anActColl = myViewWindow->getRenderer()->GetActors();
118   for (anActColl->InitTraversal(); (anActor = anActColl->GetNextActor()) != NULL;) {
119     VISU_Actor* anVISUActor = dynamic_cast<VISU_Actor*>(anActor);
120     if (anVISUActor)
121       if (anVISUActor->GetVisibility() != 0) {
122         VISU::Prs3d_i* aPrs = anVISUActor->GetPrs3d();
123         if (aPrs) {
124           if (!myPrsMap.contains(aPrs)) {
125             SALOMEDS::SObject_var aSObject = aPrs->GetSObject();
126             if(!aSObject->_is_nil()){
127               SALOMEDS::GenericAttribute_var anAttr;
128               if (aSObject->FindAttribute(anAttr, "AttributeName")) {
129                 SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
130                 string aNam = aName->Value();
131                 QString strIn(aNam.c_str());
132                 aPrsNames.append(strIn);
133                 myPrsMap[aPrs] = myOffsets.count();
134                 Offset aOffs;
135                 anVISUActor->GetPosition(aOffs.myOffset);
136                 myOffsets.append(aOffs);
137               }
138             }
139           }
140         }
141       }
142   }
143   myFieldLst->insertStringList(aPrsNames);
144   myFieldLst->setSelected(0, true);
145 }
146
147 void ArrangeDlg::init()
148 {
149   setCaption("Arrange Presentations");
150   setSizeGripEnabled( TRUE );
151
152   QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 6);
153   aMainLayout->setSpacing(5);
154
155   QButtonGroup* aBtnGrp = new QButtonGroup(2, Qt::Horizontal, this);
156   aBtnGrp->setExclusive(true);
157   aMainLayout->addWidget(aBtnGrp);
158
159   QRadioButton* aAutoBtn = new QRadioButton("Auto", aBtnGrp);
160   aBtnGrp->insert(aAutoBtn, AutoMode);
161
162   QRadioButton* aManualBtn = new QRadioButton("Manual", aBtnGrp);
163   aBtnGrp->insert(aManualBtn, ManualMode);
164   aBtnGrp->setButton(AutoMode);
165
166   myStackWgt = new QWidgetStack(this);
167   aMainLayout->addWidget(myStackWgt);
168
169   //  AUTO Pane
170   QVBox* aAutoPane = new QVBox(myStackWgt);
171   aAutoPane->setSpacing(5);
172   // Axis Group
173   myAxisGrp = new QButtonGroup(3, Qt::Horizontal,"Axis", aAutoPane);
174
175   QRadioButton* aXBtn = new QRadioButton("X",myAxisGrp );
176   myAxisGrp->insert(aXBtn, XAxis);
177
178   QRadioButton* aYBtn = new QRadioButton("Y",myAxisGrp );
179   myAxisGrp->insert(aYBtn, YAxis);
180
181   QRadioButton* aZBtn = new QRadioButton("Z",myAxisGrp );
182   myAxisGrp->insert(aZBtn, ZAxis);
183
184   myAxisGrp->setButton(XAxis);
185
186   //Distance Input
187   QHBox* aDistPane = new QHBox(aAutoPane);
188   aDistPane->setSpacing(5);
189   new QLabel("Relative Distance", aDistPane);
190   myDistVal = new QtxDblSpinBox (-10,10, 0.5, aDistPane);
191   myDistVal->setValue(1);
192
193   myStackWgt->addWidget(aAutoPane, AutoMode);
194
195   // Manual Pane
196   QHBox* aManualPane = new QHBox(myStackWgt);
197   aManualPane->setSpacing(10);
198
199   myFieldLst = new QListBox(aManualPane);
200   connect( myFieldLst, SIGNAL( highlighted(int) ),
201            this, SLOT( onFieldChange(int) ) );
202
203   QGrid* aCoordPane = new QGrid(2, aManualPane);
204   aCoordPane->setSpacing(5);
205
206   new QLabel("X", aCoordPane);
207   myCoord[0] = new QtxDblSpinBox(aCoordPane);
208   myCoord[0]->setRange(-MAXVAL, MAXVAL);
209
210   new QLabel("Y", aCoordPane);
211   myCoord[1] = new QtxDblSpinBox(aCoordPane);
212   myCoord[1]->setRange(-MAXVAL, MAXVAL);
213
214   new QLabel("Z", aCoordPane);
215   myCoord[2] = new QtxDblSpinBox(aCoordPane);
216   myCoord[2]->setRange(-MAXVAL, MAXVAL);
217
218   myStackWgt->addWidget(aManualPane, ManualMode);
219
220   myStackWgt->raiseWidget(AutoMode);
221
222   connect(aBtnGrp, SIGNAL(clicked(int)), myStackWgt, SLOT(raiseWidget(int)) );
223
224   SUIT_Study* aSUITStudy = myViewWindow->getViewManager()->study();
225   SalomeApp_Study* anAppStudy = dynamic_cast<SalomeApp_Study*>(aSUITStudy);
226   _PTR(Study) aCStudy = VISU::GetCStudy(anAppStudy);
227   if (!myAnimator && !aCStudy->GetProperties()->IsLocked()) {
228     mySaveChk = new QCheckBox ("Save to presentation", this);
229     mySaveChk->setChecked(false);
230     aMainLayout->addWidget(mySaveChk);
231   } else {
232     mySaveChk = 0;
233   }
234
235   // Common buttons ===========================================================
236   QGroupBox* GroupButtons = new QGroupBox( this, "GroupButtons" );
237   GroupButtons->setColumnLayout(0, Qt::Vertical );
238   GroupButtons->layout()->setSpacing( 0 );
239   GroupButtons->layout()->setMargin( 0 );
240   QGridLayout* GroupButtonsLayout = new QGridLayout( GroupButtons->layout() );
241   GroupButtonsLayout->setAlignment( Qt::AlignTop );
242   GroupButtonsLayout->setSpacing( 6 );
243   GroupButtonsLayout->setMargin( 11 );
244
245   QPushButton* buttonOk = new QPushButton( tr( "&OK" ), GroupButtons, "buttonOk" );
246   buttonOk->setAutoDefault( TRUE );
247   buttonOk->setDefault( TRUE );
248   GroupButtonsLayout->addWidget( buttonOk, 0, 0 );
249   GroupButtonsLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, 1 );
250
251   QPushButton* buttonCancel = new QPushButton( tr( "&Cancel" ) , GroupButtons, "buttonCancel" );
252   buttonCancel->setAutoDefault( TRUE );
253   GroupButtonsLayout->addWidget( buttonCancel, 0, 2 );
254
255   aMainLayout->addWidget( GroupButtons );
256
257   connect( buttonOk,     SIGNAL( clicked() ),      this, SLOT( accept() ) );
258   connect( buttonCancel, SIGNAL( clicked() ),      this, SLOT( reject() ) );
259 }
260
261 void ArrangeDlg::accept()
262 {
263   if (myAnimator != NULL) {
264     acceptAnimation();
265   } else {
266     acceptViewWindow();
267   }
268   QDialog::accept();
269 }
270
271 void ArrangeDlg::onFieldChange(int theCurrent)
272 {
273   if (myCurrent != theCurrent) {
274     Offset& aOffs = myOffsets[myCurrent];
275     aOffs.myOffset[0] = myCoord[0]->value();
276     aOffs.myOffset[1] = myCoord[1]->value();
277     aOffs.myOffset[2] = myCoord[2]->value();
278   }
279   myCurrent = theCurrent;
280   const Offset& aNewOffs = myOffsets[myCurrent];
281   myCoord[0]->setValue(aNewOffs.myOffset[0]);
282   myCoord[1]->setValue(aNewOffs.myOffset[1]);
283   myCoord[2]->setValue(aNewOffs.myOffset[2]);
284 }
285
286 void ArrangeDlg::acceptAnimation()
287 {
288   if (getMode() == ManualMode) {
289     // Save from GUI
290     Offset& aOffs = myOffsets[myCurrent];
291     aOffs.myOffset[0] = myCoord[0]->value();
292     aOffs.myOffset[1] = myCoord[1]->value();
293     aOffs.myOffset[2] = myCoord[2]->value();
294
295     for (int i = 0; i < myAnimator->getNbFields(); i++) {
296       Offset aOffs = myOffsets[i];
297       myAnimator->getFieldData(i).myOffset[0] = aOffs.myOffset[0];
298       myAnimator->getFieldData(i).myOffset[1] = aOffs.myOffset[1];
299       myAnimator->getFieldData(i).myOffset[2] = aOffs.myOffset[2];
300     }
301   } else {
302     QApplication::setOverrideCursor( Qt::waitCursor );
303     FieldData& aData = myAnimator->getFieldData(myFieldLst->currentItem());
304     if (aData.myPrs.empty())
305       myAnimator->generatePresentations(myFieldLst->currentItem());
306     vtkFloatingPointType aBounds[6];
307     aData.myPrs[0]->GetBounds(aBounds);
308     vtkFloatingPointType aDist = 0;
309     int aAxis = getAxis();
310     switch (aAxis) {
311     case XAxis:
312       aDist = fabs(aBounds[1] - aBounds[0]);
313       break;
314     case YAxis:
315       aDist = fabs(aBounds[3] - aBounds[2]);
316       break;
317     case ZAxis:
318       aDist = fabs(aBounds[5] - aBounds[4]);
319     }
320
321     vtkFloatingPointType dx = fabs(aBounds[1] - aBounds[0]);
322     vtkFloatingPointType dy = fabs(aBounds[3] - aBounds[2]);
323     vtkFloatingPointType dz = fabs(aBounds[5] - aBounds[4]);
324     vtkFloatingPointType max = (dx > dy) ? dx : dy;
325     max = (dz > max) ? dz : max;
326     max /= 100.0;
327
328     if (aDist < max) {
329       // set base distance between centers of bounding boxes
330       // to minimal (but big enough) size of current bounding box
331       if (dx < max) dx = FLT_MAX;
332       if (dy < max) dy = FLT_MAX;
333       if (dz < max) dz = FLT_MAX;
334
335       aDist = (dx < dy) ? dx : dy;
336       aDist = (dz < aDist) ? dz : aDist;
337     }
338     aDist = aDist * getDistance();
339     for (int i = 0; i < myAnimator->getNbFields(); i++) {
340       myAnimator->getFieldData(i).myOffset[0] = 0;
341       myAnimator->getFieldData(i).myOffset[1] = 0;
342       myAnimator->getFieldData(i).myOffset[2] = 0;
343       myAnimator->getFieldData(i).myOffset[aAxis] = aDist * i;
344     }
345
346     QApplication::restoreOverrideCursor();
347   }
348 }
349
350 void ArrangeDlg::acceptViewWindow()
351 {
352   if (getMode() == ManualMode) {
353     // Save from GUI
354     Offset& aOffs = myOffsets[myCurrent];
355     aOffs.myOffset[0] = myCoord[0]->value();
356     aOffs.myOffset[1] = myCoord[1]->value();
357     aOffs.myOffset[2] = myCoord[2]->value();
358
359     QMap<VISU::Prs3d_i*, int>::Iterator it;
360     for (it = myPrsMap.begin(); it != myPrsMap.end(); ++it) {
361       VISU::Prs3d_i* aPrs = it.key();
362       Offset& aOffs = myOffsets[it.data()];
363       if (VISU_Actor* anActor = VISU::GetActor(aPrs, myViewWindow))
364         anActor->SetPosition(aOffs.myOffset);
365       if (mySaveChk)
366         if (mySaveChk->isChecked())
367           aPrs->SetOffset(aOffs.myOffset[0],aOffs.myOffset[1],aOffs.myOffset[2]);
368     }
369   } else {
370     vtkFloatingPointType aDist = 0;
371     vtkFloatingPointType aShift = 0;
372     vtkFloatingPointType aPrevDist = 0;
373     vtkFloatingPointType aPrevShift = 0;
374     int i;
375     QMap<VISU::Prs3d_i*, int>::Iterator it;
376     for (it = myPrsMap.begin(), i = 0; it != myPrsMap.end(); ++it, i++) {
377       VISU::Prs3d_i* aPrs = it.key();
378       if (VISU_Actor* aActor = VISU::GetActor(aPrs, myViewWindow)) {
379         int aAxis = getAxis();
380
381         vtkFloatingPointType aZeroOffset[3];
382         aZeroOffset[0] = aZeroOffset[1] = aZeroOffset[2] = 0;
383         aActor->SetPosition(aZeroOffset);
384         aActor->GetMapper()->Update();
385
386         vtkFloatingPointType aBounds[6];
387         aActor->GetBounds(aBounds);
388         switch (aAxis) {
389         case XAxis:
390           aDist = fabs(aBounds[1] - aBounds[0]);
391           break;
392         case YAxis:
393           aDist = fabs(aBounds[3] - aBounds[2]);
394           break;
395         case ZAxis:
396           aDist = fabs(aBounds[5] - aBounds[4]);
397         }
398         vtkFloatingPointType aOffset[3];
399         aOffset[0] = aOffset[1] = aOffset[2] = 0;
400         aOffset[aAxis] =
401           (aBounds[2*aAxis+1] < aBounds[2*aAxis]) ? -aBounds[2*aAxis+1] : -aBounds[2*aAxis];
402
403         if (i > 0) {
404           vtkFloatingPointType aCCDist = (aDist + aPrevDist) / 2.0;
405
406           vtkFloatingPointType dx = fabs(aBounds[1] - aBounds[0]);
407           vtkFloatingPointType dy = fabs(aBounds[3] - aBounds[2]);
408           vtkFloatingPointType dz = fabs(aBounds[5] - aBounds[4]);
409           vtkFloatingPointType max = (dx > dy) ? dx : dy;
410           max = (dz > max) ? dz : max;
411           max /= 100.0;
412
413           if (aCCDist < max) {
414             // set base distance between centers of bounding boxes
415             // to minimal (but big enough) size of current bounding box
416             if (dx < max) dx = FLT_MAX;
417             if (dy < max) dy = FLT_MAX;
418             if (dz < max) dz = FLT_MAX;
419
420             aCCDist = (dx < dy) ? dx : dy;
421             aCCDist = (dz < aCCDist) ? dz : aCCDist;
422           }
423
424           //-------------------------------->
425           //             aShift
426           //                                 aDist / 2
427           //                                 <-->
428           //            .--------------.     .------.
429           //----------->|              |     |      |
430           // aPrevShift '--------------'     '------'
431           //            <------>
432           //            aPrevDist / 2
433           //
434           //                    <--------------->
435           //                    (aDist + aPrevDist) * getDistance() / 2
436
437           aShift = aPrevShift + aPrevDist/2.0 + aCCDist*getDistance() - aDist/2.0;
438         }
439
440         aOffset[aAxis] += aShift;
441         aActor->SetPosition(aOffset);
442         if (mySaveChk)
443           if (mySaveChk->isChecked())
444             aPrs->SetOffset(aOffset[0],aOffset[1],aOffset[2]);
445
446         aPrevDist = aDist;
447         aPrevShift = aShift;
448       }
449     }
450   }
451   myViewWindow->getRenderer()->ResetCameraClippingRange();
452   myViewWindow->Repaint();
453 }
454
455
456 //------------------------------------------------------------------------
457 //------------------------------------------------------------------------
458 //------------------------------------------------------------------------
459 SetupDlg::SetupDlg (QWidget* theParent,
460                     VisuGUI* theModule, 
461                     VISU_TimeAnimation* theAnimator) :
462   QDialog(theParent, 
463           "SetupDlg", 
464           true, 
465           WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
466   myAnimator(theAnimator),
467   myModule(theModule)
468 {
469   setCaption("Setup Animation");
470   setSizeGripEnabled( TRUE );
471
472   QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 6);
473   aMainLayout->setSpacing(5);
474
475   // Range of time stamps
476   QFrame* aRangeGrp = new QFrame(this);
477   QGridLayout* aRangeLayout = new QGridLayout( aRangeGrp );
478   aRangeLayout->setSpacing( 6 );
479   aRangeLayout->setMargin( 11 );
480   aRangeGrp->setFrameStyle(QFrame::Box | QFrame::Raised);
481
482   myUseRangeChk = new QCheckBox("Use range of time stamps", aRangeGrp);
483   aRangeLayout->addMultiCellWidget(myUseRangeChk, 0, 0, 0, 3);
484   myUseRangeChk->setChecked(myAnimator->isRangeDefined());
485
486   double aMaxTime = myAnimator->getMaxTime();
487   double aMinTime = myAnimator->getMinTime();
488   double aStep = (aMaxTime - aMinTime) / (myAnimator->getFieldData(0).myNbTimes - 1);
489
490   QLabel* aMinLbl = new QLabel("From", aRangeGrp);
491   aMinLbl->setEnabled(myUseRangeChk->isChecked());
492   aRangeLayout->addWidget(aMinLbl, 1, 0);
493   myMinVal = new QtxDblSpinBox( aMinTime, aMaxTime, aStep, aRangeGrp );
494   myMinVal->setEnabled(myUseRangeChk->isChecked());
495   if (myUseRangeChk->isChecked())
496     myMinVal->setValue( myAnimator->getMinRange() );
497   else
498     myMinVal->setValue( aMinTime );
499
500   connect(myMinVal, SIGNAL( valueChanged(double)),
501           this, SLOT( onMinValue(double) ));
502   aRangeLayout->addWidget(myMinVal, 1, 1);
503
504   QLabel* aMaxLbl = new QLabel("To", aRangeGrp);
505   aMaxLbl->setEnabled(myUseRangeChk->isChecked());
506   aRangeLayout->addWidget(aMaxLbl, 1, 2);
507   myMaxVal = new QtxDblSpinBox( aMinTime, aMaxTime, aStep, aRangeGrp );
508   myMaxVal->setEnabled(myUseRangeChk->isChecked());
509   if (myUseRangeChk->isChecked())
510     myMaxVal->setValue( myAnimator->getMaxRange() );
511   else
512     myMaxVal->setValue( aMaxTime );
513
514   connect(myMaxVal, SIGNAL( valueChanged(double)),
515           this, SLOT( onMaxValue(double) ));
516   aRangeLayout->addWidget(myMaxVal, 1, 3);
517
518   connect(myUseRangeChk, SIGNAL( toggled(bool)),
519           aMinLbl, SLOT( setEnabled(bool) ));
520   connect(myUseRangeChk, SIGNAL( toggled(bool)),
521           aMaxLbl, SLOT( setEnabled(bool) ));
522   connect(myUseRangeChk, SIGNAL( toggled(bool)),
523           this, SLOT( onRangeCheck(bool) ));
524
525   aMainLayout->addWidget(aRangeGrp);
526
527
528   // Fields and Properties
529   QHBox* aPropFrame = new QHBox(this);
530   aPropFrame->setSpacing(5);
531
532   QVGroupBox* aNamesBox = new QVGroupBox("Fields",aPropFrame);
533   myFieldLst = new QListBox(aNamesBox);
534   QStringList aFieldNames;
535   // Find names of fields
536   for (int i = 0; i < myAnimator->getNbFields(); i++) {
537     _PTR(SObject) aSO = myAnimator->getFieldData(i).myField;
538     aFieldNames.append(VISU::getValue(aSO, "myName"));
539   }
540   myFieldLst->insertStringList(aFieldNames);
541   myFieldLst->setSelected(0, true);
542   connect( myFieldLst, SIGNAL( highlighted(int) ),
543            this, SLOT( onFieldChange(int) ) );
544
545
546   QVBox* aSetupBox = new QVBox(aPropFrame);
547   aSetupBox->setSpacing(5);
548
549   QVGroupBox* aPropBox = new QVGroupBox("Properties", aSetupBox);
550   //QVGroupBox* aPropBox = new QVGroupBox("Properties", aPropFrame);
551   myTypeCombo = new QComboBox(aPropBox);
552   connect( myTypeCombo, SIGNAL( activated(int) ),
553            this, SLOT( onTypeChanged(int) ) );
554
555   //  QPushButton* aBarBtn = new QPushButton("Scalar Bar...", aPropBox);
556   //connect( aBarBtn, SIGNAL( clicked() ),
557   //       this, SLOT( onScalarBarDlg() ) );
558
559   myPropBtn = new QPushButton("Properties...", aPropBox);
560   //  myPropBtn->setEnabled(myAnimator->getFieldData(0).myPrsType != VISU::TSCALARMAP);
561   connect( myPropBtn, SIGNAL( clicked() ),
562            this, SLOT( onPreferencesDlg() ) );
563
564   if (myAnimator->getNbFields() > 1) {
565     myArrangeBtn = new QPushButton("Arrange...", aSetupBox);
566     connect( myArrangeBtn, SIGNAL( clicked() ), this, SLOT( onArrangeDlg() ) );
567   }
568   onFieldChange(0);
569   aMainLayout->addWidget(aPropFrame);
570
571   QHBox* aBtnBox = new QHBox(this);
572   QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox->layout());
573   aBtnLayout->addStretch();
574
575   QPushButton* aCloseBtn = new QPushButton(tr("BUT_OK"), aBtnBox);
576   connect(aCloseBtn, SIGNAL(clicked()), this, SLOT(close()));
577
578   aMainLayout->addWidget(aBtnBox);
579 }
580
581 //------------------------------------------------------------------------
582 enum PrsComboItem {
583   TSCALARMAP_ITEM     = 0, // VISU::TSCALARMAP
584   TISOSURFACE_ITEM    = 1, // VISU::TISOSURFACE
585   TCUTPLANES_ITEM     = 2, // VISU::TCUTPLANES
586   TCUTLINES_ITEM      = 3, // VISU::TCUTLINES
587   TPLOT3D_ITEM        = 4, // VISU::TPLOT3D
588   TDEFORMEDSHAPE_ITEM = 5, // VISU::TDEFORMEDSHAPE
589   TVECTORS_ITEM       = 6, // VISU::TVECTORS
590   TSTREAMLINES_ITEM   = 7, // VISU::TSTREAMLINES
591   TGAUSSPOINTS_ITEM   = 8, // VISU::TGAUSSPOINTS
592   TSCALARMAPONDEFORMEDSHAPE_ITEM = 9 // VISU::TSCALARMAPONDEFORMEDSHAPE
593 };
594
595 //------------------------------------------------------------------------
596 void SetupDlg::onFieldChange (int theIndex)
597 {
598   FieldData& aData = myAnimator->getFieldData(theIndex);
599   myTypeCombo->clear();
600   myTypeId2ComboId.clear();
601   myComboId2TypeId.clear();
602
603   // ATTENTION: append items in the same order like it is done in the PrsComboItem enumeration
604   myTypeCombo->insertItem("Scalar Map");   // item 0
605   myTypeId2ComboId[TSCALARMAP_ITEM] = myComboId2TypeId.size();
606   myComboId2TypeId.push_back(TSCALARMAP_ITEM);;
607
608   myTypeCombo->insertItem("Iso Surfaces"); // item 1
609   myTypeId2ComboId[TISOSURFACE_ITEM] = myComboId2TypeId.size();
610   myComboId2TypeId.push_back(TISOSURFACE_ITEM);;
611
612   myTypeCombo->insertItem("Cut Planes");   // item 2
613   myTypeId2ComboId[TCUTPLANES_ITEM] = myComboId2TypeId.size();
614   myComboId2TypeId.push_back(TCUTPLANES_ITEM);;
615
616   myTypeCombo->insertItem("Cut Lines");   // item 3
617   myTypeId2ComboId[TCUTLINES_ITEM] = myComboId2TypeId.size();
618   myComboId2TypeId.push_back(TCUTLINES_ITEM);;
619
620   myTypeCombo->insertItem("Plot 3D");      // item 4
621   myTypeId2ComboId[TPLOT3D_ITEM] = myComboId2TypeId.size();
622   myComboId2TypeId.push_back(TPLOT3D_ITEM);;
623
624   _PTR(SObject) aSObject = aData.myField;
625   long aNumComp = VISU::getValue(aSObject, "myNumComponent").toLong();
626   if (aNumComp > 1) {
627     myTypeCombo->insertItem("Deformed Shape"); // item 5
628     myTypeId2ComboId[TDEFORMEDSHAPE_ITEM] = myComboId2TypeId.size();
629     myComboId2TypeId.push_back(TDEFORMEDSHAPE_ITEM);;
630
631     myTypeCombo->insertItem("Vectors");        // item 6
632     myTypeId2ComboId[TVECTORS_ITEM] = myComboId2TypeId.size();
633     myComboId2TypeId.push_back(TVECTORS_ITEM);;
634
635     myTypeCombo->insertItem("Stream Lines");   // item 7
636     myTypeId2ComboId[TSTREAMLINES_ITEM] = myComboId2TypeId.size();
637     myComboId2TypeId.push_back(TSTREAMLINES_ITEM);;
638
639     myTypeCombo->insertItem("Scalar map on Deformed shape");   // item 9
640     myTypeId2ComboId[TSCALARMAPONDEFORMEDSHAPE_ITEM] = myComboId2TypeId.size();
641     myComboId2TypeId.push_back(TSCALARMAPONDEFORMEDSHAPE_ITEM);;
642   }
643
644   long anEntityId = VISU::getValue(aSObject, "myEntityId").toLong();
645   if(anEntityId == VISU::CELL){
646     myTypeCombo->insertItem("Gauss Points");   // item 8
647     myTypeId2ComboId[TGAUSSPOINTS_ITEM] = myComboId2TypeId.size();
648     myComboId2TypeId.push_back(TGAUSSPOINTS_ITEM);;
649   }
650
651   switch (aData.myPrsType) {
652   case VISU::TSCALARMAP: //Scalar Map
653     myTypeCombo->setCurrentItem(myTypeId2ComboId[TSCALARMAP_ITEM]);
654     break;
655   case VISU::TISOSURFACE: //Iso Surfaces
656     myTypeCombo->setCurrentItem(myTypeId2ComboId[TISOSURFACE_ITEM]);
657     break;
658   case VISU::TCUTPLANES: //Cut Planes
659     myTypeCombo->setCurrentItem(myTypeId2ComboId[TCUTPLANES_ITEM]);
660     break;
661   case VISU::TCUTLINES: //Cut Lines
662     myTypeCombo->setCurrentItem(myTypeId2ComboId[TCUTLINES_ITEM]);
663     break;
664   case VISU::TPLOT3D: //Plot 3D
665     myTypeCombo->setCurrentItem(myTypeId2ComboId[TPLOT3D_ITEM]);
666     break;
667   case VISU::TDEFORMEDSHAPE: //Deformed Shape
668     myTypeCombo->setCurrentItem(myTypeId2ComboId[TDEFORMEDSHAPE_ITEM]);
669     break;
670   case VISU::TSCALARMAPONDEFORMEDSHAPE: //Scalar Map on Deformed Shape
671     myTypeCombo->setCurrentItem(myTypeId2ComboId[TSCALARMAPONDEFORMEDSHAPE_ITEM]);
672     break;
673   case VISU::TVECTORS: //Vectors
674     myTypeCombo->setCurrentItem(myTypeId2ComboId[TVECTORS_ITEM]);
675     break;
676   case VISU::TSTREAMLINES: //Stream Lines
677     myTypeCombo->setCurrentItem(myTypeId2ComboId[TSTREAMLINES_ITEM]);
678     break;
679   case VISU::TGAUSSPOINTS: //Gauss Points
680     myTypeCombo->setCurrentItem(myTypeId2ComboId[TGAUSSPOINTS_ITEM]);
681     break;
682   }
683   //myPropBtn->setEnabled(aData.myPrsType != VISU::TSCALARMAP);
684 }
685
686 //------------------------------------------------------------------------
687 void SetupDlg::onTypeChanged (int theIndex)
688 {
689   FieldData& aData = myAnimator->getFieldData(myFieldLst->currentItem());
690   int aType = myComboId2TypeId[theIndex];
691   switch (aType) {
692   case TSCALARMAP_ITEM: //Scalar Map
693     aData.myPrsType = VISU::TSCALARMAP;
694     break;
695   case TISOSURFACE_ITEM: //Iso Surfaces
696     aData.myPrsType = VISU::TISOSURFACE;
697     break;
698   case TCUTPLANES_ITEM: //Cut Planes
699     aData.myPrsType = VISU::TCUTPLANES;
700     break;
701   case TCUTLINES_ITEM: //Cut Lines
702     aData.myPrsType = VISU::TCUTLINES;
703     break;
704   case TPLOT3D_ITEM: //Plot 3D
705     aData.myPrsType = VISU::TPLOT3D;
706     break;
707   case TDEFORMEDSHAPE_ITEM: //Deformed Shape
708     aData.myPrsType = VISU::TDEFORMEDSHAPE;
709     break;
710   case TSCALARMAPONDEFORMEDSHAPE_ITEM: //Scalar Map on Deformed Shape
711     aData.myPrsType = VISU::TSCALARMAPONDEFORMEDSHAPE;
712     break;
713   case TVECTORS_ITEM: //Vectors
714     aData.myPrsType = VISU::TVECTORS;
715     break;
716   case TSTREAMLINES_ITEM: //Stream Lines
717     aData.myPrsType = VISU::TSTREAMLINES;
718     break;
719   case TGAUSSPOINTS_ITEM: //Gauss Points
720     aData.myPrsType = VISU::TGAUSSPOINTS;
721     break;
722   }
723   myAnimator->clearData(aData);
724   //myPropBtn->setEnabled(aData.myPrsType != VISU::TSCALARMAP);
725   //myAnimator->generatePresentations(myFieldLst->currentItem());
726 }
727
728
729 //------------------------------------------------------------------------
730 namespace
731 {
732   template<class TPrs3d, class TDialog>
733   void
734   EditPrs(VisuGUI* theModule,
735           FieldData& theData)
736   {
737     TDialog* aDlg = new TDialog(theModule);
738     aDlg->initFromPrsObject(dynamic_cast<TPrs3d*>(theData.myPrs[0]));
739     if (aDlg->exec())
740       for (int i = 0; i < theData.myNbFrames; i++)
741         aDlg->storeToPrsObject(dynamic_cast<TPrs3d*>(theData.myPrs[i]));
742     delete aDlg;
743   }
744 }
745
746
747 void SetupDlg::onPreferencesDlg()
748 {
749   SUIT_OverrideCursor c;
750   FieldData& aData = myAnimator->getFieldData(myFieldLst->currentItem());
751   if (aData.myPrs.empty())
752     myAnimator->generatePresentations(myFieldLst->currentItem());
753
754   if(!aData.myNbFrames || !aData.myPrs[0]){
755     QApplication::restoreOverrideCursor();
756     SUIT_MessageBox::warn1(this,
757                            tr("ERROR"),
758                            VisuGUI_TimeAnimationDlg::tr("MSG_NO_ANIMATIONDATA"),
759                            tr("&OK"));
760     return;
761   }
762
763   int aType = myComboId2TypeId[myTypeCombo->currentItem()];
764   switch (aType) {
765   case TSCALARMAP_ITEM: //Scalar Map
766     c.suspend();
767     EditPrs<VISU::ScalarMap_i,VisuGUI_ScalarBarDlg>(myModule,aData);
768     break;
769   case TISOSURFACE_ITEM: //Iso Surfaces
770     c.suspend();
771     EditPrs<VISU::IsoSurfaces_i,VisuGUI_IsoSurfacesDlg>(myModule,aData);
772     break;
773   case TCUTPLANES_ITEM: //Cut Planes
774     c.suspend();
775     EditPrs<VISU::CutPlanes_i,VisuGUI_CutPlanesDlg>(myModule,aData);
776     break;
777   case TCUTLINES_ITEM: //Cut Lines
778     c.suspend();
779     EditPrs<VISU::CutLines_i,VisuGUI_CutLinesDlg>(myModule,aData);
780     break;
781   case TPLOT3D_ITEM: //Plot 3D
782     c.suspend();
783     EditPrs<VISU::Plot3D_i,VisuGUI_Plot3DDlg>(myModule,aData);
784     break;
785   case TDEFORMEDSHAPE_ITEM: //Deformed Shape
786     c.suspend();
787     EditPrs<VISU::DeformedShape_i,VisuGUI_DeformedShapeDlg>(myModule,aData);
788     break;
789   case TSCALARMAPONDEFORMEDSHAPE_ITEM: //Scalar Map on Deformed Shape
790     c.suspend();
791     {
792       typedef VisuGUI_ScalarMapOnDeformedShapeDlg DLG;
793       typedef VISU::ScalarMapOnDeformedShape_i TYPE;
794       DLG* aDlg = new DLG (myModule);
795       aDlg->initFromPrsObject(dynamic_cast<TYPE*>(aData.myPrs[0]),true);
796       if (aDlg->exec())
797         { 
798           int anbFrames=aDlg->getCurrentScalarNbIterations();
799           int aIter = 0;
800           for (int i = 0; i < aData.myNbFrames; i++){
801             TYPE* aCurrPrs_i = dynamic_cast<TYPE*>(aData.myPrs[i]);
802             aIter = i+1;
803             if(i+1 > anbFrames)
804               aIter=anbFrames;
805             aDlg->storeToPrsObject(aCurrPrs_i,false,aIter);
806           }
807         }
808       delete aDlg;
809     }
810     break;
811   case TVECTORS_ITEM: //Vectors
812     c.suspend();
813     EditPrs<VISU::Vectors_i,VisuGUI_VectorsDlg>(myModule,aData);
814     break;
815   case TSTREAMLINES_ITEM: //Stream Lines
816     c.suspend();
817     EditPrs<VISU::StreamLines_i,VisuGUI_StreamLinesDlg>(myModule,aData);
818     break;
819   case TGAUSSPOINTS_ITEM: //Gauss Points
820     c.suspend();
821     EditPrs<VISU::GaussPoints_i,VisuGUI_GaussPointsDlg>(myModule,aData);
822     break;
823   }
824 }
825
826
827 //------------------------------------------------------------------------
828 void SetupDlg::onArrangeDlg()
829 {
830   ArrangeDlg aDlg(this, myAnimator);
831   aDlg.exec();
832 }
833
834 //------------------------------------------------------------------------
835 void SetupDlg::onRangeCheck (bool theCheck)
836 {
837   for (int i = 0; i < myAnimator->getNbFields(); i++)
838     myAnimator->clearData(myAnimator->getFieldData(i));
839
840   myMinVal->setEnabled(theCheck);
841   myMaxVal->setEnabled(theCheck);
842
843   if (!theCheck)
844     myAnimator->setAnimationRange(0, 0);
845   else {
846     //    if (myMinVal->value() < myMaxVal->value())
847     myAnimator->setAnimationRange(myMinVal->value(), myMaxVal->value());
848 //     else if (myMinVal->value() > myMaxVal->value())
849 //       myAnimator->setAnimationRange(myMaxVal->value(), myMinVal->value());
850 //     else // equal case
851 //       myAnimator->setAnimationRange(0, 0);
852   }
853 }
854
855 //------------------------------------------------------------------------
856 void SetupDlg::onMinValue (double theVal)
857 {
858   if (theVal > myAnimator->getMaxRange()) {
859     myMinVal->setValue( myAnimator->getMinTime() );
860     myMinVal->setFocus();
861     return;
862   }
863   for (int i = 0; i < myAnimator->getNbFields(); i++)
864     myAnimator->clearData(myAnimator->getFieldData(i));
865   myAnimator->setAnimationRange(theVal, myAnimator->getMaxRange());
866 }
867
868 //------------------------------------------------------------------------
869 void SetupDlg::onMaxValue (double theVal)
870 {
871   if (theVal < myAnimator->getMinRange()) {
872     myMaxVal->setValue( myAnimator->getMaxTime() );
873     myMaxVal->setFocus();
874     return;
875   }
876   for (int i = 0; i < myAnimator->getNbFields(); i++)
877     myAnimator->clearData(myAnimator->getFieldData(i));
878   myAnimator->setAnimationRange(myAnimator->getMinRange(), theVal);
879 }
880
881 static const char * firstIco[] = {
882 "18 10 2 1",
883 "       g None",
884 ".      g #000000",
885 "         .     .  ",
886 "  ..    ..    ..  ",
887 "  ..   ...   ...  ",
888 "  ..  ....  ....  ",
889 "  .. ..... .....  ",
890 "  .. ..... .....  ",
891 "  ..  ....  ....  ",
892 "  ..   ...   ...  ",
893 "  ..    ..    ..  ",
894 "         .     .  "};
895
896
897 static const char * lastIco[] = {
898 "18 10 2 1",
899 "       g None",
900 ".      g #000000",
901 "  .     .         ",
902 "  ..    ..    ..  ",
903 "  ...   ...   ..  ",
904 "  ....  ....  ..  ",
905 "  ..... ..... ..  ",
906 "  ..... ..... ..  ",
907 "  ....  ....  ..  ",
908 "  ...   ...   ..  ",
909 "  ..    ..    ..  ",
910 "  .     .         "};
911
912
913 static const char * leftIco[] = {
914 "11 10 2 1",
915 "       g None",
916 ".      g #000000",
917 "    .     .",
918 "   ..    ..",
919 "  ...   ...",
920 " ....  ....",
921 "..... .....",
922 "..... .....",
923 " ....  ....",
924 "  ...   ...",
925 "   ..    ..",
926 "    .     ."};
927
928 static const char * playIco[] = {
929 "14 14 2 1",
930 "       g None",
931 ".      g #000000",
932 "              ",
933 "              ",
934 "  ..          ",
935 "  ....        ",
936 "  ......      ",
937 "  ........    ",
938 "  ..........  ",
939 "  ..........  ",
940 "  ........    ",
941 "  ......      ",
942 "  ....        ",
943 "  ..          ",
944 "              ",
945 "              "};
946
947 static QPixmap MYplayPixmap(playIco);
948
949
950 static const char * rightIco[] = {
951 "11 10 2 1",
952 "       g None",
953 ".      g #000000",
954 ".     .    ",
955 "..    ..   ",
956 "...   ...  ",
957 "....  .... ",
958 "..... .....",
959 "..... .....",
960 "....  .... ",
961 "...   ...  ",
962 "..    ..   ",
963 ".     .    "};
964
965
966 static const char * pauseIco[] = {
967 "14 14 2 1",
968 "       g None",
969 ".      g #000000",
970 "              ",
971 "              ",
972 "   ..    ..   ",
973 "   ..    ..   ",
974 "   ..    ..   ",
975 "   ..    ..   ",
976 "   ..    ..   ",
977 "   ..    ..   ",
978 "   ..    ..   ",
979 "   ..    ..   ",
980 "   ..    ..   ",
981 "   ..    ..   ",
982 "              ",
983 "              "};
984
985 static QPixmap MYpausePixmap(pauseIco);
986
987
988 VisuGUI_TimeAnimationDlg::VisuGUI_TimeAnimationDlg (VisuGUI* theModule, _PTR(Study) theStudy) :
989   QDialog(VISU::GetDesktop(theModule), 
990           "VisuGUI_TimeAnimationDlg", 
991           false, 
992           WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu | WDestructiveClose),
993   myModule(theModule),
994   myStudy(theStudy),
995   mySetupDlg(NULL)
996 {
997   setCaption("Animation");
998   setSizeGripEnabled( TRUE );
999   isClosing = false;
1000
1001   myAnimator = new VISU_TimeAnimation (theStudy);
1002   myAnimator->setSpeed(1);
1003   myAnimator->setViewer(VISU::GetActiveViewWindow<SVTK_ViewWindow>(theModule));
1004   connect(myAnimator, SIGNAL(frameChanged(long, double)), this, SLOT(onExecution(long, double)));
1005   connect(myAnimator, SIGNAL(stopped()),                  this, SLOT(onStop()));
1006
1007   QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 6);
1008   aMainLayout->setSpacing(5);
1009
1010   mySetupBtn = new QPushButton("Setup Animation...", this);
1011   connect( mySetupBtn, SIGNAL( clicked() ),
1012            this, SLOT( onSetupDlg() ) );
1013   aMainLayout->addWidget(mySetupBtn);
1014
1015   myGenBtn = new QPushButton("Generate frames", this);
1016   connect( myGenBtn, SIGNAL( clicked() ),
1017            this, SLOT( createFrames() ) );
1018   aMainLayout->addWidget(myGenBtn);
1019
1020   myPlayFrame = new QFrame(this);
1021   myPlayFrame->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
1022   myPlayFrame->setLineWidth( 1 );
1023
1024
1025   // --- Play controls ---
1026   QGridLayout* TopLayout = new QGridLayout( myPlayFrame );
1027   TopLayout->setSpacing( 6 );
1028   TopLayout->setMargin( 11 );
1029
1030   myTimeLbl = new QLabel("0", myPlayFrame);
1031   TopLayout->addMultiCellWidget(myTimeLbl, 0, 0, 0, 2, Qt::AlignHCenter);
1032
1033   mySlider = new QSlider(Qt::Horizontal, myPlayFrame);
1034   mySlider->setMinValue(0);
1035   mySlider->setMaxValue(3);
1036   mySlider->setTickInterval(1);
1037   //mySlider->setTickmarks(QSlider::Below);
1038   mySlider->setTracking(false);
1039   connect( mySlider, SIGNAL( valueChanged(int) ),
1040            this, SLOT( onWindowChanged(int) ) );
1041   TopLayout->addMultiCellWidget(mySlider, 1, 1, 0, 2);
1042
1043   myPlayBtn = new QToolButton(myPlayFrame);
1044   myPlayBtn->setIconSet(MYplayPixmap);
1045   myPlayBtn->setToggleButton(true);
1046   connect( myPlayBtn, SIGNAL( clicked() ),
1047            this, SLOT( onPlayPressed() ) );
1048   TopLayout->addMultiCellWidget(myPlayBtn, 2, 2, 0, 1);
1049
1050   QToolButton* aBackBtn = new QToolButton(myPlayFrame);
1051   aBackBtn->setIconSet(QPixmap(leftIco));
1052   connect( aBackBtn, SIGNAL( clicked() ),
1053            this, SLOT( onBackPressed() ) );
1054   TopLayout->addWidget(aBackBtn, 3, 0);
1055
1056   QToolButton* aForvardBtn = new QToolButton(myPlayFrame);
1057   aForvardBtn->setIconSet(QPixmap(rightIco));
1058   connect( aForvardBtn, SIGNAL( clicked() ),
1059            this, SLOT( onForvardPressed() ) );
1060   TopLayout->addWidget(aForvardBtn, 3, 1);
1061
1062   QToolButton* aFirstBtn = new QToolButton(myPlayFrame);
1063   aFirstBtn->setIconSet(QPixmap(firstIco));
1064   connect( aFirstBtn, SIGNAL( clicked() ),
1065            this, SLOT( onFirstPressed() ) );
1066   TopLayout->addWidget(aFirstBtn, 4, 0);
1067
1068   QToolButton* aLastBtn = new QToolButton(myPlayFrame);
1069   aLastBtn->setIconSet(QPixmap(lastIco));
1070   connect( aLastBtn, SIGNAL( clicked() ),
1071            this, SLOT( onLastPressed() ) );
1072   TopLayout->addWidget(aLastBtn, 4, 1);
1073
1074   QLabel* aSpeedLbl = new QLabel("Speed", myPlayFrame);
1075   TopLayout->addWidget(aSpeedLbl, 4, 2, Qt::AlignRight);
1076
1077   QLCDNumber* aSpeedNum  = new QLCDNumber( 2, myPlayFrame );
1078   aSpeedNum->setSegmentStyle(QLCDNumber::Flat);
1079   aSpeedNum->display(1);
1080   TopLayout->addWidget(aSpeedNum, 4, 3);
1081
1082   QwtWheel* aWheel = new QwtWheel(myPlayFrame);
1083   aWheel->setOrientation(Qt::Vertical);
1084   aWheel->setRange(1, 99, 1);
1085   connect( aWheel, SIGNAL(valueChanged(double)),
1086            aSpeedNum, SLOT(display(double)) );
1087   connect( aWheel, SIGNAL(valueChanged(double)),
1088            this, SLOT(onSpeedChange(double)) );
1089   TopLayout->addMultiCellWidget(aWheel, 1, 3, 3, 3, Qt::AlignRight);
1090
1091   QCheckBox* aCycleCheck = new QCheckBox("Cycled animation",myPlayFrame);
1092   aCycleCheck->setChecked(myAnimator->isCycling());
1093   connect(aCycleCheck, SIGNAL(toggled(bool)), myAnimator, SLOT(setCyclingSlot(bool)));
1094   TopLayout->addMultiCellWidget(aCycleCheck, 5, 5, 0, 3);
1095
1096   QCheckBox* aPropCheck = new QCheckBox("Use proportional timing",myPlayFrame);
1097   aPropCheck->setChecked(myAnimator->isProportional());
1098   connect(aPropCheck, SIGNAL(toggled(bool)), myAnimator, SLOT(setProportionalSlot(bool)));
1099   TopLayout->addMultiCellWidget(aPropCheck, 6, 6, 0, 3);
1100
1101   // Pictures saving on disk
1102   QGroupBox* aSaveBox = new QGroupBox( "Saving", myPlayFrame );
1103   aSaveBox->setColumnLayout(0, Qt::Horizontal );
1104   QGridLayout* aSaveLay = new QGridLayout(aSaveBox->layout());
1105   aSaveLay->setSpacing( 5 );
1106   aSaveLay->setMargin( 5 );
1107
1108   mySaveCheck = new QCheckBox("Save pictures to directory", aSaveBox);
1109   connect(mySaveCheck, SIGNAL( toggled(bool)),
1110           this, SLOT( onCheckDump(bool) ));
1111   aSaveLay->addMultiCellWidget(mySaveCheck, 0, 0, 0, 2);
1112
1113   QLabel* aFormatLbl = new QLabel("Saving format:", aSaveBox);
1114   aFormatLbl->setEnabled(false);
1115   connect(mySaveCheck, SIGNAL( toggled(bool)),
1116           aFormatLbl, SLOT( setEnabled(bool) ));
1117   aSaveLay->addMultiCellWidget(aFormatLbl, 1, 1, 0, 1);
1118
1119   myPicsFormat = new QComboBox(aSaveBox);
1120   QStrList aDumpFormats = QImageIO::outputFormats();
1121   for (unsigned int i = 0; i < aDumpFormats.count(); i++) {
1122     myPicsFormat->insertItem(aDumpFormats.at(i));
1123   }
1124   if (aDumpFormats.find("JPEG"))
1125     myPicsFormat->setCurrentItem(aDumpFormats.find("JPEG"));
1126   else
1127     myPicsFormat->setCurrentItem(0);
1128   myPicsFormat->setEnabled(false);
1129   aSaveLay->addWidget(myPicsFormat, 1, 2);
1130   connect(mySaveCheck, SIGNAL( toggled(bool)),
1131           myPicsFormat, SLOT( setEnabled(bool) ));
1132   connect(myPicsFormat, SIGNAL(  activated (int)),
1133           this, SLOT( onPicsFormatChanged()));
1134
1135   QLabel* aPathLbl = new QLabel("Path:", aSaveBox);
1136   aPathLbl->setEnabled(false);
1137   connect(mySaveCheck, SIGNAL( toggled(bool)),
1138           aPathLbl, SLOT( setEnabled(bool) ));
1139   aSaveLay->addWidget(aPathLbl, 2, 0);
1140
1141   myPathEdit = new QLineEdit(aSaveBox);
1142   myPathEdit->setReadOnly(true);
1143   myPathEdit->setEnabled(false);
1144   connect(mySaveCheck, SIGNAL( toggled(bool)),
1145           myPathEdit, SLOT( setEnabled(bool) ));
1146   aSaveLay->addWidget(myPathEdit, 2, 1);
1147
1148   QPushButton* aBrowseBtn = new QPushButton("Browse...", aSaveBox);
1149   aBrowseBtn->setEnabled(false);
1150   connect(mySaveCheck, SIGNAL( toggled(bool)),
1151           aBrowseBtn, SLOT( setEnabled(bool) ));
1152   connect(aBrowseBtn, SIGNAL( clicked()),
1153           this, SLOT( onBrowse() ));
1154   mySaveCheck->setChecked(false);
1155   aSaveLay->addWidget(aBrowseBtn, 2, 2);
1156
1157   mySaveAVICheck = new QCheckBox("Save animation to AVI file", aSaveBox);
1158   connect(mySaveAVICheck, SIGNAL( toggled(bool)),
1159           this, SLOT( onCheckDump(bool) ));
1160   aSaveLay->addMultiCellWidget(mySaveAVICheck, 3, 3, 0, 2);
1161
1162   QLabel* aPathAVILbl = new QLabel("Path:", aSaveBox);
1163   aPathAVILbl->setEnabled(false);
1164   connect(mySaveAVICheck, SIGNAL( toggled(bool)),
1165           aPathAVILbl, SLOT( setEnabled(bool) ));
1166   aSaveLay->addWidget(aPathAVILbl, 4, 0);
1167
1168   myPathAVIEdit = new QLineEdit(aSaveBox);
1169   myPathAVIEdit->setReadOnly(true);
1170   myPathAVIEdit->setEnabled(false);
1171   connect(mySaveAVICheck, SIGNAL( toggled(bool)),
1172           myPathAVIEdit, SLOT( setEnabled(bool) ));
1173   aSaveLay->addWidget(myPathAVIEdit, 4, 1);
1174
1175   QPushButton* aBrowseAVIBtn = new QPushButton("Browse...", aSaveBox);
1176   aBrowseAVIBtn->setEnabled(false);
1177   connect(mySaveAVICheck, SIGNAL( toggled(bool)),
1178           aBrowseAVIBtn, SLOT( setEnabled(bool) ));
1179   connect(aBrowseAVIBtn, SIGNAL( clicked()),
1180           this, SLOT( onBrowseAVI() ));
1181   aSaveLay->addWidget(aBrowseAVIBtn, 4, 2);
1182
1183   mySaveAVICheck->setChecked(false);
1184   mySaveAVICheck->setEnabled(myAnimator->checkAVIMaker());
1185
1186   TopLayout->addMultiCellWidget(aSaveBox, 7, 7, 0, 3);
1187
1188   aMainLayout->addWidget(myPlayFrame);
1189
1190   // Animation publishing in study
1191   QHBox* aPublishBox = new QHBox(this);
1192   aPublishBox->setSpacing(5);
1193
1194   myPublishBtn = new QPushButton("Publish to study", aPublishBox);
1195   connect(myPublishBtn, SIGNAL(clicked()), this, SLOT(publishToStudy()));
1196
1197   mySaveBtn = new QPushButton("Save Animation", aPublishBox);
1198   mySaveBtn->setEnabled(myAnimator->isSavedInStudy());
1199   connect(mySaveBtn, SIGNAL(clicked()), this, SLOT(saveToStudy()));
1200
1201   aMainLayout->addWidget(aPublishBox);
1202
1203
1204   QHBox* aBtnBox = new QHBox(this);
1205   QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox->layout());
1206   aBtnLayout->addStretch();
1207
1208   QPushButton* aCloseBtn = new QPushButton(tr("BUT_CLOSE"), aBtnBox);
1209   connect(aCloseBtn, SIGNAL(clicked()), this, SLOT(close()));
1210
1211   QPushButton* aHelpBtn = new QPushButton(tr("BUT_HELP"), aBtnBox);
1212   connect(aHelpBtn, SIGNAL(clicked()), this, SLOT(onHelp()));
1213
1214   SUIT_Study* aStudy = VISU::GetAppStudy(myModule);
1215   connect(aStudy, SIGNAL(destroyed()), this, SLOT(close()));
1216
1217   connect(myAnimator->getViewer(), SIGNAL(destroyed()), this, SLOT(close()));
1218   connect(myAnimator->getViewer(), SIGNAL(closing(SUIT_ViewWindow*)), this, SLOT(close()));
1219
1220   aMainLayout->addWidget(aBtnBox);
1221
1222   myPlayFrame->setEnabled(false);
1223 }
1224
1225 //------------------------------------------------------------------------
1226 VisuGUI_TimeAnimationDlg::~VisuGUI_TimeAnimationDlg()
1227 {
1228   if(myAnimator != NULL){
1229     delete myAnimator;
1230     myAnimator = NULL;
1231     VISU::GetActiveViewWindow<SVTK_ViewWindow>(myModule)->Repaint();
1232   }
1233 }
1234
1235 //------------------------------------------------------------------------
1236 void VisuGUI_TimeAnimationDlg::onTypeChange (int index)
1237 {
1238   stopAnimation();
1239   myPropBtn->setEnabled(index != 0);
1240
1241   clearView();
1242   myPlayFrame->setEnabled(false);
1243 }
1244
1245 //------------------------------------------------------------------------
1246 void VisuGUI_TimeAnimationDlg::addField (_PTR(SObject) theSObject)
1247 {
1248   myPlayFrame->setEnabled(false);
1249   myAnimator->addField(theSObject);
1250 }
1251
1252 //------------------------------------------------------------------------
1253 void VisuGUI_TimeAnimationDlg::createFrames()
1254 {
1255   stopAnimation();
1256   SUIT_OverrideCursor c;
1257
1258   for (int i = 0; i < myAnimator->getNbFields(); i++) {
1259     if (myAnimator->getFieldData(i).myPrs.empty())
1260       myAnimator->generatePresentations(i);
1261   }
1262   if (myAnimator->getNbFrames() == 0) {
1263     myPlayFrame->setEnabled(false);
1264     c.suspend();
1265     SUIT_MessageBox::warn1(this,
1266                            tr("ERROR"),
1267                            tr("MSG_NO_ANIMATIONDATA"),
1268                            tr("&OK"));
1269     return;
1270   }
1271   mySlider->setMaxValue(myAnimator->getNbFrames()-1);
1272   myPlayFrame->setEnabled(true);
1273   if (!myAnimator->generateFrames()) {
1274     c.suspend();
1275     //myPlayFrame->setEnabled(false);
1276     SUIT_MessageBox::warn1(this,
1277                            tr("ERROR"),
1278                            myAnimator->getLastErrorMsg(),
1279                            tr("&OK"));
1280     return;
1281   }
1282   //myPlayFrame->setEnabled(true);
1283 }
1284
1285 //------------------------------------------------------------------------
1286 void VisuGUI_TimeAnimationDlg::onPlayPressed()
1287 {
1288   if (myPlayBtn->isOn() && (!myAnimator->running())) {
1289     myPlayBtn->setIconSet(MYpausePixmap);
1290     if (mySaveCheck->isChecked()) {
1291       onPicsFormatChanged();
1292       onPathChanged();
1293       
1294     } else if (mySaveAVICheck->isChecked()) {
1295       myAnimator->setDumpFormat("AVI");
1296       myAnimator->dumpTo(myPathAVIEdit->text());
1297     } else {
1298       myAnimator->dumpTo("");
1299     }
1300     mySetupBtn->setEnabled(false);
1301     myGenBtn->setEnabled(false);
1302     myAnimator->startAnimation();
1303   } else {
1304     myPlayBtn->setIconSet(MYplayPixmap);
1305     myAnimator->stopAnimation();
1306     mySetupBtn->setEnabled(true);
1307     myGenBtn->setEnabled(true);
1308   }
1309 }
1310
1311 //------------------------------------------------------------------------
1312 void VisuGUI_TimeAnimationDlg::onBackPressed()
1313 {
1314   //stopAnimation();
1315   myAnimator->prevFrame();
1316 }
1317
1318 //------------------------------------------------------------------------
1319 void VisuGUI_TimeAnimationDlg::onForvardPressed()
1320 {
1321   myAnimator->nextFrame();
1322 }
1323
1324 //------------------------------------------------------------------------
1325 void VisuGUI_TimeAnimationDlg::onLastPressed()
1326 {
1327   myAnimator->lastFrame();
1328 }
1329
1330 //------------------------------------------------------------------------
1331 void VisuGUI_TimeAnimationDlg::onFirstPressed()
1332 {
1333   myAnimator->firstFrame();
1334 }
1335
1336 //------------------------------------------------------------------------
1337 void VisuGUI_TimeAnimationDlg::clearView()
1338 {
1339   myAnimator->clearView();
1340 }
1341
1342 //------------------------------------------------------------------------
1343 void VisuGUI_TimeAnimationDlg::showEvent(QShowEvent* theEvent)
1344 {
1345   mySetupDlg = new SetupDlg(this,myModule, myAnimator);
1346 }
1347
1348 void VisuGUI_TimeAnimationDlg::reject()
1349 {
1350   close();
1351   QDialog::reject();
1352 }
1353
1354 //------------------------------------------------------------------------
1355 void VisuGUI_TimeAnimationDlg::closeEvent (QCloseEvent* theEvent)
1356 {
1357   if(myAnimator != NULL){
1358     myAnimator->stopAnimation();
1359     myAnimator->wait(500);
1360     if (myAnimator->running() && (! myAnimator->finished())) {
1361       isClosing = true;
1362       myEvent = theEvent;
1363       //        * Destroing data in myAnimator before study closed.
1364       //        * It needed for correcting destroing of myAnimator, which 
1365       //        * depend from SVTK_RenderWindowInteractor() e.t.c.
1366       if(theEvent->type() == QEvent::Close){
1367         for (int i = 0; i < myAnimator->getNbFields(); i++)
1368           myAnimator->clearData(myAnimator->getFieldData(i));
1369         myAnimator->clearFieldData();
1370       }
1371     } else {
1372       QDialog::closeEvent(theEvent);
1373     }
1374   } else {
1375     QDialog::closeEvent(theEvent);
1376   }
1377 }
1378
1379 //------------------------------------------------------------------------
1380 void VisuGUI_TimeAnimationDlg::onWindowChanged (int index)
1381 {
1382   if (myAnimator->isRunning()) return;
1383   myAnimator->gotoFrame(index);
1384 }
1385
1386 //------------------------------------------------------------------------
1387 void VisuGUI_TimeAnimationDlg::onSpeedChange (double theSpeed)
1388 {
1389   myAnimator->setSpeed((int)theSpeed);
1390 }
1391
1392 //------------------------------------------------------------------------
1393 void VisuGUI_TimeAnimationDlg::stopAnimation()
1394 {
1395   myAnimator->stopAnimation();
1396   myPlayBtn->setOn(false);
1397   myPlayBtn->setIconSet(MYplayPixmap);
1398   mySetupBtn->setEnabled(true);
1399   myGenBtn->setEnabled(true);
1400 }
1401
1402 //------------------------------------------------------------------------
1403 void VisuGUI_TimeAnimationDlg::onExecution (long theNewFrame, double theTime)
1404 {
1405   myTimeLbl->setText(QString("%1").arg(theTime));
1406   mySlider->setValue(theNewFrame);
1407 }
1408
1409 //------------------------------------------------------------------------
1410 void VisuGUI_TimeAnimationDlg::onSetupDlg()
1411 {
1412   if (myAnimator->getNbFrames() > 0) 
1413     myAnimator->firstFrame();
1414   mySetupDlg->exec();
1415   myPlayFrame->setEnabled(false);
1416 }
1417
1418 //------------------------------------------------------------------------
1419 void VisuGUI_TimeAnimationDlg::onBrowse()
1420 {
1421   //  QString aPath = SUIT_FileDlg::getExistingDirectory(this, "/", "Select path");
1422   QString aDir;
1423   if (myPathEdit->text().isEmpty())
1424     aDir = getenv("HOME");
1425   else 
1426     aDir = myPathEdit->text();
1427   QString aPath = SUIT_FileDlg::getExistingDirectory(this, aDir, "Select path");
1428   if (!aPath.isEmpty())
1429     myPathEdit->setText(Qtx::addSlash(aPath));
1430   onPathChanged();
1431 }
1432
1433 //------------------------------------------------------------------------
1434 void VisuGUI_TimeAnimationDlg::onBrowseAVI()
1435 {
1436   QStringList aFilter;
1437   aFilter.append( "AVI Files (*.avi)" );
1438   aFilter.append( "All Files (*.*)" );
1439
1440   QString aDir;
1441   if (myPathAVIEdit->text().isEmpty())
1442     aDir = getenv("HOME");
1443   else {
1444     QFileInfo aFile(myPathAVIEdit->text());
1445     aDir = aFile.dirPath(true);
1446   }
1447   QString aPath = SUIT_FileDlg::getFileName(this, aDir, aFilter, "Select file", false);
1448   if (!aPath.isEmpty())
1449     myPathAVIEdit->setText(aPath);
1450 }
1451
1452 //------------------------------------------------------------------------
1453 void VisuGUI_TimeAnimationDlg::onCheckDump(bool)
1454 {
1455   const QObject* source = sender();
1456   if (source == mySaveCheck) {
1457     if (mySaveCheck->isChecked()) {
1458       onPicsFormatChanged();
1459       onPathChanged();
1460       if (mySaveAVICheck->isChecked())
1461         mySaveAVICheck->setChecked(false);
1462     } else {
1463       myAnimator->dumpTo("");
1464     }
1465     mySaveAVICheck->setEnabled(!mySaveCheck->isChecked() && myAnimator->checkAVIMaker());
1466   }
1467   else if (source == mySaveAVICheck) {
1468     if (mySaveAVICheck->isChecked()) {
1469       if (mySaveCheck->isChecked())
1470         mySaveCheck->setChecked(false);
1471     }
1472     mySaveCheck->setEnabled(!mySaveAVICheck->isChecked());
1473   }
1474 }
1475
1476 //------------------------------------------------------------------------
1477 void VisuGUI_TimeAnimationDlg::onStop()
1478 {
1479   if (isClosing) {
1480     QDialog::closeEvent(myEvent);
1481   } else {
1482     myPlayBtn->setOn(false);
1483     myPlayBtn->setIconSet(MYplayPixmap);
1484     mySetupBtn->setEnabled(true);
1485     myGenBtn->setEnabled(true);
1486   }
1487 }
1488
1489 //------------------------------------------------------------------------
1490 void VisuGUI_TimeAnimationDlg::onHelp()
1491 {
1492   QString aHelpFileName = "/files/animating_presentations.htm";
1493   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
1494   if (app)
1495     app->onHelpContextModule(myModule ? app->moduleName(myModule->moduleName()) : QString(""), aHelpFileName);
1496   else {
1497     SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
1498                            QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
1499                            arg(app->resourceMgr()->stringValue("ExternalBrowser", "application")).arg(aHelpFileName),
1500                            QObject::tr("BUT_OK"));
1501   }
1502 }
1503
1504 //------------------------------------------------------------------------
1505 void VisuGUI_TimeAnimationDlg::saveToStudy()
1506 {
1507   myAnimator->saveAnimation();
1508   VISU::UpdateObjBrowser(myModule, true);
1509 }
1510
1511 //------------------------------------------------------------------------
1512 void VisuGUI_TimeAnimationDlg::publishToStudy()
1513 {
1514   myAnimator->publishInStudy();
1515   VISU::UpdateObjBrowser(myModule, true);
1516   mySaveBtn->setEnabled(myAnimator->isSavedInStudy());
1517 }
1518
1519 //------------------------------------------------------------------------
1520 void VisuGUI_TimeAnimationDlg::restoreFromStudy(_PTR(SObject) theAnimation)
1521 {
1522   myAnimator->restoreFromStudy(theAnimation);
1523   mySaveBtn->setEnabled(myAnimator->isSavedInStudy());
1524 }
1525
1526 //------------------------------------------------------------------------
1527 void VisuGUI_TimeAnimationDlg::onPicsFormatChanged()
1528 {
1529   QStrList aDumpFormats = QImageIO::outputFormats();
1530   myAnimator->setDumpFormat(aDumpFormats.at(myPicsFormat->currentItem()));
1531 }
1532
1533 //------------------------------------------------------------------------
1534 void VisuGUI_TimeAnimationDlg::onPathChanged()
1535 {
1536   myAnimator->dumpTo(myPathEdit->text());
1537 }