changeset 2344:dbba1b96b35a refactoring

let ViewportController handle calls to IViewport::ILock::Invalidate()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 06 Oct 2026 15:42:43 +0200
parents e4d4e5d274fc
children 88b6e1c19d03
files Applications/Samples/Sdl/RtViewer/RtViewerSdl.cpp Applications/Samples/Sdl/SingleViewportSdlApplication.cpp OrthancStone/Sources/Platforms/WebAssembly/WebAssemblyViewport.cpp OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.cpp OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.h OrthancStone/Sources/Scene2D/MagnifyingGlassTracker.cpp OrthancStone/Sources/Scene2D/MagnifyingGlassTracker.h OrthancStone/Sources/Scene2D/PanSceneTracker.cpp OrthancStone/Sources/Scene2D/PanSceneTracker.h OrthancStone/Sources/Scene2D/PinchZoomTracker.cpp OrthancStone/Sources/Scene2D/PinchZoomTracker.h OrthancStone/Sources/Scene2D/RotateSceneTracker.cpp OrthancStone/Sources/Scene2D/RotateSceneTracker.h OrthancStone/Sources/Scene2D/ZoomSceneTracker.cpp OrthancStone/Sources/Scene2D/ZoomSceneTracker.h OrthancStone/Sources/Scene2DViewport/CreateAngleMeasureTracker.cpp OrthancStone/Sources/Scene2DViewport/CreateAngleMeasureTracker.h OrthancStone/Sources/Scene2DViewport/CreateLineMeasureTracker.cpp OrthancStone/Sources/Scene2DViewport/CreateLineMeasureTracker.h OrthancStone/Sources/Scene2DViewport/EditAngleMeasureTracker.cpp OrthancStone/Sources/Scene2DViewport/EditAngleMeasureTracker.h OrthancStone/Sources/Scene2DViewport/EditLineMeasureTracker.cpp OrthancStone/Sources/Scene2DViewport/EditLineMeasureTracker.h OrthancStone/Sources/Scene2DViewport/IFlexiblePointerTracker.h OrthancStone/Sources/Scene2DViewport/ViewportController.cpp OrthancStone/Sources/Scene2DViewport/ViewportController.h OrthancStone/Sources/Viewport/IViewport.h OrthancStone/Sources/Viewport/ViewportLocker.h
diffstat 29 files changed, 121 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/Sdl/RtViewer/RtViewerSdl.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/Applications/Samples/Sdl/RtViewer/RtViewerSdl.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -353,19 +353,14 @@
                 lock->GetController().HandleMousePress(interactor, p,
                                                        lock->GetCompositor().GetCanvasWidth(),
                                                        lock->GetCompositor().GetCanvasHeight());
-                lock->Invalidate();
                 break;
 
               case SDL_MOUSEMOTION:
-                if (lock->GetController().HandleMouseMove(p))
-                {
-                  lock->Invalidate();
-                }
+                lock->GetController().HandleMouseMove(p);
                 break;
 
               case SDL_MOUSEBUTTONUP:
                 lock->GetController().HandleMouseRelease(p);
-                lock->Invalidate();
                 break;
 
               default:
--- a/Applications/Samples/Sdl/SingleViewportSdlApplication.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/Applications/Samples/Sdl/SingleViewportSdlApplication.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -121,7 +121,6 @@
             {
               viewportLock->GetController().HandleMousePress(*interactor, p, viewportLock->GetCompositor().GetCanvasWidth(),
                                                              viewportLock->GetCompositor().GetCanvasHeight());
-              viewportLock->Invalidate();
               break;
             }
 
