changeset 61:ca644004d2ee wasm

MAJOR - removal of Start/Stop and observers in IWidget
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 10 May 2017 17:55:13 +0200
parents 288c948199e5
children 16af9311238e
files Applications/BasicApplicationContext.cpp Applications/IBasicApplication.cpp Applications/Sdl/SdlEngine.cpp CMakeLists.txt Framework/Viewport/IViewport.h Framework/Viewport/WidgetViewport.cpp Framework/Viewport/WidgetViewport.h Framework/Widgets/EmptyWidget.h Framework/Widgets/IWidget.h Framework/Widgets/LayeredSceneWidget.cpp Framework/Widgets/LayeredSceneWidget.h Framework/Widgets/LayoutWidget.cpp Framework/Widgets/LayoutWidget.h Framework/Widgets/WidgetBase.cpp Framework/Widgets/WidgetBase.h Framework/Widgets/WorldSceneWidget.cpp Framework/Widgets/WorldSceneWidget.h
diffstat 17 files changed, 145 insertions(+), 355 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/BasicApplicationContext.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Applications/BasicApplicationContext.cpp	Wed May 10 17:55:13 2017 +0200
@@ -32,6 +32,7 @@
     while (!that->stopped_)
     {
       {
+        printf("GOSH\n"); fflush(stdout);
         ViewportLocker locker(*that);
         locker.GetViewport().UpdateContent();
       }
@@ -136,8 +137,6 @@
       (*it)->Start();
     }
 
-    viewport_.Start();
-
     if (viewport_.HasUpdateContent())
     {
       stopped_ = false;
@@ -155,8 +154,6 @@
       updateThread_.join();
     }
     
-    viewport_.Stop();
-
     for (Volumes::iterator it = volumes_.begin(); it != volumes_.end(); ++it)
     {
       assert(*it != NULL);
--- a/Applications/IBasicApplication.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Applications/IBasicApplication.cpp	Wed May 10 17:55:13 2017 +0200
@@ -226,8 +226,6 @@
         title = "Stone of Orthanc";
       }
 
-      context.Start();
-
       {
         /**************************************************************
          * Run the application inside a SDL window
@@ -238,9 +236,23 @@
         SdlWindow window(title.c_str(), width, height, opengl);
         SdlEngine sdl(window, context);
 
+        {
+          BasicApplicationContext::ViewportLocker locker(context);
+          locker.GetViewport().Register(sdl);  // (*)
+        }
+
+        context.Start();
         sdl.Run();
 
         LOG(WARNING) << "Stopping the application";
+
+        // Don't move the "Stop()" command below out of the block,
+        // otherwise the application might crash, because the
+        // "SdlEngine" is an observer of the viewport (*) and the
+        // update thread started by "context.Start()" would call a
+        // destructed object (the "SdlEngine" is deleted with the
+        // lexical scope).
+        context.Stop();
       }
 
 
@@ -248,15 +260,7 @@
        * Finalize the application
        ****************************************************************/
 
-      context.Stop();
-
       LOG(WARNING) << "The application has stopped";
-
-      {
-        BasicApplicationContext::ViewportLocker locker(context);
-        locker.GetViewport().ResetStatusBar();
-      }
-      
       application.Finalize();
     }
     catch (Orthanc::OrthancException& e)
--- a/Applications/Sdl/SdlEngine.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Applications/Sdl/SdlEngine.cpp	Wed May 10 17:55:13 2017 +0200
@@ -105,20 +105,11 @@
     surface_(window),
     viewportChanged_(true)
   {
-    {
-      BasicApplicationContext::ViewportLocker locker(context_);
-      SetSize(locker, window_.GetWidth(), window_.GetHeight());
-      locker.GetViewport().Register(*this);
-    }
   }
   
 
   SdlEngine::~SdlEngine()
   {
-    {
-      BasicApplicationContext::ViewportLocker locker(context_);
-      locker.GetViewport().Unregister(*this);
-    }
   }
 
 
