//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "smtk/session/rgg/plugin/smtkRGGEditPinView.h"
#include "smtk/session/rgg/plugin/ui_smtkRGGEditPinParameters.h"

#include "smtkRGGViewHelper.h"

#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/DoubleItem.h"
#include "smtk/attribute/GroupItem.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/attribute/VoidItem.h"

#include "smtk/io/Logger.h"

#include "smtk/model/AuxiliaryGeometry.h"
#include "smtk/model/Resource.h"

#include "smtk/operation/Operation.h"

#include "smtk/session/rgg/Core.h"
#include "smtk/session/rgg/Pin.h"

#include "smtk/session/rgg/json/jsonPin.h"

#include "smtk/session/rgg/operators/CreateModel.h"
#include "smtk/session/rgg/operators/EditPin.h"

#include "smtk/extension/qt/qtAttribute.h"
#include "smtk/extension/qt/qtBaseAttributeView.h"
#include "smtk/extension/qt/qtItem.h"
#include "smtk/extension/qt/qtUIManager.h"

#include "smtk/view/Configuration.h"

#include "pqActiveObjects.h"
#include "pqApplicationCore.h"
#include "pqPresetDialog.h"
#include "pqRenderView.h"
#include "pqServer.h"
#include "pqSettings.h"

#include <QTableWidget>
#include <QTableWidgetItem>
#include <QVBoxLayout>

using namespace smtk::extension;
using namespace smtk::session::rgg;
using json = nlohmann::json;
using rggPin = smtk::session::rgg::Pin;

constexpr int numberOfLayersTableColumns = 2;
constexpr int numberOfPieceTableColumns = 4;

class smtkRGGEditPinViewInternals : public Ui::RGGEditPinParameters
{
public:
  smtkRGGEditPinViewInternals() {}

  ~smtkRGGEditPinViewInternals()
  {
    if (CurrentAtt)
      delete CurrentAtt;
  }

  qtAttribute* createAttUI(smtk::attribute::AttributePtr att, QWidget* pw, qtBaseView* view)
  {
    if (att && att->numberOfItems() > 0)
    {
      smtk::view::Configuration::Component comp;
      qtAttribute* attInstance = new qtAttribute(att, comp, pw, view);
      if (attInstance && attInstance->widget())
      {
        // Without any additional info lets use a basic layout with model associations
        // if any exists
        attInstance->createBasicLayout(true);
        attInstance->widget()->setObjectName("RGGPinEditor");
        QVBoxLayout* parentlayout = static_cast<QVBoxLayout*>(pw->layout());
        parentlayout->insertWidget(0, attInstance->widget());
      }
      return attInstance;
    }
    return nullptr;
  }

  QPointer<qtAttribute> CurrentAtt;
  smtk::model::Model CurrentModel; // As a convenience to fetch material info
};

smtkRGGEditPinView::smtkRGGEditPinView(const smtk::view::Information& info)
  : qtBaseAttributeView(info)
{
  this->Internals = new smtkRGGEditPinViewInternals();
}

smtkRGGEditPinView::~smtkRGGEditPinView()
{
  delete this->Internals;
}

const smtk::operation::OperationPtr& smtkRGGEditPinView::operation() const
{
  return m_viewInfo.get<smtk::operation::OperationPtr>();
}

qtBaseView* smtkRGGEditPinView::createViewWidget(const smtk::view::Information& info)
{
  smtkRGGEditPinView* view = new smtkRGGEditPinView(info);
  view->buildUI();
  return view;
}

void smtkRGGEditPinView::requestModelEntityAssociation()
{
  this->updateUI();
}

void smtkRGGEditPinView::valueChanged(smtk::attribute::ItemPtr /*optype*/)
{
  this->requestOperation(this->operation());
}

void smtkRGGEditPinView::requestOperation(const smtk::operation::OperationPtr& op)
{
  if (!op || !op->parameters())
  {
    return;
  }
  op->operate();
}

void smtkRGGEditPinView::attributeModified()
{
  // Always enable apply button here
}

void smtkRGGEditPinView::onAttItemModified(smtk::extension::qtItem* item)
{
  smtk::attribute::ItemPtr itemPtr = item->item();
  // only changing model/pin would update edit pin panel
  if (itemPtr->name() == "model/pin" && itemPtr->type() == smtk::attribute::Item::Type::ReferenceType)
  {
    this->updateEditPinPanel();
  }
}

