changeset 1059:e713f1a99861 broker

replacing MessageBroker by weak_ptr
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 11 Oct 2019 17:08:34 +0200
parents a36c47487a70
children e146743f6cdc
files Applications/Generic/NativeStoneApplicationContext.h Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h Framework/Deprecated/Layers/DicomStructureSetSlicer.cpp Framework/Deprecated/Layers/DicomStructureSetSlicer.h Framework/Deprecated/SmartLoader.cpp Framework/Deprecated/SmartLoader.h Framework/Deprecated/Toolbox/BaseWebService.cpp Framework/Deprecated/Toolbox/BaseWebService.h Framework/Deprecated/Viewport/IViewport.h Framework/Deprecated/Volumes/ISlicedVolume.h Framework/Deprecated/Volumes/IVolumeLoader.h Framework/Loaders/DicomStructureSetLoader.cpp Framework/Loaders/LoaderStateMachine.cpp Framework/Loaders/LoaderStateMachine.h Framework/Loaders/OrthancMultiframeVolumeLoader.cpp Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h Framework/Messages/ICallable.h Framework/Messages/IMessage.h Framework/Messages/IObservable.cpp Framework/Messages/IObservable.h Framework/Messages/IObserver.cpp Framework/Messages/IObserver.h Framework/Messages/LockingEmitter.h Framework/Messages/MessageBroker.h Framework/Scene2DViewport/AngleMeasureTool.cpp Framework/Scene2DViewport/AngleMeasureTool.h Framework/Scene2DViewport/EditAngleMeasureCommand.cpp Framework/Scene2DViewport/EditAngleMeasureCommand.h Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Framework/Scene2DViewport/EditAngleMeasureTracker.h Framework/Scene2DViewport/EditLineMeasureCommand.cpp Framework/Scene2DViewport/EditLineMeasureCommand.h Framework/Scene2DViewport/EditLineMeasureTracker.cpp Framework/Scene2DViewport/EditLineMeasureTracker.h Framework/Scene2DViewport/LineMeasureTool.cpp Framework/Scene2DViewport/LineMeasureTool.h Framework/Scene2DViewport/MeasureTool.cpp Framework/Scene2DViewport/MeasureTool.h Framework/Scene2DViewport/ViewportController.cpp Framework/Scene2DViewport/ViewportController.h Platforms/Generic/DelayedCallCommand.cpp Platforms/Generic/DelayedCallCommand.h Platforms/Generic/WebServiceCommandBase.cpp Platforms/Generic/WebServiceCommandBase.h Platforms/Generic/WebServiceDeleteCommand.cpp Platforms/Generic/WebServiceDeleteCommand.h Platforms/Generic/WebServiceGetCommand.cpp Platforms/Generic/WebServiceGetCommand.h Platforms/Generic/WebServicePostCommand.cpp Platforms/Generic/WebServicePostCommand.h Resources/CMake/OrthancStoneConfiguration.cmake
diffstat 53 files changed, 144 insertions(+), 331 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Generic/NativeStoneApplicationContext.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Applications/Generic/NativeStoneApplicationContext.h	Fri Oct 11 17:08:34 2019 +0200
@@ -67,11 +67,6 @@
       {
         that_.updateDelayInMs_ = delayInMs;
       }
-
-      MessageBroker& GetMessageBroker()
-      {
-        return that_.GetMessageBroker();
-      }
     };
 
     NativeStoneApplicationContext(MessageBroker& broker);
--- a/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -90,25 +90,24 @@
   DicomSeriesVolumeSlicer::DicomSeriesVolumeSlicer(OrthancStone::MessageBroker& broker,
                                                    OrthancApiClient& orthanc) :
     IVolumeSlicer(broker),
-    IObserver(broker),
     loader_(broker, orthanc),
     quality_(SliceImageQuality_FullPng)
   {
     loader_.RegisterObserverCallback(
       new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceGeometryReadyMessage>
-        (*this, &DicomSeriesVolumeSlicer::OnSliceGeometryReady));
+      (shared_from_this(), &DicomSeriesVolumeSlicer::OnSliceGeometryReady));
 
     loader_.RegisterObserverCallback(
       new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceGeometryErrorMessage>
-      (*this, &DicomSeriesVolumeSlicer::OnSliceGeometryError));
+      (shared_from_this(), &DicomSeriesVolumeSlicer::OnSliceGeometryError));
 
     loader_.RegisterObserverCallback(
       new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceImageReadyMessage>
-        (*this, &DicomSeriesVolumeSlicer::OnSliceImageReady));
+        (shared_from_this(), &DicomSeriesVolumeSlicer::OnSliceImageReady));
 
     loader_.RegisterObserverCallback(
       new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceImageErrorMessage>
-      (*this, &DicomSeriesVolumeSlicer::OnSliceImageError));
+      (shared_from_this(), &DicomSeriesVolumeSlicer::OnSliceImageError));
   }
 
   
--- a/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h	Fri Oct 11 17:08:34 2019 +0200
@@ -33,7 +33,7 @@
   // messages are sent to observers so they can use it
   class DicomSeriesVolumeSlicer :
     public IVolumeSlicer,
-    public OrthancStone::IObserver
+    public OrthancStone::ObserverBase<DicomSeriesVolumeSlicer>
     //private OrthancSlicesLoader::ISliceLoaderObserver
   {
   public:
--- a/Framework/Deprecated/Layers/DicomStructureSetSlicer.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Layers/DicomStructureSetSlicer.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -144,12 +144,11 @@
   DicomStructureSetSlicer::DicomStructureSetSlicer(OrthancStone::MessageBroker& broker,
                                                    StructureSetLoader& loader) :
     IVolumeSlicer(broker),
-    IObserver(broker),
     loader_(loader)
   {
     loader_.RegisterObserverCallback(
       new OrthancStone::Callable<DicomStructureSetSlicer, StructureSetLoader::ContentChangedMessage>
-      (*this, &DicomStructureSetSlicer::OnStructureSetLoaded));
+      (shared_from_this(), &DicomStructureSetSlicer::OnStructureSetLoaded));
   }
 
 
