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