# HG changeset patch # User Sebastien Jodogne # Date 1496048658 -7200 # Node ID 64e60018943fb39abe4089c7c514bcd9e7ac6a86 # Parent f244018a4e4b16b25b76f0de1459b27bb04b5f1f fix and observer refactoring diff -r f244018a4e4b -r 64e60018943f Applications/Samples/SingleFrameApplication.h --- a/Applications/Samples/SingleFrameApplication.h Fri May 26 18:27:59 2017 +0200 +++ b/Applications/Samples/SingleFrameApplication.h Mon May 29 11:04:18 2017 +0200 @@ -94,6 +94,14 @@ virtual void NotifyGeometryReady(const ILayerSource& source) { + const OrthancFrameLayerSource& frame = + dynamic_cast(source); + + if (frame.GetSliceCount() > 0) + { + widget_->SetSlice(frame.GetSlice(0).GetGeometry()); + widget_->SetDefaultView(); + } } virtual void NotifyGeometryError(const ILayerSource& source) @@ -109,7 +117,7 @@ { } - virtual void NotifyLayerReady(ILayerRenderer *layer, + virtual void NotifyLayerReady(std::auto_ptr& layer, const ILayerSource& source, const Slice& slice) { @@ -162,9 +170,10 @@ std::auto_ptr widget(new LayerWidget); -#if 1 +#if 0 std::auto_ptr layer (new OrthancFrameLayerSource(context.GetWebService(), instance, frame)); + layer->Register(*this); widget->AddLayer(layer.release()); if (parameters["smooth"].as()) @@ -178,6 +187,7 @@ std::auto_ptr ct; ct.reset(new OrthancFrameLayerSource(context.GetWebService(), "c804a1a2-142545c9-33b32fe2-3df4cec0-a2bea6d6", 0)); //ct.reset(new OrthancFrameLayerSource(context.GetWebService(), "4bd4304f-47478948-71b24af2-51f4f1bc-275b6c1b", 0)); // BAD SLICE + ct->Register(*this); widget->AddLayer(ct.release()); std::auto_ptr pet; diff -r f244018a4e4b -r 64e60018943f Framework/Layers/ILayerSource.h --- a/Framework/Layers/ILayerSource.h Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Layers/ILayerSource.h Mon May 29 11:04:18 2017 +0200 @@ -36,6 +36,12 @@ { } + // Triggered as soon as the source has enough information to + // answer to "GetExtent()" + virtual void NotifyGeometryReady(const ILayerSource& source) = 0; + + virtual void NotifyGeometryError(const ILayerSource& source) = 0; + // Triggered if the content of several slices in the source // volume has changed virtual void NotifyContentChange(const ILayerSource& source) = 0; @@ -48,7 +54,7 @@ // The layer must be deleted by the observer. "layer" will never // be "NULL", otherwise "NotifyLayerError()" would have been // called. - virtual void NotifyLayerReady(ILayerRenderer *layer, + virtual void NotifyLayerReady(std::auto_ptr& layer, const ILayerSource& source, const Slice& slice) = 0; @@ -60,7 +66,7 @@ { } - virtual void SetObserver(IObserver& observer) = 0; + virtual void Register(IObserver& observer) = 0; virtual bool GetExtent(double& x1, double& y1, diff -r f244018a4e4b -r 64e60018943f Framework/Layers/LayerSourceBase.cpp --- a/Framework/Layers/LayerSourceBase.cpp Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Layers/LayerSourceBase.cpp Mon May 29 11:04:18 2017 +0200 @@ -25,56 +25,69 @@ namespace OrthancStone { + namespace + { + class LayerReadyFunctor : public boost::noncopyable + { + private: + std::auto_ptr layer_; + const Slice& slice_; + + public: + LayerReadyFunctor(ILayerRenderer* layer, + const Slice& slice) : + layer_(layer), + slice_(slice) + { + } + + void operator() (ILayerSource::IObserver& observer, + const ILayerSource& source) + { + observer.NotifyLayerReady(layer_, source, slice_); + } + }; + } + + void LayerSourceBase::NotifyGeometryReady() + { + observers_.Apply(*this, &IObserver::NotifyGeometryReady); + } + + void LayerSourceBase::NotifyGeometryError() + { + observers_.Apply(*this, &IObserver::NotifyGeometryError); + } + void LayerSourceBase::NotifyContentChange() { - if (observer_ != NULL) - { - observer_->NotifyContentChange(*this); - } + observers_.Apply(*this, &IObserver::NotifyContentChange); } void LayerSourceBase::NotifySliceChange(const Slice& slice) { - if (observer_ != NULL) - { - observer_->NotifySliceChange(*this, slice); - } + observers_.Apply(*this, &IObserver::NotifySliceChange, slice); } void LayerSourceBase::NotifyLayerReady(ILayerRenderer* layer, const Slice& slice) { - std::auto_ptr tmp(layer); - if (layer == NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } - - if (observer_ != NULL) - { - observer_->NotifyLayerReady(tmp.release(), *this, slice); - } + + LayerReadyFunctor functor(layer, slice); + observers_.Notify(this, functor); } void LayerSourceBase::NotifyLayerError(const SliceGeometry& slice) { - if (observer_ != NULL) - { - observer_->NotifyLayerError(*this, slice); - } + observers_.Apply(*this, &IObserver::NotifyLayerError, slice); } - void LayerSourceBase::SetObserver(IObserver& observer) + void LayerSourceBase::Register(IObserver& observer) { - if (observer_ == NULL) - { - observer_ = &observer; - } - else - { - // Cannot add more than one observer - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } + observers_.Register(observer); } } diff -r f244018a4e4b -r 64e60018943f Framework/Layers/LayerSourceBase.h --- a/Framework/Layers/LayerSourceBase.h Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Layers/LayerSourceBase.h Mon May 29 11:04:18 2017 +0200 @@ -22,36 +22,32 @@ #pragma once #include "ILayerSource.h" +#include "../Toolbox/ObserversRegistry.h" namespace OrthancStone { class LayerSourceBase : public ILayerSource { private: - IObserver* observer_; + typedef ObserversRegistry Observers; + + Observers observers_; protected: - IObserver* GetObserver() const - { - return observer_; // TODO REMOVE THIS, FOR TEST - } + void NotifyGeometryReady(); + + void NotifyGeometryError(); void NotifyContentChange(); void NotifySliceChange(const Slice& slice); - // Takes ownership of "layer" (that cannot be "NULL") void NotifyLayerReady(ILayerRenderer* layer, const Slice& slice); void NotifyLayerError(const SliceGeometry& slice); public: - LayerSourceBase() : - observer_(NULL) - { - } - - virtual void SetObserver(IObserver& observer); + virtual void Register(IObserver& observer); }; } diff -r f244018a4e4b -r 64e60018943f Framework/Layers/OrthancFrameLayerSource.cpp --- a/Framework/Layers/OrthancFrameLayerSource.cpp Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Layers/OrthancFrameLayerSource.cpp Mon May 29 11:04:18 2017 +0200 @@ -37,7 +37,6 @@ { void OrthancFrameLayerSource::NotifyGeometryReady(const OrthancSlicesLoader& loader) { -#if 0 if (loader.GetSliceCount() > 0) { // Make sure all the slices are parallel. TODO Alleviate this constraint @@ -53,20 +52,11 @@ } LayerSourceBase::NotifyGeometryReady(); -#endif - - // TODO REMOVE THIS - /*if (GetObserver() != NULL) - { - dynamic_cast(GetObserver())->SetSlice(loader.GetSlice(0).GetGeometry()); - }*/ } void OrthancFrameLayerSource::NotifyGeometryError(const OrthancSlicesLoader& loader) { -#if 0 LayerSourceBase::NotifyGeometryError(); -#endif } void OrthancFrameLayerSource::NotifySliceImageReady(const OrthancSlicesLoader& loader, diff -r f244018a4e4b -r 64e60018943f Framework/Toolbox/ObserversRegistry.h --- a/Framework/Toolbox/ObserversRegistry.h Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Toolbox/ObserversRegistry.h Mon May 29 11:04:18 2017 +0200 @@ -92,5 +92,41 @@ { 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 f244018a4e4b -r 64e60018943f Framework/Volumes/ISlicedVolume.h --- a/Framework/Volumes/ISlicedVolume.h Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Volumes/ISlicedVolume.h Mon May 29 11:04:18 2017 +0200 @@ -46,7 +46,7 @@ // Triggered if the content of some individual slice in the // source volume has changed virtual void NotifySliceChange(const ISlicedVolume& volume, - size_t sliceIndex, + const size_t& sliceIndex, const Slice& slice) = 0; }; diff -r f244018a4e4b -r 64e60018943f Framework/Volumes/SlicedVolumeBase.cpp --- a/Framework/Volumes/SlicedVolumeBase.cpp Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Volumes/SlicedVolumeBase.cpp Mon May 29 11:04:18 2017 +0200 @@ -23,77 +23,24 @@ namespace OrthancStone { - namespace - { - struct GeometryReadyFunctor - { - void operator() (ISlicedVolume::IObserver& observer, - const ISlicedVolume& source) - { - observer.NotifyGeometryReady(source); - } - }; - - struct GeometryErrorFunctor - { - void operator() (ISlicedVolume::IObserver& observer, - const ISlicedVolume& source) - { - observer.NotifyGeometryError(source); - } - }; - - struct ContentChangeFunctor - { - void operator() (ISlicedVolume::IObserver& observer, - const ISlicedVolume& source) - { - observer.NotifyContentChange(source); - } - }; - - struct SliceChangeFunctor - { - size_t sliceIndex_; - const Slice& slice_; - - SliceChangeFunctor(size_t sliceIndex, - const Slice& slice) : - sliceIndex_(sliceIndex), - slice_(slice) - { - } - - void operator() (ISlicedVolume::IObserver& observer, - const ISlicedVolume& source) - { - observer.NotifySliceChange(source, sliceIndex_, slice_); - } - }; - } - void SlicedVolumeBase::NotifyGeometryReady() { - GeometryReadyFunctor functor; - observers_.Notify(this, functor); + observers_.Apply(*this, &IObserver::NotifyGeometryReady); } void SlicedVolumeBase::NotifyGeometryError() { - GeometryErrorFunctor functor; - observers_.Notify(this, functor); + observers_.Apply(*this, &IObserver::NotifyGeometryError); } void SlicedVolumeBase::NotifyContentChange() { - ContentChangeFunctor functor; - observers_.Notify(this, functor); + observers_.Apply(*this, &IObserver::NotifyContentChange); } - void SlicedVolumeBase::NotifySliceChange(size_t sliceIndex, + void SlicedVolumeBase::NotifySliceChange(const size_t& sliceIndex, const Slice& slice) { - SliceChangeFunctor functor(sliceIndex, slice); - observers_.Notify(this, functor); + observers_.Apply(*this, &IObserver::NotifySliceChange, sliceIndex, slice); } } diff -r f244018a4e4b -r 64e60018943f Framework/Volumes/SlicedVolumeBase.h --- a/Framework/Volumes/SlicedVolumeBase.h Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Volumes/SlicedVolumeBase.h Mon May 29 11:04:18 2017 +0200 @@ -29,7 +29,7 @@ class SlicedVolumeBase : public ISlicedVolume { private: - typedef ObserversRegistry Observers; + typedef ObserversRegistry Observers; Observers observers_; @@ -40,7 +40,7 @@ virtual void NotifyContentChange(); - virtual void NotifySliceChange(size_t sliceIndex, + virtual void NotifySliceChange(const size_t& sliceIndex, const Slice& slice); public: diff -r f244018a4e4b -r 64e60018943f Framework/Widgets/LayerWidget.cpp --- a/Framework/Widgets/LayerWidget.cpp Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Widgets/LayerWidget.cpp Mon May 29 11:04:18 2017 +0200 @@ -106,11 +106,6 @@ for (size_t i = 0; i < renderers_.size(); i++) { - if (renderers_[i] != NULL) - { - LOG(ERROR) << "..............."; - } - if (renderers_[i] != NULL && !renderers_[i]->RenderLayer(context, view, slice_)) { @@ -351,8 +346,7 @@ layersIndex_[layer] = index; ResetPendingScene(); - LOG(ERROR) << "*****************************"; - layer->SetObserver(*this); + layer->Register(*this); return index; } @@ -385,18 +379,42 @@ void LayerWidget::SetSlice(const SliceGeometry& slice) { - if (currentScene_.get() == NULL || - (pendingScene_.get() != NULL && - pendingScene_->IsComplete())) + Slice displayedSlice(slice_, THIN_SLICE_THICKNESS); + + if (!displayedSlice.ContainsPlane(slice)) { - currentScene_ = pendingScene_; - } + if (currentScene_.get() == NULL || + (pendingScene_.get() != NULL && + pendingScene_->IsComplete())) + { + currentScene_ = pendingScene_; + } - slice_ = slice; - ResetPendingScene(); + slice_ = slice; + ResetPendingScene(); + + InvalidateAllLayers(); + } } + void LayerWidget::NotifyGeometryReady(const ILayerSource& source) + { + size_t i; + if (LookupLayer(i, source)) + { + LOG(INFO) << "Geometry ready for layer " << i; + layers_[i]->ScheduleLayerCreation(slice_); + } + } + + + void LayerWidget::NotifyGeometryError(const ILayerSource& source) + { + LOG(ERROR) << "Cannot get geometry"; + } + + void LayerWidget::InvalidateAllLayers() { for (size_t i = 0; i < layers_.size(); i++) @@ -443,18 +461,16 @@ } - void LayerWidget::NotifyLayerReady(ILayerRenderer* renderer, + void LayerWidget::NotifyLayerReady(std::auto_ptr& renderer, const ILayerSource& source, const Slice& slice) { - std::auto_ptr tmp(renderer); - size_t index; if (LookupLayer(index, source) && slice.ContainsPlane(slice_)) // Whether the slice comes from an older request { LOG(INFO) << "Renderer ready for layer " << index; - UpdateLayer(index, tmp.release(), slice); + UpdateLayer(index, renderer.release(), slice); } } diff -r f244018a4e4b -r 64e60018943f Framework/Widgets/LayerWidget.h --- a/Framework/Widgets/LayerWidget.h Fri May 26 18:27:59 2017 +0200 +++ b/Framework/Widgets/LayerWidget.h Mon May 29 11:04:18 2017 +0200 @@ -55,12 +55,16 @@ double& y2, ILayerSource& source) const; + virtual void NotifyGeometryReady(const ILayerSource& source); + + virtual void NotifyGeometryError(const ILayerSource& source); + virtual void NotifyContentChange(const ILayerSource& source); virtual void NotifySliceChange(const ILayerSource& source, const Slice& slice); - virtual void NotifyLayerReady(ILayerRenderer* renderer, + virtual void NotifyLayerReady(std::auto_ptr& renderer, const ILayerSource& source, const Slice& slice);