diff --git a/Modules/Core/src/DataManagement/mitkLevelWindowManager.cpp b/Modules/Core/src/DataManagement/mitkLevelWindowManager.cpp index a5a7b5a874..d67daa36e3 100644 --- a/Modules/Core/src/DataManagement/mitkLevelWindowManager.cpp +++ b/Modules/Core/src/DataManagement/mitkLevelWindowManager.cpp @@ -1,725 +1,723 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkLevelWindowManager.h" #include "mitkImage.h" #include "mitkMessage.h" #include "mitkNodePredicateAnd.h" #include "mitkNodePredicateBase.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateOr.h" #include "mitkNodePredicateProperty.h" #include "mitkProperties.h" #include "mitkRenderingModeProperty.h" #include mitk::LevelWindowManager::LevelWindowManager() : m_DataStorage(nullptr) , m_LevelWindowProperty(nullptr) , m_AutoTopMost(true) , m_SelectedImagesMode(false) , m_CurrentImage(nullptr) , m_IsPropertyModifiedTagSet(false) , m_LevelWindowMutex(false) { } mitk::LevelWindowManager::~LevelWindowManager() { if (m_DataStorage.IsNotNull()) { m_DataStorage->AddNodeEvent.RemoveListener( MessageDelegate1(this, &LevelWindowManager::DataStorageAddedNode)); m_DataStorage->RemoveNodeEvent.RemoveListener( MessageDelegate1(this, &LevelWindowManager::DataStorageRemovedNode)); m_DataStorage = nullptr; } if (m_IsPropertyModifiedTagSet && m_LevelWindowProperty.IsNotNull()) { m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag); m_IsPropertyModifiedTagSet = false; } this->ClearPropertyObserverMaps(); } void mitk::LevelWindowManager::SetDataStorage(DataStorage *dataStorage) { if (nullptr == dataStorage) return; // remove listeners of old DataStorage if (m_DataStorage.IsNotNull()) { m_DataStorage->AddNodeEvent.RemoveListener( MessageDelegate1(this, &LevelWindowManager::DataStorageAddedNode)); m_DataStorage->RemoveNodeEvent.RemoveListener( MessageDelegate1(this, &LevelWindowManager::DataStorageRemovedNode)); } // register listener for new DataStorage m_DataStorage = dataStorage; m_DataStorage->AddNodeEvent.AddListener( MessageDelegate1(this, &LevelWindowManager::DataStorageAddedNode)); m_DataStorage->RemoveNodeEvent.AddListener( MessageDelegate1(this, &LevelWindowManager::DataStorageRemovedNode)); this->DataStorageAddedNode(); } mitk::DataStorage *mitk::LevelWindowManager::GetDataStorage() { return m_DataStorage.GetPointer(); } void mitk::LevelWindowManager::SetAutoTopMostImage(bool autoTopMost, const DataNode *removedNode/* = nullptr*/) { m_AutoTopMost = autoTopMost; if (false == m_AutoTopMost) { return; } // deactivate other mode m_SelectedImagesMode = false; if (m_IsPropertyModifiedTagSet && m_LevelWindowProperty.IsNotNull()) { m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag); m_IsPropertyModifiedTagSet = false; } // find topmost image in the data storage if (m_DataStorage.IsNull()) { mitkThrow() << "DataStorage not set"; } DataNode::Pointer topLevelNode; int maxVisibleLayer = itk::NumericTraits::min(); m_LevelWindowProperty = nullptr; m_CurrentImage = nullptr; DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes(); for (DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull() || node == removedNode) { continue; } // reset the "imageForLevelWindow" of each node m_LevelWindowMutex = true; node->SetBoolProperty("imageForLevelWindow", false); m_LevelWindowMutex = false; if (false == node->IsVisible(nullptr)) { continue; } bool validRenderingMode = HasLevelWindowRenderingMode(node); if (false == validRenderingMode) { continue; } int layer = -1; node->GetIntProperty("layer", layer); if (layer <= maxVisibleLayer) { continue; } m_LevelWindowProperty = dynamic_cast(node->GetProperty("levelwindow")); topLevelNode = node; maxVisibleLayer = layer; } // this will set the "imageForLevelWindow" property and the 'm_CurrentImage' and call 'Modified()' this->SetLevelWindowProperty(m_LevelWindowProperty); if (m_LevelWindowProperty.IsNull()) { this->Modified(); } } void mitk::LevelWindowManager::SetSelectedImages(bool selectedImagesMode, const DataNode *removedNode/* = nullptr*/) { m_SelectedImagesMode = selectedImagesMode; if (false == m_SelectedImagesMode) { return; } // deactivate other mode m_AutoTopMost = false; if (m_IsPropertyModifiedTagSet && m_LevelWindowProperty.IsNotNull()) { m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag); m_IsPropertyModifiedTagSet = false; } // find selected images in the data storage if (m_DataStorage.IsNull()) { mitkThrow() << "DataStorage not set"; } - DataNode::Pointer lastSelectedNode; m_LevelWindowProperty = nullptr; m_CurrentImage = nullptr; DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes(); for (DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull() || node == removedNode) { continue; } // reset the "imageForLevelWindow" of each node m_LevelWindowMutex = true; node->SetBoolProperty("imageForLevelWindow", false); m_LevelWindowMutex = false; if (false == node->IsSelected()) { continue; } bool validRenderingMode = HasLevelWindowRenderingMode(node); if (false == validRenderingMode) { continue; } m_LevelWindowProperty = dynamic_cast(node->GetProperty("levelwindow")); m_DataNodesForLevelWindow.push_back(node); // nodes are used inside "SetLevelWindow" if the level window is changed - lastSelectedNode = node; } // this will set the "imageForLevelWindow" property and the 'm_CurrentImage' and call 'Modified()' this->SetLevelWindowProperty(m_LevelWindowProperty); if (m_LevelWindowProperty.IsNull()) { this->Modified(); } } void mitk::LevelWindowManager::RecalculateLevelWindowForSelectedComponent(const itk::EventObject &event) { DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes(); for (DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull()) continue; bool isSelected = false; node->GetBoolProperty("selected", isSelected); if (isSelected) { LevelWindow selectedLevelWindow; node->GetLevelWindow(selectedLevelWindow); // node is an image node because of predicates auto *image = dynamic_cast(node->GetData()); int displayedComponent = 0; if (image && (node->GetIntProperty("Image.Displayed Component", displayedComponent))) { // we found a selected image with a displayed component // let's recalculate the levelwindow for this. selectedLevelWindow.SetAuto(image, true, true, static_cast(displayedComponent)); node->SetLevelWindow(selectedLevelWindow); } } LevelWindow levelWindow; node->GetLevelWindow(levelWindow); } this->Update(event); } void mitk::LevelWindowManager::Update(const itk::EventObject &) { if (m_LevelWindowMutex) // no mutex, should still help { return; } m_DataNodesForLevelWindow.clear(); if (m_AutoTopMost) { this->SetAutoTopMostImage(true); return; } if (m_SelectedImagesMode) { this->SetSelectedImages(true); return; } int maxVisibleLayer = itk::NumericTraits::min(); DataNode::Pointer topLevelNode = nullptr; std::vector nodesForLevelWindow; DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes(); for (DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull()) { continue; } if (false == node->IsVisible(nullptr)) { continue; } bool validRenderingMode = HasLevelWindowRenderingMode(node); if (false == validRenderingMode) { continue; } bool prop = false; node->GetBoolProperty("imageForLevelWindow", prop); if (prop) { nodesForLevelWindow.push_back(node); continue; } int layer = -1; node->GetIntProperty("layer", layer); if (layer <= maxVisibleLayer) { continue; } // top level node is backup node, if no node with // "imageForLevelWindow" property with value "true" is found topLevelNode = node; maxVisibleLayer = layer; } int nodesForLevelWindowSize = nodesForLevelWindow.size(); if (nodesForLevelWindowSize > 2) { MITK_ERROR << "Error: not more than two visible nodes are expected to have the imageForLevelWindow property set at " "any point."; } if (nodesForLevelWindowSize > 0) { // 1 or 2 nodes for level window found for (const auto& node : nodesForLevelWindow) { LevelWindowProperty::Pointer newProp = dynamic_cast(node->GetProperty("levelwindow")); if (newProp != m_LevelWindowProperty) { this->SetLevelWindowProperty(newProp); return; } } } else if (topLevelNode) { // no nodes for level window found LevelWindowProperty::Pointer lvlProp = dynamic_cast(topLevelNode->GetProperty("levelwindow")); this->SetLevelWindowProperty(lvlProp); } else { // no nodes for level window found and no visible top level node found this->Modified(); } } void mitk::LevelWindowManager::UpdateSelected(const itk::EventObject &) { if (m_LevelWindowMutex) // no mutex, should still help { return; } m_DataNodesForLevelWindow.clear(); if (m_SelectedImagesMode) { this->SetSelectedImages(true); } } void mitk::LevelWindowManager::SetLevelWindowProperty(LevelWindowProperty::Pointer levelWindowProperty) { if (levelWindowProperty.IsNull()) { return; } // find data node that belongs to the property DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetAll(); DataNode::Pointer propNode = nullptr; for (DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode::Pointer node = it.Value(); LevelWindowProperty::Pointer property = dynamic_cast(node->GetProperty("levelwindow")); if (property == levelWindowProperty) { propNode = node; } else { m_LevelWindowMutex = true; node->SetBoolProperty("imageForLevelWindow", false); m_LevelWindowMutex = false; } } if (propNode.IsNull()) { mitkThrow() << "No Image in the data storage that belongs to level-window property " << m_LevelWindowProperty; } if (m_IsPropertyModifiedTagSet) // remove listener for old property { m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag); m_IsPropertyModifiedTagSet = false; } m_LevelWindowProperty = levelWindowProperty; auto command = itk::ReceptorMemberCommand::New(); // register listener for new property command->SetCallbackFunction(this, &LevelWindowManager::OnPropertyModified); m_PropertyModifiedTag = m_LevelWindowProperty->AddObserver(itk::ModifiedEvent(), command); m_IsPropertyModifiedTagSet = true; m_CurrentImage = dynamic_cast(propNode->GetData()); m_LevelWindowMutex = true; propNode->SetBoolProperty("imageForLevelWindow", true); m_LevelWindowMutex = false; this->Modified(); } void mitk::LevelWindowManager::SetLevelWindow(const LevelWindow &levelWindow) { if (m_LevelWindowProperty.IsNull()) { return; } m_LevelWindowProperty->SetLevelWindow(levelWindow); for (const auto &dataNode : m_DataNodesForLevelWindow) { auto levelWindowProperty = dynamic_cast(dataNode->GetProperty("levelwindow")); if (nullptr == levelWindowProperty) { continue; } levelWindowProperty->SetLevelWindow(levelWindow); } this->Modified(); } mitk::LevelWindowProperty::Pointer mitk::LevelWindowManager::GetLevelWindowProperty() const { return m_LevelWindowProperty; } const mitk::LevelWindow &mitk::LevelWindowManager::GetLevelWindow() const { if (m_LevelWindowProperty.IsNotNull()) { return m_LevelWindowProperty->GetLevelWindow(); } else { mitkThrow() << "No LevelWindow available!"; } } bool mitk::LevelWindowManager::IsAutoTopMost() const { return m_AutoTopMost; } bool mitk::LevelWindowManager::IsSelectedImages() const { return m_SelectedImagesMode; } void mitk::LevelWindowManager::DataStorageAddedNode(const DataNode *) { // update observers with new data storage this->UpdateObservers(); // initialize LevelWindowManager to new image this->SetAutoTopMostImage(true); // check if everything is still ok if ((m_ObserverToVisibleProperty.size() != m_ObserverToLayerProperty.size()) || (m_ObserverToLayerProperty.size() != this->GetRelevantNodes()->size())) { mitkThrow() << "Wrong number of observers in Level Window Manager!"; } } void mitk::LevelWindowManager::DataStorageRemovedNode(const DataNode *removedNode) { // First: check if deleted node is part of relevant nodes. // If not, abort method because there is no need change anything. bool removedNodeIsRelevant = false; DataStorage::SetOfObjects::ConstPointer relevantNodes = GetRelevantNodes(); for (DataStorage::SetOfObjects::ConstIterator it = relevantNodes->Begin(); it != relevantNodes->End(); ++it) { if (it->Value() == removedNode) { removedNodeIsRelevant = true; } } if (false == removedNodeIsRelevant) { return; } // remember node which will be removed m_NodeMarkedToDelete = removedNode; // update observers this->UpdateObservers(); // search image that belongs to the property if (m_LevelWindowProperty.IsNull()) { this->SetAutoTopMostImage(true, removedNode); } else { auto property = NodePredicateProperty::New("levelwindow", m_LevelWindowProperty); DataNode *n = m_DataStorage->GetNode(property); if (n == nullptr || m_AutoTopMost) // if node was deleted, change our behavior to AutoTopMost, if AutoTopMost is // true change level window to topmost node { this->SetAutoTopMostImage(true, removedNode); } } // reset variable m_NodeMarkedToDelete = nullptr; // check if everything is still ok if ((m_ObserverToVisibleProperty.size() != m_ObserverToLayerProperty.size()) || (m_ObserverToLayerProperty.size() != (relevantNodes->size() - 1))) { mitkThrow() << "Wrong number of observers in Level Window Manager!"; } } void mitk::LevelWindowManager::OnPropertyModified(const itk::EventObject &) { this->Modified(); } mitk::Image *mitk::LevelWindowManager::GetCurrentImage() const { return m_CurrentImage; } int mitk::LevelWindowManager::GetNumberOfObservers() const { return m_ObserverToVisibleProperty.size(); } mitk::DataStorage::SetOfObjects::ConstPointer mitk::LevelWindowManager::GetRelevantNodes() const { if (m_DataStorage.IsNull()) { return DataStorage::SetOfObjects::ConstPointer(DataStorage::SetOfObjects::New()); } auto notBinary = NodePredicateProperty::New("binary", BoolProperty::New(false)); auto hasLevelWindow = NodePredicateProperty::New("levelwindow", nullptr); auto isImage = NodePredicateDataType::New("Image"); auto isDImage = NodePredicateDataType::New("DiffusionImage"); auto isTImage = NodePredicateDataType::New("TensorImage"); auto isOdfImage = NodePredicateDataType::New("OdfImage"); auto isShImage = NodePredicateDataType::New("ShImage"); auto predicateTypes = NodePredicateOr::New(); predicateTypes->AddPredicate(isImage); predicateTypes->AddPredicate(isDImage); predicateTypes->AddPredicate(isTImage); predicateTypes->AddPredicate(isOdfImage); predicateTypes->AddPredicate(isShImage); NodePredicateAnd::Pointer predicate = NodePredicateAnd::New(); predicate->AddPredicate(notBinary); predicate->AddPredicate(hasLevelWindow); predicate->AddPredicate(predicateTypes); DataStorage::SetOfObjects::ConstPointer relevantNodes = m_DataStorage->GetSubset(predicate); return relevantNodes; } void mitk::LevelWindowManager::UpdateObservers() { this->ClearPropertyObserverMaps(); this->CreatePropertyObserverMaps(); } void mitk::LevelWindowManager::ClearPropertyObserverMaps() { for (auto iter = m_ObserverToVisibleProperty.begin(); iter != m_ObserverToVisibleProperty.end(); ++iter) { (*iter).second->RemoveObserver((*iter).first.first); (*iter).second = nullptr; } m_ObserverToVisibleProperty.clear(); for (auto iter = m_ObserverToLayerProperty.begin(); iter != m_ObserverToLayerProperty.end(); ++iter) { (*iter).second->RemoveObserver((*iter).first.first); (*iter).second = nullptr; } m_ObserverToLayerProperty.clear(); for (auto iter = m_ObserverToRenderingModeProperty.begin(); iter != m_ObserverToRenderingModeProperty.end(); ++iter) { (*iter).second->RemoveObserver((*iter).first.first); (*iter).second = nullptr; } m_ObserverToRenderingModeProperty.clear(); for (auto iter = m_ObserverToDisplayedComponentProperty.begin(); iter != m_ObserverToDisplayedComponentProperty.end(); ++iter) { (*iter).second->RemoveObserver((*iter).first.first); (*iter).second = nullptr; } m_ObserverToDisplayedComponentProperty.clear(); for (auto iter = m_ObserverToLevelWindowImageProperty.begin(); iter != m_ObserverToLevelWindowImageProperty.end(); ++iter) { (*iter).second->RemoveObserver((*iter).first.first); (*iter).second = nullptr; } m_ObserverToLevelWindowImageProperty.clear(); for (auto iter = m_ObserverToSelectedProperty.begin(); iter != m_ObserverToSelectedProperty.end(); ++iter) { (*iter).second->RemoveObserver((*iter).first.first); (*iter).second = nullptr; } m_ObserverToSelectedProperty.clear(); } void mitk::LevelWindowManager::CreatePropertyObserverMaps() { if (m_DataStorage.IsNull()) { mitkThrow() << "DataStorage not set"; } // add observers for all relevant nodes DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes(); for (DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull() || node == m_NodeMarkedToDelete) { continue; } auto command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &LevelWindowManager::Update); unsigned long visIdx = node->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command); m_ObserverToVisibleProperty[PropDataPair(visIdx, node)] = node->GetProperty("visible"); auto command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction(this, &LevelWindowManager::Update); unsigned long layerIdx = node->GetProperty("layer")->AddObserver(itk::ModifiedEvent(), command2); m_ObserverToLayerProperty[PropDataPair(layerIdx, node)] = node->GetProperty("layer"); auto command3 = itk::ReceptorMemberCommand::New(); command3->SetCallbackFunction(this, &LevelWindowManager::Update); BaseProperty::Pointer imageRenderingMode = node->GetProperty("Image Rendering.Mode"); if (imageRenderingMode.IsNotNull()) { unsigned long rendIdx = imageRenderingMode->AddObserver(itk::ModifiedEvent(), command3); m_ObserverToRenderingModeProperty[PropDataPair(rendIdx, node)] = imageRenderingMode.GetPointer(); } auto command4 = itk::ReceptorMemberCommand::New(); command4->SetCallbackFunction(this, &LevelWindowManager::RecalculateLevelWindowForSelectedComponent); BaseProperty::Pointer displayedImageComponent = node->GetProperty("Image.Displayed Component"); if (displayedImageComponent.IsNotNull()) { unsigned long dispIdx = displayedImageComponent->AddObserver(itk::ModifiedEvent(), command4); m_ObserverToDisplayedComponentProperty[PropDataPair(dispIdx, node)] = displayedImageComponent.GetPointer(); } auto command5 = itk::ReceptorMemberCommand::New(); command5->SetCallbackFunction(this, &LevelWindowManager::Update); BaseProperty::Pointer imgForLvlWin = node->GetProperty("imageForLevelWindow"); if (imgForLvlWin.IsNull()) { node->SetBoolProperty("imageForLevelWindow", false); imgForLvlWin = node->GetProperty("imageForLevelWindow"); } unsigned long lvlWinIdx = imgForLvlWin->AddObserver(itk::ModifiedEvent(), command5); m_ObserverToLevelWindowImageProperty[PropDataPair(lvlWinIdx, node)] = node->GetProperty("imageForLevelWindow"); auto command6 = itk::ReceptorMemberCommand::New(); command6->SetCallbackFunction(this, &LevelWindowManager::UpdateSelected); BaseProperty::Pointer selectedDataNode = node->GetProperty("selected"); if (selectedDataNode.IsNull()) { node->SetBoolProperty("selected", false); selectedDataNode = node->GetProperty("selected"); } unsigned long selectedIdx = selectedDataNode->AddObserver(itk::ModifiedEvent(), command5); m_ObserverToSelectedProperty[PropDataPair(selectedIdx, node)] = node->GetProperty("selected"); } } bool mitk::LevelWindowManager::HasLevelWindowRenderingMode(DataNode *dataNode) const { RenderingModeProperty::Pointer mode = dynamic_cast(dataNode->GetProperty("Image Rendering.Mode")); if (mode.IsNotNull()) { int currMode = mode->GetRenderingMode(); if (currMode == RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR || currMode == RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR) { return true; } } return false; } diff --git a/Modules/Core/test/mitkLevelWindowManagerTest.cpp b/Modules/Core/test/mitkLevelWindowManagerTest.cpp index d0df3f1b1d..69f1d7341f 100644 --- a/Modules/Core/test/mitkLevelWindowManagerTest.cpp +++ b/Modules/Core/test/mitkLevelWindowManagerTest.cpp @@ -1,415 +1,445 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include #include #include #include #include #include #include #include #include #include class mitkLevelWindowManagerTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkLevelWindowManagerTestSuite); MITK_TEST(TestModes); MITK_TEST(TestSetLevelWindowProperty); MITK_TEST(TestVisibilityPropertyChanged); MITK_TEST(TestLayerPropertyChanged); MITK_TEST(TestImageRenderingModePropertyChanged); MITK_TEST(TestImageForLevelWindowPropertyChanged); MITK_TEST(TestSelectedPropertyChanged); MITK_TEST(TestRemoveDataNodes); MITK_TEST(TestCombinedPropertiesChanged); //MITK_TEST(TestMultiComponentRescaling); CPPUNIT_TEST_SUITE_END(); private: mitk::LevelWindowManager::Pointer m_LevelWindowManager; mitk::StandaloneDataStorage::Pointer m_DataManager; std::string m_ImagePath1; std::string m_ImagePath2; std::string m_ImagePath3; mitk::DataNode::Pointer m_DataNode1; mitk::DataNode::Pointer m_DataNode2; mitk::DataNode::Pointer m_DataNode3; mitk::Image::Pointer m_mitkMultiComponentImage; mitk::Image::Pointer m_mitkImageComponent1; mitk::Image::Pointer m_mitkImageComponent2; bool AssertImageForLevelWindowProperty(bool assert1, bool assert2, bool assert3) { bool imageForLevelWindowProperty1, imageForLevelWindowProperty2, imageForLevelWindowProperty3; m_DataNode1->GetBoolProperty("imageForLevelWindow", imageForLevelWindowProperty1); m_DataNode2->GetBoolProperty("imageForLevelWindow", imageForLevelWindowProperty2); m_DataNode3->GetBoolProperty("imageForLevelWindow", imageForLevelWindowProperty3); return (assert1 == imageForLevelWindowProperty1) && (assert2 == imageForLevelWindowProperty2) && (assert3 == imageForLevelWindowProperty3); } bool AssertLevelWindowProperty(bool assert1, bool assert2, bool assert3) { auto levelWindowProperty1 = dynamic_cast(m_DataNode1->GetProperty("levelwindow")); auto levelWindowProperty2 = dynamic_cast(m_DataNode2->GetProperty("levelwindow")); auto levelWindowProperty3 = dynamic_cast(m_DataNode3->GetProperty("levelwindow")); // Check if the active level window property of the manager is equal to any of the level window properties of the nodes auto managerLevelWindowProperty = m_LevelWindowManager->GetLevelWindowProperty(); return (assert1 == (managerLevelWindowProperty == levelWindowProperty1)) && (assert2 == (managerLevelWindowProperty == levelWindowProperty2)) && (assert3 == (managerLevelWindowProperty == levelWindowProperty3)); } public: void setUp() override { m_LevelWindowManager = mitk::LevelWindowManager::New(); m_DataManager = mitk::StandaloneDataStorage::New(); CPPUNIT_ASSERT_NO_THROW_MESSAGE("DataStorage could not be set for the new level window manager", m_LevelWindowManager->SetDataStorage(m_DataManager)); CPPUNIT_ASSERT_MESSAGE("DataStorage could not be retrieved from the new level window manager", m_DataManager == m_LevelWindowManager->GetDataStorage()); m_ImagePath1 = GetTestDataFilePath("Pic3D.nrrd"); m_ImagePath2 = GetTestDataFilePath("UltrasoundImages/4D_TEE_Data_MV.dcm"); m_ImagePath3 = GetTestDataFilePath("RenderingTestData/defaultWatermark.png"); // add multiple objects to the data storage => property observers will be created m_DataNode1 = mitk::IOUtil::Load(m_ImagePath1, *m_DataManager)->GetElement(0); m_DataNode2 = mitk::IOUtil::Load(m_ImagePath2, *m_DataManager)->GetElement(0); CPPUNIT_ASSERT_MESSAGE("Not two relevant nodes found in the data storage", m_LevelWindowManager->GetRelevantNodes()->size() == 2); CPPUNIT_ASSERT_MESSAGE("Not two observers created for the relevant nodes", m_LevelWindowManager->GetNumberOfObservers() == 2); m_DataNode1->SetIntProperty("layer", 1); m_DataNode2->SetIntProperty("layer", 2); bool isImageForLevelWindow1, isImageForLevelWindow2; m_DataNode1->GetBoolProperty("imageForLevelWindow", isImageForLevelWindow1); m_DataNode2->GetBoolProperty("imageForLevelWindow", isImageForLevelWindow2); CPPUNIT_ASSERT_MESSAGE("Initial \"imageForLevelWindow\" property not exclusively set for node 2", !isImageForLevelWindow1 && isImageForLevelWindow2); m_DataNode3 = mitk::IOUtil::Load(m_ImagePath3, *m_DataManager)->GetElement(0); CPPUNIT_ASSERT_MESSAGE("Not three relevant nodes found in the data storage", m_LevelWindowManager->GetRelevantNodes()->size() == 3); CPPUNIT_ASSERT_MESSAGE("Not three observers created for the relevant nodes", m_LevelWindowManager->GetNumberOfObservers() == 3); m_DataNode3->SetIntProperty("layer", 3); AssertImageForLevelWindowProperty(false, false, true); } void tearDown() override {} void TestModes() { CPPUNIT_ASSERT_MESSAGE("AutoTopMost mode is not enabled per default", m_LevelWindowManager->IsAutoTopMost()); CPPUNIT_ASSERT_MESSAGE("SelectedImagesMode mode is not disabled per default", !m_LevelWindowManager->IsSelectedImages()); m_LevelWindowManager->SetSelectedImages(true); CPPUNIT_ASSERT_MESSAGE("AutoTopMost mode was not disabled on mode switch", !m_LevelWindowManager->IsAutoTopMost()); CPPUNIT_ASSERT_MESSAGE("SelectedImagesMode mode was not enabled on mode switch", m_LevelWindowManager->IsSelectedImages()); m_LevelWindowManager->SetSelectedImages(false); CPPUNIT_ASSERT_MESSAGE("AutoTopMost mode was not disabled on mode switch", !m_LevelWindowManager->IsAutoTopMost()); CPPUNIT_ASSERT_MESSAGE("SelectedImagesMode mode was not disabled on mode switch", !m_LevelWindowManager->IsSelectedImages()); m_LevelWindowManager->SetSelectedImages(true); // to enable "SelectedImagesMode" m_LevelWindowManager->SetAutoTopMostImage(true); CPPUNIT_ASSERT_MESSAGE("AutoTopMost mode was not enabled on mode switch", m_LevelWindowManager->IsAutoTopMost()); CPPUNIT_ASSERT_MESSAGE("SelectedImagesMode mode was not disabled on mode switch", !m_LevelWindowManager->IsSelectedImages()); } void TestSetLevelWindowProperty() { m_LevelWindowManager->SetAutoTopMostImage(false); // Setting the level window property of the manager // will make the corresponding node be the "imageForLevelWindow" node. auto levelWindowProperty = dynamic_cast(m_DataNode1->GetProperty("levelwindow")); m_LevelWindowManager->SetLevelWindowProperty(levelWindowProperty); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); levelWindowProperty = dynamic_cast(m_DataNode2->GetProperty("levelwindow")); m_LevelWindowManager->SetLevelWindowProperty(levelWindowProperty); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); levelWindowProperty = dynamic_cast(m_DataNode3->GetProperty("levelwindow")); m_LevelWindowManager->SetLevelWindowProperty(levelWindowProperty); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); levelWindowProperty = mitk::LevelWindowProperty::New(); //CPPUNIT_ASSERT_THROW_MESSAGE("Expected exception for an invalid level window property was not thrown", //m_LevelWindowManager->SetLevelWindowProperty(levelWindowProperty), mitk::Exception); } void TestVisibilityPropertyChanged() { // Hiding a node will make the "next" node be the "imageForLevelWindow" node, if // the hidden node was the "imageForLevelWindow" node before. "Next" is dependent on the node layer. m_DataNode3->SetVisibility(false); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode2->SetVisibility(false); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode1->SetVisibility(false); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is not null", !m_LevelWindowManager->GetLevelWindowProperty()); m_DataNode3->SetVisibility(true); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); } void TestLayerPropertyChanged() { m_DataNode3->SetIntProperty("layer", itk::NumericTraits::min()); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode2->SetIntProperty("layer", itk::NumericTraits::min()); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode1->SetIntProperty("layer", itk::NumericTraits::min()); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is not null", !m_LevelWindowManager->GetLevelWindowProperty()); m_DataNode3->SetIntProperty("layer", 1); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); } void TestImageRenderingModePropertyChanged() { // checking the default rendering mode auto renderingMode = dynamic_cast(m_DataNode3->GetProperty("Image Rendering.Mode")); CPPUNIT_ASSERT_MESSAGE("Initial \"Image Rendering.Mode\" property not set to \"RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR\"", mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR == renderingMode->GetRenderingMode()); // Changing the "Image Rendering.Mode" of a node to either "LOOKUPTABLE_COLOR" or // "COLORTRANSFERFUNCTION_COLOR" will ignore this node for the level window m_DataNode3->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::LOOKUPTABLE_COLOR)); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode2->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR)); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode1->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::LOOKUPTABLE_COLOR)); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is not null", !m_LevelWindowManager->GetLevelWindowProperty()); m_DataNode3->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR)); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); } void TestImageForLevelWindowPropertyChanged() { m_LevelWindowManager->SetAutoTopMostImage(false); m_DataNode1->SetBoolProperty("imageForLevelWindow", true); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode2->SetBoolProperty("imageForLevelWindow", true); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode3->SetBoolProperty("imageForLevelWindow", true); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); // The top level node will alsways be used as a fall back node // if no specific mode is selected. m_DataNode3->SetBoolProperty("imageForLevelWindow", false); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); } void TestSelectedPropertyChanged() { // Selecting a node will make this node be the "imageForLevelWindow" node, if // the "SelectedImagesMode" is enabled (disabled per default). m_DataNode1->SetSelected(true); // selection mode not enabled - node3 stays the "imageForLevelWindow" node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); // This will immediately check for the selected node (node 1). m_LevelWindowManager->SetSelectedImages(true); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); + // Second node will be selected (node 1 and node 2 selected). + // It is not specified which data node will be used for the "imageForLevelWindow" / "levelwindow" property, + // since the data storage access to the nodes is non-deterministic. + // At least check for any valid level window property. m_DataNode2->SetSelected(true); - CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); - CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); + CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is null", m_LevelWindowManager->GetLevelWindowProperty()); + // Third node will be selected (node 1, node 2 and node 3 selected) + // It is not specified which data node will be used for the "imageForLevelWindow" / "levelwindow" property, + // since the data storage access to the nodes is non-deterministic. + // At least check for any valid level window property. m_DataNode3->SetSelected(true); - CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); - CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); + auto usedLevelWindowProperty = m_LevelWindowManager->GetLevelWindowProperty(); + CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is null", usedLevelWindowProperty); + + // All three nodes are selected: Check if only one node has the "imageForLevelWindow" property set and this node's + // "levelwindow" property is used by the level window manager. + auto levelWindowProperty1 = dynamic_cast(m_DataNode1->GetProperty("imageForLevelWindow")); + if (usedLevelWindowProperty == levelWindowProperty1) + { + CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); + CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); + } + + auto levelWindowProperty2 = dynamic_cast(m_DataNode2->GetProperty("imageForLevelWindow")); + if (usedLevelWindowProperty == levelWindowProperty2) + { + CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); + CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); + } + + auto levelWindowProperty3 = dynamic_cast(m_DataNode3->GetProperty("imageForLevelWindow")); + if (usedLevelWindowProperty == levelWindowProperty3) + { + CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); + CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); + } m_DataNode1->SetSelected(false); m_DataNode2->SetSelected(false); m_DataNode3->SetSelected(false); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is not null", !m_LevelWindowManager->GetLevelWindowProperty()); } void TestCombinedPropertiesChanged() { m_LevelWindowManager->SetSelectedImages(true); m_DataNode1->SetSelected(true); // selection mode enabled - node1 becomes the "imageForLevelWindow" node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode2->SetIntProperty("layer", itk::NumericTraits::max()); // selection mode enabled - node1 stays the "imageForLevelWindow" node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode1->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR)); // selection mode enabled - but node1 is ignored - no active level window property CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); m_DataNode3->SetBoolProperty("imageForLevelWindow", true); // selection mode enabled - no valid node selected, no active level window property CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); m_LevelWindowManager->SetSelectedImages(false); // no mode enabled - however, level window is not modified / updated CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); m_LevelWindowManager->Update(itk::ModifiedEvent()); // no mode enabled - level window is modified / updated with topmost visible node2 as fallback CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode3->SetBoolProperty("imageForLevelWindow", true); // no mode enabled - use node3 with "imageForLevelWindow" property set CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); m_DataNode3->SetVisibility(false); // node3 with "imageForLevelWindow" property not visible - use topmost visible node2 as fallback CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode2->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::LOOKUPTABLE_COLOR)); // fallback node2 is ignored - but "imageForLevelWindow" and "levelWindow" stay "true" for node2 CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_LevelWindowManager->SetAutoTopMostImage(true); // no visible node exists that is not ignored CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, false)); auto levelWindowProperty = dynamic_cast(m_DataNode3->GetProperty("levelwindow")); m_LevelWindowManager->SetLevelWindowProperty(levelWindowProperty); // explicitely set the level window to node3 CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); m_DataNode1->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR)); // auto topmost mode enabled - node1 is the only visible non-ignored node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode2->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New( mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR)); // auto topmost mode enabled - node2 is topmost visible node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, true, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, true, false)); m_DataNode2->SetIntProperty("layer", itk::NumericTraits::min()); // auto topmost mode enabled - node1 is topmost visible node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(true, false, false)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(true, false, false)); m_DataNode3->SetVisibility(true); // auto topmost mode enabled - node3 is topmost visible node CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", AssertImageForLevelWindowProperty(false, false, true)); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", AssertLevelWindowProperty(false, false, true)); } void TestRemoveDataNodes() { m_DataManager->Remove(m_DataNode3); CPPUNIT_ASSERT_MESSAGE("Node not correctly removed", m_LevelWindowManager->GetRelevantNodes()->size() == 2); CPPUNIT_ASSERT_MESSAGE("Observer not correctly removed", m_LevelWindowManager->GetNumberOfObservers() == 2); bool isImageForLevelWindow1, isImageForLevelWindow2; m_DataNode1->GetBoolProperty("imageForLevelWindow", isImageForLevelWindow1); m_DataNode2->GetBoolProperty("imageForLevelWindow", isImageForLevelWindow2); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", !isImageForLevelWindow1 && isImageForLevelWindow2); auto levelWindowProperty1 = dynamic_cast(m_DataNode1->GetProperty("levelwindow")); auto levelWindowProperty2 = dynamic_cast(m_DataNode2->GetProperty("levelwindow")); auto managerLevelWindowProperty = m_LevelWindowManager->GetLevelWindowProperty(); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", (false == (managerLevelWindowProperty == levelWindowProperty1)) && (true == (managerLevelWindowProperty == levelWindowProperty2))); m_DataManager->Remove(m_DataNode2); CPPUNIT_ASSERT_MESSAGE("Node not correctly removed", m_LevelWindowManager->GetRelevantNodes()->size() == 1); CPPUNIT_ASSERT_MESSAGE("Observer not correctly removed", m_LevelWindowManager->GetNumberOfObservers() == 1); m_DataNode1->GetBoolProperty("imageForLevelWindow", isImageForLevelWindow1); CPPUNIT_ASSERT_MESSAGE("\"imageForLevelWindow\" property not correctly set", isImageForLevelWindow1); levelWindowProperty1 = dynamic_cast(m_DataNode1->GetProperty("levelwindow")); managerLevelWindowProperty = m_LevelWindowManager->GetLevelWindowProperty(); CPPUNIT_ASSERT_MESSAGE("\"levelwindow\" property not correctly set", true == (managerLevelWindowProperty == levelWindowProperty1)); m_DataManager->Remove(m_DataNode1); CPPUNIT_ASSERT_MESSAGE("Node not correctly removed", m_LevelWindowManager->GetRelevantNodes()->size() == 0); CPPUNIT_ASSERT_MESSAGE("Observer not correctly removed", m_LevelWindowManager->GetNumberOfObservers() == 0); CPPUNIT_ASSERT_MESSAGE("LevelWindowProperty is not null", !m_LevelWindowManager->GetLevelWindowProperty()); } }; MITK_TEST_SUITE_REGISTRATION(mitkLevelWindowManager)