# HG changeset patch # User Sebastien Jodogne # Date 1541620181 -3600 # Node ID 6cc3ce74dc056dc51e6e1ac7154372ec838c6193 # Parent d20d75f20c5d3c46a9caabf68a802b2e303aa56b using message broker in widgets diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Generic/NativeStoneApplicationContext.cpp --- a/Applications/Generic/NativeStoneApplicationContext.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Generic/NativeStoneApplicationContext.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -24,9 +24,9 @@ namespace OrthancStone { - IWidget& NativeStoneApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership + IWidget& NativeStoneApplicationContext::GlobalMutexLocker::SetCentralWidget(IWidget* widget) { - centralViewport_->SetCentralWidget(widget); + that_.centralViewport_.SetCentralWidget(widget); return *widget; } @@ -37,7 +37,7 @@ { { GlobalMutexLocker locker(*that); - that->GetCentralViewport().UpdateContent(); + locker.GetCentralViewport().UpdateContent(); } boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelayInMs_)); @@ -45,8 +45,9 @@ } - NativeStoneApplicationContext::NativeStoneApplicationContext() : - centralViewport_(new OrthancStone::WidgetViewport()), + NativeStoneApplicationContext::NativeStoneApplicationContext(MessageBroker& broker) : + broker_(broker), + centralViewport_(broker), stopped_(true), updateDelayInMs_(100) // By default, 100ms between each refresh of the content { @@ -56,7 +57,10 @@ void NativeStoneApplicationContext::Start() { - if (centralViewport_->HasUpdateContent()) + boost::mutex::scoped_lock lock(globalMutex_); + + if (stopped_ && + centralViewport_.HasUpdateContent()) { stopped_ = false; updateThread_ = boost::thread(UpdateThread, this); diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Generic/NativeStoneApplicationContext.h --- a/Applications/Generic/NativeStoneApplicationContext.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Generic/NativeStoneApplicationContext.h Wed Nov 07 20:49:41 2018 +0100 @@ -34,46 +34,51 @@ class NativeStoneApplicationContext : public StoneApplicationContext { private: - static void UpdateThread(NativeStoneApplicationContext* that); - boost::mutex globalMutex_; - std::auto_ptr centralViewport_; - boost::thread updateThread_; - bool stopped_; - unsigned int updateDelayInMs_; + boost::mutex globalMutex_; + MessageBroker& broker_; + WidgetViewport centralViewport_; + boost::thread updateThread_; + bool stopped_; + unsigned int updateDelayInMs_; public: class GlobalMutexLocker: public boost::noncopyable { - boost::mutex::scoped_lock lock_; + private: + NativeStoneApplicationContext& that_; + boost::mutex::scoped_lock lock_; + public: - GlobalMutexLocker(NativeStoneApplicationContext& that): + GlobalMutexLocker(NativeStoneApplicationContext& that) : + that_(that), lock_(that.globalMutex_) { } + + IWidget& SetCentralWidget(IWidget* widget); // Takes ownership + + MessageBroker& GetMessageBroker() const + { + return that_.broker_; + } + + IViewport& GetCentralViewport() + { + return that_.centralViewport_; + } + + void SetUpdateDelay(unsigned int delayInMs) + { + that_.updateDelayInMs_ = delayInMs; + } }; - NativeStoneApplicationContext(); - - virtual ~NativeStoneApplicationContext() - { - } - - virtual IWidget& SetCentralWidget(IWidget* widget); // Takes ownership - - IViewport& GetCentralViewport() - { - return *(centralViewport_.get()); - } + NativeStoneApplicationContext(MessageBroker& broker); void Start(); void Stop(); - - void SetUpdateDelay(unsigned int delayInMs) - { - updateDelayInMs_ = delayInMs; - } }; } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Generic/NativeStoneApplicationRunner.cpp --- a/Applications/Generic/NativeStoneApplicationRunner.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Generic/NativeStoneApplicationRunner.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -24,16 +24,18 @@ #endif #include "NativeStoneApplicationRunner.h" -#include "NativeStoneApplicationContext.h" -#include #include "../../Framework/Toolbox/MessagingToolbox.h" +#include "../../Platforms/Generic/OracleWebService.h" +#include "NativeStoneApplicationContext.h" #include #include #include +#include #include -#include "../../Platforms/Generic/OracleWebService.h" + +#include namespace OrthancStone { @@ -183,7 +185,7 @@ LogStatusBar statusBar; - NativeStoneApplicationContext context; + NativeStoneApplicationContext context(broker_); { Oracle oracle(4); // use 4 threads to download content @@ -197,8 +199,8 @@ { NativeStoneApplicationContext::GlobalMutexLocker locker(context); - context.SetCentralWidget(application_.GetCentralWidget()); - context.GetCentralViewport().SetStatusBar(statusBar); + locker.SetCentralWidget(application_.GetCentralWidget()); + locker.GetCentralViewport().SetStatusBar(statusBar); } std::string title = application_.GetTitle(); diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Qt/QCairoWidget.cpp --- a/Applications/Qt/QCairoWidget.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Qt/QCairoWidget.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -25,6 +25,20 @@ #include + +QCairoWidget::StoneObserver::StoneObserver(QCairoWidget& that, + OrthancStone::IViewport& viewport, + OrthancStone::MessageBroker& broker) : + OrthancStone::IObserver(broker), + that_(that) +{ + // get notified each time the content of the central viewport changes + viewport.RegisterObserverCallback( + new OrthancStone::Callable + (*this, &StoneObserver::OnViewportChanged)); +} + + QCairoWidget::QCairoWidget(QWidget *parent) : QWidget(parent), context_(NULL) @@ -32,24 +46,29 @@ setFocusPolicy(Qt::StrongFocus); // catch keyPressEvents } -QCairoWidget::~QCairoWidget() -{ -} void QCairoWidget::SetContext(OrthancStone::NativeStoneApplicationContext& context) { context_ = &context; - context_->GetCentralViewport().Register(*this); // get notified each time the content of the central viewport changes + + { + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + observer_.reset(new StoneObserver(*this, + locker.GetCentralViewport(), + locker.GetMessageBroker())); + } } + void QCairoWidget::paintEvent(QPaintEvent* /*event*/) { QPainter painter(this); - if (image_.get() != NULL && context_ != NULL) + if (image_.get() != NULL && + context_ != NULL) { OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - OrthancStone::IViewport& viewport = context_->GetCentralViewport(); + OrthancStone::IViewport& viewport = locker.GetCentralViewport(); Orthanc::ImageAccessor a; surface_.GetWriteableAccessor(a); viewport.Render(a); @@ -103,35 +122,43 @@ default: return; // Unsupported button } - context_->GetCentralViewport().MouseDown(button, event->pos().x(), event->pos().y(), stoneModifiers); + + { + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + locker.GetCentralViewport().MouseDown(button, event->pos().x(), event->pos().y(), stoneModifiers); + } } void QCairoWidget::mouseReleaseEvent(QMouseEvent* /*eventNotUsed*/) { - context_->GetCentralViewport().MouseLeave(); + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + locker.GetCentralViewport().MouseLeave(); } void QCairoWidget::mouseMoveEvent(QMouseEvent* event) { - context_->GetCentralViewport().MouseMove(event->pos().x(), event->pos().y()); + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + locker.GetCentralViewport().MouseMove(event->pos().x(), event->pos().y()); } void QCairoWidget::wheelEvent(QWheelEvent * event) { + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + OrthancStone::KeyboardModifiers stoneModifiers = GetKeyboardModifiers(event); if (event->orientation() == Qt::Vertical) { if (event->delta() < 0) // TODO: compare direction with SDL and make sure we send the same directions { - context_->GetCentralViewport().MouseWheel(OrthancStone::MouseWheelDirection_Up, event->pos().x(), event->pos().y(), stoneModifiers); + locker.GetCentralViewport().MouseWheel(OrthancStone::MouseWheelDirection_Up, event->pos().x(), event->pos().y(), stoneModifiers); } else { - context_->GetCentralViewport().MouseWheel(OrthancStone::MouseWheelDirection_Down, event->pos().x(), event->pos().y(), stoneModifiers); + locker.GetCentralViewport().MouseWheel(OrthancStone::MouseWheelDirection_Down, event->pos().x(), event->pos().y(), stoneModifiers); } } } @@ -158,7 +185,11 @@ break; } } - context_->GetCentralViewport().KeyPressed(keyType, keyChar, stoneModifiers); + + { + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + locker.GetCentralViewport().KeyPressed(keyType, keyChar, stoneModifiers); + } } @@ -177,7 +208,9 @@ surface_.GetPitch(), QImage::Format_RGB32)); - context_->GetCentralViewport().SetSize(event->size().width(), event->size().height()); - + { + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); + locker.GetCentralViewport().SetSize(event->size().width(), event->size().height()); + } } } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Qt/QCairoWidget.h --- a/Applications/Qt/QCairoWidget.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Qt/QCairoWidget.h Wed Nov 07 20:49:41 2018 +0100 @@ -1,7 +1,7 @@ /** * Stone of Orthanc * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium +4 * 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 @@ -20,23 +20,39 @@ #pragma once -#include "../../Framework/Widgets/CairoWidget.h" #include "../../Applications/Generic/NativeStoneApplicationContext.h" #include "../../Framework/Viewport/CairoSurface.h" +#include "../../Framework/Widgets/IWidget.h" #include -#include #include #include -class QCairoWidget : public QWidget, public OrthancStone::IViewport::IObserver +class QCairoWidget : public QWidget { Q_OBJECT private: + class StoneObserver : public OrthancStone::IObserver + { + private: + QCairoWidget& that_; + + public: + StoneObserver(QCairoWidget& that, + OrthancStone::IViewport& viewport, + OrthancStone::MessageBroker& broker); + + void OnViewportChanged(const OrthancStone::IViewport::ViewportChangedMessage& message) + { + that_.OnViewportChanged(); + } + }; + std::auto_ptr image_; OrthancStone::CairoSurface surface_; OrthancStone::NativeStoneApplicationContext* context_; + std::auto_ptr observer_; protected: virtual void paintEvent(QPaintEvent *event); @@ -56,18 +72,15 @@ public: explicit QCairoWidget(QWidget *parent); - virtual ~QCairoWidget(); - void SetContext(OrthancStone::NativeStoneApplicationContext& context); - virtual void OnViewportContentChanged(const OrthancStone::IViewport& /*sceneNotUsed*/) + void OnViewportChanged() { update(); // schedule a repaint (handled by Qt) emit ContentChanged(); } signals: - void ContentChanged(); public slots: diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Qt/QStoneMainWindow.cpp --- a/Applications/Qt/QStoneMainWindow.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Qt/QStoneMainWindow.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -23,15 +23,17 @@ namespace OrthancStone { - QStoneMainWindow::QStoneMainWindow(NativeStoneApplicationContext& context, QWidget *parent) : + QStoneMainWindow::QStoneMainWindow(NativeStoneApplicationContext& context, + QWidget *parent) : QMainWindow(parent), - context_(context) + context_(context), + cairoCentralWidget_(NULL) { } - void QStoneMainWindow::SetCentralStoneWidget(QCairoWidget *centralWidget) + void QStoneMainWindow::SetCentralStoneWidget(QCairoWidget& centralWidget) { - cairoCentralWidget_ = centralWidget; + cairoCentralWidget_ = ¢ralWidget; cairoCentralWidget_->SetContext(context_); } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Qt/QStoneMainWindow.h --- a/Applications/Qt/QStoneMainWindow.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Qt/QStoneMainWindow.h Wed Nov 07 20:49:41 2018 +0100 @@ -36,10 +36,10 @@ protected: // you must inherit this class QStoneMainWindow(NativeStoneApplicationContext& context, QWidget *parent = 0); - void SetCentralStoneWidget(QCairoWidget* centralWidget); + void SetCentralStoneWidget(QCairoWidget& centralWidget); + public: virtual ~QStoneMainWindow(); - }; } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Samples/Qt/SampleMainWindow.cpp --- a/Applications/Samples/Qt/SampleMainWindow.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Samples/Qt/SampleMainWindow.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -32,13 +32,16 @@ namespace Samples { - SampleMainWindow::SampleMainWindow(OrthancStone::NativeStoneApplicationContext& context, OrthancStone::Samples::SampleSingleCanvasApplicationBase& stoneSampleApplication, QWidget *parent) : + SampleMainWindow::SampleMainWindow( + OrthancStone::NativeStoneApplicationContext& context, + OrthancStone::Samples::SampleSingleCanvasApplicationBase& stoneSampleApplication, + QWidget *parent) : QStoneMainWindow(context, parent), ui_(new Ui::SampleMainWindow), stoneSampleApplication_(stoneSampleApplication) { ui_->setupUi(this); - SetCentralStoneWidget(ui_->cairoCentralWidget); + SetCentralStoneWidget(*ui_->cairoCentralWidget); } SampleMainWindow::~SampleMainWindow() diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Samples/Qt/SampleMainWindowWithButtons.cpp --- a/Applications/Samples/Qt/SampleMainWindowWithButtons.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Samples/Qt/SampleMainWindowWithButtons.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -32,13 +32,16 @@ namespace Samples { - SampleMainWindowWithButtons::SampleMainWindowWithButtons(OrthancStone::NativeStoneApplicationContext& context, OrthancStone::Samples::SampleSingleCanvasWithButtonsApplicationBase& stoneSampleApplication, QWidget *parent) : + SampleMainWindowWithButtons::SampleMainWindowWithButtons( + OrthancStone::NativeStoneApplicationContext& context, + OrthancStone::Samples::SampleSingleCanvasWithButtonsApplicationBase& stoneSampleApplication, + QWidget *parent) : QStoneMainWindow(context, parent), ui_(new Ui::SampleMainWindowWithButtons), stoneSampleApplication_(stoneSampleApplication) { ui_->setupUi(this); - SetCentralStoneWidget(ui_->cairoCentralWidget); + SetCentralStoneWidget(*ui_->cairoCentralWidget); #if QT_VERSION >= 0x050000 connect(ui_->toolButton1, &QToolButton::clicked, this, &SampleMainWindowWithButtons::tool1Clicked); diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.cpp --- a/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -30,13 +30,16 @@ namespace SimpleViewer { - SimpleViewerMainWindow::SimpleViewerMainWindow(OrthancStone::NativeStoneApplicationContext& context, SimpleViewerApplication& stoneApplication, QWidget *parent) : + SimpleViewerMainWindow::SimpleViewerMainWindow( + OrthancStone::NativeStoneApplicationContext& context, + SimpleViewerApplication& stoneApplication, + QWidget *parent) : QStoneMainWindow(context, parent), ui_(new Ui::SimpleViewerMainWindow), stoneApplication_(stoneApplication) { ui_->setupUi(this); - SetCentralStoneWidget(ui_->cairoCentralWidget); + SetCentralStoneWidget(*ui_->cairoCentralWidget); #if QT_VERSION >= 0x050000 connect(ui_->toolButtonCrop, &QToolButton::clicked, this, &SimpleViewerMainWindow::cropClicked); diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Sdl/SdlEngine.cpp --- a/Applications/Sdl/SdlEngine.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Sdl/SdlEngine.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -32,7 +32,8 @@ void SdlEngine::SetSize(unsigned int width, unsigned int height) { - context_.GetCentralViewport().SetSize(width, height); + NativeStoneApplicationContext::GlobalMutexLocker locker(context_); + locker.GetCentralViewport().SetSize(width, height); surface_.SetSize(width, height); } @@ -42,7 +43,7 @@ if (viewportChanged_) { NativeStoneApplicationContext::GlobalMutexLocker locker(context_); - surface_.Render(context_.GetCentralViewport()); + surface_.Render(locker.GetCentralViewport()); viewportChanged_ = false; } @@ -98,7 +99,9 @@ SdlEngine::SdlEngine(SdlWindow& window, - NativeStoneApplicationContext& context) : + NativeStoneApplicationContext& context, + MessageBroker& broker) : + IObserver(broker), window_(window), context_(context), surface_(window), @@ -107,20 +110,16 @@ } - SdlEngine::~SdlEngine() - { - } - - void SdlEngine::Run() { int scancodeCount = 0; const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); + SetSize(window_.GetWidth(), window_.GetHeight()); + { NativeStoneApplicationContext::GlobalMutexLocker locker(context_); - SetSize(window_.GetWidth(), window_.GetHeight()); - context_.GetCentralViewport().FitContent(); + locker.GetCentralViewport().FitContent(); } bool stop = false; @@ -147,15 +146,15 @@ switch (event.button.button) { case SDL_BUTTON_LEFT: - context_.GetCentralViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers); + locker.GetCentralViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers); break; case SDL_BUTTON_RIGHT: - context_.GetCentralViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers); + locker.GetCentralViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers); break; case SDL_BUTTON_MIDDLE: - context_.GetCentralViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers); + locker.GetCentralViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers); break; default: @@ -164,22 +163,22 @@ } else if (event.type == SDL_MOUSEMOTION) { - context_.GetCentralViewport().MouseMove(event.button.x, event.button.y); + locker.GetCentralViewport().MouseMove(event.button.x, event.button.y); } else if (event.type == SDL_MOUSEBUTTONUP) { - context_.GetCentralViewport().MouseUp(); + locker.GetCentralViewport().MouseUp(); } else if (event.type == SDL_WINDOWEVENT) { switch (event.window.event) { case SDL_WINDOWEVENT_LEAVE: - context_.GetCentralViewport().MouseLeave(); + locker.GetCentralViewport().MouseLeave(); break; case SDL_WINDOWEVENT_ENTER: - context_.GetCentralViewport().MouseEnter(); + locker.GetCentralViewport().MouseEnter(); break; case SDL_WINDOWEVENT_SIZE_CHANGED: @@ -199,11 +198,11 @@ if (event.wheel.y > 0) { - context_.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers); + locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers); } else if (event.wheel.y < 0) { - context_.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers); + locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers); } } else if (event.type == SDL_KEYDOWN && @@ -213,59 +212,59 @@ switch (event.key.keysym.sym) { - case SDLK_a: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'a', modifiers); break; - case SDLK_b: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'b', modifiers); break; - case SDLK_c: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'c', modifiers); break; - case SDLK_d: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'd', modifiers); break; - case SDLK_e: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'e', modifiers); break; + case SDLK_a: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'a', modifiers); break; + case SDLK_b: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'b', modifiers); break; + case SDLK_c: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'c', modifiers); break; + case SDLK_d: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'd', modifiers); break; + case SDLK_e: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'e', modifiers); break; case SDLK_f: window_.ToggleMaximize(); break; - case SDLK_g: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'g', modifiers); break; - case SDLK_h: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'h', modifiers); break; - case SDLK_i: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'i', modifiers); break; - case SDLK_j: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'j', modifiers); break; - case SDLK_k: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'k', modifiers); break; - case SDLK_l: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'l', modifiers); break; - case SDLK_m: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'm', modifiers); break; - case SDLK_n: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'n', modifiers); break; - case SDLK_o: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'o', modifiers); break; - case SDLK_p: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'p', modifiers); break; + case SDLK_g: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'g', modifiers); break; + case SDLK_h: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'h', modifiers); break; + case SDLK_i: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'i', modifiers); break; + case SDLK_j: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'j', modifiers); break; + case SDLK_k: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'k', modifiers); break; + case SDLK_l: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'l', modifiers); break; + case SDLK_m: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'm', modifiers); break; + case SDLK_n: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'n', modifiers); break; + case SDLK_o: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'o', modifiers); break; + case SDLK_p: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'p', modifiers); break; case SDLK_q: stop = true; break; - case SDLK_r: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'r', modifiers); break; - case SDLK_s: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 's', modifiers); break; - case SDLK_t: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 't', modifiers); break; - case SDLK_u: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'u', modifiers); break; - case SDLK_v: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'v', modifiers); break; - case SDLK_w: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'w', modifiers); break; - case SDLK_x: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'x', modifiers); break; - case SDLK_y: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'y', modifiers); break; - case SDLK_z: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'z', modifiers); break; - case SDLK_KP_0: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '0', modifiers); break; - case SDLK_KP_1: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '1', modifiers); break; - case SDLK_KP_2: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '2', modifiers); break; - case SDLK_KP_3: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '3', modifiers); break; - case SDLK_KP_4: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '4', modifiers); break; - case SDLK_KP_5: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '5', modifiers); break; - case SDLK_KP_6: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '6', modifiers); break; - case SDLK_KP_7: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '7', modifiers); break; - case SDLK_KP_8: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '8', modifiers); break; - case SDLK_KP_9: context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '9', modifiers); break; + case SDLK_r: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'r', modifiers); break; + case SDLK_s: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 's', modifiers); break; + case SDLK_t: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 't', modifiers); break; + case SDLK_u: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'u', modifiers); break; + case SDLK_v: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'v', modifiers); break; + case SDLK_w: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'w', modifiers); break; + case SDLK_x: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'x', modifiers); break; + case SDLK_y: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'y', modifiers); break; + case SDLK_z: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'z', modifiers); break; + case SDLK_KP_0: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '0', modifiers); break; + case SDLK_KP_1: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '1', modifiers); break; + case SDLK_KP_2: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '2', modifiers); break; + case SDLK_KP_3: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '3', modifiers); break; + case SDLK_KP_4: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '4', modifiers); break; + case SDLK_KP_5: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '5', modifiers); break; + case SDLK_KP_6: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '6', modifiers); break; + case SDLK_KP_7: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '7', modifiers); break; + case SDLK_KP_8: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '8', modifiers); break; + case SDLK_KP_9: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '9', modifiers); break; case SDLK_PLUS: case SDLK_KP_PLUS: - context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '+', modifiers); break; + locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '+', modifiers); break; case SDLK_MINUS: case SDLK_KP_MINUS: - context_.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '-', modifiers); break; + locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '-', modifiers); break; case SDLK_RIGHT: - context_.GetCentralViewport().KeyPressed(KeyboardKeys_Right, 0, modifiers); break; + locker.GetCentralViewport().KeyPressed(KeyboardKeys_Right, 0, modifiers); break; case SDLK_LEFT: - context_.GetCentralViewport().KeyPressed(KeyboardKeys_Left, 0, modifiers); break; + locker.GetCentralViewport().KeyPressed(KeyboardKeys_Left, 0, modifiers); break; case SDLK_UP: - context_.GetCentralViewport().KeyPressed(KeyboardKeys_Up, 0, modifiers); break; + locker.GetCentralViewport().KeyPressed(KeyboardKeys_Up, 0, modifiers); break; case SDLK_DOWN: - context_.GetCentralViewport().KeyPressed(KeyboardKeys_Down, 0, modifiers); break; + locker.GetCentralViewport().KeyPressed(KeyboardKeys_Down, 0, modifiers); break; default: break; } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Sdl/SdlEngine.h --- a/Applications/Sdl/SdlEngine.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Sdl/SdlEngine.h Wed Nov 07 20:49:41 2018 +0100 @@ -28,7 +28,7 @@ namespace OrthancStone { - class SdlEngine : public IViewport::IObserver + class SdlEngine : public IObserver { private: SdlWindow& window_; @@ -46,11 +46,10 @@ public: SdlEngine(SdlWindow& window, - NativeStoneApplicationContext& context); + NativeStoneApplicationContext& context, + MessageBroker& broker); - virtual ~SdlEngine(); - - virtual void OnViewportContentChanged(const IViewport& viewport) + void OnViewportChanged(const IViewport::ViewportChangedMessage& message) { viewportChanged_ = true; } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Sdl/SdlStoneApplicationRunner.cpp --- a/Applications/Sdl/SdlStoneApplicationRunner.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Sdl/SdlStoneApplicationRunner.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -24,16 +24,18 @@ #endif #include "SdlStoneApplicationRunner.h" -#include #include "../../Framework/Toolbox/MessagingToolbox.h" +#include "../../Platforms/Generic/OracleWebService.h" #include "SdlEngine.h" #include #include #include +#include #include -#include "../../Platforms/Generic/OracleWebService.h" + +#include namespace OrthancStone { @@ -42,6 +44,7 @@ SdlWindow::GlobalInitialize(); } + void SdlStoneApplicationRunner::DeclareCommandLineOptions(boost::program_options::options_description& options) { boost::program_options::options_description sdl("SDL options"); @@ -54,6 +57,7 @@ options.add(sdl); } + void SdlStoneApplicationRunner::ParseCommandLineOptions(const boost::program_options::variables_map& parameters) { if (!parameters.count("width") || @@ -85,10 +89,13 @@ { LOG(WARNING) << "OpenGL is disabled, enable it with option \"--opengl=on\" for best performance"; } - } - void SdlStoneApplicationRunner::Run(NativeStoneApplicationContext& context, const std::string& title, int argc, char* argv[]) + + void SdlStoneApplicationRunner::Run(NativeStoneApplicationContext& context, + const std::string& title, + int argc, + char* argv[]) { /************************************************************** * Run the application inside a SDL window @@ -97,11 +104,16 @@ LOG(WARNING) << "Starting the application"; SdlWindow window(title.c_str(), width_, height_, enableOpenGl_); - SdlEngine sdl(window, context); + SdlEngine sdl(window, context, broker_); { NativeStoneApplicationContext::GlobalMutexLocker locker(context); - context.GetCentralViewport().Register(sdl); // (*) + + locker.GetCentralViewport().RegisterObserverCallback( + new Callable + (sdl, &SdlEngine::OnViewportChanged)); + + //context.GetCentralViewport().Register(sdl); // (*) } context.Start(); @@ -115,13 +127,14 @@ // update thread started by "context.Start()" would call a // destructed object (the "SdlEngine" is deleted with the // lexical scope). + + // TODO Is this still true with message broker? context.Stop(); } + void SdlStoneApplicationRunner::Finalize() { SdlWindow::GlobalFinalize(); } - - } diff -r d20d75f20c5d -r 6cc3ce74dc05 Applications/Sdl/SdlStoneApplicationRunner.h --- a/Applications/Sdl/SdlStoneApplicationRunner.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Applications/Sdl/SdlStoneApplicationRunner.h Wed Nov 07 20:49:41 2018 +0100 @@ -33,21 +33,29 @@ { class SdlStoneApplicationRunner : public NativeStoneApplicationRunner { - unsigned int width_; - unsigned int height_; - bool enableOpenGl_; + private: + unsigned int width_; + unsigned int height_; + bool enableOpenGl_; + public: SdlStoneApplicationRunner(MessageBroker& broker, - IStoneApplication& application) - : NativeStoneApplicationRunner(broker, application) + IStoneApplication& application) : + NativeStoneApplicationRunner(broker, application) { } virtual void Initialize(); + virtual void DeclareCommandLineOptions(boost::program_options::options_description& options); - virtual void Run(NativeStoneApplicationContext& context, const std::string& title, int argc, char* argv[]); + + virtual void Run(NativeStoneApplicationContext& context, + const std::string& title, + int argc, + char* argv[]); + virtual void ParseCommandLineOptions(const boost::program_options::variables_map& parameters); + virtual void Finalize(); }; - } diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Messages/MessageType.h --- a/Framework/Messages/MessageType.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Messages/MessageType.h Wed Nov 07 20:49:41 2018 +0100 @@ -51,6 +51,8 @@ MessageType_OrthancApi_GenericHttpError_Ready, MessageType_OrthancApi_GenericEmptyResponse_Ready, + MessageType_ViewportChanged, + // used in unit tests only MessageType_Test1, MessageType_Test2, diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Viewport/IViewport.h --- a/Framework/Viewport/IViewport.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Viewport/IViewport.h Wed Nov 07 20:49:41 2018 +0100 @@ -23,6 +23,7 @@ #include "IStatusBar.h" #include "../StoneEnumerations.h" +#include "../Messages/IObservable.h" #include @@ -30,27 +31,22 @@ { class IWidget; // Forward declaration - class IViewport : public boost::noncopyable + class IViewport : public IObservable { public: - class IObserver : public boost::noncopyable + typedef OriginMessage ViewportChangedMessage; + + IViewport(MessageBroker& broker) : + IObservable(broker) { - public: - virtual ~IObserver() - { - } - - virtual void OnViewportContentChanged(const IViewport& scene) = 0; - }; - + } + virtual ~IViewport() { } virtual void FitContent() = 0; - virtual void Register(IObserver& observer) = 0; - virtual void SetStatusBar(IStatusBar& statusBar) = 0; virtual void SetSize(unsigned int width, @@ -87,6 +83,10 @@ virtual void UpdateContent() = 0; // Should only be called from IWidget - virtual void NotifyContentChanged(const IWidget& widget) = 0; + virtual void NotifyContentChanged() + { + ViewportChangedMessage message(*this); + EmitMessage(message); + } }; } diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Viewport/WidgetViewport.cpp --- a/Framework/Viewport/WidgetViewport.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Viewport/WidgetViewport.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -26,7 +26,8 @@ namespace OrthancStone { - WidgetViewport::WidgetViewport() : + WidgetViewport::WidgetViewport(MessageBroker& broker) : + IViewport(broker), statusBar_(NULL), isMouseOver_(false), lastMouseX_(0), @@ -73,17 +74,16 @@ centralWidget_->SetStatusBar(*statusBar_); } - backgroundChanged_ = true; - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyBackgroundChanged(); return *widget; } - void WidgetViewport::NotifyContentChanged(const IWidget& widget) + void WidgetViewport::NotifyBackgroundChanged() { backgroundChanged_ = true; - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyContentChanged(); } @@ -97,7 +97,7 @@ centralWidget_->SetSize(width, height); } - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyBackgroundChanged(); } @@ -155,7 +155,7 @@ mouseTracker_.reset(NULL); } - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyContentChanged(); } @@ -165,7 +165,7 @@ { mouseTracker_->MouseUp(); mouseTracker_.reset(NULL); - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyContentChanged(); } } @@ -196,7 +196,7 @@ if (repaint) { // The scene must be repainted, notify the observers - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyContentChanged(); } } @@ -204,7 +204,7 @@ void WidgetViewport::MouseEnter() { isMouseOver_ = true; - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyContentChanged(); } @@ -218,7 +218,7 @@ mouseTracker_.reset(NULL); } - observers_.Apply(*this, &IObserver::OnViewportContentChanged); + NotifyContentChanged(); } diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Viewport/WidgetViewport.h --- a/Framework/Viewport/WidgetViewport.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Viewport/WidgetViewport.h Wed Nov 07 20:49:41 2018 +0100 @@ -22,7 +22,6 @@ #pragma once #include "IViewport.h" -#include "../Toolbox/ObserversRegistry.h" #include "../Widgets/IWidget.h" #include @@ -34,7 +33,6 @@ private: std::auto_ptr centralWidget_; IStatusBar* statusBar_; - ObserversRegistry observers_; std::auto_ptr mouseTracker_; bool isMouseOver_; int lastMouseX_; @@ -43,7 +41,7 @@ bool backgroundChanged_; public: - WidgetViewport(); + WidgetViewport(MessageBroker& broker); virtual void FitContent(); @@ -51,12 +49,7 @@ IWidget& SetCentralWidget(IWidget* widget); // Takes ownership - virtual void NotifyContentChanged(const IWidget& widget); - - virtual void Register(IObserver& observer) - { - observers_.Register(observer); - } + virtual void NotifyBackgroundChanged(); virtual void SetSize(unsigned int width, unsigned int height); diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Widgets/EmptyWidget.h --- a/Framework/Widgets/EmptyWidget.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Widgets/EmptyWidget.h Wed Nov 07 20:49:41 2018 +0100 @@ -26,9 +26,9 @@ namespace OrthancStone { /** - * This is a test widget that simply fills its surface with an - * uniform color. - **/ + * This is a test widget that simply fills its surface with an + * uniform color. + **/ class EmptyWidget : public IWidget { private: @@ -54,7 +54,7 @@ { } - virtual void SetViewport(IViewport& viewport) + virtual void SetViewport(WidgetViewport& viewport) { } diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Widgets/IWidget.h --- a/Framework/Widgets/IWidget.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Widgets/IWidget.h Wed Nov 07 20:49:41 2018 +0100 @@ -24,10 +24,11 @@ #include "../StoneEnumerations.h" #include "../Viewport/IMouseTracker.h" #include "../Viewport/IStatusBar.h" -#include "../Viewport/IViewport.h" namespace OrthancStone { + class WidgetViewport; // Forward declaration + class IWidget : public boost::noncopyable { public: @@ -39,7 +40,7 @@ virtual void SetParent(IWidget& parent) = 0; - virtual void SetViewport(IViewport& viewport) = 0; + virtual void SetViewport(WidgetViewport& viewport) = 0; virtual void SetStatusBar(IStatusBar& statusBar) = 0; diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Widgets/WidgetBase.cpp --- a/Framework/Widgets/WidgetBase.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Widgets/WidgetBase.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -36,7 +36,7 @@ if (viewport_ != NULL) { - viewport_->NotifyContentChanged(*this); + viewport_->NotifyBackgroundChanged(); } } @@ -115,7 +115,7 @@ } - void WidgetBase::SetViewport(IViewport& viewport) + void WidgetBase::SetViewport(WidgetViewport& viewport) { if (viewport_ != NULL) { diff -r d20d75f20c5d -r 6cc3ce74dc05 Framework/Widgets/WidgetBase.h --- a/Framework/Widgets/WidgetBase.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Framework/Widgets/WidgetBase.h Wed Nov 07 20:49:41 2018 +0100 @@ -24,19 +24,20 @@ #include "IWidget.h" #include "../Viewport/CairoContext.h" +#include "../Viewport/WidgetViewport.h" namespace OrthancStone { class WidgetBase : public IWidget { private: - IWidget* parent_; - IViewport* viewport_; - IStatusBar* statusBar_; - bool backgroundCleared_; - uint8_t backgroundColor_[3]; - bool transmitMouseOver_; - std::string name_; + IWidget* parent_; + WidgetViewport* viewport_; + IStatusBar* statusBar_; + bool backgroundCleared_; + uint8_t backgroundColor_[3]; + bool transmitMouseOver_; + std::string name_; protected: void ClearBackgroundOrthanc(Orthanc::ImageAccessor& target) const; @@ -61,7 +62,7 @@ virtual void SetParent(IWidget& parent); - virtual void SetViewport(IViewport& viewport); + virtual void SetViewport(WidgetViewport& viewport); void SetBackgroundCleared(bool clear) { diff -r d20d75f20c5d -r 6cc3ce74dc05 Platforms/Wasm/Defaults.cpp --- a/Platforms/Wasm/Defaults.cpp Wed Nov 07 16:17:02 2018 +0100 +++ b/Platforms/Wasm/Defaults.cpp Wed Nov 07 20:49:41 2018 +0100 @@ -20,7 +20,7 @@ static OrthancStone::StartupParametersBuilder startupParametersBuilder; static OrthancStone::MessageBroker broker; -static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_; +static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_(broker); static OrthancStone::StatusBar statusBar_; static std::list> viewports_; @@ -44,7 +44,7 @@ // when WASM needs a C++ viewport ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { - std::shared_ptr viewport(new OrthancStone::WidgetViewport); + std::shared_ptr viewport(new OrthancStone::WidgetViewport(broker)); printf("viewport %x\n", (int)viewport.get()); viewports_.push_back(viewport); @@ -52,7 +52,10 @@ printf("There are now %d viewports in C++\n", viewports_.size()); viewport->SetStatusBar(statusBar_); - viewport->Register(viewportContentChangedObserver_); + + viewport->RegisterObserverCallback( + new Callable + (viewportContentChangedObserver_, &ViewportContentChangedObserver::OnViewportChanged)); return viewport.get(); } diff -r d20d75f20c5d -r 6cc3ce74dc05 Platforms/Wasm/Defaults.h --- a/Platforms/Wasm/Defaults.h Wed Nov 07 16:17:02 2018 +0100 +++ b/Platforms/Wasm/Defaults.h Wed Nov 07 20:49:41 2018 +0100 @@ -35,15 +35,15 @@ namespace OrthancStone { // default Observer to trigger Viewport redraw when something changes in the Viewport - class ViewportContentChangedObserver : - public OrthancStone::IViewport::IObserver + class ViewportContentChangedObserver : public IObserver { private: // Flag to avoid flooding JavaScript with redundant Redraw requests bool isScheduled_; public: - ViewportContentChangedObserver() : + ViewportContentChangedObserver(MessageBroker& broker) : + IObserver(broker), isScheduled_(false) { } @@ -53,11 +53,11 @@ isScheduled_ = false; } - virtual void OnViewportContentChanged(const OrthancStone::IViewport &viewport) + void OnViewportChanged(const IViewport::ViewportChangedMessage& message) { if (!isScheduled_) { - ScheduleWebViewportRedrawFromCpp((ViewportHandle)&viewport); // loosing constness when transmitted to Web + ScheduleWebViewportRedrawFromCpp((ViewportHandle)&message.GetOrigin()); // loosing constness when transmitted to Web isScheduled_ = true; } } @@ -76,4 +76,4 @@ printf("%s\n", message.c_str()); } }; -} \ No newline at end of file +}