@@ -127,6 +118,12 @@
     int scancodeCount = 0;
     const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
 
+    {
+      BasicApplicationContext::ViewportLocker locker(context_);
+      SetSize(locker, window_.GetWidth(), window_.GetHeight());
+      locker.GetViewport().SetDefaultView();
+    }
+    
     bool stop = false;
     while (!stop)
     {
@@ -250,6 +247,8 @@
         }
       }
     }
+
+    printf("BYE\n"); fflush(stdout);
   }
 
 
--- a/CMakeLists.txt	Wed May 10 16:10:47 2017 +0200
+++ b/CMakeLists.txt	Wed May 10 17:55:13 2017 +0200
@@ -33,11 +33,11 @@
 
 BuildSample(OrthancStoneEmpty 1)
 BuildSample(OrthancStoneTestPattern 2)
-BuildSample(OrthancStoneSingleFrame 3)
-BuildSample(OrthancStoneSingleVolume 4)
-BuildSample(OrthancStoneBasicPetCtFusion 5)
-BuildSample(OrthancStoneSynchronizedSeries 6)
-BuildSample(OrthancStoneLayoutPetCtFusion 7)
+#BuildSample(OrthancStoneSingleFrame 3)
+#BuildSample(OrthancStoneSingleVolume 4)
+#BuildSample(OrthancStoneBasicPetCtFusion 5)
+#BuildSample(OrthancStoneSynchronizedSeries 6)
+#BuildSample(OrthancStoneLayoutPetCtFusion 7)
 
 
 #####################################################################
--- a/Framework/Viewport/IViewport.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Viewport/IViewport.h	Wed May 10 17:55:13 2017 +0200
@@ -28,6 +28,8 @@
 
 namespace OrthancStone
 {
+  class IWidget;   // Forward declaration
+  
   class IViewport : public boost::noncopyable
   {
   public:
@@ -45,18 +47,12 @@
     {
     }
 
-    virtual void Register(IChangeObserver& observer) = 0;
+    virtual void SetDefaultView() = 0;
 
-    virtual void Unregister(IChangeObserver& observer) = 0;
+    virtual void Register(IChangeObserver& observer) = 0;
 
     virtual void SetStatusBar(IStatusBar& statusBar) = 0;
 
-    virtual void ResetStatusBar() = 0;
-
-    virtual void Start() = 0;
-
-    virtual void Stop() = 0;
-
     virtual void SetSize(unsigned int width,
                          unsigned int height) = 0;
 
@@ -88,5 +84,8 @@
     virtual bool HasUpdateContent() = 0;
 
     virtual void UpdateContent() = 0;
+
+    // Should only be called from IWidget
+    virtual void NotifyChange(const IWidget& widget) = 0;
   };
 }
