diff --git a/Modules/Annotation/include/mitkAnnotationFactory.h b/Modules/Annotation/include/mitkAnnotationFactory.h index 9559a9f217..5223685b96 100644 --- a/Modules/Annotation/include/mitkAnnotationFactory.h +++ b/Modules/Annotation/include/mitkAnnotationFactory.h @@ -1,60 +1,60 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKANNOTATIONFACTORY_H #define MITKANNOTATIONFACTORY_H // mitk #include "MitkAnnotationExports.h" #include "mitkAnnotation.h" -#include "mitkCommon.h" #include "mitkDynamicAnnotation.h" #include "mitkLayoutAnnotationRenderer.h" // boost #include <boost/property_tree/ptree_fwd.hpp> // stl #include <unordered_map> namespace mitk { class MITKANNOTATION_EXPORT AnnotationFactory : public itk::Object { public: + using AnnotationConfigVector = std::vector<std::unordered_map<std::string, std::string>>; using AnnotationPtrVector = std::vector<DynamicAnnotation::Pointer>; - static void CreateAnnotationsFromConfiguration(AnnotationPtrVector &annotations); + static AnnotationPtrVector CreateAnnotationsFromConfiguration(const AnnotationConfigVector &annotations); static void RegisterAnnotations(const AnnotationPtrVector &annotations); private: static LayoutAnnotationRenderer::Alignment GetAlignment(const std::string &alignmentName); const std::unordered_map<std::string, std::string> m_Defaults = { {AnnotationConstants::NAME, "Unnamed Annotation"}, {AnnotationConstants::DEFAULT, "NA"}, {AnnotationConstants::PREFIX, ""}, {AnnotationConstants::SUFFIX, ""}, {AnnotationConstants::TYPE, "text"}, {AnnotationConstants::PROVIDER, ""}, {AnnotationConstants::EVENT, ""}, {AnnotationConstants::ACTION, ""}, {AnnotationConstants::WINDOW, "stdmulti.widget1"}, {AnnotationConstants::LAYOUT, "TopLeft"}, }; }; } // namespace mitk #endif // MITKANNOTATIONFACTORY_H diff --git a/Modules/Annotation/src/mitkAnnotationFactory.cpp b/Modules/Annotation/src/mitkAnnotationFactory.cpp index 2ffb47c361..6c84bc60ff 100644 --- a/Modules/Annotation/src/mitkAnnotationFactory.cpp +++ b/Modules/Annotation/src/mitkAnnotationFactory.cpp @@ -1,177 +1,183 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkAnnotationFactory.h" #include "mitkColorBarAnnotation.h" #include "mitkLayoutAnnotationRenderer.h" #include "mitkLogoAnnotation.h" #include "mitkScaleLegendAnnotation.h" #include "mitkTemporoSpatialStringProperty.h" #include "mitkTextAnnotation2D.h" #include <thread> mitk::LayoutAnnotationRenderer::Alignment mitk::AnnotationFactory::GetAlignment(const std::string &alignmentName) { static const auto alignmentMap = std::unordered_map<std::string, LayoutAnnotationRenderer::Alignment>{ {"TopLeft", LayoutAnnotationRenderer::TopLeft}, {"Top", LayoutAnnotationRenderer::Top}, {"TopRight", LayoutAnnotationRenderer::TopRight}, {"Left", LayoutAnnotationRenderer::Left}, {"Right", LayoutAnnotationRenderer::Right}, {"BottomLeft", LayoutAnnotationRenderer::BottomLeft}, {"Bottom", LayoutAnnotationRenderer::Bottom}, {"BottomRight", LayoutAnnotationRenderer::BottomRight}}; const auto alignment = alignmentMap.find(alignmentName); const auto &defaultFallback = "TopLeft"; return alignment != std::end(alignmentMap) ? alignment->second : alignmentMap.at(defaultFallback); } auto PropertyChangeAction() { return [](const itk::Object *caller, // needed to listen to modified events on the property itself const itk::EventObject &event, std::unordered_map<std::string, boost::any> dependencyValues) { // stored as additional information on provider creation auto propName = boost::any_cast<std::string>(dependencyValues["PropName"]); // stored as part of provider dependency if (dependencyValues["DataNodeProvider"].type() == typeid(mitk::DataNode::Pointer)) { auto node = boost::any_cast<mitk::DataNode::Pointer>(dependencyValues["DataNodeProvider"]); auto prop = node->GetProperty(propName.c_str()); if (prop) { // in case the data node changed update it on "yourself" auto provider = boost::any_cast<mitk::DataProvider *>(dependencyValues["Self"]); provider->SetProviderObject(prop); return prop->GetValueAsString(); } } return std::string{}; }; } auto TemporoSpatialPropertyChangeAction() { return [](const itk::Object *caller, // needed to listen to modified events on the property itself const itk::EventObject &event, std::unordered_map<std::string, boost::any> dependencyValues) { // stored as additional information on provider creation auto propName = boost::any_cast<std::string>(dependencyValues["PropName"]); // stored as part of provider dependency if (dependencyValues["DataNodeProvider"].type() == typeid(mitk::DataNode::Pointer)) { auto node = boost::any_cast<mitk::DataNode::Pointer>(dependencyValues["DataNodeProvider"]); auto prop = dynamic_cast<mitk::TemporoSpatialStringProperty *>(node->GetProperty(propName.c_str())); if (prop) { // in case the data node changed update it on "yourself" auto provider = boost::any_cast<mitk::DataProvider *>(dependencyValues["Self"]); provider->SetProviderObject(prop); // get slice data from provider dependency auto slice = 0; if (dependencyValues.find("SliceNumberProviderAxial") != std::end(dependencyValues)) { if (dependencyValues["SliceNumberProviderAxial"].type() == typeid(unsigned int)) { slice = boost::any_cast<unsigned int>(dependencyValues["SliceNumberProviderAxial"]); } } return prop->GetValueBySlice(slice); } } return std::string{"No data node selected"}; }; } -void mitk::AnnotationFactory::CreateAnnotationsFromConfiguration(AnnotationPtrVector &annotations) +mitk::AnnotationFactory::AnnotationPtrVector mitk::AnnotationFactory::CreateAnnotationsFromConfiguration( + const AnnotationConfigVector &configurations) { - for (auto &annotation : annotations) + auto result = AnnotationPtrVector{}; + for (auto &config : configurations) { + auto annotation = DynamicAnnotation::New(config); + result.push_back(annotation); + const auto &type = annotation->ConfigEntry(AnnotationConstants::TYPE); if (type == "text") { annotation->SetManagedAnnotation(mitk::TextAnnotation2D::New().GetPointer()); } else if (type == "property") { annotation->SetManagedAnnotation(mitk::TextAnnotation2D::New().GetPointer()); auto propertyProvider = DataProvider::New("PropertyProvider", nullptr, itk::ModifiedEvent().MakeObject(), PropertyChangeAction(), {"DataNodeProvider"}, {{"PropName", annotation->ConfigEntry(AnnotationConstants::PROVIDER)}}); annotation->SetDataProvider(propertyProvider); } else if (type == "dicomProperty") { annotation->SetManagedAnnotation(mitk::TextAnnotation2D::New().GetPointer()); auto propertyProvider = DataProvider::New("PropertyProvider", nullptr, itk::ModifiedEvent().MakeObject(), TemporoSpatialPropertyChangeAction(), {"DataNodeProvider", "SliceNumberProviderAxial", "TimeStepProvider"}, {{"PropName", annotation->ConfigEntry(AnnotationConstants::PROVIDER)}}); annotation->SetDataProvider(propertyProvider); } else if (type == "colorBar") { annotation->SetManagedAnnotation(ColorBarAnnotation::New().GetPointer()); } else if (type == "scaleLegend") { annotation->SetManagedAnnotation(ScaleLegendAnnotation::New().GetPointer()); } else if (type == "logo") { auto logoAnnotation = LogoAnnotation::New(); auto path = annotation->ConfigEntry(AnnotationConstants::PATH); logoAnnotation->SetLogoImagePath(path); logoAnnotation->LoadLogoImageFromPath(); annotation->SetManagedAnnotation(logoAnnotation.GetPointer()); } else { throw std::logic_error("Unknown or missing annotation type"); } } + return result; } void mitk::AnnotationFactory::RegisterAnnotations(const AnnotationPtrVector &annotations) { for (const auto &annotation : annotations) { const auto alignment = GetAlignment(annotation->ConfigEntry(AnnotationConstants::LAYOUT)); const auto renderer = BaseRenderer::GetByName(annotation->ConfigEntry(AnnotationConstants::WINDOW)); if (renderer) { LayoutAnnotationRenderer::AddAnnotation(annotation->GetManagedAnnotation(), renderer, alignment); // TODO wait so each annotation gets a unique id see T25927 std::this_thread::sleep_for(std::chrono::seconds(2)); } } }