// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file GUI/View/Sample/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/Sample/LayerForm.h" #include "Base/Util/Assert.h" #include "Base/Util/Vec.h" #include "GUI/Model/Material/MaterialItem.h" #include "GUI/Model/Material/MaterialsSet.h" #include "GUI/Model/Project/ProjectDocument.h" #include "GUI/Model/Sample/LayerItem.h" #include "GUI/Model/Sample/RoughnessItems.h" #include "GUI/Model/Sample/SampleItem.h" #include "GUI/View/Numeric/NumWidgetUtil.h" #include "GUI/View/Sample/HeinzFormLayout.h" #include "GUI/View/Sample/MaterialInplaceForm.h" #include "GUI/View/Sample/ParticleLayoutForm.h" #include "GUI/View/Sample/RoughnessForm.h" #include "GUI/View/Widget/WidgetMoverButton.h" #include <QLineEdit> #include <QPushButton> LayerForm::LayerForm(QWidget* parent, LayerItem* layer, SampleEditorController* ec) : LayerContainerForm(parent, layer, ec, "layer") { m_layout->addBoldRow("Material:", new MaterialInplaceForm(layer, ec)); m_layout->addValue(layer->thickness()); m_thickness_row = m_layout->rowCount() - 1; m_layout->addBoldRow("Number of slices:", GUI::Util::createIntSpinBox( [this] { return layerItem()->numSlices(); }, [this](int v) { layerItem()->setNumSlices(v); emit gDoc->sampleChanged(); }, RealLimits::lowerLimited(1), "Number of horizontal slices.\n" "Used for Average Layer Material calculations \n" "when corresponding simulation option is set.")); m_roughnessForm = new RoughnessForm(this, layer->roughnessSelection(), layer->expandRoughness, m_ec); m_layout->addRow(m_roughnessForm); m_roughness_row = m_layout->rowCount() - 1; // -- layouts for (auto* layout : layer->layoutItems()) m_layout->addRow(new ParticleLayoutForm(this, layout, ec)); // -- Button for adding a new layout auto* btn = new QPushButton("Add particle layout", this); connect(btn, &QPushButton::clicked, [this, ec] { ec->addLayoutItem(this); }); m_structure_editing_widgets << btn; m_layout->addStructureEditingRow(btn); // listen to changes in materials to update the title (contains the material name). Necessary // to reflect e.g. a name change done in the material editor. connect(ec->materialModel(), &MaterialsSet::materialChanged, this, &LayerForm::updateTitle); updatePositionDependentElements(); } LayerItem* LayerForm::layerItem() const { return dynamic_cast<LayerItem*>(m_item); } void LayerForm::updateTitle() { QString material_text = " Material: " + layerItem()->materialName(); if (layerItem()->isAmbient()) setTitle("Ambient" + material_text); else if (layerItem()->isSubstrate()) setTitle("Substrate" + material_text); else { const SampleItem* sampleItem = m_ec->sampleItem(); ASSERT(sampleItem); int i = Vec::indexOfPtr(layerItem(), sampleItem->uniqueLayerItems()); setTitle("Layer " + QString::number(i) + material_text); } } void LayerForm::updatePositionDependentElements() { if (m_roughness_row == -1) return; updateTitle(); const auto* sample = m_ec->sampleItem(); const bool isAmbient = layerItem()->isAmbient(); const bool isSubstrate = layerItem()->isSubstrate(); const bool thicknessIsSemiInfinite = (isAmbient || isSubstrate) && (sample->uniqueLayerItems().size() > 1); const bool thicknessIsInfinite = isAmbient && (sample->uniqueLayerItems().size() == 1); m_roughnessForm->setVisible(!isAmbient); if (m_thickness_row == -1) return; m_roughnessForm->markLayerAsSubstrate(isSubstrate); QWidget* w = m_layout->itemAt(m_thickness_row, QFormLayout::FieldRole)->widget(); if (thicknessIsSemiInfinite || thicknessIsInfinite) { auto* info = qobject_cast<QLineEdit*>(w); if (info == nullptr) { m_layout->removeRow(m_thickness_row); info = new QLineEdit(this); info->setEnabled(false); info->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_layout->insertRow(m_thickness_row, layerItem()->thickness().label(), info); } info->setText(thicknessIsSemiInfinite ? "Semi-infinite" : "Infinite"); } else if (!thicknessIsSemiInfinite && !thicknessIsInfinite && (qobject_cast<QLineEdit*>(w) != nullptr)) { m_layout->removeRow(m_thickness_row); m_layout->insertValue(m_thickness_row, layerItem()->thickness()); } m_move_button->setVisible(m_ec->sampleItem()->uniqueLayerItems().size() > 1); } void LayerForm::onLayoutAdded(ParticleLayoutItem* t) { int index = Vec::indexOfPtr(t, layerItem()->layoutItems()); const int rowInLayout = m_layout->rowCount() - layerItem()->layoutItems().size() + index; QWidget* w = new ParticleLayoutForm(this, t, m_ec); m_layout->insertRow(rowInLayout, w); } void LayerForm::onAboutToRemoveLayout(ParticleLayoutItem* t) { int index = Vec::indexOfPtr(t, layerItem()->layoutItems()); const int rowInLayout = m_layout->rowCount() - layerItem()->layoutItems().size() - 1 + index; // -1: btn m_layout->removeRow(rowInLayout); }