# HG changeset patch # User Benjamin Golinvaux # Date 1558427274 -7200 # Node ID 28b9e3a542003cedef439d32718f927199cd430e # Parent af0aa0c149fafb8a7045b399117bd95b1f78cb11 Undo mechanism implemented (not connected to UI yet). Undo stack and measuring tools are now handled by the ViewportController. Multi-touch does not crash trackers anymore. diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/AngleMeasureTool.cpp --- a/Framework/Scene2DViewport/AngleMeasureTool.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Tue May 21 10:27:54 2019 +0200 @@ -77,207 +77,209 @@ void AngleMeasureTool::RefreshScene() { - if (IsEnabled()) + if (IsSceneAlive()) { - // get the scaling factor - const double pixelToScene = - GetScene()->GetCanvasToSceneTransform().ComputeZoom(); - if (!layersCreated) + if (IsEnabled()) { - // Create the layers if need be + // get the scaling factor + const double pixelToScene = + GetScene()->GetCanvasToSceneTransform().ComputeZoom(); - assert(textBaseZIndex_ == -1); + if (!layersCreated) { - polylineZIndex_ = GetScene()->GetMaxDepth() + 100; - //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; - std::auto_ptr layer(new PolylineSceneLayer()); - GetScene()->SetLayer(polylineZIndex_, layer.release()); + // Create the layers if need be - } - { - textBaseZIndex_ = GetScene()->GetMaxDepth() + 100; - // create the four text background layers + assert(textBaseZIndex_ == -1); { - std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer(textBaseZIndex_, layer.release()); - } - { - std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer(textBaseZIndex_+1, layer.release()); - } - { - std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer(textBaseZIndex_+2, layer.release()); + polylineZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; + std::auto_ptr layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + } { - std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer(textBaseZIndex_+3, layer.release()); + textBaseZIndex_ = GetScene()->GetMaxDepth() + 100; + // create the four text background layers + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_, layer.release()); + } + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 1, layer.release()); + } + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 2, layer.release()); + } + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 3, layer.release()); + } + + // and the text layer itself + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 4, layer.release()); + } + } - - // and the text layer itself - { - std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer(textBaseZIndex_+4, layer.release()); - } - + layersCreated = true; + } + else + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textBaseZIndex_)); } - layersCreated = true; - } - else - { - assert(GetScene()->HasLayer(polylineZIndex_)); - assert(GetScene()->HasLayer(textBaseZIndex_)); - } - { - // Fill the polyline layer with the measurement line + { + // Fill the polyline layer with the measurement line + + PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + polylineLayer->ClearAllChains(); + polylineLayer->SetColor(0, 183, 17); - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); - polylineLayer->ClearAllChains(); - polylineLayer->SetColor(0, 183, 17); + // sides + { + { + PolylineSceneLayer::Chain chain; + chain.push_back(side1End_); + chain.push_back(center_); + polylineLayer->AddChain(chain, false); + } + { + PolylineSceneLayer::Chain chain; + chain.push_back(side2End_); + chain.push_back(center_); + polylineLayer->AddChain(chain, false); + } + } - // sides - { + // handles + { + //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), side1End_, 10.0 * pixelToScene); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), side2End_, 10.0 * pixelToScene); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + } + + // arc { PolylineSceneLayer::Chain chain; - chain.push_back(side1End_); - chain.push_back(center_); - polylineLayer->AddChain(chain, false); - } - { - PolylineSceneLayer::Chain chain; - chain.push_back(side2End_); - chain.push_back(center_); + + const double ARC_RADIUS_CANVAS_COORD = 30.0; + AddShortestArc(chain, *GetScene(), side1End_, center_, side2End_, + ARC_RADIUS_CANVAS_COORD * pixelToScene); polylineLayer->AddChain(chain, false); } } - - // handles { - //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), side1End_, 10.0* pixelToScene); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } + // Set the text layer - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), side2End_, 10.0* pixelToScene); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - } - - // arc - { - PolylineSceneLayer::Chain chain; - - const double ARC_RADIUS_CANVAS_COORD = 30.0; - AddShortestArc(chain, *GetScene(), side1End_, center_, side2End_, - ARC_RADIUS_CANVAS_COORD*pixelToScene); - polylineLayer->AddChain(chain, false); - } - } - { - // Set the text layer - - double p1cAngle = atan2( - side1End_.GetY() - center_.GetY(), - side1End_.GetX() - center_.GetX()); + double p1cAngle = atan2( + side1End_.GetY() - center_.GetY(), + side1End_.GetX() - center_.GetX()); - double p2cAngle = atan2( - side2End_.GetY() - center_.GetY(), - side2End_.GetX() - center_.GetX()); + double p2cAngle = atan2( + side2End_.GetY() - center_.GetY(), + side2End_.GetX() - center_.GetX()); - double delta = NormalizeAngle(p2cAngle - p1cAngle); + double delta = NormalizeAngle(p2cAngle - p1cAngle); - double theta = p1cAngle + delta/2; + double theta = p1cAngle + delta / 2; - const double TEXT_CENTER_DISTANCE_CANVAS_COORD = 90; + const double TEXT_CENTER_DISTANCE_CANVAS_COORD = 90; - double offsetX = TEXT_CENTER_DISTANCE_CANVAS_COORD * cos(theta); + double offsetX = TEXT_CENTER_DISTANCE_CANVAS_COORD * cos(theta); - double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); + double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); - double pointX = center_.GetX() + offsetX * pixelToScene; - double pointY = center_.GetY() + offsetY * pixelToScene; + double pointX = center_.GetX() + offsetX * pixelToScene; + double pointY = center_.GetY() + offsetY * pixelToScene; - char buf[64]; - double angleDeg = RadiansToDegrees(delta); + char buf[64]; + double angleDeg = RadiansToDegrees(delta); - // http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=00B0&mode=hex - sprintf(buf, "%0.02f\xc2\xb0", angleDeg); + // http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=00B0&mode=hex + sprintf(buf, "%0.02f\xc2\xb0", angleDeg); - SetTextLayerOutlineProperties( - *GetScene(), textBaseZIndex_, buf, ScenePoint2D(pointX, pointY)); + SetTextLayerOutlineProperties( + *GetScene(), textBaseZIndex_, buf, ScenePoint2D(pointX, pointY)); - // TODO:make it togglable - bool enableInfoDisplay = false; - if (enableInfoDisplay) - { - TrackerSample_SetInfoDisplayMessage("center_.GetX()", - boost::lexical_cast(center_.GetX())); + // TODO:make it togglable + bool enableInfoDisplay = false; + if (enableInfoDisplay) + { + TrackerSample_SetInfoDisplayMessage("center_.GetX()", + boost::lexical_cast(center_.GetX())); - TrackerSample_SetInfoDisplayMessage("center_.GetY()", - boost::lexical_cast(center_.GetY())); + TrackerSample_SetInfoDisplayMessage("center_.GetY()", + boost::lexical_cast(center_.GetY())); - TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", - boost::lexical_cast(side1End_.GetX())); + TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", + boost::lexical_cast(side1End_.GetX())); - TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", - boost::lexical_cast(side1End_.GetY())); + TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", + boost::lexical_cast(side1End_.GetY())); - TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", - boost::lexical_cast(side2End_.GetX())); + TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", + boost::lexical_cast(side2End_.GetX())); - TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", - boost::lexical_cast(side2End_.GetY())); + TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", + boost::lexical_cast(side2End_.GetY())); - TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", - boost::lexical_cast(RadiansToDegrees(p1cAngle))); + TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", + boost::lexical_cast(RadiansToDegrees(p1cAngle))); - TrackerSample_SetInfoDisplayMessage("delta (deg)", - boost::lexical_cast(RadiansToDegrees(delta))); + TrackerSample_SetInfoDisplayMessage("delta (deg)", + boost::lexical_cast(RadiansToDegrees(delta))); - TrackerSample_SetInfoDisplayMessage("theta (deg)", - boost::lexical_cast(RadiansToDegrees(theta))); + TrackerSample_SetInfoDisplayMessage("theta (deg)", + boost::lexical_cast(RadiansToDegrees(theta))); - TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", - boost::lexical_cast(RadiansToDegrees(p2cAngle))); + TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", + boost::lexical_cast(RadiansToDegrees(p2cAngle))); - TrackerSample_SetInfoDisplayMessage("offsetX (pix)", - boost::lexical_cast(offsetX)); + TrackerSample_SetInfoDisplayMessage("offsetX (pix)", + boost::lexical_cast(offsetX)); - TrackerSample_SetInfoDisplayMessage("offsetY (pix)", - boost::lexical_cast(offsetY)); + TrackerSample_SetInfoDisplayMessage("offsetY (pix)", + boost::lexical_cast(offsetY)); - TrackerSample_SetInfoDisplayMessage("pointX", - boost::lexical_cast(pointX)); + TrackerSample_SetInfoDisplayMessage("pointX", + boost::lexical_cast(pointX)); - TrackerSample_SetInfoDisplayMessage("pointY", - boost::lexical_cast(pointY)); + TrackerSample_SetInfoDisplayMessage("pointY", + boost::lexical_cast(pointY)); - TrackerSample_SetInfoDisplayMessage("angleDeg", - boost::lexical_cast(angleDeg)); - } + TrackerSample_SetInfoDisplayMessage("angleDeg", + boost::lexical_cast(angleDeg)); + } + } } - } - else - { - if (layersCreated) + else { - RemoveFromScene(); - layersCreated = false; + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } } } } - - } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp --- a/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Tue May 21 10:27:54 2019 +0200 @@ -28,17 +28,14 @@ CreateAngleMeasureTracker::CreateAngleMeasureTracker( MessageBroker& broker, ViewportControllerWPtr controllerW, - std::vector& undoStack, - MeasureToolList& measureTools, const PointerEvent& e) - : CreateMeasureTracker(controllerW, undoStack, measureTools) + : CreateMeasureTracker(controllerW) , state_(CreatingSide1) { command_.reset( new CreateAngleMeasureCommand( broker, controllerW, - measureTools, e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/CreateAngleMeasureTracker.h --- a/Framework/Scene2DViewport/CreateAngleMeasureTracker.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.h Tue May 21 10:27:54 2019 +0200 @@ -40,8 +40,6 @@ CreateAngleMeasureTracker( MessageBroker& broker, ViewportControllerWPtr controllerW, - std::vector& undoStack, - MeasureToolList& measureTools, const PointerEvent& e); ~CreateAngleMeasureTracker(); diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/CreateLineMeasureTracker.cpp --- a/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Tue May 21 10:27:54 2019 +0200 @@ -28,16 +28,13 @@ CreateLineMeasureTracker::CreateLineMeasureTracker( MessageBroker& broker, ViewportControllerWPtr controllerW, - std::vector& undoStack, - MeasureToolList& measureTools, const PointerEvent& e) - : CreateMeasureTracker(controllerW, undoStack, measureTools) + : CreateMeasureTracker(controllerW) { command_.reset( new CreateLineMeasureCommand( broker, controllerW, - measureTools, e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/CreateLineMeasureTracker.h --- a/Framework/Scene2DViewport/CreateLineMeasureTracker.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.h Tue May 21 10:27:54 2019 +0200 @@ -37,8 +37,6 @@ CreateLineMeasureTracker( MessageBroker& broker, ViewportControllerWPtr controllerW, - std::vector& undoStack, - MeasureToolList& measureTools, const PointerEvent& e); ~CreateLineMeasureTracker(); diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/IFlexiblePointerTracker.h --- a/Framework/Scene2DViewport/IFlexiblePointerTracker.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/IFlexiblePointerTracker.h Tue May 21 10:27:54 2019 +0200 @@ -53,6 +53,12 @@ /** This method will be called when a touch/pointer is added (mouse down, pen or finger press) + + Important note: the initial pointer down that leads to creating the + tracker is NOT sent to the tracker. + + Thus, if you count the PointerDown vs PointerUp, there will be an extra + PointerUp. */ virtual void PointerDown(const PointerEvent& event) = 0; diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/LineMeasureTool.cpp --- a/Framework/Scene2DViewport/LineMeasureTool.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Tue May 21 10:27:54 2019 +0200 @@ -85,116 +85,117 @@ void LineMeasureTool::RefreshScene() { - if (IsEnabled()) + if (IsSceneAlive()) { - if (!layersCreated) + if (IsEnabled()) { - // Create the layers if need be + if (!layersCreated) + { + // Create the layers if need be - assert(textZIndex_ == -1); + assert(textZIndex_ == -1); + { + polylineZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; + std::auto_ptr layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + } + { + textZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textZIndex_, layer.release()); + } + layersCreated = true; + } + else { - polylineZIndex_ = GetScene()->GetMaxDepth() + 100; - //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; - std::auto_ptr layer(new PolylineSceneLayer()); - GetScene()->SetLayer(polylineZIndex_, layer.release()); + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textZIndex_)); } { - textZIndex_ = GetScene()->GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer(textZIndex_, layer.release()); - } - layersCreated = true; - } - else - { - assert(GetScene()->HasLayer(polylineZIndex_)); - assert(GetScene()->HasLayer(textZIndex_)); - } - { - // Fill the polyline layer with the measurement line + // Fill the polyline layer with the measurement line - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); - polylineLayer->ClearAllChains(); - polylineLayer->SetColor(0, 223, 21); - - { - PolylineSceneLayer::Chain chain; - chain.push_back(start_); - chain.push_back(end_); - polylineLayer->AddChain(chain, false); - } - - // handles - { - //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), start_, 10.0); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } + PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + polylineLayer->ClearAllChains(); + polylineLayer->SetColor(0, 223, 21); { PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), end_, 10.0); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); + chain.push_back(start_); + chain.push_back(end_); + polylineLayer->AddChain(chain, false); } - //ScenePoint2D startC = start_.Apply(GetScene()->GetSceneToCanvasTransform()); - //double squareSize = 10.0; - //double startHandleLX = startC.GetX() - squareSize/2; - //double startHandleTY = startC.GetY() - squareSize / 2; - //double startHandleRX = startC.GetX() + squareSize / 2; - //double startHandleBY = startC.GetY() + squareSize / 2; - //ScenePoint2D startLTC(startHandleLX, startHandleTY); - //ScenePoint2D startRTC(startHandleRX, startHandleTY); - //ScenePoint2D startRBC(startHandleRX, startHandleBY); - //ScenePoint2D startLBC(startHandleLX, startHandleBY); + // handles + { + //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), start_, 10.0); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), end_, 10.0); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + //ScenePoint2D startC = start_.Apply(GetScene()->GetSceneToCanvasTransform()); + //double squareSize = 10.0; + //double startHandleLX = startC.GetX() - squareSize/2; + //double startHandleTY = startC.GetY() - squareSize / 2; + //double startHandleRX = startC.GetX() + squareSize / 2; + //double startHandleBY = startC.GetY() + squareSize / 2; + //ScenePoint2D startLTC(startHandleLX, startHandleTY); + //ScenePoint2D startRTC(startHandleRX, startHandleTY); + //ScenePoint2D startRBC(startHandleRX, startHandleBY); + //ScenePoint2D startLBC(startHandleLX, startHandleBY); - //ScenePoint2D startLT = startLTC.Apply(GetScene()->GetCanvasToSceneTransform()); - //ScenePoint2D startRT = startRTC.Apply(GetScene()->GetCanvasToSceneTransform()); - //ScenePoint2D startRB = startRBC.Apply(GetScene()->GetCanvasToSceneTransform()); - //ScenePoint2D startLB = startLBC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startLT = startLTC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startRT = startRTC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startRB = startRBC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startLB = startLBC.Apply(GetScene()->GetCanvasToSceneTransform()); + + //PolylineSceneLayer::Chain chain; + //chain.push_back(startLT); + //chain.push_back(startRT); + //chain.push_back(startRB); + //chain.push_back(startLB); + //polylineLayer->AddChain(chain, true); + } + + } + { + // Set the text layer proporeties - //PolylineSceneLayer::Chain chain; - //chain.push_back(startLT); - //chain.push_back(startRT); - //chain.push_back(startRB); - //chain.push_back(startLB); - //polylineLayer->AddChain(chain, true); + TextSceneLayer* textLayer = GetTextLayer(); + double deltaX = end_.GetX() - start_.GetX(); + double deltaY = end_.GetY() - start_.GetY(); + double squareDist = deltaX * deltaX + deltaY * deltaY; + double dist = sqrt(squareDist); + char buf[64]; + sprintf(buf, "%0.02f units", dist); + textLayer->SetText(buf); + textLayer->SetColor(0, 223, 21); + + // TODO: for now we simply position the text overlay at the middle + // of the measuring segment + double midX = 0.5 * (end_.GetX() + start_.GetX()); + double midY = 0.5 * (end_.GetY() + start_.GetY()); + textLayer->SetPosition(midX, midY); } - } + else { - // Set the text layer proporeties - - TextSceneLayer* textLayer = GetTextLayer(); - double deltaX = end_.GetX() - start_.GetX(); - double deltaY = end_.GetY() - start_.GetY(); - double squareDist = deltaX * deltaX + deltaY * deltaY; - double dist = sqrt(squareDist); - char buf[64]; - sprintf(buf, "%0.02f units", dist); - textLayer->SetText(buf); - textLayer->SetColor(0, 223, 21); - - // TODO: for now we simply position the text overlay at the middle - // of the measuring segment - double midX = 0.5*(end_.GetX() + start_.GetX()); - double midY = 0.5*(end_.GetY() + start_.GetY()); - textLayer->SetPosition(midX, midY); - } - } - else - { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } } } } - - } \ No newline at end of file diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/MeasureCommands.cpp --- a/Framework/Scene2DViewport/MeasureCommands.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureCommands.cpp Tue May 21 10:27:54 2019 +0200 @@ -20,23 +20,24 @@ #include "MeasureCommands.h" +#include +#include + namespace OrthancStone { void CreateMeasureCommand::Undo() { // simply disable the measure tool upon undo - GetMeasureTool()->Disable(); + GetController()->RemoveMeasureTool(GetMeasureTool()); } void CreateMeasureCommand::Redo() { - GetMeasureTool()->Enable(); + GetController()->AddMeasureTool(GetMeasureTool()); } - CreateMeasureCommand::CreateMeasureCommand( - ViewportControllerWPtr controllerW, MeasureToolList& measureTools) + CreateMeasureCommand::CreateMeasureCommand(ViewportControllerWPtr controllerW) : TrackerCommand(controllerW) - , measureTools_(measureTools) { } @@ -50,12 +51,12 @@ CreateLineMeasureCommand::CreateLineMeasureCommand( MessageBroker& broker, ViewportControllerWPtr controllerW, - MeasureToolList& measureTools, ScenePoint2D point) - : CreateMeasureCommand(controllerW, measureTools) - , measureTool_(new LineMeasureTool(broker, controllerW)) + : CreateMeasureCommand(controllerW) + , measureTool_( + boost::make_shared(boost::ref(broker), controllerW)) { - measureTools_.push_back(measureTool_); + GetController()->AddMeasureTool(measureTool_); measureTool_->Set(point, point); } @@ -67,12 +68,12 @@ CreateAngleMeasureCommand::CreateAngleMeasureCommand( MessageBroker& broker, ViewportControllerWPtr controllerW, - MeasureToolList& measureTools, ScenePoint2D point) - : CreateMeasureCommand(controllerW, measureTools) - , measureTool_(new AngleMeasureTool(broker, controllerW)) + : CreateMeasureCommand(controllerW) + , measureTool_( + boost::make_shared(boost::ref(broker), controllerW)) { - measureTools_.push_back(measureTool_); + GetController()->AddMeasureTool(measureTool_); measureTool_->SetSide1End(point); measureTool_->SetCenter(point); measureTool_->SetSide2End(point); @@ -90,4 +91,10 @@ measureTool_->SetSide2End(scenePos); } + ViewportControllerPtr TrackerCommand::GetController() + { + ViewportControllerPtr controller = controllerW_.lock(); + assert(controller); // accessing dead object? + return controller; + } } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/MeasureCommands.h --- a/Framework/Scene2DViewport/MeasureCommands.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureCommands.h Tue May 21 10:27:54 2019 +0200 @@ -43,19 +43,17 @@ virtual void Redo() = 0; protected: + ViewportControllerPtr GetController(); ViewportControllerWPtr controllerW_; }; class CreateMeasureCommand : public TrackerCommand { public: - CreateMeasureCommand( - ViewportControllerWPtr controllerW, MeasureToolList& measureTools); + CreateMeasureCommand(ViewportControllerWPtr controllerW); ~CreateMeasureCommand(); virtual void Undo() ORTHANC_OVERRIDE; virtual void Redo() ORTHANC_OVERRIDE; - protected: - MeasureToolList& measureTools_; private: /** Must be implemented by the subclasses that create the actual tool */ virtual MeasureToolPtr GetMeasureTool() = 0; @@ -67,7 +65,6 @@ CreateLineMeasureCommand( MessageBroker& broker, ViewportControllerWPtr controllerW, - MeasureToolList& measureTools, ScenePoint2D point); // the starting position is set in the ctor @@ -89,7 +86,6 @@ CreateAngleMeasureCommand( MessageBroker& broker, ViewportControllerWPtr controllerW, - MeasureToolList& measureTools, ScenePoint2D point); /** This method sets center*/ diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/MeasureTools.cpp --- a/Framework/Scene2DViewport/MeasureTools.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTools.cpp Tue May 21 10:27:54 2019 +0200 @@ -79,6 +79,13 @@ (*this, &MeasureTool::OnSceneTransformChanged)); } + + bool MeasureTool::IsSceneAlive() const + { + ViewportControllerPtr controller = controllerW_.lock(); + return (controller.get() != NULL); + } + void MeasureTool::OnSceneTransformChanged( const ViewportController::SceneTransformChanged& message) { diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/MeasureTools.h --- a/Framework/Scene2DViewport/MeasureTools.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTools.h Tue May 21 10:27:54 2019 +0200 @@ -63,6 +63,13 @@ protected: MeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW); + + /** + The measuring tool may exist in a standalone fashion, without any available + scene (because the controller is dead or dying). This call allows to check + before accessing the scene. + */ + bool IsSceneAlive() const; /** This is the meat of the tool: this method must [create (if needed) and] diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/MeasureTrackers.cpp --- a/Framework/Scene2DViewport/MeasureTrackers.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTrackers.cpp Tue May 21 10:27:54 2019 +0200 @@ -26,14 +26,9 @@ namespace OrthancStone { - CreateMeasureTracker::CreateMeasureTracker( - ViewportControllerWPtr controllerW, - std::vector& undoStack, - std::vector& measureTools) + CreateMeasureTracker::CreateMeasureTracker(ViewportControllerWPtr controllerW) : controllerW_(controllerW) , alive_(true) - , undoStack_(undoStack) - , measureTools_(measureTools) , commitResult_(true) { } @@ -56,12 +51,11 @@ // otherwise, we simply undo it if (commitResult_) - undoStack_.push_back(command_); + controllerW_.lock()->PushCommand(command_); else command_->Undo(); } - OrthancStone::Scene2DPtr CreateMeasureTracker::GetScene() { return controllerW_.lock()->GetScene(); diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/MeasureTrackers.h --- a/Framework/Scene2DViewport/MeasureTrackers.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTrackers.h Tue May 21 10:27:54 2019 +0200 @@ -37,10 +37,7 @@ virtual void Cancel() ORTHANC_OVERRIDE; virtual bool IsAlive() const ORTHANC_OVERRIDE; protected: - CreateMeasureTracker( - ViewportControllerWPtr controllerW, - std::vector& undoStack, - std::vector& measureTools); + CreateMeasureTracker(ViewportControllerWPtr controllerW); ~CreateMeasureTracker(); @@ -51,8 +48,6 @@ Scene2DPtr GetScene(); private: - std::vector& undoStack_; - std::vector& measureTools_; bool commitResult_; }; } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/OneGesturePointerTracker.cpp --- a/Framework/Scene2DViewport/OneGesturePointerTracker.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/OneGesturePointerTracker.cpp Tue May 21 10:27:54 2019 +0200 @@ -23,6 +23,8 @@ #include +#include + using namespace Orthanc; namespace OrthancStone @@ -31,17 +33,30 @@ ViewportControllerWPtr controllerW) : controllerW_(controllerW) , alive_(true) + , currentTouchCount_(1) { } void OneGesturePointerTracker::PointerUp(const PointerEvent& event) { - alive_ = false; + // pointer up is only called for the LAST up event in case of a multi-touch + // gesture + ORTHANC_ASSERT(currentTouchCount_ > 0, "Wrong state in tracker"); + currentTouchCount_--; + LOG(INFO) << "currentTouchCount_ becomes: " << currentTouchCount_; + if (currentTouchCount_ == 0) + { + LOG(INFO) << "currentTouchCount_ == 0 --> alive_ = false"; + alive_ = false; + } } void OneGesturePointerTracker::PointerDown(const PointerEvent& event) { - throw OrthancException(ErrorCode_InternalError, "Wrong state in tracker"); + // additional touches are not taken into account but we need to count + // the number of active touches + currentTouchCount_++; + LOG(INFO) << "currentTouchCount_ becomes: " << currentTouchCount_; } bool OneGesturePointerTracker::IsAlive() const diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/OneGesturePointerTracker.h --- a/Framework/Scene2DViewport/OneGesturePointerTracker.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/OneGesturePointerTracker.h Tue May 21 10:27:54 2019 +0200 @@ -26,14 +26,15 @@ { /** This base is class allows to write simple trackers that deal with single - drag gestures. It is *not* suitables for multi-state trackers where various - mouse operations need to be handled. + drag gestures with only one touch. It is *not* suitable for multi-touch and + multi-state trackers where various mouse operations need to be handled. In order to write such a tracker: - subclass this class - you may store the initial click/touch position in the constructor - implement PointerMove to react to pointer/touch events - implement Cancel to restore the state at initial tracker creation time + */ class OneGesturePointerTracker : public IFlexiblePointerTracker { @@ -49,6 +50,7 @@ private: ViewportControllerWPtr controllerW_; bool alive_; + int currentTouchCount_; }; } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/PointerTypes.h --- a/Framework/Scene2DViewport/PointerTypes.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/PointerTypes.h Tue May 21 10:27:54 2019 +0200 @@ -37,8 +37,6 @@ MeasureToolPtr; typedef boost::weak_ptr MeasureToolWPtr; - typedef std::vector - MeasureToolList; class LineMeasureTool; typedef boost::shared_ptr diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/ViewportController.cpp --- a/Framework/Scene2DViewport/ViewportController.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.cpp Tue May 21 10:27:54 2019 +0200 @@ -19,6 +19,7 @@ **/ #include "ViewportController.h" +#include "MeasureCommands.h" #include @@ -30,6 +31,7 @@ { ViewportController::ViewportController(MessageBroker& broker) : IObservable(broker) + , numAppliedCommands_(0) { scene_ = boost::make_shared(); } @@ -81,5 +83,55 @@ BroadcastMessage(SceneTransformChanged(*this)); } + void ViewportController::PushCommand(TrackerCommandPtr command) + { + commandStack_.erase( + commandStack_.begin() + numAppliedCommands_, + commandStack_.end()); + + ORTHANC_ASSERT(std::find(commandStack_.begin(), commandStack_.end(), command) + == commandStack_.end(), "Duplicate command"); + commandStack_.push_back(command); + numAppliedCommands_++; + } + + void ViewportController::Undo() + { + ORTHANC_ASSERT(CanUndo(), ""); + commandStack_[numAppliedCommands_-1]->Undo(); + numAppliedCommands_--; + } + + void ViewportController::Redo() + { + ORTHANC_ASSERT(CanRedo(), ""); + commandStack_[numAppliedCommands_]->Redo(); + numAppliedCommands_++; + } + + bool ViewportController::CanUndo() const + { + return numAppliedCommands_ > 0; + } + + bool ViewportController::CanRedo() const + { + return numAppliedCommands_ < commandStack_.size(); + } + + void ViewportController::AddMeasureTool(MeasureToolPtr measureTool) + { + ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool) + == measureTools_.end(), "Duplicate measure tool"); + measureTools_.push_back(measureTool); + } + + void ViewportController::RemoveMeasureTool(MeasureToolPtr measureTool) + { + ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool) + != measureTools_.end(), "Measure tool not found"); + measureTools_.push_back(measureTool); + } + } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/Scene2DViewport/ViewportController.h --- a/Framework/Scene2DViewport/ViewportController.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.h Tue May 21 10:27:54 2019 +0200 @@ -26,6 +26,8 @@ #include #include +#include + namespace OrthancStone { /** @@ -81,8 +83,54 @@ /** Forwarded to the underlying scene, and broadcasted to the observers */ void FitContent(unsigned int canvasWidth, unsigned int canvasHeight); + /** + Stores a command : + - this first trims the undo stack to keep the first numAppliedCommands_ + - then it adds the supplied command at the top of the undo stack + + In other words, when a new command is pushed, all the undone (and not + redone) commands are removed. + */ + void PushCommand(TrackerCommandPtr command); + + /** + Undoes the command at the top of the undo stack, or throws if there is no + command to undo. + You can check "CanUndo" first to protect against extraneous redo. + */ + void Undo(); + + /** + Redoes the command that is just above the last applied command in the undo + stack or throws if there is no command to redo. + You can check "CanRedo" first to protect against extraneous redo. + */ + void Redo(); + + /** selfexpl */ + bool CanUndo() const; + + /** selfexpl */ + bool CanRedo() const; + + /** Adds a new measure tool */ + void AddMeasureTool(MeasureToolPtr measureTool); + + /** Removes a measure tool or throws if it cannot be found */ + void RemoveMeasureTool(MeasureToolPtr measureTool); + private: - Scene2DPtr scene_; - FlexiblePointerTrackerPtr tracker_; + std::vector commandStack_; + + /** + This is always between >= 0 and <= undoStack_.size() and gives the + position where the controller is in the undo stack. + - If numAppliedCommands_ > 0, one can undo + - If numAppliedCommands_ < numAppliedCommands_.size(), one can redo + */ + size_t numAppliedCommands_; + std::vector measureTools_; + Scene2DPtr scene_; + FlexiblePointerTrackerPtr tracker_; }; } diff -r af0aa0c149fa -r 28b9e3a54200 Framework/StoneException.h --- a/Framework/StoneException.h Mon May 20 12:49:29 2019 +0200 +++ b/Framework/StoneException.h Tue May 21 10:27:54 2019 +0200 @@ -113,3 +113,13 @@ } +// See https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-multi-stmts +// (or google "Multiple lines macro C++ faq lite" if link is dead) +#define ORTHANC_ASSERT(cond,streamChainMessage) \ + if (!(cond)) { \ + std::stringstream sst; \ + sst << "Assertion failed. Condition = \"" #cond "\" Message = \"" << streamChainMessage << "\""; \ + std::string sstr = sst.str(); \ + throw OrthancException(ErrorCode_InternalError,sstr.c_str()); \ + } else (void)0 + diff -r af0aa0c149fa -r 28b9e3a54200 Platforms/Wasm/wasm-application-runner.ts --- a/Platforms/Wasm/wasm-application-runner.ts Mon May 20 12:49:29 2019 +0200 +++ b/Platforms/Wasm/wasm-application-runner.ts Tue May 21 10:27:54 2019 +0200 @@ -22,6 +22,15 @@ var StartWasmApplication: Function = null; export var SendSerializedMessageToStoneApplication: Function = null; +var auxiliaryParameters : Map = null; + +export function SetApplicationParameters(params : Map) { + if (auxiliaryParameters != null) { + console.warn("wasm-application-runner.SetApplicationParameters: about to overwrite the existing application parameters!") + } + auxiliaryParameters = params; +} + function DoAnimationThread() { if (WasmDoAnimation != null) { WasmDoAnimation(); @@ -31,6 +40,7 @@ setTimeout(DoAnimationThread, 100); } + function GetUriParameters(): Map { var parameters = window.location.search.substr(1); @@ -63,7 +73,16 @@ CreateWasmApplication(); - // parse uri and transmit the parameters to the app before initializing it + // transmit the API-specified parameters to the app before initializing it + for (let key in auxiliaryParameters) { + if (auxiliaryParameters.hasOwnProperty(key)) { + Logger.defaultLogger.debug( + `About to call SetStartupParameter("${key}","${auxiliaryParameters[key]}")`); + SetStartupParameter(key, auxiliaryParameters[key]); + } + } + + // parse uri and transmit the URI parameters to the app before initializing it let parameters = GetUriParameters(); for (let key in parameters) { diff -r af0aa0c149fa -r 28b9e3a54200 Samples/Sdl/TrackerSampleApp.cpp --- a/Samples/Sdl/TrackerSampleApp.cpp Mon May 20 12:49:29 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.cpp Tue May 21 10:27:54 2019 +0200 @@ -322,17 +322,17 @@ return FlexiblePointerTrackerPtr(new ZoomSceneTracker( controller_, e, compositor_->GetCanvasHeight())); //case GuiTool_AngleMeasure: - // return new AngleMeasureTracker(GetScene(), measureTools_, undoStack_, e); + // return new AngleMeasureTracker(GetScene(), e); //case GuiTool_CircleMeasure: - // return new CircleMeasureTracker(GetScene(), measureTools_, undoStack_, e); + // return new CircleMeasureTracker(GetScene(), e); //case GuiTool_EllipseMeasure: - // return new EllipseMeasureTracker(GetScene(), measureTools_, undoStack_, e); + // return new EllipseMeasureTracker(GetScene(), e); case GuiTool_LineMeasure: return FlexiblePointerTrackerPtr(new CreateLineMeasureTracker( - IObserver::GetBroker(), controller_, undoStack_, measureTools_, e)); + IObserver::GetBroker(), controller_, e)); case GuiTool_AngleMeasure: return FlexiblePointerTrackerPtr(new CreateAngleMeasureTracker( - IObserver::GetBroker(), controller_, undoStack_, measureTools_, e)); + IObserver::GetBroker(), controller_, e)); case GuiTool_CircleMeasure: LOG(ERROR) << "Not implemented yet!"; return FlexiblePointerTrackerPtr(); diff -r af0aa0c149fa -r 28b9e3a54200 Samples/Sdl/TrackerSampleApp.h --- a/Samples/Sdl/TrackerSampleApp.h Mon May 20 12:49:29 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Tue May 21 10:27:54 2019 +0200 @@ -114,14 +114,9 @@ std::map infoTextMap_; FlexiblePointerTrackerPtr activeTracker_; - std::vector undoStack_; - - // we store the measure tools here so that they don't get deleted - std::vector measureTools_; //static const int LAYER_POSITION = 150; - int TEXTURE_2x2_1_ZINDEX; int TEXTURE_1x1_ZINDEX; int TEXTURE_2x2_2_ZINDEX;