void smtkRGGEditPinView::apply()
{
  // Fill the attribute - read all data from UI
  Pin pin;
  pin.setName(this->Internals->nameLineEdit->text().toStdString());

  pin.setLabel(this->Internals->labelLineEdit->text().toStdString());

  pin.setCellMaterialIndex(this->Internals->CellMaterial->currentIndex());

  pin.setCutAway(this->Internals->cutAwayViewCheckBox->isChecked());

  pin.setZOrigin(this->Internals->Z0rigin->value());

  std::vector<double> color;
  this->Internals->chooseColorButton->getColor(color);
  pin.setColor(color);

  std::vector<Pin::Piece> pieces;
  // Add pieces
  QTableWidget* pT = this->Internals->piecesTable;
  for (int i = 0; i < pT->rowCount(); i++)
  {
    Pin::Piece currentPiece;

    int segmentType = dynamic_cast<QComboBox*>(pT->cellWidget(i, 0))->currentIndex();
    currentPiece.pieceType = segmentType ? Pin::PieceType::FRUSTUM : Pin::PieceType::CYLINDER;

    currentPiece.length = pT->item(i, 1)->text().toDouble();
    currentPiece.baseRadius = pT->item(i, 2)->text().toDouble();
    currentPiece.topRadius = pT->item(i, 3)->text().toDouble();
    pieces.push_back(currentPiece);
  }
  pin.setPieces(pieces);

  std::vector<Pin::LayerMaterial> layerMaterials;
  // Add pieces
  QTableWidget* lT = this->Internals->layersTable;
  for (int i = 0; i < lT->rowCount(); i++)
  {
    Pin::LayerMaterial currentLM;
    // sub material
    currentLM.subMaterialIndex = dynamic_cast<QComboBox*>(lT->cellWidget(i, 0))->currentIndex();
    currentLM.normRadius = lT->item(i, 1)->text().toDouble();
    layerMaterials.push_back(currentLM);
  }
  pin.setLayerMaterials(layerMaterials);
  json pinJson = pin;
  std::string pinStr = pinJson.dump();

  smtk::attribute::AttributePtr att = this->operation()->parameters();
  att->findString("pin representation")->setValue(pinStr);

  this->requestOperation(this->operation());
  this->Internals->chooseColorButton->setText(QString());
  // Switch to edit pin mode if it has just created a pin
  smtk::model::EntityRefArray ents = this->Internals->CurrentAtt->attribute()
                                       ->associatedModelEntities<smtk::model::EntityRefArray>();
  // FIXME Update the ui as well
  if (ents[0].isModel())
  {
    auto pinsCreated = ents[0].resource()->findEntitiesByProperty("label", pin.label());
    if (pinsCreated.size())
    {
      att->associate(pinsCreated[0].component());
    }
  }
}

void smtkRGGEditPinView::pieceTypeChanged()
{
  QComboBox* comboBox = qobject_cast<QComboBox*>(sender());
  if (!comboBox)
  {
    return;
  }

  if (comboBox->currentIndex() == 0) // Only cylinder needs an update on top radius
  {
    int row = comboBox->itemData(0).toInt();
    radiusItem* baseR = dynamic_cast<radiusItem*>(this->Internals->piecesTable->item(row, 2));
    radiusItem* topRItem = dynamic_cast<radiusItem*>(this->Internals->piecesTable->item(row, 3));
    topRItem->setData(Qt::EditRole, QVariant(baseR->text().toDouble()));
  }
}

void smtkRGGEditPinView::updateUI()
{
  smtk::view::ConfigurationPtr view = this->configuration();
  if (!view || !this->Widget)
  {
    return;
  }

  if (this->Internals->CurrentAtt)
  {
    delete this->Internals->CurrentAtt;
  }

  int i = view->details().findChild("AttributeTypes");
  if (i < 0)
  {
    return;
  }
  smtk::view::Configuration::Component& comp = view->details().child(i);
  std::string defName;
  for (std::size_t ci = 0; ci < comp.numberOfChildren(); ++ci)
  {
    smtk::view::Configuration::Component& attComp = comp.child(ci);
    if (attComp.name() != "Att")
    {
      continue;
    }
    std::string optype;
    if (attComp.attribute("Type", optype) && !optype.empty())
    {
      if (optype == "edit pin")
      {
        defName = optype;
        break;
      }
    }
  }
  if (defName.empty())
  {
    return;
  }

  smtk::attribute::AttributePtr att = this->operation()->parameters();
  this->Internals->CurrentAtt = this->Internals->createAttUI(att, this->Widget, this);
  if (this->Internals->CurrentAtt)
  {
    QObject::connect(this->Internals->CurrentAtt, &qtAttribute::itemModified, this,
      &smtkRGGEditPinView::onAttItemModified);

    smtk::attribute::ReferenceItemPtr pinI =
      this->Internals->CurrentAtt->attribute()->associations();

    if (!pinI)
    {
      smtkErrorMacro(
        smtk::io::Logger::instance(), "Edit pin operator does not have a pin association item");
      return;
    }
    this->updateEditPinPanel();
  }
}