--- a/Framework/Deprecated/Layers/DicomStructureSetSlicer.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Layers/DicomStructureSetSlicer.h	Fri Oct 11 17:08:34 2019 +0200
@@ -28,7 +28,7 @@
 {
   class DicomStructureSetSlicer :
     public IVolumeSlicer,
-    public OrthancStone::IObserver
+    public OrthancStone::ObserverBase<DicomStructureSetSlicer>
   {
   private:
     class Renderer;
--- a/Framework/Deprecated/SmartLoader.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/SmartLoader.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -122,7 +122,6 @@
   SmartLoader::SmartLoader(OrthancStone::MessageBroker& broker,  
                            OrthancApiClient& orthancApiClient) :
     IObservable(broker),
-    IObserver(broker),
     imageQuality_(SliceImageQuality_FullPam),
     orthancApiClient_(orthancApiClient)
   {
@@ -151,11 +150,11 @@
     }
     else
     {
-      layerSource.reset(new DicomSeriesVolumeSlicer(IObserver::GetBroker(), orthancApiClient_));
+      layerSource.reset(new DicomSeriesVolumeSlicer(IObservable::GetBroker(), orthancApiClient_));
       dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_);
-      layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady));
-      layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady));
-      layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady));
+      layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(shared_from_this(), &SmartLoader::OnLayerGeometryReady));
+      layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(shared_from_this(), &SmartLoader::OnFrameReady));
+      layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(shared_from_this(), &SmartLoader::OnLayerReady));
       dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame);
     }
 
@@ -190,7 +189,7 @@
 
 
     // create the slice in the cache with "empty" data
-    boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice(IObserver::GetBroker()));
+    boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice(IObservable::GetBroker()));
     cachedSlice->slice_.reset(new Slice(instanceId, frame));
     cachedSlice->status_ = CachedSliceStatus_ScheduledToLoad;
     std::string sliceKeyId = instanceId + ":" + boost::lexical_cast<std::string>(frame);
@@ -199,12 +198,12 @@
 
     cachedSlices_[sliceKeyId] = boost::shared_ptr<CachedSlice>(cachedSlice);
 
-    std::auto_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer(IObserver::GetBroker(), orthancApiClient_));
+    std::auto_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer(IObservable::GetBroker(), orthancApiClient_));
 
     dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_);
-    layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady));
-    layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady));
-    layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady));
+    layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(shared_from_this(), &SmartLoader::OnLayerGeometryReady));
+    layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(shared_from_this(), &SmartLoader::OnFrameReady));
+    layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(shared_from_this(), &SmartLoader::OnLayerReady));
     dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame);
 
     // keep a ref to the VolumeSlicer until the slice is fully loaded and saved to cache
@@ -235,7 +234,7 @@
 
     LOG(WARNING) << "Geometry ready: " << sliceKeyId;
 
-    boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice(IObserver::GetBroker()));
+    boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice(IObservable::GetBroker()));
     cachedSlice->slice_.reset(slice.Clone());
     cachedSlice->effectiveQuality_ = source.GetImageQuality();
     cachedSlice->status_ = CachedSliceStatus_GeometryLoaded;
@@ -256,7 +255,7 @@
 
     LOG(WARNING) << "Image ready: " << sliceKeyId;
 
-    boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice(IObserver::GetBroker()));
+    boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice(IObservable::GetBroker()));
     cachedSlice->image_.reset(Orthanc::Image::Clone(message.GetFrame()));
     cachedSlice->effectiveQuality_ = message.GetImageQuality();
     cachedSlice->slice_.reset(message.GetSlice().Clone());
--- a/Framework/Deprecated/SmartLoader.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/SmartLoader.h	Fri Oct 11 17:08:34 2019 +0200
@@ -30,7 +30,7 @@
 {
   class SliceViewerWidget;
 
-  class SmartLoader : public OrthancStone::IObservable, public OrthancStone::IObserver
+  class SmartLoader : public OrthancStone::IObservable, public OrthancStone::ObserverBase<SmartLoader>
   {
     class CachedSlice;
 
--- a/Framework/Deprecated/Toolbox/BaseWebService.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Toolbox/BaseWebService.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -97,9 +97,9 @@
       GetAsyncInternal(uri, headers,
                        new BaseWebService::BaseWebServicePayload(successCallback, failureCallback, payload), // ownership is transfered
                        new OrthancStone::Callable<BaseWebService, IWebService::HttpRequestSuccessMessage>
-                       (*this, &BaseWebService::CacheAndNotifyHttpSuccess),
+                       (shared_from_this(), &BaseWebService::CacheAndNotifyHttpSuccess),
                        new OrthancStone::Callable<BaseWebService, IWebService::HttpRequestErrorMessage>
-                       (*this, &BaseWebService::NotifyHttpError),
+                       (shared_from_this(), &BaseWebService::NotifyHttpError),
                        timeoutInSeconds);
     }
     else
--- a/Framework/Deprecated/Toolbox/BaseWebService.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Toolbox/BaseWebService.h	Fri Oct 11 17:08:34 2019 +0200
@@ -31,7 +31,7 @@
 {
   // This is an intermediate of IWebService that implements some caching on
   // the HTTP GET requests
-  class BaseWebService : public IWebService, public OrthancStone::IObserver
+  class BaseWebService : public IWebService, public OrthancStone::ObserverBase<BaseWebService>
   {
   public:
     class CachedHttpRequestSuccessMessage
@@ -93,7 +93,6 @@
 
     BaseWebService(OrthancStone::MessageBroker& broker) :
       IWebService(broker),
-      IObserver(broker),
       cacheEnabled_(false),
       cacheCurrentSize_(0),
       cacheMaxSize_(100*1024*1024)
--- a/Framework/Deprecated/Viewport/IViewport.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Viewport/IViewport.h	Fri Oct 11 17:08:34 2019 +0200
@@ -37,15 +37,6 @@
   public:
     ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ViewportChangedMessage, IViewport);
 
-    IViewport(OrthancStone::MessageBroker& broker) :
-      IObservable(broker)
-    {
-    }
-    
-    virtual ~IViewport()
-    {
-    }
-
     virtual void FitContent() = 0;
 
     virtual void SetStatusBar(IStatusBar& statusBar) = 0;
--- a/Framework/Deprecated/Volumes/ISlicedVolume.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Volumes/ISlicedVolume.h	Fri Oct 11 17:08:34 2019 +0200
@@ -65,11 +65,6 @@
     };
 
 
-    ISlicedVolume(OrthancStone::MessageBroker& broker) :
-      IObservable(broker)
-    {
-    }
-    
     virtual size_t GetSliceCount() const = 0;
 
     virtual const Slice& GetSlice(size_t slice) const = 0;
--- a/Framework/Deprecated/Volumes/IVolumeLoader.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Deprecated/Volumes/IVolumeLoader.h	Fri Oct 11 17:08:34 2019 +0200
@@ -31,10 +31,5 @@
     ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryReadyMessage, IVolumeLoader);
     ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryErrorMessage, IVolumeLoader);
     ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, IVolumeLoader);
