# HG changeset patch # User Sebastien Jodogne # Date 1541955011 -3600 # Node ID 3942123602bae12eb281a13875572b470ae6e1ab # Parent ba4ace20454e4cfae5a06ba51b4f325d452d5ae0 removing ObserversRegistry diff -r ba4ace20454e -r 3942123602ba Framework/StoneEnumerations.h --- a/Framework/StoneEnumerations.h Sun Nov 11 13:02:38 2018 +0100 +++ b/Framework/StoneEnumerations.h Sun Nov 11 17:50:11 2018 +0100 @@ -140,6 +140,12 @@ MessageType_VolumeLoader_GeometryError, MessageType_VolumeLoader_ContentChanged, // Content of several slices in the loader has changed + MessageType_SlicedVolume_GeometryReady, + MessageType_SlicedVolume_GeometryError, + MessageType_SlicedVolume_VolumeReady, + MessageType_SlicedVolume_ContentChanged, + MessageType_SlicedVolume_SliceContentChanged, + MessageType_HttpRequestSuccess, MessageType_HttpRequestError, diff -r ba4ace20454e -r 3942123602ba Framework/Toolbox/ObserversRegistry.h --- a/Framework/Toolbox/ObserversRegistry.h Sun Nov 11 13:02:38 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/** - * 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 . - **/ - - -#pragma once - -#include - -#include -#include - -namespace OrthancStone -{ - template < - typename Source, - typename Observer = typename Source::IObserver - > - class ObserversRegistry : public boost::noncopyable - { - private: - typedef std::set Observers; - - Observers observers_; - - public: - template - void Notify(const Source& source, - Functor& functor) - { - for (typename Observers::const_iterator observer = observers_.begin(); - observer != observers_.end(); ++observer) - { - functor(**observer, source); - } - } - - void Register(Observer& observer) - { - observers_.insert(&observer); - } - - void Unregister(Observer& observer) - { - observers_.erase(&observer); - } - - bool IsEmpty() - { - return observers_.empty(); - } - - void Apply(const Source& source, - void (Observer::*method) (const Source&)) - { - for (typename Observers::const_iterator it = observers_.begin(); - it != observers_.end(); ++it) - { - ((*it)->*method) (source); - } - } - - template - void Apply(const Source& source, - void (Observer::*method) (const Source&, const Argument0&), - const Argument0& argument0) - { - for (typename Observers::const_iterator it = observers_.begin(); - it != observers_.end(); ++it) - { - ((*it)->*method) (source, argument0); - } - } - - template - void Apply(const Source& source, - void (Observer::*method) (const Source&, const Argument0&, const Argument1&), - const Argument0& argument0, - const Argument1& argument1) - { - for (typename Observers::const_iterator it = observers_.begin(); - it != observers_.end(); ++it) - { - ((*it)->*method) (source, argument0, argument1); - } - } - }; -} diff -r ba4ace20454e -r 3942123602ba Framework/Volumes/ISlicedVolume.h --- a/Framework/Volumes/ISlicedVolume.h Sun Nov 11 13:02:38 2018 +0100 +++ b/Framework/Volumes/ISlicedVolume.h Sun Nov 11 17:50:11 2018 +0100 @@ -21,44 +21,53 @@ #pragma once +#include "../Messages/IObservable.h" #include "../Toolbox/Slice.h" namespace OrthancStone { - class ISlicedVolume : public boost::noncopyable + class ISlicedVolume : public IObservable { public: - class IObserver : public boost::noncopyable + typedef OriginMessage ContentChangedMessage; + typedef OriginMessage GeometryErrorMessage; + typedef OriginMessage GeometryReadyMessage; + typedef OriginMessage VolumeReadyMessage; + + class SliceContentChangedMessage : + public OriginMessage { + private: + size_t sliceIndex_; + const Slice& slice_; + public: - virtual ~IObserver() + SliceContentChangedMessage(ISlicedVolume& origin, + size_t sliceIndex, + const Slice& slice) : + OriginMessage(origin), + sliceIndex_(sliceIndex), + slice_(slice) { } - virtual void NotifyGeometryReady(const ISlicedVolume& volume) = 0; - - virtual void NotifyGeometryError(const ISlicedVolume& volume) = 0; - - // Triggered if the content of several slices in the volume has - // changed - virtual void NotifyContentChange(const ISlicedVolume& volume) = 0; + size_t GetSliceIndex() const + { + return sliceIndex_; + } - // Triggered if the content of some individual slice in the - // source volume has changed - virtual void NotifySliceContentChange(const ISlicedVolume& volume, - const size_t& sliceIndex, - const Slice& slice) = 0; + const Slice& GetSlice() const + { + return slice_; + } + }; - // Triggered when the geometry *and* the content of the volume are available - virtual void NotifyVolumeReady(const ISlicedVolume& volume) = 0; - }; - - virtual ~ISlicedVolume() + + ISlicedVolume(MessageBroker& broker) : + IObservable(broker) { } - - virtual void Register(IObserver& observer) = 0; - + virtual size_t GetSliceCount() const = 0; virtual const Slice& GetSlice(size_t slice) const = 0; diff -r ba4ace20454e -r 3942123602ba Framework/Volumes/SlicedVolumeBase.cpp --- a/Framework/Volumes/SlicedVolumeBase.cpp Sun Nov 11 13:02:38 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/** - * 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 . - **/ - - -#include "SlicedVolumeBase.h" - -namespace OrthancStone -{ - void SlicedVolumeBase::NotifyGeometryReady() - { - observers_.Apply(*this, &IObserver::NotifyGeometryReady); - } - - void SlicedVolumeBase::NotifyGeometryError() - { - observers_.Apply(*this, &IObserver::NotifyGeometryError); - } - - void SlicedVolumeBase::NotifyContentChange() - { - observers_.Apply(*this, &IObserver::NotifyContentChange); - } - - void SlicedVolumeBase::NotifySliceContentChange(const size_t& sliceIndex, - const Slice& slice) - { - observers_.Apply(*this, &IObserver::NotifySliceContentChange, sliceIndex, slice); - } - - void SlicedVolumeBase::NotifyVolumeReady() - { - observers_.Apply(*this, &IObserver::NotifyVolumeReady); - } -} diff -r ba4ace20454e -r 3942123602ba Framework/Volumes/SlicedVolumeBase.h --- a/Framework/Volumes/SlicedVolumeBase.h Sun Nov 11 13:02:38 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * 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 . - **/ - - -#pragma once - -#include "ISlicedVolume.h" -#include "../Toolbox/ObserversRegistry.h" - -namespace OrthancStone -{ - class SlicedVolumeBase : public ISlicedVolume - { - private: - typedef ObserversRegistry Observers; - - Observers observers_; - - protected: - virtual void NotifyGeometryReady(); - - virtual void NotifyGeometryError(); - - virtual void NotifyContentChange(); - - virtual void NotifySliceContentChange(const size_t& sliceIndex, - const Slice& slice); - - virtual void NotifyVolumeReady(); - - public: - virtual void Register(IObserver& observer) - { - observers_.Register(observer); - } - }; -} diff -r ba4ace20454e -r 3942123602ba Framework/dev.h --- a/Framework/dev.h Sun Nov 11 13:02:38 2018 +0100 +++ b/Framework/dev.h Sun Nov 11 17:50:11 2018 +0100 @@ -28,11 +28,12 @@ #include "Toolbox/GeometryToolbox.h" #include "Toolbox/OrthancSlicesLoader.h" #include "Volumes/ImageBuffer3D.h" -#include "Volumes/SlicedVolumeBase.h" +#include "Volumes/ISlicedVolume.h" #include "Widgets/SliceViewerWidget.h" #include #include +#include #include @@ -41,8 +42,8 @@ { // TODO: Handle errors while loading class OrthancVolumeImage : - public SlicedVolumeBase, - public OrthancStone::IObserver + public ISlicedVolume, + public IObserver { private: OrthancSlicesLoader loader_; @@ -110,7 +111,7 @@ if (loader.GetSliceCount() == 0) { LOG(ERROR) << "Empty volume image"; - SlicedVolumeBase::NotifyGeometryError(); + EmitMessage(ISlicedVolume::GeometryErrorMessage(*this)); return; } @@ -118,7 +119,7 @@ { if (!IsCompatible(loader.GetSlice(0), loader.GetSlice(i))) { - SlicedVolumeBase::NotifyGeometryError(); + EmitMessage(ISlicedVolume::GeometryErrorMessage(*this)); return; } } @@ -142,7 +143,7 @@ 0.001 /* this is expressed in mm */)) { LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; - SlicedVolumeBase::NotifyGeometryError(); + EmitMessage(ISlicedVolume::GeometryErrorMessage(*this)); return; } } @@ -169,25 +170,25 @@ // TODO Check the DicomFrameConverter are constant - SlicedVolumeBase::NotifyGeometryReady(); + EmitMessage(ISlicedVolume::GeometryReadyMessage(*this)); } - virtual void OnSliceImageReady(const OrthancSlicesLoader& loader, - unsigned int sliceIndex, - const Slice& slice, - const Orthanc::ImageAccessor& image, - SliceImageQuality quality) + void OnSliceImageReady(const OrthancSlicesLoader& loader, + unsigned int sliceIndex, + const Slice& slice, + const Orthanc::ImageAccessor& image, + SliceImageQuality quality) { { ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, sliceIndex); Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image); } - SlicedVolumeBase::NotifySliceContentChange(sliceIndex, slice); + EmitMessage(ISlicedVolume::SliceContentChangedMessage(*this, sliceIndex, slice)); if (pendingSlices_ == 1) { - SlicedVolumeBase::NotifyVolumeReady(); + EmitMessage(ISlicedVolume::VolumeReadyMessage(*this)); pendingSlices_ = 0; } else if (pendingSlices_ > 1) @@ -208,7 +209,7 @@ case MessageType_SliceLoader_GeometryError: LOG(ERROR) << "Unable to download a volume image"; - SlicedVolumeBase::NotifyGeometryError(); + EmitMessage(ISlicedVolume::GeometryErrorMessage(*this)); break; case MessageType_SliceLoader_ImageReady: @@ -241,7 +242,8 @@ OrthancVolumeImage(MessageBroker& broker, OrthancApiClient& orthanc, bool computeRange) : - OrthancStone::IObserver(broker), + ISlicedVolume(broker), + IObserver(broker), loader_(broker, orthanc), computeRange_(computeRange), pendingSlices_(0) @@ -495,7 +497,7 @@ class VolumeImageMPRSlicer : public IVolumeSlicer, - private ISlicedVolume::IObserver + public IObserver { private: class RendererFactory : public LayerReadyMessage::IRendererFactory @@ -532,10 +534,11 @@ { return axialGeometry_.get() != NULL; } - - virtual void NotifyGeometryReady(const ISlicedVolume& volume) ORTHANC_OVERRIDE + void OnGeometryReady(const ISlicedVolume::GeometryReadyMessage& message) { + assert(&message.GetOrigin() == &volume_); + // These 3 values are only used to speed up the IVolumeSlicer axialGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Axial)); coronalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Coronal)); @@ -544,30 +547,30 @@ EmitMessage(IVolumeSlicer::GeometryReadyMessage(*this)); } - virtual void NotifyGeometryError(const ISlicedVolume& volume) ORTHANC_OVERRIDE + void OnGeometryError(const ISlicedVolume::GeometryErrorMessage& message) { + assert(&message.GetOrigin() == &volume_); + EmitMessage(IVolumeSlicer::GeometryErrorMessage(*this)); } - virtual void NotifyContentChange(const ISlicedVolume& volume) ORTHANC_OVERRIDE + void OnContentChanged(const ISlicedVolume::ContentChangedMessage& message) { + assert(&message.GetOrigin() == &volume_); + EmitMessage(IVolumeSlicer::ContentChangedMessage(*this)); } - virtual void NotifySliceContentChange(const ISlicedVolume& volume, - const size_t& sliceIndex, - const Slice& slice) ORTHANC_OVERRIDE + void OnSliceContentChanged(const ISlicedVolume::SliceContentChangedMessage& message) { - //IVolumeSlicer::NotifySliceContentChange(slice); + assert(&message.GetOrigin() == &volume_); + + //IVolumeSlicer::OnSliceContentChange(slice); // TODO Improve this? EmitMessage(IVolumeSlicer::ContentChangedMessage(*this)); } - virtual void NotifyVolumeReady(const ISlicedVolume& volume) ORTHANC_OVERRIDE - { - } - const VolumeImageGeometry& GetProjectionGeometry(VolumeProjection projection) { if (!IsGeometryReady()) @@ -629,13 +632,24 @@ VolumeImageMPRSlicer(MessageBroker& broker, OrthancVolumeImage& volume) : IVolumeSlicer(broker), + IObserver(broker), volume_(volume) { - volume_.Register(*this); - } + volume_.RegisterObserverCallback( + new Callable + (*this, &VolumeImageMPRSlicer::OnGeometryReady)); + + volume_.RegisterObserverCallback( + new Callable + (*this, &VolumeImageMPRSlicer::OnGeometryError)); - virtual ~VolumeImageMPRSlicer() - { + volume_.RegisterObserverCallback( + new Callable + (*this, &VolumeImageMPRSlicer::OnContentChanged)); + + volume_.RegisterObserverCallback( + new Callable + (*this, &VolumeImageMPRSlicer::OnSliceContentChanged)); } virtual bool GetExtent(std::vector& points, @@ -702,20 +716,21 @@ class VolumeImageInteractor : public IWorldSceneInteractor, - protected ISlicedVolume::IObserver + public IObserver { private: - SliceViewerWidget& widget_; + SliceViewerWidget& widget_; VolumeProjection projection_; std::auto_ptr slices_; size_t slice_; protected: - virtual void NotifyGeometryReady(const ISlicedVolume& volume) + void OnGeometryReady(const ISlicedVolume::GeometryReadyMessage& message) { if (slices_.get() == NULL) { - const OrthancVolumeImage& image = dynamic_cast(volume); + const OrthancVolumeImage& image = + dynamic_cast(message.GetOrigin()); slices_.reset(new VolumeImageGeometry(image, projection_)); SetSlice(slices_->GetSliceCount() / 2); @@ -724,24 +739,6 @@ } } - virtual void NotifyGeometryError(const ISlicedVolume& volume) - { - } - - virtual void NotifyContentChange(const ISlicedVolume& volume) - { - } - - virtual void NotifySliceContentChange(const ISlicedVolume& volume, - const size_t& sliceIndex, - const Slice& slice) - { - } - - virtual void NotifyVolumeReady(const ISlicedVolume& volume) - { - } - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, const ViewportGeometry& view, MouseButton button, @@ -801,14 +798,19 @@ } public: - VolumeImageInteractor(OrthancVolumeImage& volume, + VolumeImageInteractor(MessageBroker& broker, + OrthancVolumeImage& volume, SliceViewerWidget& widget, VolumeProjection projection) : + IObserver(broker), widget_(widget), projection_(projection) { - volume.Register(*this); widget.SetInteractor(*this); + + volume.RegisterObserverCallback( + new Callable + (*this, &VolumeImageInteractor::OnGeometryReady)); } bool IsGeometryReady() const diff -r ba4ace20454e -r 3942123602ba Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Sun Nov 11 13:02:38 2018 +0100 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Sun Nov 11 17:50:11 2018 +0100 @@ -276,7 +276,6 @@ ${ORTHANC_STONE_ROOT}/Framework/Viewport/IViewport.h ${ORTHANC_STONE_ROOT}/Framework/Viewport/WidgetViewport.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/ImageBuffer3D.cpp - ${ORTHANC_STONE_ROOT}/Framework/Volumes/SlicedVolumeBase.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/StructureSetLoader.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/VolumeReslicer.cpp ${ORTHANC_STONE_ROOT}/Framework/Widgets/CairoWidget.cpp diff -r ba4ace20454e -r 3942123602ba UnitTestsSources/UnitTestsMain.cpp --- a/UnitTestsSources/UnitTestsMain.cpp Sun Nov 11 13:02:38 2018 +0100 +++ b/UnitTestsSources/UnitTestsMain.cpp Sun Nov 11 17:50:11 2018 +0100 @@ -28,7 +28,6 @@ #include "../Framework/Toolbox/MessagingToolbox.h" #include "../Framework/Toolbox/OrthancSlicesLoader.h" #include "../Framework/Volumes/ImageBuffer3D.h" -#include "../Framework/Volumes/SlicedVolumeBase.h" #include "../Platforms/Generic/OracleWebService.h" #include