Mercurial > hg > orthanc-stone
changeset 222:84844649a8fd am
continued: reusable applications
line wrap: on
line diff
--- a/.hgignore Mon Jun 11 14:01:02 2018 +0200 +++ b/.hgignore Tue Jun 12 17:21:15 2018 +0200 @@ -1,1 +1,2 @@ Platforms/Generic/CMakeLists.txt.user +Platforms/Generic/ThirdPartyDownloads/
--- a/Applications/BasicApplicationContext.cpp Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/BasicApplicationContext.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -23,59 +23,4 @@ namespace OrthancStone { - void BasicApplicationContext::UpdateThread(BasicApplicationContext* that) - { - while (!that->stopped_) - { - { - ViewportLocker locker(*that); - locker.GetViewport().UpdateContent(); - } - - boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelay_)); - } - } - - - BasicApplicationContext::BasicApplicationContext(Orthanc::WebServiceParameters& orthanc) : - oracle_(viewportMutex_, 4), // Use 4 threads to download - //oracle_(viewportMutex_, 1), // Disable threading to be reproducible - webService_(oracle_, orthanc), - stopped_(true), - updateDelay_(100) // By default, 100ms between each refresh of the content - { - srand(time(NULL)); - } - - - IWidget& BasicApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership - { - centralViewport_.SetCentralWidget(widget); - return *widget; - } - - - void BasicApplicationContext::Start() - { - oracle_.Start(); - - if (centralViewport_.HasUpdateContent()) - { - stopped_ = false; - updateThread_ = boost::thread(UpdateThread, this); - } - } - - - void BasicApplicationContext::Stop() - { - stopped_ = true; - - if (updateThread_.joinable()) - { - updateThread_.join(); - } - - oracle_.Stop(); - } }
--- a/Applications/BasicApplicationContext.h Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/BasicApplicationContext.h Tue Jun 12 17:21:15 2018 +0200 @@ -21,71 +21,22 @@ #pragma once +#include "../Platforms/Generic/OracleWebService.h" #include "../Framework/Viewport/WidgetViewport.h" -#include "../Framework/Volumes/ISlicedVolume.h" -#include "../Framework/Volumes/IVolumeLoader.h" -#include "../Framework/Widgets/IWorldSceneInteractor.h" -#include "../Platforms/Generic/OracleWebService.h" #include <list> -#include <boost/thread.hpp> namespace OrthancStone { class BasicApplicationContext : public boost::noncopyable { - private: - - static void UpdateThread(BasicApplicationContext* that); - - - Oracle oracle_; - OracleWebService webService_; - boost::mutex viewportMutex_; - WidgetViewport centralViewport_; - boost::thread updateThread_; - bool stopped_; - unsigned int updateDelay_; public: - class ViewportLocker : public boost::noncopyable - { - private: - boost::mutex::scoped_lock lock_; - IViewport& viewport_; + BasicApplicationContext() {} - public: - ViewportLocker(BasicApplicationContext& that) : - lock_(that.viewportMutex_), - viewport_(that.centralViewport_) - { - } - - IViewport& GetViewport() const - { - return viewport_; - } - }; - - - BasicApplicationContext(Orthanc::WebServiceParameters& orthanc); + virtual IWebService& GetWebService() = 0; + virtual IWidget& SetCentralWidget(IWidget* widget) = 0; // Takes ownership virtual ~BasicApplicationContext() {} - - IWidget& SetCentralWidget(IWidget* widget); // Takes ownership - - IWebService& GetWebService() - { - return webService_; - } - - void Start(); - - void Stop(); - - void SetUpdateDelay(unsigned int delay) // In milliseconds - { - updateDelay_ = delay; - } }; }
--- a/Applications/IBasicApplication.h Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/IBasicApplication.h Tue Jun 12 17:21:15 2018 +0200 @@ -23,6 +23,7 @@ #include "BasicApplicationContext.h" #include <boost/program_options.hpp> +#include "../Framework/Viewport/WidgetViewport.h" namespace OrthancStone { @@ -63,8 +64,11 @@ virtual void Initialize(IStatusBar& statusBar, const boost::program_options::variables_map& parameters) = 0; - virtual BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthanc) = 0; - +#if ORTHANC_ENABLE_SDL == 1 + virtual BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthancWebService) = 0; +#else + virtual BasicApplicationContext& CreateApplicationContext(IWebService& orthancWebService, std::shared_ptr<WidgetViewport> centralViewport) = 0; +#endif virtual std::string GetTitle() const = 0;
--- a/Applications/Samples/SampleApplicationContext.h Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/Samples/SampleApplicationContext.h Tue Jun 12 17:21:15 2018 +0200 @@ -34,7 +34,16 @@ namespace OrthancStone { - class SampleApplicationContext : public BasicApplicationContext + +#if ORTHANC_ENABLE_SDL +#include "../Sdl/BasicSdlApplicationContext.h" +typedef BasicSdlApplicationContext BasicApplicationContext_; +#else +#include "../Wasm/BasicWasmApplicationContext.h" +typedef BasicWasmApplicationContext BasicApplicationContext_; +#endif + + class SampleApplicationContext : public BasicApplicationContext_ { private: typedef std::list<ISlicedVolume*> SlicedVolumes; // this is actually used by the samples and shall be moved to a SampleApplicationContext
--- a/Applications/Sdl/BasicSdlApplication.cpp Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/Sdl/BasicSdlApplication.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -243,12 +243,12 @@ LOG(WARNING) << "Creating the widgets of the application"; LogStatusBar statusBar; - BasicApplicationContext& context = application.CreateApplicationContext(webService); + BasicSdlApplicationContext& context = dynamic_cast<BasicSdlApplicationContext&>(application.CreateApplicationContext(webService)); application.Initialize(statusBar, parameters); { - BasicApplicationContext::ViewportLocker locker(context); + BasicSdlApplicationContext::ViewportLocker locker(context); locker.GetViewport().SetStatusBar(statusBar); } @@ -269,7 +269,7 @@ SdlEngine sdl(window, context); { - BasicApplicationContext::ViewportLocker locker(context); + BasicSdlApplicationContext::ViewportLocker locker(context); locker.GetViewport().Register(sdl); // (*) }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Sdl/BasicSdlApplicationContext.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,81 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 "BasicSdlApplicationContext.h" + +namespace OrthancStone +{ + IWidget& BasicSdlApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership + { + centralViewport_.SetCentralWidget(widget); + return *widget; + } + + + void BasicSdlApplicationContext::UpdateThread(BasicSdlApplicationContext* that) + { + while (!that->stopped_) + { + { + ViewportLocker locker(*that); + locker.GetViewport().UpdateContent(); + } + + boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelay_)); + } + } + + + BasicSdlApplicationContext::BasicSdlApplicationContext(Orthanc::WebServiceParameters& orthanc) : + oracle_(viewportMutex_, 4), // Use 4 threads to download + //oracle_(viewportMutex_, 1), // Disable threading to be reproducible + webService_(oracle_, orthanc), + stopped_(true), + updateDelay_(100) // By default, 100ms between each refresh of the content + { + srand(time(NULL)); + } + + + void BasicSdlApplicationContext::Start() + { + oracle_.Start(); + + if (centralViewport_.HasUpdateContent()) + { + stopped_ = false; + updateThread_ = boost::thread(UpdateThread, this); + } + } + + + void BasicSdlApplicationContext::Stop() + { + stopped_ = true; + + if (updateThread_.joinable()) + { + updateThread_.join(); + } + + oracle_.Stop(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Sdl/BasicSdlApplicationContext.h Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,91 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 "../../Framework/Viewport/WidgetViewport.h" +#include "../../Framework/Volumes/ISlicedVolume.h" +#include "../../Framework/Volumes/IVolumeLoader.h" +#include "../../Framework/Widgets/IWorldSceneInteractor.h" +#include "../../Platforms/Generic/OracleWebService.h" + +#include <list> +#include <boost/thread.hpp> +#include "../BasicApplicationContext.h" + +namespace OrthancStone +{ + class BasicSdlApplicationContext : public BasicApplicationContext + { + private: + + static void UpdateThread(BasicSdlApplicationContext* that); + + Oracle oracle_; + OracleWebService webService_; + boost::mutex viewportMutex_; + WidgetViewport centralViewport_; + boost::thread updateThread_; + bool stopped_; + unsigned int updateDelay_; + + public: + class ViewportLocker : public boost::noncopyable + { + private: + boost::mutex::scoped_lock lock_; + IViewport& viewport_; + + public: + ViewportLocker(BasicSdlApplicationContext& that) : + lock_(that.viewportMutex_), + viewport_(that.centralViewport_) + { + } + + IViewport& GetViewport() const + { + return viewport_; + } + }; + + + BasicSdlApplicationContext(Orthanc::WebServiceParameters& orthanc); + + virtual ~BasicSdlApplicationContext() {} + + virtual IWidget& SetCentralWidget(IWidget* widget); // Takes ownership + + virtual IWebService& GetWebService() + { + return webService_; + } + + void Start(); + + void Stop(); + + void SetUpdateDelay(unsigned int delay) // In milliseconds + { + updateDelay_ = delay; + } + }; +}
--- a/Applications/Sdl/SdlEngine.cpp Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/Sdl/SdlEngine.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -29,7 +29,7 @@ namespace OrthancStone { - void SdlEngine::SetSize(BasicApplicationContext::ViewportLocker& locker, + void SdlEngine::SetSize(BasicSdlApplicationContext::ViewportLocker& locker, unsigned int width, unsigned int height) { @@ -42,7 +42,7 @@ { if (viewportChanged_) { - BasicApplicationContext::ViewportLocker locker(context_); + BasicSdlApplicationContext::ViewportLocker locker(context_); surface_.Render(locker.GetViewport()); viewportChanged_ = false; @@ -99,7 +99,7 @@ SdlEngine::SdlEngine(SdlWindow& window, - BasicApplicationContext& context) : + BasicSdlApplicationContext& context) : window_(window), context_(context), surface_(window), @@ -119,7 +119,7 @@ const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); { - BasicApplicationContext::ViewportLocker locker(context_); + BasicSdlApplicationContext::ViewportLocker locker(context_); SetSize(locker, window_.GetWidth(), window_.GetHeight()); locker.GetViewport().SetDefaultView(); } @@ -134,7 +134,7 @@ while (!stop && SDL_PollEvent(&event)) { - BasicApplicationContext::ViewportLocker locker(context_); + BasicSdlApplicationContext::ViewportLocker locker(context_); if (event.type == SDL_QUIT) {
--- a/Applications/Sdl/SdlEngine.h Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/Sdl/SdlEngine.h Tue Jun 12 17:21:15 2018 +0200 @@ -24,7 +24,7 @@ #if ORTHANC_ENABLE_SDL == 1 #include "SdlCairoSurface.h" -#include "../BasicApplicationContext.h" +#include "BasicSdlApplicationContext.h" namespace OrthancStone { @@ -32,11 +32,11 @@ { private: SdlWindow& window_; - BasicApplicationContext& context_; + BasicSdlApplicationContext& context_; SdlCairoSurface surface_; bool viewportChanged_; - void SetSize(BasicApplicationContext::ViewportLocker& locker, + void SetSize(BasicSdlApplicationContext::ViewportLocker& locker, unsigned int width, unsigned int height); @@ -47,7 +47,7 @@ public: SdlEngine(SdlWindow& window, - BasicApplicationContext& context); + BasicSdlApplicationContext& context); virtual ~SdlEngine();
--- a/Applications/Wasm/BasicWasmApplication.cpp Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/Wasm/BasicWasmApplication.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,43 @@ +#include "BasicWasmApplication.h" + +namespace OrthancStone +{ + + + void BasicWasmApplication::SetStartupParameter(const char* name, const char* value) { + startupParameters_.push_back(std::make_tuple(name, value)); + } + + void BasicWasmApplication::GetStartupParameters(boost::program_options::variables_map& parameters) { + boost::program_options::options_description options; + DeclareStartupOptions(options); + + const char* argv[startupParameters_.size() + 1]; + int argCounter = 0; + argv[0] = "Toto.exe"; + argCounter++; + + std::string cmdLine = ""; + for (StartupParameters::const_iterator it = startupParameters_.begin(); it != startupParameters_.end(); it++) { + char* arg = new char[128]; + snprintf(arg, 128, "--%s=%s", std::get<0>(*it).c_str(), std::get<1>(*it).c_str()); + argv[argCounter] = arg; + cmdLine = cmdLine + " --" + std::get<0>(*it) + "=" + std::get<1>(*it); + argCounter++; + } + + printf("simulated cmdLine = %s\n", cmdLine.c_str()); + + try + { + boost::program_options::store(boost::program_options::command_line_parser(argCounter, argv). + options(options).run(), parameters); + boost::program_options::notify(parameters); + } + catch (boost::program_options::error& e) + { + printf("Error while parsing the command-line arguments: %s\n", e.what()); + } + + } +} \ No newline at end of file
--- a/Applications/Wasm/BasicWasmApplication.h Mon Jun 11 14:01:02 2018 +0200 +++ b/Applications/Wasm/BasicWasmApplication.h Tue Jun 12 17:21:15 2018 +0200 @@ -25,6 +25,7 @@ #include "../IBasicApplication.h" #include <boost/program_options.hpp> +#include <tuple> #if ORTHANC_ENABLE_SDL == 1 #error this file shall be included only with the ORTHANC_ENABLE_SDL set to 0 @@ -34,11 +35,19 @@ { class BasicWasmApplication : public IBasicApplication { + typedef std::list<std::tuple<std::string, std::string>> StartupParameters; + StartupParameters startupParameters_; + public: virtual ~BasicWasmApplication() { } + void SetStartupParameter(const char* name, const char* value); + void GetStartupParameters(boost::program_options::variables_map& parameters_); + + virtual IWidget* GetCentralWidget() = 0; + //static int ExecuteWithWasm(BasicWasmApplication& application); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Wasm/BasicWasmApplicationContext.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,14 @@ +#include "BasicWasmApplicationContext.h" + +namespace OrthancStone +{ + IWidget& BasicWasmApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership + { + printf("BasicWasmApplicationContext::SetCentralWidget %x %x\n", centralViewport_.get(), widget); + assert(centralViewport_.get() != NULL); + centralViewport_->SetCentralWidget(widget); + printf("BasicWasmApplicationContext::SetCentralWidget done\n"); + return *widget; + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Wasm/BasicWasmApplicationContext.h Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,52 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 "../BasicApplicationContext.h" + +#include <list> + +namespace OrthancStone +{ + class BasicWasmApplicationContext : public BasicApplicationContext + { + private: + std::shared_ptr<WidgetViewport> centralViewport_; + IWebService& webService_; + public: + BasicWasmApplicationContext(IWebService& webService, std::shared_ptr<WidgetViewport> centralViewport) //shared ownership of centralViewport + : webService_(webService), + centralViewport_(centralViewport) + { + + } + + virtual IWidget& SetCentralWidget(IWidget* widget); // Takes ownership of central widget + + IWebService& GetWebService() + { + return webService_; + } + + virtual ~BasicWasmApplicationContext() {} + }; +}
--- a/Framework/Viewport/WidgetViewport.cpp Mon Jun 11 14:01:02 2018 +0200 +++ b/Framework/Viewport/WidgetViewport.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -64,7 +64,7 @@ } mouseTracker_.reset(NULL); - + centralWidget_.reset(widget); centralWidget_->SetViewport(*this);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/WebAssembly/Defaults.cpp Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,2 @@ +#include "Defaults.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/WebAssembly/Defaults.h Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,62 @@ +#pragma once + +#include <Framework/dev.h> +#include <Framework/Viewport/WidgetViewport.h> +#include <Framework/Widgets/LayerWidget.h> +#include <Framework/Widgets/LayoutWidget.h> + +#ifdef __cplusplus +extern "C" { +#endif + + extern void ScheduleRedraw(); + +#ifdef __cplusplus +} +#endif + + +namespace OrthancStone { + + class ChangeObserver : + public OrthancStone::IViewport::IObserver + { + private: + // Flag to avoid flooding JavaScript with redundant Redraw requests + bool isScheduled_; + + public: + ChangeObserver() : + isScheduled_(false) + { + } + + void Reset() + { + isScheduled_ = false; + } + + virtual void NotifyChange(const OrthancStone::IViewport &scene) + { + if (!isScheduled_) + { + ScheduleRedraw(); + isScheduled_ = true; + } + } + }; + + + class StatusBar : public OrthancStone::IStatusBar + { + public: + virtual void ClearMessage() + { + } + + virtual void SetMessage(const std::string& message) + { + printf("%s\n", message.c_str()); + } + }; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/WebAssembly/defaultLibrary.js Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,8 @@ +// this file contains the JS method you want to expose to C++ code + +mergeInto(LibraryManager.library, { + ScheduleRedraw: function() { + ScheduleRedraw(); + } + }); + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/WebAssembly/defaults.js Tue Jun 12 17:21:15 2018 +0200 @@ -0,0 +1,13 @@ +var isPendingRedraw = false; + +function ScheduleRedraw() +{ + if (!isPendingRedraw) { + isPendingRedraw = true; + //console.log('Scheduling a refresh of the viewport, as its content changed'); + window.requestAnimationFrame(function() { + isPendingRedraw = false; + viewport.Redraw(); + }); + } +}
--- a/README Mon Jun 11 14:01:02 2018 +0200 +++ b/README Tue Jun 12 17:21:15 2018 +0200 @@ -72,6 +72,10 @@ * Optionally, SDL, a cross-platform multimedia library: https://www.libsdl.org/ +Prerequisites to compile on Ubuntu: +``` +sudo apt-get install -y libcairo-dev libpixman-1-dev libsdl2-dev +``` Installation and usage ----------------------
--- a/Resources/CMake/OrthancStoneConfiguration.cmake Mon Jun 11 14:01:02 2018 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Tue Jun 12 17:21:15 2018 +0200 @@ -137,6 +137,7 @@ set(APPLICATIONS_SOURCES ${ORTHANC_STONE_ROOT}/Applications/IBasicApplication.h + ${ORTHANC_STONE_ROOT}/Applications/BasicApplicationContext.cpp ) if (NOT ORTHANC_SANDBOXED) @@ -147,8 +148,8 @@ ) list(APPEND APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/BasicApplicationContext.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/BasicSdlApplication.cpp + ${ORTHANC_STONE_ROOT}/Applications/Sdl/BasicSdlApplicationContext.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlEngine.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlCairoSurface.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlOrthancSurface.cpp @@ -157,6 +158,7 @@ else() list(APPEND APPLICATIONS_SOURCES ${ORTHANC_STONE_ROOT}/Applications/Wasm/BasicWasmApplication.cpp + ${ORTHANC_STONE_ROOT}/Applications/Wasm/BasicWasmApplicationContext.cpp ) endif() @@ -197,6 +199,7 @@ ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoContext.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoFont.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoSurface.cpp + ${ORTHANC_STONE_ROOT}/Framework/Viewport/IStatusBar.h ${ORTHANC_STONE_ROOT}/Framework/Viewport/WidgetViewport.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/ImageBuffer3D.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/SlicedVolumeBase.cpp