-
-    IVolumeLoader(OrthancStone::MessageBroker& broker) :
-      IObservable(broker)
-    {
-    }
   };
 }
--- a/Framework/Loaders/DicomStructureSetLoader.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Loaders/DicomStructureSetLoader.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -347,7 +347,6 @@
   DicomStructureSetLoader::DicomStructureSetLoader(IOracle& oracle,
                                                    IObservable& oracleObservable) :
     LoaderStateMachine(oracle, oracleObservable),
-    IObservable(oracleObservable.GetBroker()),
     revision_(0),
     countProcessedInstances_(0),
     countReferencedInstances_(0),
--- a/Framework/Loaders/LoaderStateMachine.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Loaders/LoaderStateMachine.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -136,7 +136,6 @@
   template <typename T>
   void LoaderStateMachine::HandleSuccessMessage(const T& message)
   {
-    LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::HandleSuccessMessage(). Receiver fingerprint = " << GetFingerprint();
     if (activeCommands_ <= 0) {
       LOG(ERROR) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::HandleSuccessMessage : activeCommands_ should be > 0 but is: " << activeCommands_;
     }
@@ -159,7 +158,6 @@
 
   LoaderStateMachine::LoaderStateMachine(IOracle& oracle,
                                          IObservable& oracleObservable) :
-    IObserver(oracleObservable.GetBroker()),
     oracle_(oracle),
     oracleObservable_(oracleObservable),
     active_(false),
@@ -170,19 +168,19 @@
 
     oracleObservable.RegisterObserverCallback(
       new Callable<LoaderStateMachine, OrthancRestApiCommand::SuccessMessage>
-      (*this, &LoaderStateMachine::HandleSuccessMessage));
+      (shared_from_this(), &LoaderStateMachine::HandleSuccessMessage));
 
     oracleObservable.RegisterObserverCallback(
       new Callable<LoaderStateMachine, GetOrthancImageCommand::SuccessMessage>
-      (*this, &LoaderStateMachine::HandleSuccessMessage));
+      (shared_from_this(), &LoaderStateMachine::HandleSuccessMessage));
 
     oracleObservable.RegisterObserverCallback(
       new Callable<LoaderStateMachine, GetOrthancWebViewerJpegCommand::SuccessMessage>
-      (*this, &LoaderStateMachine::HandleSuccessMessage));
+      (shared_from_this(), &LoaderStateMachine::HandleSuccessMessage));
 
     oracleObservable.RegisterObserverCallback(
       new Callable<LoaderStateMachine, OracleCommandExceptionMessage>
-      (*this, &LoaderStateMachine::HandleExceptionMessage));
+      (shared_from_this(), &LoaderStateMachine::HandleExceptionMessage));
   }
 
   LoaderStateMachine::~LoaderStateMachine()
--- a/Framework/Loaders/LoaderStateMachine.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Loaders/LoaderStateMachine.h	Fri Oct 11 17:08:34 2019 +0200
@@ -41,7 +41,7 @@
      rest once slots become available. It is used, a.o., by the 
      OrtancMultiframeVolumeLoader class.
   */
-  class LoaderStateMachine : public IObserver
+  class LoaderStateMachine : public ObserverBase<LoaderStateMachine>
   {
   protected:
     class State : public Orthanc::IDynamicObject
--- a/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -337,7 +337,6 @@
                                                                IOracle& oracle,
                                                                IObservable& oracleObservable) :
     LoaderStateMachine(oracle, oracleObservable),
-    IObservable(oracleObservable.GetBroker()),
     volume_(volume),
     pixelDataLoaded_(false)
   {
--- a/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -421,8 +421,6 @@
   OrthancSeriesVolumeProgressiveLoader::OrthancSeriesVolumeProgressiveLoader(const boost::shared_ptr<DicomVolumeImage>& volume,
                                                                              IOracle& oracle,
                                                                              IObservable& oracleObservable) :
-    IObserver(oracleObservable.GetBroker()),
-    IObservable(oracleObservable.GetBroker()),
     oracle_(oracle),
     oracleObservable_(oracleObservable),
     active_(false),
@@ -433,15 +431,15 @@
   {
     oracleObservable.RegisterObserverCallback(
       new Callable<OrthancSeriesVolumeProgressiveLoader, OrthancRestApiCommand::SuccessMessage>
-      (*this, &OrthancSeriesVolumeProgressiveLoader::LoadGeometry));
+      (shared_from_this(), &OrthancSeriesVolumeProgressiveLoader::LoadGeometry));
 
     oracleObservable.RegisterObserverCallback(
       new Callable<OrthancSeriesVolumeProgressiveLoader, GetOrthancImageCommand::SuccessMessage>
-      (*this, &OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent));
+      (shared_from_this(), &OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent));
 
     oracleObservable.RegisterObserverCallback(
       new Callable<OrthancSeriesVolumeProgressiveLoader, GetOrthancWebViewerJpegCommand::SuccessMessage>
-      (*this, &OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent));
+      (shared_from_this(), &OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent));
   }
 
   OrthancSeriesVolumeProgressiveLoader::~OrthancSeriesVolumeProgressiveLoader()
--- a/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h	Fri Oct 11 17:08:34 2019 +0200
@@ -42,7 +42,7 @@
     is stored in a Dicom series.
   */
   class OrthancSeriesVolumeProgressiveLoader : 
-    public IObserver,
+    public ObserverBase<OrthancSeriesVolumeProgressiveLoader>,
     public IObservable,
     public IVolumeSlicer,
     public IGeometryProvider