@@ -129,10 +128,7 @@
             {
               if (viewportLock->GetController().HasActiveTracker())
               {
-                if (viewportLock->GetController().HandleMouseMove(p))
-                {
-                  viewportLock->Invalidate();
-                }
+                viewportLock->GetController().HandleMouseMove(p);
               }
               else if (interactor->HasMouseHover())
               {
@@ -144,7 +140,6 @@
 
             case SDL_MOUSEBUTTONUP:
               viewportLock->GetController().HandleMouseRelease(p);
-              viewportLock->Invalidate();
               break;
 
             default:
--- a/OrthancStone/Sources/Platforms/WebAssembly/WebAssemblyViewport.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Platforms/WebAssembly/WebAssemblyViewport.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -178,7 +178,6 @@
       that->controller_->HandleMousePress(*that->interactor_, pointer,
                                           that->compositor_->GetCanvasWidth(),
                                           that->compositor_->GetCanvasHeight());        
-      that->Invalidate();
     }
 
     LOG(TRACE) << "Exiting: " << __func__;
@@ -196,11 +195,8 @@
       {
         PointerEvent pointer;
         ConvertMouseEvent(pointer, *mouseEvent, *that->compositor_);
-      
-        if (that->controller_->HandleMouseMove(pointer))
-        {
-          that->Invalidate();
-        }
+
+        that->controller_->HandleMouseMove(pointer);
       }
       else if (that->interactor_.get() != NULL &&
                that->interactor_->HasMouseHover())
@@ -230,7 +226,6 @@
       PointerEvent pointer;
       ConvertMouseEvent(pointer, *mouseEvent, *that->compositor_);
       that->controller_->HandleMouseRelease(pointer);
-      that->Invalidate();
     }
 
     LOG(TRACE) << "Exiting: " << __func__;
@@ -357,14 +352,12 @@
           that->controller_->HandleMousePress(*that->interactor_, event,
                                               that->compositor_->GetCanvasWidth(),
                                               that->compositor_->GetCanvasHeight());
-          that->Invalidate();
           break;
 
         case EMSCRIPTEN_EVENT_TOUCHMOVE:
-          if (that->controller_->HasActiveTracker() &&
-              that->controller_->HandleMouseMove(event))
+          if (that->controller_->HasActiveTracker())
           {
-            that->Invalidate();
+            that->controller_->HandleMouseMove(event);
           }
           break;
 
@@ -373,7 +366,6 @@
           if (that->controller_->HasActiveTracker())
           {
             that->controller_->HandleMouseRelease(event);
-            that->Invalidate();
           }
           break;
 
--- a/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -1050,13 +1050,15 @@
     {
     }
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE
     {
       primitive_.MovePreview(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_, scene);
 
       that_.BroadcastMessage(AnnotationChangedMessage(that_));
       that_.Render(scene);
+
+      return true;
     }
       
     virtual void PointerUp(const PointerEvent& event,
@@ -2395,7 +2397,7 @@
              annotation_->GetHandlesCount() >= 2);
     }
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE
     {
       if (annotation_ != NULL)
@@ -2405,6 +2407,11 @@
 
         layer_.BroadcastMessage(AnnotationChangedMessage(layer_));
         layer_.Render(scene);
+        return true;
+      }
+      else
+      {
+        return false;
       }
     }
       
@@ -2458,15 +2465,18 @@
       length_ = new LengthAnnotation(that, that.GetUnits(), false /* no length label */, sceneClick, sceneClick);
     }
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE
     {
+      bool redraw = false;
+
       if (length_ != NULL)
       {
         length_->GetHandle(1).SetCenter(event.GetMainPosition().Apply(canvasToScene_));
         length_->SignalMove(length_->GetHandle(1), scene);
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
         that_.Render(scene);
+        redraw = true;
       }
 
       if (angle_ != NULL)
@@ -2475,7 +2485,10 @@
         angle_->SignalMove(angle_->GetHandle(2), scene);
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
         that_.Render(scene);
+        redraw = true;
       }
+
+      return redraw;
     }
       
     virtual void PointerUp(const PointerEvent& event,
@@ -2546,9 +2559,10 @@
       that.Render(scene);
     }
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE
     {
+      return false;
     }
       
     virtual void PointerUp(const PointerEvent& event,
@@ -2611,9 +2625,10 @@
     {
     }
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE
     {
+      return false;
     }
       
     virtual void PointerUp(const PointerEvent& event,
--- a/OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -95,7 +95,7 @@
     };
   }
   
