Skip to content
Snippets Groups Projects
FormLayouter.cpp 6.55 KiB
Newer Older
  • Learn to ignore specific revisions
  • //  ************************************************************************************************
    //
    //  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 "GUI/Model/Descriptor/UIntDescriptor.h"
    #include "GUI/Model/Descriptor/VectorDescriptor.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>
    
    
    namespace {
    
    QWidget* createSpinBox(QWidget* parentWidget, const UIntDescriptor& d, SampleEditorController* ec)
    {
    
        auto* spinBox = new QSpinBox(parentWidget);
    
        spinBox->setFocusPolicy(Qt::StrongFocus);
        spinBox->setKeyboardTracking(false);
        spinBox->setToolTip(d.tooltip);
        spinBox->setMaximum(std::numeric_limits<int>::max());
        spinBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    
        if (d.limits.hasLowerLimit())
            spinBox->setMinimum(static_cast<int>(d.limits.lowerLimit()));
        if (d.limits.hasUpperLimit())
            spinBox->setMaximum(static_cast<int>(d.limits.upperLimit()));
    
        spinBox->setValue(d.get());
    
        QObject::connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
                         [=](int newValue) { ec->setInt(newValue, d); });
    
        return spinBox;
    }
    
    } // namespace
    
    
    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;
    }
    
    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 DoubleDescriptors& 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(const VectorDescriptor& 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(const UIntDescriptor& d)
    {
        auto* editor = createSpinBox(m_formLayout->parentWidget(), d, m_ec);
        return addRow(d.label, editor);
    }
    
    int FormLayouter::addValue(const DoubleDescriptor& d)
    {
        insertValue(m_formLayout->rowCount(), d);
        return m_formLayout->rowCount() - 1;
    }
    
    
    int FormLayouter::addValue(const DoubleDescriptor& d, function<void(double)> onValueChange)
    {
        insertValue(m_formLayout->rowCount(), d, onValueChange);
        return m_formLayout->rowCount() - 1;
    }
    
    
    void FormLayouter::insertValue(int row, const DoubleDescriptor& 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, const DoubleDescriptor& 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);
    }