// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file GUI/View/SampleDesigner/FormLayouter.cpp //! @brief Implements class FormLayouter //! //! @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/FormLayouter.h" #include "Base/Util/Assert.h" #include "GUI/Model/Descriptor/VectorProperty.h" #include "GUI/View/Common/DoubleSpinBox.h" #include "GUI/View/SampleDesigner/LayerEditorUtils.h" #include "GUI/View/SampleDesigner/SampleEditorController.h" #include "GUI/View/Tool/GroupBoxCollapser.h" #include <QFormLayout> #include <QGroupBox> #include <QLabel> #include <QPushButton> using std::function; FormLayouter::FormLayouter(QWidget* parent, SampleEditorController* ec) : m_ec(ec) { if (parent->layout() != nullptr) { m_formLayout = dynamic_cast<QFormLayout*>(parent->layout()); if (m_formLayout == nullptr) { auto* collapser = GroupBoxCollapser::findInstalledCollapser(dynamic_cast<QGroupBox*>(parent)); if (collapser) m_formLayout = dynamic_cast<QFormLayout*>(collapser->contentArea()->layout()); } ASSERT(m_formLayout); } else { m_formLayout = new QFormLayout(parent); m_formLayout->setFormAlignment(Qt::AlignLeft | Qt::AlignBottom); m_formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); } } QFormLayout* FormLayouter::layout() { return m_formLayout; } void FormLayouter::setContentsMargins(int left, int top, int right, int bottom) { m_formLayout->setContentsMargins(left, top, right, bottom); } int FormLayouter::addRow(const QString& label, QWidget* w) { insertRow(m_formLayout->rowCount(), label, w); return m_formLayout->rowCount() - 1; } int FormLayouter::addRow(const QString& label, QSpinBox* w) { return addRow(label, qobject_cast<QWidget*>(w)); } void FormLayouter::insertRow(int row, QString label, QWidget* w) { if (!label.endsWith(":")) label += ":"; m_formLayout->insertRow(row, LayerEditorUtils::createBoldLabel(label), w); } int FormLayouter::addGroupOfValues(const QString& labelText, const DoublePropertyRefs& values) { auto* w = new QWidget(m_formLayout->parentWidget()); w->setObjectName("PropertyBaseWidget"); w->setAttribute(Qt::WA_StyledBackground, true); w->setStyleSheet("#PropertyBaseWidget {background-color: transparent}"); auto* gridLayout = new QGridLayout(w); gridLayout->setContentsMargins(0, 0, 0, 0); gridLayout->setSpacing(6); LayerEditorUtils::addMultiPropertyToGrid(gridLayout, 0, values, m_ec, true); return addRow(labelText, w); } int FormLayouter::addVector(VectorProperty& d, bool vertically /*= true*/) { auto* w = new QWidget(m_formLayout->parentWidget()); w->setObjectName("PropertyBaseWidget"); w->setAttribute(Qt::WA_StyledBackground, true); w->setStyleSheet("#PropertyBaseWidget {background-color: transparent}"); auto* gridLayout = new QGridLayout(w); gridLayout->setContentsMargins(0, 0, 0, 0); gridLayout->setSpacing(6); LayerEditorUtils::addMultiPropertyToGrid(gridLayout, 0, {d.x(), d.y(), d.z()}, m_ec, vertically, true); return addRow(d.label(), w); } void FormLayouter::setRowVisible(int row, bool visible) { m_formLayout->itemAt(row, QFormLayout::LabelRole)->widget()->setVisible(visible); m_formLayout->itemAt(row, QFormLayout::FieldRole)->widget()->setVisible(visible); } void FormLayouter::removeRow(int row) { m_formLayout->removeRow(row); } void FormLayouter::addStructureEditingRow(QPushButton* button) { auto* w = new QWidget(m_formLayout->parentWidget()); auto* l = new QHBoxLayout(w); l->setContentsMargins(0, 0, 0, 0); l->setAlignment(Qt::AlignLeft); l->setSizeConstraint(QLayout::SetMinimumSize); l->addWidget(button); l->addStretch(); addRow(w); } int FormLayouter::addValue(DoubleProperty& d) { insertValue(m_formLayout->rowCount(), d); return m_formLayout->rowCount() - 1; } int FormLayouter::addValue(DoubleProperty& d, function<void(double)> onValueChange) { insertValue(m_formLayout->rowCount(), d, onValueChange); return m_formLayout->rowCount() - 1; } void FormLayouter::insertValue(int row, DoubleProperty& d) { auto* ec = m_ec; // to allow copy-capture in the following lambda insertValue(row, d, [ec, &d](double newValue) { ec->setDouble(newValue, d); }); } void FormLayouter::insertValue(int row, DoubleProperty& d, function<void(double)> onValueChange) { auto labelText = d.label(); if (!labelText.endsWith(":")) labelText += ":"; auto* label = LayerEditorUtils::createBoldLabel(labelText); label->setAlignment(Qt::AlignLeft | Qt::AlignBottom); label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); auto* editor = new DoubleSpinBox(d); QObject::connect(editor, &DoubleSpinBox::baseValueChanged, onValueChange); label->setBuddy(editor); LayerEditorUtils::updateLabelUnit(label, editor); m_formLayout->insertRow(row, label, editor); } int FormLayouter::addRow(QWidget* w) { m_formLayout->addRow(w); return m_formLayout->rowCount() - 1; } void FormLayouter::insertRow(int row, QWidget* w) { m_formLayout->insertRow(row, w); }