void smtkRGGEditPinView::createWidget()
{
  smtk::view::ConfigurationPtr view = this->configuration();
  if (!view)
  {
    return;
  }

  QVBoxLayout* parentLayout = dynamic_cast<QVBoxLayout*>(this->parentWidget()->layout());

  // Delete any pre-existing widget
  if (this->Widget)
  {
    if (parentLayout)
    {
      parentLayout->removeWidget(this->Widget);
    }
    delete this->Widget;
  }

  // Create a new frame and lay it out
  this->Widget = new QFrame(this->parentWidget());
  QVBoxLayout* layout = new QVBoxLayout(this->Widget);
  layout->setMargin(0);
  this->Widget->setLayout(layout);
  this->Widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

  QWidget* tempWidget = new QWidget(this->parentWidget());
  this->Internals->setupUi(tempWidget);
  tempWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
  layout->addWidget(tempWidget, 1);
  // Make sure that we have enough space for the custom widget
  this->Internals->scrollArea->setMinimumHeight(800);

  // Edit name
  this->Internals->nameLineEdit->setToolTip(QString::fromStdString("Set the "
                                                                   "name of the pin"));
  // Edit label
  this->Internals->labelLineEdit->setToolTip(QString::fromStdString("Set the "
                                                                    "label of the pin"));
  // Edit cell material
  this->setupMaterialComboBox(this->Internals->CellMaterial);
  this->Internals->CellMaterial->setToolTip(QString::fromStdString("Set the "
                                                                   " material on the cell"));
  // Edit z origin
  // z origin would be updated when applied
  this->Internals->Z0rigin->setToolTip(QString::fromStdString("Set the base z value of the pin"));

  // Set cut away or not
  this->Internals->cutAwayViewCheckBox->setToolTip(
    QString::fromStdString("If checked, a clipping plane would cut the "
                           "pin half through center axis"));

  // Add/edit/remove pieces table
  this->createPiecesTable();

  // Add/edit/remove layers table
  this->createLayersTable();

  this->updateButtonStatus();

  // Show help when the info button is clicked.
  QObject::connect(
    this->Internals->infoButton, &QPushButton::released, this, &smtkRGGEditPinView::onInfo);

  QObject::connect(
    this->Internals->applyButton, &QPushButton::released, this, &smtkRGGEditPinView::apply);

  this->updateUI();
}

