From feb37a8dbdf1bc1e40c522c97ef4fc41876be646 Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Sat, 18 Dec 2021 08:28:27 +0100
Subject: [PATCH] free RotationItems from SessionItem

---
 GUI/Model/Sample/RotationItemCatalog.cpp    |  80 ++++++++++++
 GUI/Model/Sample/RotationItemCatalog.h      |  60 +++++++++
 GUI/Model/Sample/RotationItems.cpp          | 110 +++++++++++++++++
 GUI/Model/{Trafo => Sample}/RotationItems.h |  49 ++++----
 GUI/Model/Trafo/RotationItems.cpp           | 128 --------------------
 5 files changed, 273 insertions(+), 154 deletions(-)
 create mode 100644 GUI/Model/Sample/RotationItemCatalog.cpp
 create mode 100644 GUI/Model/Sample/RotationItemCatalog.h
 create mode 100644 GUI/Model/Sample/RotationItems.cpp
 rename GUI/Model/{Trafo => Sample}/RotationItems.h (65%)
 delete mode 100644 GUI/Model/Trafo/RotationItems.cpp

diff --git a/GUI/Model/Sample/RotationItemCatalog.cpp b/GUI/Model/Sample/RotationItemCatalog.cpp
new file mode 100644
index 00000000000..e5bad270bc8
--- /dev/null
+++ b/GUI/Model/Sample/RotationItemCatalog.cpp
@@ -0,0 +1,80 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Model/Sample/RotationItemCatalog.cpp
+//! @brief     Implements class RotationItemCatalog
+//!
+//! @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/Model/Sample/RotationItemCatalog.h"
+#include "GUI/Model/Sample/RotationItems.h"
+
+RotationItem* RotationItemCatalog::create(Type type)
+{
+    switch (type) {
+    case Type::None:
+        return nullptr;
+    case Type::X:
+        return new XRotationItem();
+    case Type::Y:
+        return new YRotationItem();
+    case Type::Z:
+        return new ZRotationItem();
+    case Type::Euler:
+        return new EulerRotationItem();
+    }
+    ASSERT(false);
+}
+
+QVector<RotationItemCatalog::Type> RotationItemCatalog::types()
+{
+    return {Type::None, Type::X, Type::Y, Type::Z, Type::Euler};
+}
+
+RotationItemCatalog::UiInfo RotationItemCatalog::uiInfo(Type type)
+{
+    auto createUiInfo = [](const QString& menuEntry, const QString& description) {
+        UiInfo info;
+        info.menuEntry = menuEntry;
+        info.description = description;
+        return info;
+    };
+
+    switch (type) {
+    case Type::None:
+        return createUiInfo("None", "");
+    case Type::X:
+        return createUiInfo("X axis Rotation", "Particle rotation around x-axis");
+    case Type::Y:
+        return createUiInfo("Y axis Rotation", "Particle rotation around y-axis");
+    case Type::Z:
+        return createUiInfo("Z axis Rotation", "Particle rotation around z-axis");
+    case Type::Euler:
+        return createUiInfo("Euler Rotation",
+                            "Sequence of three rotations following Euler angles; notation z-x'-z'");
+    }
+    ASSERT(false);
+}
+
+RotationItemCatalog::Type RotationItemCatalog::type(RotationItem* item)
+{
+    if (!item)
+        return Type::None;
+
+    if (dynamic_cast<XRotationItem*>(item))
+        return Type::X;
+    if (dynamic_cast<YRotationItem*>(item))
+        return Type::Y;
+    if (dynamic_cast<ZRotationItem*>(item))
+        return Type::Z;
+    if (dynamic_cast<EulerRotationItem*>(item))
+        return Type::Euler;
+
+    ASSERT(false);
+}
diff --git a/GUI/Model/Sample/RotationItemCatalog.h b/GUI/Model/Sample/RotationItemCatalog.h
new file mode 100644
index 00000000000..7ce6022f2ca
--- /dev/null
+++ b/GUI/Model/Sample/RotationItemCatalog.h
@@ -0,0 +1,60 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Model/Sample/RotationItemCatalog.h
+//! @brief     Defines class RotationItemCatalog
+//!
+//! @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)
+//
+//  ************************************************************************************************
+
+#ifndef BORNAGAIN_GUI_MODEL_SAMPLE_ROTATIONITEMCATALOG_H
+#define BORNAGAIN_GUI_MODEL_SAMPLE_ROTATIONITEMCATALOG_H
+
+#include <QString>
+
+class RotationItem;
+
+class RotationItemCatalog {
+public:
+    using CatalogedType = RotationItem;
+
+    // Do not change the numbering! It is serialized!
+    enum class Type : uint8_t {
+        None = 0,
+        X = 1,
+        Y = 2,
+        Z = 3,
+        Euler = 4,
+    };
+
+    struct UiInfo {
+        QString menuEntry;
+        QString description;
+        QString iconPath;
+    };
+
+
+    //! Creates the item of the given type.
+    //!
+    //! If type is "None", a nullptr is returned.
+    static RotationItem* create(Type type);
+
+    //! Available types of interference items.
+    //!
+    //! Contains also type "None".
+    //! This list is sorted as expected in the UI (e.g. in combo box)
+    static QVector<Type> types();
+
+    //! UiInfo on the given type.
+    static UiInfo uiInfo(Type t);
+
+    //! Returns the enum type of the given item.
+    static Type type(RotationItem* item);
+};
+
+#endif // BORNAGAIN_GUI_MODEL_SAMPLE_ROTATIONITEMCATALOG_H
diff --git a/GUI/Model/Sample/RotationItems.cpp b/GUI/Model/Sample/RotationItems.cpp
new file mode 100644
index 00000000000..d2aa23d85c5
--- /dev/null
+++ b/GUI/Model/Sample/RotationItems.cpp
@@ -0,0 +1,110 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Model/Sample/RotationItems.cpp
+//! @brief     Implements class RotationItems
+//!
+//! @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/Model/Sample/RotationItems.h"
+#include "Base/Const/Units.h"
+#include "Base/Vector/RotMatrix.h"
+#include "Sample/Scattering/Rotations.h"
+
+using namespace Units;
+
+// ----------------------------------------------------------------------------
+
+RotationItem::RotationItem() {}
+
+RotMatrix RotationItem::rotation() const
+{
+    auto p = createRotation();
+    return (p != nullptr) ? p->rotMatrix() : RotMatrix();
+}
+
+// ----------------------------------------------------------------------------
+
+XRotationItem::XRotationItem()
+{
+    m_angle.init("Angle", "Rotation angle around x-axis", 0.0, Unit::degree, "angle");
+}
+
+unique_ptr<IRotation> XRotationItem::createRotation() const
+{
+    return std::make_unique<RotationX>(deg2rad(angle()));
+}
+
+DoubleDescriptor XRotationItem::angle() const
+{
+    return m_angle;
+}
+
+// ----------------------------------------------------------------------------
+
+YRotationItem::YRotationItem()
+{
+    m_angle.init("Angle", "Rotation angle around y-axis", 0.0, Unit::degree, "angle");
+}
+
+unique_ptr<IRotation> YRotationItem::createRotation() const
+{
+    return std::make_unique<RotationY>(deg2rad(angle()));
+}
+
+DoubleDescriptor YRotationItem::angle() const
+{
+    return m_angle;
+}
+
+// ----------------------------------------------------------------------------
+
+ZRotationItem::ZRotationItem()
+{
+    m_angle.init("Angle", "Rotation angle around z-axis", 0.0, Unit::degree, "angle");
+}
+
+unique_ptr<IRotation> ZRotationItem::createRotation() const
+{
+    return std::make_unique<RotationZ>(deg2rad(angle()));
+}
+
+DoubleDescriptor ZRotationItem::angle() const
+{
+    return m_angle;
+}
+
+// ----------------------------------------------------------------------------
+
+EulerRotationItem::EulerRotationItem()
+{
+    m_alpha.init("Alpha", "First Euler angle in z-x'-z' sequence", 0.0, Unit::degree, "alpha");
+    m_beta.init("Beta", "Second Euler angle in z-x'-z' sequence", 0.0, Unit::degree, "beta");
+    m_gamma.init("Gamma", "Third Euler angle in z-x'-z' sequence", 0.0, Unit::degree, "gamma");
+}
+
+unique_ptr<IRotation> EulerRotationItem::createRotation() const
+{
+    return std::make_unique<RotationEuler>(deg2rad(alpha()), deg2rad(beta()), deg2rad(gamma()));
+}
+
+DoubleDescriptor EulerRotationItem::alpha() const
+{
+    return m_alpha;
+}
+
+DoubleDescriptor EulerRotationItem::beta() const
+{
+    return m_beta;
+}
+
+DoubleDescriptor EulerRotationItem::gamma() const
+{
+    return m_gamma;
+}
diff --git a/GUI/Model/Trafo/RotationItems.h b/GUI/Model/Sample/RotationItems.h
similarity index 65%
rename from GUI/Model/Trafo/RotationItems.h
rename to GUI/Model/Sample/RotationItems.h
index 3ff2fd46361..a0a8072e810 100644
--- a/GUI/Model/Trafo/RotationItems.h
+++ b/GUI/Model/Sample/RotationItems.h
@@ -2,86 +2,78 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/Model/Trafo/RotationItems.h
+//! @file      GUI/Model/Sample/RotationItems.h
 //! @brief     Defines class RotationItems
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @copyright Forschungszentrum Jülich GmbH 2021
 //! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_GUI_MODEL_TRAFO_ROTATIONITEMS_H
