Logo Search packages:      
Sourcecode: salome version File versions  Download package

VisuGUI_TimeAnimation.cxx

//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
//
//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
//  File   : VisuGUI_TimeAnimation.cxx
//  Author : Vitaly SMETANNIKOV
//  Module : VISU
//
#include "VisuGUI_TimeAnimation.h"

#include "VisuGUI.h"
#include "VisuGUI_Tools.h"
#include "VisuGUI_ViewTools.h"
#include "VisuGUI_ScalarBarDlg.h"
#include "VisuGUI_DeformedShapeDlg.h"
#include "VisuGUI_CutPlanesDlg.h"
#include "VisuGUI_CutLinesDlg.h"
#include "VisuGUI_CutSegmentDlg.h"
#include "VisuGUI_Plot3DDlg.h"
#include "VisuGUI_VectorsDlg.h"
#include "VisuGUI_IsoSurfacesDlg.h"
#include "VisuGUI_StreamLinesDlg.h"
#include "VisuGUI_DeformedShapeAndScalarMapDlg.h"
#include "VisuGUI_GaussPointsDlg.h"

#include "VISU_TimeAnimation.h"

#include "VISU_ScalarMap_i.hh"
#include "VISU_IsoSurfaces_i.hh"
#include "VISU_DeformedShape_i.hh"
#include "VISU_CutPlanes_i.hh"
#include "VISU_Plot3D_i.hh"
#include "VISU_CutLines_i.hh"
#include "VISU_CutSegment_i.hh"
#include "VISU_Vectors_i.hh"
#include "VISU_StreamLines_i.hh"
#include "VISU_DeformedShapeAndScalarMap_i.hh"
#include "VISU_GaussPoints_i.hh"

#include "VISU_ViewManager_i.hh"

#include "VISU_ScalarBarActor.hxx"
#include "VISU_Actor.h"

#include "SalomeApp_Study.h"
#include "LightApp_Application.h"

#include "SVTK_ViewWindow.h"

#include "VTKViewer_Algorithm.h"

#include "SUIT_OverrideCursor.h"
#include "SUIT_MessageBox.h"
#include "SUIT_ResourceMgr.h"
#include "SUIT_Session.h"
#include "SUIT_Desktop.h"
#include "SUIT_FileDlg.h"

#include <vtkRenderer.h>
#include <vtkMapper.h>

#include <QGridLayout>
#include <QImage>
#include <QImageWriter>
#include <QLayout>
#include <QSlider>
#include <QThread>
#include <QListWidget>
#include <QLCDNumber>
#include <QToolButton>
#include <QKeyEvent>
#include <QComboBox>
#include <QLineEdit>
#include <QRadioButton>
#include <QGroupBox>
#include <QPushButton>
#include <QLabel>

#include <qwt_wheel.h>

#define  MAXVAL 1e10
#define  VALPRECISION 8

namespace {
  void GeneratePresentations(int theFieldId, VISU_TimeAnimation* theAnimator)
  {
    if(theAnimator->getNbFields() == 0)
      return;

    theAnimator->generatePresentations(theFieldId);
    FieldData& aFieldData = theAnimator->getFieldData(theFieldId);


    int aRefFieldId = ( theAnimator->getAnimationMode() == VISU::Animation::PARALLEL ) ? theFieldId : 0;
    if(VISU::ColoredPrs3d_i* aInitialPrs3d = dynamic_cast<VISU::ColoredPrs3d_i*>(theAnimator->getFieldData(aRefFieldId).myPrs[0])){
      for (long aFrameId = 0; aFrameId < aFieldData.myNbFrames; aFrameId++) {
        VISU::ColoredPrs3d_i* aColoredPrs3d = aFieldData.myPrs[aFrameId];

        // Special case for DeformedShape And ScalarMap presentation
        // Restore time stamp number for all presentations
        VISU::DeformedShapeAndScalarMap_i* aDeformedAndScalPrs = dynamic_cast<VISU::DeformedShapeAndScalarMap_i*>(aColoredPrs3d);
        int aTimeStampNum = -1;
        if(aDeformedAndScalPrs){
          aTimeStampNum = aDeformedAndScalPrs->GetScalarTimeStampNumber();
        }
        aColoredPrs3d->SameAs(aInitialPrs3d);

        if(aDeformedAndScalPrs){
          aDeformedAndScalPrs->SetScalarField(aDeformedAndScalPrs->GetScalarEntity(),
                                              aDeformedAndScalPrs->GetScalarFieldName(),
                                              aTimeStampNum);
        }

        std::string aTitle = aColoredPrs3d->GetCTitle();
        if ( aFrameId != 0 && theAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) {
          aColoredPrs3d->SetTitle(aTitle.c_str());
        }
      }
    }
  }
}

