// ************************************************************************************************ // // 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" #include "Base/Util/Vec.h" #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 LayerStackItem::LayerStackItem(const MaterialsSet* materials, uint n_periods) : m_n_periods(n_periods) , m_materials(materials) { ASSERT(materials); } std::vector<LayerItem*> LayerStackItem::uniqueLayerItems() { 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()); } return result; } std::vector<ItemWithLayers*> LayerStackItem::componentItems() const { std::vector<ItemWithLayers*> result; for (const auto& component : m_components) result.push_back(component->certainItem()); return result; } int LayerStackItem::indexOfComponent(const ItemWithLayers* item) const { const std::vector<ItemWithLayers*> component_items = componentItems(); return Vec::indexOfPtr(item, component_items); } ItemWithLayers* LayerStackItem::addNewItemAt(ItemWithLayers* item, int index) { ASSERT(item); if (index < 0) index = m_components.size(); auto new_item = new PolyPtr<ItemWithLayers, LayeredComponentCatalog>; new_item->setCertainItem(item); // gets ownership m_components.insert_at(index, new_item); return m_components[index]->certainItem(); } LayerItem* LayerStackItem::createLayerItemAt(int index) { ItemWithLayers* new_item = addNewItemAt(new LayerItem(m_materials), index); auto* layer = dynamic_cast<LayerItem*>(new_item); ASSERT(layer); return layer; } LayerStackItem* LayerStackItem::createLayerStackItemAt(int index) { ItemWithLayers* new_item = addNewItemAt(new LayerStackItem(m_materials), index); auto* stack = dynamic_cast<LayerStackItem*>(new_item); ASSERT(stack); return stack; } void LayerStackItem::removeComponent(const ItemWithLayers* component) { ASSERT(component); int index = indexOfComponent(component); if (index < 0) return; m_components.delete_at(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); for (const auto* component : m_components) XML::writeTaggedElement(w, Tag::Component, *component); } void LayerStackItem::readFrom(QXmlStreamReader* r) { 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); else if (tag == Tag::Component) { m_components.push_back(new PolyPtr<ItemWithLayers, LayeredComponentCatalog>); m_components.back()->readFrom(r, m_materials); XML::gotoEndElementOfTag(r, tag); } else r->skipCurrentElement(); } }