diff OrthancStone/Sources/Scene2DViewport/ViewportController.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Scene2DViewport/ViewportController.cpp@ab81ee8fce1f
children 82279abb92d0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancStone/Sources/Scene2DViewport/ViewportController.cpp	Tue Jul 07 16:21:02 2020 +0200
@@ -0,0 +1,307 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2020 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "ViewportController.h"
+
+#include "UndoStack.h"
+#include "MeasureCommands.h"
+
+#include "../StoneException.h"
+#include "../Scene2D/PanSceneTracker.h"
+#include "../Scene2D/RotateSceneTracker.h"
+#include "../Scene2D/ZoomSceneTracker.h"
+
+#include <boost/make_shared.hpp>
+
+namespace OrthancStone
+{
+  IFlexiblePointerTracker* DefaultViewportInteractor::CreateTracker(
+    boost::shared_ptr<IViewport>          viewport,
+    const PointerEvent& event,
+    unsigned int        viewportWidth,
+    unsigned int        viewportHeight)
+  {
+    switch (event.GetMouseButton())
+    {
+      case MouseButton_Left:
+        return new RotateSceneTracker(viewport, event);
+
+      case MouseButton_Middle:
+        return new PanSceneTracker(viewport, event);
+      
+      case MouseButton_Right:
+      {
+        if (viewportWidth != 0)
+        {
+          return new ZoomSceneTracker(viewport, event, viewportWidth);
+        }
+        else
+        {
+          return NULL;
+        }
+      }
+
+      default:
+        return NULL;
+    }
+  }
+
+  ViewportController::ViewportController(boost::shared_ptr<IViewport> viewport)
+    : viewport_(viewport)
+    , scene_(new Scene2D)
+    , canvasToSceneFactor_(1)
+  {
+    // undoStack_ is not default-initialized, which basically means empty.
+    // The controller must be able to cope with this.
+  }
+
+  ViewportController::~ViewportController()
+  {
+  }
+
+  void ViewportController::PushCommand(
+    boost::shared_ptr<MeasureCommand> command)
+  {
+    boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
+    if (undoStack.get() != NULL)
+    {
+      undoStack->PushCommand(command);
+    }
+    else
+    {
+      LOG(ERROR) << "Internal error: no undo stack!";
+    }
+  }
+
+  void ViewportController::Undo()
+  {
+    boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
+    if (undoStack.get() != NULL)
+    {
+      undoStack->Undo();
+    }
+    else
+    {
+      LOG(ERROR) << "Internal error: no undo stack!";
+    }
+  }
+
+  void ViewportController::Redo()
+  {
+    boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
+    if (undoStack.get() != NULL)
+    {
+      undoStack->Redo();
+    }
+    else
+    {
+      LOG(ERROR) << "Internal error: no undo stack!";
+    }
+  }
+
+  bool ViewportController::CanUndo() const
+  {
+    boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
+    if (undoStack.get() != NULL)
+    {
+      return undoStack->CanUndo();
+    }
+    else
+    {
+      LOG(ERROR) << "Internal error: no undo stack!";
+      return false;
+    }
+  }
+
+  bool ViewportController::CanRedo() const
+  {
+    boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
+    if (undoStack.get() != NULL)
+    {
+      return undoStack->CanRedo();
+    }
+    else
+    {
+      LOG(ERROR) << "Internal error: no undo stack!";
+      return false;
+    }
+  }
+  
+  std::vector<boost::shared_ptr<MeasureTool> > 
+    ViewportController::HitTestMeasureTools(ScenePoint2D p)
+  {
+    std::vector<boost::shared_ptr<MeasureTool> > ret;
+    
+    for (size_t i = 0; i < measureTools_.size(); ++i)
+    {
+      if (measureTools_[i]->HitTest(p))
+        ret.push_back(measureTools_[i]);
+    }
+    return ret;
+  }
+  
+  void ViewportController::ResetMeasuringToolsHighlight()
+  {
+    for (size_t i = 0; i < measureTools_.size(); ++i)
+    {
+      measureTools_[i]->ResetHighlightState();
+    }
+  }
+
+  OrthancStone::AffineTransform2D 
+    ViewportController::GetCanvasToSceneTransform() const
+  {
+    return scene_->GetCanvasToSceneTransform();
+  }
+
+  OrthancStone::AffineTransform2D 
+    ViewportController::GetSceneToCanvasTransform() const
+  {
+    return scene_->GetSceneToCanvasTransform();
+  }
+
+  void ViewportController::SetSceneToCanvasTransform(
+    const AffineTransform2D& transform)
+  {
+    scene_->SetSceneToCanvasTransform(transform);
+
+    canvasToSceneFactor_ = scene_->GetCanvasToSceneTransform().ComputeZoom();
+    BroadcastMessage(SceneTransformChanged(*this));
+  }
+
+  void ViewportController::FitContent(unsigned int viewportWidth,
+                                      unsigned int viewportHeight)
+  {
+    scene_->FitContent(viewportWidth, viewportHeight);
+    canvasToSceneFactor_ = scene_->GetCanvasToSceneTransform().ComputeZoom();
+    BroadcastMessage(SceneTransformChanged(*this));
+  }
+
+  void ViewportController::AddMeasureTool(
+    boost::shared_ptr<MeasureTool> measureTool)
+  {
+    ORTHANC_ASSERT(std::find(measureTools_.begin(), 
+                             measureTools_.end(), 
+                             measureTool) == measureTools_.end(), 
+                  "Duplicate measure tool");
+    measureTools_.push_back(measureTool);
+  }
+
+  void ViewportController::RemoveMeasureTool(
+    boost::shared_ptr<MeasureTool> measureTool)
+  {
+    ORTHANC_ASSERT(std::find(measureTools_.begin(), 
+                             measureTools_.end(), 
+                             measureTool) != measureTools_.end(), 
+                  "Measure tool not found");
+    measureTools_.erase(
+      std::remove(measureTools_.begin(), measureTools_.end(), measureTool), 
+      measureTools_.end());
+  }
+
+  double ViewportController::GetCanvasToSceneFactor() const
+  {
+    return canvasToSceneFactor_;
+  }
+
+  double ViewportController::GetHandleSideLengthS() const
+  {
+    return HANDLE_SIDE_LENGTH_CANVAS_COORD * GetCanvasToSceneFactor();
+  }
+
+  double ViewportController::GetAngleToolArcRadiusS() const
+  {
+    return ARC_RADIUS_CANVAS_COORD * GetCanvasToSceneFactor();
+  }
+
+  double ViewportController::GetHitTestMaximumDistanceS() const
+  {
+    return HIT_TEST_MAX_DISTANCE_CANVAS_COORD * GetCanvasToSceneFactor();
+  }
+
+  double ViewportController::GetAngleTopTextLabelDistanceS() const
+  {
+    return TEXT_CENTER_DISTANCE_CANVAS_COORD * GetCanvasToSceneFactor();
+  }
+
+
+  void ViewportController::HandleMousePress(
+    OrthancStone::IViewportInteractor&  interactor,
+    const PointerEvent&                 event,
+    unsigned int                        viewportWidth,
+    unsigned int                        viewportHeight)
+  {
+    if (activeTracker_)
+    {
+      // We are dealing with a multi-stage tracker (that is made of several 
+      // interactions)
+      activeTracker_->PointerDown(event);
+
+      if (!activeTracker_->IsAlive())
+      {
+        activeTracker_.reset();
+      }
+    }
+    else
+    {
+      // Check whether there is already a measure tool at that position
+      for (size_t i = 0; i < measureTools_.size(); ++i)
+      {
+        if (measureTools_[i]->HitTest(event.GetMainPosition()))
+        {
+          activeTracker_ = measureTools_[i]->CreateEditionTracker(event);
+          return;
+        }
+      }
+
+      // No measure tool, create new tracker from the interactor
+      activeTracker_.reset(interactor.CreateTracker(viewport_, 
+                                                    event, 
+                                                    viewportWidth, 
+                                                    viewportHeight));
+    }
+  }
+
+  bool ViewportController::HandleMouseMove(const PointerEvent& event)
+  {
+    if (activeTracker_)
+    {
+      activeTracker_->PointerMove(event);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+  void ViewportController::HandleMouseRelease(const PointerEvent& event)
+  {
+    if (activeTracker_)
+    {
+      activeTracker_->PointerUp(event);
+
+      if (!activeTracker_->IsAlive())
+      {
+        activeTracker_.reset();
+      }
+    }
+  }
+}