// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file GUI/View/SampleDesigner/InterferenceForm.cpp //! @brief Implements class InterferenceForm //! //! @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/InterferenceForm.h" #include "GUI/Model/Item/InterferenceItems.h" #include "GUI/Model/Item/Lattice2DItems.h" #include "GUI/Model/Item/ParticleLayoutItem.h" #include "GUI/Model/Descriptor/UIntDescriptor.h" #include "GUI/View/PropertyEditor/CustomEventFilters.h" #include "GUI/View/SampleDesigner/FormLayouter.h" #include "GUI/View/SampleDesigner/LatticeTypeSelectionForm.h" #include "GUI/View/SampleDesigner/SampleEditorController.h" #include "GUI/View/SampleDesigner/SelectionContainerForm.h" #include "GUI/View/Tool/GroupBoxCollapser.h" InterferenceForm::InterferenceForm(QWidget* parent, ParticleLayoutItem* layoutItem, SampleEditorController* ec) : QGroupBox(parent) , m_layoutItem(layoutItem) , m_ec(ec) { setTitle("Interference Function"); FormLayouter layouter(this, ec); layouter.setContentsMargins(6, 6, 0, 6); m_collapser = GroupBoxCollapser::installIntoGroupBox(this); m_interferenceTypeCombo = new QComboBox(this); WheelEventEater::install(m_interferenceTypeCombo); auto d = layoutItem->interference(); m_interferenceTypeCombo->addItems(d.options); m_interferenceTypeCombo->setCurrentIndex(d.currentIndex()); m_interferenceTypeCombo->setMaxVisibleItems(m_interferenceTypeCombo->count()); m_interferenceTypeCombo->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); layouter.addRow("Type:", m_interferenceTypeCombo); createInterferenceWidgets(); updateTitle(); connect(m_interferenceTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int newIndex) { m_ec->selectInterference(this, newIndex); }); } ParticleLayoutItem* InterferenceForm::layoutItem() const { return m_layoutItem; } void InterferenceForm::onInterferenceTypeChanged() { FormLayouter layouter(this, m_ec); while (layouter.layout()->rowCount() > 1) layouter.layout()->removeRow(1); createInterferenceWidgets(); updateTitle(); } void InterferenceForm::createInterferenceWidgets() { FormLayouter layouter(this, m_ec); auto* interference = m_layoutItem->interference().currentItem(); // Some values in interference settings affect the total density in the particle layout. To // provide all the updating (data & UI), the method // SampleEditorController::setDensityRelatedValueValue has to be called (instead of // SampleEditorController::setDouble). For this we have the following lambda to add a value: const auto addDensityRelatedValue = [&](DoubleDescriptor d) { layouter.addValue( d, [=](double newValue) { m_ec->setDensityRelatedValue(interference, newValue, d); }); }; if (auto* itf = dynamic_cast<Interference1DLatticeItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->length()); layouter.addValue(itf->rotationAngle()); layouter.addSelection(itf->decayFunction()); } else if (auto* itf = dynamic_cast<InterferenceRadialParaCrystalItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->peakDistance()); layouter.addValue(itf->dampingLength()); layouter.addValue(itf->domainSize()); layouter.addValue(itf->kappa()); layouter.addSelection(itf->probabilityDistribution()); } else if (auto* itf = dynamic_cast<InterferenceHardDiskItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->radius()); addDensityRelatedValue(itf->density()); } else if (auto* itf = dynamic_cast<Interference2DLatticeItem*>(interference)) { layouter.addValue(itf->positionVariance()); auto* w = new LatticeTypeSelectionForm(this, itf, m_ec); layouter.addRow(itf->latticeType().label, w); layouter.addSelection(itf->decayFunction()); } else if (auto* itf = dynamic_cast<InterferenceFinite2DLatticeItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->domainSize1()); layouter.addValue(itf->domainSize2()); auto* w = new LatticeTypeSelectionForm(this, itf, m_ec); layouter.addRow(itf->latticeType().label, w); } else if (auto* itf = dynamic_cast<Interference2DParaCrystalItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->dampingLength()); layouter.addValue(itf->domainSize1()); layouter.addValue(itf->domainSize2()); auto* w = new LatticeTypeSelectionForm(this, itf, m_ec); layouter.addRow(itf->latticeType().label, w); layouter.addSelection(itf->probabilityDistribution1()); layouter.addSelection(itf->probabilityDistribution2()); } } void InterferenceForm::updateTitle() { m_collapser->setTitle("Interference Function (" + m_interferenceTypeCombo->currentText() + ")"); }