void smtkRGGEditPinView::updateEditPinPanel()
{
  smtk::model::EntityRefArray ents = this->Internals->CurrentAtt->attribute()
                                       ->associatedModelEntities<smtk::model::EntityRefArray>();
  bool isEnabled(true);
  if ((ents.size() == 0) ||
      // Not a valid pin nor a valid model
      (((!ents[0].hasStringProperty("rggType")) ||
    (ents[0].stringProperty("rggType")[0] != rggPin::typeDescription) ||
    !(ents[0].embeddedEntities<smtk::model::EntityRefArray>().size() > 0)) &&
      !ents[0].isModel()))
  { // Its type is not rgg pin
    isEnabled = false;
  }

  if (this->Internals)
  {
    this->Internals->scrollArea->setEnabled(isEnabled);
  }
  if (isEnabled)
  {
    smtk::model::Model model = ents[0].isModel() ?
          ents[0].as<smtk::model::Model>() : ents[0].owningModel();
    bool isHex = model.integerProperty(Core::geomDescription)[0] == static_cast<int>(Core::GeomType::Hex);
    if (!this->Internals->CurrentModel.isValid())
    {
      this->Internals->CurrentModel = model;
    }

    // Update material combo box
    this->setupMaterialComboBox(this->Internals->CellMaterial);

    Pin pin;
    if (ents[0].isModel())
    {
      std::string label = Pin::generateUniqueLabel();
      // Name
      this->Internals->nameLineEdit->setText(QString::fromStdString("Pin-"+label));
      // Label
      this->Internals->labelLineEdit->setText(QString::fromStdString(label));
    }
    else
    { // FIXME: Nlohmann json cannot handle preallocated object with operator T() properly.
      // See it's github issue !958. It should be fixed after version 4.0.0.
      Pin pinTemp = json::parse(ents[0].stringProperty(rggPin::propDescription)[0]);
      pin = pinTemp;

      // Name
      this->Internals->nameLineEdit->setText(QString::fromStdString(pin.name()));
      // Label
      this->Internals->labelLineEdit->setText(QString::fromStdString(pin.label()));
    }

    // Cell material
    this->Internals->CellMaterial->setCurrentIndex(pin.cellMaterialIndex());
    // Hex
    this->Internals->isHexCheckbox->setChecked(isHex);
    // Cut away
    this->Internals->cutAwayViewCheckBox->setChecked(pin.isCutAway());
    // Z origin
    this->Internals->Z0rigin->setValue(pin.zOrigin());
    // Color
    smtk::model::FloatList pinColor = pin.color();
    if (pinColor.size() && pinColor[3] >= 0) // Valid color
    {
      QColor color = QColor::fromRgbF(pinColor[0], pinColor[1], pinColor[2], pinColor[3]);
      this->Internals->chooseColorButton->setColor(color);
    }
    else
    {
      this->Internals->chooseColorButton->setColor(qtColorButton::generateColor());
      this->Internals->chooseColorButton->setText(QString::fromStdString("(Suggesting color)"));
    }

    // Populate the piece table
    const auto& pieces = pin.pieces();
    this->Internals->piecesTable->clearSpans();
    this->Internals->piecesTable->model()->removeRows(0, this->Internals->piecesTable->rowCount());
    for (std::size_t index = 0; index < pieces.size(); index++)
    {
      this->addPieceToTable(static_cast<int>(index), pieces[index].pieceType, pieces[index].length,
        pieces[index].baseRadius, pieces[index].topRadius);
    }

    // Populate the layers table
    const auto& layerMs = pin.layerMaterials();
    this->Internals->layersTable->clearSpans();
    this->Internals->layersTable->model()->removeRows(0, this->Internals->layersTable->rowCount());
    for (std::size_t index = 0; index < layerMs.size(); index++)
    {
      this->addLayerToTable(static_cast<int>(index), layerMs[index].subMaterialIndex,
                            layerMs[index].normRadius);
    }
  }
}

void smtkRGGEditPinView::setInfoToBeDisplayed()
{
  this->m_infoDialog->displayInfo(this->configuration());
}

void smtkRGGEditPinView::createPiecesTable()
{
  QTableWidget* pt = this->Internals->piecesTable;
  pt->clear();
  pt->resizeRowsToContents();
  pt->setMinimumHeight(200);
  // type, length, base radius and top radius
  pt->setColumnCount(numberOfPieceTableColumns);
  pt->setHorizontalHeaderLabels(QStringList() << "Segment\nType"
                                              << "Length"
                                              << "Base\nRadius"
                                              << "Top\nRadius");
  // Add picece button
  this->Internals->addPieceButton->setToolTip("Add a new piece after the lastest piece");
  QObject::connect(this->Internals->addPieceButton, &QPushButton::clicked, this, [this]() {
    // Get the current last piece
    QTableWidget* pT = this->Internals->piecesTable;
    int lastRowIndex = pT->rowCount() - 1;
    if (lastRowIndex < 0)
    {
      std::cerr << "pieces table does not have initial value" << std::endl;
      return;
    }
    QWidget* tmpWidget = pT->cellWidget(lastRowIndex, 0);
    QComboBox* comboBox = dynamic_cast<QComboBox*>(tmpWidget);
    rggPin::PieceType type = static_cast<rggPin::PieceType>(comboBox->currentIndex());
    double height = pT->item(lastRowIndex, 1)->text().toDouble();
    // If last row's type is frustum, we would flip the baseR and topR here
    double baseR = static_cast<bool>(type) ? pT->item(lastRowIndex, 3)->text().toDouble()
                        : pT->item(lastRowIndex, 2)->text().toDouble();
    double topR = static_cast<bool>(type) ? pT->item(lastRowIndex, 2)->text().toDouble()
                       : pT->item(lastRowIndex, 3)->text().toDouble();
    this->addPieceToTable(lastRowIndex + 1, type, height, baseR, topR);
  });
  // Remove picece button
  this->Internals->deletePieceButton->setToolTip("Delete the current selected piece");
  QObject::connect(this->Internals->deletePieceButton, &QPushButton::clicked, this, [this]() {
    auto pT = this->Internals->piecesTable;
    pT->blockSignals(true);
    int row = pT->currentRow();
    // Check radius status, making sure that it's forming a smooth surface
    if (row > 0 || row < (pT->rowCount() - 1))
    {
      radiusItem* baseRBefore = dynamic_cast<radiusItem*>(pT->item(row - 1, 2));
      radiusItem* baseRAfter = dynamic_cast<radiusItem*>(pT->item(row + 1, 2));
      if (baseRAfter && baseRBefore && baseRBefore != baseRAfter)
      {
        baseRBefore->setData(Qt::EditRole, QVariant(baseRAfter->text().toDouble()));
      }
    }
    pT->removeRow(row);
    pT->blockSignals(false);
    this->updateButtonStatus();
  });
}