ArrangeDlg::ArrangeDlg(QWidget* theParent, VISU_TimeAnimation* theAnimator)
  : QDialog(theParent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
    myAnimator(theAnimator),
    myViewWindow(theAnimator->getViewer())
{
  setModal( true );
  myCurrent = 0;
  init();
  QStringList aFieldNames;
  // Find names of fields
  for (int i = 0; i < myAnimator->getNbFields(); i++) {
    _PTR(SObject) aSObject = myAnimator->getFieldData(i).myField;
    VISU::Storable::TRestoringMap aRestoringMap = VISU::Storable::GetStorableMap(aSObject);
    aFieldNames.append(aRestoringMap["myName"]);
    Offset aOffs;
    aOffs.myOffset[0] = myAnimator->getFieldData(i).myOffset[0];
    aOffs.myOffset[1] = myAnimator->getFieldData(i).myOffset[1];
    aOffs.myOffset[2] = myAnimator->getFieldData(i).myOffset[2];
    myOffsets.append(aOffs);
  }
  myFieldLst->addItems(aFieldNames);
  myFieldLst->setCurrentRow(0);
}

ArrangeDlg::ArrangeDlg(QWidget* theParent,
                   const SalomeApp_Module* theModule,
                   SVTK_ViewWindow* theViewWindow)
  : QDialog(theParent,  Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
    myAnimator(NULL),
    myViewWindow(theViewWindow)
{
  setModal( true );
  myCurrent = 0;
  init();
  QStringList aPrsNames;
  VTK::ActorCollectionCopy aCopy(myViewWindow->getRenderer()->GetActors());
  vtkActorCollection *aCollection = aCopy.GetActors();
  aCollection->InitTraversal();
  while(vtkActor* anActor = aCollection->GetNextActor()){
    if (VISU_Actor* anVISUActor = dynamic_cast<VISU_Actor*>(anActor)) {
      if(anVISUActor->GetVisibility() != 0){
      if (VISU::Prs3d_i* aPrs = anVISUActor->GetPrs3d()){
        if(!myPrsMap.contains(aPrs)){
          Handle(SALOME_InteractiveObject) anIO = aPrs->GetIO();
          if(!anIO->hasEntry())
            continue;
          SalomeApp_Study* aStudy = VISU::GetAppStudy(theModule);
          VISU::TObjectInfo anObjectInfo = VISU::GetObjectByEntry(aStudy, anIO->getEntry());
          if(_PTR(SObject) aSObject = anObjectInfo.mySObject){
            _PTR(GenericAttribute) anAttr;
            if (aSObject->FindAttribute(anAttr, "AttributeName")) {
            _PTR(AttributeName) aName(anAttr);
            QString strIn(aName->Value().c_str());
            aPrsNames.append(strIn);
            myPrsMap[aPrs] = myOffsets.count();
            Offset aOffs;
            anVISUActor->GetPosition(aOffs.myOffset);
            myOffsets.append(aOffs);
            }
          }
        }
      }
      }
    } else { //if PointMap3d Actor
      if (VISU_ActorBase* anActorBase = dynamic_cast<VISU_ActorBase*>(anActor))
      if(anActorBase->GetVisibility() != 0)
        if (VISU::PointMap3d_i* aPrs = dynamic_cast<VISU::PointMap3d_i*>(anActorBase->GetFactory())) {
          if(!myPointMapPrsMap.contains(aPrs)){
            Handle(SALOME_InteractiveObject) anIO = aPrs->GetIO();
            if(!anIO->hasEntry())
            continue;
            SalomeApp_Study* aStudy = VISU::GetAppStudy(theModule);
            VISU::TObjectInfo anObjectInfo = VISU::GetObjectByEntry(aStudy, anIO->getEntry());
            if(_PTR(SObject) aSObject = anObjectInfo.mySObject){
            _PTR(GenericAttribute) anAttr;
            if (aSObject->FindAttribute(anAttr, "AttributeName")) {
              _PTR(AttributeName) aName(anAttr);
              QString strIn(aName->Value().c_str());
              aPrsNames.append(strIn);
              myPointMapPrsMap[aPrs] = myOffsets.count();
              Offset aOffs;
              anActorBase->GetPosition(aOffs.myOffset);
              myOffsets.append(aOffs);
            }
            }
          }
        }
    }
  }
  myFieldLst->addItems(aPrsNames);
  myFieldLst->setCurrentRow(0);
}

void ArrangeDlg::init()
{
  setWindowTitle("Arrange Presentations");
  setSizeGripEnabled( TRUE );

  QVBoxLayout* aMainLayout = new QVBoxLayout(this);
  aMainLayout->setMargin( 7 );
  aMainLayout->setSpacing(5);

  QButtonGroup* aBtnGrp = new QButtonGroup( this);
  aBtnGrp->setExclusive(true);
  //aMainLayout->addWidget(aBtnGrp);

  QGroupBox* aBtnGB = new QGroupBox( this );
  QHBoxLayout* aHBLay = new QHBoxLayout( aBtnGB );
  aMainLayout->addWidget(aBtnGB);

  QRadioButton* aAutoBtn = new QRadioButton("Auto", aBtnGB);
  aHBLay->addWidget( aAutoBtn );
  aBtnGrp->addButton(aAutoBtn, AutoMode);

  QRadioButton* aManualBtn = new QRadioButton("Manual", aBtnGB);
  aHBLay->addWidget( aManualBtn );
  aBtnGrp->addButton(aManualBtn, ManualMode);

  aAutoBtn->setChecked( true );

  myStackWgt = new QStackedWidget(this);
  aMainLayout->addWidget(myStackWgt);

  //  AUTO Pane
  QWidget* aAutoPane = new QWidget(myStackWgt);
  QVBoxLayout* aAutoLay = new QVBoxLayout( aAutoPane );
  aAutoLay->setSpacing(5);

  // Axis Group
  myAxisGrp = new QButtonGroup(aAutoPane);

  QGroupBox* aAxisGB = new QGroupBox( "Axis", aAutoPane );
  QHBoxLayout* aVBLay = new QHBoxLayout( aAxisGB );
  aAutoLay->addWidget( aAxisGB );

  QRadioButton* aXBtn = new QRadioButton("X",aAxisGB );
  aVBLay->addWidget( aXBtn );
  myAxisGrp->addButton(aXBtn, XAxis);

  QRadioButton* aYBtn = new QRadioButton("Y",aAxisGB );
  aVBLay->addWidget( aYBtn );
  myAxisGrp->addButton(aYBtn, YAxis);

  QRadioButton* aZBtn = new QRadioButton("Z",aAxisGB );
  aVBLay->addWidget( aZBtn );
  myAxisGrp->addButton(aZBtn, ZAxis);

  aXBtn->setChecked( true );

  //Distance Input
  QWidget* aDistPane = new QWidget(aAutoPane);
  QHBoxLayout* aHLay = new QHBoxLayout( aDistPane );
  aHLay->setSpacing(5);
  aHLay->addWidget( new QLabel("Relative Distance", aDistPane) );
  myDistVal = new QtxDoubleSpinBox (-10,10, 0.5, aDistPane);
  myDistVal->setValue(1);
  aHLay->addWidget( myDistVal );

  aAutoLay->addWidget( aDistPane );

  myStackWgt->insertWidget( AutoMode, aAutoPane);

  // Manual Pane
  QWidget* aManualPane = new QWidget(myStackWgt);
  aHLay = new QHBoxLayout( aManualPane );
  aHLay->setSpacing(10);

  myFieldLst = new QListWidget(aManualPane);
  aHLay->addWidget( myFieldLst );
  connect( myFieldLst, SIGNAL( currentRowChanged(int) ),
         this, SLOT( onFieldChange(int) ) );

  QWidget* aCoordPane = new QWidget( aManualPane);
  aHLay->addWidget( aCoordPane );
  QGridLayout* aCoordLayout = new QGridLayout( aCoordPane );
  aCoordLayout->setSpacing(5);

  aCoordLayout->addWidget( new QLabel("X", aCoordPane), 0, 0 );
  myCoord[0] = new QtxDoubleSpinBox(aCoordPane);
  myCoord[0]->setRange(-MAXVAL, MAXVAL);
  aCoordLayout->addWidget( myCoord[0], 0, 1 );

  aCoordLayout->addWidget( new QLabel("Y", aCoordPane), 1, 0 );
  myCoord[1] = new QtxDoubleSpinBox(aCoordPane);
  myCoord[1]->setRange(-MAXVAL, MAXVAL);
  aCoordLayout->addWidget( myCoord[1], 1, 1 );

  aCoordLayout->addWidget( new QLabel("Z", aCoordPane), 2, 0 );
  myCoord[2] = new QtxDoubleSpinBox(aCoordPane);
  myCoord[2]->setRange(-MAXVAL, MAXVAL);
  aCoordLayout->addWidget( myCoord[2], 2, 1 );

  myStackWgt->insertWidget(ManualMode, aManualPane );

  myStackWgt->setCurrentIndex(AutoMode);

  connect(aBtnGrp, SIGNAL(buttonClicked(int)), myStackWgt, SLOT(setCurrentIndex(int)) );

  SUIT_Study* aSUITStudy = myViewWindow->getViewManager()->study();
  SalomeApp_Study* anAppStudy = dynamic_cast<SalomeApp_Study*>(aSUITStudy);
  _PTR(Study) aCStudy = VISU::GetCStudy(anAppStudy);
  if (!myAnimator && !aCStudy->GetProperties()->IsLocked()) {
    mySaveChk = new QCheckBox ("Save to presentation", this);
    mySaveChk->setChecked(false);
    aMainLayout->addWidget(mySaveChk);
  } else {
    mySaveChk = 0;
  }

  // Common buttons ===========================================================
  QGroupBox* GroupButtons = new QGroupBox( this );
  //GroupButtons->setColumnLayout(0, Qt::Vertical );
  //GroupButtons->layout()->setSpacing( 0 );
  //GroupButtons->layout()->setMargin( 0 );
  QGridLayout* GroupButtonsLayout = new QGridLayout( GroupButtons );
  GroupButtonsLayout->setAlignment( Qt::AlignTop );
  GroupButtonsLayout->setSpacing( 6 );
  GroupButtonsLayout->setMargin( 11 );

  QPushButton* buttonOk = new QPushButton( tr( "&OK" ), GroupButtons );
  buttonOk->setAutoDefault( TRUE );
  buttonOk->setDefault( TRUE );
  GroupButtonsLayout->addWidget( buttonOk, 0, 0 );
  GroupButtonsLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, 1 );

  QPushButton* buttonCancel = new QPushButton( tr( "&Cancel" ) , GroupButtons );
  buttonCancel->setAutoDefault( TRUE );
  GroupButtonsLayout->addWidget( buttonCancel, 0, 2 );

  aMainLayout->addWidget( GroupButtons );

  connect( buttonOk,     SIGNAL( clicked() ),      this, SLOT( accept() ) );
  connect( buttonCancel, SIGNAL( clicked() ),      this, SLOT( reject() ) );
}

void ArrangeDlg::accept()
{
  if (myAnimator != NULL) {
    acceptAnimation();
  } else {
    acceptViewWindow();
  }
  QDialog::accept();
}

void ArrangeDlg::onFieldChange(int theCurrent)
{
  if (myCurrent != theCurrent) {
    Offset& aOffs = myOffsets[myCurrent];
    aOffs.myOffset[0] = myCoord[0]->value();
    aOffs.myOffset[1] = myCoord[1]->value();
    aOffs.myOffset[2] = myCoord[2]->value();
  }
  myCurrent = theCurrent;
  const Offset& aNewOffs = myOffsets[myCurrent];
  myCoord[0]->setValue(aNewOffs.myOffset[0]);
  myCoord[1]->setValue(aNewOffs.myOffset[1]);
  myCoord[2]->setValue(aNewOffs.myOffset[2]);
}

void ArrangeDlg::acceptAnimation()
{
  if (getMode() == ManualMode) {
    // Save from GUI
    Offset& aOffs = myOffsets[myCurrent];
    aOffs.myOffset[0] = myCoord[0]->value();
    aOffs.myOffset[1] = myCoord[1]->value();
    aOffs.myOffset[2] = myCoord[2]->value();

    for (int i = 0; i < myAnimator->getNbFields(); i++) {
      Offset aOffs = myOffsets[i];
      myAnimator->getFieldData(i).myOffset[0] = aOffs.myOffset[0];
      myAnimator->getFieldData(i).myOffset[1] = aOffs.myOffset[1];
      myAnimator->getFieldData(i).myOffset[2] = aOffs.myOffset[2];
    }
  } else {
    QApplication::setOverrideCursor( Qt::WaitCursor );
    FieldData& aData = myAnimator->getFieldData(myFieldLst->currentRow());
    if (aData.myPrs.empty())
      GeneratePresentations(myFieldLst->currentRow(),myAnimator);
    vtkFloatingPointType aBounds[6];
    aData.myPrs[0]->GetBounds(aBounds);
    vtkFloatingPointType aDist = 0;
    int aAxis = getAxis();
    switch (aAxis) {
    case XAxis:
      aDist = fabs(aBounds[1] - aBounds[0]);
      break;
    case YAxis:
      aDist = fabs(aBounds[3] - aBounds[2]);
      break;
    case ZAxis:
      aDist = fabs(aBounds[5] - aBounds[4]);
    }

    vtkFloatingPointType dx = fabs(aBounds[1] - aBounds[0]);
    vtkFloatingPointType dy = fabs(aBounds[3] - aBounds[2]);
    vtkFloatingPointType dz = fabs(aBounds[5] - aBounds[4]);
    vtkFloatingPointType max = (dx > dy) ? dx : dy;
    max = (dz > max) ? dz : max;
    max /= 100.0;

    if (aDist < max) {
      // set base distance between centers of bounding boxes
      // to minimal (but big enough) size of current bounding box
      if (dx < max) dx = FLT_MAX;
      if (dy < max) dy = FLT_MAX;
      if (dz < max) dz = FLT_MAX;

      aDist = (dx < dy) ? dx : dy;
      aDist = (dz < aDist) ? dz : aDist;
    }
    aDist = aDist * getDistance();
    for (int i = 0; i < myAnimator->getNbFields(); i++) {
      myAnimator->getFieldData(i).myOffset[0] = 0;
      myAnimator->getFieldData(i).myOffset[1] = 0;
      myAnimator->getFieldData(i).myOffset[2] = 0;
      myAnimator->getFieldData(i).myOffset[aAxis] = aDist * i;
    }

    QApplication::restoreOverrideCursor();
  }
}

void ArrangeDlg::acceptViewWindow()
{
  if (getMode() == ManualMode) {
    // Save from GUI
    Offset& aOffs = myOffsets[myCurrent];
    aOffs.myOffset[0] = myCoord[0]->value();
    aOffs.myOffset[1] = myCoord[1]->value();
    aOffs.myOffset[2] = myCoord[2]->value();

    QMap<VISU::Prs3d_i*, int>::Iterator it;
    for (it = myPrsMap.begin(); it != myPrsMap.end(); ++it) {
      VISU::Prs3d_i* aPrs = it.key();
      Offset& aOffs = myOffsets[it.value()];
      if (VISU_Actor* anActor = VISU::FindActor(myViewWindow, aPrs))
        anActor->SetPosition(aOffs.myOffset);
      if (mySaveChk)
      if (mySaveChk->isChecked())
        aPrs->SetOffset(aOffs.myOffset[0],aOffs.myOffset[1],aOffs.myOffset[2]);
    }
    QMap<VISU::PointMap3d_i*, int>::Iterator itt;
    for (itt = myPointMapPrsMap.begin(); itt != myPointMapPrsMap.end(); ++itt) {
      VISU::PointMap3d_i* aPrs = itt.key();
      Offset& aOffs = myOffsets[itt.value()];
      if (VISU_ActorBase* anActor = VISU::FindActorBase(myViewWindow, aPrs))
        anActor->SetPosition(aOffs.myOffset);
      if (mySaveChk)
      if (mySaveChk->isChecked())
        aPrs->SetOffset(aOffs.myOffset[0],aOffs.myOffset[1],aOffs.myOffset[2]);
    }
  } else {
    vtkFloatingPointType aDist = 0;
    vtkFloatingPointType aShift = 0;
    vtkFloatingPointType aPrevDist = 0;
    vtkFloatingPointType aPrevShift = 0;
    int i = 0;
    QMap<VISU::Prs3d_i*, int>::Iterator it;
    for (it = myPrsMap.begin(); it != myPrsMap.end(); ++it, i++) {
      VISU::Prs3d_i* aPrs = it.key();
      if (VISU_Actor* aActor = VISU::FindActor(myViewWindow, aPrs)) {
      int aAxis = getAxis();

      vtkFloatingPointType aZeroOffset[3];
        aZeroOffset[0] = aZeroOffset[1] = aZeroOffset[2] = 0;
      aActor->SetPosition(aZeroOffset);
        aActor->GetMapper()->Update();

      vtkFloatingPointType aBounds[6];
      aActor->GetBounds(aBounds);
      switch (aAxis) {
      case XAxis:
        aDist = fabs(aBounds[1] - aBounds[0]);
        break;
      case YAxis:
        aDist = fabs(aBounds[3] - aBounds[2]);
        break;
      case ZAxis:
        aDist = fabs(aBounds[5] - aBounds[4]);
      }
      vtkFloatingPointType aOffset[3];
        aOffset[0] = aOffset[1] = aOffset[2] = 0;
        aOffset[aAxis] =
          (aBounds[2*aAxis+1] < aBounds[2*aAxis]) ? -aBounds[2*aAxis+1] : -aBounds[2*aAxis];

        if (i > 0) {
          vtkFloatingPointType aCCDist = (aDist + aPrevDist) / 2.0;

          vtkFloatingPointType dx = fabs(aBounds[1] - aBounds[0]);
          vtkFloatingPointType dy = fabs(aBounds[3] - aBounds[2]);
          vtkFloatingPointType dz = fabs(aBounds[5] - aBounds[4]);
          vtkFloatingPointType max = (dx > dy) ? dx : dy;
          max = (dz > max) ? dz : max;
          max /= 100.0;

          if (aCCDist < max) {
            // set base distance between centers of bounding boxes
            // to minimal (but big enough) size of current bounding box
            if (dx < max) dx = FLT_MAX;
            if (dy < max) dy = FLT_MAX;
            if (dz < max) dz = FLT_MAX;

            aCCDist = (dx < dy) ? dx : dy;
            aCCDist = (dz < aCCDist) ? dz : aCCDist;
          }

          //-------------------------------->
          //             aShift
          //                                 aDist / 2
          //                                 <-->
          //            .--------------.     .------.
          //----------->|              |     |      |
          // aPrevShift '--------------'     '------'
          //            <------>
          //            aPrevDist / 2
          //
          //                    <--------------->
          //                    (aDist + aPrevDist) * getDistance() / 2

          aShift = aPrevShift + aPrevDist/2.0 + aCCDist*getDistance() - aDist/2.0;
        }

      aOffset[aAxis] += aShift;
      aActor->SetPosition(aOffset);
      if (mySaveChk)
        if (mySaveChk->isChecked())
          aPrs->SetOffset(aOffset[0],aOffset[1],aOffset[2]);

      aPrevDist = aDist;
      aPrevShift = aShift;
      }
    } // end of myPrsMap loop
    // Loop in PointMap3D the same as previous loop
    QMap<VISU::PointMap3d_i*, int>::Iterator itt;
    for (itt = myPointMapPrsMap.begin(); itt != myPointMapPrsMap.end(); ++itt, i++) {
      VISU::PointMap3d_i* aPrs = itt.key();
      if (VISU_ActorBase* aActor = VISU::FindActorBase(myViewWindow, aPrs)) {
      int aAxis = getAxis();

      vtkFloatingPointType aZeroOffset[3];
      aZeroOffset[0] = aZeroOffset[1] = aZeroOffset[2] = 0;
      aActor->SetPosition(aZeroOffset);
        aActor->GetMapper()->Update();

      vtkFloatingPointType aBounds[6];
      aActor->GetBounds(aBounds);
      switch (aAxis) {
      case XAxis:
        aDist = fabs(aBounds[1] - aBounds[0]);
        break;
      case YAxis:
        aDist = fabs(aBounds[3] - aBounds[2]);
        break;
      case ZAxis:
        aDist = fabs(aBounds[5] - aBounds[4]);
      }
      vtkFloatingPointType aOffset[3];
        aOffset[0] = aOffset[1] = aOffset[2] = 0;
        aOffset[aAxis] =
          (aBounds[2*aAxis+1] < aBounds[2*aAxis]) ? -aBounds[2*aAxis+1] : -aBounds[2*aAxis];

        if (i > 0) {
          vtkFloatingPointType aCCDist = (aDist + aPrevDist) / 2.0;

          vtkFloatingPointType dx = fabs(aBounds[1] - aBounds[0]);
          vtkFloatingPointType dy = fabs(aBounds[3] - aBounds[2]);
          vtkFloatingPointType dz = fabs(aBounds[5] - aBounds[4]);
          vtkFloatingPointType max = (dx > dy) ? dx : dy;
          max = (dz > max) ? dz : max;
          max /= 100.0;

          if (aCCDist < max) {
            // set base distance between centers of bounding boxes
            // to minimal (but big enough) size of current bounding box
            if (dx < max) dx = FLT_MAX;
            if (dy < max) dy = FLT_MAX;
            if (dz < max) dz = FLT_MAX;

            aCCDist = (dx < dy) ? dx : dy;
            aCCDist = (dz < aCCDist) ? dz : aCCDist;
          }
          aShift = aPrevShift + aPrevDist/2.0 + aCCDist*getDistance() - aDist/2.0;
        }

      aOffset[aAxis] += aShift;
      aActor->SetPosition(aOffset);
      if (mySaveChk)
        if (mySaveChk->isChecked())
          aPrs->SetOffset(aOffset[0],aOffset[1],aOffset[2]);

      aPrevDist = aDist;
      aPrevShift = aShift;
      }
    } // end of myPointMapPrsMap loop
  }
  myViewWindow->getRenderer()->ResetCameraClippingRange();
  myViewWindow->Repaint();
}


//------------------------------------------------------------------------
//------------------------------------------------------------------------

class SetupDlg::LineEdit : public QLineEdit
{
public:
  LineEdit( QWidget* p = 0 ) : QLineEdit( p ) {}
  virtual ~LineEdit() {}

protected:
  void    focusOutEvent( QFocusEvent* e )
  {
    QLineEdit::focusOutEvent( e );

    if ( text().isEmpty() )
      emit editingFinished();
  }
  void    keyPressEvent( QKeyEvent* e )
  {
    QLineEdit::keyPressEvent( e );

    if ( text().isEmpty() && e->key() == Qt::Key_Return )
      emit returnPressed();
  }
};


//------------------------------------------------------------------------
//------------------------------------------------------------------------

SetupDlg::SetupDlg (QWidget* theParent,
                VisuGUI* theModule,
                VISU_TimeAnimation* theAnimator) :
  QDialog(theParent,
        Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
  myAnimator(theAnimator),
  myModule(theModule),
  myIsRegenerate( false )
{
  setModal( true );
  setWindowTitle("Setup Animation");
  setSizeGripEnabled( TRUE );

  QVBoxLayout* aMainLayout = new QVBoxLayout(this);
  aMainLayout->setMargin( 7 );
  aMainLayout->setSpacing(5);

  // Range of time stamps
  myUseRangeBox = new QGroupBox("Use range of time stamps", this);
  myUseRangeBox->setCheckable( true );
  myUseRangeBox->setChecked(myAnimator->isRangeDefined());

  QHBoxLayout* aRangeLayout = new QHBoxLayout( myUseRangeBox );
  aRangeLayout->setMargin( 11 );
  aRangeLayout->setSpacing( 6 );

  double aMaxTime = myAnimator->getMaxTime();
  double aMinTime = myAnimator->getMinTime();
  double aStep = 1;
  if( myAnimator->getNbFields() > 0 ) {
    if ( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL )
      aStep = (aMaxTime - aMinTime) / (myAnimator->getFieldData(0).myNbTimes - 1);
    else { // successive animation mode
      std::pair<int,long> aLastFieldFrame(myAnimator->getNbFields() - 1,
                                myAnimator->getFieldData(myAnimator->getNbFields() - 1).myNbTimes - 1);
      aStep = (aMaxTime - aMinTime) / myAnimator->getAbsoluteFrameNumber(aLastFieldFrame);
    }
  }

  QLabel* aMinLbl = new QLabel("From", myUseRangeBox);
  aRangeLayout->addWidget(aMinLbl);
  //myMinVal = new QtxDoubleSpinBox( aMinTime, aMaxTime, aStep, myUseRangeBox );
  myMinVal = new LineEdit( myUseRangeBox );
  myMinVal->setValidator( new QDoubleValidator( myMinVal ) );
  if ( myUseRangeBox->isChecked() )
    myMinVal->setText( QString::number( myAnimator->getMinRange() ) );
  else
    myMinVal->setText( QString::number( aMinTime ) );

  //  connect(myMinVal, SIGNAL( valueChanged(double)),
  //    this, SLOT( onMinValue(double) ));
  connect( myMinVal, SIGNAL( returnPressed() ), this, SLOT( onMinValue() ) );
  connect( myMinVal, SIGNAL( editingFinished() ), this, SLOT( onMinValue() ) );
//   connect( myMinVal, SIGNAL( textChanged(const QString&)),
//      this, SLOT( onMinValueEdit(const QString&) ));
  aRangeLayout->addWidget(myMinVal);

  QLabel* aMaxLbl = new QLabel("To", myUseRangeBox);
  aRangeLayout->addWidget(aMaxLbl);
  //myMaxVal = new QtxDoubleSpinBox( aMinTime, aMaxTime, aStep, myUseRangeBox );
  myMaxVal = new LineEdit( myUseRangeBox );
  myMaxVal->setValidator( new QDoubleValidator( myMaxVal ) );
  if ( myUseRangeBox->isChecked() )
    myMaxVal->setText( QString::number( myAnimator->getMaxRange() ) );
  else
    myMaxVal->setText( QString::number( aMaxTime ) );

  //  connect(myMaxVal, SIGNAL( valueChanged(double)),
  //    this, SLOT( onMaxValue(double) ));
  connect( myMaxVal, SIGNAL( returnPressed() ), this, SLOT( onMaxValue() ) );
  connect( myMaxVal, SIGNAL( editingFinished() ), this, SLOT( onMaxValue() ) );
//   connect(myMaxVal, SIGNAL( textChanged(const QString&)),
//      this, SLOT( onMaxValueEdit(const QString&) ));
  aRangeLayout->addWidget(myMaxVal);

  connect(myUseRangeBox, SIGNAL( toggled(bool)),
        this, SLOT( onRangeCheck(bool) ));

  aMainLayout->addWidget(myUseRangeBox);

  // Sequence of time stamps
  myUseSequenceBox = new QGroupBox("Use sequence of time stamps", this);
  myUseSequenceBox->setCheckable( true );
  myUseSequenceBox->setChecked( myAnimator->isSequenceDefined() );

  QGridLayout* aUseSequenceLayout = new QGridLayout( myUseSequenceBox );
  aUseSequenceLayout->setAlignment( Qt::AlignTop );
  aUseSequenceLayout->setSpacing( 6 );
  aUseSequenceLayout->setMargin( 11 );

  QLabel* anIndicesLbl = new QLabel("Indices", myUseSequenceBox);
  myIndices = new QLineEdit( myUseSequenceBox );

  myValues = new QListWidget( myUseSequenceBox );
  myValues->setSelectionMode( QAbstractItemView::ExtendedSelection );

  connect(myIndices, SIGNAL( textChanged(const QString&)),
        this, SLOT( onIndicesChanged(const QString&) ));

  connect(myValues, SIGNAL( itemSelectionChanged() ),
        this, SLOT( onValuesChanged() ) );

  connect(myUseSequenceBox, SIGNAL( toggled(bool)),
        this, SLOT( onSequenceCheck(bool) ));

  aUseSequenceLayout->addWidget( anIndicesLbl, 0, 0 );
  aUseSequenceLayout->addWidget( myIndices, 0, 1 );
  aUseSequenceLayout->addWidget( myValues, 1, 1, 1, 2 );

  aMainLayout->addWidget(myUseSequenceBox);

  // Fields and Properties
  QWidget* aPropFrame = new QWidget(this);
  QHBoxLayout* aHPropLayout = new QHBoxLayout( aPropFrame );
  aHPropLayout->setSpacing(5);
  aHPropLayout->setMargin(0);

  QGroupBox* aNamesBox = new QGroupBox("Fields",aPropFrame);
  aHPropLayout->addWidget( aNamesBox );
  QVBoxLayout* aVBoxLayout = new QVBoxLayout( aNamesBox );

  myFieldLst = new QListWidget(aNamesBox);
  aVBoxLayout->addWidget( myFieldLst );
  QStringList aFieldNames;
  // Find names of fields
  for (int i = 0; i < myAnimator->getNbFields(); i++) {
    _PTR(SObject) aSO = myAnimator->getFieldData(i).myField;
    VISU::Storable::TRestoringMap aRestoringMap = VISU::Storable::GetStorableMap(aSO);
    QString aFieldName(aRestoringMap["myName"]);
    if ( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL )
      aFieldNames.append(aFieldName);
    else if ( myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) {
      _PTR(SObject) aSObject = aSO->GetFather()->GetFather()->GetFather();
      VISU::Storable::TRestoringMap aRestoringMap = VISU::Storable::GetStorableMap(aSObject);
      QString aFileName(aRestoringMap["myInitFileName"]);
      aFileName = aFileName.right(aFileName.length() - (aFileName.lastIndexOf("/") + 1));
      aFieldNames.append(aFileName + QString(" : ") + aFieldName);
    }
  }
  myFieldLst->addItems(aFieldNames);

  if ( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL ) {
    myFieldLst->setCurrentRow(0);
    connect( myFieldLst, SIGNAL( currentRowChanged(int) ),
           this, SLOT( onFieldChange(int) ) );
  }
  else if ( myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE )
    myFieldLst->setSelectionMode(QAbstractItemView::NoSelection);

  QWidget* aSetupBox = new QWidget(aPropFrame);
  aHPropLayout->addWidget( aSetupBox );
  aVBoxLayout = new QVBoxLayout( aSetupBox );
  aVBoxLayout->setSpacing(5);
  aVBoxLayout->setMargin(0);

  QGroupBox* aPropBox = new QGroupBox("Properties", aSetupBox);
  aVBoxLayout->addWidget( aPropBox );
  QVBoxLayout* aPropVBLay = new QVBoxLayout( aPropBox );

  //QVGroupBox* aPropBox = new QVGroupBox("Properties", aPropFrame);
  myTypeCombo = new QComboBox(aPropBox);
  aPropVBLay->addWidget( myTypeCombo );
  connect( myTypeCombo, SIGNAL( activated(int) ),
         this, SLOT( onTypeChanged(int) ) );

  //  QPushButton* aBarBtn = new QPushButton("Scalar Bar...", aPropBox);
  //connect( aBarBtn, SIGNAL( clicked() ),
  //     this, SLOT( onScalarBarDlg() ) );

  myPropBtn = new QPushButton("Properties...", aPropBox);
  myPropBtn->setAutoDefault( false );
  aPropVBLay->addWidget( myPropBtn );
  //  myPropBtn->setEnabled(myAnimator->getFieldData(0).myPrsType != VISU::TSCALARMAP);
  connect( myPropBtn, SIGNAL( clicked() ),
         this, SLOT( onPreferencesDlg() ) );

  if (myAnimator->getNbFields() > 1 ) {
    if( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL ) {
      myArrangeBtn = new QPushButton("Arrange...", aSetupBox);
      aVBoxLayout->addWidget( myArrangeBtn );
      connect( myArrangeBtn, SIGNAL( clicked() ), this, SLOT( onArrangeDlg() ) );
    }
  }
  onFieldChange(0);
  aMainLayout->addWidget(aPropFrame);

  QWidget* aBtnBox = new QWidget(this);
  QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox);
  aBtnLayout->setContentsMargins( 5, 5, 0, 5 );
  //  aBtnLayout->addStretch();

  QPushButton* closeBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
  closeBtn->setAutoDefault( false );
  aBtnLayout->addStretch();
  aBtnLayout->addWidget( closeBtn );
  connect( closeBtn, SIGNAL( clicked() ), this, SLOT( onClose() ) );

  aMainLayout->addWidget( aBtnBox );
}

//------------------------------------------------------------------------
void SetupDlg::initialize()
{
  myValues->clear();

  _PTR(Study) aStudy = myAnimator->getStudy();

  if( myAnimator->getNbFields() == 0 )
    return;

  FieldData& aData = myAnimator->getFieldData( 0 );
  _PTR(SObject) aField = aData.myField;

  if ( !aField )
    return;

  _PTR(ChildIterator) anIter = aStudy->NewChildIterator(aField);
  anIter->Next(); // First is reference on support
  for(int index = 1; anIter->More(); anIter->Next(), index++)
  {
    double aTime = VISU_TimeAnimation::getTimeValue(anIter->Value());
    QString itemText = QString("[%1] - %2").arg( index ).arg( aTime );

    myValues->addItem( itemText );
  }

  QString anIndices( myAnimator->getAnimationSequence() );
  myIndices->setText( anIndices );
}

//------------------------------------------------------------------------
enum PrsComboItem {
  TSCALARMAP_ITEM     = 0, // VISU::TSCALARMAP
  TISOSURFACES_ITEM   = 1, // VISU::TISOSURFACES
  TCUTPLANES_ITEM     = 2, // VISU::TCUTPLANES
  TCUTLINES_ITEM      = 3, // VISU::TCUTLINES
  TCUTSEGMENT_ITEM    = 4, // VISU::TCUTSEGMENT
  TPLOT3D_ITEM        = 5, // VISU::TPLOT3D
  TDEFORMEDSHAPE_ITEM = 6, // VISU::TDEFORMEDSHAPE
  TVECTORS_ITEM       = 7, // VISU::TVECTORS
  TSTREAMLINES_ITEM   = 8, // VISU::TSTREAMLINES
  TGAUSSPOINTS_ITEM   = 9, // VISU::TGAUSSPOINTS
  TDEFORMEDSHAPEANDSCALARMAP_ITEM = 10 // VISU::TDEFORMEDSHAPEANDSCALARMAP
};

//------------------------------------------------------------------------
void SetupDlg::onClose()
{
  if ( !myUseRangeBox->isChecked() )
    myAnimator->setAnimationRange( 0, 0 );
  else
  {
    double min = myMinVal->text().toDouble();
    double max = myMaxVal->text().toDouble();
    myAnimator->setAnimationRange( qMin( min, max ), qMax( min, max ) );
  }

  if ( !myUseSequenceBox->isChecked() )
    myAnimator->setAnimationSequence( 0 );

  close();
}

//------------------------------------------------------------------------
void SetupDlg::onFieldChange (int theIndex)
{
  myTypeCombo->clear();
  myTypeId2ComboId.clear();
  myComboId2TypeId.clear();

  if( myAnimator->getNbFields() == 0 )
    return;

  // ATTENTION: append items in the same order like it is done in the PrsComboItem enumeration
  myTypeCombo->addItem("Scalar Map");   // item 0
  myTypeId2ComboId[TSCALARMAP_ITEM] = myComboId2TypeId.size();
  myComboId2TypeId.push_back(TSCALARMAP_ITEM);;

  myTypeCombo->addItem("Iso Surfaces"); // item 1
  myTypeId2ComboId[TISOSURFACES_ITEM] = myComboId2TypeId.size();
  myComboId2TypeId.push_back(TISOSURFACES_ITEM);;

  myTypeCombo->addItem("Cut Planes");   // item 2
  myTypeId2ComboId[TCUTPLANES_ITEM] = myComboId2TypeId.size();
  myComboId2TypeId.push_back(TCUTPLANES_ITEM);;

  myTypeCombo->addItem("Cut Lines");   // item 3
  myTypeId2ComboId[TCUTLINES_ITEM] = myComboId2TypeId.size();
  myComboId2TypeId.push_back(TCUTLINES_ITEM);;

  myTypeCombo->addItem("Cut Segment");  // item 4
  myTypeId2ComboId[TCUTSEGMENT_ITEM] = myComboId2TypeId.size();
  myComboId2TypeId.push_back(TCUTSEGMENT_ITEM);;

  myTypeCombo->addItem("Plot 3D");      // item 5
  myTypeId2ComboId[TPLOT3D_ITEM] = myComboId2TypeId.size();
  myComboId2TypeId.push_back(TPLOT3D_ITEM);;

  bool anEnableItems = false;
  bool anEnableGP = false;
  VISU::VISUType aPrsType;
  if ( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL ) { // parallel animation mode

    FieldData& aData = myAnimator->getFieldData(theIndex);
    _PTR(SObject) aSObject = aData.myField;
    VISU::Storable::TRestoringMap aRestoringMap = VISU::Storable::GetStorableMap(aSObject);
    long aNumComp = aRestoringMap["myNumComponent"].toLong();
    anEnableItems = (aNumComp > 1);

    long anEntityId = aRestoringMap["myEntityId"].toLong();
    anEnableGP = (anEntityId == VISU::CELL);

    aPrsType = aData.myPrsType;

  }
  else if ( myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) { // successive animation mode

    for (int i = 0; i < myAnimator->getNbFields(); i++) {
      _PTR(SObject) aSO = myAnimator->getFieldData(i).myField;
      VISU::Storable::TRestoringMap aRestoringMap = VISU::Storable::GetStorableMap(aSO);
      long aNumComp = aRestoringMap["myNumComponent"].toLong();
      anEnableItems = (aNumComp > 1);

      long anEntityId = aRestoringMap["myEntityId"].toLong();
      anEnableGP = (anEntityId == VISU::CELL);

      if ( !anEnableItems && !anEnableGP ) break;
    }

    aPrsType = myAnimator->getFieldData(0).myPrsType;

  }

  if (anEnableItems) {
    myTypeCombo->addItem("Deformed Shape"); // item 6
    myTypeId2ComboId[TDEFORMEDSHAPE_ITEM] = myComboId2TypeId.size();
    myComboId2TypeId.push_back(TDEFORMEDSHAPE_ITEM);;

    myTypeCombo->addItem("Vectors");        // item 7
    myTypeId2ComboId[TVECTORS_ITEM] = myComboId2TypeId.size();
    myComboId2TypeId.push_back(TVECTORS_ITEM);;

    myTypeCombo->addItem("Stream Lines");   // item 8
    myTypeId2ComboId[TSTREAMLINES_ITEM] = myComboId2TypeId.size();
    myComboId2TypeId.push_back(TSTREAMLINES_ITEM);;

    myTypeCombo->addItem("Deformed shape and Scalar map");   // item 10
    myTypeId2ComboId[TDEFORMEDSHAPEANDSCALARMAP_ITEM] = myComboId2TypeId.size();
    myComboId2TypeId.push_back(TDEFORMEDSHAPEANDSCALARMAP_ITEM);;
  }

  if(anEnableGP){
    myTypeCombo->addItem("Gauss Points");   // item 9
    myTypeId2ComboId[TGAUSSPOINTS_ITEM] = myComboId2TypeId.size();
    myComboId2TypeId.push_back(TGAUSSPOINTS_ITEM);;
  }

  switch (aPrsType) {
  case VISU::TSCALARMAP: //Scalar Map
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TSCALARMAP_ITEM]);
    break;
  case VISU::TISOSURFACES: //Iso Surfaces
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TISOSURFACES_ITEM]);
    break;
  case VISU::TCUTPLANES: //Cut Planes
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TCUTPLANES_ITEM]);
    break;
  case VISU::TCUTLINES: //Cut Lines
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TCUTLINES_ITEM]);
    break;
  case VISU::TCUTSEGMENT: //Cut Segment
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TCUTSEGMENT_ITEM]);
    break;
  case VISU::TPLOT3D: //Plot 3D
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TPLOT3D_ITEM]);
    break;
  case VISU::TDEFORMEDSHAPE: //Deformed Shape
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TDEFORMEDSHAPE_ITEM]);
    break;
  case VISU::TSCALARMAPONDEFORMEDSHAPE: //Scalar Map on Deformed Shape
  case VISU::TDEFORMEDSHAPEANDSCALARMAP:
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TDEFORMEDSHAPEANDSCALARMAP_ITEM]);
    break;
  case VISU::TVECTORS: //Vectors
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TVECTORS_ITEM]);
    break;
  case VISU::TSTREAMLINES: //Stream Lines
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TSTREAMLINES_ITEM]);
    break;
  case VISU::TGAUSSPOINTS: //Gauss Points
    myTypeCombo->setCurrentIndex(myTypeId2ComboId[TGAUSSPOINTS_ITEM]);
    break;
  }
  //myPropBtn->setEnabled(aData.myPrsType != VISU::TSCALARMAP);
}

