From 13b0645b1b7f4025fb9bef29476669bb23f9cdb6 Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Mon, 11 Oct 2021 14:19:10 +0200
Subject: [PATCH] use SelectionDescriptor in ItemWithParticles

---
 GUI/Models/ItemWithParticles.cpp  | 51 +++++++++++++++++++++++++++++--
 GUI/Models/ItemWithParticles.h    |  8 +++++
 GUI/Models/TransformationItem.cpp |  5 +++
 GUI/Models/TransformationItem.h   |  1 +
 4 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/GUI/Models/ItemWithParticles.cpp b/GUI/Models/ItemWithParticles.cpp
index 3b9543c97f6..f6e33af1a06 100644
--- a/GUI/Models/ItemWithParticles.cpp
+++ b/GUI/Models/ItemWithParticles.cpp
@@ -60,6 +60,12 @@ void ItemWithParticles::setTransformation(RotationItem* transformation)
     model()->moveItem(transformation, this, -1, T_TRANSFORMATION);
 }
 
+RotationItem* ItemWithParticles::rotationItem() const
+{
+    auto* transformationItem = dynamic_cast<TransformationItem*>(getItem(T_TRANSFORMATION));
+    return transformationItem ? transformationItem->rotationItem() : nullptr;
+}
+
 bool ItemWithParticles::isTransformationTagName(const QString& name)
 {
     return name == T_TRANSFORMATION;
@@ -67,8 +73,49 @@ bool ItemWithParticles::isTransformationTagName(const QString& name)
 
 Transform3D ItemWithParticles::rotation() const
 {
-    const auto item = dynamic_cast<TransformationItem*>(getItem(T_TRANSFORMATION));
-    return item ? item->rotationItem()->rotation() : Transform3D();
+    const auto item = rotationItem();
+    return item ? item->rotation() : Transform3D();
+}
+
+SelectionDescriptor<RotationItem*> ItemWithParticles::rotationMethod()
+{
+    SelectionDescriptor<RotationItem*> d;
+
+    // we need a special filling for this selection descriptor (not just from a GroupItem), since
+    // the rotation is stored in a TransformationItem instance, which can be present or not.
+
+    static QVector<QPair<QString, QString>> map = {{"None", ""},
+                                                   {"X axis Rotation", XRotationItem::M_TYPE},
+                                                   {"Y axis Rotation", YRotationItem::M_TYPE},
+                                                   {"Z axis Rotation", ZRotationItem::M_TYPE},
+                                                   {"Euler Rotation", EulerRotationItem::M_TYPE}};
+
+    d.label = "Rotation";
+
+    for (auto [title, type] : map)
+        d.options << title;
+
+    d.currentItem = [=]() -> RotationItem* { return rotationItem(); };
+
+    d.setCurrentIndex = [=](int current) {
+        if (auto item = getItem(T_TRANSFORMATION))
+            model()->removeItem(item);
+        if (current > 0)
+            createTransformationItem()->setRotationType(map[current].second);
+    };
+
+    d.currentIndex = [=]() {
+        auto item = rotationItem();
+        if (item == nullptr)
+            return 0;
+        for (int i = 1; i < map.size(); i++)
+            if (map[i].second == item->modelType())
+                return i;
+
+        return 0;
+    };
+
+    return d;
 }
 
 ItemWithParticles::ItemWithParticles(const QString& model_type, const QString& abundance_tooltip,
diff --git a/GUI/Models/ItemWithParticles.h b/GUI/Models/ItemWithParticles.h
index 0bb1fcc5760..3ee3a69acbf 100644
--- a/GUI/Models/ItemWithParticles.h
+++ b/GUI/Models/ItemWithParticles.h
@@ -16,6 +16,7 @@
 #define BORNAGAIN_GUI_MODELS_ITEMWITHPARTICLES_H
 
 #include "Base/Vector/Vectors3D.h"
+#include "GUI/Models/SelectionDescriptor.h"
 #include "GUI/Models/SessionGraphicsItem.h"
 
 class RotationItem;
@@ -45,6 +46,9 @@ public:
     //! Returns identity transformation if no rotation is defined at all
     Transform3D rotation() const;
 
+    //! Returns selection descriptor for rotation methods.
+    SelectionDescriptor<RotationItem*> rotationMethod();
+
 protected:
     ItemWithParticles(const QString& model_type, const QString& abundance_tooltip,
                       const QString& position_tooltip);
@@ -53,6 +57,10 @@ protected:
 
 private:
     virtual bool isShellParticle() const;
+
+    //! Convenience method to return a rotation item from the contained transformation item.
+    //! nullptr, if no transformation item defined.
+    RotationItem* rotationItem() const;
 };
 
 #endif // BORNAGAIN_GUI_MODELS_ITEMWITHPARTICLES_H
diff --git a/GUI/Models/TransformationItem.cpp b/GUI/Models/TransformationItem.cpp
index 213abba3896..79ccf7a54b9 100644
--- a/GUI/Models/TransformationItem.cpp
+++ b/GUI/Models/TransformationItem.cpp
@@ -34,3 +34,8 @@ RotationItem* TransformationItem::rotationItem() const
 {
     return dynamic_cast<RotationItem*>(getGroupItem(P_ROT));
 }
+
+void TransformationItem::setRotationType(const QString& modelType)
+{
+    setGroupProperty(P_ROT, modelType);
+}
diff --git a/GUI/Models/TransformationItem.h b/GUI/Models/TransformationItem.h
index 9f088f780d6..77a4746c86e 100644
--- a/GUI/Models/TransformationItem.h
+++ b/GUI/Models/TransformationItem.h
@@ -30,6 +30,7 @@ public:
 
     RotationItem* rotationItem() const;
     template <typename T> T* setRotationType();
+    void setRotationType(const QString& modelType);
 };
 
 
-- 
GitLab