void smtkRGGEditPinView::addPieceToTable(
  int row, rggPin::PieceType type, double height, double baseR, double topR)
{
  QTableWidget* pt = this->Internals->piecesTable;
  pt->setRowCount(pt->rowCount() + 1);
  pt->blockSignals(true);
  QTableWidgetItem* item(nullptr);
  // Type
  { //drop box
    QWidget* tmpWidget = pt->cellWidget(row, 0);
    QComboBox* comboBox = dynamic_cast<QComboBox*>(tmpWidget);
    if (comboBox == nullptr)
    {
      comboBox = new QComboBox(this->Internals->piecesTable);
      comboBox->addItem("Cylinder");
      comboBox->addItem("Frustum");
      comboBox->setObjectName("PincellPartBox_" + QString::number(row));
      pt->setCellWidget(row, 0, comboBox);
      item = new QTableWidgetItem;
      pt->setItem(row, 0, item);
      QObject::connect(comboBox, QOverload<const QString&>::of(&QComboBox::currentIndexChanged),
        this, &smtkRGGEditPinView::pieceTypeChanged);
    }
    // Cache row number on comboBox
    QVariant vdata;
    vdata.setValue(row);
    comboBox->setItemData(0, vdata);
    comboBox->blockSignals(true);
    if (type == rggPin::PieceType::FRUSTUM)
    {
      comboBox->setCurrentIndex(1);
    }
    else
    {
      comboBox->setCurrentIndex(0);
    }
    comboBox->blockSignals(false);
  }

  // length
  {
    item = new generalItem();
    item->setText(QString::number(height));
    pt->setItem(row, 1, item);
  }

  // radius (base)
  item = new radiusItem(RADIUSType::BASE);
  item->setText(QString::number(baseR));
  pt->setItem(row, 2, item);

  // radius (top)
  item = new radiusItem(RADIUSType::TOP);
  item->setText(QString::number(topR));
  pt->setItem(row, 3, item);

  pt->blockSignals(false);

  this->updateButtonStatus();
}

void smtkRGGEditPinView::createLayersTable()
{
  QTableWidget* pt = this->Internals->layersTable;
  pt->clear();
  this->Internals->layersTable->setRowCount(0);
  this->Internals->layersTable->setColumnCount(numberOfLayersTableColumns);
  this->Internals->layersTable->setHorizontalHeaderLabels(QStringList() << "Material"
                                                                        << "Radius\n(normalized)");
  this->Internals->layersTable->horizontalHeader()->setStretchLastSection(true);
  // Hard code a value so that the widget is align with the table
  this->Internals->layersTable->horizontalHeader()->setMinimumSectionSize(180);
  this->Internals->layersTable->horizontalHeader()->setSizeAdjustPolicy(
    QAbstractScrollArea::AdjustToContents);

  // Add layer before button
  QObject::connect(this->Internals->addLayerBeforeButton, &QPushButton::clicked, this,
    &smtkRGGEditPinView::addlayerBefore);
  // Add layer after button
  QObject::connect(this->Internals->addLayerAfterButton, &QPushButton::clicked, this,
    &smtkRGGEditPinView::addlayerAfter);

  // Delete layer button
  this->Internals->deleteLayerButton->setToolTip("Delete the current selected layer");
  QObject::connect(this->Internals->deleteLayerButton, &QPushButton::clicked, this,
    &smtkRGGEditPinView::deletelayer);
  QObject::connect(this->Internals->layersTable, &QTableWidget::itemSelectionChanged, this,
    &smtkRGGEditPinView::updateButtonStatus);
}