//------------------------------------------------------------------------
void SetupDlg::onTypeChanged (int theIndex)
{
  int aType = myComboId2TypeId[theIndex];

  for (int i = 0; i < myAnimator->getNbFields(); i++) {
    FieldData& aData = ( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL ) ?
      myAnimator->getFieldData(myFieldLst->currentRow()) :
      myAnimator->getFieldData(i);

    switch (aType) {
    case TSCALARMAP_ITEM: //Scalar Map
      aData.myPrsType = VISU::TSCALARMAP;
      break;
    case TISOSURFACES_ITEM: //Iso Surfaces
      aData.myPrsType = VISU::TISOSURFACES;
      break;
    case TCUTPLANES_ITEM: //Cut Planes
      aData.myPrsType = VISU::TCUTPLANES;
      break;
    case TCUTLINES_ITEM: //Cut Lines
      aData.myPrsType = VISU::TCUTLINES;
      break;
    case TCUTSEGMENT_ITEM: //Cut Segment
      aData.myPrsType = VISU::TCUTSEGMENT;
      break;
    case TPLOT3D_ITEM: //Plot 3D
      aData.myPrsType = VISU::TPLOT3D;
      break;
    case TDEFORMEDSHAPE_ITEM: //Deformed Shape
      aData.myPrsType = VISU::TDEFORMEDSHAPE;
      break;
    case TDEFORMEDSHAPEANDSCALARMAP_ITEM: //Scalar Map on Deformed Shape
      aData.myPrsType = VISU::TDEFORMEDSHAPEANDSCALARMAP;
      break;
    case TVECTORS_ITEM: //Vectors
      aData.myPrsType = VISU::TVECTORS;
      break;
    case TSTREAMLINES_ITEM: //Stream Lines
      aData.myPrsType = VISU::TSTREAMLINES;
      break;
    case TGAUSSPOINTS_ITEM: //Gauss Points
      aData.myPrsType = VISU::TGAUSSPOINTS;
      break;
    }
    myAnimator->clearData(aData);

    if ( myAnimator->getAnimationMode() == VISU::Animation::PARALLEL ) // parallel animation mode
      break;
  }
  //myPropBtn->setEnabled(aData.myPrsType != VISU::TSCALARMAP);
  //myAnimator->generatePresentations(myFieldLst->currentItem());
}


