changeset 90:64e60018943f wasm

fix and observer refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 29 May 2017 11:04:18 +0200
parents f244018a4e4b
children 81f73efd81a1
files Applications/Samples/SingleFrameApplication.h Framework/Layers/ILayerSource.h Framework/Layers/LayerSourceBase.cpp Framework/Layers/LayerSourceBase.h Framework/Layers/OrthancFrameLayerSource.cpp Framework/Toolbox/ObserversRegistry.h Framework/Volumes/ISlicedVolume.h Framework/Volumes/SlicedVolumeBase.cpp Framework/Volumes/SlicedVolumeBase.h Framework/Widgets/LayerWidget.cpp Framework/Widgets/LayerWidget.h
diffstat 11 files changed, 153 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/SingleFrameApplication.h	Fri May 26 18:27:59 2017 +0200
+++ b/Applications/Samples/SingleFrameApplication.h	Mon May 29 11:04:18 2017 +0200
@@ -94,6 +94,14 @@
 
       virtual void NotifyGeometryReady(const ILayerSource& source)
       {
+        const OrthancFrameLayerSource& frame =
+          dynamic_cast<const OrthancFrameLayerSource&>(source);
+
+        if (frame.GetSliceCount() > 0)
+        {
+          widget_->SetSlice(frame.GetSlice(0).GetGeometry());
+          widget_->SetDefaultView();
+        }
       }
       
       virtual void NotifyGeometryError(const ILayerSource& source)
@@ -109,7 +117,7 @@
       {
       }
  
