From 0fe174eeba590fbbda5825c95f4825c3cee94898 Mon Sep 17 00:00:00 2001
From: Tobias Knopff <t.knopff@fz-juelich.de>
Date: Wed, 7 Jul 2021 12:31:37 +0200
Subject: [PATCH] Make ItemWithParticles::T_TRANSFORMATION private

---
 GUI/Models/GUIDomainSampleVisitor.cpp         | 24 ++++++------
 GUI/Models/ItemWithParticles.cpp              | 25 ++++++++++++-
 GUI/Models/ItemWithParticles.h                | 11 +++++-
 GUI/Models/ParticleItem.cpp                   |  2 +-
 GUI/Views/SampleDesigner/DesignerScene.cpp    | 37 +++++++++++--------
 GUI/Views/SampleDesigner/MesoCrystalView.cpp  |  2 +-
 .../ParticleCompositionView.cpp               |  2 +-
 Tests/UnitTests/GUI/TestParticleItem.cpp      |  2 +-
 8 files changed, 70 insertions(+), 35 deletions(-)

diff --git a/GUI/Models/GUIDomainSampleVisitor.cpp b/GUI/Models/GUIDomainSampleVisitor.cpp
index 32e5ceda187..a496ed0c213 100644
--- a/GUI/Models/GUIDomainSampleVisitor.cpp
+++ b/GUI/Models/GUIDomainSampleVisitor.cpp
@@ -499,11 +499,11 @@ void GUIDomainSampleVisitor::visit(const InterferenceFunctionRadialParaCrystal*
 
 void GUIDomainSampleVisitor::visit(const RotationX* sample)
 {
-    SessionItem* parent = m_levelToParentItem[depth() - 1];
+    ItemWithParticles* parent =
+        polymorphic_cast<ItemWithParticles*>(m_levelToParentItem[depth() - 1]);
     ASSERT(parent);
 
-    auto transformation_item =
-        m_sampleModel->insertItem<TransformationItem>(parent, -1, ParticleItem::T_TRANSFORMATION);
+    TransformationItem* transformation_item = parent->createTransformationItem();
     XRotationItem* rotationItem =
         transformation_item->setGroupPropertyType<XRotationItem>(TransformationItem::P_ROT);
     rotationItem->setAngleValue(Units::rad2deg(sample->getAngle()));
@@ -512,11 +512,11 @@ void GUIDomainSampleVisitor::visit(const RotationX* sample)
 
 void GUIDomainSampleVisitor::visit(const RotationY* sample)
 {
-    SessionItem* parent = m_levelToParentItem[depth() - 1];
+    ItemWithParticles* parent =
+        polymorphic_cast<ItemWithParticles*>(m_levelToParentItem[depth() - 1]);
     ASSERT(parent);
 
-    auto transformation_item =
-        m_sampleModel->insertItem<TransformationItem>(parent, -1, ParticleItem::T_TRANSFORMATION);
+    TransformationItem* transformation_item = parent->createTransformationItem();
     YRotationItem* rotationItem =
         transformation_item->setGroupPropertyType<YRotationItem>(TransformationItem::P_ROT);
     rotationItem->setAngleValue(Units::rad2deg(sample->getAngle()));
@@ -525,11 +525,11 @@ void GUIDomainSampleVisitor::visit(const RotationY* sample)
 
 void GUIDomainSampleVisitor::visit(const RotationZ* sample)
 {
-    SessionItem* parent = m_levelToParentItem[depth() - 1];
+    ItemWithParticles* parent =
+        polymorphic_cast<ItemWithParticles*>(m_levelToParentItem[depth() - 1]);
     ASSERT(parent);
 
-    auto transformation_item =
-        m_sampleModel->insertItem<TransformationItem>(parent, -1, ParticleItem::T_TRANSFORMATION);
+    TransformationItem* transformation_item = parent->createTransformationItem();
     ZRotationItem* rotationItem =
         transformation_item->setGroupPropertyType<ZRotationItem>(TransformationItem::P_ROT);
     rotationItem->setAngleValue(Units::rad2deg(sample->getAngle()));
@@ -538,11 +538,11 @@ void GUIDomainSampleVisitor::visit(const RotationZ* sample)
 
 void GUIDomainSampleVisitor::visit(const RotationEuler* sample)
 {
-    SessionItem* parent = m_levelToParentItem[depth() - 1];
+    ItemWithParticles* parent =
+        polymorphic_cast<ItemWithParticles*>(m_levelToParentItem[depth() - 1]);
     ASSERT(parent);
 
-    auto transformation_item =
-        m_sampleModel->insertItem<TransformationItem>(parent, -1, ParticleItem::T_TRANSFORMATION);
+    TransformationItem* transformation_item = parent->createTransformationItem();
     EulerRotationItem* rotationItem =
         transformation_item->setGroupPropertyType<EulerRotationItem>(TransformationItem::P_ROT);
     rotationItem->setAlphaValue(Units::rad2deg(sample->getAlpha()));
diff --git a/GUI/Models/ItemWithParticles.cpp b/GUI/Models/ItemWithParticles.cpp
index 07bedd7ba54..342495b0091 100644
--- a/GUI/Models/ItemWithParticles.cpp
+++ b/GUI/Models/ItemWithParticles.cpp
@@ -13,8 +13,11 @@
 //  ************************************************************************************************
 
 #include "GUI/Models/ItemWithParticles.h"
-#include "GUI/Models/VectorItem.h"
+#include "GUI/Models/RotationItems.h"
 #include "GUI/Models/SessionItemUtils.h"
+#include "GUI/Models/SessionModel.h"
+#include "GUI/Models/TransformationItem.h"
+#include "GUI/Models/VectorItem.h"
 
 const QString ItemWithParticles::P_ABUNDANCE = "Abundance";
 const QString ItemWithParticles::P_POSITION = "Position Offset";
@@ -50,6 +53,21 @@ VectorItem* ItemWithParticles::positionItem() const
     return item<VectorItem>(P_POSITION);
 }
 
+TransformationItem* ItemWithParticles::createTransformationItem()
+{
+    return model()->insertItem<TransformationItem>(this, -1, T_TRANSFORMATION);
+}
+
+void ItemWithParticles::setTransformation(RotationItem* transformation)
+{
+    model()->moveItem(transformation, this, -1, T_TRANSFORMATION);
+}
+
+bool ItemWithParticles::isTransformationTagName(const QString& name)
+{
+    return name == T_TRANSFORMATION;
+}
+
 ItemWithParticles::ItemWithParticles(const QString& model_type, const QString& abundance_tooltip,
                                      const QString& position_tooltip)
     : SessionGraphicsItem(model_type)
@@ -79,6 +97,11 @@ ItemWithParticles::ItemWithParticles(const QString& model_type, const QString& a
     });
 }
 
+void ItemWithParticles::setDefaultTagTransformation()
+{
+    setDefaultTag(T_TRANSFORMATION);
+}
+
 bool ItemWithParticles::isShellParticle() const
 {
     return false;
diff --git a/GUI/Models/ItemWithParticles.h b/GUI/Models/ItemWithParticles.h
index 520aacee7e1..1c7f4c9f969 100644
--- a/GUI/Models/ItemWithParticles.h
+++ b/GUI/Models/ItemWithParticles.h
@@ -19,16 +19,17 @@
 #include "Base/Vector/Vectors3D.h"
 #include "GUI/Models/SessionGraphicsItem.h"
 
+class RotationItem;
+class TransformationItem;
 class VectorItem;
 
 class BA_CORE_API_ ItemWithParticles : public virtual SessionGraphicsItem {
 private:
     static const QString P_ABUNDANCE;
     static const QString P_POSITION;
-
-public:
     static const QString T_TRANSFORMATION;
 
+public:
     double abundance() const;
     void setAbundance(double abundance);
     SessionItem* abundanceItem() const;
@@ -37,10 +38,16 @@ public:
     void setPosition(const kvector_t& position);
     VectorItem* positionItem() const;    
 
+    TransformationItem* createTransformationItem();
+    void setTransformation(RotationItem* transformation);
+    static bool isTransformationTagName(const QString& name);
+
 protected:
     ItemWithParticles(const QString& model_type, const QString& abundance_tooltip,
                       const QString& position_tooltip);
 
+    void setDefaultTagTransformation();
+
 private:
     virtual bool isShellParticle() const;
 };
diff --git a/GUI/Models/ParticleItem.cpp b/GUI/Models/ParticleItem.cpp
index 357cfc68284..24fa01336ae 100644
--- a/GUI/Models/ParticleItem.cpp
+++ b/GUI/Models/ParticleItem.cpp
@@ -42,7 +42,7 @@ ParticleItem::ParticleItem()
 {
     addGroupProperty(P_FORM_FACTOR, "Form Factor");
 
-    setDefaultTag(T_TRANSFORMATION);
+    setDefaultTagTransformation();
 }
 
 std::unique_ptr<Particle> ParticleItem::createParticle() const
diff --git a/GUI/Views/SampleDesigner/DesignerScene.cpp b/GUI/Views/SampleDesigner/DesignerScene.cpp
index 8a9623b7da1..105f376c98c 100644
--- a/GUI/Views/SampleDesigner/DesignerScene.cpp
+++ b/GUI/Views/SampleDesigner/DesignerScene.cpp
@@ -21,6 +21,7 @@
 #include "GUI/Models/ParticleCoreShellItem.h"
 #include "GUI/Models/ParticleItem.h"
 #include "GUI/Models/ParticleLayoutItem.h"
+#include "GUI/Models/RotationItems.h"
 #include "GUI/Models/SampleModel.h"
 #include "GUI/Views/CommonWidgets/DesignerHelper.h"
 #include "GUI/Views/SampleDesigner/DesignerMimeData.h"
@@ -34,6 +35,10 @@
 #include <QItemSelection>
 #include <QPainter>
 
+#include <boost/polymorphic_cast.hpp>
+using boost::polymorphic_cast;
+using boost::polymorphic_downcast;
+
 DesignerScene::DesignerScene(QObject* parent)
     : QGraphicsScene(parent)
     , m_sampleModel(0)
@@ -343,33 +348,33 @@ void DesignerScene::drawForeground(QPainter* painter, const QRectF& /* rect */)
 }
 
 //! propagates connection established by NodeEditor to the model
-void DesignerScene::onEstablishedConnection(NodeEditorConnection* connection)
+void DesignerScene::onEstablishedConnection(NodeEditorConnection* connection_ptr)
 {
+    // delete after use of just created connection because it will be recreated from the model
+    std::unique_ptr<NodeEditorConnection> connection(connection_ptr);
+
     ConnectableView* parentView = connection->getParentView();
-    ConnectableView* childView = connection->getChildView();
+    SessionItem* childItem = connection->getChildView()->getItem();
+    SessionItem* parentItem = parentView->getItem();
 
     QString tag;
-    if (connection->getParentView()->getItem()->modelType() == "ParticleLayout") {
+    if (parentItem->modelType() == "ParticleLayout") {
         if (connection->inputPort()->getPortType() == NodeEditorPort::INTERFERENCE)
             tag = ParticleLayoutItem::T_INTERFERENCE;
-    } else if (connection->getParentView()->getItem()->modelType() == "ParticleCoreShell") {
+    } else if ((parentItem->modelType() == "ParticleCoreShell"
+                || parentItem->modelType() == "ParticleComposition"
+                || parentItem->modelType() == "MesoCrystal")
+               && connection->inputPort()->getPortType() == NodeEditorPort::TRANSFORMATION) {
+        polymorphic_cast<ItemWithParticles*>(parentItem)->setTransformation
+            (polymorphic_downcast<RotationItem*>(childItem));
+        return;
+    } else if (parentItem->modelType() == "ParticleCoreShell") {
         if (parentView->getInputPortIndex(connection->inputPort()) == 0)
             tag = ParticleCoreShellItem::T_CORE;
         else if (parentView->getInputPortIndex(connection->inputPort()) == 1)
             tag = ParticleCoreShellItem::T_SHELL;
-        else if (connection->inputPort()->getPortType() == NodeEditorPort::TRANSFORMATION)
-            tag = ParticleItem::T_TRANSFORMATION;
-
-    } else if (connection->getParentView()->getItem()->modelType() == "ParticleComposition") {
-        if (connection->inputPort()->getPortType() == NodeEditorPort::TRANSFORMATION)
-            tag = ParticleItem::T_TRANSFORMATION;
-    } else if (connection->getParentView()->getItem()->modelType() == "MesoCrystal") {
-        if (connection->inputPort()->getPortType() == NodeEditorPort::TRANSFORMATION)
-            tag = ParticleItem::T_TRANSFORMATION;
     }
-    delete connection; // deleting just created connection because it will be recreated from the
-                       // model
-    m_sampleModel->moveItem(childView->getItem(), parentView->getItem(), -1, tag);
+    m_sampleModel->moveItem(childItem, parentItem, -1, tag);
 }
 
 //! propagates break of connection between views on scene to the model
diff --git a/GUI/Views/SampleDesigner/MesoCrystalView.cpp b/GUI/Views/SampleDesigner/MesoCrystalView.cpp
index dc682442d47..49121c6a07c 100644
--- a/GUI/Views/SampleDesigner/MesoCrystalView.cpp
+++ b/GUI/Views/SampleDesigner/MesoCrystalView.cpp
@@ -35,7 +35,7 @@ MesoCrystalView::MesoCrystalView(QGraphicsItem* parent) : ConnectableView(parent
 void MesoCrystalView::addView(IView* childView, int /* row */)
 {
     int index = 0;
-    if (this->getItem()->tagFromItem(childView->getItem()) == ParticleItem::T_TRANSFORMATION)
+    if (ItemWithParticles::isTransformationTagName(getItem()->tagFromItem(childView->getItem())))
         index = 1;
     connectInputPort(dynamic_cast<ConnectableView*>(childView), index);
 }
diff --git a/GUI/Views/SampleDesigner/ParticleCompositionView.cpp b/GUI/Views/SampleDesigner/ParticleCompositionView.cpp
index 653f20d461d..9ea3dcd5914 100644
--- a/GUI/Views/SampleDesigner/ParticleCompositionView.cpp
+++ b/GUI/Views/SampleDesigner/ParticleCompositionView.cpp
@@ -34,7 +34,7 @@ ParticleCompositionView::ParticleCompositionView(QGraphicsItem* parent) : Connec
 void ParticleCompositionView::addView(IView* childView, int /* row */)
 {
     int index = 0;
-    if (this->getItem()->tagFromItem(childView->getItem()) == ParticleItem::T_TRANSFORMATION)
+    if (ItemWithParticles::isTransformationTagName(getItem()->tagFromItem(childView->getItem())))
         index = 1;
     connectInputPort(dynamic_cast<ConnectableView*>(childView), index);
 }
diff --git a/Tests/UnitTests/GUI/TestParticleItem.cpp b/Tests/UnitTests/GUI/TestParticleItem.cpp
index c0cd023c197..9bf59cc3ec6 100644
--- a/Tests/UnitTests/GUI/TestParticleItem.cpp
+++ b/Tests/UnitTests/GUI/TestParticleItem.cpp
@@ -19,7 +19,7 @@ TEST_F(TestParticleItem, test_InitialState)
     EXPECT_EQ(item->displayName(), item->itemName());
     // xpos, ypos, P_FORM_FACTOR, P_MATERIAL, P_ABUNDANCE, P_POSITION
     EXPECT_EQ(item->children().size(), 6);
-    EXPECT_EQ(item->defaultTag(), ParticleItem::T_TRANSFORMATION);
+    EXPECT_TRUE(ItemWithParticles::isTransformationTagName(item->defaultTag()));
 
     GroupItem* group = item->formFactorItem();
     EXPECT_EQ(group->displayName(), "Form Factor");
-- 
GitLab