//------------------------------------------------------------------------
namespace
{
  template<class TPrs3d, class TDialog>
  void
  EditPrs(VisuGUI* theModule,
        FieldData& theData,
        VISU_TimeAnimation* theAnimator)
  {
    TDialog* aDlg = new TDialog(theModule);
    TPrs3d* aPrs3d = dynamic_cast<TPrs3d*>(theData.myPrs[0]);
    aDlg->initFromPrsObject(aPrs3d, true);
    if (aDlg->exec() && aDlg->storeToPrsObject(dynamic_cast<TPrs3d*>(aPrs3d))) {

      for (long aFrameId = 1; aFrameId < theData.myNbFrames; aFrameId++){
      VISU::ColoredPrs3d_i* aColoredPrs3d = theData.myPrs[aFrameId];
      aColoredPrs3d->SameAs(aPrs3d);
      }

      if ( theAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) {
      for (int aFieldId = 1; aFieldId < theAnimator->getNbFields(); aFieldId++) {
        FieldData& aFieldData = theAnimator->getFieldData(aFieldId);
        for (long aFrameId = 0; aFrameId < aFieldData.myNbFrames; aFrameId++) {
          VISU::ColoredPrs3d_i* aColoredPrs3d = aFieldData.myPrs[aFrameId];
          std::string aTitle = aColoredPrs3d->GetCTitle();
          aColoredPrs3d->SameAs(aPrs3d);
          aColoredPrs3d->SetTitle(aTitle.c_str());
        }
      }
      }
    }
    delete aDlg;
  }
}