--- a/Framework/Messages/ICallable.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/ICallable.h	Fri Oct 11 17:08:34 2019 +0200
@@ -22,17 +22,17 @@
 #pragma once
 
 #include "IMessage.h"
+#include "IObserver.h"
 
 #include <Core/Logging.h>
 
 #include <boost/noncopyable.hpp>
+#include <boost/weak_ptr.hpp>
 
 #include <string>
 
-namespace OrthancStone {
-
-  class IObserver;
-
+namespace OrthancStone 
+{
   // This is referencing an object and member function that can be notified
   // by an IObservable.  The object must derive from IO
   // The member functions must be of type "void Function(const IMessage& message)" or reference a derived class of IMessage
@@ -47,11 +47,14 @@
 
     virtual const MessageIdentifier& GetMessageIdentifier() = 0;
 
-    virtual IObserver* GetObserver() const = 0;
+    // TODO - Is this needed?
+    virtual boost::weak_ptr<IObserver> GetObserver() const = 0;
   };
 
+
+  // TODO - Remove this class
   template <typename TMessage>
-  class MessageHandler: public ICallable
+  class MessageHandler : public ICallable
   {
   };
 
@@ -63,45 +66,26 @@
   private:
     typedef void (TObserver::* MemberFunction) (const TMessage&);
 
-    TObserver&         observer_;
-    MemberFunction     function_;
-    std::string        observerFingerprint_;
+    boost::weak_ptr<IObserver>  observer_;
+    MemberFunction              function_;
 
   public:
-    Callable(TObserver& observer,
+    Callable(boost::shared_ptr<TObserver> observer,
              MemberFunction function) :
       observer_(observer),
-      function_(function),
-      observerFingerprint_(observer.GetFingerprint())
-    {
-    }
-
-    void ApplyInternal(const TMessage& message)
+      function_(function)
     {
-      std::string currentFingerprint(observer_.GetFingerprint());
-      if (observerFingerprint_ != currentFingerprint)
-      {
-        LOG(TRACE) << "The observer at address " << 
-          std::hex << &observer_ << std::dec << 
-          ") has a different fingerprint than the one recorded at callback " <<
-          "registration time. This means that it is not the same object as " <<
-          "the one recorded, even though their addresses are the same. " <<
-          "Callback will NOT be sent!";
-        LOG(TRACE) << " recorded fingerprint = " << observerFingerprint_ << 
-          " current fingerprint = " << currentFingerprint;
-      }
-      else
-      {
-        LOG(TRACE) << "The recorded fingerprint is " << observerFingerprint_
-          << " and the current fingerprint is " << currentFingerprint
-          << " -- callable will be called.";
-        (observer_.*function_) (message);
-      }
     }
 
     virtual void Apply(const IMessage& message)
     {
-      ApplyInternal(dynamic_cast<const TMessage&>(message));
+      boost::shared_ptr<IObserver> lock(observer_);
+      if (lock)
+      {
+        TObserver& observer = dynamic_cast<TObserver&>(*lock);
+        const TMessage& typedMessage = dynamic_cast<const TMessage&>(message);
+        (observer.*function_) (typedMessage);
+      }
     }
 
     virtual const MessageIdentifier& GetMessageIdentifier()
@@ -109,9 +93,9 @@
       return TMessage::GetStaticIdentifier();
     }
 
-    virtual IObserver* GetObserver() const
+    virtual boost::weak_ptr<IObserver> GetObserver() const
     {
-      return &observer_;
+      return observer_;
     }
   };
 
--- a/Framework/Messages/IMessage.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/IMessage.h	Fri Oct 11 17:08:34 2019 +0200
@@ -33,6 +33,12 @@
     const char*  file_;
     int          line_;
 
+    bool IsEqual(const MessageIdentifier& other) const
+    {
+      return (line_ == other.line_ &&
+              strcmp(file_, other.file_) == 0);
+    }
+
   public:
     MessageIdentifier(const char* file,
                       int line) :
@@ -62,6 +68,16 @@
         return strcmp(file_, other.file_) < 0;
       }
     }
+
+    bool operator== (const MessageIdentifier& other) const
+    {
+      return IsEqual(other);
+    }
+
+    bool operator!= (const MessageIdentifier& other) const
+    {
+      return !IsEqual(other);
+    }
   };
 
     
--- a/Framework/Messages/IObservable.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/IObservable.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -48,7 +48,10 @@
          it != forwarders_.end(); ++it)
     {
       IMessageForwarder* fw = *it;
-      broker_.Unregister(dynamic_cast<IObserver&>(*fw));
+
+      // TODO - What to do with forwarders?
+      
+      //broker_.Unregister(dynamic_cast<IObserver&>(*fw));
     }
   }
   
