Newer
Older
// ************************************************************************************************
//
// 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 "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)
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());
}
std::vector<ItemWithLayers*> LayerStackItem::componentItems() const
return result;
}
int LayerStackItem::indexOfComponent(const ItemWithLayers* item) const
{
const std::vector<ItemWithLayers*> component_items = componentItems();
return Vec::indexOfPtr(item, component_items);
LayerStackItem* LayerStackItem::parentOfComponent(const ItemWithLayers* searchedItem)
{
for (auto* component : componentItems()) {
if (component == searchedItem)
return this;
if (auto* stack = dynamic_cast<LayerStackItem*>(component)) {
auto* subparent = stack->parentOfComponent(searchedItem);
if (subparent)
return subparent;
}
}
return nullptr;
}
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();
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);
}
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)
{
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);
m_components.push_back(new PolyPtr<ItemWithLayers, LayeredComponentCatalog>);
m_components.back()->readFrom(r, m_materials);