void SetupDlg::onPreferencesDlg()
{
  if(myAnimator->getNbFields() == 0){
    SUIT_MessageBox::warning(this,
                           tr("ERROR"),
                           VisuGUI_TimeAnimationDlg::tr("MSG_NO_ANIMATIONDATA"),
                           tr("&OK"));
    return;
  }

  SUIT_OverrideCursor c;

  VISU::Animation::AnimationMode aMode = myAnimator->getAnimationMode();
  int aRefFieldId = ( aMode == VISU::Animation::PARALLEL ) ? myFieldLst->currentRow() : 0;
  FieldData& aData = myAnimator->getFieldData(aRefFieldId);
  if (aData.myPrs.empty())
    myAnimator->generatePresentations(aRefFieldId);

  if ( myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) {
    for (int i = 0; i < myAnimator->getNbFields(); i++) {
      if ( i != aRefFieldId && myAnimator->getFieldData(i).myPrs.empty() )
      myAnimator->generatePresentations(i);
    }
  }

  if(!aData.myNbFrames || aData.myPrs.empty() || !aData.myPrs[0]){
    QApplication::restoreOverrideCursor();
    SUIT_MessageBox::warning(this,
                           tr("ERROR"),
                           VisuGUI_TimeAnimationDlg::tr("MSG_NO_ANIMATIONDATA"),
                           tr("&OK"));
    return;
  }

  int aType = myComboId2TypeId[myTypeCombo->currentIndex()];
  switch (aType) {
  case TSCALARMAP_ITEM: //Scalar Map
    c.suspend();
    EditPrs<VISU::ScalarMap_i,VisuGUI_ScalarBarDlg>(myModule,aData,myAnimator);
    break;
  case TISOSURFACES_ITEM: //Iso Surfaces
    c.suspend();
    EditPrs<VISU::IsoSurfaces_i,VisuGUI_IsoSurfacesDlg>(myModule,aData,myAnimator);
    break;
  case TCUTPLANES_ITEM: //Cut Planes
    c.suspend();
    EditPrs<VISU::CutPlanes_i,VisuGUI_CutPlanesDlg>(myModule,aData,myAnimator);
    break;
  case TCUTLINES_ITEM: //Cut Lines
    c.suspend();
    EditPrs<VISU::CutLines_i,VisuGUI_CutLinesDlg>(myModule,aData,myAnimator);
    break;
  case TCUTSEGMENT_ITEM: //Cut Segment
    c.suspend();
    EditPrs<VISU::CutSegment_i,VisuGUI_CutSegmentDlg>(myModule,aData,myAnimator);
    break;
  case TPLOT3D_ITEM: //Plot 3D
    c.suspend();
    EditPrs<VISU::Plot3D_i,VisuGUI_Plot3DDlg>(myModule,aData,myAnimator);
    break;
  case TDEFORMEDSHAPE_ITEM: //Deformed Shape
    c.suspend();
    EditPrs<VISU::DeformedShape_i,VisuGUI_DeformedShapeDlg>(myModule,aData,myAnimator);
    break;
  case TDEFORMEDSHAPEANDSCALARMAP_ITEM: //Scalar Map on Deformed Shape
    c.suspend();
    {
      typedef VisuGUI_DeformedShapeAndScalarMapDlg DLG;
      typedef VISU::DeformedShapeAndScalarMap_i TYPE;
      DLG* aDlg = new DLG (myModule);
      TYPE* aPrs3d = dynamic_cast<TYPE*>(aData.myPrs[0]);
      aDlg->initFromPrsObject(aPrs3d, true);
      if (aDlg->exec() && aDlg->storeToPrsObject(aData.myPrs[0])) {
        for (long aFrameId = 1; aFrameId < aData.myNbFrames; aFrameId++){
          TYPE* aDeformedPrs3d = dynamic_cast<TYPE*>(aData.myPrs[aFrameId]);
          //Set correct time stamp number
          int aTimeStampNum = aDeformedPrs3d->GetScalarTimeStampNumber();
          aDeformedPrs3d->SameAs(aPrs3d);
          aDeformedPrs3d->SetScalarField(aDeformedPrs3d->GetScalarEntity(),
                                         aDeformedPrs3d->GetScalarFieldName(),
                                         aTimeStampNum);

        }

        if ( myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) {
          for (int aFieldId = 1; aFieldId < myAnimator->getNbFields(); aFieldId++) {
            FieldData& aFieldData = myAnimator->getFieldData(aFieldId);
            for (long aFrameId = 0; aFrameId < aFieldData.myNbFrames; aFrameId++) {
              TYPE* aDeformedPrs3d = dynamic_cast<TYPE*>(aFieldData.myPrs[aFrameId]);
              std::string aTitle = aDeformedPrs3d->GetCTitle();
              //Set correct time stamp number
              int aTimeStampNum = aDeformedPrs3d->GetScalarTimeStampNumber();
              aDeformedPrs3d->SameAs(aPrs3d);
              aDeformedPrs3d->SetTitle(aTitle.c_str());
              aDeformedPrs3d->SetScalarField(aDeformedPrs3d->GetScalarEntity(),
                                             aDeformedPrs3d->GetScalarFieldName(),
                                             aTimeStampNum);

            }
          }
        }
      }
      delete aDlg;
    }
    break;
  case TVECTORS_ITEM: //Vectors
    c.suspend();
    EditPrs<VISU::Vectors_i,VisuGUI_VectorsDlg>(myModule,aData,myAnimator);
    break;
  case TSTREAMLINES_ITEM: //Stream Lines
    c.suspend();
    EditPrs<VISU::StreamLines_i,VisuGUI_StreamLinesDlg>(myModule,aData,myAnimator);
    break;
  case TGAUSSPOINTS_ITEM: //Gauss Points
    c.suspend();
    EditPrs<VISU::GaussPoints_i,VisuGUI_GaussPointsDlg>(myModule,aData,myAnimator);
    break;
  }
}