-  void GrayscaleWindowingSceneTracker::SetWindowing(float center,
+  bool GrayscaleWindowingSceneTracker::SetWindowing(float center,
                                                     float width)
   {
     if (active_)
@@ -108,8 +108,11 @@
         accessor.GetLayer().SetCustomWindowing(center, width);
         accessor.BroadcastGrayscaleWindowingChanged(center, width);
         accessor.Invalidate();
+        return true;
       }
-    }      
+    }
+
+    return false;
   }
     
 
@@ -154,7 +157,7 @@
     }
   }
   
-  void GrayscaleWindowingSceneTracker::PointerMove(const PointerEvent& event,
+  bool GrayscaleWindowingSceneTracker::PointerMove(const PointerEvent& event,
                                                    Scene2D& scene)
   {
     if (active_)
@@ -170,7 +173,11 @@
         width = 1;
       }
       
-      SetWindowing(center, width);
+      return SetWindowing(center, width);
+    }
+    else
+    {
+      return false;
     }
   }
 
--- a/OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -43,7 +43,7 @@
     double  clickX_;
     double  clickY_;
 
-    void SetWindowing(float center,
+    bool SetWindowing(float center,
                       float width);
     
   public:
@@ -53,7 +53,7 @@
                                    unsigned int canvasWidth,
                                    unsigned int canvasHeight);
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void Cancel(Scene2D& scene) ORTHANC_OVERRIDE;
--- a/OrthancStone/Sources/Scene2D/MagnifyingGlassTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/MagnifyingGlassTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -69,7 +69,7 @@
   }
 
   
-  void MagnifyingGlassTracker::PointerMove(const PointerEvent& event,
+  bool MagnifyingGlassTracker::PointerMove(const PointerEvent& event,
                                            Scene2D& scene)
   {
     ViewportLocker locker(viewport_);
@@ -77,6 +77,11 @@
     if (locker.IsValid())
     {
       Update(locker, event);
+      return true;
+    }
+    else
+    {
+      return false;
     }
   }
     
--- a/OrthancStone/Sources/Scene2D/MagnifyingGlassTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/MagnifyingGlassTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -48,7 +48,7 @@
     virtual void PointerUp(const PointerEvent& event,
                            Scene2D& scene) ORTHANC_OVERRIDE;
     
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void Cancel(Scene2D& scene) ORTHANC_OVERRIDE;
--- a/OrthancStone/Sources/Scene2D/PanSceneTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/PanSceneTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -43,7 +43,7 @@
   }
 
 
-  void PanSceneTracker::PointerMove(const PointerEvent& event,
+  bool PanSceneTracker::PointerMove(const PointerEvent& event,
                                     Scene2D& scene)
   {
     ScenePoint2D p = event.GetMainPosition().Apply(originalCanvasToScene_);
@@ -58,7 +58,10 @@
           AffineTransform2D::CreateOffset(p.GetX() - pivot_.GetX(),
                                           p.GetY() - pivot_.GetY())));
       locker.Invalidate();
+      return true;
     }
+
+    return false;
   }
 
   void PanSceneTracker::Cancel(Scene2D& scene)
--- a/OrthancStone/Sources/Scene2D/PanSceneTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/PanSceneTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -39,9 +39,9 @@
     PanSceneTracker(boost::weak_ptr<IViewport> viewport,
                     const PointerEvent& event);
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual void Cancel(Scene2D& scene) ORTHANC_OVERRIDE;
+
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE;
-    
-    virtual void Cancel(Scene2D& scene) ORTHANC_OVERRIDE;
   };
 }
--- a/OrthancStone/Sources/Scene2D/PinchZoomTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/PinchZoomTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -64,7 +64,7 @@
   }
 
 