--- a/Framework/Viewport/WidgetViewport.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Viewport/WidgetViewport.cpp	Wed May 10 17:55:13 2017 +0200
@@ -26,28 +26,25 @@
 
 namespace OrthancStone
 {
-  void WidgetViewport::UnregisterCentralWidget()
-  {
-    mouseTracker_.reset(NULL);
-
-    if (centralWidget_.get() != NULL)
-    {
-      centralWidget_->Unregister(*this);
-    }
-  }
-
-
   WidgetViewport::WidgetViewport() :
     statusBar_(NULL),
     isMouseOver_(false),
     lastMouseX_(0),
     lastMouseY_(0),
-    backgroundChanged_(false),
-    started_(false)
+    backgroundChanged_(false)
   {
   }
 
 
+  void WidgetViewport::SetDefaultView()
+  {
+    if (centralWidget_.get() != NULL)
+    {
+      centralWidget_->SetDefaultView();
+    }
+  }
+
+
   void WidgetViewport::SetStatusBar(IStatusBar& statusBar)
   {
     statusBar_ = &statusBar;
@@ -59,39 +56,19 @@
   }
 
 
-  void WidgetViewport::ResetStatusBar()
-  {
-    statusBar_ = NULL;
-
-    if (centralWidget_.get() != NULL)
-    {
-      centralWidget_->ResetStatusBar();
-    }
-  }
-
-
   IWidget& WidgetViewport::SetCentralWidget(IWidget* widget)
   {
-    if (started_)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
     if (widget == NULL)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
 
-    UnregisterCentralWidget();
+    mouseTracker_.reset(NULL);
       
     centralWidget_.reset(widget);
-    centralWidget_->Register(*this);
+    centralWidget_->SetViewport(*this);
 
-    if (statusBar_ == NULL)
-    {
-      centralWidget_->ResetStatusBar();
-    }
-    else
+    if (statusBar_ != NULL)
     {
       centralWidget_->SetStatusBar(*statusBar_);
     }
@@ -109,28 +86,6 @@
   }
 
 
-  void WidgetViewport::Start()
-  {
-    if (centralWidget_.get() != NULL)
-    {
-      centralWidget_->Start();
-    }
-
-    started_ = true;
-  }
-
-
-  void WidgetViewport::Stop()
-  {
-    started_ = false;
-
-    if (centralWidget_.get() != NULL)
-    {
-      centralWidget_->Stop();
-    }
-  }
-
-
   void WidgetViewport::SetSize(unsigned int width,
                                unsigned int height)
   {
@@ -147,8 +102,7 @@
 
   bool WidgetViewport::Render(Orthanc::ImageAccessor& surface)
   {
-    if (!started_ ||
-        centralWidget_.get() == NULL)
+    if (centralWidget_.get() == NULL)
     {
       return false;
     }
@@ -187,11 +141,6 @@
                                  int y,
                                  KeyboardModifiers modifiers)
   {
-    if (!started_)
-    {
-      return;
-    }
-
     lastMouseX_ = x;
     lastMouseY_ = y;
 
@@ -210,11 +159,6 @@
 
   void WidgetViewport::MouseUp()
   {
-    if (!started_)
-    {
-      return;
-    }
-
     if (mouseTracker_.get() != NULL)
     {
       mouseTracker_->MouseUp();
@@ -227,7 +171,7 @@
   void WidgetViewport::MouseMove(int x, 
                                  int y) 
   {
-    if (!started_)
+    if (centralWidget_.get() == NULL)
     {
       return;
     }
@@ -266,8 +210,7 @@
   {
     isMouseOver_ = false;
 
-    if (started_ &&
-        mouseTracker_.get() != NULL)
+    if (mouseTracker_.get() != NULL)
     {
       mouseTracker_->MouseUp();
       mouseTracker_.reset(NULL);
@@ -282,11 +225,6 @@
                                   int y,
                                   KeyboardModifiers modifiers)
   {
-    if (!started_)
-    {
-      return;
-    }
-
     if (centralWidget_.get() != NULL &&
         mouseTracker_.get() == NULL)
     {
--- a/Framework/Viewport/WidgetViewport.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Viewport/WidgetViewport.h	Wed May 10 17:55:13 2017 +0200
@@ -29,9 +29,7 @@
 
 namespace OrthancStone
 {
-  class WidgetViewport : 
-    public IViewport,
-    public IWidget::IChangeObserver    
+  class WidgetViewport : public IViewport
   {
   private:
     std::auto_ptr<IWidget>        centralWidget_;
@@ -43,22 +41,14 @@
     int                           lastMouseY_;
     CairoSurface                  background_;
     bool                          backgroundChanged_;
-    bool                          started_;
-
-    void UnregisterCentralWidget();
 
   public:
     WidgetViewport();
 
-    virtual ~WidgetViewport()
-    {
-      UnregisterCentralWidget();
-    }
+    virtual void SetDefaultView();
 
     virtual void SetStatusBar(IStatusBar& statusBar);
 
-    virtual void ResetStatusBar();
-
     IWidget& SetCentralWidget(IWidget* widget);  // Takes ownership
 
     virtual void NotifyChange(const IWidget& widget);
@@ -68,15 +58,6 @@
       observers_.Register(observer);
     }
 
-    virtual void Unregister(IViewport::IChangeObserver& observer)
-    {
-      observers_.Unregister(observer);
-    }
-
-    virtual void Start();
-
-    virtual void Stop();
-
     virtual void SetSize(unsigned int width,
                          unsigned int height);
 
--- a/Framework/Widgets/EmptyWidget.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/EmptyWidget.h	Wed May 10 17:55:13 2017 +0200
@@ -46,27 +46,23 @@
     {
     }
 
-    virtual void SetStatusBar(IStatusBar& statusBar)
+    virtual void SetDefaultView()
     {
     }
-
-    virtual void ResetStatusBar()
+  
+    virtual void SetParent(OrthancStone::IWidget& widget)
+    {
+    }
+    
+    virtual void SetViewport(IViewport& viewport)
     {
     }
 
-    virtual void Register(IChangeObserver& observer)
+    virtual void NotifyChange()
     {
     }
 
-    virtual void Unregister(IChangeObserver& observer)
-    {
-    }
-
-    virtual void Start()
-    {
-    }
-
-    virtual void Stop()
+    virtual void SetStatusBar(IStatusBar& statusBar)
     {
     }
 
--- a/Framework/Widgets/IWidget.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/IWidget.h	Wed May 10 17:55:13 2017 +0200
@@ -24,37 +24,24 @@
 #include "../Enumerations.h"
 #include "../Viewport/IMouseTracker.h"
 #include "../Viewport/IStatusBar.h"
+#include "../Viewport/IViewport.h"
 
 namespace OrthancStone
 {
   class IWidget : public boost::noncopyable
   {
   public:
-    class IChangeObserver : public boost::noncopyable
-    {
-    public:
-      virtual ~IChangeObserver()
-      {
-      }
-      
-      virtual void NotifyChange(const IWidget& widget) = 0;
-    };
-
     virtual ~IWidget()
     {
     }
 
-    virtual void SetStatusBar(IStatusBar& statusBar) = 0;
-
-    virtual void ResetStatusBar() = 0;
-
-    virtual void Register(IChangeObserver& observer) = 0;
+    virtual void SetDefaultView() = 0;
 
-    virtual void Unregister(IChangeObserver& observer) = 0;
+    virtual void SetParent(IWidget& parent) = 0;
+    
+    virtual void SetViewport(IViewport& viewport) = 0;
 
-    virtual void Start() = 0;
-
-    virtual void Stop() = 0;
+    virtual void SetStatusBar(IStatusBar& statusBar) = 0;
 
     virtual void SetSize(unsigned int width, 
                          unsigned int height) = 0;
@@ -83,5 +70,7 @@
     virtual bool HasUpdateContent() const = 0;
 
     virtual void UpdateContent() = 0;
+
+    virtual void NotifyChange() = 0;
   };
 }
--- a/Framework/Widgets/LayeredSceneWidget.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/LayeredSceneWidget.cpp	Wed May 10 17:55:13 2017 +0200
@@ -395,7 +395,6 @@
   bool LayeredSceneWidget::RenderScene(CairoContext& context,
                                        const ViewportGeometry& view) 
   {
-    assert(IsStarted());
     return renderers_->RenderScene(context, view);
   }
 
@@ -490,12 +489,6 @@
   ILayerRendererFactory& LayeredSceneWidget::AddLayer(size_t& layerIndex,
                                                       ILayerRendererFactory* factory)
   {
-    if (IsStarted())
-    {
-      // Start() has already been invoked
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
     layerIndex = layers_.size();
     layers_.push_back(new Layer(factory, *pendingLayers_, layers_.size()));
 
@@ -586,14 +579,9 @@
   }
 
 
+#if 0
   void LayeredSceneWidget::Start()
   {
-    if (IsStarted())
-    {
-      // Start() has already been invoked
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
     for (size_t i = 0; i < layers_.size(); i++)
     {
       layers_[i]->Start();
@@ -610,14 +598,7 @@
 
   void LayeredSceneWidget::Stop()
   {
-    if (!IsStarted())
-    {
-      // Stop() has already been invoked
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
     pendingLayers_->Stop();
-    WorldSceneWidget::Stop();
 
     renderers_.reset(NULL);
     pendingRenderers_.reset(NULL);
@@ -627,4 +608,5 @@
       layers_[i]->Stop();
     }
   }
+#endif
 }
--- a/Framework/Widgets/LayeredSceneWidget.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/LayeredSceneWidget.h	Wed May 10 17:55:13 2017 +0200
@@ -24,6 +24,7 @@
 #include "WorldSceneWidget.h"
 
 #include "../Layers/ILayerRendererFactory.h"
+#include "../Toolbox/ObserversRegistry.h"
 
 #include <boost/thread/mutex.hpp>  // TODO remove
 
@@ -97,10 +98,6 @@
 
     void InvalidateAllLayers();
 
-    virtual void Start();
-
-    virtual void Stop();
-
     using WorldSceneWidget::Register;
     using WorldSceneWidget::Unregister;
 
--- a/Framework/Widgets/LayoutWidget.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/LayoutWidget.cpp	Wed May 10 17:55:13 2017 +0200
@@ -269,7 +269,6 @@
 
   LayoutWidget::LayoutWidget() :
     isHorizontal_(true),
-    started_(false),
     width_(0),
     height_(0),
     paddingLeft_(0),
@@ -285,12 +284,20 @@
   {
     for (size_t i = 0; i < children_.size(); i++)
     {
-      children_[i]->GetWidget().Unregister(*this);
       delete children_[i];
     }
   }
 
 
+  void LayoutWidget::SetDefaultView()
+  {
+    for (size_t i = 0; i < children_.size(); i++)
+    {
+      children_[i]->GetWidget().SetDefaultView();
+    }
+  }
+  
+
   void LayoutWidget::NotifyChange(const IWidget& widget)
   {
     // One of the children has changed
@@ -338,12 +345,6 @@
 
   IWidget& LayoutWidget::AddWidget(IWidget* widget)  // Takes ownership
   {
-    if (started_)
-    {
-      LOG(ERROR) << "Cannot add child once Start() has been invoked";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
     if (widget == NULL)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
@@ -353,13 +354,9 @@
     {
       widget->SetStatusBar(*GetStatusBar());
     }
-    else
-    {
-      widget->ResetStatusBar();
-    }
 
     children_.push_back(new ChildWidget(widget));
-    widget->Register(*this);
+    widget->SetParent(*this);
 
     ComputeChildrenExtents();
 
@@ -383,39 +380,6 @@
   }
 
 
-  void LayoutWidget::ResetStatusBar()
-  {
-    WidgetBase::ResetStatusBar();
-
-    for (size_t i = 0; i < children_.size(); i++)
-    {
-      children_[i]->GetWidget().ResetStatusBar();
-    }
-  }  
-
-
-  void LayoutWidget::Start()
-  {
-    for (size_t i = 0; i < children_.size(); i++)
-    {
-      children_[i]->GetWidget().Start();
-    }
-
-    WidgetBase::Start();
-  }
-
-
-  void LayoutWidget::Stop()
-  {
-    WidgetBase::Stop();
-
-    for (size_t i = 0; i < children_.size(); i++)
-    {
-      children_[i]->GetWidget().Stop();
-    }
-  }
-
-
   void LayoutWidget::SetSize(unsigned int width,
                              unsigned int height)
   {
--- a/Framework/Widgets/LayoutWidget.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/LayoutWidget.h	Wed May 10 17:55:13 2017 +0200
@@ -28,9 +28,7 @@
 
 namespace OrthancStone
 {
-  class LayoutWidget : 
-    public WidgetBase,
-    public IWidget::IChangeObserver
+  class LayoutWidget : public WidgetBase
   {
   private:
     class LayoutMouseTracker;
@@ -38,7 +36,6 @@
 
     std::vector<ChildWidget*>     children_;
     bool                          isHorizontal_;
-    bool                          started_;
     unsigned int                  width_;
     unsigned int                  height_;
     std::auto_ptr<IMouseTracker>  mouseTracker_;
@@ -56,6 +53,8 @@
 
     virtual ~LayoutWidget();
 
+    virtual void SetDefaultView();
+
     virtual void NotifyChange(const IWidget& widget);
 
     void SetHorizontal();
@@ -99,12 +98,6 @@
 
     virtual void SetStatusBar(IStatusBar& statusBar);
 
-    virtual void ResetStatusBar();
-
-    virtual void Start();
-
-    virtual void Stop();
-
     virtual void SetSize(unsigned int width,
                          unsigned int height);
 
--- a/Framework/Widgets/WidgetBase.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/WidgetBase.cpp	Wed May 10 17:55:13 2017 +0200
@@ -27,6 +27,33 @@
 
 namespace OrthancStone
 {
+  void WidgetBase::NotifyChange()
+  {
+    if (parent_ != NULL)
+    {
+      parent_->NotifyChange();
+    }
+
+    if (viewport_ != NULL)
+    {
+      viewport_->NotifyChange(*this);
+    }
+  }
+
+
+  void WidgetBase::SetParent(IWidget& parent)
+  {
+    if (parent_ != NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      parent_ = &parent;
+    }
+  }    
+
+  
   void WidgetBase::ClearBackgroundOrthanc(Orthanc::ImageAccessor& target) const 
   {
     // Clear the background using Orthanc
@@ -65,12 +92,6 @@
   }
 
 
-  void WidgetBase::NotifyChange()
-  {
-    observers_.NotifyChange(this);
-  }
-
-
   void WidgetBase::UpdateStatusBar(const std::string& message)
   {
     if (statusBar_ != NULL)
@@ -81,8 +102,9 @@
 
 
   WidgetBase::WidgetBase() :
+    parent_(NULL),
+    viewport_(NULL),
     statusBar_(NULL),
-    started_(false),
     backgroundCleared_(false)
   {
     backgroundColor_[0] = 0;
@@ -91,6 +113,19 @@
   }
 
 
+  void WidgetBase::SetViewport(IViewport& viewport)
+  {
+    if (viewport_ != NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      viewport_ = &viewport;
+    }
+  }
+
+  
   void WidgetBase::SetBackgroundColor(uint8_t red,
                                       uint8_t green,
                                       uint8_t blue)
@@ -110,61 +145,8 @@
   }
 
 
-  void WidgetBase::Register(IChangeObserver& observer)
-  {
-    if (started_)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    observers_.Register(observer);
-  }
-
-
-  void WidgetBase::Unregister(IChangeObserver& observer)
-  {
-    if (started_)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    observers_.Unregister(observer);
-  }
-
-
-  void WidgetBase::Start()
-  {
-    if (started_)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-    else
-    {
-      started_ = true;
-    }
-  }
-
-  
-  void WidgetBase::Stop()
-  {
-    if (started_)
-    {
-      started_ = false;
-    }
-    else
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-  }
-
-  
   bool WidgetBase::Render(Orthanc::ImageAccessor& surface)
   {
-    if (!started_)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-    
 #if 0
     ClearBackgroundOrthanc(surface);
 #else
--- a/Framework/Widgets/WidgetBase.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/WidgetBase.h	Wed May 10 17:55:13 2017 +0200
@@ -24,18 +24,17 @@
 #include "IWidget.h"
 
 #include "../Viewport/CairoContext.h"
-#include "../Toolbox/ObserversRegistry.h"
 
 namespace OrthancStone
 {
   class WidgetBase : public IWidget
   {
   private:
-    IStatusBar*                  statusBar_;
-    ObserversRegistry<IWidget>   observers_;
-    bool                         started_;
-    bool                         backgroundCleared_;
-    uint8_t                      backgroundColor_[3];
+    IWidget*     parent_;
+    IViewport*   viewport_;
+    IStatusBar*  statusBar_;
+    bool         backgroundCleared_;
+    uint8_t      backgroundColor_[3];
 
   protected:
     void ClearBackgroundOrthanc(Orthanc::ImageAccessor& target) const;
@@ -44,8 +43,6 @@
 
     void ClearBackgroundCairo(Orthanc::ImageAccessor& target) const;
 
-    void NotifyChange();
-
     void UpdateStatusBar(const std::string& message);
 
     IStatusBar* GetStatusBar() const
@@ -53,14 +50,17 @@
       return statusBar_;
     }
 
-    bool IsStarted() const
-    {
-      return started_;
-    }
-
   public:
     WidgetBase();
 
+    virtual void SetDefaultView()
+    {
+    }
+  
+    virtual void SetParent(IWidget& parent);
+    
+    virtual void SetViewport(IViewport& viewport);
+
     void SetBackgroundCleared(bool clear)
     {
       backgroundCleared_ = clear;
@@ -79,24 +79,11 @@
                             uint8_t& green,
                             uint8_t& blue) const;
 
-    virtual void Register(IChangeObserver& observer);
-
-    virtual void Unregister(IChangeObserver& observer);
-    
     virtual void SetStatusBar(IStatusBar& statusBar)
     {
       statusBar_ = &statusBar;
     }
 
-    virtual void ResetStatusBar()
-    {
-      statusBar_ = NULL;
-    }    
-
-    virtual void Start();
-
-    virtual void Stop();
-
     virtual bool Render(Orthanc::ImageAccessor& surface);
 
     virtual bool HasUpdateContent() const
@@ -110,5 +97,7 @@
     {
       return false;
     }
+
+    virtual void NotifyChange();
   };
 }
--- a/Framework/Widgets/WorldSceneWidget.cpp	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/WorldSceneWidget.cpp	Wed May 10 17:55:13 2017 +0200
@@ -282,26 +282,10 @@
 
   void WorldSceneWidget::SetInteractor(IWorldSceneInteractor& interactor)
   {
-    if (IsStarted())
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
     interactor_ = &interactor;
   }
 
 
-  void WorldSceneWidget::Start()
-  {
-    SetSceneExtent(view_);
-    
-    WidgetBase::Start();
-
-    ViewChangeFunctor functor(view_);
-    observers_.Notify(this, functor);
-  }
-      
-
   void WorldSceneWidget::SetDefaultView()
   {
     SetSceneExtent(view_);
--- a/Framework/Widgets/WorldSceneWidget.h	Wed May 10 16:10:47 2017 +0200
+++ b/Framework/Widgets/WorldSceneWidget.h	Wed May 10 17:55:13 2017 +0200
@@ -24,6 +24,7 @@
 #include "CairoWidget.h"
 #include "IWorldSceneInteractor.h"
 
+#include "../Toolbox/ObserversRegistry.h"
 #include "../Toolbox/ViewportGeometry.h"
 
 namespace OrthancStone
@@ -83,9 +84,6 @@
     {
     }
 
-    using WidgetBase::Register;
-    using WidgetBase::Unregister;
-
     void Register(IWorldObserver& observer)
     {
       observers_.Register(observer);
@@ -101,9 +99,7 @@
 
     void SetInteractor(IWorldSceneInteractor& interactor);
 
-    virtual void Start();
-      
-    void SetDefaultView();
+    virtual void SetDefaultView();
 
     void SetView(const ViewportGeometry& view);