//------------------------------------------------------------------------
void SetupDlg::onArrangeDlg()
{
  ArrangeDlg aDlg(this, myAnimator);
  aDlg.exec();
}

//------------------------------------------------------------------------
void SetupDlg::onRangeCheck (bool theCheck)
{
  if( theCheck )
  {
    myUseSequenceBox->blockSignals( true );
    myUseSequenceBox->setChecked( false );
    myUseSequenceBox->blockSignals( false );
  }

  if (!theCheck)
    myAnimator->setAnimationRange(0, 0);
  else
    myAnimator->setAnimationRange(myMinVal->text().toDouble(), myMaxVal->text().toDouble());

  setIsRegenerate( true );
}

//------------------------------------------------------------------------
void SetupDlg::onMinValue()
{
  double aVal = myMinVal->text().toDouble();
  aVal = qMax( qMin( aVal, myAnimator->getMaxRange() ), myAnimator->getMinTime() );
  myAnimator->setAnimationRange( aVal, myAnimator->getMaxRange() );
  myMinVal->setText( QString::number( aVal ) );
  myMinVal->setFocus();

  setIsRegenerate( true );
}

//------------------------------------------------------------------------
void SetupDlg::onMaxValue()
{
  double aVal = myMaxVal->text().toDouble();
  aVal = qMin( qMax( aVal, myAnimator->getMinRange() ), myAnimator->getMaxTime() );
  myAnimator->setAnimationRange( myAnimator->getMinRange(), aVal );
  myMaxVal->setText( QString::number( aVal ) );
  myMaxVal->setFocus();

  setIsRegenerate( true );
}

//------------------------------------------------------------------------
void SetupDlg::onMinValueEdit (const QString& theVal)
{
  double aVal = theVal.toDouble();
  if ((aVal > myAnimator->getMaxRange()) || (aVal < myAnimator->getMinRange())){
    myMinVal->setText( QString::number(myAnimator->getMinTime()) );
    myMinVal->setFocus();
    return;
  }
}

//------------------------------------------------------------------------
void SetupDlg::onMaxValueEdit (const QString& theVal)
{
  double aVal = theVal.toDouble();
  if ((aVal > myAnimator->getMaxRange()) || (aVal < myAnimator->getMinRange())) {
    myMaxVal->setText( QString::number(myAnimator->getMaxTime()) );
    myMaxVal->setFocus();
  }
}

//------------------------------------------------------------------------
void SetupDlg::onSequenceCheck( bool theCheck )
{
  if( theCheck )
  {
    myUseRangeBox->blockSignals( true );
    myUseRangeBox->setChecked( false );
    myUseRangeBox->blockSignals( false );
  }

  QString anIndices = myIndices->text();
  myAnimator->setAnimationSequence( anIndices.toLatin1().data() );

  setIsRegenerate( true );
}

//------------------------------------------------------------------------
void SetupDlg::onIndicesChanged( const QString& theIndices )
{
  bool aCorrect = true;
  int aLimit = myValues->count();

  QList<long> anIndicesList;
  aCorrect = myAnimator->getIndicesFromSequence( theIndices, anIndicesList );

  myValues->blockSignals( true );
  myValues->clearSelection();

  QList<long>::iterator indIt = anIndicesList.begin();
  QList<long>::iterator indItEnd = anIndicesList.end();
  for( int i = 0; indIt != indItEnd; ++indIt, i++ )
  {
    long anIndex = *indIt;
    if( anIndex < 1 || anIndex > aLimit )
    {
      aCorrect = false;
      myValues->clearSelection();
      break;
    }
    myValues->item( anIndex-1 )->setSelected( true );
  }

  myValues->blockSignals( false );

  QPalette palette = myIndices->palette();

  if( !aCorrect )
  {
    palette.setColor(myIndices->foregroundRole(), Qt::red);
    myIndices->setPalette(palette);
    return;
  }

  palette.setColor(myIndices->foregroundRole(), Qt::black);
  myIndices->setPalette(palette);

  myAnimator->setAnimationSequence( theIndices.toLatin1().data() );

  setIsRegenerate( true );
}

//------------------------------------------------------------------------
void SetupDlg::onValuesChanged()
{
  int aLimit = myValues->count();

  QString anIndices;

  for( int i = 0; i < aLimit; i++ )
  {
    if( !myValues->item( i )->isSelected() )
      continue;

    QString aString = QString::number( i+1 );

    bool aPrevSelected = i != 0 && myValues->item( i-1 )->isSelected();
    bool aNextSelected = i != aLimit - 1 && myValues->item( i+1 )->isSelected();
    if( aPrevSelected )
    {
      if( aNextSelected )
      aString = "";
      else
      aString += ",";
    }
    else
    {
      if( aNextSelected )
      aString += "-";
      else
      aString += ",";
    }

    anIndices += aString;
  }

  if( anIndices.right( 1 ) == "," )
    anIndices.truncate( anIndices.length() - 1 );

  myIndices->blockSignals( true );

  QPalette palette = myIndices->palette();
  palette.setColor(myIndices->foregroundRole(), Qt::black);
  myIndices->setPalette(palette);

  myIndices->setText( anIndices );
  myIndices->blockSignals( false );

  myAnimator->setAnimationSequence( anIndices.toLatin1().data() );

  setIsRegenerate( true );
}

//------------------------------------------------------------------------
static const char * firstIco[] = {
"18 10 2 1",
"     g None",
".    g #000000",
"         .     .  ",
"  ..    ..    ..  ",
"  ..   ...   ...  ",
"  ..  ....  ....  ",
"  .. ..... .....  ",
"  .. ..... .....  ",
"  ..  ....  ....  ",
"  ..   ...   ...  ",
"  ..    ..    ..  ",
"         .     .  "};


static const char * lastIco[] = {
"18 10 2 1",
"     g None",
".    g #000000",
"  .     .         ",
"  ..    ..    ..  ",
"  ...   ...   ..  ",
"  ....  ....  ..  ",
"  ..... ..... ..  ",
"  ..... ..... ..  ",
"  ....  ....  ..  ",
"  ...   ...   ..  ",
"  ..    ..    ..  ",
"  .     .         "};


static const char * leftIco[] = {
"11 10 2 1",
"     g None",
".    g #000000",
"    .     .",
"   ..    ..",
"  ...   ...",
" ....  ....",
"..... .....",
"..... .....",
" ....  ....",
"  ...   ...",
"   ..    ..",
"    .     ."};

static const char * playIco[] = {
"14 14 2 1",
"     g None",
".    g #000000",
"              ",
"              ",
"  ..          ",
"  ....        ",
"  ......      ",
"  ........    ",
"  ..........  ",
"  ..........  ",
"  ........    ",
"  ......      ",
"  ....        ",
"  ..          ",
"              ",
"              "};

static QPixmap MYplayPixmap(playIco);


static const char * rightIco[] = {
"11 10 2 1",
"     g None",
".    g #000000",
".     .    ",
"..    ..   ",
"...   ...  ",
"....  .... ",
"..... .....",
"..... .....",
"....  .... ",
"...   ...  ",
"..    ..   ",
".     .    "};


static const char * pauseIco[] = {
"14 14 2 1",
"     g None",
".    g #000000",
"              ",
"              ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"   ..    ..   ",
"              ",
"              "};

static QPixmap MYpausePixmap(pauseIco);