-  void PinchZoomTracker::PointerMove(const PointerEvent &event,
+  bool PinchZoomTracker::PointerMove(const PointerEvent &event,
                                      Scene2D &scene)
   {
     if (state_ == State_OneFinger &&
@@ -97,7 +97,7 @@
       else
       {
         state_ = State_Dead;
-        return;
+        return true;
       }
 
       double distance = ScenePoint2D::DistancePtPt(event.GetPosition(0), event.GetPosition(1));
@@ -106,7 +106,7 @@
     else
     {
       state_ = State_Dead;
-      return;
+      return true;
     }
 
     {
@@ -121,6 +121,11 @@
             AffineTransform2D::CreateScaling(zoom),
             AffineTransform2D::CreateOffset(-pivot_.GetX(), -pivot_.GetY())));
         locker.Invalidate();
+        return true;
+      }
+      else
+      {
+        return false;
       }
     }
   }
--- a/OrthancStone/Sources/Scene2D/PinchZoomTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/PinchZoomTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -52,7 +52,7 @@
     PinchZoomTracker(const boost::shared_ptr<IViewport>& viewport,
                      const PointerEvent& event);
 
-    virtual void PointerMove(const PointerEvent &event,
+    virtual bool PointerMove(const PointerEvent &event,
                              Scene2D &scene) ORTHANC_OVERRIDE;
 
     virtual void PointerUp(const PointerEvent &event,
--- a/OrthancStone/Sources/Scene2D/RotateSceneTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/RotateSceneTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -44,7 +44,7 @@
   }
 
   
-  void RotateSceneTracker::PointerMove(const PointerEvent& event,
+  bool RotateSceneTracker::PointerMove(const PointerEvent& event,
                                        Scene2D& scene)
   {
     if (aligner_.get() != NULL)
@@ -74,9 +74,12 @@
               originalSceneToCanvas_));
           aligner_->Apply(locker.GetController().GetScene());
           locker.Invalidate();
+          return true;
         }
       }
     }
+
+    return false;
   }
 
   
--- a/OrthancStone/Sources/Scene2D/RotateSceneTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/RotateSceneTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -44,7 +44,7 @@
     RotateSceneTracker(boost::weak_ptr<IViewport> viewport,
                        const PointerEvent& event);
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void Cancel(Scene2D& scene) ORTHANC_OVERRIDE;
--- a/OrthancStone/Sources/Scene2D/ZoomSceneTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/ZoomSceneTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -48,7 +48,7 @@
     }
   }
   
-  void ZoomSceneTracker::PointerMove(const PointerEvent& event,
+  bool ZoomSceneTracker::PointerMove(const PointerEvent& event,
                                      Scene2D& scene)
   {
     static const double MIN_ZOOM = -4;
@@ -89,8 +89,11 @@
             originalSceneToCanvas_));
         aligner_->Apply(locker.GetController().GetScene());
         locker.Invalidate();
+        return true;
       }
     }
+
+    return false;
   }
 
   void ZoomSceneTracker::Cancel(Scene2D& scene)
--- a/OrthancStone/Sources/Scene2D/ZoomSceneTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2D/ZoomSceneTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -47,7 +47,7 @@
                      const PointerEvent& event,
                      unsigned int canvasHeight);
 
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void Cancel(Scene2D& scene) ORTHANC_OVERRIDE;
--- a/OrthancStone/Sources/Scene2DViewport/CreateAngleMeasureTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/CreateAngleMeasureTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -47,7 +47,7 @@
   {
   }
 
-  void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event,
+  bool CreateAngleMeasureTracker::PointerMove(const PointerEvent& event,
                                               Scene2D& scene)
   {
     if (!alive_)
@@ -81,6 +81,7 @@
       //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << "     " <<
       //  "scenePos.GetY() = " << scenePos.GetY();
       lock->Invalidate();
+      return true;
     }
   }
 
--- a/OrthancStone/Sources/Scene2DViewport/CreateAngleMeasureTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/CreateAngleMeasureTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -45,7 +45,7 @@
 
     ~CreateAngleMeasureTracker();
 
