From 95c25c5cc338e3697d07a2ff4eeac9e60e2b98be Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Sun, 12 Dec 2021 09:42:02 +0100
Subject: [PATCH] concretize allowed items for RealSpaceBuilder

---
 GUI/View/Realspace/RealSpaceBuilder.cpp | 18 +++++++++---------
 GUI/View/Realspace/RealSpaceBuilder.h   |  7 ++++++-
 GUI/View/Realspace/RealSpaceCanvas.cpp  | 18 ++++++++++++------
 GUI/View/Realspace/RealSpaceCanvas.h    | 19 +++++++++++++------
 GUI/View/SampleDesigner/SampleView.cpp  | 17 ++++++++++++++++-
 5 files changed, 56 insertions(+), 23 deletions(-)

diff --git a/GUI/View/Realspace/RealSpaceBuilder.cpp b/GUI/View/Realspace/RealSpaceBuilder.cpp
index 08120dd45da..f9b20233e81 100644
--- a/GUI/View/Realspace/RealSpaceBuilder.cpp
+++ b/GUI/View/Realspace/RealSpaceBuilder.cpp
@@ -68,21 +68,21 @@ RealSpaceBuilder::RealSpaceBuilder(const MaterialModel* materialModel)
     m_builderUtils = std::make_unique<RealSpace::BuilderUtils>(materialModel);
 }
 