-      virtual void NotifyLayerReady(ILayerRenderer *layer,
+      virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer,
                                     const ILayerSource& source,
                                     const Slice& slice)
       {
@@ -162,9 +170,10 @@
 
         std::auto_ptr<LayerWidget> widget(new LayerWidget);
 
-#if 1
+#if 0
         std::auto_ptr<OrthancFrameLayerSource> layer
           (new OrthancFrameLayerSource(context.GetWebService(), instance, frame));
+        layer->Register(*this);
         widget->AddLayer(layer.release());
 
         if (parameters["smooth"].as<bool>())
@@ -178,6 +187,7 @@
         std::auto_ptr<OrthancFrameLayerSource> ct;
         ct.reset(new OrthancFrameLayerSource(context.GetWebService(), "c804a1a2-142545c9-33b32fe2-3df4cec0-a2bea6d6", 0));
         //ct.reset(new OrthancFrameLayerSource(context.GetWebService(), "4bd4304f-47478948-71b24af2-51f4f1bc-275b6c1b", 0));  // BAD SLICE
+        ct->Register(*this);
         widget->AddLayer(ct.release());
 
         std::auto_ptr<OrthancFrameLayerSource> pet;
--- a/Framework/Layers/ILayerSource.h	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Layers/ILayerSource.h	Mon May 29 11:04:18 2017 +0200
@@ -36,6 +36,12 @@
       {
       }
 
+      // Triggered as soon as the source has enough information to
+      // answer to "GetExtent()"
+      virtual void NotifyGeometryReady(const ILayerSource& source) = 0;
+      
+      virtual void NotifyGeometryError(const ILayerSource& source) = 0;
+      
       // Triggered if the content of several slices in the source
       // volume has changed
       virtual void NotifyContentChange(const ILayerSource& source) = 0;
@@ -48,7 +54,7 @@
       // The layer must be deleted by the observer. "layer" will never
       // be "NULL", otherwise "NotifyLayerError()" would have been
       // called.
-      virtual void NotifyLayerReady(ILayerRenderer *layer,
+      virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer,
                                     const ILayerSource& source,
                                     const Slice& slice) = 0;
 
@@ -60,7 +66,7 @@
     {
     }
 
-    virtual void SetObserver(IObserver& observer) = 0;
+    virtual void Register(IObserver& observer) = 0;
 
     virtual bool GetExtent(double& x1,
                            double& y1,
--- a/Framework/Layers/LayerSourceBase.cpp	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Layers/LayerSourceBase.cpp	Mon May 29 11:04:18 2017 +0200
@@ -25,56 +25,69 @@
 
 namespace OrthancStone
 {
+  namespace
+  {
+    class LayerReadyFunctor : public boost::noncopyable
+    {
+    private:
+      std::auto_ptr<ILayerRenderer>  layer_;
+      const Slice&                   slice_;
+      
+    public:
+      LayerReadyFunctor(ILayerRenderer* layer,
+                        const Slice& slice) :
+        layer_(layer),
+        slice_(slice)
+      {
+      }
+
+      void operator() (ILayerSource::IObserver& observer,
+                       const ILayerSource& source)
+      {
+        observer.NotifyLayerReady(layer_, source, slice_);
+      }
+    };
+  }
+
+  void LayerSourceBase::NotifyGeometryReady()
+  {
+    observers_.Apply(*this, &IObserver::NotifyGeometryReady);
+  }
+    
+  void LayerSourceBase::NotifyGeometryError()
+  {
+    observers_.Apply(*this, &IObserver::NotifyGeometryError);
+  }  
+    
   void LayerSourceBase::NotifyContentChange()
   {
-    if (observer_ != NULL)
-    {
-      observer_->NotifyContentChange(*this);
-    }
+    observers_.Apply(*this, &IObserver::NotifyContentChange);
   }
 
   void LayerSourceBase::NotifySliceChange(const Slice& slice)
   {
-    if (observer_ != NULL)
-    {
-      observer_->NotifySliceChange(*this, slice);
-    }
+    observers_.Apply(*this, &IObserver::NotifySliceChange, slice);
   }
 
   void LayerSourceBase::NotifyLayerReady(ILayerRenderer* layer,
                                          const Slice& slice)
   {
-    std::auto_ptr<ILayerRenderer> tmp(layer);
-    
     if (layer == NULL)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
-    
-    if (observer_ != NULL)
-    {
-      observer_->NotifyLayerReady(tmp.release(), *this, slice);
-    }
+
+    LayerReadyFunctor functor(layer, slice);
+    observers_.Notify(this, functor);
   }
 
   void LayerSourceBase::NotifyLayerError(const SliceGeometry& slice)
   {
-    if (observer_ != NULL)
-    {
-      observer_->NotifyLayerError(*this, slice);
-    }
+    observers_.Apply(*this, &IObserver::NotifyLayerError, slice);
   }
 
-  void LayerSourceBase::SetObserver(IObserver& observer)
+  void LayerSourceBase::Register(IObserver& observer)
   {
-    if (observer_ == NULL)
-    {
-      observer_ = &observer;
-    }
-    else
-    {
-      // Cannot add more than one observer
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
+    observers_.Register(observer);
   }
 }
--- a/Framework/Layers/LayerSourceBase.h	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Layers/LayerSourceBase.h	Mon May 29 11:04:18 2017 +0200
@@ -22,36 +22,32 @@
 #pragma once
 
 #include "ILayerSource.h"
+#include "../Toolbox/ObserversRegistry.h"
 
 namespace OrthancStone
 {
   class LayerSourceBase : public ILayerSource
   {
   private:
-    IObserver*  observer_;
+    typedef ObserversRegistry<ILayerSource, IObserver>  Observers;
+
+    Observers  observers_;
 
   protected:
-    IObserver* GetObserver() const
-    {
-      return observer_;  // TODO REMOVE THIS, FOR TEST
-    }
+    void NotifyGeometryReady();
+    
+    void NotifyGeometryError();
 
     void NotifyContentChange();
 
     void NotifySliceChange(const Slice& slice);
 
-    // Takes ownership of "layer" (that cannot be "NULL")
     void NotifyLayerReady(ILayerRenderer* layer,
                           const Slice& slice);
     
     void NotifyLayerError(const SliceGeometry& slice);
 
   public:
-    LayerSourceBase() :
-      observer_(NULL)
-    {
-    }
-    
-    virtual void SetObserver(IObserver& observer);
+    virtual void Register(IObserver& observer);
   };
 }
--- a/Framework/Layers/OrthancFrameLayerSource.cpp	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Layers/OrthancFrameLayerSource.cpp	Mon May 29 11:04:18 2017 +0200
@@ -37,7 +37,6 @@
 {
   void OrthancFrameLayerSource::NotifyGeometryReady(const OrthancSlicesLoader& loader)
   {
-#if 0
     if (loader.GetSliceCount() > 0)
     {
       // Make sure all the slices are parallel. TODO Alleviate this constraint
@@ -53,20 +52,11 @@
     }
 
     LayerSourceBase::NotifyGeometryReady();
-#endif
-
-    // TODO REMOVE THIS
-    /*if (GetObserver() != NULL)
-    {
-      dynamic_cast<LayerWidget*>(GetObserver())->SetSlice(loader.GetSlice(0).GetGeometry());
-      }*/
   }
 
   void OrthancFrameLayerSource::NotifyGeometryError(const OrthancSlicesLoader& loader)
   {
-#if 0
     LayerSourceBase::NotifyGeometryError();
-#endif
   }
 
   void OrthancFrameLayerSource::NotifySliceImageReady(const OrthancSlicesLoader& loader,
--- a/Framework/Toolbox/ObserversRegistry.h	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Toolbox/ObserversRegistry.h	Mon May 29 11:04:18 2017 +0200
@@ -92,5 +92,41 @@
     {
       return observers_.empty();
     }
+
+    void Apply(const Source& source,
+               void (Observer::*method) (const Source&))
+    {
+      for (typename Observers::const_iterator it = observers_.begin();
+           it != observers_.end(); ++it)
+      {
+        ((*it)->*method) (source);
+      }
+    }
+
+    template <typename Argument0>
+    void Apply(const Source& source,
+               void (Observer::*method) (const Source&, const Argument0&),
+               const Argument0& argument0)
+    {
+      for (typename Observers::const_iterator it = observers_.begin();
+           it != observers_.end(); ++it)
+      {
+        ((*it)->*method) (source, argument0);
+      }
+    }
+
+    template <typename Argument0,
+              typename Argument1>
+    void Apply(const Source& source,
+               void (Observer::*method) (const Source&, const Argument0&, const Argument1&),
+               const Argument0& argument0,
+               const Argument1& argument1)
+    {
+      for (typename Observers::const_iterator it = observers_.begin();
+           it != observers_.end(); ++it)
+      {
+        ((*it)->*method) (source, argument0, argument1);
+      }
+    }
   };
 }
--- a/Framework/Volumes/ISlicedVolume.h	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Volumes/ISlicedVolume.h	Mon May 29 11:04:18 2017 +0200
@@ -46,7 +46,7 @@
       // Triggered if the content of some individual slice in the
       // source volume has changed
       virtual void NotifySliceChange(const ISlicedVolume& volume,
-                                     size_t sliceIndex,
+                                     const size_t& sliceIndex,
                                      const Slice& slice) = 0;
     };
     
--- a/Framework/Volumes/SlicedVolumeBase.cpp	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Volumes/SlicedVolumeBase.cpp	Mon May 29 11:04:18 2017 +0200
@@ -23,77 +23,24 @@
 
 namespace OrthancStone
 {
-  namespace
-  {
-    struct GeometryReadyFunctor
-    {
-      void operator() (ISlicedVolume::IObserver& observer,
-                       const ISlicedVolume& source)
-      {
-        observer.NotifyGeometryReady(source);
-      }
-    };
-
-    struct GeometryErrorFunctor
-    {
-      void operator() (ISlicedVolume::IObserver& observer,
-                       const ISlicedVolume& source)
-      {
-        observer.NotifyGeometryError(source);
-      }
-    };
-
-    struct ContentChangeFunctor
-    {
-      void operator() (ISlicedVolume::IObserver& observer,
-                       const ISlicedVolume& source)
-      {
-        observer.NotifyContentChange(source);
-      }
-    };
-
-    struct SliceChangeFunctor
-    {
-      size_t sliceIndex_;
-      const Slice& slice_;
-
-      SliceChangeFunctor(size_t sliceIndex,
-                         const Slice& slice) :
-        sliceIndex_(sliceIndex),
-        slice_(slice)
-      {
-      }
-
-      void operator() (ISlicedVolume::IObserver& observer,
-                       const ISlicedVolume& source)
-      {
-        observer.NotifySliceChange(source, sliceIndex_, slice_);
-      }
-    };
-  }
-
   void SlicedVolumeBase::NotifyGeometryReady()
   {
-    GeometryReadyFunctor functor;
-    observers_.Notify(this, functor);
+    observers_.Apply(*this, &IObserver::NotifyGeometryReady);
   }
       
   void SlicedVolumeBase::NotifyGeometryError()
   {
-    GeometryErrorFunctor functor;
-    observers_.Notify(this, functor);
+    observers_.Apply(*this, &IObserver::NotifyGeometryError);
   }
     
   void SlicedVolumeBase::NotifyContentChange()
   {
-    ContentChangeFunctor functor;
-    observers_.Notify(this, functor);
+    observers_.Apply(*this, &IObserver::NotifyContentChange);
   }
 
-  void SlicedVolumeBase::NotifySliceChange(size_t sliceIndex,
+  void SlicedVolumeBase::NotifySliceChange(const size_t& sliceIndex,
                                            const Slice& slice)
   {
-    SliceChangeFunctor functor(sliceIndex, slice);
-    observers_.Notify(this, functor);
+    observers_.Apply(*this, &IObserver::NotifySliceChange, sliceIndex, slice);
   }
 }
--- a/Framework/Volumes/SlicedVolumeBase.h	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Volumes/SlicedVolumeBase.h	Mon May 29 11:04:18 2017 +0200
@@ -29,7 +29,7 @@
   class SlicedVolumeBase : public ISlicedVolume
   {
   private:
-    typedef ObserversRegistry<SlicedVolumeBase, IObserver>  Observers;
+    typedef ObserversRegistry<ISlicedVolume, IObserver>  Observers;
 
     Observers  observers_;
 
@@ -40,7 +40,7 @@
     
     virtual void NotifyContentChange();
 
-    virtual void NotifySliceChange(size_t sliceIndex,
+    virtual void NotifySliceChange(const size_t& sliceIndex,
                                    const Slice& slice);
 
   public:
--- a/Framework/Widgets/LayerWidget.cpp	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Widgets/LayerWidget.cpp	Mon May 29 11:04:18 2017 +0200
@@ -106,11 +106,6 @@
 
       for (size_t i = 0; i < renderers_.size(); i++)
       {
-        if (renderers_[i] != NULL)
-        {
-          LOG(ERROR) << "...............";
-        }
-
         if (renderers_[i] != NULL &&
             !renderers_[i]->RenderLayer(context, view, slice_))
         {
@@ -351,8 +346,7 @@
     layersIndex_[layer] = index;
 
     ResetPendingScene();
-    LOG(ERROR) << "*****************************";
-    layer->SetObserver(*this);
+    layer->Register(*this);
 
     return index;
   }
@@ -385,18 +379,42 @@
 
   void LayerWidget::SetSlice(const SliceGeometry& slice)
   {
-    if (currentScene_.get() == NULL ||
-        (pendingScene_.get() != NULL &&
-         pendingScene_->IsComplete()))
+    Slice displayedSlice(slice_, THIN_SLICE_THICKNESS);
+
+    if (!displayedSlice.ContainsPlane(slice))
     {
-      currentScene_ = pendingScene_;
-    }
+      if (currentScene_.get() == NULL ||
+          (pendingScene_.get() != NULL &&
+           pendingScene_->IsComplete()))
+      {
+        currentScene_ = pendingScene_;
+      }
 
-    slice_ = slice;
-    ResetPendingScene();
+      slice_ = slice;
+      ResetPendingScene();
+
+      InvalidateAllLayers();
+    }
   }
 
 
+  void LayerWidget::NotifyGeometryReady(const ILayerSource& source)
+  {
+    size_t i;
+    if (LookupLayer(i, source))
+    {
+      LOG(INFO) << "Geometry ready for layer " << i;
+      layers_[i]->ScheduleLayerCreation(slice_);
+    }
+  }
+  
+
+  void LayerWidget::NotifyGeometryError(const ILayerSource& source)
+  {
+    LOG(ERROR) << "Cannot get geometry";
+  }
+  
+
   void LayerWidget::InvalidateAllLayers()
   {
     for (size_t i = 0; i < layers_.size(); i++)
@@ -443,18 +461,16 @@
   }
   
   
-  void LayerWidget::NotifyLayerReady(ILayerRenderer* renderer,
+  void LayerWidget::NotifyLayerReady(std::auto_ptr<ILayerRenderer>& renderer,
                                      const ILayerSource& source,
                                      const Slice& slice)
   {
-    std::auto_ptr<ILayerRenderer> tmp(renderer);
-
     size_t index;
     if (LookupLayer(index, source) &&
         slice.ContainsPlane(slice_))  // Whether the slice comes from an older request
     {
       LOG(INFO) << "Renderer ready for layer " << index;
-      UpdateLayer(index, tmp.release(), slice);
+      UpdateLayer(index, renderer.release(), slice);
     }
   }
 
--- a/Framework/Widgets/LayerWidget.h	Fri May 26 18:27:59 2017 +0200
+++ b/Framework/Widgets/LayerWidget.h	Mon May 29 11:04:18 2017 +0200
@@ -55,12 +55,16 @@
                          double& y2,
                          ILayerSource& source) const;
 
+    virtual void NotifyGeometryReady(const ILayerSource& source);
+
+    virtual void NotifyGeometryError(const ILayerSource& source);
+
     virtual void NotifyContentChange(const ILayerSource& source);
 
     virtual void NotifySliceChange(const ILayerSource& source,
                                    const Slice& slice);
 
-    virtual void NotifyLayerReady(ILayerRenderer* renderer,
+    virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& renderer,
                                   const ILayerSource& source,
                                   const Slice& slice);