@@ -75,7 +78,10 @@
       for (std::set<ICallable*>::const_iterator
              itCallable = itCallableSet->second.begin(); itCallable != itCallableSet->second.end(); )
       {
-        if ((*itCallable)->GetObserver() == observer)
+        boost::shared_ptr<IObserver> shared((*itCallable)->GetObserver());
+
+        if (shared &&
+            shared.get() == observer)
         {
           LOG(TRACE) << "  ** IObservable::Unregister : deleting callable: "
             << std::hex << (*itCallable) << std::dec;
@@ -102,11 +108,12 @@
       {
         assert(*it != NULL);
 
-        const IObserver* observer = (*it)->GetObserver();
-        if (broker_.IsActive(*observer))
+        boost::shared_ptr<IObserver> observer((*it)->GetObserver());
+
+        if (observer)
         {
           if (receiver == NULL ||    // Are we broadcasting?
-              observer == receiver)  // Not broadcasting, but this is the receiver
+              observer.get() == receiver)  // Not broadcasting, but this is the receiver
           {
             (*it)->Apply(message);
           }
--- a/Framework/Messages/IObservable.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/IObservable.h	Fri Oct 11 17:08:34 2019 +0200
@@ -24,7 +24,6 @@
 #include "../StoneEnumerations.h"
 #include "ICallable.h"
 #include "IObserver.h"
-#include "MessageBroker.h"
 #include "MessageForwarder.h"
 
 #include <set>
@@ -39,7 +38,6 @@
 
     typedef std::set<IMessageForwarder*>     Forwarders;
 
-    MessageBroker&  broker_;
     Callables       callables_;
     Forwarders      forwarders_;
 
@@ -47,21 +45,12 @@
                              const IMessage& message);
 
   public:
-    IObservable(MessageBroker& broker) :
-      broker_(broker)
-    {
-    }
-
     virtual ~IObservable();
 
-    MessageBroker& GetBroker() const
-    {
-      return broker_;
-    }
-
     // Takes ownsership
     void RegisterObserverCallback(ICallable* callable);
 
+    // TODO - Remove this?
     void Unregister(IObserver* observer);
 
     void BroadcastMessage(const IMessage& message);
--- a/Framework/Messages/IObserver.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2019 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "IObserver.h"
-
-#include "IMessage.h"
-#include "../StoneException.h"
-
-#include <Core/Logging.h>
-#include <Core/Toolbox.h>
-
-namespace OrthancStone 
-{
-  IObserver::IObserver(MessageBroker& broker)
-    : broker_(broker)
-    , fingerprint_()
-  {
-    // we store the fingerprint_ as a char array to avoid problems when
-    // reading it in a deceased object.
-    // remember this is panic-level code to track zombie object usage
-    std::string fingerprint = Orthanc::Toolbox::GenerateUuid();
-    const char* fingerprintRaw = fingerprint.c_str();
-    memcpy(fingerprint_, fingerprintRaw, 37);
-    broker_.Register(*this);
-  }
-
-
-  IObserver::~IObserver()
-  {
-    try
-    {
-      LOG(TRACE) << "IObserver(" << std::hex << this << std::dec << ")::~IObserver : fingerprint_ == " << fingerprint_;
-      const char* deadMarker = "deadbeef-dead-dead-0000-0000deadbeef";
-      ORTHANC_ASSERT(strlen(deadMarker) == 36);
-      memcpy(fingerprint_, deadMarker, 37);
-      broker_.Unregister(*this);
-    }
-    catch (const Orthanc::OrthancException& e)
-    {
-      if (e.HasDetails())
-      {
-        LOG(ERROR) << "OrthancException in ~IObserver: " << e.What() << " Details: " << e.GetDetails();
-      }
-      else
-      {
-        LOG(ERROR) << "OrthancException in ~IObserver: " << e.What();
-      }
-    }
-    catch (const std::exception& e)
-    {
-      LOG(ERROR) << "std::exception in ~IObserver: " << e.what();
-    }
-    catch (...)
-    {
-      LOG(ERROR) << "Unknown exception in ~IObserver";
-    }
-  }
-
-
-  bool IObserver::DoesFingerprintLookGood() const
-  {
-    for (size_t i = 0; i < 36; ++i) {
-      bool ok = false;
-      if (fingerprint_[i] >= 'a' && fingerprint_[i] <= 'f')
-        ok = true;
-      if (fingerprint_[i] >= '0' && fingerprint_[i] <= '9')
-        ok = true;
-      if (fingerprint_[i] == '-')
-        ok = true;
-      if (!ok)
-        return false;
-    }
-    return fingerprint_[36] == 0;
-  }
-}
--- a/Framework/Messages/IObserver.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/IObserver.h	Fri Oct 11 17:08:34 2019 +0200
@@ -21,33 +21,34 @@
 
 #pragma once
 
-#include "MessageBroker.h"
+#include <boost/noncopyable.hpp>
+#include <boost/enable_shared_from_this.hpp>
 
 namespace OrthancStone 
 {
+  class MessageBroker;  // TODO - Remove
+
   class IObserver : public boost::noncopyable
   {
-  private:
-    MessageBroker&  broker_;
-    // the following is a UUID that is used to disambiguate different observers
-    // that may have the same address
-    char     fingerprint_[37];
+  public:
+    IObserver()
+    {
+    }
 
-  public:
-    IObserver(MessageBroker& broker);
-
-    virtual ~IObserver();
-
-    const char* GetFingerprint() const
+    // TODO - Remove
+    IObserver(MessageBroker& broker)
     {
-      return fingerprint_;
     }
 
-    bool DoesFingerprintLookGood() const;
-
-    MessageBroker& GetBroker() const
+    virtual ~IObserver()
     {
-      return broker_;
     }
   };
+
+  template <typename T>
+  class ObserverBase : 
+    public IObserver,
+    public boost::enable_shared_from_this<T>    
+  {
+  };
 }
--- a/Framework/Messages/LockingEmitter.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/LockingEmitter.h	Fri Oct 11 17:08:34 2019 +0200
@@ -39,21 +39,10 @@
   class LockingEmitter : public IMessageEmitter
   {
   private:
-    boost::shared_mutex                mutex_;
-    MessageBroker        broker_;
+    boost::shared_mutex  mutex_;
     IObservable          oracleObservable_;
 
   public:
-    LockingEmitter() :
-      oracleObservable_(broker_)
-    {
-    }
-
-    MessageBroker& GetBroker()
-    {
-      return broker_;
-    }
-
     virtual void EmitMessage(const IObserver& observer,
       const IMessage& message) ORTHANC_OVERRIDE
     {
@@ -97,11 +86,6 @@
       {
       }
 
-      MessageBroker& GetBroker()
-      {
-        return that_.broker_;
-      }
-
       IObservable& GetOracleObservable()
       {
         return that_.oracleObservable_;
--- a/Framework/Messages/MessageBroker.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Messages/MessageBroker.h	Fri Oct 11 17:08:34 2019 +0200
@@ -20,9 +20,7 @@
 
 #pragma once
 
-#include "boost/noncopyable.hpp"
-
-#include <set>
+#include <boost/noncopyable.hpp>
 
 namespace OrthancStone
 {
@@ -35,27 +33,18 @@
    */
   class MessageBroker : public boost::noncopyable
   {
-  private:
-    std::set<const IObserver*> activeObservers_;  // the list of observers that are currently alive (that have not been deleted)
-
   public:
-    MessageBroker()
-    {
-    }
-
     void Register(const IObserver& observer)
     {
-      activeObservers_.insert(&observer);
     }
 
     void Unregister(const IObserver& observer)
     {
-      activeObservers_.erase(&observer);
     }
 
     bool IsActive(const IObserver& observer)
     {
-      return activeObservers_.find(&observer) != activeObservers_.end();
+      return false;
     }
   };
 }
--- a/Framework/Scene2DViewport/AngleMeasureTool.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -189,8 +189,9 @@
         boost::weak_ptr<ViewportController>          controllerW,
         const PointerEvent & e);
     */
+
     boost::shared_ptr<EditAngleMeasureTracker> editAngleMeasureTracker(
-      new EditAngleMeasureTracker(shared_from_this(), GetBroker(), GetController(), e));
+      new EditAngleMeasureTracker(shared_from_this(), GetController(), e));
     return editAngleMeasureTracker;
   }
 
--- a/Framework/Scene2DViewport/AngleMeasureTool.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/AngleMeasureTool.h	Fri Oct 11 17:08:34 2019 +0200
@@ -37,7 +37,7 @@
 
 namespace OrthancStone
 {
-  class AngleMeasureTool : public MeasureTool, public boost::enable_shared_from_this<AngleMeasureTool>
+  class AngleMeasureTool : public MeasureTool
   {
   public:
     AngleMeasureTool(MessageBroker& broker, boost::weak_ptr<ViewportController> controllerW);
--- a/Framework/Scene2DViewport/EditAngleMeasureCommand.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureCommand.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -23,8 +23,7 @@
 namespace OrthancStone
 {
   EditAngleMeasureCommand::EditAngleMeasureCommand(
-    boost::shared_ptr<AngleMeasureTool>  measureTool,
-    MessageBroker& broker,
+    boost::shared_ptr<MeasureTool>  measureTool,
     boost::weak_ptr<ViewportController> controllerW)
     : EditMeasureCommand(measureTool, controllerW)
     , measureTool_(measureTool)
@@ -33,21 +32,21 @@
 
   void EditAngleMeasureCommand::SetCenter(ScenePoint2D scenePos)
   {
-    measureTool_->SetCenter(scenePos);
+    dynamic_cast<AngleMeasureTool&>(*measureTool_).SetCenter(scenePos);
     mementoModified_ = measureTool_->GetMemento();
   }
 
 
   void EditAngleMeasureCommand::SetSide1End(ScenePoint2D scenePos)
   {
-    measureTool_->SetSide1End(scenePos);
+    dynamic_cast<AngleMeasureTool&>(*measureTool_).SetSide1End(scenePos);
     mementoModified_ = measureTool_->GetMemento();
   }
 
 
   void EditAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos)
   {
-    measureTool_->SetSide2End(scenePos);
+    dynamic_cast<AngleMeasureTool&>(*measureTool_).SetSide2End(scenePos);
     mementoModified_ = measureTool_->GetMemento();
   }
 }
--- a/Framework/Scene2DViewport/EditAngleMeasureCommand.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureCommand.h	Fri Oct 11 17:08:34 2019 +0200
@@ -28,8 +28,7 @@
   public:
     /** Ctor sets end of side 1*/
     EditAngleMeasureCommand(
-      boost::shared_ptr<AngleMeasureTool>  measureTool,
-      MessageBroker& broker,
+      boost::shared_ptr<MeasureTool>  measureTool,
       boost::weak_ptr<ViewportController> controllerW);
 
     /** This method sets center*/
@@ -46,6 +45,6 @@
     {
       return measureTool_;
     }
-    boost::shared_ptr<AngleMeasureTool> measureTool_;
+    boost::shared_ptr<MeasureTool> measureTool_;
   };
 }
--- a/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -26,8 +26,7 @@
 namespace OrthancStone
 {
   EditAngleMeasureTracker::EditAngleMeasureTracker(
-    boost::shared_ptr<AngleMeasureTool>  measureTool,
-    MessageBroker& broker,
+    boost::shared_ptr<MeasureTool>  measureTool,
     boost::weak_ptr<ViewportController> controllerW,
     const PointerEvent& e)
     : EditMeasureTracker(controllerW, e)
@@ -35,9 +34,9 @@
     ScenePoint2D scenePos = e.GetMainPosition().Apply(
       GetScene().GetCanvasToSceneTransform());
 
-    modifiedZone_ = measureTool->AngleHitTest(scenePos);
+    modifiedZone_ = dynamic_cast<AngleMeasureTool&>(*measureTool).AngleHitTest(scenePos);
 
-    command_.reset(new EditAngleMeasureCommand(measureTool, broker, controllerW));
+    command_.reset(new EditAngleMeasureCommand(measureTool, controllerW));
   }
 
   EditAngleMeasureTracker::~EditAngleMeasureTracker()
--- a/Framework/Scene2DViewport/EditAngleMeasureTracker.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.h	Fri Oct 11 17:08:34 2019 +0200
@@ -37,8 +37,7 @@
     must be supplied, too
     */
     EditAngleMeasureTracker(
-      boost::shared_ptr<AngleMeasureTool>  measureTool,
-      MessageBroker& broker,
+      boost::shared_ptr<MeasureTool>  measureTool,
       boost::weak_ptr<ViewportController> controllerW,
       const PointerEvent& e);
 
--- a/Framework/Scene2DViewport/EditLineMeasureCommand.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureCommand.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -23,8 +23,7 @@
 namespace OrthancStone
 {
   EditLineMeasureCommand::EditLineMeasureCommand(
-    boost::shared_ptr<LineMeasureTool>  measureTool,
-    MessageBroker& broker,
+    boost::shared_ptr<MeasureTool>  measureTool,
     boost::weak_ptr<ViewportController> controllerW)
     : EditMeasureCommand(measureTool, controllerW)
     , measureTool_(measureTool)
@@ -34,14 +33,14 @@
 
   void EditLineMeasureCommand::SetStart(ScenePoint2D scenePos)
   {
-    measureTool_->SetStart(scenePos);
+    dynamic_cast<LineMeasureTool&>(*measureTool_).SetStart(scenePos);
     mementoModified_ = measureTool_->GetMemento();
   }
 
 
   void EditLineMeasureCommand::SetEnd(ScenePoint2D scenePos)
   {
-    measureTool_->SetEnd(scenePos);
+    dynamic_cast<LineMeasureTool&>(*measureTool_).SetEnd(scenePos);
     mementoModified_ = measureTool_->GetMemento();
   }
 }
--- a/Framework/Scene2DViewport/EditLineMeasureCommand.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureCommand.h	Fri Oct 11 17:08:34 2019 +0200
@@ -27,8 +27,7 @@
   {
   public:
     EditLineMeasureCommand(
-      boost::shared_ptr<LineMeasureTool>  measureTool,
-      MessageBroker& broker,
+      boost::shared_ptr<MeasureTool>  measureTool,
       boost::weak_ptr<ViewportController> controllerW);
 
     void SetStart(ScenePoint2D scenePos);
@@ -39,7 +38,6 @@
     {
       return measureTool_;
     }
-    boost::shared_ptr<LineMeasureTool> measureTool_;
+    boost::shared_ptr<MeasureTool> measureTool_;
   };
 }
