diff Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp @ 1804:5a872e69c74f

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 May 2021 14:48:51 +0200
parents d1849468729b
children de7cea710008
line wrap: on
line diff
--- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp	Thu May 20 14:15:00 2021 +0200
+++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp	Thu May 20 14:48:51 2021 +0200
@@ -24,10 +24,10 @@
 #include "../../Common/SampleHelpers.h"
 
 #include "../../../../OrthancStone/Sources/Loaders/GenericLoadersContext.h"
+#include "../../../../OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h"
 #include "../../../../OrthancStone/Sources/Scene2DViewport/AngleMeasureTool.h"
 #include "../../../../OrthancStone/Sources/Scene2DViewport/LineMeasureTool.h"
 #include "../../../../OrthancStone/Sources/Scene2DViewport/UndoStack.h"
-#include "../../../../OrthancStone/Sources/StoneEnumerations.h"
 #include "../../../../OrthancStone/Sources/StoneException.h"
 #include "../../../../OrthancStone/Sources/StoneInitialization.h"
 #include "../../../../OrthancStone/Sources/Viewport/DefaultViewportInteractor.h"
@@ -43,1585 +43,9 @@
 #include <string>
 
 
-
-#if 1
-#include "../../../../OrthancStone/Sources/Scene2D/MacroSceneLayer.h"
-
-#include <boost/math/constants/constants.hpp>
-
-static const double HANDLE_SIZE = 10.0;
-static const double PI = boost::math::constants::pi<double>();
-
-static const char* const KEY_ANNOTATIONS = "annotations";
-static const char* const KEY_TYPE = "type";
-static const char* const KEY_X1 = "x1";
-static const char* const KEY_Y1 = "y1";
-static const char* const KEY_X2 = "x2";
-static const char* const KEY_Y2 = "y2";
-static const char* const KEY_X3 = "x3";
-static const char* const KEY_Y3 = "y3";
-
-static const char* const VALUE_ANGLE = "angle";
-static const char* const VALUE_CIRCLE = "circle";
-static const char* const VALUE_SEGMENT = "segment";
-
-
-namespace OrthancStone
-{
-  class AnnotationsLayer : public IObservable
-  {
-  public:
-    ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, AnnotationAddedMessage, AnnotationsLayer);
-    ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, AnnotationRemovedMessage, AnnotationsLayer);
-
-    enum Tool
-    {
-      Tool_Edit,
-      Tool_None,
-      Tool_Segment,
-      Tool_Angle,
-      Tool_Circle,
-      Tool_Erase
-    };
-    
-  private:
-    class Annotation;
-    
-    class GeometricPrimitive : public boost::noncopyable
-    {
-    private:
-      bool         modified_;
-      Annotation&  parentAnnotation_;
-      Color        color_;
-      Color        hoverColor_;
-      bool         isHover_;
-      int          depth_;
-
-    public:
-      GeometricPrimitive(Annotation& parentAnnotation,
-                         int depth) :
-        modified_(true),
-        parentAnnotation_(parentAnnotation),
-        color_(192, 192, 192),
-        hoverColor_(0, 255, 0),
-        isHover_(false),
-        depth_(depth)
-      {
-      }
-      
-      virtual ~GeometricPrimitive()
-      {
-      }
-
-      Annotation& GetParentAnnotation() const
-      {
-        return parentAnnotation_;
-      }
-      
-      int GetDepth() const
-      {
-        return depth_;
-      }
-
-      void SetHover(bool hover)
-      {
-        if (hover != isHover_)
-        {
-          isHover_ = hover;
-          modified_ = true;
-        }
-      }
-
-      bool IsHover() const
-      {
-        return isHover_;
-      }
-      
-      void SetModified(bool modified)
-      {
-        modified_ = modified;
-      }
-      
-      bool IsModified() const
-      {
-        return modified_;
-      }
-
-      void SetColor(const Color& color)
-      {
-        SetModified(true);
-        color_ = color;
-      }
-
-      void SetHoverColor(const Color& color)
-      {
-        SetModified(true);
-        hoverColor_ = color;
-      }
-
-      const Color& GetColor() const
-      {
-        return color_;
-      }
-
-      const Color& GetHoverColor() const
-      {
-        return hoverColor_;
-      }
-
-      virtual bool IsHit(const ScenePoint2D& p,
-                         const Scene2D& scene) const = 0;
-
-      // Always called, even if not modified
-      virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
-                                       const Scene2D& scene) = 0;
-
-      // Only called if modified
-      virtual void RenderOtherLayers(MacroSceneLayer& macro,
-                                     const Scene2D& scene) = 0;
-
-      virtual void MovePreview(const ScenePoint2D& delta) = 0;
-
-      virtual void MoveDone(const ScenePoint2D& delta) = 0;
-    };
-    
-
-    class Annotation : public boost::noncopyable
-    {
-    private:
-      typedef std::list<GeometricPrimitive*>  GeometricPrimitives;
-      
-      AnnotationsLayer&    that_;
-      GeometricPrimitives  primitives_;
-      
-    public:
-      Annotation(AnnotationsLayer& that) :
-        that_(that)
-      {
-        that.AddAnnotation(this);
-      }
-      
-      virtual ~Annotation()
-      {
-        for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
-        {
-          that_.DeletePrimitive(*it);
-        }
-      }
-
-      GeometricPrimitive* AddPrimitive(GeometricPrimitive* primitive)
-      {
-        if (primitive == NULL)
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
-        }
-        else
-        {
-          assert(that_.primitives_.find(primitive) == that_.primitives_.end());
-          primitives_.push_back(primitive);  // For automated deallocation
-          that_.primitives_.insert(primitive);
-          return primitive;
-        }
-      }
-
-      template <typename T>
-      T& AddTypedPrimitive(T* primitive)
-      {
-        AddPrimitive(primitive);
-        return *primitive;
-      }
-
-      virtual void SignalMove(GeometricPrimitive& primitive) = 0;
-
-      virtual void Serialize(Json::Value& target) = 0;
-    };
-
-
-    class Handle : public GeometricPrimitive
-    {
-    private:
-      ScenePoint2D  center_;
-      ScenePoint2D  delta_;
-
-    public:
-      explicit Handle(Annotation& parentAnnotation,
-                      const ScenePoint2D& center) :
-        GeometricPrimitive(parentAnnotation, 0),  // Highest priority
-        center_(center),
-        delta_(0, 0)
-      {
-      }
-
-      void SetSize(unsigned int size)
-      {
-        SetModified(true);
-      }
-
-      void SetCenter(const ScenePoint2D& center)
-      {
-        SetModified(true);
-        center_ = center;
-        delta_ = ScenePoint2D(0, 0);
-      }
-
-      ScenePoint2D GetCenter() const
-      {
-        return center_ + delta_;
-      }
-
-      virtual bool IsHit(const ScenePoint2D& p,
-                         const Scene2D& scene) const
-      {
-        const double zoom = scene.GetSceneToCanvasTransform().ComputeZoom();
-
-        double dx = (center_.GetX() + delta_.GetX() - p.GetX()) * zoom;
-        double dy = (center_.GetY() + delta_.GetY() - p.GetY()) * zoom;
-
-        return (std::abs(dx) <= HANDLE_SIZE / 2.0 &&
-                std::abs(dy) <= HANDLE_SIZE / 2.0);
-      }
-
-      virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
-                                       const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-        const double zoom = scene.GetSceneToCanvasTransform().ComputeZoom();
-
-        // TODO: take DPI into account 
-        double x1 = center_.GetX() + delta_.GetX() - (HANDLE_SIZE / 2.0) / zoom;
-        double y1 = center_.GetY() + delta_.GetY() - (HANDLE_SIZE / 2.0) / zoom;
-        double x2 = center_.GetX() + delta_.GetX() + (HANDLE_SIZE / 2.0) / zoom;
-        double y2 = center_.GetY() + delta_.GetY() + (HANDLE_SIZE / 2.0) / zoom;
-
-        PolylineSceneLayer::Chain chain;
-        chain.reserve(4);
-        chain.push_back(ScenePoint2D(x1, y1));
-        chain.push_back(ScenePoint2D(x2, y1));
-        chain.push_back(ScenePoint2D(x2, y2));
-        chain.push_back(ScenePoint2D(x1, y2));
-
-        if (IsHover())
-        {
-          polyline.AddChain(chain, true /* closed */, GetHoverColor());
-        }
-        else
-        {
-          polyline.AddChain(chain, true /* closed */, GetColor());
-        }
-      }
-      
-      virtual void RenderOtherLayers(MacroSceneLayer& macro,
-                                     const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        SetModified(true);
-        delta_ = delta;
-        GetParentAnnotation().SignalMove(*this);
-      }
-
-      virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        SetModified(true);
-        center_ = center_ + delta;
-        delta_ = ScenePoint2D(0, 0);
-        GetParentAnnotation().SignalMove(*this);
-      }
-    };
-
-    
-    class Segment : public GeometricPrimitive
-    {
-    private:
-      ScenePoint2D  p1_;
-      ScenePoint2D  p2_;
-      ScenePoint2D  delta_;
-      
-    public:
-      Segment(Annotation& parentAnnotation,
-              const ScenePoint2D& p1,
-              const ScenePoint2D& p2) :
-        GeometricPrimitive(parentAnnotation, 1),  // Can only be selected if no handle matches
-        p1_(p1),
-        p2_(p2),
-        delta_(0, 0)
-      {
-      }
-
-      void SetPosition(const ScenePoint2D& p1,
-                       const ScenePoint2D& p2)
-      {
-        SetModified(true);
-        p1_ = p1;
-        p2_ = p2;
-        delta_ = ScenePoint2D(0, 0);
-      }
-
-      ScenePoint2D GetPosition1() const
-      {
-        return p1_ + delta_;
-      }
-
-      ScenePoint2D GetPosition2() const
-      {
-        return p2_ + delta_;
-      }
-
-      virtual bool IsHit(const ScenePoint2D& p,
-                         const Scene2D& scene) const
-      {
-        const double zoom = scene.GetSceneToCanvasTransform().ComputeZoom();
-        return (ScenePoint2D::SquaredDistancePtSegment(p1_ + delta_, p2_ + delta_, p) * zoom * zoom <=
-                (HANDLE_SIZE / 2.0) * (HANDLE_SIZE / 2.0));
-      }
-
-      virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
-                                       const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-        PolylineSceneLayer::Chain chain;
-        chain.reserve(2);
-        chain.push_back(p1_ + delta_);
-        chain.push_back(p2_ + delta_);
-
-        if (IsHover())
-        {
-          polyline.AddChain(chain, false /* closed */, GetHoverColor());
-        }
-        else
-        {
-          polyline.AddChain(chain, false /* closed */, GetColor());
-        }
-      }
-      
-      virtual void RenderOtherLayers(MacroSceneLayer& macro,
-                                     const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        SetModified(true);
-        delta_ = delta;
-        GetParentAnnotation().SignalMove(*this);
-      }
-
-      virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        SetModified(true);
-        p1_ = p1_ + delta;
-        p2_ = p2_ + delta;
-        delta_ = ScenePoint2D(0, 0);
-        GetParentAnnotation().SignalMove(*this);
-      }
-    };
-
-    
-    class Circle : public GeometricPrimitive
-    {
-    private:
-      ScenePoint2D  p1_;
-      ScenePoint2D  p2_;
-      
-    public:
-      Circle(Annotation& parentAnnotation,
-             const ScenePoint2D& p1,
-             const ScenePoint2D& p2) :
-        GeometricPrimitive(parentAnnotation, 2),
-        p1_(p1),
-        p2_(p2)
-      {
-      }
-
-      void SetPosition(const ScenePoint2D& p1,
-                       const ScenePoint2D& p2)
-      {
-        SetModified(true);
-        p1_ = p1;
-        p2_ = p2;
-      }
-
-      ScenePoint2D GetPosition1() const
-      {
-        return p1_;
-      }
-
-      ScenePoint2D GetPosition2() const
-      {
-        return p2_;
-      }
-
-      virtual bool IsHit(const ScenePoint2D& p,
-                         const Scene2D& scene) const
-      {
-        return false;
-      }
-
-      virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
-                                       const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-        static unsigned int NUM_SEGMENTS = 128;
-
-        ScenePoint2D middle((p1_.GetX() + p2_.GetX()) / 2.0,
-                            (p1_.GetY() + p2_.GetY()) / 2.0);
-        
-        const double radius = ScenePoint2D::DistancePtPt(middle, p1_);
-
-        double increment = 2.0 * PI / static_cast<double>(NUM_SEGMENTS - 1);
-
-        PolylineSceneLayer::Chain chain;
-        chain.reserve(NUM_SEGMENTS);
-
-        double theta = 0;
-        for (unsigned int i = 0; i < NUM_SEGMENTS; i++)
-        {
-          chain.push_back(ScenePoint2D(middle.GetX() + radius * cos(theta),
-                                       middle.GetY() + radius * sin(theta)));
-          theta += increment;
-        }
-        
-        if (IsHover())
-        {
-          polyline.AddChain(chain, false /* closed */, GetHoverColor());
-        }
-        else
-        {
-          polyline.AddChain(chain, false /* closed */, GetColor());
-        }
-      }
-      
-      virtual void RenderOtherLayers(MacroSceneLayer& macro,
-                                     const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
-      }
-
-      virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
-      }
-    };
-
-    
-    class Arc : public GeometricPrimitive
-    {
-    private:
-      ScenePoint2D  start_;
-      ScenePoint2D  middle_;
-      ScenePoint2D  end_;
-      double        radius_;  // in pixels
-
-      void ComputeAngles(double& fullAngle,
-                         double& startAngle,
-                         double& endAngle) const
-      {
-        const double x1 = start_.GetX();
-        const double y1 = start_.GetY();
-        const double xc = middle_.GetX();
-        const double yc = middle_.GetY();
-        const double x2 = end_.GetX();
-        const double y2 = end_.GetY();
-        
-        startAngle = atan2(y1 - yc, x1 - xc);
-        endAngle = atan2(y2 - yc, x2 - xc);
-
-        fullAngle = endAngle - startAngle;
-        
-        while (fullAngle < -PI)
-        {
-          fullAngle += 2.0 * PI;
-        }
-        
-        while (fullAngle >= PI)
-        {
-          fullAngle -= 2.0 * PI;
-        }
-      }
-      
-    public:
-      Arc(Annotation& parentAnnotation,
-          const ScenePoint2D& start,
-          const ScenePoint2D& middle,
-          const ScenePoint2D& end) :
-        GeometricPrimitive(parentAnnotation, 2),
-        start_(start),
-        middle_(middle),
-        end_(end),
-        radius_(20)
-      {
-      }
-
-      double GetAngle() const
-      {
-        double fullAngle, startAngle, endAngle;
-        ComputeAngles(fullAngle, startAngle, endAngle);
-        return fullAngle;
-      }
-
-      void SetStart(const ScenePoint2D& p)
-      {
-        SetModified(true);
-        start_ = p;
-      }
-
-      void SetMiddle(const ScenePoint2D& p)
-      {
-        SetModified(true);
-        middle_ = p;
-      }
-
-      void SetEnd(const ScenePoint2D& p)
-      {
-        SetModified(true);
-        end_ = p;
-      }
-
-      virtual bool IsHit(const ScenePoint2D& p,
-                         const Scene2D& scene) const
-      {
-        return false;
-      }
-
-      virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
-                                       const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-        static unsigned int NUM_SEGMENTS = 64;
-
-        const double radius = radius_ / scene.GetSceneToCanvasTransform().ComputeZoom();
-
-        double fullAngle, startAngle, endAngle;
-        ComputeAngles(fullAngle, startAngle, endAngle);
-
-        double increment = fullAngle / static_cast<double>(NUM_SEGMENTS - 1);
-
-        PolylineSceneLayer::Chain chain;
-        chain.reserve(NUM_SEGMENTS);
-
-        double theta = startAngle;
-        for (unsigned int i = 0; i < NUM_SEGMENTS; i++)
-        {
-          chain.push_back(ScenePoint2D(middle_.GetX() + radius * cos(theta),
-                                       middle_.GetY() + radius * sin(theta)));
-          theta += increment;
-        }
-        
-        if (IsHover())
-        {
-          polyline.AddChain(chain, false /* closed */, GetHoverColor());
-        }
-        else
-        {
-          polyline.AddChain(chain, false /* closed */, GetColor());
-        }
-      }
-      
-      virtual void RenderOtherLayers(MacroSceneLayer& macro,
-                                     const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
-      }
-
-      virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
-      }
-    };
-
-    
-    class Text : public GeometricPrimitive
-    {
-    private:
-      AnnotationsLayer&                that_;
-      bool                             first_;
-      size_t                           subLayer_;
-      std::unique_ptr<TextSceneLayer>  content_;
-
-    public:
-      Text(AnnotationsLayer& that,
-           Annotation& parentAnnotation) :
-        GeometricPrimitive(parentAnnotation, 2),
-        that_(that),
-        first_(true)
-      {
-      }
-
-      virtual ~Text()
-      {
-        if (!first_)
-        {
-          that_.TagSubLayerToRemove(subLayer_);
-        }
-      }
-      
-      void SetContent(const TextSceneLayer& content)
-      {
-        SetModified(true);
-        content_.reset(dynamic_cast<TextSceneLayer*>(content.Clone()));
-      }        
-
-      virtual bool IsHit(const ScenePoint2D& p,
-                         const Scene2D& scene) const
-      {
-        return false;
-      }
-
-      virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
-                                       const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-      }
-      
-      virtual void RenderOtherLayers(MacroSceneLayer& macro,
-                                     const Scene2D& scene) ORTHANC_OVERRIDE
-      {
-        if (content_.get() != NULL)
-        {
-          std::unique_ptr<TextSceneLayer> layer(reinterpret_cast<TextSceneLayer*>(content_->Clone()));
-
-          layer->SetColor(IsHover() ? GetHoverColor() : GetColor());
-          
-          if (first_)
-          {
-            subLayer_ = macro.AddLayer(layer.release());
-            first_ = false;
-          }
-          else
-          {
-            macro.UpdateLayer(subLayer_, layer.release());
-          }
-        }
-      }
-
-      virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
-      }
-
-      virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
-      }
-    };
-
-
-    class EditPrimitiveTracker : public IFlexiblePointerTracker
-    {
-    private:
-      GeometricPrimitive&  primitive_;
-      ScenePoint2D         sceneClick_;
-      AffineTransform2D    canvasToScene_;
-      bool                 alive_;
-      
-    public:
-      EditPrimitiveTracker(GeometricPrimitive& primitive,
-                           const ScenePoint2D& sceneClick,
-                           const AffineTransform2D& canvasToScene) :
-        primitive_(primitive),
-        sceneClick_(sceneClick),
-        canvasToScene_(canvasToScene),
-        alive_(true)
-      {
-      }
-
-      virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-        primitive_.MovePreview(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_);
-      }
-      
-      virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-        primitive_.MoveDone(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_);
-        alive_ = false;
-      }
-
-      virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual bool IsAlive() const ORTHANC_OVERRIDE
-      {
-        return alive_;
-      }
-
-      virtual void Cancel() ORTHANC_OVERRIDE
-      {
-        primitive_.MoveDone(ScenePoint2D(0, 0));
-      }
-    };
-
-
-    class SegmentAnnotation : public Annotation
-    {
-    private:
-      bool      showLabel_;
-      Handle&   handle1_;
-      Handle&   handle2_;
-      Segment&  segment_;
-      Text&     label_;
-
-      void UpdateLabel()
-      {
-        if (showLabel_)
-        {
-          TextSceneLayer content;
-
-          double x1 = handle1_.GetCenter().GetX();
-          double y1 = handle1_.GetCenter().GetY();
-          double x2 = handle2_.GetCenter().GetX();
-          double y2 = handle2_.GetCenter().GetY();
-        
-          // Put the label to the right of the right-most handle
-          if (x1 < x2)
-          {
-            content.SetPosition(x2, y2);
-          }
-          else
-          {
-            content.SetPosition(x1, y1);
-          }
-
-          content.SetAnchor(BitmapAnchor_CenterLeft);
-          content.SetBorder(10);
-
-          double dx = x1 - x2;
-          double dy = y1 - y2;
-          char buf[32];
-          sprintf(buf, "%0.2f cm", sqrt(dx * dx + dy * dy) / 10.0);
-          content.SetText(buf);
-
-          label_.SetContent(content);
-        }
-      }
-
-    public:
-      SegmentAnnotation(AnnotationsLayer& that,
-                        bool showLabel,
-                        const ScenePoint2D& p1,
-                        const ScenePoint2D& p2) :
-        Annotation(that),
-        showLabel_(showLabel),
-        handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))),
-        handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))),
-        segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))),
-        label_(AddTypedPrimitive<Text>(new Text(that, *this)))
-      {
-        label_.SetColor(Color(255, 0, 0));
-        UpdateLabel();
-      }
-
-      Handle& GetHandle1() const
-      {
-        return handle1_;
-      }
-
-      Handle& GetHandle2() const
-      {
-        return handle2_;
-      }
-
-      virtual void SignalMove(GeometricPrimitive& primitive) ORTHANC_OVERRIDE
-      {
-        if (&primitive == &handle1_ ||
-            &primitive == &handle2_)
-        {
-          segment_.SetPosition(handle1_.GetCenter(), handle2_.GetCenter());
-        }
-        else if (&primitive == &segment_)
-        {
-          handle1_.SetCenter(segment_.GetPosition1());
-          handle2_.SetCenter(segment_.GetPosition2());
-        }
-        
-        UpdateLabel();
-      }
-
-      virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
-      {
-        target = Json::objectValue;
-        target[KEY_TYPE] = VALUE_SEGMENT;
-        target[KEY_X1] = handle1_.GetCenter().GetX();
-        target[KEY_Y1] = handle1_.GetCenter().GetY();
-        target[KEY_X2] = handle2_.GetCenter().GetX();
-        target[KEY_Y2] = handle2_.GetCenter().GetY();
-      }
-
-      static void Unserialize(AnnotationsLayer& target,
-                              const Json::Value& source)
-      {
-        if (source.isMember(KEY_X1) &&
-            source.isMember(KEY_Y1) &&
-            source.isMember(KEY_X2) &&
-            source.isMember(KEY_Y2) &&
-            source[KEY_X1].isNumeric() &&
-            source[KEY_Y1].isNumeric() &&
-            source[KEY_X2].isNumeric() &&
-            source[KEY_Y2].isNumeric())
-        {
-          new SegmentAnnotation(target, true,
-                                ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()),
-                                ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble()));
-        }
-        else
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize an segment annotation");
-        }
-      }
-    };
-
-    
-    class AngleAnnotation : public Annotation
-    {
-    private:
-      Handle&   startHandle_;
-      Handle&   middleHandle_;
-      Handle&   endHandle_;
-      Segment&  segment1_;
-      Segment&  segment2_;
-      Arc&      arc_;
-      Text&     label_;
-
-      void UpdateLabel()
-      {
-        TextSceneLayer content;
-
-        const double x1 = startHandle_.GetCenter().GetX();
-        const double x2 = middleHandle_.GetCenter().GetX();
-        const double y2 = middleHandle_.GetCenter().GetY();
-        const double x3 = endHandle_.GetCenter().GetX();
-        
-        if (x2 < x1 &&
-            x2 < x3)
-        {
-          content.SetAnchor(BitmapAnchor_CenterRight);
-        }
-        else
-        {
-          content.SetAnchor(BitmapAnchor_CenterLeft);
-        }
-
-        content.SetPosition(x2, y2);
-        content.SetBorder(10);
-
-        char buf[32];
-        sprintf(buf, "%.01f%c%c", std::abs(arc_.GetAngle()) / PI * 180.0,
-                0xc2, 0xb0 /* two bytes corresponding to degree symbol in UTF-8 */);
-        content.SetText(buf);
-
-        label_.SetContent(content);
-      }
-
-    public:
-      AngleAnnotation(AnnotationsLayer& that,
-                      const ScenePoint2D& start,
-                      const ScenePoint2D& middle,
-                      const ScenePoint2D& end) :
-        Annotation(that),
-        startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, start))),
-        middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, middle))),
-        endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, end))),
-        segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))),
-        segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))),
-        arc_(AddTypedPrimitive<Arc>(new Arc(*this, start, middle, end))),
-        label_(AddTypedPrimitive<Text>(new Text(that, *this)))
-      {
-        label_.SetColor(Color(255, 0, 0));
-        UpdateLabel();
-      }
-
-      Handle& GetEndHandle() const
-      {
-        return endHandle_;
-      }
-
-      virtual void SignalMove(GeometricPrimitive& primitive) ORTHANC_OVERRIDE
-      {
-        if (&primitive == &startHandle_)
-        {
-          segment1_.SetPosition(startHandle_.GetCenter(), middleHandle_.GetCenter());
-          arc_.SetStart(startHandle_.GetCenter());
-        }
-        else if (&primitive == &middleHandle_)
-        {
-          segment1_.SetPosition(startHandle_.GetCenter(), middleHandle_.GetCenter());
-          segment2_.SetPosition(middleHandle_.GetCenter(), endHandle_.GetCenter());
-          arc_.SetMiddle(middleHandle_.GetCenter());
-        }
-        else if (&primitive == &endHandle_)
-        {
-          segment2_.SetPosition(middleHandle_.GetCenter(), endHandle_.GetCenter());
-          arc_.SetEnd(endHandle_.GetCenter());
-        }
-        else if (&primitive == &segment1_)
-        {
-          startHandle_.SetCenter(segment1_.GetPosition1());
-          middleHandle_.SetCenter(segment1_.GetPosition2());
-          segment2_.SetPosition(segment1_.GetPosition2(), segment2_.GetPosition2());
-          arc_.SetStart(segment1_.GetPosition1());
-          arc_.SetMiddle(segment1_.GetPosition2());
-        }
-        else if (&primitive == &segment2_)
-        {
-          middleHandle_.SetCenter(segment2_.GetPosition1());
-          endHandle_.SetCenter(segment2_.GetPosition2());
-          segment1_.SetPosition(segment1_.GetPosition1(), segment2_.GetPosition1());
-          arc_.SetMiddle(segment2_.GetPosition1());
-          arc_.SetEnd(segment2_.GetPosition2());
-        }
-
-        UpdateLabel();
-      }
-
-      virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
-      {
-        target = Json::objectValue;
-        target[KEY_TYPE] = VALUE_ANGLE;
-        target[KEY_X1] = startHandle_.GetCenter().GetX();
-        target[KEY_Y1] = startHandle_.GetCenter().GetY();
-        target[KEY_X2] = middleHandle_.GetCenter().GetX();
-        target[KEY_Y2] = middleHandle_.GetCenter().GetY();
-        target[KEY_X3] = endHandle_.GetCenter().GetX();
-        target[KEY_Y3] = endHandle_.GetCenter().GetY();
-      }
-
-      static void Unserialize(AnnotationsLayer& target,
-                              const Json::Value& source)
-      {
-        if (source.isMember(KEY_X1) &&
-            source.isMember(KEY_Y1) &&
-            source.isMember(KEY_X2) &&
-            source.isMember(KEY_Y2) &&
-            source.isMember(KEY_X3) &&
-            source.isMember(KEY_Y3) &&
-            source[KEY_X1].isNumeric() &&
-            source[KEY_Y1].isNumeric() &&
-            source[KEY_X2].isNumeric() &&
-            source[KEY_Y2].isNumeric() &&
-            source[KEY_X3].isNumeric() &&
-            source[KEY_Y3].isNumeric())
-        {
-          new AngleAnnotation(target,
-                              ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()),
-                              ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble()),
-                              ScenePoint2D(source[KEY_X3].asDouble(), source[KEY_Y3].asDouble()));
-        }
-        else
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize an angle annotation");
-        }
-      }
-    };
-
-    
-    class CircleAnnotation : public Annotation
-    {
-    private:
-      Handle&   handle1_;
-      Handle&   handle2_;
-      Segment&  segment_;
-      Circle&   circle_;
-      Text&     label_;
-
-      void UpdateLabel()
-      {
-        TextSceneLayer content;
-
-        double x1 = handle1_.GetCenter().GetX();
-        double y1 = handle1_.GetCenter().GetY();
-        double x2 = handle2_.GetCenter().GetX();
-        double y2 = handle2_.GetCenter().GetY();
-        
-        // Put the label to the right of the right-most handle
-        if (x1 < x2)
-        {
-          content.SetPosition(x2, y2);
-        }
-        else
-        {
-          content.SetPosition(x1, y1);
-        }
-
-        content.SetAnchor(BitmapAnchor_CenterLeft);
-        content.SetBorder(10);
-
-        double dx = x1 - x2;
-        double dy = y1 - y2;
-        double diameter = sqrt(dx * dx + dy * dy);  // in millimeters
-
-        double area = PI * diameter * diameter / 4.0;
-        
-        char buf[32];
-        sprintf(buf, "%0.2f cm\n%0.2f cm%c%c",
-                diameter / 10.0,
-                area / 100.0,
-                0xc2, 0xb2 /* two bytes corresponding to two power in UTF-8 */);
-        content.SetText(buf);
-
-        label_.SetContent(content);
-      }
-
-    public:
-      CircleAnnotation(AnnotationsLayer& that,
-                       const ScenePoint2D& p1,
-                       const ScenePoint2D& p2) :
-        Annotation(that),
-        handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))),
-        handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))),
-        segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))),
-        circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))),
-        label_(AddTypedPrimitive<Text>(new Text(that, *this)))
-      {
-        label_.SetColor(Color(255, 0, 0));
-        UpdateLabel();
-      }
-
-      Handle& GetHandle2() const
-      {
-        return handle2_;
-      }
-
-      virtual void SignalMove(GeometricPrimitive& primitive) ORTHANC_OVERRIDE
-      {
-        if (&primitive == &handle1_ ||
-            &primitive == &handle2_)
-        {
-          segment_.SetPosition(handle1_.GetCenter(), handle2_.GetCenter());
-          circle_.SetPosition(handle1_.GetCenter(), handle2_.GetCenter());          
-        }
-        else if (&primitive == &segment_)
-        {
-          handle1_.SetCenter(segment_.GetPosition1());
-          handle2_.SetCenter(segment_.GetPosition2());
-          circle_.SetPosition(segment_.GetPosition1(), segment_.GetPosition2());
-        }
-        
-        UpdateLabel();
-      }
-
-      virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
-      {
-        target = Json::objectValue;
-        target[KEY_TYPE] = VALUE_CIRCLE;
-        target[KEY_X1] = handle1_.GetCenter().GetX();
-        target[KEY_Y1] = handle1_.GetCenter().GetY();
-        target[KEY_X2] = handle2_.GetCenter().GetX();
-        target[KEY_Y2] = handle2_.GetCenter().GetY();
-      }
-
-      static void Unserialize(AnnotationsLayer& target,
-                              const Json::Value& source)
-      {
-        if (source.isMember(KEY_X1) &&
-            source.isMember(KEY_Y1) &&
-            source.isMember(KEY_X2) &&
-            source.isMember(KEY_Y2) &&
-            source[KEY_X1].isNumeric() &&
-            source[KEY_Y1].isNumeric() &&
-            source[KEY_X2].isNumeric() &&
-            source[KEY_Y2].isNumeric())
-        {
-          new CircleAnnotation(target,
-                               ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()),
-                               ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble()));
-        }
-        else
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize an circle annotation");
-        }
-      }
-    };
-
-    
-    class CreateSegmentOrCircleTracker : public IFlexiblePointerTracker
-    {
-    private:
-      AnnotationsLayer&  that_;
-      Annotation*        annotation_;
-      AffineTransform2D  canvasToScene_;
-      Handle*            handle2_;
-      
-    public:
-      CreateSegmentOrCircleTracker(AnnotationsLayer& that,
-                                   bool isCircle,
-                                   const ScenePoint2D& sceneClick,
-                                   const AffineTransform2D& canvasToScene) :
-        that_(that),
-        annotation_(NULL),
-        canvasToScene_(canvasToScene),
-        handle2_(NULL)
-      {
-        if (isCircle)
-        {
-          annotation_ = new CircleAnnotation(that, sceneClick, sceneClick);
-          handle2_ = &dynamic_cast<CircleAnnotation*>(annotation_)->GetHandle2();
-        }
-        else
-        {
-          annotation_ = new SegmentAnnotation(that, true /* show label */, sceneClick, sceneClick);
-          handle2_ = &dynamic_cast<SegmentAnnotation*>(annotation_)->GetHandle2();
-        }
-        
-        assert(annotation_ != NULL &&
-               handle2_ != NULL);
-      }
-
-      virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-        if (annotation_ != NULL)
-        {
-          assert(handle2_ != NULL);
-          handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-          annotation_->SignalMove(*handle2_);
-        }
-      }
-      
-      virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-        annotation_ = NULL;  // IsAlive() becomes false
-
-        that_.BroadcastMessage(AnnotationAddedMessage(that_));
-      }
-
-      virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual bool IsAlive() const ORTHANC_OVERRIDE
-      {
-        return (annotation_ != NULL);
-      }
-
-      virtual void Cancel() ORTHANC_OVERRIDE
-      {
-        if (annotation_ != NULL)
-        {
-          that_.DeleteAnnotation(annotation_);
-          annotation_ = NULL;
-        }
-      }
-    };
-
-
-    class CreateAngleTracker : public IFlexiblePointerTracker
-    {
-    private:
-      AnnotationsLayer&   that_;
-      SegmentAnnotation*  segment_;
-      AngleAnnotation*    angle_;
-      AffineTransform2D   canvasToScene_;
-      
-    public:
-      CreateAngleTracker(AnnotationsLayer& that,
-                         const ScenePoint2D& sceneClick,
-                         const AffineTransform2D& canvasToScene) :
-        that_(that),
-        segment_(NULL),
-        angle_(NULL),
-        canvasToScene_(canvasToScene)
-      {
-        segment_ = new SegmentAnnotation(that, false /* no length label */, sceneClick, sceneClick);
-      }
-
-      virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-        if (segment_ != NULL)
-        {
-          segment_->GetHandle2().SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-          segment_->SignalMove(segment_->GetHandle2());
-        }
-
-        if (angle_ != NULL)
-        {
-          angle_->GetEndHandle().SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-          angle_->SignalMove(angle_->GetEndHandle());
-        }
-      }
-      
-      virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-        if (segment_ != NULL)
-        {
-          // End of first step: The first segment is available, now create the angle
-
-          angle_ = new AngleAnnotation(that_, segment_->GetHandle1().GetCenter(),
-                                       segment_->GetHandle2().GetCenter(),
-                                       segment_->GetHandle2().GetCenter());
-          
-          that_.DeleteAnnotation(segment_);
-          segment_ = NULL;
-        }
-        else
-        {
-          angle_ = NULL;  // IsAlive() becomes false
-
-          that_.BroadcastMessage(AnnotationAddedMessage(that_));
-        }
-      }
-
-      virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual bool IsAlive() const ORTHANC_OVERRIDE
-      {
-        return (segment_ != NULL ||
-                angle_ != NULL);
-      }
-
-      virtual void Cancel() ORTHANC_OVERRIDE
-      {
-        if (segment_ != NULL)
-        {
-          that_.DeleteAnnotation(segment_);
-          segment_ = NULL;
-        }
-
-        if (angle_ != NULL)
-        {
-          that_.DeleteAnnotation(angle_);
-          angle_ = NULL;
-        }
-      }
-    };
-
-
-    // Dummy tracker that is only used for deletion, in order to warn
-    // the caller that the mouse action was taken into consideration
-    class EraseTracker : public IFlexiblePointerTracker
-    {
-    public:
-      EraseTracker()
-      {
-      }
-
-      virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-      }
-      
-      virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE
-      {
-      }
-
-      virtual bool IsAlive() const ORTHANC_OVERRIDE
-      {
-        return false;
-      }
-
-      virtual void Cancel() ORTHANC_OVERRIDE
-      {
-      }
-    };
-
-
-    typedef std::set<GeometricPrimitive*>  GeometricPrimitives;
-    typedef std::set<Annotation*>          Annotations;
-    typedef std::set<size_t>               SubLayers;
-
-    Tool                 activeTool_;
-    size_t               macroLayerIndex_;
-    size_t               polylineSubLayer_;
-    GeometricPrimitives  primitives_;
-    Annotations          annotations_;
-    SubLayers            subLayersToRemove_;
-
-    void AddAnnotation(Annotation* annotation)
-    {
-      assert(annotation != NULL);
-      assert(annotations_.find(annotation) == annotations_.end());
-      annotations_.insert(annotation);
-    }
-
-    void DeleteAnnotation(Annotation* annotation)
-    {
-      if (annotation != NULL)
-      {
-        assert(annotations_.find(annotation) != annotations_.end());
-        annotations_.erase(annotation);
-        delete annotation;
-      }
-    }
-
-    void DeletePrimitive(GeometricPrimitive* primitive)
-    {
-      if (primitive != NULL)
-      {
-        assert(primitives_.find(primitive) != primitives_.end());
-        primitives_.erase(primitive);
-        delete primitive;
-      }
-    }
-
-    void TagSubLayerToRemove(size_t subLayerIndex)
-    {
-      assert(subLayersToRemove_.find(subLayerIndex) == subLayersToRemove_.end());
-      subLayersToRemove_.insert(subLayerIndex);
-    }
-    
-  public:
-    AnnotationsLayer(size_t macroLayerIndex) :
-      activeTool_(Tool_Edit),
-      macroLayerIndex_(macroLayerIndex),
-      polylineSubLayer_(0)  // dummy initialization
-    {
-      annotations_.insert(new SegmentAnnotation(*this, true /* show label */, ScenePoint2D(0, 0), ScenePoint2D(100, 100)));
-      annotations_.insert(new AngleAnnotation(*this, ScenePoint2D(100, 50), ScenePoint2D(150, 40), ScenePoint2D(200, 50)));
-      annotations_.insert(new CircleAnnotation(*this, ScenePoint2D(50, 200), ScenePoint2D(100, 250)));
-    }
-    
-    ~AnnotationsLayer()
-    {
-      Clear();
-    }
-
-    void Clear()
-    {
-      for (Annotations::iterator it = annotations_.begin(); it != annotations_.end(); ++it)
-      {
-        assert(*it != NULL);
-        delete *it;
-      }
-
-      annotations_.clear();
-    }
-
-    void SetActiveTool(Tool tool)
-    {
-      activeTool_ = tool;
-    }
-
-    Tool GetActiveTool() const
-    {
-      return activeTool_;
-    }
-
-    void Render(Scene2D& scene)
-    {
-      MacroSceneLayer* macro = NULL;
-
-      if (scene.HasLayer(macroLayerIndex_))
-      {
-        macro = &dynamic_cast<MacroSceneLayer&>(scene.GetLayer(macroLayerIndex_));
-      }
-      else
-      {
-        macro = &dynamic_cast<MacroSceneLayer&>(scene.SetLayer(macroLayerIndex_, new MacroSceneLayer));
-        polylineSubLayer_ = macro->AddLayer(new PolylineSceneLayer);
-      }
-
-      for (SubLayers::const_iterator it = subLayersToRemove_.begin(); it != subLayersToRemove_.end(); ++it)
-      {
-        assert(macro->HasLayer(*it));
-        macro->DeleteLayer(*it);
-      }
-
-      subLayersToRemove_.clear();
-
-      std::unique_ptr<PolylineSceneLayer> polyline(new PolylineSceneLayer);
-
-      for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
-      {
-        assert(*it != NULL);
-        GeometricPrimitive& primitive = **it;        
-        
-        primitive.RenderPolylineLayer(*polyline, scene);
-
-        if (primitive.IsModified())
-        {
-          primitive.RenderOtherLayers(*macro, scene);
-          primitive.SetModified(false);
-        }
-      }
-
-      macro->UpdateLayer(polylineSubLayer_, polyline.release());
-    }
-
-    bool ClearHover()
-    {
-      bool needsRefresh = false;
-      
-      for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
-      {
-        assert(*it != NULL);
-        if ((*it)->IsHover())
-        {
-          (*it)->SetHover(false);
-          needsRefresh = true;
-        }
-      }
-
-      return needsRefresh;
-    }
-
-    bool SetMouseHover(const ScenePoint2D& p /* expressed in canvas coordinates */,
-                       const Scene2D& scene)
-    {
-      if (activeTool_ == Tool_None)
-      {
-        return ClearHover();
-      }
-      else
-      {
-        bool needsRefresh = false;
-      
-        const ScenePoint2D s = p.Apply(scene.GetCanvasToSceneTransform());
-      
-        for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
-        {
-          assert(*it != NULL);
-          bool hover = (*it)->IsHit(s, scene);
-
-          if ((*it)->IsHover() != hover)
-          {
-            needsRefresh = true;
-          }
-        
-          (*it)->SetHover(hover);
-        }
-
-        return needsRefresh;
-      }
-    }
-
-
-    IFlexiblePointerTracker* CreateTracker(const ScenePoint2D& p /* expressed in canvas coordinates */,
-                                           const Scene2D& scene)
-    {
-      if (activeTool_ == Tool_None)
-      {
-        return NULL;
-      }
-      else
-      {
-        const ScenePoint2D s = p.Apply(scene.GetCanvasToSceneTransform());
-
-        GeometricPrimitive* bestHit = NULL;
-      
-        for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
-        {
-          assert(*it != NULL);
-          if ((*it)->IsHit(s, scene))
-          {
-            if (bestHit == NULL ||
-                bestHit->GetDepth() > (*it)->GetDepth())
-            {
-              bestHit = *it;
-            }
-          }
-        }
-
-        if (bestHit != NULL)
-        {
-          if (activeTool_ == Tool_Erase)
-          {
-            DeleteAnnotation(&bestHit->GetParentAnnotation());
-            BroadcastMessage(AnnotationRemovedMessage(*this));
-            return new EraseTracker;
-          }
-          else
-          {
-            return new EditPrimitiveTracker(*bestHit, s, scene.GetCanvasToSceneTransform());
-          }
-        }
-        else
-        {
-          switch (activeTool_)
-          {
-            case Tool_Segment:
-              return new CreateSegmentOrCircleTracker(*this, false /* segment */, s, scene.GetCanvasToSceneTransform());
-
-            case Tool_Circle:
-              return new CreateSegmentOrCircleTracker(*this, true /* circle */, s, scene.GetCanvasToSceneTransform());
-
-            case Tool_Angle:
-              return new CreateAngleTracker(*this, s, scene.GetCanvasToSceneTransform());
-
-            default:
-              return NULL;
-          }
-        }
-      }
-    }
-
-
-    void Serialize(Json::Value& target) const
-    {
-      Json::Value annotations = Json::arrayValue;
-      
-      for (Annotations::const_iterator it = annotations_.begin(); it != annotations_.end(); ++it)
-      {
-        assert(*it != NULL);
-
-        Json::Value item;
-        (*it)->Serialize(item);
-        annotations.append(item);
-      }
-
-      target = Json::objectValue;
-      target[KEY_ANNOTATIONS] = annotations;
-    }
-
-
-    void Unserialize(const Json::Value& serialized)
-    {
-      Clear();
-      
-      if (serialized.type() != Json::objectValue ||
-          !serialized.isMember(KEY_ANNOTATIONS) ||
-          serialized[KEY_ANNOTATIONS].type() != Json::arrayValue)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize a set of annotations");
-      }
-
-      const Json::Value& annotations = serialized[KEY_ANNOTATIONS];
-
-      for (Json::Value::ArrayIndex i = 0; i < annotations.size(); i++)
-      {
-        if (annotations[i].type() != Json::objectValue ||
-            !annotations[i].isMember(KEY_TYPE) ||
-            annotations[i][KEY_TYPE].type() != Json::stringValue)
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
-        }
-
-        const std::string& type = annotations[i][KEY_TYPE].asString();
-
-        if (type == VALUE_ANGLE)
-        {
-          AngleAnnotation::Unserialize(*this, annotations[i]);
-        }
-        else if (type == VALUE_CIRCLE)
-        {
-          CircleAnnotation::Unserialize(*this, annotations[i]);
-        }
-        else if (type == VALUE_SEGMENT)
-        {
-          SegmentAnnotation::Unserialize(*this, annotations[i]);
-        }
-        else
-        {
-          LOG(ERROR) << "Cannot unserialize unknown type of annotation: " << type;
-        }
-      }
-    }
-  };
-}
-#endif
-
-
-
-std::string orthancUrl;
-std::string instanceId;
-int frameIndex = 0;
+static std::string orthancUrl;
+static std::string instanceId;
+static int frameIndex = 0;
 
 
 static void ProcessOptions(int argc, char* argv[])
@@ -1721,7 +145,7 @@
 
     {
 
-#if 1
+#if 0
       boost::shared_ptr<OrthancStone::SdlViewport> viewport =
         OrthancStone::SdlOpenGLViewport::Create("Stone of Orthanc", 800, 600);
 #else
@@ -1759,8 +183,8 @@
         bool angleMeasureFirst = true;
         angleMeasureTool->Disable();
 
-        OrthancStone::AnnotationsLayer annotations(10);
-        annotations.SetActiveTool(OrthancStone::AnnotationsLayer::Tool_Angle);
+        OrthancStone::AnnotationsSceneLayer annotations(10);
+        annotations.SetActiveTool(OrthancStone::AnnotationsSceneLayer::Tool_Angle);
 
         {
           Json::Value v;