/****************************************************************************
*
* Copyright (c) 2000 - 2018, Lawrence Livermore National Security, LLC
* Produced at the Lawrence Livermore National Laboratory
* LLNL-CODE-442911
* All rights reserved.
*
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

#include "QvisExplodeWindow.h"

#include <ExplodeAttributes.h>
#include <DebugStream.h>

#include <QCheckBox>
#include <QLabel>
#include <QLayout>
#include <QLineEdit>
#include <QSpinBox>
#include <QTabWidget>
#include <QListWidget>
#include <QComboBox>
#include <QGroupBox>
#include <QPushButton>
#include <QList>
#include <QModelIndexList>

#include <numeric>

// ****************************************************************************
// Method: QvisExplodeWindow::QvisExplodeWindow
//
// Purpose: 
//   Constructor
//
// Note:       Autogenerated by xml2window.
//
// Programmer: xml2window
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

QvisExplodeWindow::QvisExplodeWindow(const int type,
                         ExplodeAttributes *subj,
                         const QString &caption,
                         const QString &shortName,
                         QvisNotepadArea *notepad)
    : QvisOperatorWindow(type,subj, caption, shortName, notepad)
{
    atts       = subj;
    windowAtts = ExplodeAttributes();
    origAtts   = ExplodeAttributes();
    windowAtts.CopyAttributes(atts);
    origAtts.CopyAttributes(atts);
}


// ****************************************************************************
// Method: QvisExplodeWindow::~QvisExplodeWindow
//
// Purpose: 
//   Destructor
//
// Note:       Autogenerated by xml2window.
//
// Programmer: xml2window
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

QvisExplodeWindow::~QvisExplodeWindow()
{
}

// ****************************************************************************
// Method: QvisExplodeWindow::CreateWindowContents
//
// Purpose: 
//   Creates the widgets for the window.
//
// Note:       Autogenerated by xml2window.
//
// Programmer: xml2window
// Creation:   omitted
//
// Modifications:
//   
//    Alister Maguire, Thu Dec 21 15:46:39 PST 2017
//    Completely refactored for a better looking/acting gui. 
//
//    Alister Maguire, Mon Jan 29 10:12:44 PST 2018
//    Changed 'Explosions' title to 'Origin'. 
//
//    Alister Maguire, Wed Feb 21 11:20:52 PST 2018
//    Refactored to handle multiple explosions. 
//
//    Alister Maguire, Fri Mar  2 16:29:13 PST 2018
//    Only enable update and remove when an explosion
//    has been selected. 
//
// ****************************************************************************

void
QvisExplodeWindow::CreateWindowContents()
{
    QGridLayout *mainLayout = new QGridLayout(0);
    topLayout->addLayout(mainLayout);

    //
    // Explosions Group
    //
    QGroupBox *listGroup = new QGroupBox(central);
    listGroup->setTitle(tr("Explosions"));
    mainLayout->addWidget(listGroup, 0, 0, 3, 1);

    QGridLayout *listLayout = new QGridLayout(listGroup);

    //
    // Explosion List
    //
    explosionList = new QListWidget(central);
    listLayout->addWidget(explosionList, 0, 0, 2, 4); 
    connect(explosionList, SIGNAL(itemClicked(QListWidgetItem *)),
        this, SLOT(switchCurrentExplosion(QListWidgetItem *)));

    addExplosionButton = new QPushButton("Add", central);
    listLayout->addWidget(addExplosionButton, 1, 0);
    connect(addExplosionButton, SIGNAL(clicked()),
            this, SLOT(addExplosionToList()));

    removeExplosionButton = new QPushButton("Remove", central);
    removeExplosionButton->setEnabled(false);
    listLayout->addWidget(removeExplosionButton, 1, 1);
    connect(removeExplosionButton, SIGNAL(clicked()),
            this, SLOT(removeExplosionFromList()));

    updateExplosionButton = new QPushButton("Update", central);
    updateExplosionButton->setEnabled(false);
    listLayout->addWidget(updateExplosionButton, 1, 2);
    connect(updateExplosionButton, SIGNAL(clicked()), 
            this, SLOT(updateExplosion()));

    clearExplosionsButton = new QPushButton("Clear", central);
    listLayout->addWidget(clearExplosionsButton, 1, 3);
    connect(clearExplosionsButton, SIGNAL(clicked()),
            this, SLOT(clearExplosionList()));

    //
    // Origin
    //
    QGroupBox *typeGroup = new QGroupBox(central);
    typeGroup->setTitle(tr("Origin"));
    mainLayout->addWidget(typeGroup, 0, 1);

    QGridLayout *typeLayout = new QGridLayout(typeGroup);
    
    explosionTabs                  = new QTabWidget(central);
    QWidget    *explosionPointTab  = new QWidget(central);
    QWidget    *explodePlaneTab    = new QWidget(central);
    QWidget    *explodeCylinderTab = new QWidget(central);
    connect(explosionTabs, SIGNAL(currentChanged(int)),
            this, SLOT(explosionTabsChangedIndex(int)));
    explosionTabs->addTab(explosionPointTab, tr("Point"));
    explosionTabs->addTab(explodePlaneTab, tr("Plane"));
    explosionTabs->addTab(explodeCylinderTab, tr("Cylinder"));
    typeLayout->addWidget(explosionTabs, 1, 0, 1, 3);
    QGridLayout *explosionPointLayout  = new QGridLayout(explosionPointTab);
    QGridLayout *explodePlaneLayout    = new QGridLayout(explodePlaneTab);
    QGridLayout *explodeCylinderLayout = new QGridLayout(explodeCylinderTab);

    QLabel *explosionPointLabel = new QLabel(tr("Explosion Point"), central);
    explosionPointLayout->addWidget(explosionPointLabel, 0, 0);
    explosionPoint = new QLineEdit(central);
    explosionPoint->setPlaceholderText("0.0 0.0 0.0");
    connect(explosionPoint, SIGNAL(returnPressed()),
            this, SLOT(explosionPointProcessText()));
    explosionPointLayout->addWidget(explosionPoint, 0, 1);

    QLabel *planePointLabel = new QLabel(tr("Plane Point"), central);
    explodePlaneLayout->addWidget(planePointLabel, 0, 0);
    planePoint = new QLineEdit(central);
    planePoint->setPlaceholderText("0.0 0.0 0.0");
    connect(planePoint, SIGNAL(returnPressed()),
            this, SLOT(planePointProcessText()));
    explodePlaneLayout->addWidget(planePoint, 0, 1);

    QLabel *planeNormLabel = new QLabel(tr("Plane Normal"), central);
    explodePlaneLayout->addWidget(planeNormLabel, 1, 0);
    planeNorm = new QLineEdit(central);
    planeNorm->setPlaceholderText("0.0 0.0 0.0");
    connect(planeNorm, SIGNAL(returnPressed()),
            this, SLOT(planeNormProcessText()));
    explodePlaneLayout->addWidget(planeNorm, 1, 1);

    QLabel *cylinderPoint1Label = new QLabel(tr("Cylinder Point 1"), central);
    explodeCylinderLayout->addWidget(cylinderPoint1Label, 0, 0);
    cylinderPoint1 = new QLineEdit(central);
    cylinderPoint1->setPlaceholderText("0.0 0.0 0.0");
    connect(cylinderPoint1, SIGNAL(returnPressed()),
            this, SLOT(cylinderPoint1ProcessText()));
    explodeCylinderLayout->addWidget(cylinderPoint1, 0, 1);

    QLabel *cylinderPoint2Label = new QLabel(tr("Cylinder Point 2"), central);
    explodeCylinderLayout->addWidget(cylinderPoint2Label, 1, 0);
    cylinderPoint2 = new QLineEdit(central);
    cylinderPoint2->setPlaceholderText("0.0 0.0 0.0");
    connect(cylinderPoint2, SIGNAL(returnPressed()),
            this, SLOT(cylinderPoint2ProcessText()));
    explodeCylinderLayout->addWidget(cylinderPoint2, 1, 1);

    QLabel *cylinderRadiusLabel = new QLabel(tr("Cylinder Radius"), central);
    explodeCylinderLayout->addWidget(cylinderRadiusLabel, 2, 0);
    cylinderRadius = new QLineEdit(central);
    cylinderRadius->setPlaceholderText("0.0");
    connect(cylinderRadius, SIGNAL(returnPressed()),
            this, SLOT(cylinderRadiusProcessText()));
    explodeCylinderLayout->addWidget(cylinderRadius, 2, 1);

    //
    // Material Options
    //
    materialGroup = new QGroupBox(central);
    materialGroup->setTitle(tr("Material Explosion"));
    mainLayout->addWidget(materialGroup, 1, 1);

    QGridLayout *materialLayout = new QGridLayout(materialGroup);
    
    QLabel *materialExplosionFactorLabel = new QLabel(tr("Explosion Factor"), central);
    materialLayout->addWidget(materialExplosionFactorLabel, 2, 0);
    materialExplosionFactor = new QLineEdit(central);
    materialExplosionFactor->setPlaceholderText("0.0");
    connect(materialExplosionFactor, SIGNAL(returnPressed()),
            this, SLOT(materialExplosionFactorProcessText()));
    materialLayout->addWidget(materialExplosionFactor, 2, 1); 

    QLabel *materialsLabel  = new QLabel(tr("Available Materials"), central); 
    materialLayout->addWidget(materialsLabel, 3, 0);
    materialsWidget = new QWidget(central);
    materialsCombo  = new QComboBox(materialsWidget);
    materialLayout->addWidget(materialsCombo, 3, 1);

    //
    // Cell Options
    //
    QGroupBox *cellGroup = new QGroupBox(central);
    cellGroup->setTitle(tr("Cell Explosion"));
    mainLayout->addWidget(cellGroup, 2, 1);

    QGridLayout *cellLayout = new QGridLayout(cellGroup);

    explodeMaterialCells = new QCheckBox(tr("Explode Material Cells"), central);
    cellLayout->addWidget(explodeMaterialCells, 0, 0);
    connect(explodeMaterialCells, SIGNAL(toggled(bool)),
            this, SLOT(explodeMaterialCellsToggled(bool)));

    explodeAllCells = new QCheckBox(tr("Explode All Cells"), central);
    cellLayout->addWidget(explodeAllCells, 1, 0);
    connect(explodeAllCells, SIGNAL(toggled(bool)),
            this, SLOT(explodeAllCellsToggled(bool)));
   
    QLabel *cellExplosionFactorLabel = new QLabel(tr("Explosion Factor"), central);
    cellLayout->addWidget(cellExplosionFactorLabel, 2, 0);
    cellExplosionFactor = new QLineEdit(central);
    cellExplosionFactor->setPlaceholderText("0.0");
    cellExplosionFactor->setEnabled(false);
    connect(cellExplosionFactor, SIGNAL(returnPressed()),
            this, SLOT(cellExplosionFactorProcessText()));
    cellLayout->addWidget(cellExplosionFactor, 2, 1); 

    QLabel *patternLabel = new QLabel(tr("Explosion Pattern"), central); 
    cellLayout->addWidget(patternLabel, 3, 0);
    QWidget *patternWidget = new QWidget(central);
    explosionPattern = new QComboBox(patternWidget);
    explosionPattern->addItem("Impact");
    explosionPattern->addItem("Scatter");
    explosionPattern->setEnabled(false);
    connect(explosionPattern, SIGNAL(currentIndexChanged(int)),
            this, SLOT(explosionPatternChangedIndex(int)));
    cellLayout->addWidget(explosionPattern, 3, 1);

    boundaryString  = "";
}


// ****************************************************************************
// Method: QvisExplodeWindow::UpdateWindow
//
// Purpose: 
//   Updates the widgets in the window when the subject changes.
//
// Note:       Autogenerated by xml2window.
//
// Programmer: xml2window
// Creation:   omitted
//
// Modifications:
//
//    Alister Maguire, Thu Dec 21 15:46:39 PST 2017
//    Changed the way boundary names are updated as 
//    well as explosion type and explosion pattern. 
//   
//    Alister Maguire, Wed Feb 21 11:20:52 PST 2018
//    Added case for updating the list of explosions. 
//
// ****************************************************************************

void
QvisExplodeWindow::UpdateWindow(bool doAll)
{
    if (!origAtts.AttributesMatch(*atts))
    {
        origAtts.CopyAttributes(atts);
        windowAtts.CopyAttributes(atts);
    }

    for(int i = 0; i < windowAtts.NumAttributes(); ++i)
    {
        if(!doAll)
        {
            if(!windowAtts.IsSelected(i))
            {
                continue;
            }
        }

        switch(i)
        {
            case ExplodeAttributes::ID_boundaryNames:
            {
                stringVector materials = windowAtts.GetBoundaryNames();
                std::string tmp;
                tmp = std::accumulate(materials.begin(), materials.end(), tmp);

                if (tmp.empty())
                {
                    materialGroup->setEnabled(false);
                    explodeMaterialCells->setEnabled(false);
                }
                else if (tmp != boundaryString)
                {
                    materialGroup->setEnabled(true);
                    explodeMaterialCells->setEnabled(true);

                    boundaryString = tmp;
                    int numMaterials = windowAtts.GetBoundaryNames().size();          
          
                    materialsCombo->blockSignals(true);
                    materialsCombo->clear();
                    materialsCombo->blockSignals(false);

                    for(size_t idx = 0; idx < numMaterials; ++idx)
                    {
                        const char *name = windowAtts.GetBoundaryNames()[idx].c_str();
                        materialsCombo->blockSignals(true);
                        materialsCombo->addItem(name);
                        materialsCombo->blockSignals(false);
                    }
                }
                else
                {
                    int selectedIdx    = 0;
                    std::string selectedMat = windowAtts.GetMaterial();
                    int numMaterials = windowAtts.GetBoundaryNames().size();          
                    for(size_t idx = 0; idx < numMaterials; ++idx)
                    {
                        const char *name = windowAtts.GetBoundaryNames()[idx].c_str();
                        if (name == selectedMat)
                        {
                            selectedIdx = idx;
                        }
                        materialsCombo->setCurrentIndex(selectedIdx);
                    }
                }
            }
            break;
          case ExplodeAttributes::ID_explosionPoint:
              explosionPoint->setText(DoublesToQString(windowAtts.GetExplosionPoint(), 3));
              break;
          case ExplodeAttributes::ID_planePoint:
              planePoint->setText(DoublesToQString(windowAtts.GetPlanePoint(), 3));
              break;
          case ExplodeAttributes::ID_planeNorm:
              planeNorm->setText(DoublesToQString(windowAtts.GetPlaneNorm(), 3));
              break;
          case ExplodeAttributes::ID_cylinderPoint1:
              cylinderPoint1->setText(DoublesToQString(windowAtts.GetCylinderPoint1(), 3));
              break;
          case ExplodeAttributes::ID_cylinderPoint2:
              cylinderPoint2->setText(DoublesToQString(windowAtts.GetCylinderPoint2(), 3));
              break;
          case ExplodeAttributes::ID_materialExplosionFactor:
              materialExplosionFactor->setText(DoubleToQString(windowAtts.GetMaterialExplosionFactor()));
              break;
          case ExplodeAttributes::ID_explodeMaterialCells:
              explodeMaterialCells->setChecked(windowAtts.GetExplodeMaterialCells());
              break;
          case ExplodeAttributes::ID_explodeAllCells:
              explodeAllCells->setChecked(windowAtts.GetExplodeAllCells());
              break;
          case ExplodeAttributes::ID_cellExplosionFactor:
              cellExplosionFactor->setText(DoubleToQString(windowAtts.GetCellExplosionFactor()));
              break;
          case ExplodeAttributes::ID_cylinderRadius:
              cylinderRadius->setText(DoubleToQString(windowAtts.GetCylinderRadius()));
              break;
          case ExplodeAttributes::ID_explosionPattern:
          {
              int patternID = windowAtts.GetExplosionPattern();
              switch (patternID)
              {
                  case ExplodeAttributes::Impact:
                  {
                      explosionPattern->setCurrentIndex(IMPACT);
                  }
                  break;
                  case ExplodeAttributes::Scatter:
                  {
                      explosionPattern->setCurrentIndex(SCATTER);
                  }
                  break;
              }
              break;
          }
          case ExplodeAttributes::ID_explosionType:
          {
              int typeID = windowAtts.GetExplosionType();
              switch (typeID)
              {
                  case ExplodeAttributes::Point:
                  {
                    explosionTabs->setCurrentIndex(POINT);
                  }
                  break;
                  case ExplodeAttributes::Plane:
                  {
                    explosionTabs->setCurrentIndex(PLANE);
                  }
                  break;
                  case ExplodeAttributes::Cylinder:
                  {
                    explosionTabs->setCurrentIndex(CYLINDER);
                  }
                  break;
              }
          }
          case ExplodeAttributes::ID_explosions:
          {
              int curRow; 
              curRow = explosionList->currentRow();    
              explosionList->clear();
              
              for (int i = 0; i < atts->GetNumExplosions(); ++i)
              {
                  QString rename = QString("Explosion %1").arg(i);
                  explosionList->addItem(rename); 
              }
              explosionList->setCurrentRow(curRow);
          }
      }
   }
}


// ****************************************************************************
// Method: QvisExplodeWindow::GetCurrentValues
//
// Purpose: 
//   Gets values from certain widgets and stores them in the subject.
//
// Note:       Autogenerated by xml2window.
//
// Programmer: xml2window
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void
QvisExplodeWindow::GetCurrentValues(int which_widget)
{
    bool doAll = (which_widget == -1);

    // Do explosionPoint
    if(which_widget == ExplodeAttributes::ID_explosionPoint || doAll)
    {
        double val[3];
        if(LineEditGetDoubles(explosionPoint, val, 3))
            windowAtts.SetExplosionPoint(val);
        else
        {
            ResettingError(tr("explosionPoint"),
                DoublesToQString(windowAtts.GetExplosionPoint(),3));
            windowAtts.SetExplosionPoint(windowAtts.GetExplosionPoint());
        }
    }

    // Do planePoint
    if(which_widget == ExplodeAttributes::ID_planePoint || doAll)
    {
        double val[3];
        if(LineEditGetDoubles(planePoint, val, 3))
            windowAtts.SetPlanePoint(val);
        else
        {
            ResettingError(tr("planePoint"),
                DoublesToQString(windowAtts.GetPlanePoint(),3));
            windowAtts.SetPlanePoint(windowAtts.GetPlanePoint());
        }
    }

    // Do planeNorm
    if(which_widget == ExplodeAttributes::ID_planeNorm || doAll)
    {
        double val[3];
        if(LineEditGetDoubles(planeNorm, val, 3))
            windowAtts.SetPlaneNorm(val);
        else
        {
            ResettingError(tr("planeNorm"),
                DoublesToQString(windowAtts.GetPlaneNorm(),3));
            windowAtts.SetPlaneNorm(windowAtts.GetPlaneNorm());
        }
    }

    // Do cylinderPoint1
    if(which_widget == ExplodeAttributes::ID_cylinderPoint1 || doAll)
    {
        double val[3];
        if(LineEditGetDoubles(cylinderPoint1, val, 3))
            windowAtts.SetCylinderPoint1(val);
        else
        {
            ResettingError(tr("cylinderPoint1"),
                DoublesToQString(windowAtts.GetCylinderPoint1(),3));
            windowAtts.SetCylinderPoint1(windowAtts.GetCylinderPoint1());
        }
    }

    // Do cylinderPoint2
    if(which_widget == ExplodeAttributes::ID_cylinderPoint2 || doAll)
    {
        double val[3];
        if(LineEditGetDoubles(cylinderPoint2, val, 3))
            windowAtts.SetCylinderPoint2(val);
        else
        {
            ResettingError(tr("cylinderPoint2"),
                DoublesToQString(windowAtts.GetCylinderPoint2(),3));
            windowAtts.SetCylinderPoint2(windowAtts.GetCylinderPoint2());
        }
    }

    // Do materialExplosionFactor
    if(which_widget == ExplodeAttributes::ID_materialExplosionFactor || doAll)
    {
        double val;
        if(LineEditGetDouble(materialExplosionFactor, val))
            windowAtts.SetMaterialExplosionFactor(val);
        else
        {
            ResettingError(tr("materialExplosionFactor"),
                DoubleToQString(windowAtts.GetMaterialExplosionFactor()));
            windowAtts.SetMaterialExplosionFactor(windowAtts.GetMaterialExplosionFactor());
        }
    }

    // Do cellExplosionFactor
    if(which_widget == ExplodeAttributes::ID_cellExplosionFactor || doAll)
    {
        double val;
        if(LineEditGetDouble(cellExplosionFactor, val))
            windowAtts.SetCellExplosionFactor(val);
        else
        {
            ResettingError(tr("cellExplosionFactor"),
                DoubleToQString(windowAtts.GetCellExplosionFactor()));
            windowAtts.SetCellExplosionFactor(windowAtts.GetCellExplosionFactor());
        }
    }

    // Do materials
    if(which_widget == ExplodeAttributes::ID_material || doAll)
    {
        windowAtts.SetMaterial(materialsCombo->currentText().toStdString());
    }

    // Do cylinderRadius
    if(which_widget == ExplodeAttributes::ID_cylinderRadius || doAll)
    {
        double val;
        if(LineEditGetDouble(cylinderRadius, val))
            windowAtts.SetCylinderRadius(val);
        else
        {
            ResettingError(tr("cylinderRadius"),
                DoubleToQString(windowAtts.GetCylinderRadius()));
            windowAtts.SetCylinderRadius(windowAtts.GetCylinderRadius());
        }
    }
}


//
// Qt Slot functions
//

void
QvisExplodeWindow::explosionTabsChangedIndex(int type)
{
    // Do explosionType
    if(type != windowAtts.GetExplosionType())
    {
        switch (type)
        {
            case POINT:
            {
                windowAtts.SetExplosionType(ExplodeAttributes::Point);
            }
            break;
            case PLANE:
            {
                windowAtts.SetExplosionType(ExplodeAttributes::Plane);
            }
            break;
            case CYLINDER:
            {
                windowAtts.SetExplosionType(ExplodeAttributes::Cylinder);
            }
            break;
        }
        SetUpdate(false);
    }
}


void
QvisExplodeWindow::explosionPatternChangedIndex(int type)
{
    // Do explosionPattern
    if(type != windowAtts.GetExplosionPattern())
    {
        switch (type)
        {
            case IMPACT:
            {
                windowAtts.SetExplosionPattern(ExplodeAttributes::Impact);
            }
            break;
            case SCATTER:
            {
                windowAtts.SetExplosionPattern(ExplodeAttributes::Scatter);
            }
            break;
        }
        SetUpdate(false);
    }
}


void
QvisExplodeWindow::explosionPointProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_explosionPoint);
}


void
QvisExplodeWindow::planePointProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_planePoint);
}


void
QvisExplodeWindow::planeNormProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_planeNorm);
}


void
QvisExplodeWindow::cylinderPoint1ProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_cylinderPoint1);
}


void
QvisExplodeWindow::cylinderPoint2ProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_cylinderPoint2);
}


void
QvisExplodeWindow::materialExplosionFactorProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_materialExplosionFactor);
}


void
QvisExplodeWindow::cellExplosionFactorProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_cellExplosionFactor);
}


void
QvisExplodeWindow::materialProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_material);
}


void
QvisExplodeWindow::cylinderRadiusProcessText()
{
    GetCurrentValues(ExplodeAttributes::ID_cylinderRadius);
}

void 
QvisExplodeWindow::explodeMaterialCellsToggled(bool val)
{
    cellExplosionFactor->setEnabled(val);
    explosionPattern->setEnabled(val);
    explodeAllCells->setEnabled(!val);
    windowAtts.SetExplodeMaterialCells(val); 
}

void 
QvisExplodeWindow::explodeAllCellsToggled(bool val)
{
    cellExplosionFactor->setEnabled(val);
    explosionPattern->setEnabled(val);
    materialGroup->setEnabled(!val);
    explodeMaterialCells->setEnabled(!val);
    windowAtts.SetExplodeAllCells(val); 
}

void
QvisExplodeWindow::addExplosionToList()
{
    GetCurrentValues(-1);
    atts->AddExplosions(windowAtts);
    windowAtts = origAtts;
    explosionList->clear();
    updateExplosionButton->setEnabled(false);
    removeExplosionButton->setEnabled(false);
    UpdateWindow(true);
    Apply();
}

void
QvisExplodeWindow::removeExplosionFromList()
{
    QModelIndexList indices = explosionList->selectionModel()->selectedIndexes();
    
    foreach (QModelIndex idx, indices)
    {
        atts->RemoveExplosions(idx.row());
    }

    explosionList->clear();
    windowAtts = origAtts;
    updateExplosionButton->setEnabled(false);
    removeExplosionButton->setEnabled(false);
    UpdateWindow(true);
    Apply();
}

void
QvisExplodeWindow::clearExplosionList()
{
    atts->ClearExplosions();
    explosionList->clear();
    updateExplosionButton->setEnabled(false);
    removeExplosionButton->setEnabled(false);
    UpdateWindow(false);
    Apply();
}

void 
QvisExplodeWindow::switchCurrentExplosion(QListWidgetItem *item)
{
    int curRow; 
    curRow     = explosionList->currentRow();    
    windowAtts = atts->GetExplosions(curRow);
    updateExplosionButton->setEnabled(true);
    removeExplosionButton->setEnabled(true);
    UpdateWindow(true);
}

void
QvisExplodeWindow::updateExplosion()
{
    int curRow;
    curRow = explosionList->currentRow();
    
    std::vector<ExplodeAttributes> explosions;
    int numExp = atts->GetNumExplosions();

    for (int i = 0; i < numExp; ++i)
    {
        ExplodeAttributes attsCpy;
        attsCpy.CopyAttributes(&atts->GetExplosions(i));
        explosions.push_back(attsCpy);
    }

    GetCurrentValues(-1);
    explosions[curRow] = windowAtts;
    clearExplosionList();
    
    for (int i = 0; i < numExp; ++i)
    {
        atts->AddExplosions(explosions[i]);
    }

    windowAtts = origAtts;
    updateExplosionButton->setEnabled(false);
    removeExplosionButton->setEnabled(false);
    UpdateWindow(true);
    Apply();
}
