// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file GUI/View/SampleDesigner/LayerForm.cpp //! @brief Implements class LayerForm //! //! @homepage http://www.bornagainproject.org //! @license GNU General Public License v3 or higher (see COPYING) //! @copyright Forschungszentrum Jülich GmbH 2021 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) // // ************************************************************************************************ #include "GUI/View/SampleDesigner/LayerForm.h" #include "GUI/Model/Sample/LayerItem.h" #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Types/UIntDescriptor.h" #include "GUI/View/SampleDesigner/ActionFactory.h" #include "GUI/View/SampleDesigner/MaterialInplaceForm.h" #include "GUI/View/SampleDesigner/ParticleLayoutForm.h" #include "GUI/View/SampleDesigner/WidgetMoverButton.h" #include "GUI/View/Tool/GroupBoxCollapser.h" #include <QLineEdit> #include <QMenu> #include <QPushButton> LayerForm::LayerForm(QWidget* parent, LayerItem* layer, SampleEditorController* ec) : QGroupBox(parent), m_layer(layer), m_ec(ec) { setTitle(m_layer->itemName()); m_layouter.reset(new FormLayouter(this, ec)); m_layouter->setContentsMargins(6, 6, 0, 6); m_collapser = GroupBoxCollapser::installIntoGroupBox(this, false); m_removeAction = ActionFactory::createRemoveAction(this, "layer", [=] { ec->removeLayer(layer); }); auto* chooseColorAction = new QAction(this); chooseColorAction->setText("Choose color"); chooseColorAction->setIcon(QIcon(":/images/palette.svg")); chooseColorAction->setIconText("Choose color"); chooseColorAction->setToolTip("Choose a color for this layer"); auto* menu = new QMenu(this); chooseColorAction->setMenu(menu); for (auto col : LayerEditorUtils::predefinedLayerColors()) { QPixmap p(64, 64); p.fill(col); auto ca = menu->addAction(QIcon(p), ""); connect(ca, &QAction::triggered, [=]() { layer->setColor(col); updateColor(); }); } auto* moveButton = new WidgetMoverButton(this, this, 1); moveButton->setToolTip("Move layer up/down"); connect(moveButton, &WidgetMoverButton::startingToMove, ec, &SampleEditorController::onStartingToMoveLayer); connect(moveButton, &WidgetMoverButton::finishedMoving, ec, &SampleEditorController::onStoppedToMoveLayer); auto* showInRealSpaceAction = ActionFactory::createShowInRealSpaceAction( this, "layer", [=] { m_ec->requestViewInRealSpace(layer); }); m_collapser->addAction(showInRealSpaceAction); m_collapser->addAction(chooseColorAction); m_collapser->addAction(m_removeAction); m_collapser->addWidget(moveButton); m_structureEditingWidgets << moveButton; QColor bckgroundCol = m_layer->color(); setStyleSheet("QGroupBox {background-color: " + bckgroundCol.name(QColor::HexRgb) + "}"); m_layouter->addRow("Material:", new MaterialInplaceForm(this, layer, ec)); m_thicknessRow = m_layouter->addValue(m_layer->thickness()); m_layouter->addValue(m_layer->numSlices()); m_roughnessRow = m_layouter->addSelection(m_layer->roughness()); // -- layouts for (auto layout : layer->layouts()) m_layouter->addRow(new ParticleLayoutForm(this, layout, ec)); // -- Button for adding a new layout auto* btn = new QPushButton("Add particle layout", this); connect(btn, &QPushButton::clicked, [=] { ec->addLayout(this); }); m_structureEditingWidgets << btn; m_layouter->addStructureEditingRow(btn); updateLayerPositionDependentElements(); } void LayerForm::enableStructureEditing(bool b) { m_removeAction->setVisible(b); for (auto w : m_structureEditingWidgets) w->setVisible(b); } void LayerForm::updateColor() { QColor bckgroundCol = m_layer->color(); setStyleSheet("QGroupBox {background-color: " + bckgroundCol.name(QColor::HexRgb) + "}"); } void LayerForm::updateTitle() { const auto* multiLayer = dynamic_cast<MultiLayerItem*>(m_layer->parent()); int i = multiLayer->layers().indexOf(m_layer); m_collapser->setTitle("Layer " + QString::number(i) + " Material: " + m_layer->materialName()); } void LayerForm::updateLayerPositionDependentElements() { if (m_roughnessRow == -1) return; updateTitle(); const auto* multiLayer = dynamic_cast<MultiLayerItem*>(m_layer->parent()); const bool isFirstLayer = multiLayer->layers().first() == m_layer; const bool isLastLayer = multiLayer->layers().last() == m_layer; const bool thicknessIsSemiInfinite = (isFirstLayer || isLastLayer) && (multiLayer->layers().size() != 1); const bool thicknessIsInfinite = multiLayer->layers().size() == 1; m_layouter->setRowVisible(m_roughnessRow, !isFirstLayer); if (m_thicknessRow == -1) return; QWidget* w = m_layouter->layout()->itemAt(m_thicknessRow, QFormLayout::FieldRole)->widget(); if (thicknessIsSemiInfinite || thicknessIsInfinite) { QLineEdit* info = qobject_cast<QLineEdit*>(w); if (info == nullptr) { m_layouter->removeRow(m_thicknessRow); info = new QLineEdit(this); info->setEnabled(false); info->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_layouter->insertRow(m_thicknessRow, m_layer->thickness().label, info); } info->setText(thicknessIsSemiInfinite ? "Semi-infinite" : "Infinite"); } else if (!thicknessIsSemiInfinite && !thicknessIsInfinite && (qobject_cast<QLineEdit*>(w) != nullptr)) { m_layouter->removeRow(m_thicknessRow); m_layouter->insertValue(m_thicknessRow, m_layer->thickness()); } } void LayerForm::onLayoutAdded(ParticleLayoutItem* newLayoutItem) { int index = m_layer->layouts().indexOf(newLayoutItem); const int rowInLayout = m_layouter->layout()->rowCount() - m_layer->layouts().size() + index; m_layouter->insertRow(rowInLayout, new ParticleLayoutForm(this, newLayoutItem, m_ec)); } void LayerForm::onAboutToRemoveLayout(ParticleLayoutItem* layoutItem) { int index = m_layer->layouts().indexOf(layoutItem); const int rowInLayout = m_layouter->layout()->rowCount() - m_layer->layouts().size() - 1 + index; // -1: btn m_layouter->removeRow(rowInLayout); } LayerItem* LayerForm::layerItem() const { return m_layer; }