-
--- a/Framework/Scene2DViewport/EditLineMeasureTracker.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -27,8 +27,7 @@
 namespace OrthancStone
 {
   EditLineMeasureTracker::EditLineMeasureTracker(
-    boost::shared_ptr<LineMeasureTool>  measureTool,
-    MessageBroker& broker,
+    boost::shared_ptr<MeasureTool>  measureTool,
     boost::weak_ptr<ViewportController> controllerW,
     const PointerEvent& e) 
     : EditMeasureTracker(controllerW, e)
@@ -36,13 +35,9 @@
     ScenePoint2D scenePos = e.GetMainPosition().Apply(
       GetScene().GetCanvasToSceneTransform());
 
-    modifiedZone_ = measureTool->LineHitTest(scenePos);
+    modifiedZone_ = dynamic_cast<LineMeasureTool&>(*measureTool).LineHitTest(scenePos);
 
-    command_.reset(
-      new EditLineMeasureCommand(
-        measureTool,
-        broker,
-        controllerW));
+    command_.reset(new EditLineMeasureCommand(measureTool, controllerW));
   }
 
   EditLineMeasureTracker::~EditLineMeasureTracker()
--- a/Framework/Scene2DViewport/EditLineMeasureTracker.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureTracker.h	Fri Oct 11 17:08:34 2019 +0200
@@ -37,8 +37,7 @@
     must be supplied, too
     */
     EditLineMeasureTracker(
-      boost::shared_ptr<LineMeasureTool>  measureTool,
-      MessageBroker&                      broker,
+      boost::shared_ptr<MeasureTool>  measureTool,
       boost::weak_ptr<ViewportController> controllerW,
       const PointerEvent&                 e);
 