-    virtual void PointerMove(const PointerEvent& e,
+    virtual bool PointerMove(const PointerEvent& e,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/CreateLineMeasureTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/CreateLineMeasureTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -48,7 +48,7 @@
 
   }
 
-  void CreateLineMeasureTracker::PointerMove(const PointerEvent& event,
+  bool CreateLineMeasureTracker::PointerMove(const PointerEvent& event,
                                              Scene2D& scene)
   {
     if (!alive_)
@@ -72,6 +72,7 @@
       assert(concreteThis != NULL);*/
 
     GetCommand()->SetEnd(scenePos);
+    return true;
   }
 
   void CreateLineMeasureTracker::PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/CreateLineMeasureTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/CreateLineMeasureTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -45,7 +45,7 @@
 
     ~CreateLineMeasureTracker();
 
-    virtual void PointerMove(const PointerEvent& e,
+    virtual bool PointerMove(const PointerEvent& e,
                              Scene2D& scene) ORTHANC_OVERRIDE;
 
     virtual void PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/EditAngleMeasureTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/EditAngleMeasureTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -50,7 +50,7 @@
 
   }
 
-  void EditAngleMeasureTracker::PointerMove(const PointerEvent& e,
+  bool EditAngleMeasureTracker::PointerMove(const PointerEvent& e,
                                             Scene2D& scene)
   {
     std::unique_ptr<IViewport::ILock> lock(GetViewportLock());
@@ -105,6 +105,8 @@
         LOG(WARNING) << "Warning: please retry the measuring tool editing operation!";
         break;
     }
+
+    return true;
   }
 
   void EditAngleMeasureTracker::PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/EditAngleMeasureTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/EditAngleMeasureTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -45,7 +45,7 @@
 
     ~EditAngleMeasureTracker();
 
-    virtual void PointerMove(const PointerEvent& e,
+    virtual bool PointerMove(const PointerEvent& e,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/EditLineMeasureTracker.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/EditLineMeasureTracker.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -46,7 +46,7 @@
     command_.reset(new EditLineMeasureCommand(measureTool, viewport));
   }
 
-  void EditLineMeasureTracker::PointerMove(const PointerEvent& e,
+  bool EditLineMeasureTracker::PointerMove(const PointerEvent& e,
                                            Scene2D& scene)
   {
     std::unique_ptr<IViewport::ILock> lock(GetViewportLock());
@@ -90,6 +90,8 @@
         LOG(WARNING) << "Warning: please retry the measuring tool editing operation!";
         break;
     }
+
+    return true;
   }
 
   void EditLineMeasureTracker::PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/EditLineMeasureTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/EditLineMeasureTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -48,7 +48,7 @@
       boost::weak_ptr<IViewport>      viewport,
       const PointerEvent&             e);
 
-    virtual void PointerMove(const PointerEvent& e,
+    virtual bool PointerMove(const PointerEvent& e,
                              Scene2D& scene) ORTHANC_OVERRIDE;
     
     virtual void PointerUp(const PointerEvent& e,
--- a/OrthancStone/Sources/Scene2DViewport/IFlexiblePointerTracker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/IFlexiblePointerTracker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -44,8 +44,10 @@
 
     /**
     This method will be repeatedly called during user interaction
+
+    Return "true" if the scene must be redrawn.
     */
-    virtual void PointerMove(const PointerEvent& event,
+    virtual bool PointerMove(const PointerEvent& event,
                              Scene2D& scene) = 0;
 
     /**
@@ -80,6 +82,6 @@
     its changes to the underlying model. If the model has been modified during
     tracker lifetime, it must be restored to its initial value
     */
-    virtual void Cancel(Scene2D& scene) = 0;
+    virtual void Cancel(Scene2D& scene) = 0;   // TODO Refactoring - Seems unused
   };
 }
--- a/OrthancStone/Sources/Scene2DViewport/ViewportController.cpp	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/ViewportController.cpp	Tue Oct 06 15:42:43 2026 +0200
@@ -30,7 +30,7 @@
 
 namespace OrthancStone
 {
-  ViewportController::ViewportController(boost::weak_ptr<IViewport> viewport) :
+  ViewportController::ViewportController(const boost::shared_ptr<IViewport>& viewport) :
     scene_(new Scene2D),
     viewport_(viewport)
   {
@@ -173,6 +173,18 @@
   }
 
 
+  void ViewportController::InvalidateViewport()
+  {
+    boost::shared_ptr<IViewport> sharedViewport(viewport_.lock());
+
+    if (sharedViewport)
+    {
+      std::unique_ptr<IViewport::ILock> lock(sharedViewport->Lock());
+      lock->Invalidate();
+    }
+  }
+
+
   void ViewportController::HandleMousePress(IViewportInteractor&  interactor,
                                             const PointerEvent&   event,
                                             unsigned int          viewportWidth,
@@ -197,6 +209,7 @@
         if (measureTools_[i]->HitTest(event.GetMainPosition()))
         {
           activeTracker_ = measureTools_[i]->CreateEditionTracker(event);
+          InvalidateViewport();
           return;
         }
       }
@@ -212,21 +225,21 @@
         activeTracker_.reset();
       }
     }
+
+    InvalidateViewport();
   }
 
-  bool ViewportController::HandleMouseMove(const PointerEvent& event)
+
+  void ViewportController::HandleMouseMove(const PointerEvent& event)
   {
-    if (activeTracker_)
+    if (activeTracker_ &&
+        activeTracker_->PointerMove(event, GetScene()))
     {
-      activeTracker_->PointerMove(event, GetScene());
-      return true;
-    }
-    else
-    {
-      return false;
+      InvalidateViewport();
     }
   }
 
+
   void ViewportController::HandleMouseRelease(const PointerEvent& event)
   {
     if (activeTracker_)
@@ -237,6 +250,8 @@
       {
         activeTracker_.reset();
       }
+
+      InvalidateViewport();
     }
   }
 }
