Skip to content
Snippets Groups Projects
LayerStackItem.cpp 4.55 KiB
Newer Older
  • Learn to ignore specific revisions
  • //  ************************************************************************************************
    //
    //  BornAgain: simulate and fit reflection and scattering
    //
    //! @file      GUI/Model/Sample/LayerStackItem.cpp
    //! @brief     Implements class LayerStackItem.
    //!
    //! @homepage  http://www.bornagainproject.org
    //! @license   GNU General Public License v3 or higher (see COPYING)
    //! @copyright Forschungszentrum Jülich GmbH 2024
    //! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
    //
    //  ************************************************************************************************
    
    #include "GUI/Model/Sample/LayerStackItem.h"
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    #include "Base/Util/Vec.h"
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    #include "GUI/Model/Material/MaterialsSet.h"
    #include "GUI/Model/Sample/LayerItem.h"
    
    #include "GUI/Model/Util/UtilXML.h"
    
    namespace {
    namespace Tag {
    
    const QString BaseData("BaseData");
    const QString Component("Component");
    const QString NumPeriods("NumPeriods");
    
    } // namespace Tag
    } // namespace
    
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    LayerStackItem::LayerStackItem(const MaterialsSet* materials, uint n_periods)
    
        : m_n_periods(n_periods)
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        , m_materials(materials)
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        ASSERT(materials);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    std::vector<LayerItem*> LayerStackItem::uniqueLayerItems()
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        std::vector<LayerItem*> result;
        for (const auto& component : m_components) {
            std::vector<LayerItem*> sublayers = component.certainItem()->uniqueLayerItems();
            result.insert(result.end(), sublayers.begin(), sublayers.end());
        }
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        return result;
    }
    
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    std::vector<ItemWithLayers*> LayerStackItem::componentItems() const
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        std::vector<ItemWithLayers*> result;
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        for (const auto& component : m_components)
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
            result.push_back(component.certainItem());
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        return result;
    }
    
    int LayerStackItem::indexOfComponent(const ItemWithLayers* item) const
    {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        const std::vector<ItemWithLayers*> component_items = componentItems();
        return Vec::indexOfPtr(item, component_items);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    ItemWithLayers* LayerStackItem::addNewItemAt(ItemWithLayers* item, int index)
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    {
        ASSERT(item);
        if (index < 0)
            index = m_components.size();
    
        PolyPtr<ItemWithLayers, LayeredComponentCatalog> new_item;
        new_item.setCertainItem(item); // gets ownership
        m_components.insert(m_components.begin() + index, std::move(new_item));
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        return m_components[index].certainItem();
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    LayerItem* LayerStackItem::createLayerItemAt(int index)
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
    {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        ItemWithLayers* new_item = addNewItemAt(new LayerItem(m_materials), index);
        auto* layer = dynamic_cast<LayerItem*>(new_item);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        ASSERT(layer);
        return layer;
    }
    
    LayerStackItem* LayerStackItem::createLayerStackItemAt(int index)
    {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        ItemWithLayers* new_item = addNewItemAt(new LayerStackItem(m_materials), index);
        auto* stack = dynamic_cast<LayerStackItem*>(new_item);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        ASSERT(stack);
        return stack;
    }
    
    void LayerStackItem::removeComponent(const ItemWithLayers* component)
    {
        ASSERT(component);
        int index = indexOfComponent(component);
        if (index < 0)
            return;
        m_components.erase(m_components.begin() + index);
    }
    
    void LayerStackItem::moveComponent(ItemWithLayers* component, ItemWithLayers* aboveThisComponent)
    {
        if (component == aboveThisComponent)
            return;
    
        int currentIndex = indexOfComponent(component);
        ASSERT(currentIndex >= 0);
    
        int abothThisIndex = indexOfComponent(aboveThisComponent);
        if (abothThisIndex < 0)
            abothThisIndex = m_components.size();
    
        ASSERT(currentIndex != abothThisIndex);
    
        auto b = m_components.begin();
        if (currentIndex < abothThisIndex)
            std::rotate(b + currentIndex, b + currentIndex + 1, b + abothThisIndex);
        else
            std::rotate(b + abothThisIndex, b + currentIndex, b + currentIndex + 1);
    }
    
    
    void LayerStackItem::writeTo(QXmlStreamWriter* w) const
    {
        XML::writeBaseElement<ItemWithLayers>(w, Tag::BaseData, this);
        XML::writeTaggedValue(w, Tag::NumPeriods, m_n_periods);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        for (const auto& component : m_components)
            XML::writeTaggedElement(w, Tag::Component, component);
    
    }
    
    void LayerStackItem::readFrom(QXmlStreamReader* r)
    {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        m_components.clear();
    
        while (r->readNextStartElement()) {
            QString tag = r->name().toString();
            if (tag == Tag::BaseData)
                XML::readBaseElement<ItemWithLayers>(r, tag, this);
            else if (tag == Tag::NumPeriods)
                m_n_periods = XML::readTaggedUInt(r, tag);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
            else if (tag == Tag::Component) {
                m_components.push_back(std::move(PolyPtr<ItemWithLayers, LayeredComponentCatalog>()));
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
                m_components.back().readFrom(r, m_materials);
                XML::gotoEndElementOfTag(r, tag);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
            } else
    
                r->skipCurrentElement();
        }
    }