Skip to content
Snippets Groups Projects
LayerItem.cpp 5.24 KiB
//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/Model/Sample/LayerItem.cpp
//! @brief     Implements class LayerItem
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/Model/Sample/LayerItem.h"
#include "GUI/Model/Group/GroupInfo.h"
#include "GUI/Model/Sample/LayerRoughnessItems.h"
#include "GUI/Model/Sample/MesoCrystalItem.h"
#include "GUI/Model/Sample/MultiLayerItem.h"
#include "GUI/Model/Sample/ParticleCompositionItem.h"
#include "GUI/Model/Sample/ParticleCoreShellItem.h"
#include "GUI/Model/Sample/ParticleItem.h"
#include "GUI/Model/Sample/ParticleLayoutItem.h"
#include "GUI/Model/Types/DoubleDescriptor.h"
#include "GUI/Model/Types/UIntDescriptor.h"
#include "GUI/Util/Error.h"
#include <QColor>

namespace {

QVector<ItemWithMaterial*> layoutItemsWithMaterial(ParticleLayoutItem* item)
{
    QVector<ItemWithMaterial*> result;

    QVector<ItemWithParticles*> itemsWithParticles{item->particles()};
    while (!itemsWithParticles.empty()) {
        auto* item = itemsWithParticles.takeFirst();
        if (!item)
            continue;

        if (auto* p = dynamic_cast<ParticleCompositionItem*>(item))
            itemsWithParticles << p->particles();
        else if (auto* p = dynamic_cast<MesoCrystalItem*>(item))
            itemsWithParticles << p->basisParticle();
        else if (auto* p = dynamic_cast<ParticleItem*>(item))
            result << p;
        else if (auto* p = dynamic_cast<ParticleCoreShellItem*>(item)) {
            if (p->core())
                result << p->core();
            if (p->shell())
                result << p->shell();
        } else
            ASSERT(false);
    }
    return result;
}

} // namespace

LayerItem::LayerItem() : SessionItem(M_TYPE), ItemWithMaterial(M_TYPE)
{
    addProperty(P_THICKNESS, 0.0)->setLimits(RealLimits::lowerLimited(0.0));
    addProperty(P_NSLICES, 1)->setLimits(RealLimits::lowerLimited(0.0));
    addProperty(P_COLOR, QColor()); // initially no color

    GroupInfo info;
    info.add(LayerBasicRoughnessItem::M_TYPE, "Basic");
    info.add(LayerZeroRoughnessItem::M_TYPE, "No");
    info.setDefaultType(LayerZeroRoughnessItem::M_TYPE);
    addGroupProperty(P_ROUGHNESS, info)->setToolTip("Roughness of top interface");

    registerTag(T_LAYOUTS, 0, -1, {ParticleLayoutItem::M_TYPE});
    setDefaultTag(T_LAYOUTS);
}

QString LayerItem::layerName() const
{
    return itemName();
}

QVector<ItemWithMaterial*> LayerItem::itemsWithMaterial()
{
    QVector<ItemWithMaterial*> result;
    result.push_back(this);
    for (auto* layout : layouts())
        result.append(layoutItemsWithMaterial(layout));
    return result;
}

QVector<ItemWithParticles*> LayerItem::itemsWithParticles() const
{
    QVector<ItemWithParticles*> result;
    for (auto* layout : layouts())
        result << layout->containedItemsWithParticles();
    return result;
}

DoubleDescriptor LayerItem::thickness() const
{
    DoubleDescriptor d(getItem(P_THICKNESS), Unit::nanometer);
    d.tooltip = "Thickness of the layer";
    return d;
}

bool LayerItem::isThicknessPropertyName(const QString& name)
{
    return name == P_THICKNESS;
}

void LayerItem::setThicknessEnabled(bool enabled)
{
    getItem(P_THICKNESS)->setEnabled(enabled);
}

SelectionDescriptor<std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*>>
LayerItem::roughness()
{
    SelectionDescriptor<std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*>> d(
        item<GroupItem>(P_ROUGHNESS));

    d.currentItem = [=]() -> std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*> {
        if (auto* r = dynamic_cast<LayerBasicRoughnessItem*>(getGroupItem(P_ROUGHNESS)))
            return {r};
        return {dynamic_cast<LayerZeroRoughnessItem*>(getGroupItem(P_ROUGHNESS))};
    };

    return d;
}

void LayerItem::setRoughnessEnabled(bool enabled)
{
    getItem(P_ROUGHNESS)->setEnabled(enabled);
}

UIntDescriptor LayerItem::numSlices() const
{
    UIntDescriptor d(getItem(P_NSLICES), Unit::unitless);
    d.tooltip = "Number of horizontal slices.\n"
                "Used for Average Layer Material calculations \n"
                "when corresponding simulation option is set.";
    return d;
}

QVector<ParticleLayoutItem*> LayerItem::layouts() const
{
    return items<ParticleLayoutItem>(T_LAYOUTS);
}

ParticleLayoutItem* LayerItem::addLayout()
{
    return model()->insertItem<ParticleLayoutItem>(this);
}

void LayerItem::removeLayout(ParticleLayoutItem* layout)
{
    model()->removeItem(layout);
}

QColor LayerItem::color() const
{
    return getItemValue(P_COLOR).value<QColor>();
}

void LayerItem::setColor(const QColor& color)
{
    setItemValue(P_COLOR, color);
}

void LayerItem::setIsTopLayer(bool b)
{
    m_isTopLayer = b;
}

bool LayerItem::isTopLayer() const
{
    return m_isTopLayer;
}

void LayerItem::setIsBottomLayer(bool b)
{
    m_isBottomLayer = b;
}

bool LayerItem::isBottomLayer() const
{
    return m_isBottomLayer;
}