-void RealSpaceBuilder::populate(RealSpace::Model* model, SampleItem item,
+void RealSpaceBuilder::populate(RealSpace::Model* model, ItemForRealSpace item,
                                 const SceneGeometry& sceneGeometry,
                                 const RealSpace::Camera::Position& cameraPosition) const
 {
     // default value of cameraPosition is in RealSpaceBuilder.h
     model->defCamPos = cameraPosition;
 
-    if (const auto* p = item.get_if<MultiLayerItem*>())
-        populateMultiLayer(model, *p, sceneGeometry);
-    else if (const auto* p = item.get_if<LayerItem*>())
-        populateLayer(model, *p, sceneGeometry);
-    else if (const auto* p = item.get_if<ParticleLayoutItem*>())
-        populateLayout(model, *p, sceneGeometry);
-    else if (const auto* p = item.get_if<ItemWithParticles*>())
-        populateParticleFromParticleItem(model, *p);
+    if (const auto* p = std::get_if<MultiLayerItem*>(&item))
+        populateMultiLayer(model, **p, sceneGeometry);
+    else if (const auto* p = std::get_if<LayerItem*>(&item))
+        populateLayer(model, **p, sceneGeometry);
+    else if (const auto* p = std::get_if<ParticleLayoutItem*>(&item))
+        populateLayout(model, **p, sceneGeometry);
+    else if (const auto* p = std::get_if<ItemWithParticles*>(&item))
+        populateParticleFromParticleItem(model, **p);
 }
 
 void RealSpaceBuilder::populateMultiLayer(GUI::RealSpace::Model* model,
diff --git a/GUI/View/Realspace/RealSpaceBuilder.h b/GUI/View/Realspace/RealSpaceBuilder.h
index 6262aab0e85..2006554c171 100644
--- a/GUI/View/Realspace/RealSpaceBuilder.h
+++ b/GUI/View/Realspace/RealSpaceBuilder.h
@@ -37,9 +37,14 @@ using namespace GUI;
 class RealSpaceBuilder {
 
 public:
+    //! Defines the item types this class can handle
+    using ItemForRealSpace =
+        std::variant<MultiLayerItem*, LayerItem*, ParticleLayoutItem*, ItemWithParticles*>;
+
     RealSpaceBuilder(const MaterialModel* materialModel);
 
-    void populate(RealSpace::Model* model, SampleItem item, const SceneGeometry& sceneGeometry,
+    void populate(RealSpace::Model* model, ItemForRealSpace item,
+                  const SceneGeometry& sceneGeometry,
                   const RealSpace::Camera::Position& cameraPosition =
                       RealSpace::Camera::Position(RealSpace::Vector3D(0, -200, 120), // eye
                                                   RealSpace::Vector3D(0, 0, 0),      // center
diff --git a/GUI/View/Realspace/RealSpaceCanvas.cpp b/GUI/View/Realspace/RealSpaceCanvas.cpp
index 2c2a6439ea5..2af6ed697fc 100644
--- a/GUI/View/Realspace/RealSpaceCanvas.cpp
+++ b/GUI/View/Realspace/RealSpaceCanvas.cpp
@@ -39,14 +39,20 @@ RealSpaceCanvas::RealSpaceCanvas(const MaterialModel* materialModel, QWidget* pa
     setLayout(layout);
 }
 
-void RealSpaceCanvas::setCurrentItem(SampleItem item)
+void RealSpaceCanvas::setCurrentItem(ItemForRealSpace item)
 {
-    m_currentItem = item;
-    updateScene();
-    defaultView(); // Enforces default view and also sets the zoomLevel to default i.e. 0
+    bool isValid = false;
+    std::visit([&](auto&& arg) { isValid = arg != nullptr; }, item);
+
+    if (isValid) {
+        m_currentItem = item;
+        updateScene();
+        defaultView(); // Enforces default view and also sets the zoomLevel to default i.e. 0
+    } else
+        resetScene();
 }
 
-std::optional<SampleItem> RealSpaceCanvas::currentItem() const
+std::optional<RealSpaceCanvas::ItemForRealSpace> RealSpaceCanvas::currentItem() const
 {
     return m_currentItem;
 }
@@ -135,7 +141,7 @@ void RealSpaceCanvas::resetScene()
 {
     m_realSpaceModel.reset();
     m_view->setModel(nullptr);
-    m_currentItem = nullptr;
+    m_currentItem.reset();
 }
 
 void RealSpaceCanvas::defaultView()
diff --git a/GUI/View/Realspace/RealSpaceCanvas.h b/GUI/View/Realspace/RealSpaceCanvas.h
index 5444313ca52..17e718d0327 100644
--- a/GUI/View/Realspace/RealSpaceCanvas.h
+++ b/GUI/View/Realspace/RealSpaceCanvas.h
@@ -15,18 +15,21 @@
 #ifndef BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACECANVAS_H
 #define BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACECANVAS_H
 
-#include "GUI/Model/Sample/SampleItem.h"
 #include <QWidget>
 #include <memory>
 #include <optional>
+#include <variant>
 
 class CautionSign;
 class MaterialModel;
-namespace GUI::RealSpace {
+class MultiLayerItem;
+class LayerItem;
+class ParticleLayoutItem;
+class ItemWithParticles;
 
+namespace GUI::RealSpace {
 class Canvas;
 class Model;
-
 } // namespace GUI::RealSpace
 
 //! Size and thickness information of layers
@@ -41,10 +44,14 @@ class RealSpaceCanvas : public QWidget {
     Q_OBJECT
 
 public:
+    //! Defines the item types which can be the "current item"
+    using ItemForRealSpace =
+        std::variant<MultiLayerItem*, LayerItem*, ParticleLayoutItem*, ItemWithParticles*>;
+
     RealSpaceCanvas(const MaterialModel* materialModel, QWidget* parent = nullptr);
 
-    void setCurrentItem(SampleItem item);
-    std::optional<SampleItem> currentItem() const;
+    void setCurrentItem(ItemForRealSpace item);
+    std::optional<ItemForRealSpace> currentItem() const;
     void defaultView();
     void sideView();
     void topView();
@@ -64,7 +71,7 @@ private:
     std::unique_ptr<GUI::RealSpace::Model> m_realSpaceModel;
     SceneGeometry m_sceneGeometry;
     CautionSign* m_cautionSign;
-    std::optional<SampleItem> m_currentItem;
+    std::optional<ItemForRealSpace> m_currentItem;
     bool m_firstView;
 };
 
diff --git a/GUI/View/SampleDesigner/SampleView.cpp b/GUI/View/SampleDesigner/SampleView.cpp
index cb976451d4e..f23e3279150 100644
--- a/GUI/View/SampleDesigner/SampleView.cpp
+++ b/GUI/View/SampleDesigner/SampleView.cpp
@@ -14,7 +14,10 @@
 
 #include "GUI/View/SampleDesigner/SampleView.h"
 #include "GUI/Model/Project/ProjectDocument.h"
+#include "GUI/Model/Sample/ItemWithParticles.h"
+#include "GUI/Model/Sample/LayerItem.h"
 #include "GUI/Model/Sample/MultiLayerItem.h"
+#include "GUI/Model/Sample/ParticleLayoutItem.h"
 #include "GUI/Model/Sample/SampleModel.h"
 #include "GUI/View/Common/DocksController.h"
 #include "GUI/View/Common/StyledToolBar.h"
@@ -113,8 +116,20 @@ void SampleView::onRequestViewInRealSpace(SessionItem* itemToView)
     if (!itemToView)
         return;
 
+    RealSpaceCanvas::ItemForRealSpace itemForRealSpace;
+    if (auto* p = dynamic_cast<MultiLayerItem*>(itemToView))
+        itemForRealSpace = p;
+    else if (auto* p = dynamic_cast<LayerItem*>(itemToView))
+        itemForRealSpace = p;
+    else if (auto* p = dynamic_cast<ParticleLayoutItem*>(itemToView))
+        itemForRealSpace = p;
+    else if (auto* p = dynamic_cast<ItemWithParticles*>(itemToView))
+        itemForRealSpace = p;
+    else
+        return;
+
     m_docks->setDockVisible(REALSPACEPANEL);
-    m_realSpacePanel->canvas()->setCurrentItem(itemToView);
+    m_realSpacePanel->canvas()->setCurrentItem(itemForRealSpace);
 }
 
 void SampleView::onAboutToRemoveItem(SampleItem item)
-- 
GitLab