--- a/Framework/Scene2DViewport/LineMeasureTool.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/LineMeasureTool.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -148,7 +148,7 @@
         const PointerEvent & e);
     */
     boost::shared_ptr<EditLineMeasureTracker> editLineMeasureTracker(
-      new EditLineMeasureTracker(shared_from_this(), GetBroker(), GetController(), e));
+      new EditLineMeasureTracker(shared_from_this(), GetController(), e));
     return editLineMeasureTracker;
   }
 
--- a/Framework/Scene2DViewport/LineMeasureTool.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/LineMeasureTool.h	Fri Oct 11 17:08:34 2019 +0200
@@ -35,7 +35,7 @@
 
 namespace OrthancStone
 {
-  class LineMeasureTool : public MeasureTool, public boost::enable_shared_from_this<LineMeasureTool>
+  class LineMeasureTool : public MeasureTool
   {
   public:
     LineMeasureTool(MessageBroker& broker, boost::weak_ptr<ViewportController> controllerW);
--- a/Framework/Scene2DViewport/MeasureTool.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureTool.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -81,13 +81,12 @@
 
   MeasureTool::MeasureTool(MessageBroker& broker,
     boost::weak_ptr<ViewportController> controllerW)
-    : IObserver(broker)
-    , controllerW_(controllerW)
+    : controllerW_(controllerW)
     , enabled_(true)
   {
     GetController()->RegisterObserverCallback(
       new Callable<MeasureTool, ViewportController::SceneTransformChanged>
-      (*this, &MeasureTool::OnSceneTransformChanged));
+      (shared_from_this(), &MeasureTool::OnSceneTransformChanged));
   }
 
 
--- a/Framework/Scene2DViewport/MeasureTool.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureTool.h	Fri Oct 11 17:08:34 2019 +0200
@@ -38,7 +38,7 @@
   class IFlexiblePointerTracker;
   class MeasureToolMemento;
 
-  class MeasureTool : public IObserver
+  class MeasureTool : public ObserverBase<MeasureTool>
   {
   public:
     virtual ~MeasureTool();
--- a/Framework/Scene2DViewport/ViewportController.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/ViewportController.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -30,10 +30,8 @@
 namespace OrthancStone
 {
   ViewportController::ViewportController(boost::weak_ptr<UndoStack> undoStackW,
-                                         MessageBroker& broker,
                                          IViewport& viewport)
-    : IObservable(broker)
-    , undoStackW_(undoStackW)
+    : undoStackW_(undoStackW)
     , canvasToSceneFactor_(0.0)
     , viewport_(viewport)
   {
--- a/Framework/Scene2DViewport/ViewportController.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Framework/Scene2DViewport/ViewportController.h	Fri Oct 11 17:08:34 2019 +0200
@@ -81,7 +81,6 @@
       SceneTransformChanged, ViewportController);
 
     ViewportController(boost::weak_ptr<UndoStack> undoStackW,
-                       MessageBroker& broker,
                        IViewport& viewport);
 
 
--- a/Platforms/Generic/DelayedCallCommand.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/DelayedCallCommand.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -26,13 +26,11 @@
 
 namespace Deprecated
 {
-  DelayedCallCommand::DelayedCallCommand(OrthancStone::MessageBroker& broker,
-                                         OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback,  // takes ownership
+  DelayedCallCommand::DelayedCallCommand(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback,  // takes ownership
                                          unsigned int timeoutInMs,
                                          Orthanc::IDynamicObject* payload /* takes ownership */,
                                          OrthancStone::NativeStoneApplicationContext& context
                                          ) :
-    IObservable(broker),
     callback_(callback),
     payload_(payload),
     context_(context),
--- a/Platforms/Generic/DelayedCallCommand.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/DelayedCallCommand.h	Fri Oct 11 17:08:34 2019 +0200
@@ -42,8 +42,7 @@
     unsigned int                            timeoutInMs_;
 
   public:
-    DelayedCallCommand(OrthancStone::MessageBroker& broker,
-                       OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback,  // takes ownership
+    DelayedCallCommand(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback,  // takes ownership
                        unsigned int timeoutInMs,
                        Orthanc::IDynamicObject* payload /* takes ownership */,
                        OrthancStone::NativeStoneApplicationContext& context
--- a/Platforms/Generic/WebServiceCommandBase.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServiceCommandBase.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -25,8 +25,7 @@
 
 namespace Deprecated
 {
-  WebServiceCommandBase::WebServiceCommandBase(OrthancStone::MessageBroker& broker,
-                                               OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,
+  WebServiceCommandBase::WebServiceCommandBase(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,
                                                OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,
                                                const Orthanc::WebServiceParameters& parameters,
                                                const std::string& url,
@@ -34,7 +33,6 @@
                                                unsigned int timeoutInSeconds,
                                                Orthanc::IDynamicObject* payload /* takes ownership */,
                                                OrthancStone::NativeStoneApplicationContext& context) :
-    IObservable(broker),
     successCallback_(successCallback),
     failureCallback_(failureCallback),
     parameters_(parameters),
--- a/Platforms/Generic/WebServiceCommandBase.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServiceCommandBase.h	Fri Oct 11 17:08:34 2019 +0200
@@ -51,8 +51,7 @@
     unsigned int                            timeoutInSeconds_;
 
   public:
-    WebServiceCommandBase(OrthancStone::MessageBroker& broker,
-                          OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+    WebServiceCommandBase(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                           OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                           const Orthanc::WebServiceParameters& parameters,
                           const std::string& url,
--- a/Platforms/Generic/WebServiceDeleteCommand.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServiceDeleteCommand.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -25,8 +25,7 @@
 
 namespace Deprecated
 {
-  WebServiceDeleteCommand::WebServiceDeleteCommand(OrthancStone::MessageBroker& broker,
-                                                   OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+  WebServiceDeleteCommand::WebServiceDeleteCommand(OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                                                    OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                                                    const Orthanc::WebServiceParameters& parameters,
                                                    const std::string& url,
@@ -34,7 +33,7 @@
                                                    unsigned int timeoutInSeconds,
                                                    Orthanc::IDynamicObject* payload /* takes ownership */,
                                                    OrthancStone::NativeStoneApplicationContext& context) :
-    WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context)
+    WebServiceCommandBase(successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context)
   {
   }
 
--- a/Platforms/Generic/WebServiceDeleteCommand.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServiceDeleteCommand.h	Fri Oct 11 17:08:34 2019 +0200
@@ -28,8 +28,7 @@
   class WebServiceDeleteCommand : public WebServiceCommandBase
   {
   public:
-    WebServiceDeleteCommand(OrthancStone::MessageBroker& broker,
-                            OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+    WebServiceDeleteCommand(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                             OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                             const Orthanc::WebServiceParameters& parameters,
                             const std::string& url,
--- a/Platforms/Generic/WebServiceGetCommand.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServiceGetCommand.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -25,9 +25,7 @@
 
 namespace Deprecated
 {
-
-  WebServiceGetCommand::WebServiceGetCommand(OrthancStone::MessageBroker& broker,
-                                             OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+  WebServiceGetCommand::WebServiceGetCommand(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                                              OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                                              const Orthanc::WebServiceParameters& parameters,
                                              const std::string& url,
@@ -35,7 +33,7 @@
                                              unsigned int timeoutInSeconds,
                                              Orthanc::IDynamicObject* payload /* takes ownership */,
                                              OrthancStone::NativeStoneApplicationContext& context) :
-    WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context)
+    WebServiceCommandBase(successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context)
   {
   }
 
--- a/Platforms/Generic/WebServiceGetCommand.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServiceGetCommand.h	Fri Oct 11 17:08:34 2019 +0200
@@ -28,8 +28,7 @@
   class WebServiceGetCommand : public WebServiceCommandBase
   {
   public:
-    WebServiceGetCommand(OrthancStone::MessageBroker& broker,
-                         OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+    WebServiceGetCommand(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                          OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                          const Orthanc::WebServiceParameters& parameters,
                          const std::string& url,
--- a/Platforms/Generic/WebServicePostCommand.cpp	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServicePostCommand.cpp	Fri Oct 11 17:08:34 2019 +0200
@@ -25,8 +25,7 @@
 
 namespace Deprecated
 {
-  WebServicePostCommand::WebServicePostCommand(OrthancStone::MessageBroker& broker,
-                                               OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+  WebServicePostCommand::WebServicePostCommand(OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                                                OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                                                const Orthanc::WebServiceParameters& parameters,
                                                const std::string& url,
@@ -35,7 +34,7 @@
                                                const std::string& body,
                                                Orthanc::IDynamicObject* payload /* takes ownership */,
                                                OrthancStone::NativeStoneApplicationContext& context) :
-    WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context),
+    WebServiceCommandBase(successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context),
     body_(body)
   {
   }
--- a/Platforms/Generic/WebServicePostCommand.h	Fri Oct 11 13:38:35 2019 +0200
+++ b/Platforms/Generic/WebServicePostCommand.h	Fri Oct 11 17:08:34 2019 +0200
@@ -31,8 +31,7 @@
     std::string  body_;
 
   public:
-    WebServicePostCommand(OrthancStone::MessageBroker& broker,
-                          OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+    WebServicePostCommand(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
                           OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
                           const Orthanc::WebServiceParameters& parameters,
                           const std::string& url,
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Fri Oct 11 13:38:35 2019 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Fri Oct 11 17:08:34 2019 +0200
@@ -452,7 +452,6 @@
   ${ORTHANC_STONE_ROOT}/Framework/Messages/ICallable.h
   ${ORTHANC_STONE_ROOT}/Framework/Messages/IMessage.h
   ${ORTHANC_STONE_ROOT}/Framework/Messages/IObservable.cpp
-  ${ORTHANC_STONE_ROOT}/Framework/Messages/IObserver.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Messages/IObserver.h
   ${ORTHANC_STONE_ROOT}/Framework/Messages/MessageBroker.h
   ${ORTHANC_STONE_ROOT}/Framework/Messages/MessageForwarder.cpp