VisuGUI_TimeAnimationDlg::VisuGUI_TimeAnimationDlg (VisuGUI* theModule,
                                        _PTR(Study) theStudy,
                                        VISU::Animation::AnimationMode theMode) :
  QDialog(VISU::GetDesktop(theModule),
        Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
  myModule(theModule),
  mySetupDlg(NULL)
{
  setAttribute( Qt::WA_DeleteOnClose, true );
  setModal( false );
  if ( theMode == VISU::Animation::PARALLEL )
    setWindowTitle(tr("PARALLEL_ANIMATION"));
  else
    setWindowTitle(tr("SUCCESSIVE_ANIMATION"));
  setSizeGripEnabled( TRUE );

  myAnimator = new VISU_TimeAnimation (theStudy);
  myAnimator->setViewer(VISU::GetActiveViewWindow<SVTK_ViewWindow>(theModule));
  connect(myAnimator, SIGNAL(frameChanged(long, double)), this, SLOT(onExecution(long, double)));
  connect(myAnimator, SIGNAL(stopped()),            this, SLOT(onStop()));
  myAnimator->setAnimationMode(theMode);

  QVBoxLayout* aMainLayout = new QVBoxLayout(this);
  aMainLayout->setMargin( 7 );
  aMainLayout->setSpacing(5);

  mySetupBtn = new QPushButton("Setup Animation...", this);
  connect( mySetupBtn, SIGNAL( clicked() ),
         this, SLOT( onSetupDlg() ) );
  aMainLayout->addWidget(mySetupBtn);

  myGenBtn = new QPushButton("Generate frames", this);
  connect( myGenBtn, SIGNAL( clicked() ),
         this, SLOT( createFrames() ) );
  aMainLayout->addWidget(myGenBtn);

  myPlayFrame = new QFrame(this);
  myPlayFrame->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
  myPlayFrame->setLineWidth( 1 );


  // --- Play controls ---
  QGridLayout* TopLayout = new QGridLayout( myPlayFrame );
  TopLayout->setSpacing( 6 );
  TopLayout->setMargin( 11 );

  myTimeLbl = new QLabel("0", myPlayFrame);
  TopLayout->addWidget(myTimeLbl, 0, 0, 1, 3, Qt::AlignHCenter);

  mySlider = new QSlider( myPlayFrame);
  mySlider->setOrientation(Qt::Horizontal);
  mySlider->setMinimum(0);
  mySlider->setMaximum(3);
  mySlider->setTickInterval(1);
  //mySlider->setTickmarks(QSlider::Below);
  mySlider->setTracking(false);
  connect( mySlider, SIGNAL( sliderMoved(int) ),
         this, SLOT( onWindowChanged(int) ) );
  TopLayout->addWidget(mySlider, 1, 0, 1, 3);

  myPlayBtn = new QPushButton(myPlayFrame);
  myPlayBtn->setIcon(MYplayPixmap);
  myPlayBtn->setCheckable(true);
  connect( myPlayBtn, SIGNAL( clicked() ),
         this, SLOT( onPlayPressed() ) );
  TopLayout->addWidget(myPlayBtn, 2, 0, 1, 2);

  QPushButton* aBackBtn = new QPushButton(myPlayFrame);
  aBackBtn->setIcon(QPixmap(leftIco));
  connect( aBackBtn, SIGNAL( clicked() ),
         this, SLOT( onBackPressed() ) );
  TopLayout->addWidget(aBackBtn, 3, 0);

  QPushButton* aForvardBtn = new QPushButton(myPlayFrame);
  aForvardBtn->setIcon(QPixmap(rightIco));
  connect( aForvardBtn, SIGNAL( clicked() ),
         this, SLOT( onForvardPressed() ) );
  TopLayout->addWidget(aForvardBtn, 3, 1);

  QPushButton* aFirstBtn = new QPushButton(myPlayFrame);
  aFirstBtn->setIcon(QPixmap(firstIco));
  connect( aFirstBtn, SIGNAL( clicked() ),
         this, SLOT( onFirstPressed() ) );
  TopLayout->addWidget(aFirstBtn, 4, 0);

  QPushButton* aLastBtn = new QPushButton(myPlayFrame);
  aLastBtn->setIcon(QPixmap(lastIco));
  connect( aLastBtn, SIGNAL( clicked() ),
         this, SLOT( onLastPressed() ) );
  TopLayout->addWidget(aLastBtn, 4, 1);

  QLabel* aSpeedLbl = new QLabel("Speed", myPlayFrame);
  TopLayout->addWidget(aSpeedLbl, 4, 2, Qt::AlignRight);

  QLCDNumber* aSpeedNum  = new QLCDNumber( 2, myPlayFrame );
  aSpeedNum->setSegmentStyle(QLCDNumber::Flat);
  aSpeedNum->display((int)myAnimator->getSpeed());
  TopLayout->addWidget(aSpeedNum, 4, 3);

  QwtWheel* aWheel = new QwtWheel(myPlayFrame);
  aWheel->setOrientation(Qt::Vertical);
  aWheel->setRange(1, 99, 1);
  aWheel->setValue((int)myAnimator->getSpeed());
  connect( aWheel, SIGNAL(valueChanged(double)),
         aSpeedNum, SLOT(display(double)) );
  connect( aWheel, SIGNAL(valueChanged(double)),
         this, SLOT(onSpeedChange(double)) );
  TopLayout->addWidget(aWheel, 1, 3, 3, 1, Qt::AlignRight);

  QCheckBox* aCycleCheck = new QCheckBox("Cycled animation",myPlayFrame);
  aCycleCheck->setChecked(myAnimator->isCycling());
  connect(aCycleCheck, SIGNAL(toggled(bool)), myAnimator, SLOT(setCyclingSlot(bool)));
  TopLayout->addWidget(aCycleCheck, 5, 0, 1, 4);

  QCheckBox* aPropCheck = new QCheckBox("Use proportional timing",myPlayFrame);
  aPropCheck->setChecked(myAnimator->isProportional());
  connect(aPropCheck, SIGNAL(toggled(bool)), myAnimator, SLOT(setProportionalSlot(bool)));
  TopLayout->addWidget(aPropCheck, 6, 0, 1, 4);

  // Pictures saving on disk
  QGroupBox* aSaveBox = new QGroupBox( "Saving", myPlayFrame );
  //aSaveBox->setColumnLayout(0, Qt::Horizontal );
  QGridLayout* aSaveLay = new QGridLayout(aSaveBox);
  aSaveLay->setSpacing( 5 );
  aSaveLay->setMargin( 5 );

  mySaveCheck = new QCheckBox("Save pictures to directory", aSaveBox);
  connect(mySaveCheck, SIGNAL( toggled(bool)),
          this, SLOT( onCheckDump(bool) ));
  aSaveLay->addWidget(mySaveCheck, 0, 0, 1, 3);

  QLabel* aFormatLbl = new QLabel("Saving format:", aSaveBox);
  aFormatLbl->setEnabled(false);
  connect(mySaveCheck, SIGNAL( toggled(bool)),
          aFormatLbl, SLOT( setEnabled(bool) ));
  aSaveLay->addWidget(aFormatLbl, 1, 0, 1, 2);

  myPicsFormat = new QComboBox(aSaveBox);
  QList<QByteArray> aDumpFormats = QImageWriter::supportedImageFormats();
  for (unsigned int i = 0; i < aDumpFormats.count(); i++) {
    myPicsFormat->addItem(aDumpFormats.at(i));
  }
  if (aDumpFormats.indexOf("jpeg") >= 0)
    myPicsFormat->setCurrentIndex(aDumpFormats.indexOf("jpeg"));
  else
    myPicsFormat->setCurrentIndex(0);

  myPicsFormat->setEnabled(false);
  aSaveLay->addWidget(myPicsFormat, 1, 2);
  connect(mySaveCheck, SIGNAL( toggled(bool)),
          myPicsFormat, SLOT( setEnabled(bool) ));
  connect(myPicsFormat, SIGNAL(  activated (int)),
        this, SLOT( onPicsFormatChanged()));

  QLabel* aPathLbl = new QLabel("Path:", aSaveBox);
  aPathLbl->setEnabled(false);
  connect(mySaveCheck, SIGNAL( toggled(bool)),
          aPathLbl, SLOT( setEnabled(bool) ));
  aSaveLay->addWidget(aPathLbl, 2, 0);

  myPathEdit = new QLineEdit(aSaveBox);
  myPathEdit->setReadOnly(true);
  myPathEdit->setEnabled(false);
  connect(mySaveCheck, SIGNAL( toggled(bool)),
          myPathEdit, SLOT( setEnabled(bool) ));
  aSaveLay->addWidget(myPathEdit, 2, 1);

  QPushButton* aBrowseBtn = new QPushButton("Browse...", aSaveBox);
  aBrowseBtn->setEnabled(false);
  connect(mySaveCheck, SIGNAL( toggled(bool)),
        aBrowseBtn, SLOT( setEnabled(bool) ));
  connect(aBrowseBtn, SIGNAL( clicked()),
        this, SLOT( onBrowse() ));
  mySaveCheck->setChecked(false);
  aSaveLay->addWidget(aBrowseBtn, 2, 2);

  mySaveAVICheck = new QCheckBox("Save animation to AVI file", aSaveBox);
  connect(mySaveAVICheck, SIGNAL( toggled(bool)),
          this, SLOT( onCheckDump(bool) ));
  aSaveLay->addWidget(mySaveAVICheck, 3, 0, 1, 3);

  myPathAVILbl = new QLabel("Path:", aSaveBox);
  myPathAVILbl->setEnabled(false);
  //connect(mySaveAVICheck, SIGNAL( toggled(bool)),
  //        myPathAVILbl, SLOT( setEnabled(bool) ));
  aSaveLay->addWidget(myPathAVILbl, 4, 0);

  myPathAVIEdit = new QLineEdit(aSaveBox);
  myPathAVIEdit->setReadOnly(true);
  myPathAVIEdit->setEnabled(false);
  //connect(mySaveAVICheck, SIGNAL( toggled(bool)),
  //        myPathAVIEdit, SLOT( setEnabled(bool) ));
  aSaveLay->addWidget(myPathAVIEdit, 4, 1);

  myBrowseAVIBtn = new QPushButton("Browse...", aSaveBox);
  myBrowseAVIBtn->setEnabled(false);
  //connect(mySaveAVICheck, SIGNAL( toggled(bool)),
  //        myBrowseAVIBtn, SLOT( setEnabled(bool) ));
  connect(myBrowseAVIBtn, SIGNAL( clicked()),
        this, SLOT( onBrowseAVI() ));
  aSaveLay->addWidget(myBrowseAVIBtn, 4, 2);

  mySaveAVICheck->setChecked(false);
  //mySaveAVICheck->setEnabled(myAnimator->checkAVIMaker());

  TopLayout->addWidget(aSaveBox, 7, 0, 1, 4);

  QCheckBox* aCleanMemCheck = new QCheckBox("Clean memory at each frame",myPlayFrame);
  aCleanMemCheck->setChecked(myAnimator->isCleaningMemoryAtEachFrame());
  connect(aCleanMemCheck, SIGNAL(toggled(bool)), myAnimator, SLOT(setCleaningMemoryAtEachFrameSlot(bool)));
  TopLayout->addWidget(aCleanMemCheck, 8, 0, 1, 4);

  aMainLayout->addWidget(myPlayFrame);

  // Animation publishing in study
  QWidget* aPublishBox = new QWidget(this);
  QHBoxLayout* aPubHBLay = new QHBoxLayout( aPublishBox );
  aPubHBLay->setMargin( 0 );

  myPublishBtn = new QPushButton("Publish to study", aPublishBox);
  aPubHBLay->addWidget( myPublishBtn );
  connect(myPublishBtn, SIGNAL(clicked()), this, SLOT(publishToStudy()));

  mySaveBtn = new QPushButton("Save Animation", aPublishBox);
  mySaveBtn->setEnabled(myAnimator->isSavedInStudy());
  aPubHBLay->addWidget( mySaveBtn );
  connect(mySaveBtn, SIGNAL(clicked()), this, SLOT(saveToStudy()));

  aMainLayout->addWidget(aPublishBox);


  QWidget* aBtnBox = new QWidget(this);
  QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox);
  aBtnLayout->setContentsMargins( 5, 5, 0, 5 );
  aBtnLayout->addStretch();

  QPushButton* aCloseBtn = new QPushButton(tr("BUT_CLOSE"), aBtnBox);
  aBtnLayout->addWidget( aCloseBtn );
  connect(aCloseBtn, SIGNAL(clicked()), this, SLOT(close()));

  QPushButton* aHelpBtn = new QPushButton(tr("BUT_HELP"), aBtnBox);
  aBtnLayout->addWidget( aHelpBtn );
  connect(aHelpBtn, SIGNAL(clicked()), this, SLOT(onHelp()));

  SUIT_Study* aStudy = VISU::GetAppStudy(myModule);
  connect(aStudy, SIGNAL(destroyed()), this, SLOT(close()));

  connect(myAnimator->getViewer(), SIGNAL(destroyed()), this, SLOT(close()));
  connect(myAnimator->getViewer(), SIGNAL(closing(SUIT_ViewWindow*)), this, SLOT(close()));

  aMainLayout->addWidget(aBtnBox);

  myPlayFrame->setEnabled(false);
}