void smtkRGGEditPinView::addlayerBefore()
{
  QTableWidget* lT = this->Internals->layersTable;
  int row = 0;
  if (lT->selectedItems().count() != 0)
  {
    row = lT->selectedItems().value(0)->row();
  }
  // Generate the new rN. Input is assumed to be valid
  double beforeRN, afterRN;
  beforeRN = (row == 0) ? 0 : lT->item(row - 1, 1)->text().toDouble();
  afterRN = lT->item((row), 1)->text().toDouble();
  double rN = (beforeRN + afterRN) / 2;
  this->addLayerToTable(row, 0, rN);
}

void smtkRGGEditPinView::addlayerAfter()
{
  QTableWidget* lT = this->Internals->layersTable;
  int row = 0;
  if (lT->selectedItems().count() != 0)
  {
    row = lT->selectedItems().value(0)->row();
  }
  // Generate the new rN. Input is assumed to be valid
  double beforeRN, afterRN;
  beforeRN = lT->item(row, 1)->text().toDouble();
  afterRN = lT->item((row + 1), 1)->text().toDouble();
  double rN = (beforeRN + afterRN) / 2;
  this->addLayerToTable(row + 1, 0, rN);
}

void smtkRGGEditPinView::deletelayer()
{
  this->Internals->layersTable->blockSignals(true);
  int row = this->Internals->layersTable->currentRow();
  if (row == (this->Internals->layersTable->rowCount() - 1))
  { // Upper bound of normalized radius should always be 1
    this->Internals->layersTable->item(row - 1, 1)->setText(QString::number(1.0));
  }
  this->Internals->layersTable->removeRow(row);
  this->Internals->layersTable->blockSignals(false);
  this->updateButtonStatus();
}

void smtkRGGEditPinView::addLayerToTable(int row, int subMaterial, double rN)
{
  // Caller is reponsible for
  QTableWidget* lT = this->Internals->layersTable;
  // 0 would insert row to the very top and rowCount woud insert row to the very bottom
  if (row < 0 || row > lT->rowCount())
  { // invalid input
    return;
  }
  lT->blockSignals(true);
  lT->insertRow(row);
  // Create the material combo box first
  {
    QWidget* tmp = lT->cellWidget(row, 0);
    QComboBox* materialCom = dynamic_cast<QComboBox*>(tmp);
    if (materialCom == nullptr)
    {
      materialCom = new QComboBox(this->Internals->layersTable);
      materialCom->setObjectName("PinMaterialBox_" + QString::number(row));
      lT->setCellWidget(row, 0, materialCom);
    }
    materialCom->blockSignals(true);
    this->setupMaterialComboBox(materialCom);
    materialCom->blockSignals(false);
    materialCom->setCurrentIndex(subMaterial);
  }
  // normalRadius
  rangeItem* radiusNItem = new rangeItem();
  radiusNItem->setText(QString::number(rN));
  lT->setItem(row, 1, radiusNItem);
  //
  lT->blockSignals(false);
}

void smtkRGGEditPinView::updateButtonStatus()
{
  // Delete piece
  int rc = this->Internals->piecesTable->rowCount();
  this->Internals->deletePieceButton->setEnabled(rc > 1);
  // Delete layer
  rc = this->Internals->layersTable->rowCount();
  this->Internals->deleteLayerButton->setEnabled(rc > 1);
  // Add layer after
  if (this->Internals->layersTable->currentRow() == (rc - 1) ||
    this->Internals->layersTable->selectedItems().count() == 0)
  {
    this->Internals->addLayerAfterButton->setEnabled(false);
  }
  else
  {
    this->Internals->addLayerAfterButton->setEnabled(true);
  }
  if (this->Internals->layersTable->selectedItems().count() == 0)
  {
    this->Internals->addLayerBeforeButton->setEnabled(false);
  }
  else
  {
    this->Internals->addLayerBeforeButton->setEnabled(true);
  }
}

void smtkRGGEditPinView::setupMaterialComboBox(QComboBox* box, bool isCell)
{
  box->clear();
  size_t matN = smtk::session::rgg::CreateModel::materialNum(this->Internals->CurrentModel);
  for (size_t i = 0; i < matN; i++)
  {
    std::string name = smtk::session::rgg::CreateModel::getMaterial(i,
                                                                    this->Internals->CurrentModel);
    box->addItem(QString::fromStdString(name));
  }
  if (isCell)
  {
    // In this condition, the part does not need to have a material. Change the item text
  }
}