-#define BORNAGAIN_GUI_MODEL_TRAFO_ROTATIONITEMS_H
+#ifndef BORNAGAIN_GUI_MODEL_SAMPLE_ROTATIONITEMS_H
+#define BORNAGAIN_GUI_MODEL_SAMPLE_ROTATIONITEMS_H
 
 #include "GUI/Model/Session/SessionItem.h"
+#include "GUI/Model/Types/DoubleProperty.h"
 
 class IRotation;
 class RotMatrix;
-class DoubleDescriptor;
 
 using std::unique_ptr;
 
-class BA_CORE_API_ RotationItem : public SessionItem {
+class RotationItem {
 public:
+    virtual ~RotationItem() = default;
     RotMatrix rotation() const;
 
 protected:
-    explicit RotationItem(const QString& name);
+    RotationItem();
     virtual unique_ptr<IRotation> createRotation() const = 0;
 };
 
 class XRotationItem : public RotationItem {
-private:
-    static constexpr auto P_ANGLE{"Angle"};
-
 public:
-    static constexpr auto M_TYPE{"XRotation"};
     XRotationItem();
 
     DoubleDescriptor angle() const;
 
 protected:
     unique_ptr<IRotation> createRotation() const override;
-};
 
-class YRotationItem : public RotationItem {
 private:
-    static constexpr auto P_ANGLE{"Angle"};
+    DoubleProperty m_angle;
+};
 
+class YRotationItem : public RotationItem {
 public:
-    static constexpr auto M_TYPE{"YRotation"};
     YRotationItem();
 
     DoubleDescriptor angle() const;
 
 protected:
     unique_ptr<IRotation> createRotation() const override;
-};
 
-class ZRotationItem : public RotationItem {
 private:
-    static constexpr auto P_ANGLE{"Angle"};
+    DoubleProperty m_angle;
+};
 
+class ZRotationItem : public RotationItem {
 public:
-    static constexpr auto M_TYPE{"ZRotation"};
     ZRotationItem();
 
     DoubleDescriptor angle() const;
 
 protected:
     unique_ptr<IRotation> createRotation() const override;
-};
 
-class EulerRotationItem : public RotationItem {
 private:
-    static constexpr auto P_ALPHA{"Alpha"};
-    static constexpr auto P_BETA{"Beta"};
-    static constexpr auto P_GAMMA{"Gamma"};
+    DoubleProperty m_angle;
+};
 
+class EulerRotationItem : public RotationItem {
 public:
-    static constexpr auto M_TYPE{"EulerRotation"};
     EulerRotationItem();
 
     DoubleDescriptor alpha() const;
@@ -90,6 +82,11 @@ public:
 
 protected:
     unique_ptr<IRotation> createRotation() const override;
+
+private:
+    DoubleProperty m_alpha;
+    DoubleProperty m_beta;
+    DoubleProperty m_gamma;
 };
 
-#endif // BORNAGAIN_GUI_MODEL_TRAFO_ROTATIONITEMS_H
+#endif // BORNAGAIN_GUI_MODEL_SAMPLE_ROTATIONITEMS_H
diff --git a/GUI/Model/Trafo/RotationItems.cpp b/GUI/Model/Trafo/RotationItems.cpp
deleted file mode 100644
index 8cd34e1df1e..00000000000
--- a/GUI/Model/Trafo/RotationItems.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit reflection and scattering
-//
-//! @file      GUI/Model/Trafo/RotationItems.cpp
-//! @brief     Implements class RotationItems
-//!
-//! @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/Trafo/RotationItems.h"
-#include "Base/Const/Units.h"
-#include "Base/Vector/RotMatrix.h"
-#include "GUI/Model/Types/DoubleDescriptor.h"
-#include "Sample/Scattering/Rotations.h"
-
-using namespace Units;
-
-// ----------------------------------------------------------------------------
-
-RotationItem::RotationItem(const QString& name) : SessionItem(name) {}
-
-RotMatrix RotationItem::rotation() const
-{
-    auto p = createRotation();
-    return (p != nullptr) ? p->rotMatrix() : RotMatrix();
-}
-
-// ----------------------------------------------------------------------------
-
-XRotationItem::XRotationItem() : RotationItem(M_TYPE)
-{
-    setToolTip("Particle rotation around x-axis");
-    addProperty(P_ANGLE, 0.0)->setToolTip("Rotation angle around x-axis in degrees");
-}
-
-unique_ptr<IRotation> XRotationItem::createRotation() const
-{
-    return std::make_unique<RotationX>(deg2rad(angle()));
-}
-
-DoubleDescriptor XRotationItem::angle() const
-{
-    DoubleDescriptor d(getItem(P_ANGLE), Unit::degree);
-    d.tooltip = "Rotation angle around x-axis"; // tooltip w/o unit
-    return d;
-}
-
-// ----------------------------------------------------------------------------
-
-YRotationItem::YRotationItem() : RotationItem(M_TYPE)
-{
-    setToolTip("Particle rotation around y-axis");
-    addProperty(P_ANGLE, 0.0)->setToolTip("Rotation angle around y-axis in degrees");
-}
-
-unique_ptr<IRotation> YRotationItem::createRotation() const
-{
-    return std::make_unique<RotationY>(deg2rad(angle()));
-}
-
-DoubleDescriptor YRotationItem::angle() const
-{
-    DoubleDescriptor d(getItem(P_ANGLE), Unit::degree);
-    d.tooltip = "Rotation angle around y-axis"; // tooltip w/o unit
-    return d;
-}
-
-// ----------------------------------------------------------------------------
-
-ZRotationItem::ZRotationItem() : RotationItem(M_TYPE)
-{
-    setToolTip("Particle rotation around z-axis");
-    addProperty(P_ANGLE, 0.0)->setToolTip("Rotation angle around z-axis in degrees");
-}
-
-unique_ptr<IRotation> ZRotationItem::createRotation() const
-{
-    return std::make_unique<RotationZ>(deg2rad(angle()));
-}
-
-DoubleDescriptor ZRotationItem::angle() const
-{
-    DoubleDescriptor d(getItem(P_ANGLE), Unit::degree);
-    d.tooltip = "Rotation angle around z-axis"; // tooltip w/o unit
-    return d;
-}
-
-// ----------------------------------------------------------------------------
-
-EulerRotationItem::EulerRotationItem() : RotationItem(M_TYPE)
-{
-    setToolTip("Sequence of three rotations following Euler angles \n"
-               "notation z-x'-z'");
-    addProperty(P_ALPHA, 0.0)->setToolTip("First Euler angle in z-x'-z' sequence in degrees");
-    addProperty(P_BETA, 0.0)->setToolTip("Second Euler angle in z-x'-z' sequence in degrees");
-    addProperty(P_GAMMA, 0.0)->setToolTip("Third Euler angle in z-x'-z' sequence in degrees");
-}
-
-unique_ptr<IRotation> EulerRotationItem::createRotation() const
-{
-    return std::make_unique<RotationEuler>(deg2rad(alpha()), deg2rad(beta()), deg2rad(gamma()));
-}
-
-DoubleDescriptor EulerRotationItem::alpha() const
-{
-    DoubleDescriptor d(getItem(P_ALPHA), Unit::degree);
-    d.tooltip = "First Euler angle in z-x'-z' sequence"; // tooltip w/o unit
-    return d;
-}
-
-DoubleDescriptor EulerRotationItem::beta() const
-{
-    DoubleDescriptor d(getItem(P_BETA), Unit::degree);
-    d.tooltip = "Second Euler angle in z-x'-z' sequence"; // tooltip w/o unit
-    return d;
-}
-
-DoubleDescriptor EulerRotationItem::gamma() const
-{
-    DoubleDescriptor d(getItem(P_GAMMA), Unit::degree);
-    d.tooltip = "Third Euler angle in z-x'-z' sequence"; // tooltip w/o unit
-    return d;
-}
-- 
GitLab