Skip to content
Snippets Groups Projects
LayerForm.cpp 6.06 KiB
Newer Older
  • Learn to ignore specific revisions
  • //  ************************************************************************************************
    //
    //  BornAgain: simulate and fit reflection and scattering
    //
    //! @file      GUI/Views/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/Views/SampleDesigner/LayerForm.h"
    
    #include "GUI/Items/LayerItem.h"
    #include "GUI/Items/MultiLayerItem.h"
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    #include "GUI/Models/Types/UIntDescriptor.h"
    
    #include "GUI/CommonWidgets/GroupBoxCollapser.h"
    
    #include "GUI/Views/SampleDesigner/MaterialInplaceForm.h"
    #include "GUI/Views/SampleDesigner/ParticleLayoutForm.h"
    #include "GUI/Views/SampleDesigner/SampleEditorController.h"
    #include "GUI/Views/SampleDesigner/SelectionContainerForm.h"
    #include "GUI/Views/SampleDesigner/WidgetMoverButton.h"
    #include "GUI/utils/ActionFactory.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); });
    
        QAction* 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");
        QMenu* 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);
        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;
    
        m_layouter->setRowVisible(m_roughnessRow, !isFirstLayer);
    
        if (m_thicknessRow == -1)
            return;
        QWidget* w = m_layouter->layout()->itemAt(m_thicknessRow, QFormLayout::FieldRole)->widget();
        if (thicknessIsSemiInfinite && (qobject_cast<QLineEdit*>(w) == nullptr)) {
            m_layouter->removeRow(m_thicknessRow);
            QLineEdit* info = new QLineEdit("Semi-infinite", this);
            info->setEnabled(false);
            info->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
            m_layouter->insertRow(m_thicknessRow, m_layer->thickness().label, info);
        } else if (!thicknessIsSemiInfinite && (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;
    }