Mercurial > hg > orthanc-stone
changeset 530:64782d018fc4 bgo-commands-codegen
Merged am-touch-events
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Sun, 17 Mar 2019 20:16:21 +0100 |
parents | 7b29a8599318 (diff) 2549363fadc3 (current diff) |
children | 32dc5af8ab99 |
files | |
diffstat | 22 files changed, 1314 insertions(+), 388 deletions(-) [+] |
line wrap: on
line diff
--- a/Applications/Commands/BaseCommandBuilder.cpp Tue Mar 12 17:29:12 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 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 "BaseCommandBuilder.h" -#include "Core/OrthancException.h" -#include <iostream> -#include "Framework/StoneException.h" - -namespace OrthancStone -{ - ICommand* BaseCommandBuilder::CreateFromJson(const Json::Value& commandJson) - { - if (!commandJson.isObject() || !commandJson["command"].isString()) - { - throw StoneException(ErrorCode_CommandJsonInvalidFormat); - } - - if (commandJson["commandType"].isString() && commandJson["commandType"].asString() == "generic-no-arg-command") - { - return new GenericNoArgCommand(commandJson["command"].asString().c_str()); - } - else if (commandJson["commandType"].isString() && commandJson["commandType"].asString() == "generic-one-string-arg-command") - { - // TODO: we should create a command with a string arg ! - return new GenericNoArgCommand(commandJson["command"].asString().c_str()); - } - - return NULL; - } - -}
--- a/Applications/Commands/BaseCommandBuilder.h Tue Mar 12 17:29:12 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 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/>. - **/ - -#pragma once - -#include <map> -#include <memory> - -#include "ICommand.h" -#include "../../Applications/Commands/ICommandBuilder.h" - -// TODO: must be reworked completely (check trello) - -namespace OrthancStone -{ - class BaseCommandBuilder : public ICommandBuilder - { - public: - virtual ICommand* CreateFromJson(const Json::Value& commandJson); - }; -}
--- a/Applications/Commands/ICommand.h Tue Mar 12 17:29:12 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 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/>. - **/ - - -#pragma once - -#include <json/json.h> - -// TODO: must be reworked completely (check trello) - -namespace OrthancStone -{ - class ICommand // TODO noncopyable - { - protected: - std::string name_; - ICommand(const std::string& name) - : name_(name) - {} - public: - virtual ~ICommand() - {} - virtual void Execute() = 0; -// virtual void Configure(const Json::Value& arguments) = 0; - const std::string& GetName() const - { - return name_; - } - }; - - - template <typename TCommand> - class BaseCommand : public ICommand - { - protected: - BaseCommand(const std::string& name) - : ICommand(name) - {} - - public: - static ICommand* Create() { - return new TCommand(); - } - - virtual void Configure(const Json::Value& arguments) { - } - }; - - class NoopCommand : public BaseCommand<NoopCommand> - { - public: - NoopCommand() - : BaseCommand("noop") - {} - virtual void Execute() {} - }; - - class GenericNoArgCommand : public BaseCommand<GenericNoArgCommand> - { - public: - GenericNoArgCommand(const std::string& name) - : BaseCommand(name) - {} - virtual void Execute() {} // TODO currently not used but this is not nice at all ! - }; - - class GenericOneStringArgCommand : public BaseCommand<GenericOneStringArgCommand> - { - std::string argument_; - public: - GenericOneStringArgCommand(const std::string& name, const std::string& argument) - : BaseCommand(name) - {} - - const std::string& GetArgument() const {return argument_;} - virtual void Execute() {} // TODO currently not used but this is not nice at all ! - }; - -}
--- a/Applications/Commands/ICommandBuilder.h Tue Mar 12 17:29:12 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 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/>. - **/ - - -#pragma once - -#include <boost/noncopyable.hpp> -#include <json/json.h> - -#include "ICommand.h" - -namespace OrthancStone -{ - - class ICommandBuilder : public boost::noncopyable - { - public: - virtual ICommand* CreateFromJson(const Json::Value& commandJson) = 0; - }; -}
--- a/Applications/Commands/ICommandExecutor.h Tue Mar 12 17:29:12 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 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/>. - **/ - - -#pragma once - -#include <boost/noncopyable.hpp> - -namespace OrthancStone -{ - class ICommandExecutor : public boost::noncopyable - { - - }; -}
--- a/Applications/IStoneApplication.h Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/IStoneApplication.h Sun Mar 17 20:16:21 2019 +0100 @@ -25,9 +25,6 @@ #include <boost/program_options.hpp> #include "../Framework/Viewport/WidgetViewport.h" #include "json/json.h" -#include "Commands/ICommand.h" -#include "Commands/BaseCommandBuilder.h" - namespace OrthancStone { @@ -61,16 +58,6 @@ virtual std::string GetTitle() const = 0; virtual IWidget* GetCentralWidget() = 0; - virtual void Finalize() = 0; - - virtual BaseCommandBuilder& GetCommandBuilder() = 0; - - virtual void HandleSerializedMessage(const char* data) {}; - - virtual void ExecuteCommand(ICommand& command) - { - } }; - }
--- a/Applications/Samples/CMakeLists.txt Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/CMakeLists.txt Sun Mar 17 20:16:21 2019 +0100 @@ -8,6 +8,14 @@ include(../../Resources/CMake/OrthancStoneParameters.cmake) +if (OPENSSL_NO_CAPIENG) +add_definitions(-DOPENSSL_NO_CAPIENG=1) +endif() + +if (BGO_USE_NEW_COMMANDS) +add_definitions(-DBGO_USE_NEW_COMMANDS=1) +endif() + #set(ENABLE_DCMTK ON) set(ENABLE_SDL OFF CACHE BOOL "Target SDL Native application") @@ -38,7 +46,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${WASM_FLAGS}") # not always clear which flags are for the compiler and which one are for the linker -> pass them all to the linker too - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Applications/Samples/samples-library.js") + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Applications/Samples/samples-library.js") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmWebService.js") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmDelayedCallExecutor.js") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/default-library.js") @@ -181,16 +189,20 @@ list(APPEND SIMPLE_VIEWER_APPLICATION_SOURCES ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Wasm/mainWasm.cpp ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.h ${STONE_WASM_SOURCES} ) endif() add_executable(OrthancStoneSimpleViewer - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/ThumbnailInteractor.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/AppStatus.h ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/MainWidgetInteractor.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/AppStatus.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/MainWidgetInteractor.h ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Messages.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/SimpleViewerApplication.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/ThumbnailInteractor.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/ThumbnailInteractor.h ${SIMPLE_VIEWER_APPLICATION_SOURCES} ) target_link_libraries(OrthancStoneSimpleViewer OrthancStone)
--- a/Applications/Samples/SampleApplicationBase.h Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SampleApplicationBase.h Sun Mar 17 20:16:21 2019 +0100 @@ -41,7 +41,6 @@ class SampleApplicationBase : public IStoneApplication { protected: - BaseCommandBuilder commandBuilder_; WorldSceneWidget* mainWidget_; // ownership is transfered to the application context public: @@ -56,8 +55,6 @@ return "Stone of Orthanc - Sample"; } - virtual BaseCommandBuilder& GetCommandBuilder() {return commandBuilder_;} - virtual void Finalize() {} virtual IWidget* GetCentralWidget() {return mainWidget_;}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/Samples-status.md Sun Mar 17 20:16:21 2019 +0100 @@ -0,0 +1,103 @@ +Executable versions +================ +Generic options +---------------------- +``` +("help", "Display this help and exit") +("verbose", "Be verbose in logs") +("orthanc", boost::program_options::value<std::string>() + ->default_value("http://localhost:8042/"), + "URL to the Orthanc server") +("username", "Username for the Orthanc server") +("password", "Password for the Orthanc server") +("https-verify", boost::program_options::value<bool>() + ->default_value(true), "Check HTTPS certificates") +``` +OrthancStoneSimpleViewer +------------------------------------- +- Options: + ``` + - "studyId", std::string, "Orthanc ID of the study" + ``` +- study loading works OK +- Invert does not work: +``` +void SimpleViewerApplication::ExecuteAction(SimpleViewerApplication::Actions action) + { + // TODO + } +``` + +OrthancStoneSimpleViewerSingleFile +------------------------------------- +- Options: + ``` + - "studyId", std::string, "Orthanc ID of the study" + ``` + +Study loading works. + +The `line` and `circle` buttons work and call this: +``` +virtual void OnTool1Clicked() +{ + currentTool_ = Tools_LineMeasure; +} + +virtual void OnTool2Clicked() +{ + currentTool_ = Tools_CircleMeasure; +} +``` +The `action1` and `action2` buttons are not connected + +The following is displayed in the console at launch time: +``` +W0313 12:20:12.790449 NativeStoneApplicationRunner.cpp:55] Use the key "s" to reinitialize the layout +W0313 12:20:12.790449 NativeStoneApplicationRunner.cpp:55] Use the key "n" to go to next image in the main viewport +``` +However, when looking at `MainWidgetInteractor::KeyPressed` (`SimpleViewerApplicationSingleFile.h:169`), only the following is processed: +- 's': reset layout +- 'l': select line tool +- 'c': select circle tool + +OrthancStoneSingleFrame +------------------------------------- +``` +generic.add_options() +("instance", boost::program_options::value<std::string>(), +"Orthanc ID of the instance") +("frame", boost::program_options::value<unsigned int>() + ->default_value(0), +"Number of the frame, for multi-frame DICOM instances") +("smooth", boost::program_options::value<bool>() + ->default_value(true), +"Enable bilinear interpolation to smooth the image"); +``` +only key handled in `KeyPressed` is `s` to call `widget.FitContent()` + + +OrthancStoneSingleFrameEditor +------------------------------------- +``` +generic.add_options() +("instance", boost::program_options::value<std::string>(), +"Orthanc ID of the instance") +("frame", boost::program_options::value<unsigned int>() + ->default_value(0), +"Number of the frame, for multi-frame DICOM instances"); +``` +Available commands in `KeyPressed` (`SingleFrameEditorApplication.h:280`): +- 'a' widget.FitContent() +- 'c' Crop tool +- 'm' Mask tool +- 'd' dump to json and diplay result (?) +- 'e' export current view to Dicom with dummy tags (?) +- 'i' wdiget.SwitchInvert +- 't' Move tool +- 'n' switch between nearest and bilinear interpolation +- 'r' Rotate tool +- 's' Resize tool +- 'w' Windowing tool +- 'ctrl+y' redo +- 'ctrl+z' undo
--- a/Applications/Samples/SimpleViewer/MainWidgetInteractor.cpp Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SimpleViewer/MainWidgetInteractor.cpp Sun Mar 17 20:16:21 2019 +0100 @@ -37,33 +37,32 @@ { if (button == MouseButton_Left) { - if (application_.GetCurrentTool() == SimpleViewerApplication::Tools_LineMeasure) + if (application_.GetCurrentTool() == Tool_LineMeasure) { return new LineMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } - else if (application_.GetCurrentTool() == SimpleViewerApplication::Tools_CircleMeasure) + else if (application_.GetCurrentTool() == Tool_CircleMeasure) { return new CircleMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } - else if (application_.GetCurrentTool() == SimpleViewerApplication::Tools_Crop) + else if (application_.GetCurrentTool() == Tool_Crop) { // TODO } - else if (application_.GetCurrentTool() == SimpleViewerApplication::Tools_Windowing) + else if (application_.GetCurrentTool() == Tool_Windowing) { // TODO } - else if (application_.GetCurrentTool() == SimpleViewerApplication::Tools_Zoom) + else if (application_.GetCurrentTool() == Tool_Zoom) { // TODO } - else if (application_.GetCurrentTool() == SimpleViewerApplication::Tools_Pan) + else if (application_.GetCurrentTool() == Tool_Pan) { // TODO } - } return NULL; }
--- a/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.cpp Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.cpp Sun Mar 17 20:16:21 2019 +0100 @@ -27,8 +27,15 @@ #include <ui_SimpleViewerMainWindow.h> #include "../SimpleViewerApplication.h" + namespace SimpleViewer { + template<typename T, typename U> + bool ExecuteCommand(U* handler, const T& command) + { + std::string serializedCommand = StoneSerialize(command); + StoneDispatchToHandler(serializedCommand, handler); + } SimpleViewerMainWindow::SimpleViewerMainWindow( OrthancStone::NativeStoneApplicationContext& context, @@ -67,43 +74,36 @@ void SimpleViewerMainWindow::cropClicked() { - GenericNoArgCommand command("selectTool:crop"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(SelectTool(Tool_Crop)); } void SimpleViewerMainWindow::undoCropClicked() { - GenericNoArgCommand command("action:undo-crop"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(Action(ActionType_UndoCrop)); } void SimpleViewerMainWindow::lineClicked() { - GenericNoArgCommand command("selectTool:line-measure"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(SelectTool(Tool_LineMeasure)); } void SimpleViewerMainWindow::circleClicked() { - GenericNoArgCommand command("selectTool:circle-measure"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(SelectTool(Tool_CircleMeasure)); } void SimpleViewerMainWindow::windowingClicked() { - GenericNoArgCommand command("selectTool:windowing"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(SelectTool(Tool_Windowing)); } void SimpleViewerMainWindow::rotateClicked() { - GenericNoArgCommand command("action:rotate"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(Action(ActionType_Rotate)); } void SimpleViewerMainWindow::invertClicked() { - GenericNoArgCommand command("action:invert"); - stoneApplication_.ExecuteCommand(command); + stoneApplication_.ExecuteCommand(Action(ActionType_Invert)); } }
--- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Sun Mar 17 20:16:21 2019 +0100 @@ -153,13 +153,16 @@ void SimpleViewerApplication::LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId) { LOG(INFO) << "Loading thumbnail for series " << seriesId; + SliceViewerWidget* thumbnailWidget = new SliceViewerWidget(IObserver::GetBroker(), "thumbnail-series-" + seriesId); thumbnails_.push_back(thumbnailWidget); thumbnailsLayout_->AddWidget(thumbnailWidget); + thumbnailWidget->RegisterObserverCallback( new Callable<SimpleViewerApplication, SliceViewerWidget::GeometryChangedMessage> (*this, &SimpleViewerApplication::OnWidgetGeometryChanged)); + smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0); thumbnailWidget->SetInteractor(*thumbnailInteractor_); } @@ -180,53 +183,29 @@ smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0); } - - - void SimpleViewerApplication::ExecuteCommand(ICommand& command) + bool SimpleViewerApplication::Handle(const StoneSampleCommands::SelectTool& value) ORTHANC_OVERRIDE { - statusBar_->SetMessage("received command: " + std::string(command.GetName())); - if (command.GetName() == "selectTool:circle-measure") - { - SelectTool(Tools_CircleMeasure); - } - else if (command.GetName() == "selectTool:line-measure") - { - SelectTool(Tools_LineMeasure); - } - else if (command.GetName() == "selectTool:crop") - { - SelectTool(Tools_Crop); - } - else if (command.GetName() == "selectTool:windowing") - { - SelectTool(Tools_Windowing); - } - else if (command.GetName() == "action:rotate") - { - ExecuteAction(Actions_Rotate); - } - else if (command.GetName() == "action:undo-crop") - { - ExecuteAction(Actions_UndoCrop); - } - else if (command.GetName() == "action:invert") - { - ExecuteAction(Actions_Invert); - } - else - { - command.Execute(); - } + currentTool_ = value.tool; + return true; } - void SimpleViewerApplication::ExecuteAction(SimpleViewerApplication::Actions action) + bool SimpleViewerApplication::Handle(const StoneSampleCommands::Action& value) ORTHANC_OVERRIDE { - // TODO - } - - void SimpleViewerApplication::SelectTool(SimpleViewerApplication::Tools tool) - { - currentTool_ = tool; + switch (value.type) + { + case ActionType_Invert: + // TODO + break; + case ActionType_UndoCrop: + // TODO + break; + case ActionType_Rotate: + // TODO + break; + default: + throw std::runtime_error("Action type not supported"); + } + return true; } #if ORTHANC_ENABLE_QT==1
--- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.h Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.h Sun Mar 17 20:16:21 2019 +0100 @@ -21,6 +21,12 @@ #pragma once + /* + This header contains the command definitions for the sample applications + */ +#include "Applications/Samples/StoneSampleCommands_generated.hpp" +using namespace StoneSampleCommands; + #include "Applications/IStoneApplication.h" #include "Framework/Layers/CircleMeasureTracker.h" @@ -53,10 +59,11 @@ namespace SimpleViewer { - class SimpleViewerApplication : - public IStoneApplication, - public IObserver, - public IObservable + class SimpleViewerApplication + : public IStoneApplication + , public IObserver + , public IObservable + , public StoneSampleCommands::IHandler { public: @@ -71,23 +78,9 @@ } }; - enum Tools { - Tools_LineMeasure, - Tools_CircleMeasure, - Tools_Crop, - Tools_Windowing, - Tools_Zoom, - Tools_Pan - }; + private: + Tool currentTool_; - enum Actions { - Actions_Rotate, - Actions_Invert, - Actions_UndoCrop - }; - - private: - Tools currentTool_; std::auto_ptr<MainWidgetInteractor> mainWidgetInteractor_; std::auto_ptr<ThumbnailInteractor> thumbnailInteractor_; LayoutWidget* mainLayout_; @@ -96,8 +89,6 @@ std::vector<SliceViewerWidget*> thumbnails_; std::map<std::string, std::vector<std::string> > instancesIdsPerSeriesId_; std::map<std::string, Json::Value> seriesTags_; - BaseCommandBuilder commandBuilder_; - unsigned int currentInstanceIndex_; OrthancStone::WidgetViewport* wasmViewport1_; OrthancStone::WidgetViewport* wasmViewport2_; @@ -111,7 +102,7 @@ SimpleViewerApplication(MessageBroker& broker) : IObserver(broker), IObservable(broker), - currentTool_(Tools_LineMeasure), + currentTool_(StoneSampleCommands::Tool_LineMeasure), mainLayout_(NULL), currentInstanceIndex_(0), wasmViewport1_(NULL), @@ -142,9 +133,8 @@ void SelectSeriesInMainViewport(const std::string& seriesId); - void SelectTool(Tools tool); - - Tools GetCurrentTool() const + + Tool GetCurrentTool() const { return currentTool_; } @@ -154,12 +144,18 @@ return font_; } - void ExecuteAction(Actions action); + // ExecuteAction method was empty (its body was a single "TODO" comment) + virtual bool Handle(const SelectTool& value) ORTHANC_OVERRIDE; + virtual bool Handle(const Action& value) ORTHANC_OVERRIDE; + + template<typename T> + bool ExecuteCommand(const T& cmd) + { + std::string cmdStr = StoneSampleCommands::StoneSerialize(cmd); + return StoneSampleCommands::StoneDispatchToHandler(cmdStr, this); + } virtual std::string GetTitle() const {return "SimpleViewer";} - virtual void ExecuteCommand(ICommand& command); - virtual BaseCommandBuilder& GetCommandBuilder() {return commandBuilder_;} - #if ORTHANC_ENABLE_WASM==1 virtual void InitializeWasm();
--- a/Applications/Samples/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp Sun Mar 17 20:16:21 2019 +0100 @@ -45,7 +45,7 @@ writer->write(event, &outputStr); - NotifyStatusUpdateFromCppToWeb(outputStr.str()); + NotifyStatusUpdateFromCppToWebWithString(outputStr.str()); } } // namespace SimpleViewer \ No newline at end of file
--- a/Applications/Samples/SimpleViewerApplicationSingleFile.h Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SimpleViewerApplicationSingleFile.h Sun Mar 17 20:16:21 2019 +0100 @@ -127,12 +127,12 @@ { if (button == MouseButton_Left) { - if (application_.currentTool_ == Tools_LineMeasure) + if (application_.currentTool_ == Tool_LineMeasure) { return new LineMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } - else if (application_.currentTool_ == Tools_CircleMeasure) + else if (application_.currentTool_ == Tool_CircleMeasure) { return new CircleMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); @@ -179,11 +179,11 @@ break; case 'l': - application_.currentTool_ = Tools_LineMeasure; + application_.currentTool_ = Tool_LineMeasure; break; case 'c': - application_.currentTool_ = Tools_CircleMeasure; + application_.currentTool_ = Tool_CircleMeasure; break; default: @@ -214,13 +214,13 @@ { if (input == "select-tool:line-measure") { - viewerApplication_.currentTool_ = Tools_LineMeasure; - NotifyStatusUpdateFromCppToWeb("currentTool=line-measure"); + viewerApplication_.currentTool_ = Tool_LineMeasure; + NotifyStatusUpdateFromCppToWebWithString("currentTool=line-measure"); } else if (input == "select-tool:circle-measure") { - viewerApplication_.currentTool_ = Tools_CircleMeasure; - NotifyStatusUpdateFromCppToWeb("currentTool=circle-measure"); + viewerApplication_.currentTool_ = Tool_CircleMeasure; + NotifyStatusUpdateFromCppToWebWithString("currentTool=circle-measure"); } output = "ok"; @@ -231,19 +231,19 @@ UpdateStoneApplicationStatusFromCppWithSerializedMessage(statusUpdateMessage.c_str()); } - virtual void NotifyStatusUpdateFromCppToWeb(const std::string& statusUpdateMessage) + virtual void NotifyStatusUpdateFromCppToWebWithString(const std::string& statusUpdateMessage) { UpdateStoneApplicationStatusFromCppWithString(statusUpdateMessage.c_str()); } }; #endif - enum Tools { - Tools_LineMeasure, - Tools_CircleMeasure + enum Tool { + Tool_LineMeasure, + Tool_CircleMeasure }; - Tools currentTool_; + Tool currentTool_; std::auto_ptr<MainWidgetInteractor> mainWidgetInteractor_; std::auto_ptr<ThumbnailInteractor> thumbnailInteractor_; LayoutWidget* mainLayout_; @@ -265,7 +265,7 @@ public: SimpleViewerApplication(MessageBroker& broker) : IObserver(broker), - currentTool_(Tools_LineMeasure), + currentTool_(Tool_LineMeasure), mainLayout_(NULL), currentInstanceIndex_(0), wasmViewport1_(NULL), @@ -438,8 +438,8 @@ virtual void OnPushButton1Clicked() {} virtual void OnPushButton2Clicked() {} - virtual void OnTool1Clicked() { currentTool_ = Tools_LineMeasure;} - virtual void OnTool2Clicked() { currentTool_ = Tools_CircleMeasure;} + virtual void OnTool1Clicked() { currentTool_ = Tool_LineMeasure;} + virtual void OnTool2Clicked() { currentTool_ = Tool_CircleMeasure;} virtual void GetButtonNames(std::string& pushButton1, std::string& pushButton2,
--- a/Applications/Samples/SingleFrameApplication.h Tue Mar 12 17:29:12 2019 +0000 +++ b/Applications/Samples/SingleFrameApplication.h Sun Mar 17 20:16:21 2019 +0100 @@ -138,7 +138,7 @@ if (slice >= static_cast<int>(source_->GetSliceCount())) { - slice = source_->GetSliceCount() - 1; + slice = static_cast<int>(source_->GetSliceCount()) - 1; } if (slice != static_cast<int>(slice_)) @@ -160,7 +160,7 @@ if (source_ != NULL && index < source_->GetSliceCount()) { - slice_ = index; + slice_ = static_cast<unsigned int>(index); #if 1 GetMainWidget().SetSlice(source_->GetSlice(slice_).GetGeometry());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/StoneSampleCommands.yml Sun Mar 17 20:16:21 2019 +0100 @@ -0,0 +1,35 @@ +# +# 1 2 3 4 5 6 7 8 +# 345678901234567890123456789012345678901234567890123456789012345678901234567890 +# +rootName: StoneSampleCommands + +# +---------------------------------+ +# | Messages from TypeScript to C++ | +# +---------------------------------+ + +enum Tool: + - LineMeasure + - CircleMeasure + - Crop + - Windowing + - Zoom + - Pan + - Move + - Rotate + - Resize + - Mask + +struct SelectTool: + __handler: cpp + tool: Tool + +enum ActionType: + - UndoCrop + - Rotate + - Invert + +struct Action: + __handler: cpp + type: ActionType +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/StoneSampleCommands_generate.py Sun Mar 17 20:16:21 2019 +0100 @@ -0,0 +1,16 @@ +import sys +import os + +# add the generation script location to the search paths +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'Resources', 'CodeGeneration')) + +# import the code generation tooling script +import stonegentool + +schemaFile = os.path.join(os.path.dirname(__file__), 'StoneSampleCommands.yml') +outDir = os.path.dirname(__file__) + +# ignition! +stonegentool.Process(schemaFile, outDir) + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/StoneSampleCommands_generated.hpp Sun Mar 17 20:16:21 2019 +0100 @@ -0,0 +1,696 @@ +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 + +Generated on 2019-03-15 10:00:48.763392 by stonegentool + +*/ +#pragma once + +#include <exception> +#include <iostream> +#include <string> +#include <sstream> +#include <assert.h> +#include <memory> +#include <json/json.h> + +//#define STONEGEN_NO_CPP11 1 + +#ifdef STONEGEN_NO_CPP11 +#define StoneSmartPtr std::auto_ptr +#else +#define StoneSmartPtr std::unique_ptr +#endif + +namespace StoneSampleCommands +{ + /** Throws in case of problem */ + inline void _StoneDeserializeValue(int32_t& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue.asInt(); + } + + inline Json::Value _StoneSerializeValue(int32_t value) + { + Json::Value result(value); + return result; + } + + inline void _StoneDeserializeValue(Json::Value& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue; + } + + inline Json::Value _StoneSerializeValue(Json::Value value) + { + return value; + } + + /** Throws in case of problem */ + inline void _StoneDeserializeValue(double& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue.asDouble(); + } + + inline Json::Value _StoneSerializeValue(double value) + { + Json::Value result(value); + return result; + } + + /** Throws in case of problem */ + inline void _StoneDeserializeValue(bool& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue.asBool(); + } + + inline Json::Value _StoneSerializeValue(bool value) + { + Json::Value result(value); + return result; + } + + /** Throws in case of problem */ + inline void _StoneDeserializeValue( + std::string& destValue + , const Json::Value& jsonValue) + { + destValue = jsonValue.asString(); + } + + inline Json::Value _StoneSerializeValue(const std::string& value) + { + // the following is better than + Json::Value result(value.data(),value.data()+value.size()); + return result; + } + + inline std::string MakeIndent(int indent) + { + char* txt = reinterpret_cast<char*>(malloc(indent+1)); // NO EXCEPTION BELOW!!!!!!!!!!!! + for(size_t i = 0; i < indent; ++i) + txt[i] = ' '; + txt[indent] = 0; + std::string retVal(txt); + free(txt); // NO EXCEPTION ABOVE !!!!!!!!!! + return retVal; + } + + // generic dumper + template<typename T> + std::ostream& StoneDumpValue(std::ostream& out, const T& value, int indent) + { + out << MakeIndent(indent) << value; + return out; + } + + // string dumper + inline std::ostream& StoneDumpValue(std::ostream& out, const std::string& value, int indent) + { + out << MakeIndent(indent) << "\"" << value << "\""; + return out; + } + + /** Throws in case of problem */ + template<typename T> + void _StoneDeserializeValue( + std::map<std::string, T>& destValue, const Json::Value& jsonValue) + { + destValue.clear(); + for ( + Json::Value::const_iterator itr = jsonValue.begin(); + itr != jsonValue.end(); + itr++) + { + std::string key; + _StoneDeserializeValue(key, itr.key()); + + T innerDestValue; + _StoneDeserializeValue(innerDestValue, *itr); + + destValue[key] = innerDestValue; + } + } + + template<typename T> + Json::Value _StoneSerializeValue(const std::map<std::string,T>& value) + { + Json::Value result(Json::objectValue); + + for (typename std::map<std::string, T>::const_iterator it = value.cbegin(); + it != value.cend(); ++it) + { + // it->first it->second + result[it->first] = _StoneSerializeValue(it->second); + } + return result; + } + + template<typename T> + std::ostream& StoneDumpValue(std::ostream& out, const std::map<std::string,T>& value, int indent) + { + out << MakeIndent(indent) << "{\n"; + for (typename std::map<std::string, T>::const_iterator it = value.cbegin(); + it != value.cend(); ++it) + { + out << MakeIndent(indent+2) << "\"" << it->first << "\" : "; + StoneDumpValue(out, it->second, indent+2); + } + out << MakeIndent(indent) << "}\n"; + return out; + } + + /** Throws in case of problem */ + template<typename T> + void _StoneDeserializeValue( + std::vector<T>& destValue, const Json::Value& jsonValue) + { + destValue.clear(); + destValue.reserve(jsonValue.size()); + for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) + { + T innerDestValue; + _StoneDeserializeValue(innerDestValue, jsonValue[i]); + destValue.push_back(innerDestValue); + } + } + + template<typename T> + Json::Value _StoneSerializeValue(const std::vector<T>& value) + { + Json::Value result(Json::arrayValue); + for (size_t i = 0; i < value.size(); ++i) + { + result.append(_StoneSerializeValue(value[i])); + } + return result; + } + + template<typename T> + std::ostream& StoneDumpValue(std::ostream& out, const std::vector<T>& value, int indent) + { + out << MakeIndent(indent) << "[\n"; + for (size_t i = 0; i < value.size(); ++i) + { + StoneDumpValue(out, value[i], indent+2); + } + out << MakeIndent(indent) << "]\n"; + return out; + } + + inline void StoneCheckSerializedValueTypeGeneric(const Json::Value& value) + { + if ((!value.isMember("type")) || (!value["type"].isString())) + { + std::stringstream ss; + ss << "Cannot deserialize value ('type' key invalid)"; + throw std::runtime_error(ss.str()); + } + } + + inline void StoneCheckSerializedValueType( + const Json::Value& value, std::string typeStr) + { + StoneCheckSerializedValueTypeGeneric(value); + + std::string actTypeStr = value["type"].asString(); + if (actTypeStr != typeStr) + { + std::stringstream ss; + ss << "Cannot deserialize type" << actTypeStr + << "into " << typeStr; + throw std::runtime_error(ss.str()); + } + } + + // end of generic methods + +// end of generic methods + + enum Tool { + Tool_LineMeasure, + Tool_CircleMeasure, + Tool_Crop, + Tool_Windowing, + Tool_Zoom, + Tool_Pan, + Tool_Move, + Tool_Rotate, + Tool_Resize, + Tool_Mask, + }; + + inline std::string ToString(const Tool& value) + { + if( value == Tool_LineMeasure) + { + return std::string("LineMeasure"); + } + if( value == Tool_CircleMeasure) + { + return std::string("CircleMeasure"); + } + if( value == Tool_Crop) + { + return std::string("Crop"); + } + if( value == Tool_Windowing) + { + return std::string("Windowing"); + } + if( value == Tool_Zoom) + { + return std::string("Zoom"); + } + if( value == Tool_Pan) + { + return std::string("Pan"); + } + if( value == Tool_Move) + { + return std::string("Move"); + } + if( value == Tool_Rotate) + { + return std::string("Rotate"); + } + if( value == Tool_Resize) + { + return std::string("Resize"); + } + if( value == Tool_Mask) + { + return std::string("Mask"); + } + std::stringstream ss; + ss << "Value \"" << value << "\" cannot be converted to Tool. Possible values are: " + << " LineMeasure = " << static_cast<int64_t>(Tool_LineMeasure) << ", " + << " CircleMeasure = " << static_cast<int64_t>(Tool_CircleMeasure) << ", " + << " Crop = " << static_cast<int64_t>(Tool_Crop) << ", " + << " Windowing = " << static_cast<int64_t>(Tool_Windowing) << ", " + << " Zoom = " << static_cast<int64_t>(Tool_Zoom) << ", " + << " Pan = " << static_cast<int64_t>(Tool_Pan) << ", " + << " Move = " << static_cast<int64_t>(Tool_Move) << ", " + << " Rotate = " << static_cast<int64_t>(Tool_Rotate) << ", " + << " Resize = " << static_cast<int64_t>(Tool_Resize) << ", " + << " Mask = " << static_cast<int64_t>(Tool_Mask) << ", " + << std::endl; + std::string msg = ss.str(); + throw std::runtime_error(msg); + } + + inline void FromString(Tool& value, std::string strValue) + { + if( strValue == std::string("LineMeasure") ) + { + value = Tool_LineMeasure; + return; + } + if( strValue == std::string("CircleMeasure") ) + { + value = Tool_CircleMeasure; + return; + } + if( strValue == std::string("Crop") ) + { + value = Tool_Crop; + return; + } + if( strValue == std::string("Windowing") ) + { + value = Tool_Windowing; + return; + } + if( strValue == std::string("Zoom") ) + { + value = Tool_Zoom; + return; + } + if( strValue == std::string("Pan") ) + { + value = Tool_Pan; + return; + } + if( strValue == std::string("Move") ) + { + value = Tool_Move; + return; + } + if( strValue == std::string("Rotate") ) + { + value = Tool_Rotate; + return; + } + if( strValue == std::string("Resize") ) + { + value = Tool_Resize; + return; + } + if( strValue == std::string("Mask") ) + { + value = Tool_Mask; + return; + } + + std::stringstream ss; + ss << "String \"" << strValue << "\" cannot be converted to Tool. Possible values are: LineMeasure CircleMeasure Crop Windowing Zoom Pan Move Rotate Resize Mask "; + std::string msg = ss.str(); + throw std::runtime_error(msg); + } + + + inline void _StoneDeserializeValue( + Tool& destValue, const Json::Value& jsonValue) + { + FromString(destValue, jsonValue.asString()); + } + + inline Json::Value _StoneSerializeValue(const Tool& value) + { + std::string strValue = ToString(value); + return Json::Value(strValue); + } + + inline std::ostream& StoneDumpValue(std::ostream& out, const Tool& value, int indent = 0) + { + if( value == Tool_LineMeasure) + { + out << MakeIndent(indent) << "LineMeasure" << std::endl; + } + if( value == Tool_CircleMeasure) + { + out << MakeIndent(indent) << "CircleMeasure" << std::endl; + } + if( value == Tool_Crop) + { + out << MakeIndent(indent) << "Crop" << std::endl; + } + if( value == Tool_Windowing) + { + out << MakeIndent(indent) << "Windowing" << std::endl; + } + if( value == Tool_Zoom) + { + out << MakeIndent(indent) << "Zoom" << std::endl; + } + if( value == Tool_Pan) + { + out << MakeIndent(indent) << "Pan" << std::endl; + } + if( value == Tool_Move) + { + out << MakeIndent(indent) << "Move" << std::endl; + } + if( value == Tool_Rotate) + { + out << MakeIndent(indent) << "Rotate" << std::endl; + } + if( value == Tool_Resize) + { + out << MakeIndent(indent) << "Resize" << std::endl; + } + if( value == Tool_Mask) + { + out << MakeIndent(indent) << "Mask" << std::endl; + } + return out; + } + + + enum ActionType { + ActionType_UndoCrop, + ActionType_Rotate, + ActionType_Invert, + }; + + inline std::string ToString(const ActionType& value) + { + if( value == ActionType_UndoCrop) + { + return std::string("UndoCrop"); + } + if( value == ActionType_Rotate) + { + return std::string("Rotate"); + } + if( value == ActionType_Invert) + { + return std::string("Invert"); + } + std::stringstream ss; + ss << "Value \"" << value << "\" cannot be converted to ActionType. Possible values are: " + << " UndoCrop = " << static_cast<int64_t>(ActionType_UndoCrop) << ", " + << " Rotate = " << static_cast<int64_t>(ActionType_Rotate) << ", " + << " Invert = " << static_cast<int64_t>(ActionType_Invert) << ", " + << std::endl; + std::string msg = ss.str(); + throw std::runtime_error(msg); + } + + inline void FromString(ActionType& value, std::string strValue) + { + if( strValue == std::string("UndoCrop") ) + { + value = ActionType_UndoCrop; + return; + } + if( strValue == std::string("Rotate") ) + { + value = ActionType_Rotate; + return; + } + if( strValue == std::string("Invert") ) + { + value = ActionType_Invert; + return; + } + + std::stringstream ss; + ss << "String \"" << strValue << "\" cannot be converted to ActionType. Possible values are: UndoCrop Rotate Invert "; + std::string msg = ss.str(); + throw std::runtime_error(msg); + } + + + inline void _StoneDeserializeValue( + ActionType& destValue, const Json::Value& jsonValue) + { + FromString(destValue, jsonValue.asString()); + } + + inline Json::Value _StoneSerializeValue(const ActionType& value) + { + std::string strValue = ToString(value); + return Json::Value(strValue); + } + + inline std::ostream& StoneDumpValue(std::ostream& out, const ActionType& value, int indent = 0) + { + if( value == ActionType_UndoCrop) + { + out << MakeIndent(indent) << "UndoCrop" << std::endl; + } + if( value == ActionType_Rotate) + { + out << MakeIndent(indent) << "Rotate" << std::endl; + } + if( value == ActionType_Invert) + { + out << MakeIndent(indent) << "Invert" << std::endl; + } + return out; + } + + + +#ifdef _MSC_VER +#pragma region SelectTool +#endif //_MSC_VER + + struct SelectTool + { + Tool tool; + + SelectTool(Tool tool = Tool()) + { + this->tool = tool; + } + }; + + inline void _StoneDeserializeValue(SelectTool& destValue, const Json::Value& value) + { + _StoneDeserializeValue(destValue.tool, value["tool"]); + } + + inline Json::Value _StoneSerializeValue(const SelectTool& value) + { + Json::Value result(Json::objectValue); + result["tool"] = _StoneSerializeValue(value.tool); + + return result; + } + + inline std::ostream& StoneDumpValue(std::ostream& out, const SelectTool& value, int indent = 0) + { + out << MakeIndent(indent) << "{\n"; + out << MakeIndent(indent) << "tool:\n"; + StoneDumpValue(out, value.tool,indent+2); + out << "\n"; + + out << MakeIndent(indent) << "}\n"; + return out; + } + + inline void StoneDeserialize(SelectTool& destValue, const Json::Value& value) + { + StoneCheckSerializedValueType(value, "StoneSampleCommands.SelectTool"); + _StoneDeserializeValue(destValue, value["value"]); + } + + inline Json::Value StoneSerializeToJson(const SelectTool& value) + { + Json::Value result(Json::objectValue); + result["type"] = "StoneSampleCommands.SelectTool"; + result["value"] = _StoneSerializeValue(value); + return result; + } + + inline std::string StoneSerialize(const SelectTool& value) + { + Json::Value resultJson = StoneSerializeToJson(value); + std::string resultStr = resultJson.toStyledString(); + return resultStr; + } + +#ifdef _MSC_VER +#pragma endregion SelectTool +#endif //_MSC_VER + +#ifdef _MSC_VER +#pragma region Action +#endif //_MSC_VER + + struct Action + { + ActionType type; + + Action(ActionType type = ActionType()) + { + this->type = type; + } + }; + + inline void _StoneDeserializeValue(Action& destValue, const Json::Value& value) + { + _StoneDeserializeValue(destValue.type, value["type"]); + } + + inline Json::Value _StoneSerializeValue(const Action& value) + { + Json::Value result(Json::objectValue); + result["type"] = _StoneSerializeValue(value.type); + + return result; + } + + inline std::ostream& StoneDumpValue(std::ostream& out, const Action& value, int indent = 0) + { + out << MakeIndent(indent) << "{\n"; + out << MakeIndent(indent) << "type:\n"; + StoneDumpValue(out, value.type,indent+2); + out << "\n"; + + out << MakeIndent(indent) << "}\n"; + return out; + } + + inline void StoneDeserialize(Action& destValue, const Json::Value& value) + { + StoneCheckSerializedValueType(value, "StoneSampleCommands.Action"); + _StoneDeserializeValue(destValue, value["value"]); + } + + inline Json::Value StoneSerializeToJson(const Action& value) + { + Json::Value result(Json::objectValue); + result["type"] = "StoneSampleCommands.Action"; + result["value"] = _StoneSerializeValue(value); + return result; + } + + inline std::string StoneSerialize(const Action& value) + { + Json::Value resultJson = StoneSerializeToJson(value); + std::string resultStr = resultJson.toStyledString(); + return resultStr; + } + +#ifdef _MSC_VER +#pragma endregion Action +#endif //_MSC_VER + +#ifdef _MSC_VER +#pragma region Dispatching code +#endif //_MSC_VER + + class IHandler + { + public: + virtual bool Handle(const SelectTool& value) = 0; + }; + + /** Service function for StoneDispatchToHandler */ + inline bool StoneDispatchJsonToHandler( + const Json::Value& jsonValue, IHandler* handler) + { + StoneCheckSerializedValueTypeGeneric(jsonValue); + std::string type = jsonValue["type"].asString(); + if (type == "") + { + // this should never ever happen + throw std::runtime_error("Caught empty type while dispatching"); + } + else if (type == "StoneSampleCommands.SelectTool") + { + SelectTool value; + _StoneDeserializeValue(value, jsonValue["value"]); + return handler->Handle(value); + } + else + { + return false; + } + } + + /** Takes a serialized type and passes this to the handler */ + inline bool StoneDispatchToHandler(std::string strValue, IHandler* handler) + { + Json::Value readValue; + + Json::CharReaderBuilder builder; + Json::CharReader* reader = builder.newCharReader(); + + StoneSmartPtr<Json::CharReader> ptr(reader); + + std::string errors; + + bool ok = reader->parse( + strValue.c_str(), + strValue.c_str() + strValue.size(), + &readValue, + &errors + ); + if (!ok) + { + std::stringstream ss; + ss << "Jsoncpp parsing error: " << errors; + throw std::runtime_error(ss.str()); + } + return StoneDispatchJsonToHandler(readValue, handler); + } + +#ifdef _MSC_VER +#pragma endregion Dispatching code +#endif //_MSC_VER +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/StoneSampleCommands_generated.ts Sun Mar 17 20:16:21 2019 +0100 @@ -0,0 +1,333 @@ +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 + +Generated on 2019-03-15 10:00:48.763392 by stonegentool + +*/ + +function StoneCheckSerializedValueType(value: any, typeStr: string) +{ + StoneCheckSerializedValueTypeGeneric(value); + + if (value['type'] != typeStr) + { + throw new Error( + `Cannot deserialize type ${value['type']} into ${typeStr}`); + } +} + +function isString(val: any) :boolean +{ + return ((typeof val === 'string') || (val instanceof String)); +} + +function StoneCheckSerializedValueTypeGeneric(value: any) +{ + // console.//log("+-------------------------------------------------+"); + // console.//log("| StoneCheckSerializedValueTypeGeneric |"); + // console.//log("+-------------------------------------------------+"); + // console.//log("value = "); + // console.//log(value); + if ( (!('type' in value)) || (!isString(value.type)) ) + { + throw new Error( + "Cannot deserialize value ('type' key invalid)"); + } +} + +// end of generic methods + +export enum Tool { + LineMeasure = "LineMeasure", + CircleMeasure = "CircleMeasure", + Crop = "Crop", + Windowing = "Windowing", + Zoom = "Zoom", + Pan = "Pan", + Move = "Move", + Rotate = "Rotate", + Resize = "Resize", + Mask = "Mask" +}; + +export function Tool_FromString(strValue:string) : Tool +{ + if( strValue == "LineMeasure" ) + { + return Tool.LineMeasure; + } + if( strValue == "CircleMeasure" ) + { + return Tool.CircleMeasure; + } + if( strValue == "Crop" ) + { + return Tool.Crop; + } + if( strValue == "Windowing" ) + { + return Tool.Windowing; + } + if( strValue == "Zoom" ) + { + return Tool.Zoom; + } + if( strValue == "Pan" ) + { + return Tool.Pan; + } + if( strValue == "Move" ) + { + return Tool.Move; + } + if( strValue == "Rotate" ) + { + return Tool.Rotate; + } + if( strValue == "Resize" ) + { + return Tool.Resize; + } + if( strValue == "Mask" ) + { + return Tool.Mask; + } + + let msg : string = `String ${strValue} cannot be converted to Tool. Possible values are: LineMeasure, CircleMeasure, Crop, Windowing, Zoom, Pan, Move, Rotate, Resize, Mask`; + throw new Error(msg); +} + +export function Tool_ToString(value:Tool) : string +{ + if( value == Tool.LineMeasure ) + { + return "LineMeasure"; + } + if( value == Tool.CircleMeasure ) + { + return "CircleMeasure"; + } + if( value == Tool.Crop ) + { + return "Crop"; + } + if( value == Tool.Windowing ) + { + return "Windowing"; + } + if( value == Tool.Zoom ) + { + return "Zoom"; + } + if( value == Tool.Pan ) + { + return "Pan"; + } + if( value == Tool.Move ) + { + return "Move"; + } + if( value == Tool.Rotate ) + { + return "Rotate"; + } + if( value == Tool.Resize ) + { + return "Resize"; + } + if( value == Tool.Mask ) + { + return "Mask"; + } + + let msg : string = `Value ${value} cannot be converted to Tool. Possible values are: `; + { + let _LineMeasure_enumValue : string = Tool.LineMeasure; // enums are strings in stonecodegen, so this will work. + let msg_LineMeasure : string = `LineMeasure (${_LineMeasure_enumValue}), `; + msg = msg + msg_LineMeasure; + } + { + let _CircleMeasure_enumValue : string = Tool.CircleMeasure; // enums are strings in stonecodegen, so this will work. + let msg_CircleMeasure : string = `CircleMeasure (${_CircleMeasure_enumValue}), `; + msg = msg + msg_CircleMeasure; + } + { + let _Crop_enumValue : string = Tool.Crop; // enums are strings in stonecodegen, so this will work. + let msg_Crop : string = `Crop (${_Crop_enumValue}), `; + msg = msg + msg_Crop; + } + { + let _Windowing_enumValue : string = Tool.Windowing; // enums are strings in stonecodegen, so this will work. + let msg_Windowing : string = `Windowing (${_Windowing_enumValue}), `; + msg = msg + msg_Windowing; + } + { + let _Zoom_enumValue : string = Tool.Zoom; // enums are strings in stonecodegen, so this will work. + let msg_Zoom : string = `Zoom (${_Zoom_enumValue}), `; + msg = msg + msg_Zoom; + } + { + let _Pan_enumValue : string = Tool.Pan; // enums are strings in stonecodegen, so this will work. + let msg_Pan : string = `Pan (${_Pan_enumValue}), `; + msg = msg + msg_Pan; + } + { + let _Move_enumValue : string = Tool.Move; // enums are strings in stonecodegen, so this will work. + let msg_Move : string = `Move (${_Move_enumValue}), `; + msg = msg + msg_Move; + } + { + let _Rotate_enumValue : string = Tool.Rotate; // enums are strings in stonecodegen, so this will work. + let msg_Rotate : string = `Rotate (${_Rotate_enumValue}), `; + msg = msg + msg_Rotate; + } + { + let _Resize_enumValue : string = Tool.Resize; // enums are strings in stonecodegen, so this will work. + let msg_Resize : string = `Resize (${_Resize_enumValue}), `; + msg = msg + msg_Resize; + } + { + let _Mask_enumValue : string = Tool.Mask; // enums are strings in stonecodegen, so this will work. + let msg_Mask : string = `Mask (${_Mask_enumValue})`; + msg = msg + msg_Mask; + } + throw new Error(msg); +} + +export enum ActionType { + UndoCrop = "UndoCrop", + Rotate = "Rotate", + Invert = "Invert" +}; + +export function ActionType_FromString(strValue:string) : ActionType +{ + if( strValue == "UndoCrop" ) + { + return ActionType.UndoCrop; + } + if( strValue == "Rotate" ) + { + return ActionType.Rotate; + } + if( strValue == "Invert" ) + { + return ActionType.Invert; + } + + let msg : string = `String ${strValue} cannot be converted to ActionType. Possible values are: UndoCrop, Rotate, Invert`; + throw new Error(msg); +} + +export function ActionType_ToString(value:ActionType) : string +{ + if( value == ActionType.UndoCrop ) + { + return "UndoCrop"; + } + if( value == ActionType.Rotate ) + { + return "Rotate"; + } + if( value == ActionType.Invert ) + { + return "Invert"; + } + + let msg : string = `Value ${value} cannot be converted to ActionType. Possible values are: `; + { + let _UndoCrop_enumValue : string = ActionType.UndoCrop; // enums are strings in stonecodegen, so this will work. + let msg_UndoCrop : string = `UndoCrop (${_UndoCrop_enumValue}), `; + msg = msg + msg_UndoCrop; + } + { + let _Rotate_enumValue : string = ActionType.Rotate; // enums are strings in stonecodegen, so this will work. + let msg_Rotate : string = `Rotate (${_Rotate_enumValue}), `; + msg = msg + msg_Rotate; + } + { + let _Invert_enumValue : string = ActionType.Invert; // enums are strings in stonecodegen, so this will work. + let msg_Invert : string = `Invert (${_Invert_enumValue})`; + msg = msg + msg_Invert; + } + throw new Error(msg); +} + + + +export class SelectTool { + tool:Tool; + + constructor() { + } + + public StoneSerialize(): string { + let container: object = {}; + container['type'] = 'StoneSampleCommands.SelectTool'; + container['value'] = this; + return JSON.stringify(container); + } + + public static StoneDeserialize(valueStr: string) : SelectTool + { + let value: any = JSON.parse(valueStr); + StoneCheckSerializedValueType(value, 'StoneSampleCommands.SelectTool'); + let result: SelectTool = value['value'] as SelectTool; + return result; + } +} +export class Action { + type:ActionType; + + constructor() { + } + + public StoneSerialize(): string { + let container: object = {}; + container['type'] = 'StoneSampleCommands.Action'; + container['value'] = this; + return JSON.stringify(container); + } + + public static StoneDeserialize(valueStr: string) : Action + { + let value: any = JSON.parse(valueStr); + StoneCheckSerializedValueType(value, 'StoneSampleCommands.Action'); + let result: Action = value['value'] as Action; + return result; + } +} + +export interface IHandler { +}; + +/** Service function for StoneDispatchToHandler */ +export function StoneDispatchJsonToHandler( + jsonValue: any, handler: IHandler): boolean +{ + StoneCheckSerializedValueTypeGeneric(jsonValue); + let type: string = jsonValue["type"]; + if (type == "") + { + // this should never ever happen + throw new Error("Caught empty type while dispatching"); + } + else + { + return false; + } +} + +/** Takes a serialized type and passes this to the handler */ +export function StoneDispatchToHandler( + strValue: string, handler: IHandler): boolean +{ + // console.//log("+------------------------------------------------+"); + // console.//log("| StoneDispatchToHandler |"); + // console.//log("+------------------------------------------------+"); + // console.//log("strValue = "); + // console.//log(strValue); + let jsonValue: any = JSON.parse(strValue) + return StoneDispatchJsonToHandler(jsonValue, handler); +} \ No newline at end of file
--- a/Framework/Widgets/LayoutWidget.cpp Tue Mar 12 17:29:12 2019 +0000 +++ b/Framework/Widgets/LayoutWidget.cpp Sun Mar 17 20:16:21 2019 +0100 @@ -74,7 +74,7 @@ std::vector<Touch> relativeTouches; for (size_t t = 0; t < displayTouches.size(); t++) { - relativeTouches.push_back(Touch((int)displayTouches[t].x - left_, (int)displayTouches[t].y - top_)); + relativeTouches.push_back(Touch(displayTouches[t].x - left_, displayTouches[t].y - top_)); } tracker_->MouseMove(x - left_, y - top_, relativeTouches); @@ -226,7 +226,7 @@ } else if (isHorizontal_) { - unsigned int padding = paddingLeft_ + paddingRight_ + (children_.size() - 1) * paddingInternal_; + unsigned int padding = paddingLeft_ + paddingRight_ + (static_cast<unsigned int>(children_.size()) - 1) * paddingInternal_; float childWidth = ((static_cast<float>(width_) - static_cast<float>(padding)) / static_cast<float>(children_.size())); @@ -250,7 +250,7 @@ } else { - unsigned int padding = paddingTop_ + paddingBottom_ + (children_.size() - 1) * paddingInternal_; + unsigned int padding = paddingTop_ + paddingBottom_ + (static_cast<unsigned int>(children_.size()) - 1) * paddingInternal_; float childHeight = ((static_cast<float>(height_) - static_cast<float>(padding)) / static_cast<float>(children_.size()));
--- a/README.md Tue Mar 12 17:29:12 2019 +0000 +++ b/README.md Sun Mar 17 20:16:21 2019 +0100 @@ -125,7 +125,10 @@ source code in an `orthanc` folder next to the Stone of Orthanc repository, please enter the following: +**Simple make generator with dynamic build** + ``` +# Please set $currentDir to the current folder mkdir -p ~/builds/orthanc-stone-build cd ~/builds/orthanc-stone-build cmake -DORTHANC_FRAMEWORK_SOURCE=path \ @@ -134,6 +137,16 @@ ~/orthanc-stone/Applications/Samples/ ``` +**Ninja generator with static build (typical under Windows)** + +``` +# Please yourself one level above the orthanc-stone and orthanc folders +mkdir -p stone_build_sdl +cd stone_build_sdl +cmake -G Ninja -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples/ +``` + + If you are working on Windows, add the correct generator option to cmake to, for instance, generate msbuild files for Visual Studio. @@ -146,9 +159,14 @@ Building the Qt native samples (SimpleViewer only) under Windows: ------------------------------------------------------------------ + +**MSVC 2017 generator with static build (typical under Windows)** + For instance, if Qt is installed in `C:\Qt\5.12.0\msvc2017_64` -`cmake -DSTATIC_BUILD=ON -DCMAKE_PREFIX_PATH=C:\Qt\5.12.0\msvc2017_64 -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_QT=ON -G "Visual Studio 15 2017 Win64" ../orthanc-stone/Applications/Samples/` +``` +cmake -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DCMAKE_PREFIX_PATH=C:\Qt\5.12.0\msvc2017_64 -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_QT=ON -G "Visual Studio 15 2017 Win64" ../orthanc-stone/Applications/Samples/ +``` Note: replace `$($pwd)` with the current directory when not using Powershell @@ -196,3 +214,9 @@ url="https://doi.org/10.1007/s10278-018-0082-y" } +Various notes to be deleted +--------------------------- +class BaseCommand : public ICommand + +RadiographySceneCommand +GenericNoArgCommand