//------------------------------------------------------------------------
VisuGUI_TimeAnimationDlg::~VisuGUI_TimeAnimationDlg()
{
  if (myAnimator != NULL) {
    delete myAnimator;
    myAnimator = NULL;
    if ( VISU::GetActiveViewWindow<SVTK_ViewWindow>(myModule) )
      VISU::GetActiveViewWindow<SVTK_ViewWindow>(myModule)->Repaint();
  }
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onTypeChange (int index)
{
  stopAnimation();
  myPropBtn->setEnabled(index != 0);

  clearView();
  myPlayFrame->setEnabled(false);
}

//------------------------------------------------------------------------
bool VisuGUI_TimeAnimationDlg::addField (_PTR(SObject) theSObject)
{
  myPlayFrame->setEnabled(false);
  return myAnimator->addField(theSObject);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::createFrames()
{
  stopAnimation();
  SUIT_OverrideCursor c;

  bool isRegenerate = mySetupDlg->isRegenerate();

  for (int i = 0; i < myAnimator->getNbFields(); i++) {
    FieldData& aFieldData = myAnimator->getFieldData(i);
    if( aFieldData.myPrs.empty() )
    {
      //myAnimator->generatePresentations(i);
      GeneratePresentations(i,myAnimator);
      continue;
    }

    // ouv : IPAL18064
    // even if aFieldData is not empty, we must regenerate presentations,
    // when a range or a sequence of the animation has been changed
    if( isRegenerate )
    {
      GeneratePresentations(i,myAnimator);
      /*
      VISU::ColoredPrs3d_i* aPrs3d = dynamic_cast<VISU::ColoredPrs3d_i*>(aFieldData.myPrs[0]);
      if( !aPrs3d )
      continue;

      myAnimator->generatePresentations(i);

      aFieldData = myAnimator->getFieldData(i);
      for (long aFrameId = 0; aFrameId < aFieldData.myNbFrames; aFrameId++) {
      VISU::ColoredPrs3d_i* aColoredPrs3d = aFieldData.myPrs[aFrameId];
      std::string aTitle = aColoredPrs3d->GetCTitle();
      aColoredPrs3d->SameAs(aPrs3d);
      if ( aFrameId != 0 && myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE ) {
        aColoredPrs3d->SetTitle(aTitle.c_str());
      }
      }
      */
    }
  }
  if( isRegenerate )
    mySetupDlg->setIsRegenerate( false );

  if (myAnimator->getNbFrames() == 0) {
    myPlayFrame->setEnabled(false);
    c.suspend();
    SUIT_MessageBox::warning(this,
                           tr("ERROR"),
                           tr("MSG_NO_ANIMATIONDATA"),
                           tr("&OK"));
    return;
  }
  mySlider->setMaximum(myAnimator->getNbFrames()-1);
  myPlayFrame->setEnabled(true);
  if (!myAnimator->generateFrames()) {
    c.suspend();
    //myPlayFrame->setEnabled(false);
    SUIT_MessageBox::warning(this,
                           tr("ERROR"),
                           myAnimator->getLastErrorMsg(),
                           tr("&OK"));
    return;
  }
  //myPlayFrame->setEnabled(true);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onPlayPressed()
{
  if (myPlayBtn->isChecked() && (!myAnimator->isRunning())) {
    myPlayBtn->setIcon(MYpausePixmap);
    if (mySaveCheck->isChecked()) {
      onPicsFormatChanged();
      onPathChanged();

    } else if (mySaveAVICheck->isChecked()) {
      myAnimator->setDumpFormat("AVI");
      myAnimator->dumpTo(myPathAVIEdit->text().toLatin1().data());
    } else {
      myAnimator->dumpTo("");
    }
    mySetupBtn->setEnabled(false);
    myGenBtn->setEnabled(false);
    myAnimator->startAnimation();
  } else {
    myPlayBtn->setIcon(MYplayPixmap);
    myAnimator->stopAnimation();
    mySetupBtn->setEnabled(true);
    myGenBtn->setEnabled(true);
  }
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onBackPressed()
{
  stopAnimation();
  myAnimator->prevFrame();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onForvardPressed()
{
  stopAnimation();
  myAnimator->nextFrame();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onLastPressed()
{
  stopAnimation();
  myAnimator->lastFrame();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onFirstPressed()
{
  stopAnimation();
  myAnimator->firstFrame();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::clearView()
{
  myAnimator->clearView();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::showEvent(QShowEvent* theEvent)
{
  mySetupDlg = new SetupDlg(this,myModule, myAnimator);
  mySetupDlg->initialize();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::closeEvent (QCloseEvent* theEvent)
{
  if (myAnimator != NULL) {
    myAnimator->stopAnimation();
    myAnimator->wait(500);
    if (myAnimator->isRunning() && (! myAnimator->isFinished())) {
      theEvent->ignore();
      QCloseEvent* aNewCloseEvent = new QCloseEvent;
      QApplication::postEvent( this, aNewCloseEvent );
    } else {
      QDialog::closeEvent(theEvent);
    }
  } else {
    QDialog::closeEvent(theEvent);
  }
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onWindowChanged (int index)
{
  if (myAnimator->isRunning()) return;
  myAnimator->gotoFrame(index);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onSpeedChange (double theSpeed)
{
  myAnimator->setSpeed((int)theSpeed);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::stopAnimation()
{
  myAnimator->stopAnimation();
  myPlayBtn->setChecked(false);
  myPlayBtn->setIcon(MYplayPixmap);
  mySetupBtn->setEnabled(true);
  myGenBtn->setEnabled(true);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onExecution (long theNewFrame, double theTime)
{
  myTimeLbl->setText(QString("%1").arg(theTime));
  mySlider->setValue(theNewFrame);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onSetupDlg()
{
  if (myAnimator->getNbFrames() > 0)
    myAnimator->firstFrame();
  mySetupDlg->exec();
  myPlayFrame->setEnabled(false);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onBrowse()
{
  //  QString aPath = SUIT_FileDlg::getExistingDirectory(this, "/", "Select path");
  QString aDir;
  if (myPathEdit->text().isEmpty())
    aDir = getenv("HOME");
  else
    aDir = myPathEdit->text();
  QString aPath = SUIT_FileDlg::getExistingDirectory(this, aDir, "Select path");
  if (!aPath.isEmpty())
    myPathEdit->setText(Qtx::addSlash(aPath));
  onPathChanged();
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onBrowseAVI()
{
  QStringList aFilter;
  aFilter.append( "AVI Files (*.avi)" );
  aFilter.append( "All Files (*.*)" );

  QString aDir;
  if (myPathAVIEdit->text().isEmpty())
    aDir = getenv("HOME");
  else {
    QFileInfo aFile(myPathAVIEdit->text());
    aDir = aFile.absoluteDir().absolutePath();
  }
  QString aPath = SUIT_FileDlg::getFileName(this, aDir, aFilter, "Select file", false);
  if (!aPath.isEmpty())
    myPathAVIEdit->setText(aPath);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onCheckDump(bool)
{
  const QObject* source = sender();
  if (source == mySaveCheck) {
    if (mySaveCheck->isChecked()) {
      onPicsFormatChanged();
      onPathChanged();
      if (mySaveAVICheck->isChecked())
      mySaveAVICheck->setChecked(false);
    } else {
      myAnimator->dumpTo("");
    }
    //mySaveAVICheck->setEnabled(!mySaveCheck->isChecked() && myAnimator->checkAVIMaker());
    mySaveAVICheck->setEnabled(!mySaveCheck->isChecked());
  }
  else if (source == mySaveAVICheck) {
    if (mySaveAVICheck->isChecked()) {
      if (!myAnimator->checkAVIMaker()) {
        // AVI maker is not available
        SUIT_MessageBox::warning(this, tr("ERROR"), tr("MSG_NO_AVI_MAKER"), tr("&OK"));
        mySaveAVICheck->setChecked(false);
      }
      else {
        if (mySaveCheck->isChecked()) {
          mySaveCheck->setChecked(false);
        }
        myPathAVILbl->setEnabled(true);
        myPathAVIEdit->setEnabled(true);
        myBrowseAVIBtn->setEnabled(true);
      }
    }
    else {
      // it is necessary in case of not available AVI maker,
      // because otherwise they will stay enabled
      // (??? slots, connected on SIGNAL(toggled(bool)) of mySaveAVICheck,
      // works in wrong order ???)
      myPathAVILbl->setEnabled(false);
      myPathAVIEdit->setEnabled(false);
      myBrowseAVIBtn->setEnabled(false);
    }
    mySaveCheck->setEnabled(!mySaveAVICheck->isChecked());
  }
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onStop()
{
  myPlayBtn->setChecked(false);
  myPlayBtn->setIcon(MYplayPixmap);
  mySetupBtn->setEnabled(true);
  myGenBtn->setEnabled(true);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onHelp()
{
  QString aHelpFileName = "animating_page.html";
  LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
  if (app)
    app->onHelpContextModule(myModule ? app->moduleName(myModule->moduleName()) : QString(""), aHelpFileName);
  else {
            QString platform;
#ifdef WIN32
            platform = "winapplication";
#else
            platform = "application";
#endif
    SUIT_MessageBox::warning(0, QObject::tr("WRN_WARNING"),
                     QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
                     arg(app->resourceMgr()->stringValue("ExternalBrowser", platform)).arg(aHelpFileName),
                     QObject::tr("BUT_OK"));
  }
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::saveToStudy()
{
  myAnimator->saveAnimation();
  VISU::UpdateObjBrowser(myModule, true);
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::publishToStudy()
{
  myAnimator->publishInStudy();
  VISU::UpdateObjBrowser(myModule, true);
  mySaveBtn->setEnabled(myAnimator->isSavedInStudy());
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::restoreFromStudy(_PTR(SObject) theAnimation)
{
  myAnimator->restoreFromStudy(theAnimation);
  mySaveBtn->setEnabled(myAnimator->isSavedInStudy());
  if ( myAnimator->getAnimationMode() == VISU::Animation::SUCCESSIVE )
    setWindowTitle(tr("SUCCESSIVE_ANIMATION"));
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onPicsFormatChanged()
{
  QList<QByteArray> aDumpFormats = QImageWriter::supportedImageFormats();
  if (aDumpFormats.count() < 1) {
    SUIT_MessageBox::warning(this, tr("ERROR"), tr("MSG_NO_SUPPORTED_IMAGE_FORMATS"), tr("&OK"));
    return;
  }
  if (myPicsFormat->currentIndex() < 0 || aDumpFormats.count() <= myPicsFormat->currentIndex()) {
    SUIT_MessageBox::warning(this, tr("ERROR"), tr("MSG_INVALID_IMAGE_FORMAT_INDEX"), tr("&OK"));
    return;
  }
  myAnimator->setDumpFormat(aDumpFormats.at(myPicsFormat->currentIndex()));
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::onPathChanged()
{
  myAnimator->dumpTo(myPathEdit->text().toLatin1().data());
}

//------------------------------------------------------------------------
void VisuGUI_TimeAnimationDlg::keyPressEvent( QKeyEvent* e )
{
  QDialog::keyPressEvent( e );
  if ( e->isAccepted() )
    return;

  if ( e->key() == Qt::Key_F1 )
    {
      e->accept();
      onHelp();
    }
}

Generated by  Doxygen 1.6.0   Back to index