--- a/OrthancStone/Sources/Scene2DViewport/ViewportController.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/ViewportController.h	Tue Oct 06 15:42:43 2026 +0200
@@ -111,7 +111,7 @@
       }
     };
 
-    explicit ViewportController(boost::weak_ptr<IViewport> viewport);
+    explicit ViewportController(const boost::shared_ptr<IViewport>& viewport);
 
     ~ViewportController();
 
@@ -203,9 +203,8 @@
                           unsigned int viewportWidth,
                           unsigned int viewportHeight);
 
-    // Must be expressed in canvas coordinates. Returns "true" if the
-    // state has changed, so that "Invalidate()" can be called.
-    bool HandleMouseMove(const PointerEvent& event);
+    // Must be expressed in canvas coordinates
+    void HandleMouseMove(const PointerEvent& event);
 
     // Must be expressed in canvas coordinates
     void HandleMouseRelease(const PointerEvent& event);
@@ -264,5 +263,7 @@
     boost::weak_ptr<UndoStack>                    undoStackW_;  // Global stack, possibly shared by all viewports
     std::vector<boost::shared_ptr<MeasureTool> >  measureTools_;
     boost::shared_ptr<IFlexiblePointerTracker>    activeTracker_;  // TODO - Couldn't this be a "std::unique_ptr"?
+
+    void InvalidateViewport();
   };
 }
--- a/OrthancStone/Sources/Viewport/IViewport.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Viewport/IViewport.h	Tue Oct 06 15:42:43 2026 +0200
@@ -61,7 +61,7 @@
       Do not store the result! Only access the compositor interface through
       the lock.
       */
-      virtual ViewportController& GetController() = 0;
+      virtual ViewportController& GetController() = 0;  // TODO Refactoring - Remove this
 
       virtual void Invalidate() = 0;
 
--- a/OrthancStone/Sources/Viewport/ViewportLocker.h	Tue Oct 06 14:48:10 2026 +0200
+++ b/OrthancStone/Sources/Viewport/ViewportLocker.h	Tue Oct 06 15:42:43 2026 +0200
@@ -27,6 +27,7 @@
 
 namespace OrthancStone
 {
+  // TODO Refactoring - Remove this class
   class ViewportLocker : public boost::noncopyable
   {
   private: