diff --git a/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp b/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp index 8bf243c4d0..cc8c0f0189 100644 --- a/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp +++ b/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp @@ -1,117 +1,111 @@ /*=================================================================== 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 "mitkBindDispatcherInteractor.h" #include "mitkMessage.h" #include // us #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +//#include "mitkInformer.h" mitk::BindDispatcherInteractor::BindDispatcherInteractor() : m_DataStorage(NULL),m_InformerService(NULL) { ModuleContext* context = ModuleRegistry::GetModule(1)->GetModuleContext(); if (context == NULL) { MITK_ERROR<< "BindDispatcherInteractor() - Context could not be obtained."; return; } - ServiceReference serviceRef = context->GetServiceReference(); - if (!serviceRef) - { // the service should only be registered once - m_InformerService = new InformerService(); - context->RegisterService(m_InformerService); - } m_Dispatcher = Dispatcher::New(); } void mitk::BindDispatcherInteractor::SetDataStorage(mitk::DataStorage::Pointer dataStorage) { // Set/Change Datastorage. This registers BDI to listen for events of DataStorage, to be informed when // a DataNode with a Interactor is added/modified/removed. // clean up events from previous datastorage UnRegisterDataStorageEvents(); m_DataStorage = dataStorage; RegisterDataStorageEvents(); } mitk::BindDispatcherInteractor::~BindDispatcherInteractor() { if (m_DataStorage.IsNotNull()) { UnRegisterDataStorageEvents(); } } void mitk::BindDispatcherInteractor::RegisterInteractor(const mitk::DataNode* dataNode) { if (m_Dispatcher.IsNotNull()) { m_Dispatcher->AddDataInteractor(dataNode); } } void mitk::BindDispatcherInteractor::RegisterDataStorageEvents() { if (m_DataStorage.IsNotNull()) { m_DataStorage->AddNodeEvent.AddListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); m_DataStorage->RemoveNodeEvent.AddListener( MessageDelegate1(this, &BindDispatcherInteractor::UnRegisterInteractor)); m_DataStorage->ChangedNodeEvent.AddListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); } } void mitk::BindDispatcherInteractor::UnRegisterInteractor(const DataNode* dataNode) { if (m_Dispatcher.IsNotNull()) { m_Dispatcher->RemoveDataInteractor(dataNode); } } -mitk::Dispatcher::Pointer mitk::BindDispatcherInteractor::GetDispatcher() +const mitk::Dispatcher::Pointer mitk::BindDispatcherInteractor::GetDispatcher() { return m_Dispatcher; } void mitk::BindDispatcherInteractor::SetDispatcher(Dispatcher::Pointer dispatcher) { m_Dispatcher = dispatcher; } void mitk::BindDispatcherInteractor::UnRegisterDataStorageEvents() { if (m_DataStorage.IsNotNull()) { m_DataStorage->AddNodeEvent.RemoveListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); m_DataStorage->RemoveNodeEvent.RemoveListener( MessageDelegate1(this, &BindDispatcherInteractor::UnRegisterInteractor)); m_DataStorage->ChangedNodeEvent.RemoveListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); } } diff --git a/Core/Code/Interactions/mitkBindDispatcherInteractor.h b/Core/Code/Interactions/mitkBindDispatcherInteractor.h index 773ad37736..87e1571fc2 100644 --- a/Core/Code/Interactions/mitkBindDispatcherInteractor.h +++ b/Core/Code/Interactions/mitkBindDispatcherInteractor.h @@ -1,87 +1,82 @@ /*=================================================================== 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 mitkBindDispatcherInteractor_h #define mitkBindDispatcherInteractor_h -#include "itkObject.h" -#include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkDataStorage.h" #include "mitkDataNode.h" #include "mitkDispatcher.h" namespace mitk { class InformerService; /** * \class BindDispatcherInteractor * \brief This Class is used to connect a DataStorage with the Dispatcher. + * * This is done by registering for DataStorage Events and sending the Events to the registered Dispatcher. * When a DataInteractor is registered with a DataNode the Dispatcher will be notified. - * Also this class registers the MicroService at which EventObservers can register to receive events. + * Also this class registers the MicroService at which InteractionEventObservers can register to receive events. * * \ingroup Interaction */ - class MITK_CORE_EXPORT BindDispatcherInteractor: public itk::Object + class MITK_CORE_EXPORT BindDispatcherInteractor { public: - mitkClassMacro(BindDispatcherInteractor, itk::Object); - itkNewMacro(Self); + BindDispatcherInteractor(); + ~BindDispatcherInteractor(); /** * Sets the DataStorage to which Events the class subscribes. */ void SetDataStorage(DataStorage::Pointer dataStorage); /** * Sets Dispatcher which will be notified. By default each RenderWindow gets its own Dispatcher, * this function can be used to override this behavior. */ void SetDispatcher(Dispatcher::Pointer dispatcher); /** * Return currently active Dispatcher. */ - Dispatcher::Pointer GetDispatcher(); + const Dispatcher::Pointer GetDispatcher(); - protected: - - BindDispatcherInteractor(); - virtual ~BindDispatcherInteractor(); private: /** @brief Registers for events from DataStorage. * * This way whenever a DataNode is added the Dispatcher is notified about this change, and checks whether a DataInteractor * is set for this DataNode */ void RegisterInteractor(const DataNode* dataNode); void UnRegisterInteractor(const DataNode* dataNode); void RegisterDataStorageEvents(); void UnRegisterDataStorageEvents(); Dispatcher::Pointer m_Dispatcher; DataStorage::Pointer m_DataStorage; InformerService* m_InformerService; // holds reference to MicroService that notifies listeners }; } #endif /* mitkBindDispatcherInteractor_h */ diff --git a/Core/Code/Interactions/mitkDataInteractor.cpp b/Core/Code/Interactions/mitkDataInteractor.cpp index 93963e30b6..c99f9e01d8 100644 --- a/Core/Code/Interactions/mitkDataInteractor.cpp +++ b/Core/Code/Interactions/mitkDataInteractor.cpp @@ -1,121 +1,93 @@ /*=================================================================== 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 "mitkDataInteractor.h" #include "mitkInteractor.h" #include "mitkPointSet.h" #include "mitkDataNode.h" #include "mitkStateMachineState.h" mitk::DataInteractor::DataInteractor() { - m_SelectionAccuracy = 3.5; } -mitk::DataNode::Pointer mitk::DataInteractor::GetDataNode() +mitk::DataInteractor::NodeType mitk::DataInteractor::GetDataNode() const { return m_DataNode; } void mitk::DataInteractor::SetDataNode(DataNode::Pointer dataNode) { if (dataNode == m_DataNode) return; if (m_DataNode.IsNotNull()) { // if DataInteractors' DataNode is set to null, the "old" DataNode has to be notified (else the Dispatcher won't be notified either) m_DataNode->SetDataInteractor(NULL); } m_DataNode = dataNode; if (m_DataNode.IsNotNull()) { m_DataNode->SetDataInteractor(this); } // notify implementations ... DataNodeChanged(); } -int mitk::DataInteractor::GetLayer() +int mitk::DataInteractor::GetLayer() const { int layer = -1; if (m_DataNode.IsNotNull()) { m_DataNode->GetIntProperty("layer", layer); } return layer; } mitk::DataInteractor::~DataInteractor() { if (m_DataNode.IsNotNull()) { m_DataNode->SetInteractor(NULL); } } -void mitk::DataInteractor::SetAccuracy(float accuracy) -{ - m_SelectionAccuracy = accuracy; -} - void mitk::DataInteractor::ConnectActionsAndFunctions() { MITK_WARN<< "ConnectActionsAndFunctions in DataInteractor not implemented.\n DataInteractor will not be able to process any events."; } mitk::ProcessEventMode mitk::DataInteractor::GetMode() { if (GetCurrentState()->GetMode() == "PREFER_INPUT") { return PREFERINPUT; } if (GetCurrentState()->GetMode() == "GRAB_INPUT") { return GRABINPUT; } return REGULAR; } -int mitk::DataInteractor::GetPointIndexByPosition(Point3D position, int time) -{ - - // iterate over point set and check if it contains a point close enough to the pointer to be selected - PointSet* points = dynamic_cast(GetDataNode()->GetData()); - int index = -1; - if (points == NULL) - { - return index; - } - PointSet::PointsContainer* pointsContainer = points->GetPointSet(time)->GetPoints(); - float minDistance = m_SelectionAccuracy; - for (PointSet::PointsIterator it = pointsContainer->Begin(); it != pointsContainer->End(); it++) - { - float distance = sqrt(position.SquaredEuclideanDistanceTo(points->GetPoint(it->Index(), time))); // TODO: support time! - if (distance < minDistance) // if several points fall within the margin, choose the one with minimal distance to position - { // TODO: does this make sense, which unit is it? - index = it->Index(); - } - } - return index; -} void mitk::DataInteractor::DataNodeChanged() { } diff --git a/Core/Code/Interactions/mitkDataInteractor.h b/Core/Code/Interactions/mitkDataInteractor.h index ec9982b3d3..94cd3b5d58 100644 --- a/Core/Code/Interactions/mitkDataInteractor.h +++ b/Core/Code/Interactions/mitkDataInteractor.h @@ -1,126 +1,100 @@ /*=================================================================== 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 MITKEVENTINTERACTOR_H_ #define MITKEVENTINTERACTOR_H_ -#include "itkObject.h" #include "itkSmartPointer.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkEventStateMachine.h" #include namespace mitk { /** * \class DataInteractor * * \brief Base class from with interactors that handle DataNodes are to be derived. * * Base class from with interactors that handle DataNodes are to be derived. * Provides an interface that is relevant for the interactor to work together with the dispatcher. * To implement a new interactor overwrite the ConnectActionsAndFunctions to connect the actions. */ // Public 'cause it's also used by the mitk::Dispatcher enum ProcessEventMode { REGULAR = 0, GRABINPUT = 1, PREFERINPUT = 2, CONNECTEDMOUSEACTION = 3 // only used by mitk::Dispatcher }; class DataNode; class MITK_CORE_EXPORT DataInteractor: public EventStateMachine { public: typedef itk::SmartPointer NodeType; - mitkClassMacro(DataInteractor, EventStateMachine); - itkNewMacro(Self); + mitkClassMacro(DataInteractor, EventStateMachine) + itkNewMacro(Self) /** * Set/Change the DataNode of the DataInteractor */ void SetDataNode(NodeType); - /** - * Sets the maximum distance that is accepted when looking for a point at a certain position using the GetPointIndexByPosition function. - */ - void SetAccuracy(float accuracy); - /** * @brief Returns the mode the DataInteractor currently is in. See in mitkDispatcher the description of m_ProcessingMode for further details. */ ProcessEventMode GetMode(); - NodeType GetDataNode(); - int GetLayer(); + NodeType GetDataNode() const; + int GetLayer() const; protected: DataInteractor(); virtual ~DataInteractor(); /** * @brief Overwrite this function to connect actions from StateMachine description with functions. * * Following example shows how to connect the 'addpoint' action from the StateMachine XML description using the CONNECT_FUNCTION macro * with the AddPoint() function in the TestInteractor. * @code * void mitk::TestInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addpoint", AddPoint); } * @endcode */ virtual void ConnectActionsAndFunctions(); - /** - * @ brief Return index in PointSet of the point that is within given accuracy to the provided position. - * - * Assumes that the DataNode contains a PointSet, if so it iterates over all points - * in the DataNode to check if it contains a point near the pointer position. - * If a point is found its index-position is returned, else -1 is returned. - */ - virtual int GetPointIndexByPosition(Point3D position, int time = 0); - /** \brief Is called when a DataNode is initially set or changed * To be implemented by sub-classes for initialization code which require a DataNode. * \note New DataInteractors usually are expected to have the focus, but this only works if they have the highest Layer, * since empty DataNodes have a layer of -1, the DataNode must be filled here in order to get a layer assigned. * \note Is also called when the DataNode is set to NULL. - * */ virtual void DataNodeChanged(); - /** \brief Is called when a DataNode is initially set or changed - * - * To be implemented by sub-classes for initialization code which require a DataNode. - * \note New DataInteractors usually are expected to have the focus, but this only works if they have the highest Layer, - * since empty DataNodes have a layer of -1, the DataNode must be filled here in order to get a layer assigned. - * \note Is also called when the DataNode is set to NULL. - * - */ - private: NodeType m_DataNode; - float m_SelectionAccuracy; }; } /* namespace mitk */ #endif /* MITKEVENTINTERACTOR_H_ */ diff --git a/Core/Code/Interactions/mitkDispatcher.cpp b/Core/Code/Interactions/mitkDispatcher.cpp index 26f82ac5f5..e14376a7de 100644 --- a/Core/Code/Interactions/mitkDispatcher.cpp +++ b/Core/Code/Interactions/mitkDispatcher.cpp @@ -1,217 +1,230 @@ /*=================================================================== 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 "mitkDispatcher.h" #include "mitkInteractionEvent.h" #include "mitkInternalEvent.h" // MicroServices #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +#include "mitkInteractionEventObserver.h" -mitk::Dispatcher::Dispatcher() + +mitk::Dispatcher::Dispatcher() : + m_ProcessingMode(REGULAR), m_EventObserverTracker(GetModuleContext()) { - m_ProcessingMode = REGULAR; - // get service to inform EventObserver - mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - mitk::ServiceReference serviceRef = context->GetServiceReference(); - m_InformerService = dynamic_cast(context->GetService(serviceRef)); + m_EventObserverTracker.Open(); } void mitk::Dispatcher::AddDataInteractor(const DataNode* dataNode) { RemoveDataInteractor(dataNode); RemoveOrphanedInteractors(); DataInteractor::Pointer dataInteractor = dataNode->GetDataInteractor(); if (dataInteractor.IsNotNull()) { m_Interactors.push_back(dataInteractor); } } /* * Note: One DataInteractor can only have one DataNode and vice versa, * BUT the m_Interactors list may contain another DataInteractor that is still connected to this DataNode, * in this case we have to remove >1 DataInteractor. (Some special case of switching DataNodes between DataInteractors and registering a * DataNode to a DataStorage after assigning it to an DataInteractor) */ void mitk::Dispatcher::RemoveDataInteractor(const DataNode* dataNode) { for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();) { if ((*it)->GetDataNode() == dataNode) { it = m_Interactors.erase(it); } else { ++it; } } } size_t mitk::Dispatcher::GetNumberOfInteractors() { return m_Interactors.size(); } mitk::Dispatcher::~Dispatcher() { } bool mitk::Dispatcher::ProcessEvent(InteractionEvent* event) { InteractionEvent::Pointer p = event; //MITK_INFO << event->GetEventClass(); bool eventIsHandled = false; /* Filter out and handle Internal Events separately */ InternalEvent* internalEvent = dynamic_cast(event); if (internalEvent != NULL) { eventIsHandled = HandleInternalEvent(internalEvent); // InternalEvents that are handled are not sent to the listeners if (eventIsHandled) { return true; } } switch (m_ProcessingMode) { case CONNECTEDMOUSEACTION: // finished connected mouse action if (p->GetEventClass() == "MouseReleaseEvent") { m_ProcessingMode = REGULAR; eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); } // give event to selected interactor if (eventIsHandled == false) { eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); } break; case GRABINPUT: eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); SetEventProcessingMode(m_SelectedInteractor); break; case PREFERINPUT: if (m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()) == true) { SetEventProcessingMode(m_SelectedInteractor); eventIsHandled = true; } break; case REGULAR: break; } // Standard behavior. Is executed in STANDARD mode and PREFERINPUT mode, if preferred interactor rejects event. if (m_ProcessingMode == REGULAR || (m_ProcessingMode == PREFERINPUT && eventIsHandled == false)) { m_Interactors.sort(cmp()); // sorts interactors by layer (descending); for (std::list::iterator it = m_Interactors.begin(); it != m_Interactors.end(); ++it) { // explicit copy of pointer because HandleEvent function causes the m_Interactors list to be updated, // which in turn invalidates the iterator. DataInteractor::Pointer dataInteractor = *it; if (dataInteractor->HandleEvent(event, dataInteractor->GetDataNode())) { // if an event is handled several properties are checked, in order to determine the processing mode of the dispatcher SetEventProcessingMode(dataInteractor); if (p->GetEventClass() == "MousePressEvent" && m_ProcessingMode == REGULAR) { m_SelectedInteractor = dataInteractor; m_ProcessingMode = CONNECTEDMOUSEACTION; } eventIsHandled = true; break; } } } - /* Notify EventObserver */ - m_InformerService->NotifyObservers(event, eventIsHandled); + /* Notify InteractionEventObserver */ + std::list listEventObserver; + m_EventObserverTracker.GetServiceReferences(listEventObserver); + for (std::list::iterator it = listEventObserver.begin(); it != listEventObserver.end(); ++it) + { + + Any patternName = it->GetProperty("org.mitk.statemachinepattern"); + + //if (!patternName.Empty() || patternName.ToString() == "") + //{ + InteractionEventObserver* interactionEventObserver = m_EventObserverTracker.GetService(*it); + if (interactionEventObserver != NULL) + { + interactionEventObserver->Notify(event, eventIsHandled); + } + //} + } // Process event queue if (!m_QueuedEvents.empty()) { InteractionEvent::Pointer e = m_QueuedEvents.front(); m_QueuedEvents.pop_front(); ProcessEvent(e); } return eventIsHandled; } /* * Checks if DataNodes associated with DataInteractors point back to them. * If not remove the DataInteractors. (This can happen when s.o. tries to set DataNodes to multiple DataInteractors) */ void mitk::Dispatcher::RemoveOrphanedInteractors() { for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();) { DataNode::Pointer dn = (*it)->GetDataNode(); if (dn.IsNull()) { it = m_Interactors.erase(it); } else { DataInteractor::Pointer interactor = dn->GetDataInteractor(); if (interactor != it->GetPointer()) { it = m_Interactors.erase(it); } else { ++it; } } } } void mitk::Dispatcher::QueueEvent(InteractionEvent* event) { m_QueuedEvents.push_back(event); } void mitk::Dispatcher::SetEventProcessingMode(DataInteractor::Pointer dataInteractor) { m_ProcessingMode = dataInteractor->GetMode(); if (dataInteractor->GetMode() != REGULAR) { m_SelectedInteractor = dataInteractor; } } bool mitk::Dispatcher::HandleInternalEvent(InternalEvent* internalEvent) { if (internalEvent->GetSignalName() == IntDeactivateMe && internalEvent->GetTargetInteractor() != NULL) { internalEvent->GetTargetInteractor()->GetDataNode()->SetDataInteractor(NULL); internalEvent->GetTargetInteractor()->SetDataNode(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } diff --git a/Core/Code/Interactions/mitkDispatcher.h b/Core/Code/Interactions/mitkDispatcher.h index 8750937781..2ba95e36d4 100644 --- a/Core/Code/Interactions/mitkDispatcher.h +++ b/Core/Code/Interactions/mitkDispatcher.h @@ -1,129 +1,131 @@ /*=================================================================== 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 mitkDispatcher_h #define mitkDispatcher_h -#include "itkObject.h" +#include "itkLightObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkDataNode.h" #include "mitkDataInteractor.h" #include #include +#include "mitkServiceTracker.h" namespace mitk { class InternalEvent; class InteractionEvent; - class InformerService; + class InteractionEventObserver; /** * \class Dispatcher * \brief Manages event distribution * * Receives Events (Mouse-,Key-, ... Events) and dispatches them to the registered DataInteractor Objects. * The order in which DataInteractors are offered to handle an event is determined by layer of their associated DataNode. * Higher layers are preferred. * * \ingroup Interaction */ - class MITK_CORE_EXPORT Dispatcher: public itk::Object + class MITK_CORE_EXPORT Dispatcher: public itk::LightObject { public: - mitkClassMacro(Dispatcher, itk::Object); + mitkClassMacro(Dispatcher, itk::LightObject); itkNewMacro(Self); typedef std::list ListInteractorType; typedef std::list > ListEventsType; /** * To post new Events which are to be handled by the Dispatcher. * * @return Returns true if the event has been handled by an DataInteractor, and false else. */ bool ProcessEvent(InteractionEvent* event); /** * Adds an Event to the Dispatchers EventQueue, these events will be processed after a a regular posted event has been fully handled. - * This allows Interactors to post their own events without interrupting regular Dispatching workflow. - * NOTES: 1) If an event is added from an other source than an Interactor / Listener its execution will be delayed until the next regular event - * comes in. - * 2) Make sure you're not causing infinite loops! + * This allows DataInteractors to post their own events without interrupting regular Dispatching workflow. + * It is important to note that the queued events will be processed AFTER the state change of a current transition (which queued the events) + * is performed. * + * \note 1) If an event is added from an other source than an DataInteractor / Observer its execution will be delayed until the next regular event + * comes in. + * \note 2) Make sure you're not causing infinite loops! */ - void QueueEvent(InteractionEvent* event); /** * Adds the DataInteractor that is associated with the DataNode to the Dispatcher Queue. * If there already exists an DataInteractor that has a reference to the same DataNode, it is removed. * Note that within this method also all other DataInteractors are checked and removed if they are no longer active, * and were not removed properly. */ void AddDataInteractor(const DataNode* dataNode); /** * Remove all DataInteractors related to this Node, to prevent double entries and dead references. */ void RemoveDataInteractor(const DataNode* dataNode); size_t GetNumberOfInteractors(); // DEBUG TESTING protected: Dispatcher(); virtual ~Dispatcher(); private: struct cmp{ bool operator()(DataInteractor::Pointer d1, DataInteractor::Pointer d2){ return (d1->GetLayer() > d2->GetLayer()); } }; std::list m_Interactors; ListEventsType m_QueuedEvents; /** * Removes all Interactors without a DataNode pointing to them, this is necessary especially when a DataNode is assigned to a new Interactor */ void RemoveOrphanedInteractors(); /** * See \ref DispatcherEventDistSection for a description of ProcessEventModes */ ProcessEventMode m_ProcessingMode; DataInteractor::Pointer m_SelectedInteractor; void SetEventProcessingMode(DataInteractor::Pointer); /** * Function to handle special internal events, * such as events that are directed at a specific DataInteractor, * or the request to delete an Interactor and its DataNode. */ bool HandleInternalEvent(InternalEvent* internalEvent); /** - * Hold microservice reference to object that takes care of informing the EventObservers about InteractionEvents + * Hold microservice reference to object that takes care of informing the InteractionEventObservers about InteractionEvents */ - InformerService* m_InformerService; + mitk::ServiceTracker m_EventObserverTracker; }; } /* namespace mitk */ #endif /* mitkDispatcher_h */ diff --git a/Core/Code/Interactions/mitkDisplayInteractor.cpp b/Core/Code/Interactions/mitkDisplayInteractor.cpp index 1e9a6bafc7..dc0a4fb335 100644 --- a/Core/Code/Interactions/mitkDisplayInteractor.cpp +++ b/Core/Code/Interactions/mitkDisplayInteractor.cpp @@ -1,345 +1,346 @@ /*=================================================================== 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 "mitkDisplayInteractor.h" #include "mitkBaseRenderer.h" #include "mitkInteractionPositionEvent.h" #include "mitkPropertyList.h" #include // level window #include "mitkStandaloneDataStorage.h" #include "mitkNodePredicateDataType.h" #include "mitkLevelWindowProperty.h" #include "mitkLevelWindow.h" -void mitk::DisplayInteractor::Notify(InteractionEvent::Pointer interactionEvent, bool isHandled) +void mitk::DisplayInteractor::Notify(InteractionEvent* interactionEvent, bool isHandled) { // to use the state machine pattern, // the event is passed to the state machine interface to be handled if (!isHandled || m_AlwaysReact) { this->HandleEvent(interactionEvent, NULL); } } void mitk::DisplayInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("init", Init); CONNECT_FUNCTION("move", Move); CONNECT_FUNCTION("zoom", Zoom); CONNECT_FUNCTION("scroll", Scroll); CONNECT_FUNCTION("ScrollOneDown", ScrollOneDown); CONNECT_FUNCTION("ScrollOneUp", ScrollOneUp); CONNECT_FUNCTION("levelWindow", AdjustLevelWindow); } -mitk::DisplayInteractor::DisplayInteractor() +mitk::DisplayInteractor::DisplayInteractor() : + m_IndexToSliceModifier(4),m_AutoRepeat(false), m_AlwaysReact(false), m_ZoomFactor(2) { m_StartDisplayCoordinate.Fill(0); m_LastDisplayCoordinate.Fill(0); m_CurrentDisplayCoordinate.Fill(0); - m_IndexToSliceModifier = 4; - m_AlwaysReact = false; - m_AutoRepeat = false; - m_ZoomFactor = 2; } mitk::DisplayInteractor::~DisplayInteractor() { } bool mitk::DisplayInteractor::Init(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); + BaseRenderer* sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor cannot process the event: " << interactionEvent->GetEventClass(); return false; } Vector2D origin = sender->GetDisplayGeometry()->GetOriginInMM(); double scaleFactorMMPerDisplayUnit = sender->GetDisplayGeometry()->GetScaleFactorMMPerDisplayUnit(); m_StartDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_StartCoordinateInMM = mitk::Point2D( (origin + m_StartDisplayCoordinate.GetVectorFromOrigin() * scaleFactorMMPerDisplayUnit).GetDataPointer()); return true; } bool mitk::DisplayInteractor::Move(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); + BaseRenderer* sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor: cannot process the event in Move action: " << interactionEvent->GetEventClass(); return false; } // perform translation sender->GetDisplayGeometry()->MoveBy((positionEvent->GetPointerPositionOnScreen() - m_LastDisplayCoordinate) * (-1.0)); sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow()); m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); return true; } bool mitk::DisplayInteractor::Zoom(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); + const BaseRenderer::Pointer sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor cannot process the event: " << interactionEvent->GetEventClass(); return false; } float factor = 1.0; float distance = 0; if (m_ZoomDirection == "leftright") { distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]; } else { distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]; } // set zooming speed if (distance < 0.0) { factor = 1.0 / m_ZoomFactor; } else if (distance > 0.0) { factor = 1.0 * m_ZoomFactor; } sender->GetDisplayGeometry()->ZoomWithFixedWorldCoordinates(factor, m_StartDisplayCoordinate, m_StartCoordinateInMM); sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow()); m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); return true; } bool mitk::DisplayInteractor::Scroll(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor::Scroll cannot process the event: " << interactionEvent->GetEventClass(); return false; } mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (sliceNaviController) { int delta = 0; // Scrolling direction if (m_ScrollDirection == "leftright") { delta = static_cast(m_LastDisplayCoordinate[1] - positionEvent->GetPointerPositionOnScreen()[1]); } else { delta = static_cast(m_LastDisplayCoordinate[0] - positionEvent->GetPointerPositionOnScreen()[0]); } // Set how many pixels the mouse has to be moved to scroll one slice // if we moved less than 'm_IndexToSliceModifier' pixels slice ONE slice only if (delta > 0 && delta < m_IndexToSliceModifier) { delta = m_IndexToSliceModifier; } else if (delta < 0 && delta > -m_IndexToSliceModifier) { delta = -m_IndexToSliceModifier; } delta /= m_IndexToSliceModifier; int newPos = sliceNaviController->GetSlice()->GetPos() + delta; // if auto repeat is on, start at first slice if you reach the last slice and vice versa int maxSlices = sliceNaviController->GetSlice()->GetSteps(); if (m_AutoRepeat) { while (newPos < 0) { newPos += maxSlices; } while (newPos >= maxSlices) { newPos -= maxSlices; } } else { // if the new slice is below 0 we still show slice 0 // due to the stepper using unsigned int we have to do this ourselves if (newPos < 1) { newPos = 0; } } // set the new position sliceNaviController->GetSlice()->SetPos(newPos); m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); } return true; } bool mitk::DisplayInteractor::ScrollOneDown(StateMachineAction*, InteractionEvent* interactionEvent) { mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (!sliceNaviController->GetSliceLocked()) { mitk::Stepper* stepper = sliceNaviController->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = sliceNaviController->GetTime(); } stepper->Next(); } return true; } bool mitk::DisplayInteractor::ScrollOneUp(StateMachineAction*, InteractionEvent* interactionEvent) { mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (!sliceNaviController->GetSliceLocked()) { mitk::Stepper* stepper = sliceNaviController->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = sliceNaviController->GetTime(); } stepper->Previous(); return true; } return false; } bool mitk::DisplayInteractor::AdjustLevelWindow(StateMachineAction*, InteractionEvent* interactionEvent) { BaseRenderer::Pointer sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor::Scroll cannot process the event: " << interactionEvent->GetEventClass(); return false; } m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); // search for active image mitk::DataStorage::Pointer storage = sender->GetDataStorage(); mitk::DataNode::Pointer node = NULL; mitk::DataStorage::SetOfObjects::ConstPointer allImageNodes = storage->GetSubset(mitk::NodePredicateDataType::New("Image")); for (unsigned int i = 0; i < allImageNodes->size(); i++) { bool isActiveImage = false; bool propFound = allImageNodes->at(i)->GetBoolProperty("imageForLevelWindow", isActiveImage); if (propFound && isActiveImage) { node = allImageNodes->at(i); continue; } } if (node.IsNull()) { node = storage->GetNode(mitk::NodePredicateDataType::New("Image")); } if (node.IsNull()) { return false; } mitk::LevelWindow lv = mitk::LevelWindow(); node->GetLevelWindow(lv); ScalarType level = lv.GetLevel(); ScalarType window = lv.GetWindow(); // calculate adjustments from mouse movements level += (m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]) * static_cast(2); window += (m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]) * static_cast(2); lv.SetLevelWindow(level, window); dynamic_cast(node->GetProperty("levelwindow"))->SetLevelWindow(lv); sender->GetRenderingManager()->RequestUpdateAll(); return true; } void mitk::DisplayInteractor::ConfigurationChanged() { mitk::PropertyList::Pointer properties = GetAttributes(); // auto repeat std::string strAutoRepeat = ""; if (properties->GetStringProperty("autoRepeat", strAutoRepeat)) { if (strAutoRepeat == "true") { m_AutoRepeat = true; } else { m_AutoRepeat = false; } } // pixel movement for scrolling one slice std::string strPixelPerSlice = ""; if (properties->GetStringProperty("pixelPerSlice", strPixelPerSlice)) { m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str()); } else { m_IndexToSliceModifier = 4; } // scroll direction if (!properties->GetStringProperty("zoomDirection", m_ScrollDirection)) { m_ScrollDirection = "updown"; } // zoom direction if (!properties->GetStringProperty("zoomDirection", m_ZoomDirection)) { m_ZoomDirection = "updown"; } // zoom factor std::string strZoomFactor = ""; properties->GetStringProperty("zoomFactor", strZoomFactor); m_ZoomFactor = .05; if (atoi(strZoomFactor.c_str()) > 0) { m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0); } // allwaysReact std::string strAlwaysReact = ""; if (properties->GetStringProperty("alwaysReact", strAlwaysReact)) { if (strAlwaysReact == "true") { m_AlwaysReact = true; } else { m_AlwaysReact = false; } } else { m_AlwaysReact = false; } } + +bool mitk::DisplayInteractor::FilterEvents(InteractionEvent* /*interactionEvent*/, DataNode* /*dataNode*/) +{ + return true; +} diff --git a/Core/Code/Interactions/mitkDisplayInteractor.h b/Core/Code/Interactions/mitkDisplayInteractor.h index c78db7be66..4658a9127e 100644 --- a/Core/Code/Interactions/mitkDisplayInteractor.h +++ b/Core/Code/Interactions/mitkDisplayInteractor.h @@ -1,154 +1,163 @@ /*=================================================================== 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 mitkDisplayInteractor_h #define mitkDisplayInteractor_h #include -#include "mitkEventObserver.h" +#include "mitkInteractionEventObserver.h" namespace mitk { /** *\class DisplayInteractor *@brief Observer that manages the interaction with the display. * - * This includes the interaction of Zooming, Panning and Scrolling. + * This includes the interaction of Zooming, Panning, Scrolling and adjusting the LevelWindow. * * @ingroup Interaction **/ /** - * Inherits from mitk::EventObserver since it doesn't alter any data (only their representation), - * and its actions cannot be associated with a DataNode. + * Inherits from mitk::InteractionEventObserver since it doesn't alter any data (only their representation), + * and its actions cannot be associated with a DataNode. Also inherits from EventStateMachine */ - class MITK_CORE_EXPORT DisplayInteractor: public EventObserver + class MITK_CORE_EXPORT DisplayInteractor: public EventStateMachine, public InteractionEventObserver { public: - mitkClassMacro(DisplayInteractor, StateMachine); - itkNewMacro(Self); + mitkClassMacro(DisplayInteractor, EventStateMachine) + itkNewMacro(Self) /** * By this function the Observer gets notifier about new events. * Here it is adapted to pass the events to the state machine in order to use * its infrastructure. * It also checks if event is to be accepted when i already has been processed by a DataInteractor. */ - virtual void Notify(InteractionEvent::Pointer interactionEvent, bool isHandled); + virtual void Notify(InteractionEvent* interactionEvent, bool isHandled); protected: DisplayInteractor(); virtual ~DisplayInteractor(); /** * Derived function. * Connects the action names used in the state machine pattern with functions implemented within - * this EventObserver. This is only necessary here because the events are processed by the state machine. + * this InteractionEventObserver. This is only necessary here because the events are processed by the state machine. */ void ConnectActionsAndFunctions(); /** * Derived function. * Is executed when config object is set / changed. * Here it is used to read out the parameters set in the configuration file, * and set the member variables accordingly. */ virtual void ConfigurationChanged(); + + /** + * Derived function. + * Is executed when config object is set / changed. + * Here it is used to read out the parameters set in the configuration file, + * and set the member variables accordingly. + */ + virtual bool FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode); + /** * \brief Initializes an interaction, saves the pointers start position for further reference. */ virtual bool Init(StateMachineAction*, InteractionEvent*); /** * \brief Performs panning of the data set in the render window. */ virtual bool Move(StateMachineAction*, InteractionEvent*); /** * \brief Performs zooming relative to mouse/pointer movement. * * Behavior is determined by \see m_ZoomDirection and \see m_ZoomFactor. * */ virtual bool Zoom(StateMachineAction*, InteractionEvent*); /** * \brief Performs scrolling relative to mouse/pointer movement. * * Behavior is determined by \see m_ScrollDirection and \see m_AutoRepeat. * */ virtual bool Scroll(StateMachineAction*, InteractionEvent*); /** * \brief Scrolls one layer up */ virtual bool ScrollOneDown(StateMachineAction*, InteractionEvent*); /** * \brief Scrolls one layer down */ virtual bool ScrollOneUp(StateMachineAction*, InteractionEvent*); /** * \brief Adjusts the level windows relative to mouse/pointer movement. */ virtual bool AdjustLevelWindow(StateMachineAction*, InteractionEvent*); private: /** * \brief Coordinate of the pointer at begin of an interaction */ mitk::Point2D m_StartDisplayCoordinate; /** * \brief Coordinate of the pointer at begin of an interaction translated to mm unit */ mitk::Point2D m_StartCoordinateInMM; /** * \brief Coordinate of the pointer in the last step within an interaction. */ mitk::Point2D m_LastDisplayCoordinate; /** * \brief Current coordinates of the pointer. */ mitk::Point2D m_CurrentDisplayCoordinate; /** * \brief Modifier that defines how many slices are scrolled per pixel that the mouse has moved * * This modifier defines how many slices the scene is scrolled per pixel that the mouse cursor has moved. * By default the modifier is 4. This means that when the user moves the cursor by 4 pixels in Y-direction * the scene is scrolled by one slice. If the user has moved the the cursor by 20 pixels, the scene is * scrolled by 5 slices. * * If the cursor has moved less than m_IndexToSliceModifier pixels the scene is scrolled by one slice. */ int m_IndexToSliceModifier; /** Defines behavior at end of data set. * If set to true it will restart at end of data set from the beginning. */ bool m_AutoRepeat; /** * Defines scroll behavior. * Default is up/down movement of pointer performs scrolling */ std::string m_ScrollDirection; /** * Defines scroll behavior. * Default is up/down movement of pointer performs zooming */ std::string m_ZoomDirection; /** * Determines if the Observer reacts to events that already have been processed by a DataInteractor. * The default value is false. */ bool m_AlwaysReact; /** * Factor to adjust zooming speed. */ float m_ZoomFactor; }; } #endif diff --git a/Core/Code/Interactions/mitkDisplayPositionEvent.cpp b/Core/Code/Interactions/mitkDisplayPositionEvent.cpp index 1884421ad6..8ee766820b 100644 --- a/Core/Code/Interactions/mitkDisplayPositionEvent.cpp +++ b/Core/Code/Interactions/mitkDisplayPositionEvent.cpp @@ -1,76 +1,76 @@ /*=================================================================== 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 "mitkDisplayPositionEvent.h" #include "mitkBaseRenderer.h" mitk::DisplayPositionEvent::DisplayPositionEvent( mitk::BaseRenderer *sender, int type, int button, int buttonState, int key, const mitk::Point2D& displPosition ) : Event( sender, type, button, buttonState, key ), m_DisplayPosition( displPosition ), m_WorldPositionIsSet( false ), m_PickedObjectIsSet( false ) { } -const mitk::Point3D& mitk::DisplayPositionEvent::GetWorldPosition() const +mitk::Point3D &mitk::DisplayPositionEvent::GetWorldPosition() const { // Method performs position picking and sets world position if ( m_WorldPositionIsSet ) return m_WorldPosition; assert( m_Sender != NULL ); m_Sender->PickWorldPoint( m_DisplayPosition, m_WorldPosition ); m_WorldPositionIsSet = true; return m_WorldPosition; } mitk::DataNode *mitk::DisplayPositionEvent::GetPickedObjectNode() const { // Method performs object picking and sets both object and world position if ( m_PickedObjectIsSet ) { return m_PickedObjectNode; } assert( m_Sender != NULL ); m_PickedObjectNode = m_Sender->PickObject( m_DisplayPosition, m_WorldPosition ); m_PickedObjectIsSet = true; m_WorldPositionIsSet = true; return m_PickedObjectNode; } mitk::BaseData *mitk::DisplayPositionEvent::GetPickedObject() const { mitk::DataNode *node = this->GetPickedObjectNode(); if ( node != NULL ) { return node->GetData(); } else { return NULL; } } diff --git a/Core/Code/Interactions/mitkDisplayPositionEvent.h b/Core/Code/Interactions/mitkDisplayPositionEvent.h index 90ec265819..f3ed4377a3 100644 --- a/Core/Code/Interactions/mitkDisplayPositionEvent.h +++ b/Core/Code/Interactions/mitkDisplayPositionEvent.h @@ -1,80 +1,82 @@ /*=================================================================== 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 DISPLAYPOSITIONEVENT_H_HEADER_INCLUDED_C184F366 #define DISPLAYPOSITIONEVENT_H_HEADER_INCLUDED_C184F366 #include #include "mitkEvent.h" #include "mitkVector.h" #include "mitkDataNode.h" namespace mitk { /** * \brief Event that stores coordinates * * Stores display position of the mouse. * * If requested, the correspondent 3D world position in mm is calculated via * picking (delegated to the BaseRenderer). Additionally, the mitk::BaseData or * mitk::DataNode corresponding to the picked object in the (3D) scene can * be retrieved. * \ingroup Interaction + * \deprecatedSince{2013_03} mitk::DisplayPositionEvent is deprecated. Use mitk::InteractionPositionEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. */ class MITK_CORE_EXPORT DisplayPositionEvent : public Event { public: /** \brief Constructor with all necessary arguments. * * \param sender is the renderer that caused that event * \param type, button, buttonState, key: information from the Event * \param displPosition is the 2D Position of the mouse */ DisplayPositionEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, const Point2D& displPosition); const Point2D& GetDisplayPosition() const { return m_DisplayPosition; } void SetDisplayPosition(const Point2D& displPosition) { m_DisplayPosition = displPosition; } - const Point3D& GetWorldPosition() const; + Point3D& GetWorldPosition() const; /** Returns node with object at the current position (NULL if not applicable) */ mitk::DataNode *GetPickedObjectNode() const; /** Returns object at the current position (NULL if not applicable) */ mitk::BaseData *GetPickedObject() const; protected: Point2D m_DisplayPosition; mutable Point3D m_WorldPosition; mutable bool m_WorldPositionIsSet; mutable mitk::DataNode::Pointer m_PickedObjectNode; mutable bool m_PickedObjectIsSet; }; typedef DisplayPositionEvent MouseEvent; } // namespace mitk #endif /* DISPLAYPOSITIONozsiEVENT_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkEvent.h b/Core/Code/Interactions/mitkEvent.h index c68e7e05fe..a59464aee4 100644 --- a/Core/Code/Interactions/mitkEvent.h +++ b/Core/Code/Interactions/mitkEvent.h @@ -1,76 +1,80 @@ /*=================================================================== 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 EVENT_H_HEADER_INCLUDED_C1889CEE #define EVENT_H_HEADER_INCLUDED_C1889CEE #include namespace mitk { class BaseRenderer; //##Documentation //## @brief represents an Event with all its information //## //## Class, that stores mouse as well as key-events. Type stores the type of //## event, that has been activated (KeyPress, MouseMove...), Button and Key //## represent the cause of this event and ButtonState holds the Modifiers, //## that might have been pressed during the appearance of this event. //## Ether Button (Mouse) or Key (Keyboard) is set. if both are set //## accidentally then the button is accepted. //## @ingroup Interaction + /** + * \deprecatedSince{2013_03} mitk::Event is deprecated. Use mitk::InteractionEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT Event { public: //##Documentation //## @param sender Needed for DisplayCoordinateOperation in DisplayVectorInteractor....???? if not needed, then set on NULL //## @param type Type of Event: Mouse or Key Event? (look in mitkInteractionConst.h) //## @param button Mouse button //## @param buttonState Which other key has been pressed? (Mouse/Keyboard modifier-keys) //## @param key Pressed key Event(mitk::BaseRenderer* sender, int type, int button, int buttonState, int key); virtual ~Event(); mitk::BaseRenderer* GetSender() const; int GetType() const; int GetButton() const; int GetKey() const; bool operator==(const Event& event) const; int GetButtonState() const; protected: mitk::BaseRenderer* m_Sender; int m_Type; int m_Button; int m_ButtonState; int m_Key; }; } // namespace mitk #endif /* EVENT_H_HEADER_INCLUDED_C1889CEE */ diff --git a/Core/Code/Interactions/mitkEventConfig.cpp b/Core/Code/Interactions/mitkEventConfig.cpp index 80afa068ae..19c869a8c5 100755 --- a/Core/Code/Interactions/mitkEventConfig.cpp +++ b/Core/Code/Interactions/mitkEventConfig.cpp @@ -1,196 +1,196 @@ /*=================================================================== 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 "mitkEventConfig.h" #include #include #include #include #include #include "mitkEventFactory.h" #include "mitkInteractionEvent.h" #include "mitkInternalEvent.h" #include "mitkInteractionKeyEvent.h" #include "mitkInteractionEventConst.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include "mitkModuleResourceStream.h" #include "mitkModuleRegistry.h" namespace mitk { vtkStandardNewMacro(EventConfig); } -mitk::EventConfig::EventConfig() -:m_Errors(false) +mitk::EventConfig::EventConfig() : + m_Errors(false) { if (m_PropertyList.IsNull()) { m_PropertyList = PropertyList::New(); } } mitk::EventConfig::~EventConfig() { } void mitk::EventConfig::InsertMapping(EventMapping mapping) { for (EventListType::iterator it = m_EventList.begin(); it != m_EventList.end(); ++it) { if ((*it).interactionEvent->MatchesTemplate(mapping.interactionEvent)) { - MITK_INFO<< "Configuration overwritten:" << (*it).variantName; + //MITK_INFO<< "Configuration overwritten:" << (*it).variantName; m_EventList.erase(it); break; } } m_EventList.push_back(mapping); } /** * @brief Loads the xml file filename and generates the necessary instances. **/ bool mitk::EventConfig::LoadConfig(std::string fileName, std::string moduleName) { mitk::Module* module = mitk::ModuleRegistry::GetModule(moduleName); mitk::ModuleResource resource = module->GetResource("Interactions/" + fileName); if (!resource.IsValid()) { mitkThrow()<< ("Resource not valid. State machine pattern not found:" + fileName); } mitk::ModuleResourceStream stream(resource); this->SetStream(&stream); return this->Parse() && !m_Errors; } void mitk::EventConfig::StartElement(const char* elementName, const char **atts) { std::string name(elementName); if (name == xmlTagConfigRoot) { // } else if (name == xmlTagParam) { std::string name = ReadXMLStringAttribut(xmlParameterName, atts); std::string value = ReadXMLStringAttribut(xmlParameterValue, atts); m_PropertyList->SetStringProperty(name.c_str(), value.c_str()); } - else if (name == xmlTagInput) + else if (name == xmlTagEventVariant) { std::string eventClass = ReadXMLStringAttribut(xmlParameterEventClass, atts); - std::string eventVariant = ReadXMLStringAttribut(xmlParameterEventVariant, atts); + std::string eventVariant = ReadXMLStringAttribut(xmlParameterName, atts); // New list in which all parameters are stored that are given within the tag m_EventPropertyList = PropertyList::New(); m_EventPropertyList->SetStringProperty(xmlParameterEventClass.c_str(), eventClass.c_str()); m_EventPropertyList->SetStringProperty(xmlParameterEventVariant.c_str(), eventVariant.c_str()); m_CurrEventMapping.variantName = eventVariant; } else if (name == xmlTagAttribute) { // Attributes that describe an Input Event, such as which MouseButton triggered the event,or which modifier keys are pressed std::string name = ReadXMLStringAttribut(xmlParameterName, atts); std::string value = ReadXMLStringAttribut(xmlParameterValue, atts); m_EventPropertyList->SetStringProperty(name.c_str(), value.c_str()); } } void mitk::EventConfig::EndElement(const char* elementName) { std::string name(elementName); // At end of input section, all necessary infos are collected to created an interaction event. - if (name == xmlTagInput) + if (name == xmlTagEventVariant) { InteractionEvent::Pointer event = EventFactory::CreateEvent(m_EventPropertyList); if (event.IsNotNull()) { m_CurrEventMapping.interactionEvent = event; InsertMapping(m_CurrEventMapping); } else { MITK_WARN<< "EventConfig: Unknown Event-Type in config. Entry skipped: " << name; } } } std::string mitk::EventConfig::ReadXMLStringAttribut(std::string name, const char** atts) { if (atts) { const char** attsIter = atts; while (*attsIter) { if (name == *attsIter) { attsIter++; return *attsIter; } attsIter += 2; } } return std::string(); } -const mitk::PropertyList::Pointer mitk::EventConfig::GetAttributes() +mitk::PropertyList::Pointer mitk::EventConfig::GetAttributes() const { return m_PropertyList; } -std::string mitk::EventConfig::GetMappedEvent(InteractionEvent* interactionEvent) +std::string mitk::EventConfig::GetMappedEvent(InteractionEvent::Pointer interactionEvent) { // internal events are excluded from mapping if (interactionEvent->GetEventClass() == "InternalEvent") { - InternalEvent* internalEvent = dynamic_cast(interactionEvent); + InternalEvent* internalEvent = dynamic_cast(interactionEvent.GetPointer()); return internalEvent->GetSignalName(); } for (EventListType::iterator it = m_EventList.begin(); it != m_EventList.end(); ++it) { if ((*it).interactionEvent->MatchesTemplate(interactionEvent)) { return (*it).variantName; } } // if this part is reached, no mapping has been found, // so here we handle key events and map a key event to the string "Std" + letter/code // so "A" will be returned as "StdA" if (interactionEvent->GetEventClass() == "KeyEvent") { - InteractionKeyEvent* keyEvent = dynamic_cast(interactionEvent); + InteractionKeyEvent* keyEvent = dynamic_cast(interactionEvent.GetPointer()); return ("Std" + keyEvent->GetKey()); } return ""; } void mitk::EventConfig::ClearConfig() { m_EventList.clear(); } bool mitk::EventConfig::ReadXMLBooleanAttribut(std::string name, const char** atts) { std::string s = ReadXMLStringAttribut(name, atts); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s == "TRUE"; } diff --git a/Core/Code/Interactions/mitkEventConfig.h b/Core/Code/Interactions/mitkEventConfig.h index b79cbd0502..2f41a6640d 100755 --- a/Core/Code/Interactions/mitkEventConfig.h +++ b/Core/Code/Interactions/mitkEventConfig.h @@ -1,139 +1,144 @@ /*=================================================================== 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 mitkStateMachineConfig_h #define mitkStateMachineConfig_h #include #include -#include "itkObject.h" - -#include "itkObjectFactory.h" #include "mitkCommon.h" #include #include #include namespace mitk { class InteractionEvent; + class EventConfigReader: public vtkXMLParser + { + public: + + private: + }; + /** * \class EventConfig * \brief Configuration Object for Statemachines. * * Reads given config file, which translates specific user inputs (InteractionEvents) into EventVariants that can be processed * by the StateMachine. * Refer to \ref ConfigFileDescriptionSection . * * @ingroup Interaction **/ - class MITK_CORE_EXPORT EventConfig: public vtkXMLParser + class EventConfig: public vtkXMLParser { public: static EventConfig *New(); - vtkTypeMacro(EventConfig,vtkXMLParser); + vtkTypeMacro(EventConfig,vtkXMLParser) + typedef itk::SmartPointer EventType; /** - * @brief Loads XML resource - * - * Loads a XML resource file in the given module context. - * The files have to be placed in the Resources/Interaction folder of their respective module. - **/ + * @brief Loads XML resource + * + * Loads a XML resource file in the given module context. + * The files have to be placed in the Resources/Interaction folder of their respective module. + **/ bool LoadConfig(std::string fileName, std::string moduleName = "Mitk"); void ClearConfig(); /** * Returns a PropertyList that contains the properties set in the configuration file. * All properties are stored as strings. */ - const PropertyList::Pointer GetAttributes(); + PropertyList::Pointer GetAttributes() const; /** - * Checks if the config object has a definition for the given event. If it has the corresponding variant name is return, else + * Checks if the config object has a definition for the given event. If it has, the corresponding variant name is returned, else * an empty string is returned. * \note mitk::InternalEvents are handled differently. Their signal name is returned as event variant. So there is no need * to configure them in a config file. - * \note mitk::InteractionKeys my have a defined event variant, if this is the case, this function returns it. If no + * \note mitk::InteractionKeys may have a defined event variant, if this is the case, this function returns it. If no * such definition is found key events are mapped to Std + Key , so an 'A' will be return as 'StdA' . */ - std::string GetMappedEvent(InteractionEvent* interactionEvent); + std::string GetMappedEvent(EventType interactionEvent); protected: EventConfig(); virtual ~EventConfig(); /** * @brief Derived from XMLReader **/ void StartElement(const char* elementName, const char **atts); /** * @brief Derived from XMLReader **/ void EndElement(const char* elementName); private: /** * @brief Derived from XMLReader **/ std::string ReadXMLStringAttribut(std::string name, const char** atts); /** * @brief Derived from XMLReader **/ bool ReadXMLBooleanAttribut(std::string name, const char** atts); - /** * @brief List of all global properties of the config object. */ PropertyList::Pointer m_PropertyList; /** * @brief Temporal list of all properties of a Event. Used to parse an Input-Event and collect all parameters between the two - * and tags. + * and tags. */ PropertyList::Pointer m_EventPropertyList; struct EventMapping { std::string variantName; EventType interactionEvent; }; + /** * Checks if mapping with the same parameters already exists, if so, it is replaced, * else the new mapping added */ void InsertMapping(EventMapping mapping); typedef std::list EventListType; EventMapping m_CurrEventMapping; /** * Stores InteractionEvents and their corresponding VariantName */ EventListType m_EventList; bool m_Errors; // use member, because of inheritance from vtkXMLParser we can't return a success value for parsing the file. }; } // namespace mitk #endif /* mitkStateMachineConfig_h */ diff --git a/Core/Code/Interactions/mitkEventDescription.h b/Core/Code/Interactions/mitkEventDescription.h index 46fa633d3e..fc660a62df 100644 --- a/Core/Code/Interactions/mitkEventDescription.h +++ b/Core/Code/Interactions/mitkEventDescription.h @@ -1,60 +1,66 @@ /*=================================================================== 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 EVENTDESCRIPTION_H_HEADER_INCLUDED_C188FC4D #define EVENTDESCRIPTION_H_HEADER_INCLUDED_C188FC4D #include #include "mitkEvent.h" #include #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4251) #endif namespace mitk { //##Documentation //## @brief adds additional Information (Name and EventID) to an Event //## //## A name and an ID is added to the information of an event, so the event can //## be processed futher on. //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} EventDescription is deprecated. It will become obsolete. + * All necessary information is now store in the event classes derived from mitk::InteractionEvent . + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT EventDescription : public Event { public: EventDescription(int type, int button, int buttonState,int key, std::string name, int id); std::string GetName() const; int GetId() const; private: std::string m_Name; int m_Id; }; } // namespace mitk #ifdef _MSC_VER # pragma warning(pop) #endif #endif /* EVENTDESCRIPTION_H_HEADER_INCLUDED_C188FC4D */ diff --git a/Core/Code/Interactions/mitkEventFactory.cpp b/Core/Code/Interactions/mitkEventFactory.cpp index 2aeb5eeaa5..9fcc7d3078 100755 --- a/Core/Code/Interactions/mitkEventFactory.cpp +++ b/Core/Code/Interactions/mitkEventFactory.cpp @@ -1,222 +1,224 @@ /*=================================================================== 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 "mitkEventFactory.h" #include #include #include #include #include #include #include #include #include #include #include - -std::vector &mitk::EventFactory::split(const std::string &s, char delim, std::vector &elems) +namespace { - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) + std::vector &split(const std::string &s, char delim, std::vector &elems) { - elems.push_back(item); + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + elems.push_back(item); + } + return elems; } - return elems; -} -std::vector mitk::EventFactory::split(const std::string &s, char delim) -{ - std::vector elems; - return split(s, delim, elems); + std::vector split(const std::string &s, char delim) + { + std::vector < std::string > elems; + return split(s, delim, elems); + } } mitk::InteractionEvent::Pointer mitk::EventFactory::CreateEvent(PropertyList::Pointer list) { - // +// std::string eventClass, eventVariant; list->GetStringProperty(xmlParameterEventClass.c_str(), eventClass); list->GetStringProperty(xmlParameterEventVariant.c_str(), eventVariant); - // Query all possible attributes, if they are not present, set their default values. - // Position Events & Key Events +// Query all possible attributes, if they are not present, set their default values. +// Position Events & Key Events std::string strModifiers; ModifierKeys modifiers = NoKey; std::string strEventButton; MouseButtons eventButton = NoButton; std::string strButtonState; MouseButtons buttonState = NoButton; std::string strKey; std::string key; std::string strWheelDelta; int wheelDelta; std::string strSignalName = ""; Point2D pos; pos.Fill(0); - // Parse modifier information +// Parse modifier information if (list->GetStringProperty(xmlEventPropertyModifier.c_str(), strModifiers)) { std::vector mods = split(strModifiers, ','); for (std::vector::iterator it = mods.begin(); it != mods.end(); ++it) { std::transform((*it).begin(), (*it).end(), (*it).begin(), ::toupper); if (*it == "CTRL") { modifiers = modifiers | ControlKey; } else if (*it == "ALT") { modifiers = modifiers | AltKey; } else if (*it == "SHIFT") { modifiers = modifiers | ShiftKey; } else { MITK_WARN<< "mitkEventFactory: Invalid event modifier in config file :" << (*it); } } } - // Set EventButton +// Set EventButton if (list->GetStringProperty(xmlEventPropertyEventButton.c_str(), strEventButton)) { std::transform(strEventButton.begin(), strEventButton.end(), strEventButton.begin(), ::toupper); if (strEventButton == "MIDDLEMOUSEBUTTON") { eventButton = MiddleMouseButton; } else if (strEventButton == "LEFTMOUSEBUTTON") { eventButton = LeftMouseButton; } else if (strEventButton == "RIGHTMOUSEBUTTON") { eventButton = RightMouseButton; } else { MITK_WARN<< "mitkEventFactory: Invalid event button in config file: " << strEventButton; } } - // Parse ButtonStates +// Parse ButtonStates if (list->GetStringProperty(xmlEventPropertyButtonState.c_str(), strButtonState)) { std::vector mods = split(strButtonState, ','); for (std::vector::iterator it = mods.begin(); it != mods.end(); ++it) { std::transform((*it).begin(), (*it).end(), (*it).begin(), ::toupper); if (*it == "MIDDLEMOUSEBUTTON") { buttonState = buttonState | MiddleMouseButton; } else if (*it == "LEFTMOUSEBUTTON") { buttonState = buttonState | LeftMouseButton; } else if (*it == "RIGHTMOUSEBUTTON") { buttonState = buttonState | RightMouseButton; } else { MITK_WARN<< "mitkEventFactory: Invalid event buttonstate in config file:" << (*it); } } } - // Key +// Key if (!list->GetStringProperty(xmlEventPropertyKey.c_str(), strKey)) { key = ""; } else { key = strKey; } - // WheelDelta +// WheelDelta if (!list->GetStringProperty(xmlEventPropertyScrollDirection.c_str(), strWheelDelta)) { wheelDelta = 0; } else { std::transform(strWheelDelta.begin(), strWheelDelta.end(), strWheelDelta.begin(), ::toupper); if (strWheelDelta == "DOWN") { wheelDelta = -1; } else { wheelDelta = 1; } } - // Internal Signals Name +// Internal Signals Name list->GetStringProperty(xmlEventPropertySignalName.c_str(), strSignalName); /* * Here the objects are created */ mitk::InteractionEvent::Pointer event; std::transform(eventClass.begin(), eventClass.end(), eventClass.begin(), ::toupper); if (eventClass == "MOUSEPRESSEVENT") { // buttonstates incorporate the event button (as in Qt) buttonState = buttonState | eventButton; event = MousePressEvent::New(NULL, pos, buttonState, modifiers, eventButton); } else if (eventClass == "MOUSEMOVEEVENT") { event = MouseMoveEvent::New(NULL, pos, buttonState, modifiers); } else if (eventClass == "MOUSERELEASEEVENT") { event = MouseReleaseEvent::New(NULL, pos, buttonState, modifiers, eventButton); } else if (eventClass == "KEYEVENT") { event = InteractionKeyEvent::New(NULL, key, modifiers); } else if (eventClass == "MOUSEWHEELEVENT") { event = MouseWheelEvent::New(NULL, pos, buttonState, modifiers, wheelDelta); } else if (eventClass == "POSITIONEVENT") { event = InteractionPositionEvent::New(NULL, pos, "PositionEvent"); } else if (eventClass == "INTERNALEVENT") { event = InternalEvent::New(NULL, NULL, strSignalName); } else if (eventClass == "INTERACTIONEVENT") { event = InteractionEvent::New(NULL, strSignalName); } if (event.IsNull()) { MITK_WARN<< "Event couldn't be constructed. Please check your StateMachine patterns and config files\n for the following event class, which is not valid: " << eventClass; return NULL; } return event; } diff --git a/Core/Code/Interactions/mitkEventFactory.h b/Core/Code/Interactions/mitkEventFactory.h index f9d10c9bfd..3b4efe2504 100755 --- a/Core/Code/Interactions/mitkEventFactory.h +++ b/Core/Code/Interactions/mitkEventFactory.h @@ -1,52 +1,47 @@ /*=================================================================== 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 mitkEventFactory_h #define mitkEventFactory_h -#include "itkObject.h" -#include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEvent.h" #include "mitkPropertyList.h" #include namespace mitk { /** * \class EventFactory * \brief Generates InteractionEvent-Objects which are described by a PropertyList. - * This call is used by the EventConfig object to parse configuration files and create Events based on the xml description. + * This class is used by the EventConfig object to parse configuration files and create Events based on the xml description. * * \ingroup Interaction */ - class MITK_CORE_EXPORT EventFactory: public itk::Object + class MITK_CORE_EXPORT EventFactory { public: /** * Parses PropertyList and queries all possible Information. * If an attribute is not present the default value is used. * Finally the Event-Type is chosen by the ClassName property and the object is created using the collected information. */ static InteractionEvent::Pointer CreateEvent(PropertyList::Pointer eventDescription); - private: - static std::vector &split(const std::string &s, char delim, std::vector &elems); - static std::vector split(const std::string &s, char delim); }; } #endif /* mitkEventFactory_h */ diff --git a/Core/Code/Interactions/mitkEventInformer.h b/Core/Code/Interactions/mitkEventInformer.h index 24602e173c..7aa3432720 100644 --- a/Core/Code/Interactions/mitkEventInformer.h +++ b/Core/Code/Interactions/mitkEventInformer.h @@ -1,43 +1,43 @@ /*=================================================================== 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 mitkEventInformer_h #define mitkEventInformer_h -#include "mitkEventObserver.h" +#include "mitkInteractionEventObserver.h" #include "mitkInteractionEvent.h" #include namespace mitk { /** - * Serves as an interface for the micro service that takes care of informing/registering EventObserver + * Serves as an interface for the micro service that takes care of informing/registering InteractionEventObserver */ struct EventInformerService { virtual ~EventInformerService() { } - virtual void RegisterObserver(EventObserver::Pointer eventObserver) = 0; - virtual void UnRegisterObserver(EventObserver::Pointer eventObserver) = 0; + virtual void RegisterObserver(InteractionEventObserver::Pointer InteractionEventObserver) = 0; + virtual void UnRegisterObserver(InteractionEventObserver::Pointer InteractionEventObserver) = 0; virtual void NotifyObservers(InteractionEvent::Pointer interactionEvent) = 0; }; } /* namespace mitk */ US_DECLARE_SERVICE_INTERFACE(mitk::EventInformerService, "EventInformerService/1.0") #endif diff --git a/Core/Code/Interactions/mitkEventMapper.cpp b/Core/Code/Interactions/mitkEventMapper.cpp index 113851f947..23515bdbaf 100644 --- a/Core/Code/Interactions/mitkEventMapper.cpp +++ b/Core/Code/Interactions/mitkEventMapper.cpp @@ -1,708 +1,710 @@ /*=================================================================== 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. ===================================================================*/ /** * EventMapping: * This class maps the Events, usually given by the OS or here by QT, to a MITK internal EventId. * It loads all information from the xml-file (possible, understandable Events with the mitkEventID). * If an event appears, the method MapEvent is called with the event params. * This Method looks up the event params, and tries to find an mitkEventId to it. * If yes, then sends the event and the found ID to the globalStateMachine, which handles all * further operations of that event. * */ #include "mitkEventMapper.h" #include "mitkInteractionConst.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkGlobalInteraction.h" #include #include "mitkStandardFileLocations.h" //#include #include "mitkConfig.h" #include "mitkCoreObjectFactory.h" #include #include #include #include // us #include "mitkModule.h" #include "mitkModuleResource.h" #include "mitkModuleResourceStream.h" #include "mitkModuleRegistry.h" +#include +#include namespace mitk { vtkStandardNewMacro(EventMapper); } #ifdef MBI_INTERNAL_CONFERENCE #include #include #include #include #include #endif //MBI_INTERNAL_CONFERENCE //XML Event const std::string mitk::EventMapper::STYLE = "STYLE"; const std::string mitk::EventMapper::NAME = "NAME"; const std::string mitk::EventMapper::ID = "ID"; const std::string mitk::EventMapper::TYPE = "TYPE"; const std::string mitk::EventMapper::BUTTON = "BUTTON"; const std::string mitk::EventMapper::BUTTONSTATE = "BUTTONSTATE"; const std::string mitk::EventMapper::KEY = "KEY"; const std::string mitk::EventMapper::EVENTS = "events"; const std::string mitk::EventMapper::EVENT = "event"; mitk::EventMapper::EventDescriptionVec mitk::EventMapper::m_EventDescriptions; std::string mitk::EventMapper::m_XmlFileName; mitk::StateEvent mitk::EventMapper::m_StateEvent; std::string mitk::EventMapper::m_StyleName; struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; mitk::EventMapper::EventMapper() { //map with string to key for mapping string from xml-file to int m_EventConstMap["Type_None"] = mitk::Type_None; // invalid event m_EventConstMap["Type_Timer"] = mitk::Type_Timer; // timer event m_EventConstMap["Type_MouseButtonPress"] = mitk::Type_MouseButtonPress; // mouse button pressed m_EventConstMap["Type_MouseButtonRelease"] = mitk::Type_MouseButtonRelease; // mouse button released m_EventConstMap["Type_MouseButtonDblClick"] = mitk::Type_MouseButtonDblClick; // mouse button double click m_EventConstMap["Type_MouseMove"] = mitk::Type_MouseMove; // mouse move m_EventConstMap["Type_KeyPress"] = mitk::Type_KeyPress; // key pressed m_EventConstMap["Type_KeyRelease"] = mitk::Type_KeyRelease; // key released m_EventConstMap["Type_FocusIn"] = 8; // keyboard focus received m_EventConstMap["Type_FocusOut"] = 9; // keyboard focus lost m_EventConstMap["Type_Enter"] = 10; // mouse enters widget m_EventConstMap["Type_Leave"] = 11; // mouse leaves widget m_EventConstMap["Type_Paint"] = 12; // paint widget m_EventConstMap["Type_Move"] = 13; // move widget m_EventConstMap["Type_Resize"] = 14; // resize widget m_EventConstMap["Type_Create"] = 15; // after object creation m_EventConstMap["Type_Destroy"] = 16; // during object destruction m_EventConstMap["Type_Show"] = 17; // widget is shown m_EventConstMap["Type_Hide"] = 18; // widget is hidden m_EventConstMap["Type_Close"] = 19; // request to close widget m_EventConstMap["Type_Quit"] = 20; // request to quit application m_EventConstMap["Type_Reparent"] = 21; // widget has been reparented m_EventConstMap["Type_ShowMinimized"] = 22; // widget is shown minimized m_EventConstMap["Type_ShowNormal"] = 23; // widget is shown normal m_EventConstMap["Type_WindowActivate"] = 24; // window was activated m_EventConstMap["Type_WindowDeactivate"] = 25; // window was deactivated m_EventConstMap["Type_ShowToParent"] = 26; // widget is shown to parent m_EventConstMap["Type_HideToParent"] = 27; // widget is hidden to parent m_EventConstMap["Type_ShowMaximized"] = 28; // widget is shown maximized m_EventConstMap["Type_ShowFullScreen"] = 29; // widget is shown full-screen m_EventConstMap["Type_Accel"] = 30; // accelerator event m_EventConstMap["Type_Wheel"] = 31; // wheel event m_EventConstMap["Type_AccelAvailable"] = 32; // accelerator available event m_EventConstMap["Type_CaptionChange"] = 33; // caption changed m_EventConstMap["Type_IconChange"] = 34; // icon changed m_EventConstMap["Type_ParentFontChange"] = 35; // parent font changed m_EventConstMap["Type_ApplicationFontChange"] = 36;// application font changed m_EventConstMap["Type_ParentPaletteChange"] = 37; // parent palette changed m_EventConstMap["Type_ApplicationPaletteChange"] = 38;// application palette changed m_EventConstMap["Type_PaletteChange"] = 39; // widget palette changed m_EventConstMap["Type_Clipboard"] = 40; // internal clipboard event m_EventConstMap["Type_Speech"] = 42; // reserved for speech input m_EventConstMap["Type_SockAct"] = 50; // socket activation m_EventConstMap["Type_AccelOverride"] = 51; // accelerator override event m_EventConstMap["Type_DeferredDelete"] = 52; // deferred delete event m_EventConstMap["Type_DragEnter"] = 60; // drag moves into widget m_EventConstMap["Type_DragMove"] = 61; // drag moves in widget m_EventConstMap["Type_DragLeave"] = 62; // drag leaves or is cancelled m_EventConstMap["Type_Drop"] = 63; // actual drop m_EventConstMap["Type_DragResponse"] = 64; // drag accepted/rejected m_EventConstMap["Type_ChildInserted"] = 70; // new child widget m_EventConstMap["Type_ChildRemoved"] = 71; // deleted child widget m_EventConstMap["Type_LayoutHint"] = 72; // child min/max size changed m_EventConstMap["Type_ShowWindowRequest"] = 73; // widget's window should be mapped m_EventConstMap["Type_ActivateControl"] = 80; // ActiveX activation m_EventConstMap["Type_DeactivateControl"] = 81; // ActiveX deactivation m_EventConstMap["Type_ContextMenu"] = 82; // context popup menu m_EventConstMap["Type_IMStart"] = 83; // input method composition start m_EventConstMap["Type_IMCompose"] = 84; // input method composition m_EventConstMap["Type_IMEnd"] = 85; // input method composition end m_EventConstMap["Type_Accessibility"] = 86; // accessibility information is requested m_EventConstMap["Type_TabletMove"] = 87; // Wacom tablet event m_EventConstMap["Type_LocaleChange"] = 88; // the system locale changed m_EventConstMap["Type_LanguageChange"] = 89; // the application language changed m_EventConstMap["Type_LayoutDirectionChange"] = 90; // the layout direction changed m_EventConstMap["Type_Style"] = 91; // internal style event m_EventConstMap["Type_TabletPress"] = 92; // tablet press m_EventConstMap["Type_TabletRelease"] = 93; // tablet release // apparently not necessary, since the IDs can be assigned earlier (in the AddOns after they are generated in the driver) //m_EventConstMap["Type_TDMouseInput"] = mitk::Type_TDMouseInput; // 3D mouse input occured m_EventConstMap["Type_User"] = 1000; // first user event id m_EventConstMap["Type_MaxUser"] = 65535; // last user event id //ButtonState m_EventConstMap["BS_NoButton"] = mitk::BS_NoButton;//0x0000 m_EventConstMap["BS_LeftButton"] = mitk::BS_LeftButton;//0x0001 m_EventConstMap["BS_RightButton"] = mitk::BS_RightButton;//0x0002 m_EventConstMap["BS_MidButton"] = mitk::BS_MidButton;//0x0004 m_EventConstMap["BS_MouseButtonMask"] = mitk::BS_MouseButtonMask;//0x0007 m_EventConstMap["BS_ShiftButton"] = mitk::BS_ShiftButton;//0x0008 m_EventConstMap["BS_ControlButton"] = mitk::BS_ControlButton;//0x0010 m_EventConstMap["BS_AltButton"] = mitk::BS_AltButton;//0x0020 m_EventConstMap["BS_KeyButtonMask"] = mitk::BS_KeyButtonMask;//0x0038 m_EventConstMap["BS_Keypad"] = mitk::BS_Keypad;//0x4000 //Modifier m_EventConstMap["Mod_SHIFT"] = 0x00200000; m_EventConstMap["Mod_CTRL"] = 0x00400000; m_EventConstMap["Mod_ALT"] = 0x00800000; m_EventConstMap["Mod_MODIFIER_MASK"] = 0x00e00000; m_EventConstMap["Mod_UNICODE_ACCEL"] = 0x10000000; m_EventConstMap["Mod_ASCII_ACCEL"] = 0x10000000; //Key m_EventConstMap["Key_Escape"] = 0x1000; m_EventConstMap["Key_Tab"] = 0x1001; m_EventConstMap["Key_Backtab"] = 0x1002; m_EventConstMap["Key_BackTab"] = 0x1002; m_EventConstMap["Key_Backspace"] = 0x1003; m_EventConstMap["Key_BackSpace"] = 0x1003; m_EventConstMap["Key_Return"] = 0x1004; m_EventConstMap["Key_Enter"] = 0x1005; m_EventConstMap["Key_Insert"] = 0x1006; m_EventConstMap["Key_Delete"] = 0x1007; m_EventConstMap["Key_Pause"] = 0x1008; m_EventConstMap["Key_Print"] = 0x1009; m_EventConstMap["Key_SysReq"] = 0x100a; m_EventConstMap["Key_Home"] = 0x1010; m_EventConstMap["Key_End"] = 0x1011; m_EventConstMap["Key_Left"] = 0x1012; m_EventConstMap["Key_Up"] = 0x1013; m_EventConstMap["Key_Right"] = 0x1014; m_EventConstMap["Key_Down"] = 0x1015; m_EventConstMap["Key_Prior"] = 0x1016; m_EventConstMap["Key_PageUp"] = 0x1016; m_EventConstMap["Key_Next"] = 0x1017; m_EventConstMap["Key_PageDown"] = 0x1017; m_EventConstMap["Key_Shift"] = 0x1020; m_EventConstMap["Key_Control"] = 0x1021; m_EventConstMap["Key_Meta"] = 0x1022; m_EventConstMap["Key_Alt"] = 0x1023; m_EventConstMap["Key_CapsLock"] = 0x1024; m_EventConstMap["Key_NumLock"] = 0x1025; m_EventConstMap["Key_ScrollLock"] = 0x1026; m_EventConstMap["Key_F1"] = 0x1030; m_EventConstMap["Key_F2"] = 0x1031; m_EventConstMap["Key_F3"] = 0x1032; m_EventConstMap["Key_F4"] = 0x1033; m_EventConstMap["Key_F5"] = 0x1034; m_EventConstMap["Key_F6"] = 0x1035; m_EventConstMap["Key_F7"] = 0x1036; m_EventConstMap["Key_F8"] = 0x1037; m_EventConstMap["Key_F9"] = 0x1038; m_EventConstMap["Key_F10"] = 0x1039; m_EventConstMap["Key_F11"] = 0x103a; m_EventConstMap["Key_F12"] = 0x103b; m_EventConstMap["Key_F13"] = 0x103c; m_EventConstMap["Key_F14"] = 0x103d; m_EventConstMap["Key_F15"] = 0x103e; m_EventConstMap["Key_F16"] = 0x103f; m_EventConstMap["Key_F17"] = 0x1040; m_EventConstMap["Key_F18"] = 0x1041; m_EventConstMap["Key_F19"] = 0x1042; m_EventConstMap["Key_F20"] = 0x1043; m_EventConstMap["Key_F21"] = 0x1044; m_EventConstMap["Key_F22"] = 0x1045; m_EventConstMap["Key_F23"] = 0x1046; m_EventConstMap["Key_F24"] = 0x1047; m_EventConstMap["Key_F25"] = 0x1048; m_EventConstMap["Key_F26"] = 0x1049; m_EventConstMap["Key_F27"] = 0x104a; m_EventConstMap["Key_F28"] = 0x104b; m_EventConstMap["Key_F29"] = 0x104c; m_EventConstMap["Key_F30"] = 0x104d; m_EventConstMap["Key_F31"] = 0x104e; m_EventConstMap["Key_F32"] = 0x104f; m_EventConstMap["Key_F33"] = 0x1050; m_EventConstMap["Key_F34"] = 0x1051; m_EventConstMap["Key_F35"] = 0x1052; m_EventConstMap["Key_Super_L"] = 0x1053; m_EventConstMap["Key_Super_R"] = 0x1054; m_EventConstMap["Key_Menu"] = 0x1055; m_EventConstMap["Key_Hyper_L"] = 0x1056; m_EventConstMap["Key_Hyper_R"] = 0x1057; m_EventConstMap["Key_Help"] = 0x1058; m_EventConstMap["Key_Muhenkan"] = 0x1122; m_EventConstMap["Key_Henkan"] = 0x1123; m_EventConstMap["Key_Hiragana_Katakana"] = 0x1127; m_EventConstMap["Key_Zenkaku_Hankaku"] = 0x112A; m_EventConstMap["Key_Space"] = 0x20; m_EventConstMap["Key_Any"] = 0x20; m_EventConstMap["Key_Exclam"] = 0x21; m_EventConstMap["Key_QuoteDbl"] = 0x22; m_EventConstMap["Key_NumberSign"] = 0x23; m_EventConstMap["Key_Dollar"] = 0x24; m_EventConstMap["Key_Percent"] = 0x25; m_EventConstMap["Key_Ampersand"] = 0x26; m_EventConstMap["Key_Apostrophe"] = 0x27; m_EventConstMap["Key_ParenLeft"] = 0x28; m_EventConstMap["Key_ParenRight"] = 0x29; m_EventConstMap["Key_Asterisk"] = 0x2a; m_EventConstMap["Key_Plus"] = 0x2b; m_EventConstMap["Key_Comma"] = 0x2c; m_EventConstMap["Key_Minus"] = 0x2d; m_EventConstMap["Key_Period"] = 0x2e; m_EventConstMap["Key_Slash"] = 0x2f; m_EventConstMap["Key_0"] = 0x30; m_EventConstMap["Key_1"] = 0x31; m_EventConstMap["Key_2"] = 0x32; m_EventConstMap["Key_3"] = 0x33; m_EventConstMap["Key_4"] = 0x34; m_EventConstMap["Key_5"] = 0x35; m_EventConstMap["Key_6"] = 0x36; m_EventConstMap["Key_7"] = 0x37; m_EventConstMap["Key_8"] = 0x38; m_EventConstMap["Key_9"] = 0x39; m_EventConstMap["Key_Colon"] = 0x3a; m_EventConstMap["Key_Semicolon"] = 0x3b; m_EventConstMap["Key_Less"] = 0x3c; m_EventConstMap["Key_Equal"] = 0x3d; m_EventConstMap["Key_Greater"] = 0x3e; m_EventConstMap["Key_Question"] = 0x3f; m_EventConstMap["Key_At"] = 0x40; m_EventConstMap["Key_A"] = 0x41; m_EventConstMap["Key_B"] = 0x42; m_EventConstMap["Key_C"] = 0x43; m_EventConstMap["Key_D"] = 0x44; m_EventConstMap["Key_E"] = 0x45; m_EventConstMap["Key_F"] = 0x46; m_EventConstMap["Key_G"] = 0x47; m_EventConstMap["Key_H"] = 0x48; m_EventConstMap["Key_I"] = 0x49; m_EventConstMap["Key_J"] = 0x4a; m_EventConstMap["Key_K"] = 0x4b; m_EventConstMap["Key_L"] = 0x4c; m_EventConstMap["Key_M"] = 0x4d; m_EventConstMap["Key_N"] = 0x4e; m_EventConstMap["Key_O"] = 0x4f; m_EventConstMap["Key_P"] = 0x50; m_EventConstMap["Key_Q"] = 0x51; m_EventConstMap["Key_R"] = 0x52; m_EventConstMap["Key_S"] = 0x53; m_EventConstMap["Key_T"] = 0x54; m_EventConstMap["Key_U"] = 0x55; m_EventConstMap["Key_V"] = 0x56; m_EventConstMap["Key_W"] = 0x57; m_EventConstMap["Key_X"] = 0x58; m_EventConstMap["Key_Y"] = 0x59; m_EventConstMap["Key_Z"] = 0x5a; m_EventConstMap["Key_BracketLeft"] = 0x5b; m_EventConstMap["Key_Backslash"] = 0x5c; m_EventConstMap["Key_BracketRight"] = 0x5d; m_EventConstMap["Key_AsciiCircum"] = 0x5e; m_EventConstMap["Key_Underscore"] = 0x5f; m_EventConstMap["Key_QuoteLeft"] = 0x60; m_EventConstMap["Key_BraceLeft"] = 0x7b; m_EventConstMap["Key_Bar"] = 0x7c; m_EventConstMap["Key_BraceRight"] = 0x7d; m_EventConstMap["Key_AsciiTilde"] = 0x7e; m_EventConstMap["Key_nobreakspace"] = 0x0a0; m_EventConstMap["Key_exclamdown"] = 0x0a1; m_EventConstMap["Key_cent"] = 0x0a2; m_EventConstMap["Key_sterling"] = 0x0a3; m_EventConstMap["Key_currency"] = 0x0a4; m_EventConstMap["Key_yen"] = 0x0a5; m_EventConstMap["Key_brokenbar"] = 0x0a6; m_EventConstMap["Key_section"] = 0x0a7; m_EventConstMap["Key_diaeresis"] = 0x0a8; m_EventConstMap["Key_copyright"] = 0x0a9; m_EventConstMap["Key_ordfeminine"] = 0x0aa; m_EventConstMap["Key_guillemotleft"] = 0x0ab; m_EventConstMap["Key_notsign"] = 0x0ac; m_EventConstMap["Key_hyphen"] = 0x0ad; m_EventConstMap["Key_registered"] = 0x0ae; m_EventConstMap["Key_macron"] = 0x0af; m_EventConstMap["Key_degree"] = 0x0b0; m_EventConstMap["Key_plusminus"] = 0x0b1; m_EventConstMap["Key_twosuperior"] = 0x0b2; m_EventConstMap["Key_threesuperior"] = 0x0b3; m_EventConstMap["Key_acute"] = 0x0b4; m_EventConstMap["Key_mu"] = 0x0b5; m_EventConstMap["Key_paragraph"] = 0x0b6; m_EventConstMap["Key_periodcentered"] = 0x0b7; m_EventConstMap["Key_cedilla"] = 0x0b8; m_EventConstMap["Key_onesuperior"] = 0x0b9; m_EventConstMap["Key_masculine"] = 0x0ba; m_EventConstMap["Key_guillemotright"] = 0x0bb; m_EventConstMap["Key_onequarter"] = 0x0bc; m_EventConstMap["Key_onehalf"] = 0x0bd; m_EventConstMap["Key_threequarters"] = 0x0be; m_EventConstMap["Key_questiondown"] = 0x0bf; m_EventConstMap["Key_Agrave"] = 0x0c0; m_EventConstMap["Key_Aacute"] = 0x0c1; m_EventConstMap["Key_Acircumflex"] = 0x0c2; m_EventConstMap["Key_Atilde"] = 0x0c3; m_EventConstMap["Key_Adiaeresis"] = 0x0c4; m_EventConstMap["Key_Aring"] = 0x0c5; m_EventConstMap["Key_AE"] = 0x0c6; m_EventConstMap["Key_Ccedilla"] = 0x0c7; m_EventConstMap["Key_Egrave"] = 0x0c8; m_EventConstMap["Key_Eacute"] = 0x0c9; m_EventConstMap["Key_Ecircumflex"] = 0x0ca; m_EventConstMap["Key_Ediaeresis"] = 0x0cb; m_EventConstMap["Key_Igrave"] = 0x0cc; m_EventConstMap["Key_Iacute"] = 0x0cd; m_EventConstMap["Key_Icircumflex"] = 0x0ce; m_EventConstMap["Key_Idiaeresis"] = 0x0cf; m_EventConstMap["Key_ETH"] = 0x0d0; m_EventConstMap["Key_Ntilde"] = 0x0d1; m_EventConstMap["Key_Ograve"] = 0x0d2; m_EventConstMap["Key_Oacute"] = 0x0d3; m_EventConstMap["Key_Ocircumflex"] = 0x0d4; m_EventConstMap["Key_Otilde"] = 0x0d5; m_EventConstMap["Key_Odiaeresis"] = 0x0d6; m_EventConstMap["Key_multiply"] = 0x0d7; m_EventConstMap["Key_Ooblique"] = 0x0d8; m_EventConstMap["Key_Ugrave"] = 0x0d9; m_EventConstMap["Key_Uacute"] = 0x0da; m_EventConstMap["Key_Ucircumflex"] = 0x0db; m_EventConstMap["Key_Udiaeresis"] = 0x0dc; m_EventConstMap["Key_Yacute"] = 0x0dd; m_EventConstMap["Key_THORN"] = 0x0de; m_EventConstMap["Key_ssharp"] = 0x0df; m_EventConstMap["Key_agrave"] = 0x0e0; m_EventConstMap["Key_aacute"] = 0x0e1; m_EventConstMap["Key_acircumflex"] = 0x0e2; m_EventConstMap["Key_atilde"] = 0x0e3; m_EventConstMap["Key_adiaeresis"] = 0x0e4; m_EventConstMap["Key_aring"] = 0x0e5; m_EventConstMap["Key_ae"] = 0x0e6; m_EventConstMap["Key_ccedilla"] = 0x0e7; m_EventConstMap["Key_egrave"] = 0x0e8; m_EventConstMap["Key_eacute"] = 0x0e9; m_EventConstMap["Key_ecircumflex"] = 0x0ea; m_EventConstMap["Key_ediaeresis"] = 0x0eb; m_EventConstMap["Key_igrave"] = 0x0ec; m_EventConstMap["Key_iacute"] = 0x0ed; m_EventConstMap["Key_icircumflex"] = 0x0ee; m_EventConstMap["Key_idiaeresis"] = 0x0ef; m_EventConstMap["Key_eth"] = 0x0f0; m_EventConstMap["Key_ntilde"] = 0x0f1; m_EventConstMap["Key_ograve"] = 0x0f2; m_EventConstMap["Key_oacute"] = 0x0f3; m_EventConstMap["Key_ocircumflex"] = 0x0f4; m_EventConstMap["Key_otilde"] = 0x0f5; m_EventConstMap["Key_odiaeresis"] = 0x0f6; m_EventConstMap["Key_division"] = 0x0f7; m_EventConstMap["Key_oslash"] = 0x0f8; m_EventConstMap["Key_ugrave"] = 0x0f9; m_EventConstMap["Key_uacute"] = 0x0fa; m_EventConstMap["Key_ucircumflex"] = 0x0fb; m_EventConstMap["Key_udiaeresis"] = 0x0fc; m_EventConstMap["Key_yacute"] = 0x0fd; m_EventConstMap["Key_thorn"] = 0x0fe; m_EventConstMap["Key_ydiaeresis"] = 0x0ff; m_EventConstMap["Key_unknown"] = 0xffff; m_EventConstMap["Key_none"] = 0xffff; } mitk::EventMapper::~EventMapper() { } //##Documentation //## searches for the event in m_EventDescription and adds the corresponding eventID //## bool mitk::EventMapper::MapEvent(Event* event, GlobalInteraction* globalInteraction, int mitkPostedEventID ) { int eventID = mitkPostedEventID; if( mitkPostedEventID == 0 ) { //search the event in the list of event descriptions, if found, then take the number and produce a stateevent EventDescriptionVecIter iter; for (iter = m_EventDescriptions.begin(); iter!=m_EventDescriptions.end();iter++) { if (*iter == *event) break; } if (iter == m_EventDescriptions.end())//not found return false; eventID = (*iter).GetId(); } //set the Menger_Var m_StateEvent and send to StateMachine, which does everything further! m_StateEvent.Set( eventID, event ); /* Group and Object EventId: then EventMapper has the power to decide which operations hang together; each event causes n (n e N) operations (e.g. StateChanges, data-operations...). Undo must recall all these coherent operations, so all of the same objectId. But Undo has also the power to recall more operationsets, for example a set for building up a new object, so that a newly build up object is deleted after a Undo and not only the latest set point. The StateMachines::ExecuteAction have the power to descide weather a new GroupID has to be calculated (by example after the editing of a new object) A user interaction with the mouse is started by a mousePressEvent, continues with a MouseMove and finishes with a MouseReleaseEvent */ switch (event->GetType()) { case mitk::Type_MouseButtonPress://Increase mitk::OperationEvent::IncCurrObjectEventId(); break; case mitk::Type_MouseMove://same break; case mitk::Type_MouseButtonRelease://same break; case mitk::Type_User://same break; case mitk::Type_KeyPress://Increase mitk::OperationEvent::IncCurrObjectEventId(); break; default://increase mitk::OperationEvent::IncCurrObjectEventId(); } #ifdef MBI_INTERNAL_CONFERENCE //Conference - pass local events through if ( mitkPostedEventID == 0 ) { mitk::CoreObjectFactory::GetInstance()->MapEvent(event,eventID); } #endif //MBI_INTERNAL_CONFERENCE mitk::OperationEvent::ExecuteIncrement(); if ( globalInteraction != NULL ) { return globalInteraction->HandleEvent( &m_StateEvent ); } else { return mitk::GlobalInteraction::GetInstance()->HandleEvent(&m_StateEvent); } } bool mitk::EventMapper::LoadBehavior(std::string fileName) { if ( fileName.empty() ) return false; if (m_XmlFileName.length() > 0) { if (fileName.compare(m_XmlFileName) == 0) return true; // this is nothing bad, we already loaded this file. } this->SetFileName( fileName.c_str() ); m_XmlFileName = fileName.c_str(); return ( this->Parse() ); } bool mitk::EventMapper::LoadBehaviorString(std::string xmlString) { if ( xmlString.empty() ) return false; return ( this->Parse(xmlString.c_str(), xmlString.length()) ); } bool mitk::EventMapper::LoadStandardBehavior() { - Module* module = ModuleRegistry::GetModule("Mitk"); + Module* module = GetModuleContext()->GetModule(); if (module == NULL) { - mitkThrow()<< ("Module Mitk unavailable." ); + mitkThrow()<< ("Module context unavailable." ); return false; } ModuleResource resource = module->GetResource("Interactions/Legacy/StateMachine.xml"); if (!resource.IsValid()) { mitkThrow()<< ("Resource not valid. State machine pattern not found:Interactions/Legacy/StateMachine.xml" ); } mitk::ModuleResourceStream stream(resource); - std::string patternString((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); - return LoadBehaviorString(patternString); + this->SetStream(&stream); + return this->Parse(); } //##Documentation //## @brief converts the given const String declared in the xml-file //## to the defined const int inline int mitk::EventMapper::convertConstString2ConstInt(std::string input) { ConstMapIter tempIt = m_EventConstMap.find(input.c_str()); if (tempIt != m_EventConstMap.end()) { return (tempIt)->second; } //mitk::StatusBar::GetInstance()->DisplayText("Warning! from mitkEventMapper.cpp: Couldn't find matching Event Int from Event String in XML-File"); return -1;//for didn't find anything } void mitk::EventMapper::StartElement (const char *elementName, const char **atts) { if ( elementName == EVENT ) { // EventDescription(int type, int button, int buttonState,int key, std::string name, int id) EventDescription eventDescr( convertConstString2ConstInt( ReadXMLStringAttribut( TYPE, atts )), convertConstString2ConstInt( ReadXMLStringAttribut( BUTTON, atts )), ReadXMLIntegerAttribut( BUTTONSTATE, atts ), convertConstString2ConstInt( ReadXMLStringAttribut( KEY, atts )), ReadXMLStringAttribut( NAME, atts ), ReadXMLIntegerAttribut( ID, atts )); //check for a double entry unless it is an event for internal usage if (eventDescr.GetType()!= mitk::Type_User) { for (EventDescriptionVecIter iter = m_EventDescriptions.begin(); iter!=m_EventDescriptions.end(); iter++) { if (*iter == eventDescr) { MITK_DEBUG << "Event description " << eventDescr.GetName() << " already present! Skipping event description"; return; } } } m_EventDescriptions.push_back(eventDescr); } else if ( elementName == EVENTS ) m_StyleName = ReadXMLStringAttribut( STYLE, atts ); } std::string mitk::EventMapper::GetStyleName() const { return m_StyleName; } std::string mitk::EventMapper::ReadXMLStringAttribut( std::string name, const char** atts ) { if(atts) { const char** attsIter = atts; while(*attsIter) { if ( name == *attsIter ) { attsIter++; return *attsIter; } attsIter++; attsIter++; } } return std::string(); } int mitk::EventMapper::ReadXMLIntegerAttribut( std::string name, const char** atts ) { std::string s = ReadXMLStringAttribut( name, atts ); static const std::string hex = "0x"; int result; if ( s[0] == hex[0] && s[1] == hex[1] ) result = strtol( s.c_str(), NULL, 16 ); else result = atoi( s.c_str() ); return result; } void mitk::EventMapper::SetStateEvent(mitk::Event* event) { m_StateEvent.Set( m_StateEvent.GetId(), event ); } bool mitk::EventMapper::RefreshStateEvent(mitk::StateEvent* stateEvent) { //search the event within stateEvent in the list of event descriptions, if found adapt stateEvent ID EventDescriptionVecIter iter; for (iter = m_EventDescriptions.begin(); iter!=m_EventDescriptions.end(); iter++) { if (*iter == *(stateEvent->GetEvent())) break; } if (iter != m_EventDescriptions.end())//found { stateEvent->Set((*iter).GetId(), stateEvent->GetEvent()); return true; } else return false; return false; } void mitk::EventMapper::AddEventMapperAddOn(mitk::EventMapperAddOn* newAddOn) { bool addOnAlreadyAdded = false; for(AddOnVectorType::const_iterator it = this->m_AddOnVector.begin();it != m_AddOnVector.end();it++) { if(*it == newAddOn) { addOnAlreadyAdded = true; break; } } if(!addOnAlreadyAdded) { m_AddOnVector.push_back(newAddOn); MITK_INFO << "AddOn Count: " << m_AddOnVector.size(); } } void mitk::EventMapper::RemoveEventMapperAddOn(mitk::EventMapperAddOn* unusedAddOn) { for(AddOnVectorType::iterator it = this->m_AddOnVector.begin();it != m_AddOnVector.end();it++) { if(*it == unusedAddOn) { m_AddOnVector.erase(it); break; } } } diff --git a/Core/Code/Interactions/mitkEventMapper.h b/Core/Code/Interactions/mitkEventMapper.h index 169e23f1f9..e94f2d88f3 100644 --- a/Core/Code/Interactions/mitkEventMapper.h +++ b/Core/Code/Interactions/mitkEventMapper.h @@ -1,201 +1,208 @@ /*=================================================================== 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 EVENTMAPPER_H_HEADER_INCLUDED #define EVENTMAPPER_H_HEADER_INCLUDED #include #include #include #include #include #include #include namespace mitk { struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; typedef std::string msgString; //for friendship wor to set the stateevent after calculating class GlobalInteraction; class StateMachine; class StateEvent; class EventMapperAddOn; //##Documentation //## @brief Maps an Event to its description //## //## EventMapping: //## This class mapps the Events, usually given by the OS or here by QT, to a MITK internal EventId. //## It loads all information from the xml-file (possible, understandable Events with the mitkEventID). //## If an event appears, the method MapEvent is called with the event params. //## This Method looks up the event params, and tries to find an mitkEventId to it. //## If yes, then sends the event and the found ID to the globalStateMachine, which handles all //## further operations of that event. //## For Undo-Mechanism a statechanging StateMachine::HandleEvent is connected to an ObjectEventID and an GroupEventId. //## That way a fine an raw Undo is possible (fine for ObjectID by ObjectID, raw for GroupID for GroupID) //## Here the ObjectEventID gets increased, //## not the GroupEventId(must get increased by a StateMachine, that has the information when a new Group of operation starts) //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} EventMapper is deprecated. It will become obsolete. + * Mapping from Qt to MITK events is performed now by mitk::QmitkRenderWindow . + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT EventMapper : public vtkXMLParser { public: static EventMapper *New(); vtkTypeMacro(EventMapper,vtkXMLParser); typedef std::vector EventDescriptionVec; typedef std::vector::iterator EventDescriptionVecIter; typedef std::map ConstMap; typedef std::map::iterator ConstMapIter; typedef std::vector< itk::SmartPointer > AddOnVectorType; //##Documentation //## searches the Event in m_EventDescription //## and if included transmits the event to globalInteraction. //## If specified, a custom instance of GlobalInteraction will be used, //## otherwise the method will retrieve the default (singleton) instance. //## the optional parameter should be used in a conference to avoid a //## feedback static bool MapEvent(Event* event, GlobalInteraction* globalInteraction = NULL, int mitkPostedEventID=0 ); //##Documentation //## Searches for the event within stateEvent in the internal map of event descriptions //## If entry found the stateEvent ID is adapted //## maps the Event in m_EventDescription with the ID //## and if found returns true, //## if not found it returns false static bool RefreshStateEvent(StateEvent* stateEvent); //##Documentation //## loads an XML-File containing events and adds definition to internal mapping list //## //## Several files can be loaded. Event descriptions have to be unique or a warning will be displayed. //## If the same file is loaded twice, //## it will only be parsed the first time. //## If a file A, then a file B and then file A is to be loaded, warnings //## will be displayed when loading file A the second time. bool LoadBehavior(std::string fileName); //##Documentation //## loads Events into m_EventDescriptions from xml string //## also involved: EventMapper::startEvent(...) bool LoadBehaviorString(std::string xmlString); //##Documentation //## Try to load standard behavior file "StateMachine.xml" //## //## Search strategy: //## \li try environment variable "MITKCONF" (path to "StateMachine.xml") //## \li try "./StateMachine.xml" //## \li try via source directory (using MITKROOT from cmake-created //## mitkConfig.h) "MITKROOT/Interactions/mitkBaseInteraction/StateMachine.xml" bool LoadStandardBehavior(); //##Documentation //## reads a Tag from an XML-file //## adds Events to m_EventDescription std::string GetStyleName() const; //friendship because of SetStateEvent for computing WorldCoordinates friend class mitk::GlobalInteraction; /** * @brief adds a new EventMapper addon */ void AddEventMapperAddOn(mitk::EventMapperAddOn* newAddOn); /** * @brief removes an EventMapper addon */ void RemoveEventMapperAddOn(mitk::EventMapperAddOn* unusedAddOn); protected: EventMapper(); ~EventMapper(); //##Documentation //##@brief method only for GlobalInteraction to change the Event (from DiplayPositionEvent to PositionEvent) static void SetStateEvent(Event* event); private: //##Documentation //## @brief method used in XLM-Reading; gets called when a start-tag is read void StartElement (const char *elementName, const char **atts); //##Documentation //## @brief reads an XML-String-Attribute std::string ReadXMLStringAttribut( std::string name, const char** atts); //##Documentation //## @brief reads an XML-Integer-Attribute int ReadXMLIntegerAttribut( std::string name, const char** atts ); //##Documentation //## @brief converts the strings given by the XML-Behaviour-File to int inline int convertConstString2ConstInt(std::string input); //static std::string Convert2String(int input); //static std::string Convert2String(double input); //static std::string Convert2String(float input); //##Documentation //## @brief maps the strings to int for convertion from XML-Behaviour-File ConstMap m_EventConstMap; //##Documentation //## @brief stores the information for the connection between QT-Events and the internal EventId. //## gets this information from xml-File static EventDescriptionVec m_EventDescriptions; static std::string m_XmlFileName; static StateEvent m_StateEvent; //##Documentation //## @brief stores the name of the Event-Style loaded static std::string m_StyleName; static const std::string STYLE; static const std::string NAME; static const std::string ID; static const std::string TYPE; static const std::string BUTTON; static const std::string BUTTONSTATE; static const std::string KEY; static const std::string EVENTS; static const std::string EVENT; /** * @brief all available EventMapper addons consisting of one or more input devices */ AddOnVectorType m_AddOnVector; }; } // namespace mitk #endif /* EVENTMAPPER_H_HEADER_INCLUDED_C187864A */ diff --git a/Core/Code/Interactions/mitkEventStateMachine.cpp b/Core/Code/Interactions/mitkEventStateMachine.cpp index fe64b217c4..233f19ddd7 100644 --- a/Core/Code/Interactions/mitkEventStateMachine.cpp +++ b/Core/Code/Interactions/mitkEventStateMachine.cpp @@ -1,148 +1,148 @@ /*=================================================================== 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 "mitkEventStateMachine.h" #include "mitkStateMachineContainer.h" #include "mitkInteractionEvent.h" #include "mitkStateMachineAction.h" #include "mitkStateMachineTransition.h" #include "mitkStateMachineState.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include "mitkModuleResourceStream.h" #include "mitkModuleRegistry.h" -mitk::EventStateMachine::EventStateMachine() +mitk::EventStateMachine::EventStateMachine() : + m_StateMachineContainer(NULL), m_CurrentState(NULL) { - m_StateMachineContainer = NULL; - m_CurrentState = NULL; } -bool mitk::EventStateMachine::LoadStateMachine(std::string filename, std::string moduleName) +bool mitk::EventStateMachine::LoadStateMachine(const std::string filename, const std::string moduleName) { if (m_StateMachineContainer != NULL) { m_StateMachineContainer->Delete(); } m_StateMachineContainer = StateMachineContainer::New(); - if (m_StateMachineContainer->LoadBehavior(filename,moduleName)) + if (m_StateMachineContainer->LoadBehavior(filename, moduleName)) { m_CurrentState = m_StateMachineContainer->GetStartState(); // clear actions map ,and connect all actions as declared in sub-class m_ActionFunctionsMap.clear(); ConnectActionsAndFunctions(); return true; } else { MITK_WARN<< "Unable to load StateMachine from file: " << filename; return false; } } mitk::EventStateMachine::~EventStateMachine() { if (m_StateMachineContainer != NULL) { m_StateMachineContainer->Delete(); } } -void mitk::EventStateMachine::AddActionFunction(std::string action, mitk::TActionFunctor* functor) +void mitk::EventStateMachine::AddActionFunction(const std::string action, mitk::TActionFunctor* functor) { if (!functor) return; // make sure double calls for same action won't cause memory leaks delete m_ActionFunctionsMap[action]; m_ActionFunctionsMap[action] = functor; } bool mitk::EventStateMachine::HandleEvent(InteractionEvent* event, DataNode* dataNode) { if (!FilterEvents(event, dataNode)) { return false; } // check if the current state holds a transition that works with the given event. StateMachineTransition::Pointer transition = m_CurrentState->GetTransition(event->GetEventClass(), MapToEventVariant(event)); if (transition.IsNotNull()) { // iterate over all actions in this transition and execute them ActionVectorType actions = transition->GetActions(); bool success = false; for (ActionVectorType::iterator it = actions.begin(); it != actions.end(); ++it) { success |= ExecuteAction(*it, event); // treat an event as handled if at least one of the actions is executed successfully } if (success || actions.empty()) // an empty action list is always successful { // perform state change m_CurrentState = transition->GetNextState(); //MITK_INFO<< "StateChange: " << m_CurrentState->GetName(); } return success; } else { return false; // no transition found that matches event } } void mitk::EventStateMachine::ConnectActionsAndFunctions() { MITK_WARN<< "ConnectActionsAndFunctions in DataInteractor not implemented.\n DataInteractor will not be able to process any events."; } bool mitk::EventStateMachine::ExecuteAction(StateMachineAction* action, InteractionEvent* event) { if (action == NULL) { return false; } // Maps Action-Name to Functor and executes DoAction on Functor. TActionFunctor* actionFunction = m_ActionFunctionsMap[action->GetActionName()]; if (actionFunction == NULL) { return false; } bool retVal = actionFunction->DoAction(action, event); return retVal; } mitk::StateMachineState* mitk::EventStateMachine::GetCurrentState() { return m_CurrentState.GetPointer(); } bool mitk::EventStateMachine::FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode) { - if (dataNode == NULL) { - MITK_WARN << "EventStateMachine: Empty DataNode received along with this Event " << interactionEvent; + if (dataNode == NULL) + { + MITK_WARN<< "EventStateMachine: Empty DataNode received along with this Event " << interactionEvent; return false; } bool visible = false; if (dataNode->GetPropertyList()->GetBoolProperty("visible", visible) == false) { //property doesn't exist return false; } return visible; } diff --git a/Core/Code/Interactions/mitkEventStateMachine.h b/Core/Code/Interactions/mitkEventStateMachine.h index 26266be58d..f4152a0a50 100644 --- a/Core/Code/Interactions/mitkEventStateMachine.h +++ b/Core/Code/Interactions/mitkEventStateMachine.h @@ -1,176 +1,176 @@ /*=================================================================== 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 MITKEVENTSTATEMACHINE_H_ #define MITKEVENTSTATEMACHINE_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" -#include "mitkEventHandler.h" +#include "mitkInteractionEventHandler.h" #include #include namespace mitk { class StateMachineContainer; class StateMachineAction; class InteractionEvent; class StateMachineState; class DataNode; /** * \class TActionFunctor * \brief Base class of ActionFunctors, to provide an easy to connect actions with functions. */ class MITK_CORE_EXPORT TActionFunctor { public: virtual bool DoAction(StateMachineAction*, InteractionEvent*)=0; virtual ~TActionFunctor() { } }; /** * \class TSpecificActionFunctor * Specific implementation of ActionFunctor class, implements a reference to the function which is to be executed. It takes two arguments: * StateMachineAction - the action by which the function call is invoked, InteractionEvent - the event that caused the transition. */ template class TSpecificActionFunctor: public TActionFunctor { public: TSpecificActionFunctor(T* object, bool (T::*memberFunctionPointer)(StateMachineAction*, InteractionEvent*)) : m_Object(object), m_MemberFunctionPointer(memberFunctionPointer) { } virtual ~TSpecificActionFunctor() { } virtual bool DoAction(StateMachineAction* action, InteractionEvent* event) { return (*m_Object.*m_MemberFunctionPointer)(action, event);// executes member function } private: T* m_Object; bool (T::*m_MemberFunctionPointer)(StateMachineAction*, InteractionEvent*); }; /** Macro that can be used to connect a StateMachineAction with a function. * It assumes that there is a typedef Classname Self in classes that use this macro, as is provided by e.g. mitkClassMacro */ #define CONNECT_FUNCTION(a, f) \ EventStateMachine::AddActionFunction(a, new TSpecificActionFunctor(this, &Self::f)); /** * \class EventStateMachine * * \brief Super-class that provides the functionality of a StateMachine to DataInteractors. * * A state machine is created by loading a state machine pattern. It consists of states, transitions and action. * The state represent the current status of the interaction, transitions are means to switch between states. Each transition * is triggered by an event and it is associated with actions that are to be executed when the state change is performed. * */ - class MITK_CORE_EXPORT EventStateMachine: public virtual EventHandler + class MITK_CORE_EXPORT EventStateMachine : public mitk::InteractionEventHandler { public: - mitkClassMacro(EventStateMachine, EventHandler); - itkNewMacro(Self); + mitkClassMacro(EventStateMachine, InteractionEventHandler) + itkNewMacro(Self) typedef std::map ActionFunctionsMapType; typedef itk::SmartPointer StateMachineStateType; /** * @brief Loads XML resource * * Loads a XML resource file in the given module context. * Default is the Mitk module (core). * The files have to be placed in the Resources/Interaction folder of their respective module. **/ - bool LoadStateMachine(std::string filename, std::string moduleName="Mitk"); + bool LoadStateMachine(const std::string filename, const std::string moduleName="Mitk"); /** * Receives Event from Dispatcher. * Event is mapped using the EventConfig Object to a variant, then it is checked if the StateMachine is listening for * such an Event. If this is the case, the transition to the next state it performed and all actions associated with the transition executed, * and true is returned to the caller. * If the StateMachine can't handle this event false is returned. * Attention: * If a transition is associated with multiple actions - "true" is returned if one action returns true, * and the event is treated as HANDLED even though some actions might not have been executed! So be sure that all actions that occur within * one transitions have the same conditions. */ bool HandleEvent(InteractionEvent* event, DataNode* dataNode); protected: EventStateMachine(); virtual ~EventStateMachine(); /** * Connects action from StateMachine (String in XML file) with a function that is called when this action is to be executed. */ - void AddActionFunction(std::string action, TActionFunctor* functor); + void AddActionFunction(const std::string action, TActionFunctor* functor); StateMachineState* GetCurrentState(); /** * Is called after loading a statemachine. * Overwrite this function in specific interactor implementations. * Connect actions and functions using the CONNECT_FUNCTION macro within this function. */ virtual void ConnectActionsAndFunctions(); /** * Looks up function that is associated with action and executes it. * To implement your own execution scheme overwrite this in your DataInteractor. */ virtual bool ExecuteAction(StateMachineAction* action, InteractionEvent* interactionEvent); /** * Implements filter scheme for events. * Standard implementation accepts events from 2d and 3d windows, * and rejects events if DataNode is not visible. * \return true if event is accepted, else false * * Overwrite this function to adapt for your own needs, for example to filter out events from * 3d windows like this: \code bool mitk::EventStateMachine::FilterEvents(InteractionEvent* interactionEvent, DataNode*dataNode) { return interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D; // only 2D mappers } \endcode * or to enforce that the interactor only reacts when the corresponding DataNode is selected in the DataManager view.. */ virtual bool FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode); private: StateMachineContainer* m_StateMachineContainer; // storage of all states, action, transitions on which the statemachine operates. ActionFunctionsMapType m_ActionFunctionsMap; // stores association between action string StateMachineStateType m_CurrentState; }; } /* namespace mitk */ #endif /* MITKEVENTSTATEMACHINE_H_ */ diff --git a/Core/Code/Interactions/mitkGlobalInteraction.h b/Core/Code/Interactions/mitkGlobalInteraction.h index 973ebf51da..816a712f29 100755 --- a/Core/Code/Interactions/mitkGlobalInteraction.h +++ b/Core/Code/Interactions/mitkGlobalInteraction.h @@ -1,317 +1,323 @@ /*=================================================================== 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 GLOBALINTERACTION_H_HEADER_INCLUDED_C152938A #define GLOBALINTERACTION_H_HEADER_INCLUDED_C152938A #include "mitkFocusManager.h" #include #include "mitkStateMachineFactory.h" #include "mitkEventMapper.h" #include "mitkInteractor.h" namespace mitk { class PositionEvent; //##Documentation //## @brief handles all global Events //## //## superior statemachine, that spreads the events to all other interactors //## //## Initialization //## Attention: GlobalInteraction must be initialized by the Initialize() method //## before usage by giving it an XML scheme. Possibilities are giving it an empty string (default), //## the filename of an XML file or the actual XML content as std::string. If an empty string is given, //## the content is tried to be loaded from the default file location. //## //## Concept of sending events: //## In this concept of interaction, the statemachines can be divided into two main statemachines: //## Listeners and interactors. //## Listeners only receive the event to process it, but don't change any data. They want to listen to all events. //## Interactors do change data according to the received event. They do not need to receive all events, only //## those they are interested in. //## Additional to that a EVENT_NOTIFICATION_POLICY can be set. This can be either INFORM_MULTIPLE (the event is passed //## to all listeners) or INFORM_ONE (event is passed to the listener which can handle the event best and only to this one). //## //## To divide these two types of statemachine this class holds three lists and two maps: //## m_ListenerList, m_InteractorList, m_SelectedList and m_InteractorRelevanceMap and m_ListenerRelevanceMap //## The list m_ListenerList holds all listeners. //## m_InteractorList holds all interactors, and the List m_SelectedList holds all machines, that were set to SELECTED or SUBSELECTED. //## m_InteractorRelevanceMap and m_ListenerRelevanceMap map values returned from CanHandleEvent to the asked Interactors and Listeners. //## Through m_InteractorRelevanceMap stepping through interactors, that were not selected and could handle that event, can be done. //## Through m_ListenerRelevanceMap the listener which can handle the event best can be determined. In case of the INFORM_ONE notification policy //## the event is passed to just this listener //## //## First the listeners are informed with the event. //## Then the selected or subselected interactors are asked if they can handle that event. //## They can handle it, if the mode of the interactor after HandleEvent(..) is still in SMSELECTED or SMSUBSELECTED. //## They can't handle it, if the mode changed to SMDESELECTED. Then the interactor is removed from the selected-list. //## In that case, all interactors are asked to calculate and return their area of Relevance. //## An iterator is held on one interactor in the map. With the iterator, the map can be looped through so //## so that several geometric objects, that lie on top of each other, can be selected. //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} GlobalInteraction is deprecated. It is replaced by mitk::Dispatcher. + * Please use the new implementation described in \see DataInteractionPage . + */ + class MITK_CORE_EXPORT GlobalInteraction : public StateMachine { public: mitkClassMacro(GlobalInteraction, StateMachine); itkNewMacro(Self); typedef std::vector StateMachineList; typedef std::vector StateMachineCPointerList; typedef StateMachineList::iterator StateMachineListIter; typedef StateMachineCPointerList::iterator StateMachineCPointerListIter; typedef std::vector InteractorList; typedef InteractorList::iterator InteractorListIter; typedef std::multimap > InteractorMap; typedef std::multimap > StateMachineMap; typedef InteractorMap::iterator InteractorMapIter; typedef StateMachineMap::iterator StateMachineMapIter; /** * Enum for setting the event notification policy of the GlobalInteraction. */ enum EVENT_NOTIFICATION_POLICY { INFORM_MULTIPLE, /** For setting that all registered listeners are informed */ INFORM_ONE /** For setting that just the listener that can handle the event best is informed */ }; //##Documentation //## @brief add an Interactor to the list of all interactors that are asked for handling an event //## //## returns true in case of success void AddInteractor(Interactor* interactor); //##Documentation //## @brief remove a certain Interactor from the set of interactors that are asked for handling an event //## //## returns true in case of success bool RemoveInteractor(Interactor* interactor); //##Documentation //## @brief returns true, if the given interactor is already added to the Interactor-List bool InteractorRegistered (Interactor* interactor); //##Documentation //## @brief add a Listener to the list of all Listeners that are informed of an event //## //## returns true in case of success void AddListener(StateMachine* listener); //##Documentation //## @brief remove a certain Listener from the set of Listeners that are informed of an event //## //## returns true in case of success bool RemoveListener(StateMachine* listener); //##Documentation //## @brief returns true, if the given interactor is already added to the Listener-List bool ListenerRegistered (StateMachine* listener); //##Documentation //## @brief adds an element in the list in FocusManager //## //## true if success, false if the element is already in list bool AddFocusElement(FocusManager::FocusElement* element); //##Documentation //## @brief Removes an element in FocusManager //## //## true if success, false if the element was not in the list bool RemoveFocusElement(FocusManager::FocusElement* element); //##Documentation //## @brief Returns the focused Element in FocusManager FocusManager::FocusElement* GetFocus(); //##Documentation //## @brief Sets the given Element to focused //## //## returns true if the given element was found and focused bool SetFocus(FocusManager::FocusElement* element); //##Documentation //## @brief Returns the pointer to the FocusManager //## //## to add the observer for an event FocusManager* GetFocusManager(); //##Documentation //## @brief Returns the pointer to the EventMapper //## //## to add an addon EventMapper* GetEventMapper(); /** * @brief Return StateMachineFactory **/ StateMachineFactory* GetStateMachineFactory(); /** * @brief Returns the StartState of the StateMachine with the name type; * * Asks member StateMachineFactory for the StartState. * Returns NULL if no entry with name type is found. **/ State* GetStartState(const char* type); //##Documentation //## @brief Returns the global (singleton) instance of //## GlobalInteraction. Create it, if it does not exist. static GlobalInteraction* GetInstance(); //##Documentation //## @brief Initializes the global (singleton) instance of //## GlobalInteraction via an XML string. Must! be done before usage. Can be done only once. //## Can be used with an empty string (default), a file name with path, or the actual XML content as string. bool Initialize(const char* globalInteractionName, const std::string XMLBehaviorInput = ""); //##Documentation //## @brief Check if GlobalInteraction has already been initialized. Init must! be done before usage. bool IsInitialized() {return m_IsInitialized;} /** * @brief Set the policy of how the global interaction informs listeners and interactors * * INFORM_MULTIPLE broadcasts the event to all listeners and interactors that can handle the event * INFORM_ONE only informs the listener or interactor which can handle the event best **/ void SetEventNotificationPolicy(EVENT_NOTIFICATION_POLICY); /** * Return the current set eventspreading policy * @returns the current event spreading policy **/ EVENT_NOTIFICATION_POLICY GetEventNotificationPolicy() const; //so that the interactors can call AddToSelectedInteractors() and RemoveFromSelectedInteractors() friend class Interactor; protected: /** * @brief Default Constructor with type to load the StateMachinePattern of the StateMachine * @param XMLbehaviorFile the file which contains the statemachine and event patterns * @param type the name of the statemachine pattern this class shall use **/ GlobalInteraction(); /** * @brief Default destructor. **/ ~GlobalInteraction(); virtual bool ExecuteAction(Action* action, mitk::StateEvent const* stateEvent); /* *@brief adds the given interactor to the list of selected interactors. * This list is asked first to handle an event. */ virtual bool AddToSelectedInteractors(Interactor* interactor); /* *@brief removes the given interactor from the list of selected interactors * This list is asked first to handle an event. */ virtual bool RemoveFromSelectedInteractors(Interactor* interactor); private: //##Documentation //##@brief informing all statemachines that are held in the list m_ListenerList void InformListeners(mitk::StateEvent const* stateEvent); //##Documentation //##@brief asking the selected Interactor if an event can be handled //## //## returns false if no Interactor could handle the event bool AskSelected(mitk::StateEvent const* stateEvent); //##Documentation //##@brief asking next interactor of m_RelevanceMap bool AskCurrentInteractor(mitk::StateEvent const* stateEvent); //##Documentation //##@brief filling m_InteractorRelevanceMap //## //## @ params threshold: if the calculated Relevance value is above threshold, then add it to the map void FillInteractorRelevanceMap(mitk::StateEvent const* stateEvent, float threshold); //##Documentation //##@brief filling m_ListenerRelevanceMap //## //## @ params threshold: if the calculated Relevance value is above threshold, then add it to the map void FillListenerRelevanceMap(mitk::StateEvent const* stateEvent, float threshold); void RemoveFlaggedListeners(); StateMachineCPointerList m_ListenersFlaggedForRemoval; //##Documentation //## @brief list of all listening statemachines, that want to receive all events StateMachineList m_ListenerList; //##Documentation //## @brief list of all interactors (statemachine, that change data) InteractorList m_InteractorList; //##Documentation //## @brief list of all interactors, that are in Mode SELECTED or SUBSELECTED InteractorList m_SelectedList; //##Documentation //## @brief map for sorting all interactors by the value returned from CanHandleEvent(..). //## //## With that list certain interactors can be looped through like diving through layers InteractorMap m_InteractorRelevanceMap; //##Documentation //## @brief map for sorting all listeners by the value returned from CanHandleEvent(..). //## //## With that list certain listeners can be looped through like diving through layers StateMachineMap m_ListenerRelevanceMap; //##Documentation //## @brief iterator on an entry in m_RelevanceMap for stepping through interactors InteractorMapIter m_CurrentInteractorIter; //##Documentation //## @brief holds a list of BaseRenderer and one focused FocusManager::Pointer m_FocusManager; /** * @brief StatemachineFactory loads statemachine patterns and provides start states **/ StateMachineFactory* m_StateMachineFactory; /** * @brief EventMapper loads event patterns **/ EventMapper* m_EventMapper; bool m_CurrentlyInInformListenersLoop; bool m_CurrentlyInInformInteractorsLoop; bool m_IsInitialized; EVENT_NOTIFICATION_POLICY m_EventNotificationPolicy; }; } // namespace mitk #endif /* GLOBALINTERACTION_H_HEADER_INCLUDED_C152938A */ diff --git a/Core/Code/Interactions/mitkInformer.cpp b/Core/Code/Interactions/mitkInformer.cpp deleted file mode 100644 index dba4560923..0000000000 --- a/Core/Code/Interactions/mitkInformer.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/*=================================================================== - - 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 "mitkInformer.h" -#include -#include -#include - - - -mitk::InformerService::InformerService() -{ -} - -void mitk::InformerService::RegisterObserver(EventObserver* eventObserver) -{ - // explicitly use smart pointer, else the search for it will fail - // especially std::find() seems to fail on list of smart pointer objects - EventObserver::Pointer pEventObserver = eventObserver; - for (std::list::iterator it = m_ListObserver.begin(); it != m_ListObserver.end(); ++it) - { - if (*it == pEventObserver) - { - return; - } - } - m_ListObserver.push_back(pEventObserver); -} - -void mitk::InformerService::UnRegisterObserver(EventObserver* eventObserver) -{ - EventObserver::Pointer pEventObserver = eventObserver; - m_ListObserver.remove(pEventObserver); -} - -void mitk::InformerService::NotifyObservers(InteractionEvent::Pointer interactionEvent, bool isHandled) -{ - for (std::list::iterator it = m_ListObserver.begin(); it != m_ListObserver.end(); ++it) - { - (*it)->Notify(interactionEvent, isHandled); - } -} - -mitk::InformerService::~InformerService() -{ - m_ListObserver.clear(); -} diff --git a/Core/Code/Interactions/mitkInformer.h b/Core/Code/Interactions/mitkInformer.h deleted file mode 100644 index dd4a88ebc1..0000000000 --- a/Core/Code/Interactions/mitkInformer.h +++ /dev/null @@ -1,63 +0,0 @@ -/*=================================================================== - - 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 mitkInformerService_h -#define mitkInformerService_h - -#include "mitkEventInformer.h" -#include "mitkInteractionEvent.h" -#include "mitkEventObserver.h" -#include "itkObject.h" -#include "itkObjectFactory.h" -#include -#include "mitkCommon.h" -#include -#include - -namespace mitk -{ - /** - * \class InformerService - * - * MicroService that handles informing the EventObservers about InteractionEvents. - * Also provides an interface to register and unregister EventObservers for InteractionEvents - */ - class MITK_CORE_EXPORT InformerService: public itk::Object - { - public: - /** - * \brief Register a new EventObserver - */ - void RegisterObserver(EventObserver* eventObserver); - /** - * \brief Unregister an EventObserver - */ - void UnRegisterObserver(EventObserver* eventObserver); - /** - * \brief Distributes an event to all registered observers - */ - void NotifyObservers(InteractionEvent::Pointer interactionEvent, bool isHandled); - - InformerService(); - ~InformerService(); - - private: - std::list m_ListObserver; // list that stores all registered observers - }; - -} /* namespace mitk */ -US_DECLARE_SERVICE_INTERFACE(mitk::InformerService, "org.mitk.InformerService") -#endif diff --git a/Core/Code/Interactions/mitkInteractionEvent.cpp b/Core/Code/Interactions/mitkInteractionEvent.cpp index d14abe307a..195e0f0c76 100644 --- a/Core/Code/Interactions/mitkInteractionEvent.cpp +++ b/Core/Code/Interactions/mitkInteractionEvent.cpp @@ -1,48 +1,53 @@ /*=================================================================== 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 "mitkException.h" #include "mitkInteractionEvent.h" mitk::InteractionEvent::InteractionEvent(BaseRenderer* baseRenderer, std::string eventClass) : m_Sender(baseRenderer) , m_EventClass(eventClass) { } void mitk::InteractionEvent::SetSender(mitk::BaseRenderer* sender) { m_Sender = sender; } mitk::BaseRenderer* mitk::InteractionEvent::GetSender() { - return m_Sender.GetPointer(); + return m_Sender; } bool mitk::InteractionEvent::MatchesTemplate(InteractionEvent::Pointer) { return false; } mitk::InteractionEvent::~InteractionEvent() { } -std::string mitk::InteractionEvent::GetEventClass() +bool mitk::InteractionEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} + +std::string mitk::InteractionEvent::GetEventClass() const { return m_EventClass; } diff --git a/Core/Code/Interactions/mitkInteractionEvent.h b/Core/Code/Interactions/mitkInteractionEvent.h index 5070b8d0cc..64ac405415 100644 --- a/Core/Code/Interactions/mitkInteractionEvent.h +++ b/Core/Code/Interactions/mitkInteractionEvent.h @@ -1,77 +1,75 @@ /*=================================================================== 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 MITKINTERACTIONEVENT_H_ #define MITKINTERACTIONEVENT_H_ -#include "itkObject.h" +#include "itkLightObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkBaseRenderer.h" #include #include namespace mitk { - class MITK_CORE_EXPORT InteractionEvent: public itk::Object + class MITK_CORE_EXPORT InteractionEvent: public itk::LightObject { - public: - mitkClassMacro(InteractionEvent,itk::Object); - mitkNewMacro2Param(Self,BaseRenderer*, std::string); + mitkClassMacro(InteractionEvent,itk::LightObject) + mitkNewMacro2Param(Self,BaseRenderer*, std::string) + void SetSender(BaseRenderer* sender); BaseRenderer* GetSender(); /** * Implementation of equality for each event class. * Equality does \b not mean an exact copy or pointer equality. * * A match is determined by agreement in all attributes that are necessary to describe * the event for a state machine transition. * E.g. for a mouse event press event, it is important which modifiers are used, * which mouse button was used to triggered the event, but the mouse position is irrelevant. */ virtual bool MatchesTemplate(InteractionEvent::Pointer); /** * Return unique string identifier that gives the event class of this object, as it can be used in a state machine pattern. + * --- itk */ - std::string GetEventClass(); + std::string GetEventClass() const; + /** * This class implements an up cast to check if the provided baseClass object is derived from this class. * This function is used to support polymorphism on state machine pattern (XML) level. */ - template - bool IsSubClassOf(T *baseClass) - { - return dynamic_cast(baseClass) != NULL; - } + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: InteractionEvent(BaseRenderer*, std::string); virtual ~InteractionEvent(); private: - BaseRenderer::Pointer m_Sender; + BaseRenderer* m_Sender; std::string m_EventClass; }; } /* namespace mitk */ #endif /* MITKINTERACTIONEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkInteractionEventConst.h b/Core/Code/Interactions/mitkInteractionEventConst.h index 6c09341ab5..f332d73487 100644 --- a/Core/Code/Interactions/mitkInteractionEventConst.h +++ b/Core/Code/Interactions/mitkInteractionEventConst.h @@ -1,128 +1,131 @@ /*=================================================================== 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 MITKINTERACTEVENTCONST_H #define MITKINTERACTEVENTCONST_H //##Documentation //## @file mitkInteractionEventConst.h //## @brief Constants to describe Mouse Events and special Key Events. +#include + namespace mitk { //##ButtonState // Mouse/keyboard state values enum MouseButtons { NoButton = 0x0000, LeftMouseButton = 0x0001, RightMouseButton = 0x0002, MiddleMouseButton = 0x0004, }; enum ModifierKeys { NoKey = 0x0000, ShiftKey = 0x0100, ControlKey = 0x0200, AltKey = 0x0400 }; /* * Allow bitwise OR operation on enums. */ inline MouseButtons operator|(MouseButtons a, MouseButtons b) { return static_cast(static_cast(a) | static_cast(b)); } - // TODO: FixME not working! - inline MouseButtons operator|=(MouseButtons a, MouseButtons b) + + inline MouseButtons& operator|=(MouseButtons& a, MouseButtons& b) { - return static_cast(static_cast(a) | static_cast(b)); + a = static_cast(static_cast(a) | static_cast(b)); + return a; } inline ModifierKeys operator|(ModifierKeys a, ModifierKeys b) { return static_cast(static_cast(a) | static_cast(b)); } -// TODO: FixME not working! - inline ModifierKeys operator|=(ModifierKeys a, ModifierKeys b) + inline ModifierKeys& operator|=(ModifierKeys& a, ModifierKeys& b) { - return static_cast(static_cast(a) | static_cast(b)); + a = static_cast(static_cast(a) | static_cast(b)); + return a; } /** * KeyConstants Constants for special keys */ // Special Keys const std::string KeyEsc = "Escape"; const std::string KeyEnter = "Enter"; const std::string KeyReturn = "Return"; const std::string KeyDelete = "Delete"; const std::string KeyArrowUp = "ArrowUp"; const std::string KeyArrowDown = "ArrowDown"; const std::string KeyArrowLeft = "ArrowLeft"; const std::string KeyArrowRight = "ArrowRight"; const std::string KeyF1 = "F1"; const std::string KeyF2 = "F2"; const std::string KeyF3 = "F3"; const std::string KeyF4 = "F4"; const std::string KeyF5 = "F5"; const std::string KeyF6 = "F6"; const std::string KeyF7 = "F7"; const std::string KeyF8 = "F8"; const std::string KeyF9 = "F9"; const std::string KeyF10 = "F10"; const std::string KeyF11 = "F11"; const std::string KeyF12 = "F12"; const std::string KeyPos1 = "Pos1"; const std::string KeyEend = "End"; const std::string KeyInsert = "Insert"; const std::string KeyPageUp = "PageUp"; const std::string KeyPageDown = "PageDown"; // End special keys // XML Tags const std::string xmlTagConfigRoot = "config"; const std::string xmlTagParam = "param"; - const std::string xmlTagInput = "input"; + const std::string xmlTagEventVariant = "event_variant"; const std::string xmlTagAttribute = "attribute"; // XML Param const std::string xmlParameterName = "name"; const std::string xmlParameterValue = "value"; const std::string xmlParameterEventVariant = "event_variant"; - const std::string xmlParameterEventClass = "event_class"; + const std::string xmlParameterEventClass = "class"; // Event Description const std::string xmlEventPropertyModifier = "Modifiers"; const std::string xmlEventPropertyEventButton = "EventButton"; const std::string xmlEventPropertyButtonState = "ButtonState"; const std::string xmlEventPropertyKey = "Key"; const std::string xmlEventPropertyScrollDirection = "ScrollDirection"; const std::string xmlEventPropertySignalName = "SignalName"; // Predefined internal events/signals const std::string IntDeactivateMe = "DeactivateMe"; const std::string IntLeaveWidget = "LeaveWidget"; const std::string IntEnterWidget = "EnterWidget"; } //namespace mitk #endif //ifndef MITKINTERACTEVENTCONST_H diff --git a/Core/Code/Interactions/mitkEventHandler.cpp b/Core/Code/Interactions/mitkInteractionEventHandler.cpp similarity index 66% rename from Core/Code/Interactions/mitkEventHandler.cpp rename to Core/Code/Interactions/mitkInteractionEventHandler.cpp index 7cb125615e..2157bf592e 100644 --- a/Core/Code/Interactions/mitkEventHandler.cpp +++ b/Core/Code/Interactions/mitkInteractionEventHandler.cpp @@ -1,75 +1,75 @@ /*=================================================================== 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 "mitkEventHandler.h" +#include "mitkInteractionEventHandler.h" #include "mitkInteractionEvent.h" -mitk::EventHandler::EventHandler(): +mitk::InteractionEventHandler::InteractionEventHandler(): m_EventConfig(NULL) { } -mitk::EventHandler::~EventHandler() +mitk::InteractionEventHandler::~InteractionEventHandler() { } -bool mitk::EventHandler::LoadEventConfig(std::string filename, std::string moduleName) +bool mitk::InteractionEventHandler::LoadEventConfig(std::string filename, std::string moduleName) { m_EventConfig = vtkSmartPointer::New(); // notify sub-classes that new config is set bool success = m_EventConfig->LoadConfig(filename, moduleName); ConfigurationChanged(); return success; } -bool mitk::EventHandler::AddEventConfig(std::string filename, std::string moduleName) +bool mitk::InteractionEventHandler::AddEventConfig(std::string filename, std::string moduleName) { if (m_EventConfig == NULL) { MITK_ERROR<< "LoadEventConfig has to be called before AddEventConfig can be used."; return false; } // notify sub-classes that new config is set bool success = m_EventConfig->LoadConfig(filename, moduleName); ConfigurationChanged(); return success; } -mitk::PropertyList::Pointer mitk::EventHandler::GetAttributes() +mitk::PropertyList::Pointer mitk::InteractionEventHandler::GetAttributes() { if (m_EventConfig != NULL) { return m_EventConfig->GetAttributes(); } else { - MITK_ERROR << "EventHandler::GetAttributes() requested, but not configuration loaded."; + MITK_ERROR << "InteractionEventHandler::GetAttributes() requested, but not configuration loaded."; return NULL; } } -std::string mitk::EventHandler::MapToEventVariant(InteractionEvent* interactionEvent) +std::string mitk::InteractionEventHandler::MapToEventVariant(InteractionEvent* interactionEvent) { if (m_EventConfig != NULL) { return m_EventConfig->GetMappedEvent(interactionEvent); } else { return ""; } } -void mitk::EventHandler::ConfigurationChanged() +void mitk::InteractionEventHandler::ConfigurationChanged() { } diff --git a/Core/Code/Interactions/mitkEventHandler.h b/Core/Code/Interactions/mitkInteractionEventHandler.h similarity index 82% rename from Core/Code/Interactions/mitkEventHandler.h rename to Core/Code/Interactions/mitkInteractionEventHandler.h index f376ccf09a..8b45862464 100644 --- a/Core/Code/Interactions/mitkEventHandler.h +++ b/Core/Code/Interactions/mitkInteractionEventHandler.h @@ -1,83 +1,84 @@ /*=================================================================== 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 MITKEVENTHANDLER_H_ #define MITKEVENTHANDLER_H_ -#include "itkObject.h" +#include "itkLightObject.h" #include "itkObjectFactory.h" #include "mitkEvent.h" #include "mitkCommon.h" #include #include "mitkEventConfig.h" #include "mitkPropertyList.h" #include #include namespace mitk { /** * \class EventHandler - * Base Class for Interaction handling classes. - * Handles loading of configuration object and mapping of events to variant names. + * Serves as a base class for all objects and classes that handle mitk::InteractionEvents. + * + * It provides an interface to load configuration objects map of events to variant names. */ class InteractionEvent; - class MITK_CORE_EXPORT EventHandler : public itk::Object { + class MITK_CORE_EXPORT InteractionEventHandler : public itk::LightObject { public: - mitkClassMacro(EventHandler, itk::Object); - itkNewMacro(Self); + mitkClassMacro(InteractionEventHandler, itk::LightObject) + itkNewMacro(Self) /** * @brief Loads XML resource * * Loads a XML resource file in the given module context. * Default is the Mitk module (core). * The files have to be placed in the Resources/Interaction folder of their respective module. * This method will remove all existing configuration and replaces it with the new one. */ virtual bool LoadEventConfig(std::string filename, std::string moduleName = "Mitk"); /** * This method EXTENDs the configuration. * The configuration from the resource provided is loaded and only the ones conflicting are replaced by the new one. * This way several configuration files can be combined */ virtual bool AddEventConfig(std::string filename, std::string moduleName = "Mitk"); protected: - EventHandler(); - virtual ~EventHandler(); + InteractionEventHandler(); + virtual ~InteractionEventHandler(); /** * Returns a PropertyList in which the parameters defined in the config file are listed. */ PropertyList::Pointer GetAttributes(); std::string MapToEventVariant(InteractionEvent* interactionEvent); /** * Is called whenever a new config object ist set. * Overwrite this method e.g. to initialize EventHandler with parameters in configuration file. */ virtual void ConfigurationChanged(); private: vtkSmartPointer m_EventConfig; }; } /* namespace mitk */ #endif /* MITKEVENTHANDLER_H_ */ diff --git a/Core/Code/Interactions/mitkInteractionKeyEvent.cpp b/Core/Code/Interactions/mitkInteractionKeyEvent.cpp index c2dd7792fb..feb979df3f 100644 --- a/Core/Code/Interactions/mitkInteractionKeyEvent.cpp +++ b/Core/Code/Interactions/mitkInteractionKeyEvent.cpp @@ -1,47 +1,52 @@ /*=================================================================== 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 "mitkInteractionKeyEvent.h" -mitk::InteractionKeyEvent::InteractionKeyEvent(mitk::BaseRenderer* baseRenderer, std::string key, mitk::ModifierKeys modifiers = ControlKey) : +mitk::InteractionKeyEvent::InteractionKeyEvent(mitk::BaseRenderer* baseRenderer, const std::string key, mitk::ModifierKeys modifiers = ControlKey) : InteractionEvent(baseRenderer, "KeyEvent"), m_Key(key), m_Modifiers(modifiers) { } mitk::ModifierKeys mitk::InteractionKeyEvent::GetModifiers() const { return m_Modifiers; } std::string mitk::InteractionKeyEvent::GetKey() const { return m_Key; } mitk::InteractionKeyEvent::~InteractionKeyEvent() { } bool mitk::InteractionKeyEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::InteractionKeyEvent* keyEvent = dynamic_cast(interactionEvent.GetPointer()); if (keyEvent == NULL) { return false; } return (this->GetModifiers() == keyEvent->GetModifiers() && this->GetKey() == keyEvent->GetKey()); } + +bool mitk::InteractionKeyEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkInteractionKeyEvent.h b/Core/Code/Interactions/mitkInteractionKeyEvent.h index c0bfc924c4..7dea3c994c 100644 --- a/Core/Code/Interactions/mitkInteractionKeyEvent.h +++ b/Core/Code/Interactions/mitkInteractionKeyEvent.h @@ -1,64 +1,65 @@ /*=================================================================== 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 MITKINTERACTIONKEYEVENT_H_ #define MITKINTERACTIONKEYEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include #include /* * Note: A Click with the MiddleButton is to be handled with MousePressEvents */ namespace mitk { /** * \class InteractionKeyEvent * \brief Handles key events. * \input std::string for pressed key or special key description , mitk::ModifierKeys for modifiers * \ingroup Interaction. */ class MITK_CORE_EXPORT InteractionKeyEvent : public InteractionEvent { public: - mitkClassMacro(InteractionKeyEvent,InteractionEvent); - mitkNewMacro3Param(Self, BaseRenderer*, std::string , ModifierKeys); + mitkClassMacro(InteractionKeyEvent,InteractionEvent) + mitkNewMacro3Param(Self, BaseRenderer*, const std::string , ModifierKeys) virtual bool MatchesTemplate(InteractionEvent::Pointer); + bool IsSuperClassOf(InteractionEvent::Pointer baseClass); ModifierKeys GetModifiers() const; std::string GetKey() const; protected: - InteractionKeyEvent(BaseRenderer*, std::string key, ModifierKeys modifiers); + InteractionKeyEvent(BaseRenderer*, const std::string key, ModifierKeys modifiers); virtual ~InteractionKeyEvent(); private: std::string m_Key; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKINTERACTIONKEYEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkInteractionPositionEvent.cpp b/Core/Code/Interactions/mitkInteractionPositionEvent.cpp index 42cecbcffb..155f6c80a0 100644 --- a/Core/Code/Interactions/mitkInteractionPositionEvent.cpp +++ b/Core/Code/Interactions/mitkInteractionPositionEvent.cpp @@ -1,53 +1,58 @@ /*=================================================================== 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 "mitkInteractionPositionEvent.h" #include mitk::InteractionPositionEvent::InteractionPositionEvent(mitk::BaseRenderer* baseRenderer, - mitk::Point2D mousePosition, - std::string eventClass) + const mitk::Point2D mousePosition, + const std::string eventClass) : InteractionEvent(baseRenderer, eventClass) , m_PointerPosition(mousePosition) { if (GetSender() != NULL) { m_WorldPosition = GetSender()->Map2DRendererPositionTo3DWorldPosition(&m_PointerPosition); } else { m_WorldPosition.Fill(0); } } -mitk::Point2D mitk::InteractionPositionEvent::GetPointerPositionOnScreen() +const mitk::Point2D mitk::InteractionPositionEvent::GetPointerPositionOnScreen() { return m_PointerPosition; } -mitk::Point3D mitk::InteractionPositionEvent::GetPositionInWorld() +const mitk::Point3D mitk::InteractionPositionEvent::GetPositionInWorld() { return m_WorldPosition; } bool mitk::InteractionPositionEvent::MatchesTemplate(InteractionEvent::Pointer) { return true; } mitk::InteractionPositionEvent::~InteractionPositionEvent() { } + +bool mitk::InteractionPositionEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkInteractionPositionEvent.h b/Core/Code/Interactions/mitkInteractionPositionEvent.h index b7d43a8328..5f7960cd9a 100644 --- a/Core/Code/Interactions/mitkInteractionPositionEvent.h +++ b/Core/Code/Interactions/mitkInteractionPositionEvent.h @@ -1,63 +1,65 @@ /*=================================================================== 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 MITKINTERACTIONPOSITIONEVENT_H_ #define MITKINTERACTIONPOSITIONEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEvent.h" #include "mitkInteractionEventConst.h" #include #include namespace mitk { /** * \class InteractionPositionEvent * * \brief Super class for all position events. * * This class is instantiated with a BaseRenderer and the 2D pointer position relative to the renderer, * the object then queries the Renderer for 3D world coordinates and supplies them to deriving classes. * */ class MITK_CORE_EXPORT InteractionPositionEvent : public InteractionEvent { public: mitkClassMacro(InteractionPositionEvent,InteractionEvent); - mitkNewMacro3Param(Self, BaseRenderer*, Point2D , std::string); + mitkNewMacro3Param(Self, BaseRenderer*, const Point2D , const std::string); - Point2D GetPointerPositionOnScreen(); - Point3D GetPositionInWorld(); + const Point2D GetPointerPositionOnScreen(); + const Point3D GetPositionInWorld(); - protected: - InteractionPositionEvent(BaseRenderer* baseRenderer, Point2D mousePosition, std::string eventClass); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); + + protected: + InteractionPositionEvent(BaseRenderer* baseRenderer, const Point2D mousePosition, const std::string eventClass); virtual ~InteractionPositionEvent(); private: Point2D m_PointerPosition; Point3D m_WorldPosition; }; } /* namespace mitk */ #endif /* MITKINTERACTIONPOSITIONEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkInteractor.h b/Core/Code/Interactions/mitkInteractor.h index 1178a06d81..8574a27b4f 100755 --- a/Core/Code/Interactions/mitkInteractor.h +++ b/Core/Code/Interactions/mitkInteractor.h @@ -1,170 +1,174 @@ /*=================================================================== 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 INTERACTOR_H_HEADER_INCLUDED #define INTERACTOR_H_HEADER_INCLUDED #include #include "mitkStateMachine.h" #include "mitkGeometry3D.h" #include namespace mitk { class DataNode; class BaseData; //##Documentation //## @brief Interface for an Interactor. //## //## The Interactor is held with a SmartPointer by a DataNode //## and holds its Node with a Pointer. That way Smartpointer doesn't build a circle. //## Different Modes: In order to not send Events to all StateMachines, a StateMachine can be //## in three different modes: //## DESELECTED: this statemachine doesn't wait for an event //## SELECTED: this statemachine just has handled an event and waits for the next one //## SUBSELECTED: depricate; was used for hierarchical statemachines before. //## Guidelines for the modevalues: Selected if the coresponding data is selected, deselected if deselect of data. //## //## In moving the machine is selected. After a new insert the machine is selected, since the data is also selected //## In method ExecuteAction(..) the different actions are divided up through switch/case statements. Each block has to check //## the appropriate type of event to process the actions. Especially in guarding states (a state, that checks certain conditions (e.g. is picked) //## the according Event must be called to continue in states. No return false here! //## @ingroup Interaction +/** + * \deprecatedSince{2013_03} mitk::Interactor is deprecated. Use mitk::DataInteractor instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT Interactor : public StateMachine { public: mitkClassMacro(Interactor, StateMachine); /** * @brief NewMacro with two parameters for calling itk::Lightobject::New(..) method **/ mitkNewMacro2Param(Self, const char*, DataNode*); //##Documentation //##@brief Enumeration of the different modes an Interactor can be into. //## See class documentation for further details enum SMMode { SMDESELECTED = 0, SMSELECTED, SMSUBSELECTED }; typedef SMMode ModeType; //##Documentation //## @brief Get the Mode of the Interactor. Use enum SMMode for return parameter SMMode GetMode() const; //##Documentation //## @brief Check the interaction mode bool IsNotSelected() const; //##Documentation //## @brief Check the interaction mode bool IsSelected() const; //##Documentation //## @brief calculates how good the data, this statemachine handles, is hit by the event. //## //## Returns a value between 0 and 1 //## where 0 represents not responsible and 1 represents definitive responsible! //## Standard function to override if needed. //## (Used by GlobalInteraction to decide which DESELECTED statemachine to send the event to.) virtual float CanHandleEvent(StateEvent const* stateEvent) const; /** * @brief Updates the current TimeStep according to the associated data and calls Superclass::HandleEvent() **/ bool HandleEvent(StateEvent const* stateEvent); /** * @brief Method to call if the associated data has changed by the user (loading of data) * This method is called by DataNode::SetData() to tell the interactor to reinitialize. * This method should be overwritten by specialized interactors. * (e.g. PointSetInteractor: go to the right state according to number of loaded points) * Note: It will not be called when the data gets modified (e.g. adding / removing points to a PointSet) **/ virtual void DataChanged(){}; //##Documentation //## @brief adds handling of operations used for mode change. Unrecognized Operations are send to Superclass. //## *ATTENTION*: THIS METHOD SHOULD NOT BE CALLED FROM OTHER CLASSES DIRECTLY! virtual void ExecuteOperation(Operation* operation); static const std::string XML_NODE_NAME; protected: /** * @brief Constructor * @param dataNode is the node, this Interactor is connected to * @param type is the type of StateMachine like declared in the XML-Configure-File * * Interactor connects itself to the DataNode-Interactor-pointer through call of SetInteractor(this) **/ Interactor(const char * type, DataNode* dataNode); /** * @brief Destructor **/ ~Interactor(){} bool OnModeSelect(Action* action, StateEvent const*); bool OnModeDeselect(Action* action, StateEvent const*); bool OnModeSubSelect(Action* action, StateEvent const*); //##Documentation virtual const std::string& GetXMLNodeName() const; //##Documentation //## @brief creates a ModeOperation with the transmitted mode and sends it to this. Undo supported! void CreateModeOperation(ModeType mode); //##Documentation //## @brief convenience method for accessing the data contained in the //## node to which this interactor is associated to BaseData* GetData() const; //##Documentation //## @brief Used by friend class DataNode virtual void SetDataNode( DataNode* dataNode ); /** * @brief Derived from superclass to also check if enough timesteps are instantiated in m_CurrentStateVector * The number of timesteps is read from the dedicated data. * @param[in] timeStep The timeStep that the statemachine has to be set to **/ virtual void UpdateTimeStep(unsigned int timeStep); //##Documentation //## @brief Pointer to the data, this object handles the Interaction for DataNode* m_DataNode; //##Documentation //## @brief Mode of Selection ModeType m_Mode; friend class DataNode; }; }//namespace mitk #endif /* INTERACTOR_H_HEADER_INCLUDED */ diff --git a/Core/Code/Interactions/mitkInternalEvent.cpp b/Core/Code/Interactions/mitkInternalEvent.cpp index e9950f6a35..15622e6bc1 100644 --- a/Core/Code/Interactions/mitkInternalEvent.cpp +++ b/Core/Code/Interactions/mitkInternalEvent.cpp @@ -1,50 +1,55 @@ /*=================================================================== 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 "mitkInternalEvent.h" #include "mitkDataInteractor.h" -mitk::InternalEvent::InternalEvent(mitk::BaseRenderer* baseRenderer, DataInteractor* sourceInteractor, std::string signalName) +mitk::InternalEvent::InternalEvent(mitk::BaseRenderer* baseRenderer, DataInteractor* sourceInteractor, const std::string signalName) : InteractionEvent(baseRenderer, "InternalEvent") , m_DataInteractor(sourceInteractor) , m_SignalName(signalName) { } bool mitk::InternalEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::InternalEvent* internalEvent = dynamic_cast(interactionEvent.GetPointer()); if (internalEvent == NULL) { return false; } return (m_SignalName == internalEvent->GetSignalName()); } mitk::InternalEvent::~InternalEvent() { } -std::string mitk::InternalEvent::GetSignalName() +const std::string mitk::InternalEvent::GetSignalName() { return m_SignalName; } mitk::DataInteractor* mitk::InternalEvent::GetTargetInteractor() { return m_DataInteractor.GetPointer(); } + +bool mitk::InternalEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (NULL != dynamic_cast(baseClass.GetPointer()) ); +} diff --git a/Core/Code/Interactions/mitkInternalEvent.h b/Core/Code/Interactions/mitkInternalEvent.h index 468eb26b9d..4d511084e2 100644 --- a/Core/Code/Interactions/mitkInternalEvent.h +++ b/Core/Code/Interactions/mitkInternalEvent.h @@ -1,62 +1,63 @@ /*=================================================================== 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 mitkInternalEvent_h #define mitkInternalEvent_h #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionEvent.h" #include "mitkBaseRenderer.h" #include #include namespace mitk { /** *\brief Class to create events from within the application to signal about internal events. * * These events can target a specific DataInteractor, if this DataInteractor is specified in the constructor; * else this parameter is set to NULL and the event is treated as a regular event. */ class DataInteracor; class MITK_CORE_EXPORT InternalEvent: public InteractionEvent { public: mitkClassMacro(InternalEvent,InteractionEvent); - mitkNewMacro3Param(Self, BaseRenderer*, DataInteractor*, std::string); + mitkNewMacro3Param(Self, BaseRenderer*, DataInteractor*, const std::string); - std::string GetSignalName(); + const std::string GetSignalName(); DataInteractor* GetTargetInteractor(); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - InternalEvent(BaseRenderer*, DataInteractor* destInteractor, std::string signalName); + InternalEvent(BaseRenderer*, DataInteractor* destInteractor, const std::string signalName); virtual ~InternalEvent(); private: DataInteractor::Pointer m_DataInteractor; std::string m_SignalName; }; } #endif /* mitkInternalEvent_h */ diff --git a/Core/Code/Interactions/mitkKeyEvent.h b/Core/Code/Interactions/mitkKeyEvent.h index 080d0e429b..6f4f555edb 100644 --- a/Core/Code/Interactions/mitkKeyEvent.h +++ b/Core/Code/Interactions/mitkKeyEvent.h @@ -1,78 +1,83 @@ /*=================================================================== 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 KeyEvent_H_HEADER_INCLUDED_C184F366 #define KeyEvent_H_HEADER_INCLUDED_C184F366 #include #include "mitkEvent.h" #include "mitkVector.h" namespace mitk { //##Documentation //## @brief Event that stores coordinates and the key which is pressed //## //## Stores display position of the mouse. If requested, the correspondent //## 3D world position in mm is calculated via picking (delegated to the //## BaseRenderer). //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} KeyEvent is deprecated. Use mitk::InteractionKeyEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT KeyEvent : public Event { public: //##Documentation //## @brief Constructor with all necessary arguments. //## //## @param sender is the renderer that caused that event //## @param type, button, buttonState, key: information from the Event //## @param displPosition is the 2D Position of the mouse KeyEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, std::string text, const Point2D& displPosition); const Point2D& GetDisplayPosition() const { return m_DisplayPosition; } void SetDisplayPosition(const Point2D& displPosition) { m_DisplayPosition = displPosition; } const Point3D& GetWorldPosition() const; int GetKey() const { return m_Key; } const char* GetText() const { return m_Text.c_str(); } int GetType() const { return m_Type; } protected: Point2D m_DisplayPosition; int m_Key; std::string m_Text; mutable Point3D m_WorldPosition; mutable bool m_WorldPositionIsSet; }; } // namespace mitk #endif /* DISPLAYPOSITIONozsiEVENT_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkMouseModeSwitcher.cpp b/Core/Code/Interactions/mitkMouseModeSwitcher.cpp index 43955309d9..5412233987 100644 --- a/Core/Code/Interactions/mitkMouseModeSwitcher.cpp +++ b/Core/Code/Interactions/mitkMouseModeSwitcher.cpp @@ -1,112 +1,110 @@ /*=================================================================== 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 "mitkMouseModeSwitcher.h" // us #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +#include "mitkInteractionEventObserver.h" mitk::MouseModeSwitcher::MouseModeSwitcher() : - m_ActiveInteractionScheme(MITK), m_ActiveMouseMode(MousePointer) + m_ActiveInteractionScheme(MITK), m_ActiveMouseMode(MousePointer), m_CurrentObserver(NULL) { - m_CurrentObserver = NULL; this->InitializeListeners(); this->SetInteractionScheme(m_ActiveInteractionScheme); } mitk::MouseModeSwitcher::~MouseModeSwitcher() { +// m_ServiceRegistration.Unregister(); } void mitk::MouseModeSwitcher::InitializeListeners() { if (m_CurrentObserver.IsNull()) { m_CurrentObserver = mitk::DisplayInteractor::New(); m_CurrentObserver->LoadStateMachine("DisplayInteraction.xml"); m_CurrentObserver->LoadEventConfig("DisplayConfigMITK.xml"); - // Register as listener - mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - mitk::ServiceReference serviceRef = context->GetServiceReference(); - mitk::InformerService* service = dynamic_cast(context->GetService(serviceRef)); - service->RegisterObserver(m_CurrentObserver.GetPointer()); + // Register as listener via micro services + ServiceRegistration m_ServiceRegistration = GetModuleContext()->RegisterService( + m_CurrentObserver.GetPointer()); } } void mitk::MouseModeSwitcher::SetInteractionScheme(InteractionScheme scheme) { switch (scheme) { case MITK: { m_CurrentObserver->LoadEventConfig("DisplayConfigMITK.xml"); } break; case PACS: { m_CurrentObserver->LoadEventConfig("DisplayConfigPACS.xml"); } break; } m_ActiveInteractionScheme = scheme; - this->InvokeEvent( MouseModeChangedEvent() ); + this->InvokeEvent(MouseModeChangedEvent()); } void mitk::MouseModeSwitcher::SelectMouseMode(MouseMode mode) { if (m_ActiveInteractionScheme != PACS) return; switch (mode) { case MousePointer: { m_CurrentObserver->LoadEventConfig("DisplayConfigPACS.xml"); break; } // case 0 case Scroll: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSScroll.xml"); break; } case LevelWindow: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSLevelWindow.xml"); break; } case Zoom: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSZoom.xml"); break; } case Pan: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSPan.xml"); break; } } // end switch (mode) m_ActiveMouseMode = mode; - this->InvokeEvent( MouseModeChangedEvent() ); + this->InvokeEvent(MouseModeChangedEvent()); } mitk::MouseModeSwitcher::MouseMode mitk::MouseModeSwitcher::GetCurrentMouseMode() const { return m_ActiveMouseMode; } diff --git a/Core/Code/Interactions/mitkMouseModeSwitcher.h b/Core/Code/Interactions/mitkMouseModeSwitcher.h index 4d9347bcc8..c3d54cf19b 100644 --- a/Core/Code/Interactions/mitkMouseModeSwitcher.h +++ b/Core/Code/Interactions/mitkMouseModeSwitcher.h @@ -1,124 +1,129 @@ /*=================================================================== 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 MITKMouseModeSwitcher_H_HEADER_INCLUDED_C10DC4EB #define MITKMouseModeSwitcher_H_HEADER_INCLUDED_C10DC4EB #include "MitkExports.h" #include #include "mitkDisplayInteractor.h" namespace mitk { /*********************************************************************** * * \brief Class that offers a convenient way to switch between different * interaction schemes * * This class offers the possibility to switch between the two different * interaction schemes that are available: * - MITK : The original interaction scheme * - left mouse button : setting the cross position in the MPR view * - middle mouse button : panning * - right mouse button : zooming * * * - PACS : an alternative interaction scheme that behaves more like a * PACS workstation * - left mouse button : behavior depends on current MouseMode * - middle mouse button : fast scrolling * - right mouse button : level-window * - ctrl + right button : zooming * - shift+ right button : panning * * There are 5 different MouseModes that are available in the PACS scheme. * Each MouseMode defines the interaction that is performed on a left * mouse button click: * - Pointer : sets the cross position for the MPR * - Scroll * - Level-Window * - Zoom * - Pan * * When the interaction scheme or the MouseMode is changed, this class * manages the adding and removing of the relevant listeners offering * a convenient way to modify the interaction behavior. * ***********************************************************************/ class MITK_CORE_EXPORT MouseModeSwitcher : public itk::Object { public: #pragma GCC visibility push(default) /** \brief Can be observed by GUI class to update button states when mode is changed programatically. */ itkEventMacro( MouseModeChangedEvent, itk::AnyEvent ); #pragma GCC visibility pop mitkClassMacro( MouseModeSwitcher, itk::Object ); itkNewMacro(Self); // enum of the different interaction schemes that are available enum InteractionScheme { PACS = 0, MITK = 1 }; // enum of available mouse modes for PACS interaction scheme enum MouseMode { MousePointer = 0, Scroll, LevelWindow, Zoom, Pan }; /** * \brief Setter for interaction scheme */ void SetInteractionScheme( InteractionScheme ); /** * \brief Setter for mouse mode */ void SelectMouseMode( MouseMode mode ); /** * \brief Returns the current mouse mode */ MouseMode GetCurrentMouseMode() const; protected: MouseModeSwitcher(); virtual ~MouseModeSwitcher(); private: /** * \brief Initializes the listener with the MITK default behavior. */ void InitializeListeners(); InteractionScheme m_ActiveInteractionScheme; MouseMode m_ActiveMouseMode; DisplayInteractor::Pointer m_CurrentObserver; + /** + * Reference to the service registration of the observer, + * it is needed to unregister the observer on unload. + */ + ServiceRegistration m_ServiceRegistration; }; } // namespace mitk #endif /* MITKMouseModeSwitcher_H_HEADER_INCLUDED_C10DC4EB */ diff --git a/Core/Code/Interactions/mitkMouseMoveEvent.cpp b/Core/Code/Interactions/mitkMouseMoveEvent.cpp index 7184da4a05..31492997e0 100644 --- a/Core/Code/Interactions/mitkMouseMoveEvent.cpp +++ b/Core/Code/Interactions/mitkMouseMoveEvent.cpp @@ -1,60 +1,64 @@ /*=================================================================== 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 "mitkException.h" #include "mitkMouseMoveEvent.h" -mitk::MouseMoveEvent::MouseMoveEvent(mitk::BaseRenderer* baseRenderer, mitk::Point2D mousePosition = NULL, mitk::MouseButtons buttonStates = - NoButton, mitk::ModifierKeys modifiers = NoKey) +mitk::MouseMoveEvent::MouseMoveEvent(mitk::BaseRenderer* baseRenderer, mitk::Point2D mousePosition , mitk::MouseButtons buttonStates, mitk::ModifierKeys modifiers) : InteractionPositionEvent(baseRenderer, mousePosition, "MouseMoveEvent") , m_ButtonStates(buttonStates) , m_Modifiers(modifiers) { } mitk::ModifierKeys mitk::MouseMoveEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MouseMoveEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MouseMoveEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MouseMoveEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MouseMoveEvent::~MouseMoveEvent() { } bool mitk::MouseMoveEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::MouseMoveEvent* mpe = dynamic_cast(interactionEvent.GetPointer()); if (mpe == NULL) { return false; } return (this->GetModifiers() == mpe->GetModifiers() && this->GetButtonStates() == mpe->GetButtonStates()); } + +bool mitk::MouseMoveEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMouseMoveEvent.h b/Core/Code/Interactions/mitkMouseMoveEvent.h index db1bc60dbe..dc7dd8a5cf 100644 --- a/Core/Code/Interactions/mitkMouseMoveEvent.h +++ b/Core/Code/Interactions/mitkMouseMoveEvent.h @@ -1,56 +1,57 @@ /*=================================================================== 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 MITKMOUSEMOVEEVENT_H_ #define MITKMOUSEMOVEEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include namespace mitk { class MITK_CORE_EXPORT MouseMoveEvent : public InteractionPositionEvent { public: mitkClassMacro(MouseMoveEvent,InteractionPositionEvent); mitkNewMacro4Param(Self, BaseRenderer*, Point2D , MouseButtons , ModifierKeys); ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MouseMoveEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers); + MouseMoveEvent(BaseRenderer*, Point2D = Point2D(), MouseButtons buttonStates = NoButton, mitk::ModifierKeys modifiers = NoKey); virtual ~MouseMoveEvent(); private: MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSEMOVEEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkMousePressEvent.cpp b/Core/Code/Interactions/mitkMousePressEvent.cpp index e8fdff0887..6026811db7 100644 --- a/Core/Code/Interactions/mitkMousePressEvent.cpp +++ b/Core/Code/Interactions/mitkMousePressEvent.cpp @@ -1,75 +1,80 @@ /*=================================================================== 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 "mitkException.h" #include "mitkMousePressEvent.h" mitk::MousePressEvent::MousePressEvent(mitk::BaseRenderer* baseRenderer, - mitk::Point2D mousePosition, + const mitk::Point2D mousePosition, mitk::MouseButtons buttonStates, mitk::ModifierKeys modifiers, mitk::MouseButtons eventButton) : InteractionPositionEvent(baseRenderer, mousePosition, "MousePressEvent") , m_EventButton(eventButton) , m_ButtonStates(buttonStates) , m_Modifiers( modifiers) { } mitk::MouseButtons mitk::MousePressEvent::GetEventButton() const { return m_EventButton; } void mitk::MousePressEvent::SetEventButton(MouseButtons buttons) { m_EventButton = buttons; } mitk::ModifierKeys mitk::MousePressEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MousePressEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MousePressEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MousePressEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MousePressEvent::~MousePressEvent() { } bool mitk::MousePressEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::MousePressEvent* mpe = dynamic_cast(interactionEvent.GetPointer()); if (mpe == NULL) { return false; } return (this->GetEventButton() == mpe->GetEventButton() && this->GetModifiers() == mpe->GetModifiers() && this->GetButtonStates() == mpe->GetButtonStates()); } + +bool mitk::MousePressEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMousePressEvent.h b/Core/Code/Interactions/mitkMousePressEvent.h index 53d7f6ce99..f15f3f15b4 100644 --- a/Core/Code/Interactions/mitkMousePressEvent.h +++ b/Core/Code/Interactions/mitkMousePressEvent.h @@ -1,58 +1,62 @@ /*=================================================================== 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 MITKMOUSEPRESSEVENT_H_ #define MITKMOUSEPRESSEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include namespace mitk { - class MITK_CORE_EXPORT MousePressEvent : public InteractionPositionEvent { + class MITK_CORE_EXPORT MousePressEvent: public InteractionPositionEvent + { public: - mitkClassMacro(MousePressEvent,InteractionPositionEvent); - mitkNewMacro5Param(Self, BaseRenderer*, Point2D , MouseButtons , ModifierKeys, MouseButtons); + mitkClassMacro(MousePressEvent,InteractionPositionEvent) + mitkNewMacro5Param(Self, BaseRenderer*, const Point2D , MouseButtons , ModifierKeys, MouseButtons) ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); - MouseButtons GetEventButton() const ; - void SetEventButton(MouseButtons buttons) ; + MouseButtons GetEventButton() const; + void SetEventButton(MouseButtons buttons); + virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MousePressEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers, MouseButtons eventButton); + MousePressEvent(BaseRenderer*, const Point2D = Point2D(), mitk::MouseButtons buttonStates = NoButton, mitk::ModifierKeys modifiers = + NoKey, mitk::MouseButtons eventButton = NoButton); virtual ~MousePressEvent(); private: MouseButtons m_EventButton; MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSEPRESSEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkMouseReleaseEvent.cpp b/Core/Code/Interactions/mitkMouseReleaseEvent.cpp index a9bebdb8bb..1a8a6d5354 100644 --- a/Core/Code/Interactions/mitkMouseReleaseEvent.cpp +++ b/Core/Code/Interactions/mitkMouseReleaseEvent.cpp @@ -1,78 +1,83 @@ /*=================================================================== 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 "mitkException.h" #include "mitkMouseReleaseEvent.h" mitk::MouseReleaseEvent::MouseReleaseEvent(mitk::BaseRenderer* baseRenderer, mitk::Point2D mousePosition, mitk::MouseButtons buttonStates, mitk::ModifierKeys modifiers, mitk::MouseButtons eventButton) : InteractionPositionEvent(baseRenderer, mousePosition, "MouseReleaseEvent") , m_EventButton(eventButton) ,m_ButtonStates(buttonStates) , m_Modifiers(modifiers) { } mitk::MouseButtons mitk::MouseReleaseEvent::GetEventButton() const { return m_EventButton; } void mitk::MouseReleaseEvent::SetEventButton(MouseButtons buttons) { m_EventButton = buttons; } mitk::ModifierKeys mitk::MouseReleaseEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MouseReleaseEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MouseReleaseEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MouseReleaseEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MouseReleaseEvent::~MouseReleaseEvent() { } bool mitk::MouseReleaseEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::MouseReleaseEvent* mre = dynamic_cast(interactionEvent.GetPointer()); if (mre == NULL) { return false; } return (this->GetEventButton() == mre->GetEventButton() && this->GetModifiers() == mre->GetModifiers() && this->GetButtonStates() == mre->GetButtonStates() ); } + +bool mitk::MouseReleaseEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMouseReleaseEvent.h b/Core/Code/Interactions/mitkMouseReleaseEvent.h index a74cc3ac73..966c4d70da 100644 --- a/Core/Code/Interactions/mitkMouseReleaseEvent.h +++ b/Core/Code/Interactions/mitkMouseReleaseEvent.h @@ -1,59 +1,65 @@ /*=================================================================== 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 MITKMOUSERELEASEEVENT_H_ #define MITKMOUSERELEASEEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionPositionEvent.h" #include "mitkInteractionEventConst.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include namespace mitk { class MITK_CORE_EXPORT MouseReleaseEvent: public InteractionPositionEvent { public: - mitkClassMacro(MouseReleaseEvent,InteractionPositionEvent); - mitkNewMacro5Param(Self, BaseRenderer*, Point2D ,MouseButtons , ModifierKeys, MouseButtons) ; + mitkClassMacro(MouseReleaseEvent,InteractionPositionEvent) + mitkNewMacro5Param(Self, BaseRenderer*, const Point2D ,MouseButtons , ModifierKeys, MouseButtons) ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); MouseButtons GetEventButton() const; void SetEventButton(MouseButtons buttons); + virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MouseReleaseEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers, MouseButtons eventButton); + MouseReleaseEvent(BaseRenderer*, + mitk::Point2D mousePosition = Point2D(), + mitk::MouseButtons buttonStates = NoButton, + mitk::ModifierKeys modifiers = NoKey, + mitk::MouseButtons eventButton = NoButton); virtual ~MouseReleaseEvent(); private: MouseButtons m_EventButton; MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSERELEASEEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkMouseWheelEvent.cpp b/Core/Code/Interactions/mitkMouseWheelEvent.cpp index b97968007a..d81b1800e3 100644 --- a/Core/Code/Interactions/mitkMouseWheelEvent.cpp +++ b/Core/Code/Interactions/mitkMouseWheelEvent.cpp @@ -1,74 +1,79 @@ /*=================================================================== 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 "mitkMouseWheelEvent.h" mitk::MouseWheelEvent::MouseWheelEvent(BaseRenderer* baseRenderer, Point2D mousePosition, MouseButtons buttonStates, ModifierKeys modifiers, int wheelDelta) : InteractionPositionEvent(baseRenderer, mousePosition, "MouseWheelEvent") , m_WheelDelta(wheelDelta) , m_ButtonStates(buttonStates) , m_Modifiers(modifiers) { } int mitk::MouseWheelEvent::GetWheelDelta() const { return m_WheelDelta; } void mitk::MouseWheelEvent::SetWheelDelta(int delta) { m_WheelDelta = delta; } mitk::ModifierKeys mitk::MouseWheelEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MouseWheelEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MouseWheelEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MouseWheelEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MouseWheelEvent::~MouseWheelEvent() { } bool mitk::MouseWheelEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { const mitk::MouseWheelEvent* mwe = dynamic_cast(interactionEvent.GetPointer()); if (mwe == NULL) { return false; } return ((this->GetWheelDelta() * mwe->GetWheelDelta() > 0) // Consider WheelEvents to be equal if the scrolling is done in the same direction. && this->GetModifiers() == mwe->GetModifiers() && this->GetButtonStates() == mwe->GetButtonStates()); } + +bool mitk::MouseWheelEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMouseWheelEvent.h b/Core/Code/Interactions/mitkMouseWheelEvent.h index 98c1ac7eee..deac97bb56 100644 --- a/Core/Code/Interactions/mitkMouseWheelEvent.h +++ b/Core/Code/Interactions/mitkMouseWheelEvent.h @@ -1,63 +1,68 @@ /*=================================================================== 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 MITKMOUSEWHEELEVENT_H_ #define MITKMOUSEWHEELEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include /** * Note: A Click with the MiddleButton is to be handled with MousePressEvents */ - namespace mitk { - class MITK_CORE_EXPORT MouseWheelEvent : public InteractionPositionEvent { + class MITK_CORE_EXPORT MouseWheelEvent: public InteractionPositionEvent + { public: - mitkClassMacro(MouseWheelEvent,InteractionPositionEvent); - mitkNewMacro5Param(Self, BaseRenderer*, Point2D , MouseButtons , ModifierKeys, int); + mitkClassMacro(MouseWheelEvent,InteractionPositionEvent) + mitkNewMacro5Param(Self, BaseRenderer*, const Point2D , MouseButtons , ModifierKeys, int) ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); int GetWheelDelta() const; void SetWheelDelta(int delta); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MouseWheelEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers, int wheelDelta); + MouseWheelEvent(BaseRenderer* = NULL, + const Point2D mousePosition = Point2D(), + MouseButtons buttonStates = NoButton, + ModifierKeys modifiers = NoKey, + int wheelDelta = 0); virtual ~MouseWheelEvent(); private: int m_WheelDelta; MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSEPRESSEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkPointSetDataInteractor.cpp b/Core/Code/Interactions/mitkPointSetDataInteractor.cpp index e8902028a7..c4c7416a21 100644 --- a/Core/Code/Interactions/mitkPointSetDataInteractor.cpp +++ b/Core/Code/Interactions/mitkPointSetDataInteractor.cpp @@ -1,304 +1,333 @@ /*=================================================================== 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 "mitkPointSetDataInteractor.h" #include "mitkMouseMoveEvent.h" #include #include "mitkInteractionConst.h" // TODO: refactor file #include "mitkRenderingManager.h" #include "mitkInternalEvent.h" // #include "mitkDispatcher.h" #include "mitkBaseRenderer.h" void mitk::PointSetDataInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addpoint", AddPoint); CONNECT_FUNCTION("selectpoint", SelectPoint); CONNECT_FUNCTION("unselect", UnSelectPoint); CONNECT_FUNCTION("initMove", InitMove); CONNECT_FUNCTION("initMovePointSet", InitMoveAll); CONNECT_FUNCTION("movePoint", MovePoint); CONNECT_FUNCTION("movePointSet", MoveSet); CONNECT_FUNCTION("finishMovement", FinishMove); CONNECT_FUNCTION("removePoint", RemovePoint); } bool mitk::PointSetDataInteractor::AddPoint(StateMachineAction* stateMachineAction, InteractionEvent* interactionEvent) { // Find the position, the point is to be added to: first entry with // empty index. If the Set is empty, then start with 0. if not empty, // then take the first index which is not occupied int lastPosition = 0; PointSet::PointsContainer* pointsContainer = m_PointSet->GetPointSet(0)->GetPoints(); if (!pointsContainer->empty()) { mitk::PointSet::PointsIterator it, end; it = pointsContainer->Begin(); end = pointsContainer->End(); while (it != end) { if (!pointsContainer->IndexExists(lastPosition)) break; ++it; ++lastPosition; } } InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { IsClosedContour(stateMachineAction, interactionEvent); // Get time step from BaseRenderer int timeStep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D point = positionEvent->GetPositionInWorld(); m_PointSet->InsertPoint(lastPosition, point, timeStep); m_NumberOfPoints++; GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); if (m_MaxNumberOfPoints != 0 && m_NumberOfPoints >= m_MaxNumberOfPoints) { InternalEvent::Pointer event = InternalEvent::New(NULL, this, "MaxNumberOfPoints"); positionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } else { return false; } } bool mitk::PointSetDataInteractor::SelectPoint(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); Point3D point = positionEvent->GetPositionInWorld(); // iterate over point set and check if it contains a point close enough to the pointer to be selected if (GetPointIndexByPosition(point, timeStep) != -1) { //TODO FIXME is this safe ? can pointset and renderer have different sizes ? m_SelectedPointIndex = GetPointIndexByPosition(point, timeStep); GetDataNode()->SetProperty("contourcolor", ColorProperty::New(0.0, 0.0, 1.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } else { return false; } } mitk::PointSetDataInteractor::PointSetDataInteractor() : - m_NumberOfPoints(0), m_MaxNumberOfPoints(0),m_SelectedPointIndex(-1) + m_NumberOfPoints(0), m_MaxNumberOfPoints(0),m_SelectedPointIndex(-1),m_SelectionAccuracy(3.5) { } mitk::PointSetDataInteractor::~PointSetDataInteractor() { } bool mitk::PointSetDataInteractor::RemovePoint(StateMachineAction*, InteractionEvent*) { if (m_SelectedPointIndex != -1) { Point3D point; PointOperation* doOp = new PointOperation(mitk::OpREMOVE, point, m_SelectedPointIndex); GetDataNode()->GetData()->ExecuteOperation(doOp); m_SelectedPointIndex = -1; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_NumberOfPoints--; return true; } else { return false; } } bool mitk::PointSetDataInteractor::IsClosedContour(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); Point3D point = positionEvent->GetPositionInWorld(); // iterate over point set and check if it contains a point close enough to the pointer to be selected if (GetPointIndexByPosition(point, timeStep) != -1 && m_PointSet->GetSize(timeStep) >= 3) { InternalEvent::Pointer event = InternalEvent::New(NULL, this, "ClosedContour"); positionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); return true; } } return false; } bool mitk::PointSetDataInteractor::MovePoint(StateMachineAction* stateMachineAction, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { IsClosedContour(stateMachineAction, interactionEvent); // Get time step from BaseRenderer int timeStep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D point = positionEvent->GetPositionInWorld(); m_PointSet->SetPoint(m_SelectedPointIndex, point, timeStep); GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); IsClosedContour(stateMachineAction,interactionEvent); return true; } else { return false; } } bool mitk::PointSetDataInteractor::MoveSet(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); // Vector that represents movement relative to last position Point3D movementVector; movementVector[0] = positionEvent->GetPositionInWorld()[0] - m_PointSet->GetPoint(m_SelectedPointIndex, timeStep)[0]; movementVector[1] = positionEvent->GetPositionInWorld()[1] - m_PointSet->GetPoint(m_SelectedPointIndex, timeStep)[1]; movementVector[2] = positionEvent->GetPositionInWorld()[2] - m_PointSet->GetPoint(m_SelectedPointIndex, timeStep)[2]; PointSet* points = dynamic_cast(GetDataNode()->GetData()); PointSet::PointsContainer* pointsContainer = points->GetPointSet(timeStep)->GetPoints(); // Iterate over point set and update each point Point3D newPoint; for (PointSet::PointsIterator it = pointsContainer->Begin(); it != pointsContainer->End(); it++) { newPoint[0] = m_PointSet->GetPoint(it->Index(), timeStep)[0] + movementVector[0]; newPoint[1] = m_PointSet->GetPoint(it->Index(), timeStep)[1] + movementVector[1]; newPoint[2] = m_PointSet->GetPoint(it->Index(), timeStep)[2] + movementVector[2]; m_PointSet->SetPoint(it->Index(), newPoint, timeStep); } GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } else { return false; } } bool mitk::PointSetDataInteractor::UnSelectPoint(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); Point3D point = positionEvent->GetPositionInWorld(); // iterate over point set and check if it contains a point close enough to the pointer to be selected int index = GetPointIndexByPosition(point, timeStep); // here it is ensured that we don't switch from one point being selected to another one being selected, // without accepting the unselect of the current point if (index == -1 || index != m_SelectedPointIndex) { m_SelectedPointIndex = -1; GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 0.0, 1.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } else { return false; } } bool mitk::PointSetDataInteractor::Abort(StateMachineAction*, InteractionEvent* interactionEvent) { InternalEvent::Pointer event = InternalEvent::New(NULL, this, IntDeactivateMe); interactionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); return true; } /* * Check whether the DataNode contains a pointset, if not create one and add it. */ void mitk::PointSetDataInteractor::DataNodeChanged() { if (GetDataNode().IsNotNull()) { // find proper place for this command! // maybe when DN is created ? GetDataNode()->SetBoolProperty("show contour", true); PointSet* points = dynamic_cast(GetDataNode()->GetData()); if (points == NULL) { m_PointSet = PointSet::New(); GetDataNode()->SetData(m_PointSet); } else { m_PointSet = points; } // load config file parameter: maximal number of points mitk::PropertyList::Pointer properties = GetAttributes(); std::string strNumber; if (properties->GetStringProperty("MaxPoints", strNumber)) { m_MaxNumberOfPoints = atoi(strNumber.c_str()); } } } bool mitk::PointSetDataInteractor::InitMove(StateMachineAction*, InteractionEvent*) { GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 1.0, 1.0)); return true; } bool mitk::PointSetDataInteractor::FinishMove(StateMachineAction* stateMachineAction, InteractionEvent* interactionEvent) { IsClosedContour(stateMachineAction, interactionEvent); GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 0.0, 0.0)); return true; } bool mitk::PointSetDataInteractor::InitMoveAll(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { m_LastMovePosition = positionEvent->GetPositionInWorld(); return true; } else { return false; } } + +void mitk::PointSetDataInteractor::SetAccuracy(float accuracy) +{ + m_SelectionAccuracy = accuracy; +} + +int mitk::PointSetDataInteractor::GetPointIndexByPosition(Point3D position, int time) +{ + + // iterate over point set and check if it contains a point close enough to the pointer to be selected + PointSet* points = dynamic_cast(GetDataNode()->GetData()); + int index = -1; + if (points == NULL) + { + return index; + } + PointSet::PointsContainer* pointsContainer = points->GetPointSet(time)->GetPoints(); + + float minDistance = m_SelectionAccuracy; + for (PointSet::PointsIterator it = pointsContainer->Begin(); it != pointsContainer->End(); it++) + { + float distance = sqrt(position.SquaredEuclideanDistanceTo(points->GetPoint(it->Index(), time))); // TODO: support time! + if (distance < minDistance) // if several points fall within the margin, choose the one with minimal distance to position + { // TODO: does this make sense, which unit is it? + index = it->Index(); + } + } + return index; +} diff --git a/Core/Code/Interactions/mitkPointSetDataInteractor.h b/Core/Code/Interactions/mitkPointSetDataInteractor.h index 4fbef1a603..75bee9b476 100644 --- a/Core/Code/Interactions/mitkPointSetDataInteractor.h +++ b/Core/Code/Interactions/mitkPointSetDataInteractor.h @@ -1,124 +1,141 @@ /*=================================================================== 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 mitkPointSetDataInteractor_h_ #define mitkPointSetDataInteractor_h_ #include "itkObject.h" #include "itkSmartPointer.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkDataInteractor.h" #include namespace mitk { /** * Class PointSetDataInteractor * \brief Implementation of the PointSetInteractor * * Interactor operates on a point set and supports to: * - add points * - remove points * - move single points * - move complete pointset * - select/unselect a point * * in 2d and 3d render windows. */ // Inherit from DataInteratcor, this provides functionality of a state machine and configurable inputs. class MITK_CORE_EXPORT PointSetDataInteractor: public DataInteractor { public: - mitkClassMacro(PointSetDataInteractor, DataInteractor); - itkNewMacro(Self); + mitkClassMacro(PointSetDataInteractor, DataInteractor) + itkNewMacro(Self) protected: PointSetDataInteractor(); virtual ~PointSetDataInteractor(); /** * Here actions strings from the loaded state machine pattern are mapped to functions of * the DataInteractor. These functions are called when an action from the state machine pattern is executed. */ virtual void ConnectActionsAndFunctions(); /** * This function is called when a DataNode has been set/changed. * It is used to initialize the DataNode, e.g. if no PointSet exists yet it is created * and added to the DataNode. */ virtual void DataNodeChanged(); + + /** + * Sets the maximum distance that is accepted when looking for a point at a certain position using the GetPointIndexByPosition function. + */ + void SetAccuracy(float accuracy); + + /** + * @ brief Return index in PointSet of the point that is within given accuracy to the provided position. + * + * Assumes that the DataNode contains a PointSet, if so it iterates over all points + * in the DataNode to check if it contains a point near the pointer position. + * If a point is found its index-position is returned, else -1 is returned. + */ + virtual int GetPointIndexByPosition(Point3D position, int time = 0); + /** Adds a point at the given coordinates. * Every time a point is added it is also checked if the maximal number of points is reached, * and if so an InternalEvent with the signal name "MaxNumberOfPoints" is triggered. */ virtual bool AddPoint(StateMachineAction*, InteractionEvent*); /** Removes point that is selected */ virtual bool RemovePoint(StateMachineAction*, InteractionEvent*); /** * Checks if new point is close enough to an old one, * if so, trigger the ClosedContour signal which can be caught by the state machine. */ virtual bool IsClosedContour(StateMachineAction*, InteractionEvent*); /** * Moves the currenlty selected point to the new coodinates. */ virtual bool MovePoint(StateMachineAction*, InteractionEvent*); /** * Initializes the movement, stores starting position. */ virtual bool InitMove(StateMachineAction*, InteractionEvent*); /** * Is called when a movement is finished, changes back to regular color. */ virtual bool FinishMove(StateMachineAction*, InteractionEvent*); /** * Stores original position from which movement can be calculated. */ virtual bool InitMoveAll(StateMachineAction*, InteractionEvent*); /** * Moves all points of the PointSet by the same vector, which is the relative distance from the * initialization point. */ virtual bool MoveSet(StateMachineAction*, InteractionEvent*); /** * Selects a point from the PointSet as currently active. */ virtual bool SelectPoint(StateMachineAction*, InteractionEvent*); /** * Unselects a point, e.g. the pointer coordinates point to empty space. */ virtual bool UnSelectPoint(StateMachineAction*, InteractionEvent*); /** * Calls for inactivation of the DataInteractor */ virtual bool Abort(StateMachineAction*, InteractionEvent*); private: PointSet::Pointer m_PointSet; int m_NumberOfPoints; // to keep track of number of points in pointset int m_MaxNumberOfPoints; // maximum of allowed number of points int m_SelectedPointIndex; // index of currently selected point in PointSet /** member to keep track of PointSet movements */ Point3D m_LastMovePosition; + + float m_SelectionAccuracy; // accuracy that's needed to select a point }; } #endif diff --git a/Core/Code/Interactions/mitkPointSetInteractor.cpp b/Core/Code/Interactions/mitkPointSetInteractor.cpp index 4c7b60118f..1fbee816a6 100644 --- a/Core/Code/Interactions/mitkPointSetInteractor.cpp +++ b/Core/Code/Interactions/mitkPointSetInteractor.cpp @@ -1,1132 +1,1119 @@ /*=================================================================== 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 "mitkPointSetInteractor.h" #include "mitkPointOperation.h" #include "mitkPositionEvent.h" #include "mitkPointSet.h" //#include "mitkStatusBar.h" #include "mitkDataNode.h" #include "mitkInteractionConst.h" #include "mitkAction.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkStateMachineFactory.h" #include "mitkStateTransitionOperation.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" //how precise must the user pick the point //default value const int PRECISION = 5; mitk::PointSetInteractor ::PointSetInteractor(const char * type, DataNode* dataNode, int n) :Interactor(type, dataNode), m_Precision(PRECISION), m_N(n) { if (m_N==0) { STATEMACHINE_WARN<<"Instanciation of PointSetInteractor which takes care of 0 points does't make sense!\n"; STATEMACHINE_WARN<<"Setting number of points to 1!\n"; m_N = 1; } m_LastPoint.Fill(0); m_SumVec.Fill(0); this->InitAccordingToNumberOfPoints(); } mitk::PointSetInteractor::~PointSetInteractor() { } //##Documentation //## overwritten cause this class can handle it better! float mitk::PointSetInteractor::CanHandleEvent(StateEvent const* stateEvent) const { float returnValue = 0.0; //if it is a key event that can be handled in the current state, then return 0.5 mitk::DisplayPositionEvent const *disPosEvent = dynamic_cast (stateEvent->GetEvent()); - //Key event handling: if (disPosEvent == NULL) { //check, if the current state has a transition waiting for that key event. if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) - { - return 0.5; - } + {return 0.5;} else - { - return 0; - } + {return 0;} } - //on MouseMove do nothing! if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove) - { - return 0; - } - + {return 0;} //get the time of the sender to look for the right transition. mitk::BaseRenderer* sender = stateEvent->GetEvent()->GetSender(); if (sender != NULL) { unsigned int timeStep = sender->GetTimeStep(m_DataNode->GetData()); //if the event can be understood and if there is a transition waiting for that event mitk::State const* state = this->GetCurrentState(timeStep); if (state!= NULL) if (state->GetTransition(stateEvent->GetId())!=NULL) returnValue = 0.5;//it can be understood - - mitk::PointSet *pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet != NULL ) { //if we have one point or more, then check if the have been picked if ( (pointSet->GetSize( timeStep ) > 0) && (pointSet->SearchPoint( disPosEvent->GetWorldPosition(), m_Precision, timeStep) > -1) ) - { - returnValue = 1.0; - } + {returnValue = 1.0;} } } return returnValue; } //TODO: add a new calculation of precision here! Input: StateEvent and Precision //the method does a 2D picking with display coordinates and display geometry. //Here the distance between the mouse position and the point is not as relative anymore! //float mitk::PointSetInteractor::CalculatePrecision(float precision, mitk::StateEvent stateEvent) //{ // mitk::BaseRenderer *renderer = stateEvent->GetEvent()->GetSender(); // if (renderer != NULL) // { // const mitk::DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry(); // if (displayGeometry != NULL) // displayGeometry->WorldToDisplay(, lineFrom); // precision = // } // // return precision; // //} void mitk::PointSetInteractor::UnselectAll( unsigned int timeStep, ScalarType timeInMS ) { mitk::PointSet *pointSet = dynamic_cast( m_DataNode->GetData() ); if ( pointSet == NULL ) { return; } mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet( timeStep ); if ( itkPointSet == NULL ) { return; } mitk::PointSet::PointsContainer::Iterator it, end; end = itkPointSet->GetPoints()->End(); for (it = itkPointSet->GetPoints()->Begin(); it != end; it++) { int position = it->Index(); PointSet::PointDataType pointData = {0, false, PTUNDEFINED}; itkPointSet->GetPointData( position, &pointData ); //then declare an operation which unselects this point; //UndoOperation as well! if ( pointData.selected ) { mitk::Point3D noPoint; noPoint.Fill( 0 ); mitk::PointOperation *doOp = new mitk::PointOperation( OpDESELECTPOINT, timeInMS, noPoint, position); if ( m_UndoEnabled ) { mitk::PointOperation *undoOp = new mitk::PointOperation(OpSELECTPOINT, timeInMS, noPoint, position); OperationEvent *operationEvent = new OperationEvent( pointSet, doOp, undoOp ); m_UndoController->SetOperationEvent( operationEvent ); } pointSet->ExecuteOperation( doOp ); if ( !m_UndoEnabled ) delete doOp; } } } void mitk::PointSetInteractor::SelectPoint( int position, unsigned int timeStep, ScalarType timeInMS ) { mitk::PointSet *pointSet = dynamic_cast< mitk::PointSet * >( m_DataNode->GetData() ); //if List is empty, then no select of a point can be done! if ( (pointSet == NULL) || (pointSet->GetSize( timeStep ) <= 0) ) { return; } //dummyPoint... not needed anyway mitk::Point3D noPoint; noPoint.Fill(0); mitk::PointOperation *doOp = new mitk::PointOperation( OpSELECTPOINT, timeInMS, noPoint, position); if ( m_UndoEnabled ) { mitk::PointOperation* undoOp = new mitk::PointOperation( OpDESELECTPOINT, timeInMS, noPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } pointSet->ExecuteOperation( doOp ); if ( !m_UndoEnabled ) delete doOp; } bool mitk::PointSetInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ) { bool ok = false;//for return type bool //checking corresponding Data; has to be a PointSet or a subclass mitk::PointSet* pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet == NULL ) { return false; } //get the timestep to support 3D+T const mitk::Event *theEvent = stateEvent->GetEvent(); mitk::ScalarType timeInMS = 0.0; //check if the current timestep has to be changed if ( theEvent ) { if (theEvent->GetSender() != NULL) { //additionaly to m_TimeStep we need timeInMS to satisfy the execution of the operations timeInMS = theEvent->GetSender()->GetTime(); } } //for reading on the points, Id's etc mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet( m_TimeStep ); if ( itkPointSet == NULL ) { return false; } mitk::PointSet::PointsContainer *points = itkPointSet->GetPoints(); /*Each case must watch the type of the event!*/ switch (action->GetActionId()) { case AcDONOTHING: ok = true; break; case AcCHECKOPERATION: //to check if the given Event is a DisplayPositionEvent. { mitk::DisplayPositionEvent const *dispPosEvent = dynamic_cast ( stateEvent->GetEvent()); if (dispPosEvent != NULL) { mitk::StateEvent newStateEvent(EIDYES, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); } else { mitk::StateEvent newStateEvent(EIDNO, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); } ok = true; break; } case AcADDPOINT: // Declare two operations: one for the selected state: deselect the last // one selected and select the new one the other operation is the add // operation: There the first empty place have to be found and the new // point inserted into that space { mitk::DisplayPositionEvent const *posEvent = dynamic_cast < const mitk::DisplayPositionEvent * > (stateEvent->GetEvent()); // Check if it is a DisplayEvent thrown in a 3D window. Then the // z-information is missing. Returning false might end in the state // full, but the last point couldn't be added, so the set wouldn't be // full. So a extra Action that checks the operationtype has been added. if ( posEvent == NULL ) { return false; } mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); // undo-supported deselect of all points in the DataList; if List is // empty, then nothing will be unselected this->UnselectAll( m_TimeStep, timeInMS ); // find the position, the point is to be added to: first entry with // empty index. If the Set is empty, then start with 0. if not empty, // then take the first index not occupied int lastPosition = 0; if (!points->empty()) { mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( it != end ) { if (!points->IndexExists(lastPosition)) break; ++it; ++lastPosition; } } PointOperation* doOp = new mitk::PointOperation( OpINSERT, timeInMS, itkPoint, lastPosition); if (m_UndoEnabled) { // difference between OpDELETE and OpREMOVE is, that OpDELETE deletes // a point at the end, and OpREMOVE deletes it from the given position // remove is better, cause we need the position to add or remove the // point anyway. We can get the last position from size() PointOperation *undoOp = new mitk::PointOperation( OpREMOVE, timeInMS, itkPoint, lastPosition); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Add point"); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; //the point is added and directly selected in PintSet. So no need to call OpSELECTPOINT ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcINITMOVEMENT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; // start of the Movement is stored to calculate the undoKoordinate // in FinishMovement m_LastPoint = posEvent->GetWorldPosition(); // initialize a value to calculate the movement through all // MouseMoveEvents from MouseClick to MouseRelease m_SumVec.Fill(0); ok = true; break; } case AcMOVESELECTED://moves all selected Elements { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D newPoint, resultPoint; newPoint = posEvent->GetWorldPosition(); // search the elements in the list that are selected then calculate the // vector, because only with the vector we can move several elements in // the same direction // newPoint - lastPoint = vector // then move all selected and set the lastPoint = newPoint. // then add all vectors to a summeryVector (to be able to calculate the // startpoint for undoOperation) mitk::Vector3D dirVector = newPoint - m_LastPoint; //sum up all Movement for Undo in FinishMovement m_SumVec = m_SumVec + dirVector; mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( it != end ) { int position = it->Index(); if ( pointSet->GetSelectInfo(position, m_TimeStep) )//if selected { PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); mitk::Point3D sumVec; sumVec[0] = pt[0]; sumVec[1] = pt[1]; sumVec[2] = pt[2]; resultPoint = sumVec + dirVector; PointOperation doOp(OpMOVE, timeInMS, resultPoint, position); //execute the Operation //here no undo is stored, because the movement-steps aren't interesting. // only the start and the end is interisting to store for undo. pointSet->ExecuteOperation(&doOp); } ++it; } m_LastPoint = newPoint;//for calculation of the direction vector ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcREMOVEPOINT://remove the given Point from the list { //if the point to be removed is given by the positionEvent: mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent != NULL) { mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); //search the point in the list int position = pointSet->SearchPoint(itkPoint, 0.0, m_TimeStep); //distance set to 0, cause we already got the exact point from last //State checkpointbut we also need the position in the list to remove it if (position>=0)//found a point { PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); itkPoint[0] = pt[0]; itkPoint[1] = pt[1]; itkPoint[2] = pt[2]; //Undo PointOperation* doOp = new mitk::PointOperation(OpREMOVE, timeInMS, itkPoint, position); if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpINSERT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Remove point"); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; /*now select the point "position-1", and if it is the first in list, then contine at the last in list*/ //only then a select of a point is possible! if (pointSet->GetSize( m_TimeStep ) > 0) { if (position>0)//not the first in list { this->SelectPoint( position-1, m_TimeStep, timeInMS ); } //it was the first point in list, that was removed, so select //the last in list else { position = pointSet->GetSize( m_TimeStep ) - 1; //last in list this->SelectPoint( position, m_TimeStep, timeInMS ); }//else }//if ok = true; } } else //no position is given so remove all selected elements { //delete all selected points //search for the selected one and then declare the operations! mitk::PointSet::PointsContainer::Iterator it, end; it = points->Begin(); end = points->End(); int position = 0; int previousExistingPosition = -1;//to recognize the last existing position; needed because the iterator gets invalid if the point is deleted! int lastDelPrevExistPosition = -1; //the previous position of the last deleted point while (it != end) { if (points->IndexExists(it->Index())) { //if point is selected if ( pointSet->GetSelectInfo(it->Index(), m_TimeStep) ) { //get the coordinates of that point to be undoable PointSet::PointType selectedPoint = it->Value(); mitk::Point3D itkPoint; itkPoint[0] = selectedPoint[0]; itkPoint[1] = selectedPoint[1]; itkPoint[2] = selectedPoint[2]; position = it->Index(); PointOperation* doOp = new mitk::PointOperation(OpREMOVE, timeInMS, itkPoint, position); //Undo if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpINSERT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Remove point"); m_UndoController->SetOperationEvent(operationEvent); } pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; //after delete the iterator is undefined, so start again //count to the last existing entry if (points->Size()>1 && points->IndexExists(previousExistingPosition)) { for (it = points->Begin(); it != points->End(); it++) { if (it->Index() == (unsigned int) previousExistingPosition) { lastDelPrevExistPosition = previousExistingPosition; break; //return if the iterator on the last existing position is found } } } else // size <= 1 or no previous existing position set { //search for the first existing position for (it = points->Begin(); it != points->End(); it++) if (points->IndexExists(it->Index())) { previousExistingPosition = it->Index(); break; } } //now that we have set the iterator, lets get sure, that the next it++ will not crash! if (it == end) { break; } }//if else { previousExistingPosition = it->Index(); } }//if index exists it++; }//while if (lastDelPrevExistPosition < 0)//the var has not been set because the first element was deleted and there was no prev position lastDelPrevExistPosition = previousExistingPosition; //go to the end /* * now select the point before the point/points that was/were deleted */ if (pointSet->GetSize( m_TimeStep ) > 0) //only then a select of a point is possible! { if (points->IndexExists(lastDelPrevExistPosition)) { this->SelectPoint( lastDelPrevExistPosition, m_TimeStep, timeInMS ); } else { //select the first existing element for (mitk::PointSet::PointsContainer::Iterator it = points->Begin(); it != points->End(); it++) if (points->IndexExists(it->Index())) { this->SelectPoint( it->Index(), m_TimeStep, timeInMS ); break; } } }//if ok = true; }//else }//case // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; // Remove all Points that have been set at once. // TODO: Undo function not supported yet. case AcREMOVEALL: { if ( !points->empty() ) { PointSet::PointType pt; mitk::PointSet::PointsContainer::Iterator it, end; it = points->Begin(); end = points->End(); int position = 0; while ( it != end ) { position = it->Index(); if ( points->IndexExists( position ) ) { pt = pointSet->GetPoint( position, m_TimeStep ); PointOperation doOp( OpREMOVE, timeInMS, pt, position ); ++it; pointSet->ExecuteOperation( &doOp ); } else it++; } } ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } //Checking if the Point transmitted is close enough to one point. Then //generate a new event with the point and let this statemaschine //handle the event. case AcCHECKELEMENT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent != NULL) { mitk::Point3D worldPoint = posEvent->GetWorldPosition(); int position = pointSet->SearchPoint( worldPoint, m_Precision, m_TimeStep ); if (position>=0)//found a point near enough to the given point { //get that point, the one meant by the user! PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); mitk::Point2D displPoint; displPoint[0] = worldPoint[0]; displPoint[1] = worldPoint[1]; //new Event with information YES and with the correct point mitk::PositionEvent newPosEvent(posEvent->GetSender(), Type_None, BS_NoButton, BS_NoButton, Key_none, displPoint, pt); mitk::StateEvent newStateEvent(EIDYES, &newPosEvent); //call HandleEvent to leave the guard-state this->HandleEvent( &newStateEvent ); ok = true; } else { //new Event with information NO mitk::StateEvent newStateEvent(EIDNO, posEvent); this->HandleEvent(&newStateEvent ); ok = true; } } else { MITK_DEBUG("OperationError")<GetType()<<" AcCHECKELEMENT expected PointOperation."; mitk::DisplayPositionEvent const *disPosEvent = dynamic_cast ( stateEvent->GetEvent()); if (disPosEvent != NULL) { //2d Koordinates for 3D Interaction; return false to redo //the last statechange mitk::StateEvent newStateEvent(EIDNO, disPosEvent); this->HandleEvent(&newStateEvent); ok = true; } } break; } case AcCHECKONESELECTED: //check if there is a point that is selected { if (pointSet->GetNumberOfSelected(m_TimeStep)>0) { mitk::StateEvent newStateEvent( EIDYES, theEvent); this->HandleEvent( &newStateEvent ); } else //not selected then call event EIDNO { //new Event with information NO mitk::StateEvent newStateEvent( EIDNO, theEvent); this->HandleEvent( &newStateEvent ); } ok = true; break; } case AcCHECKSELECTED: /*check, if the given point is selected: if no, then send EIDNO if yes, then send EIDYES*/ // check, if: because of the need to look up the point again, it is // possible, that we grab the wrong point in case there are two same points // so maybe we do have to set a global index for further computation, // as long, as the mouse is moved... { int position = -1; mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D worldPoint = posEvent->GetWorldPosition(); position = pointSet->SearchPoint(worldPoint, m_Precision, m_TimeStep); if (position>=0) { mitk::PositionEvent const *newPosEvent = new mitk::PositionEvent(posEvent->GetSender(), posEvent->GetType(), posEvent->GetButton(), posEvent->GetButtonState(), posEvent->GetKey(), posEvent->GetDisplayPosition(), posEvent->GetWorldPosition()); //if selected on true, then call Event EIDYES if (pointSet->GetSelectInfo(position, m_TimeStep)) { mitk::StateEvent newStateEvent( EIDYES, newPosEvent ); this->HandleEvent( &newStateEvent ); ok = true; //saving the spot for calculating the direction vector in moving m_LastPoint = posEvent->GetWorldPosition(); } else //not selected then call event EIDNO { //new Event with information NO mitk::StateEvent newStateEvent( EIDNO, newPosEvent ); this->HandleEvent( &newStateEvent ); ok = true; } delete newPosEvent; } //the position wasn't set properly. If necessary: search the given //point in list and set var position else { /* mitk::StatusBar::GetInstance()->DisplayText( "Message from mitkPointSetInteractor: Error in Actions! Check Config XML-file", 10000); */ ok = false; } break; } //generate Events if the set will be full after the addition of the // point or not. case AcCHECKNMINUS1: { // number of points not limited->pass on // "Amount of points in Set is smaller then N-1" if (m_N<0) { mitk::StateEvent newStateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else { if (pointSet->GetSize( m_TimeStep ) < m_N-1 ) //pointset after addition won't be full { mitk::StateEvent newStateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else //after the addition of a point, the container will be full { mitk::StateEvent newStateEvent(EIDSTLARGERNMINUS1, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; }//else }//else } break; case AcCHECKEQUALS1: { //the number of points in the list is 1 (or smaler) if (pointSet->GetSize( m_TimeStep ) <= 1) { mitk::StateEvent newStateEvent(EIDYES, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else //more than 1 points in list, so stay in the state! { mitk::StateEvent newStateEvent(EIDNO, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } } break; case AcCHECKNUMBEROFPOINTS: { //the number of points in the list is 1 (or smaler), so will be empty after delete if (pointSet->GetSize( m_TimeStep ) <= 1) { mitk::StateEvent newStateEvent(EIDEMPTY, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else if (pointSet->GetSize( m_TimeStep ) <= m_N || m_N <= -1) //m_N is set to unlimited points allowed or more than 1 points in list, but not full, so stay in the state! { // if the number of points equals m_N and no point of the point set is selected switch to state EIDEQUALSN if ((pointSet->GetSize( m_TimeStep ) == m_N)&&(pointSet->GetNumberOfSelected()==0)) { mitk::StateEvent newStateEvent(EIDEQUALSN, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } // if the number of points is small than or equal m_N and point(s) are selected stay in state else { mitk::StateEvent newStateEvent(EIDSMALLERN, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } } else //pointSet->GetSize( m_TimeStep ) >=m_N. // This can happen if the points were not added // by interaction but by loading a .mps file { mitk::StateEvent newStateEvent(EIDEQUALSN, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } } break; case AcSELECTPICKEDOBJECT://and deselect others { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); //search the point in the list int position = pointSet->SearchPoint(itkPoint, 0.0, m_TimeStep); //distance set to 0, cause we already got the exact point from last //State checkpoint but we also need the position in the list to move it if (position>=0)//found a point { //first deselect the other points //undoable deselect of all points in the DataList this->UnselectAll( m_TimeStep, timeInMS); PointOperation* doOp = new mitk::PointOperation(OpSELECTPOINT, timeInMS, itkPoint, position); //Undo if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpDESELECTPOINT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; ok = true; } // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcDESELECTOBJECT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); //search the point in the list int position = pointSet->SearchPoint(itkPoint, 0.0, m_TimeStep); //distance set to 0, cause we already got the exact point from last // State checkpoint but we also need the position in the list to move it if (position>=0)//found a point { //Undo PointOperation* doOp = new mitk::PointOperation(OpDESELECTPOINT, timeInMS, itkPoint, position); if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpSELECTPOINT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; ok = true; } // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcDESELECTALL: { //undo-supported able deselect of all points in the DataList this->UnselectAll( m_TimeStep, timeInMS ); ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcFINISHMOVEMENT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; //finish the movement: //the final point is m_LastPoint //m_SumVec stores the movement in a vector //the operation would not be necessary, but we need it for the undo Operation. //m_LastPoint is for the Operation //the point for undoOperation calculates from all selected //elements (point) - m_SumVec //search all selected elements and move them with undo-functionality. mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( it != end ) { int position = it->Index(); if ( pointSet->GetSelectInfo(position, m_TimeStep) )//if selected { PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); Point3D itkPoint; itkPoint[0] = pt[0]; itkPoint[1] = pt[1]; itkPoint[2] = pt[2]; PointOperation* doOp = new mitk::PointOperation(OpMOVE, timeInMS, itkPoint, position); if ( m_UndoEnabled )//&& (posEvent->GetType() == mitk::Type_MouseButtonRelease) { //set the undo-operation, so the final position is undo-able //calculate the old Position from the already moved position - m_SumVec mitk::Point3D undoPoint = ( itkPoint - m_SumVec ); PointOperation* undoOp = new mitk::PointOperation(OpMOVE, timeInMS, undoPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Move point"); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; } ++it; } //set every variable for movement calculation to zero // commented out: increases usebility in derived classes. /*m_LastPoint.Fill(0); m_SumVec.Fill(0);*/ //increase the GroupEventId, so that the Undo goes to here this->IncCurrGroupEventId(); ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcCLEAR: { this->Clear( m_TimeStep, timeInMS ); // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } default: return Superclass::ExecuteAction( action, stateEvent ); } // indicate modification of data tree node m_DataNode->Modified(); return ok; } void mitk::PointSetInteractor::Clear( unsigned int timeStep, ScalarType timeInMS ) { mitk::Point3D point; point.Fill(0); mitk::PointSet *pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet == NULL ) { return; } mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet( timeStep ); if ( itkPointSet == NULL ) { return; } //for reading on the points, Id's etc mitk::PointSet::PointsContainer *points = itkPointSet->GetPoints(); mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( (it != end) && (pointSet->GetSize( timeStep ) > 0) ) { point = pointSet->GetPoint( it->Index(), timeStep ); PointOperation *doOp = new mitk::PointOperation( OpREMOVE, timeInMS, point, it->Index()); //write to UndoMechanism if ( m_UndoEnabled ) { PointOperation *undoOp = new mitk::PointOperation( OpINSERT, timeInMS, point, it->Index()); OperationEvent *operationEvent = new OperationEvent( pointSet, doOp, undoOp ); m_UndoController->SetOperationEvent( operationEvent ); } //execute the Operation ++it; pointSet->ExecuteOperation( doOp ); if ( !m_UndoEnabled ) delete doOp; } //reset the statemachine this->ResetStatemachineToStartState(timeStep); } void mitk::PointSetInteractor::InitAccordingToNumberOfPoints() { if (m_DataNode == NULL) return; mitk::PointSet *pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet != NULL ) { //resize the CurrentStateVector this->ExpandStartStateVector(pointSet->GetPointSetSeriesSize()); for (unsigned int timestep = 0; timestep < pointSet->GetPointSetSeriesSize(); timestep++) { //go to new timestep this->UpdateTimeStep(timestep); int numberOfPoints = pointSet->GetSize( timestep ); if (numberOfPoints == 0) continue; //pointset is empty else { //we have a set of loaded points. Deselect all points, because they are all set to selected when added! this->UnselectAll(timestep); if (numberOfPointsHandleEvent( &newStateEvent ); } else if (numberOfPoints>=m_N) { if (numberOfPoints>m_N) { STATEMACHINE_WARN<<"Point Set contains more points than needed!\n";//display a warning that there are too many points } //get the currentState to state "Set full" const mitk::Event nullEvent(NULL, Type_User, BS_NoButton, BS_NoButton, Key_none); mitk::StateEvent newStateEvent(EIDEQUALSN, &nullEvent); this->HandleEvent( &newStateEvent ); } } } } return; } void mitk::PointSetInteractor::DataChanged() { this->InitAccordingToNumberOfPoints(); return; } diff --git a/Core/Code/Interactions/mitkPositionEvent.h b/Core/Code/Interactions/mitkPositionEvent.h index 306284fb9c..689d1d9c94 100644 --- a/Core/Code/Interactions/mitkPositionEvent.h +++ b/Core/Code/Interactions/mitkPositionEvent.h @@ -1,50 +1,55 @@ /*=================================================================== 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 POSITIONEVENT_H_HEADER_INCLUDED_C184F366 #define POSITIONEVENT_H_HEADER_INCLUDED_C184F366 #include #include "mitkDisplayPositionEvent.h" #include "mitkVector.h" namespace mitk { //##Documentation //## @brief Event that stores coordinates //## //## Stores display position of the mouse and 3D world position in mm. //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} mitk::PositionEvent is deprecated. Use mitk::InteractionPositionEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT PositionEvent : public DisplayPositionEvent { public: //##Documentation //## @brief Constructor with all necessary arguments. //## //## @param sender: the widget, that caused that event, so that it can be asked for worldCoordinates. changed later to a focus //## @param type, button, buttonState, key: information from the Event //## @param displPosition: the 2D Position e.g. from the mouse //## @param worldPosition: the 3D position e.g. from a picking PositionEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, const Point2D& displPosition, const Point3D& worldPosition); }; } // namespace mitk #endif /* POSITIONEVENT_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkState.h b/Core/Code/Interactions/mitkState.h index b7530e3e5b..7c43113e0f 100755 --- a/Core/Code/Interactions/mitkState.h +++ b/Core/Code/Interactions/mitkState.h @@ -1,133 +1,134 @@ /*=================================================================== -The Medical Imaging Interaction Toolkit (MITK) + The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. + 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. + 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. - -===================================================================*/ + See LICENSE.txt or http://www.mitk.org for details. + ===================================================================*/ #ifndef STATE_H_HEADER_INCLUDED_C19A8A5D #define STATE_H_HEADER_INCLUDED_C19A8A5D #include #include #include #include #include #include #include #include "mitkTransition.h" -namespace mitk { +namespace mitk +{ /** - * @brief represents one state with all its necessary information - * - * Name and ID are stored. Also methods for building up, connecting and - * parsing for well formed statemachines are present. - * This class holds a map of transitions to next States. - * @ingroup Interaction - **/ - class MITK_CORE_EXPORT State : public itk::Object + * @brief represents one state with all its necessary information + * + * Name and ID are stored. Also methods for building up, connecting and + * parsing for well formed statemachines are present. + * This class holds a map of transitions to next States. + * @ingroup Interaction + * \deprecatedSince{2013_03} mitk::State is deprecated. Please use the mitk::StateMachineState instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + + class MITK_CORE_EXPORT State: public itk::Object { public: - mitkClassMacro(State, itk::Object); + mitkClassMacro(State, itk::Object) /** - * @brief static New method to use SmartPointer - **/ - mitkNewMacro2Param(Self, std::string, int); + * @brief static New method to use SmartPointer + **/ + mitkNewMacro2Param(Self, std::string, int) typedef std::map StateMap; typedef std::map > TransitionMap; typedef StateMap::iterator StateMapIter; typedef TransitionMap::iterator TransMapIter; typedef TransitionMap::const_iterator TransMapConstIter; /** - * @brief Add a transition to the map of transitions. - * - * Instances of all added transitions are freed in destructor of this class. - **/ - bool AddTransition( Transition* transition ); + * @brief Add a transition to the map of transitions. + * + * Instances of all added transitions are freed in destructor of this class. + **/ + bool AddTransition(Transition* transition); /** - * @brief hashmap-lookup and returning the Transition. Returns NULL Pointer if not located - **/ + * @brief hashmap-lookup and returning the Transition. Returns NULL Pointer if not located + **/ const Transition* GetTransition(int eventId) const; /** - * @brief Returns the name. - **/ + * @brief Returns the name. + **/ std::string GetName() const; /** - * @brief Returns the Id. - **/ + * @brief Returns the Id. + **/ int GetId() const; /** - * @brief Returns a set of all next States. E.g. to parse through all States. - **/ + * @brief Returns a set of all next States. E.g. to parse through all States. + **/ std::set GetAllNextStates() const; /** - * @brief Check, if this event (eventId) leads to a state. - **/ + * @brief Check, if this event (eventId) leads to a state. + **/ bool IsValidEvent(int eventId) const; /** - * @brief Searches dedicated States of all Transitions and sets *nextState of these Transitions. - * Required for this is a List of all build States of that StateMachine (allStates). This way the StateMachine can be build up. - **/ + * @brief Searches dedicated States of all Transitions and sets *nextState of these Transitions. + * Required for this is a List of all build States of that StateMachine (allStates). This way the StateMachine can be build up. + **/ bool ConnectTransitions(StateMap* allStates); protected: /** - * @brief Default Constructor. Use ::New instead! - * Set the name and the Id of the state. - * Name is to maintain readability during debug and Id is to identify this state inside the StateMachinePattern - **/ + * @brief Default Constructor. Use ::New instead! + * Set the name and the Id of the state. + * Name is to maintain readability during debug and Id is to identify this state inside the StateMachinePattern + **/ State(std::string name, int id); /** - * @brief Default Destructor - **/ + * @brief Default Destructor + **/ ~State(); private: /** - * @brief Name of this State to support readability during debug - **/ + * @brief Name of this State to support readability during debug + **/ std::string m_Name; /** - * @brief Id of this State important for interaction mechanism in StateMachinePattern - * - * All states inside a StateMachinePattern (construct of several states connected with transitions and actions) have to have an own id with which it is identifyable. - **/ + * @brief Id of this State important for interaction mechanism in StateMachinePattern + * + * All states inside a StateMachinePattern (construct of several states connected with transitions and actions) have to have an own id with which it is identifyable. + **/ int m_Id; /** - * @brief map of transitions that lead from this state to the next state - **/ + * @brief map of transitions that lead from this state to the next state + **/ TransitionMap m_Transitions; }; } // namespace mitk - - #endif /* STATE_H_HEADER_INCLUDED_C19A8A5D */ diff --git a/Core/Code/Interactions/mitkStateEvent.h b/Core/Code/Interactions/mitkStateEvent.h index 53d05e7f88..0326d07952 100644 --- a/Core/Code/Interactions/mitkStateEvent.h +++ b/Core/Code/Interactions/mitkStateEvent.h @@ -1,66 +1,72 @@ /*=================================================================== 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 STATEEVENT_H_HEADER_INCLUDED_C188E5BF #define STATEEVENT_H_HEADER_INCLUDED_C188E5BF #include namespace mitk { class Event; //##Documentation //## @brief Class holding an mitk-event and the mitk-event-number for a statechange //## //## Holds an event, with which a statechange of a statemachine shall be //## done. iD represents the mitk-event-number, event all further necessary information like //## the MousePosition or a key. //## Not derived from event to hold only one object stateevent, pass it to the statemachines, //## set the next event and reuse this object //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} mitk::StateEvent is deprecated. It becomes obsolete. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT StateEvent { public: StateEvent(); //##Documentation //## @brief Constructor //## @param id: mitk internal EventID //## @param event: the information about the appeared event StateEvent(int id, Event const* event = 0 ); ~StateEvent(); //##Documentation //## @brief to set the params and reuse an object void Set(int id, Event const* event); int GetId() const; mitk::Event const* GetEvent() const; private: int m_Id; mitk::Event const* m_Event; }; } // namespace mitk #endif /* STATEEVENT_H_HEADER_INCLUDED_C188E5BF */ diff --git a/Core/Code/Interactions/mitkStateMachine.h b/Core/Code/Interactions/mitkStateMachine.h index 52e389b291..1a7e848569 100644 --- a/Core/Code/Interactions/mitkStateMachine.h +++ b/Core/Code/Interactions/mitkStateMachine.h @@ -1,301 +1,307 @@ /*=================================================================== 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 STATEMACHINE_H_HEADER_INCLUDED_C18896BD #define STATEMACHINE_H_HEADER_INCLUDED_C18896BD #include #include #include "mitkOperationActor.h" #include #include "mitkState.h" #include "mitkUndoModel.h" namespace mitk { class Action; class StateEvent; class UndoController; // base class of statem machine functors + class MITK_CORE_EXPORT TStateMachineFunctor { public: virtual bool DoAction(Action*, const StateEvent*)=0; // call using function virtual ~TStateMachineFunctor() {} }; // the template functor for arbitrary StateMachine derivations template class TSpecificStateMachineFunctor : public TStateMachineFunctor { public: // constructor - takes pointer to an object and pointer to a member and stores // them in two private variables TSpecificStateMachineFunctor(T* object, bool(T::*memberFunctionPointer)(Action*, const StateEvent*)) :m_Object(object), m_MemberFunctionPointer(memberFunctionPointer) { } virtual ~TSpecificStateMachineFunctor() {} // virtual destructor // override function "Call" virtual bool DoAction(Action* action, const StateEvent* stateEvent) { return (*m_Object.*m_MemberFunctionPointer)(action, stateEvent); // execute member function } private: T* m_Object; // pointer to object bool (T::*m_MemberFunctionPointer)(Action*, const StateEvent*); // pointer to member function }; /// Can be uses by derived classes of StateMachine to connect action IDs to methods /// Assumes that there is a typedef Classname Self in classes that use this macro #define CONNECT_ACTION(a, f) \ StateMachine::AddActionFunction(a, new TSpecificStateMachineFunctor(this, &Self::f)); #define STATEMACHINE_INFO MITK_INFO("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_WARN MITK_WARN("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_FATAL MITK_FATAL("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_ERROR MITK_ERROR("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_DEBUG MITK_DEBUG("StateMachine") << "[type: " << GetType() << "] " /** @brief Superior statemachine @ingroup Interaction Realizes the methods, that every statemachine has to have. Undo can be enabled and disabled through EnableUndo. To implement your own state machine, you have to derive a class from mitk::StateMachine and either - override ExecuteAction() or - Write bool methods that take (Action*, const StateEvent*) as parameter and use the CONNECT_ACTION macro in your constructor The second version is recommended, since it provides more structured code. The following piece of code demonstrates how to use the CONNECT_ACTION macro. The important detail is to provide a typedef classname Self \code class LightSwitch : public StateMachine { public: mitkClassMacro(LightSwitch, StateMachine); // this creates the Self typedef LightSwitch(const char*); bool DoSwitchOn(Action*, const StateEvent*); bool DoSwitchOff(Action*, const StateEvent*); } LightSwitch::LightSwitch(const char* type) :StateMachine(type) { // make sure that AcSWITCHON and AcSWITCHOFF are defined int constants somewhere (e.g. mitkInteractionConst.h) CONNECT_ACTION( AcSWITCHON, DoSwitchOn ); CONNECT_ACTION( AcSWITCHOFF, DoSwitchOff ); } bool LightSwitch::DoSwitchOn(Action*, const StateEvent*) { std::cout << "Enlightenment" << std::endl; } bool LightSwitch::DoSwitchOff(Action*, const StateEvent*) { std::cout << "Confusion" << std::endl; } \endcode What CONNECT_ACTION does, is call StateMachine::AddActionFunction(...) to add some function pointer wrapping class (functor) to a std::map of StateMachine. Whenever StateMachines ExecuteAction is called, StateMachine will lookup the desired Action in its map and call the appropriate method in your derived class. **/ + /** + * \deprecatedSince{2013_03} mitk::StateMachine is deprecated. Use mitk::EventStateMachine instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT StateMachine : public itk::Object, public mitk::OperationActor { public: mitkClassMacro(StateMachine,itk::Object); /** * @brief New Macro with one parameter for creating this object with static New(..) method **/ mitkNewMacro1Param(Self, const char*); /** * @brief Map to connect action IDs with method calls. Use AddActionFunction or (even better) the CONNECT_ACTION macro to fill the map. **/ typedef std::map ActionFunctionsMapType; /** * @brief Type for a vector of StartStatePointers **/ typedef std::vector StartStateVectorType; /** * @brief Get the name and with this the type of the StateMachine **/ std::string GetType() const; /** * @brief handles an Event accordingly to its current State * * Statechange with Undo functionality; * EventMapper gives each event a new objectEventId * and a StateMachine::ExecuteAction can descide weather it gets a * new GroupEventId or not, depending on its state (e.g. finishedNewObject then new GroupEventId). * Object- and group-EventId can also be accessed through static methods from OperationEvent **/ virtual bool HandleEvent(StateEvent const* stateEvent); /** * @brief calculates how good this statemachine can handle the event. * * Returns a value between 0 and 1 * where 0 represents not responsible and 1 represents definitive responsible! * Standard function to override if needed. * (Used by GlobalInteraction to decide which DESELECTED statemachine to send the event to.) **/ virtual float CanHandleEvent(const StateEvent *) const; /** * @brief Enables or disabled Undo. **/ void EnableUndo(bool enable); /** * @brief A statemachine is also an OperationActor due to the UndoMechanism. * * The statechange is done in ExecuteOperation, so that the statechange can be undone by UndoMechanism. * Is set private here and in superclass it is set public, so UndoController * can reach ist, but it can't be overwritten by a subclass * *ATTENTION*: THIS METHOD SHOULD NOT BE CALLED FROM OTHER CLASSES DIRECTLY! **/ virtual void ExecuteOperation(Operation* operation); /** * @brief Friend so that UndoModel can call ExecuteOperation for Undo. **/ friend class UndoModel; friend class GlobalInteraction; protected: /** * @brief Default Constructor. Obsolete to instanciate it with this method! Use ::New(..) method instead. Set the "type" and with this the pattern of the StateMachine **/ StateMachine(const char * type); /** * @brief Default Destructor **/ ~StateMachine(); /** * @brief Adds the Function to ActionList. **/ void AddActionFunction(int action, TStateMachineFunctor* functor); /** * @brief Method called in HandleEvent after Statechange. * * Each statechange has actions, which can be assigned by it's number. * If you are developing a new statemachine, declare all your operations here and send them to Undo-Controller and to the Data. * Object- and group-EventId can also be accessed through static methods from OperationEvent **/ virtual bool ExecuteAction(Action* action, StateEvent const* stateEvent); /** * @brief returns the current state **/ const State* GetCurrentState(unsigned int timeStep = 0) const; /** * @brief if true, then UndoFunctionality is enabled * * Default value is true; **/ bool m_UndoEnabled; /** * @brief Friend protected function of OperationEvent; that way all StateMachines can set GroupEventId to be incremented! **/ void IncCurrGroupEventId(); /** * @brief holds an UndoController, that can be accessed from all StateMachines. For ExecuteAction **/ UndoController* m_UndoController; /** * @brief Resets the current state from the given timeStep to the StartState with undo functionality! Use carefully! * @param[in] timeStep If the statemachine has several timesteps to take care of, specify the according timestep **/ void ResetStatemachineToStartState(unsigned int timeStep = 0); /** * @brief Check if the number of timeSteps is equal to the number of stored StartStates. Nothing is changed if the number is equal. **/ void ExpandStartStateVector(unsigned int timeSteps); /** * @brief initializes m_CurrentStateVector **/ void InitializeStartStates(unsigned int timeSteps); /** * @brief Update the TimeStep of the statemachine with undo-support if undo enabled **/ virtual void UpdateTimeStep(unsigned int timeStep); /** * @brief Current TimeStep if the data which is to be interacted on, has more than 1 TimeStep **/ unsigned int m_TimeStep; private: /** * @brief The type of the StateMachine. This string specifies the StateMachinePattern that is loaded from the StateMachineFactory. **/ std::string m_Type; /** * @brief Points to the current state. **/ StartStateVectorType m_CurrentStateVector; /** * @brief Map of the added Functions **/ ActionFunctionsMapType m_ActionFunctionsMap; }; } // namespace mitk #endif /* STATEMACHINE_H_HEADER_INCLUDED_C18896BD */ diff --git a/Core/Code/Interactions/mitkStateMachineFactory.h b/Core/Code/Interactions/mitkStateMachineFactory.h index 333bf33fae..9840a80224 100755 --- a/Core/Code/Interactions/mitkStateMachineFactory.h +++ b/Core/Code/Interactions/mitkStateMachineFactory.h @@ -1,227 +1,232 @@ /*=================================================================== 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 STATEMACHINEFACTORY_H_HEADER_INCLUDED_C19AEDDD #define STATEMACHINEFACTORY_H_HEADER_INCLUDED_C19AEDDD #include #include "mitkState.h" #include "mitkTransition.h" #include "mitkAction.h" #include #include #include namespace mitk { /** *@brief builds up all specifiyed statemachines and hold them for later access * * According to the XML-File every different statemachine is build up. A new * instance of a new StateMachine grabs a StartState of one certain * state machine. Two instances of one kind of state machine share that * state machine. * During buildprocess at runtime each state machine is parsed for well formed style. * Currently different interaction styles are not yet supported. * To add individual state machine patterns, call LoadBehavior(...) * and it will be parsed added to the internal list of patterns * * @ingroup Interaction **/ + /** + * \deprecatedSince{2013_03} StateMachineFactory is deprecated. Please use mitk::StateMachineContainer instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT StateMachineFactory : public vtkXMLParser { public: static StateMachineFactory *New(); vtkTypeMacro(StateMachineFactory,vtkXMLParser); /** * @brief Typedef for all states that are defined as start-states **/ typedef std::map StartStateMap; typedef StartStateMap::iterator StartStateMapIter; /** * @brief Typedef to be used for parsing all states of one statemachine **/ typedef std::set HistorySet; typedef HistorySet::iterator HistorySetIter; /** * @brief This type holds all states of one statemachine. **/ typedef std::map StateMachineMapType; /** * @brief this type holds all states of all statemachines so that a specific state can be accessed for persistence **/ typedef std::map AllStateMachineMapType; /** * @brief Returns the StartState of the StateMachine with the name type; * * Returns NULL if no entry with name type is found. * Here a Smartpointer is returned to ensure, that StateMachines are also considered during reference counting. **/ State* GetStartState(const char* type); /** * @brief loads the xml file filename and generates the necessary instances **/ bool LoadBehavior(std::string fileName); /** * @brief loads the xml string and generates the necessary instances **/ bool LoadBehaviorString(std::string xmlString); /** * @brief Try to load standard behavior file "StateMachine.xml" * * Search strategy: * \li try environment variable "MITKCONF" (path to "StateMachine.xml") * \li try "./StateMachine.xml" * \li try via source directory (using MITKROOT from cmake-created * mitkConfig.h) "MITKROOT/Interactions/mitkBaseInteraction/StateMachine.xml" **/ bool LoadStandardBehavior(); const std::string& GetLastLoadedBehavior() { return m_LastLoadedBehavior; } /** * @brief Adds the given pattern to the internal list of patterns * * Method to support addition of externaly loaded patterns. * Instances of states, transitions and actions are maintained within this class and freed on destruction. * The states already have to be connected by transitions and actions and checked for errors. * @params type name of the pattern to add. Will be used during initialization of a new interactor. * @params startState the start state of this pattern. * @params allStatesOfStateMachine a map of state ids and its states to hold their reference and delete them in destructor **/ bool AddStateMachinePattern(const char * type, mitk::State* startState, StateMachineMapType* allStatesOfStateMachine); /** * brief To enable StateMachine to access states **/ friend class StateMachine; protected: /** * @brief Default Constructor **/ StateMachineFactory(); /** * @brief Default Destructor **/ ~StateMachineFactory(); /** * @brief Derived from XMLReader **/ void StartElement (const char* elementName, const char **atts); /** * @brief Derived from XMLReader **/ void EndElement (const char* elementName); private: /** * @brief Derived from XMLReader **/ std::string ReadXMLStringAttribut( std::string name, const char** atts); /** * @brief Derived from XMLReader **/ float ReadXMLFloatAttribut( std::string name, const char** atts ); /** * @brief Derived from XMLReader **/ double ReadXMLDoubleAttribut( std::string name, const char** atts ); /** * @brief Derived from XMLReader **/ int ReadXMLIntegerAttribut( std::string name, const char** atts ); /** * @brief Derived from XMLReader **/ bool ReadXMLBooleanAttribut( std::string name, const char** atts ); /** * @brief Returns a Pointer to the desired state if found. **/ mitk::State* GetState( const char* type, int StateId ); /** * @brief Sets the pointers in Transition (setNextState(..)) according to the extracted xml-file content **/ bool ConnectStates(mitk::State::StateMap* states); /** * @brief Recusive method, that parses this pattern of the stateMachine and returns true if correct **/ bool RParse(mitk::State::StateMap* states, mitk::State::StateMapIter thisState, HistorySet *history); /** * @brief Holds all created States that are defined as StartState **/ StartStateMap m_StartStates; /** * @brief Holds all States of one StateMachine to build up the pattern. **/ mitk::State::StateMap m_AllStatesOfOneStateMachine; /** * @brief A pointer to a State to help building up the pattern **/ State::Pointer m_AktState; /** * @brief A pointer to a Transition to help building up the pattern **/ itk::WeakPointer m_AktTransition; /** * @brief A pointer to an Action to help building up the pattern **/ Action::Pointer m_AktAction; /** * @brief map to hold all statemachines to call GetState for friends **/ AllStateMachineMapType m_AllStateMachineMap; std::string m_LastLoadedBehavior; std::string m_AktStateMachineName; /** * @brief Variable to skip a state machine pattern if the state machine name is not unique **/ bool m_SkipStateMachine; }; } // namespace mitk #endif /* STATEMACHINEFACTORY_H_HEADER_INCLUDED_C19AEDDD */ diff --git a/Core/Code/Interactions/mitkStateMachineState.cpp b/Core/Code/Interactions/mitkStateMachineState.cpp index f501131398..155b41cb57 100755 --- a/Core/Code/Interactions/mitkStateMachineState.cpp +++ b/Core/Code/Interactions/mitkStateMachineState.cpp @@ -1,86 +1,86 @@ /*=================================================================== 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 "mitkStateMachineState.h" mitk::StateMachineState::StateMachineState(std::string stateName, std::string stateMode) : m_Name(stateName), m_StateMode(stateMode) { } -std::string mitk::StateMachineState::GetMode() +std::string mitk::StateMachineState::GetMode() const { return m_StateMode; } mitk::StateMachineState::~StateMachineState() { m_Transitions.clear(); } bool mitk::StateMachineState::AddTransition(StateMachineTransition::Pointer transition) { for (TransitionVector::iterator it = m_Transitions.begin(); it != m_Transitions.end(); ++it) { if (transition.GetPointer() == (*it).GetPointer()) return false; } m_Transitions.push_back(transition); return true; } -mitk::StateMachineTransition::Pointer mitk::StateMachineState::GetTransition(std::string eventClass, std::string eventVariant) +mitk::StateMachineTransition::Pointer mitk::StateMachineState::GetTransition(const std::string eventClass, const std::string eventVariant) { mitk::StateMachineTransition::Pointer t = mitk::StateMachineTransition::New("", eventClass, eventVariant); for (TransitionVector::iterator it = m_Transitions.begin(); it != m_Transitions.end(); ++it) { if (**it == *t) // do not switch it and t, order matters, see mitk::StateMachineTransition == operator return *it; } return NULL; } -std::string mitk::StateMachineState::GetName() +std::string mitk::StateMachineState::GetName() const { return m_Name; } //##Documentation //## Post-processing step, when builing StateMachine from XML. //## Parse all transitions and find the State that matches the String-Name. bool mitk::StateMachineState::ConnectTransitions(StateMap *allStates) { for (TransitionVector::iterator transIt = m_Transitions.begin(); transIt != m_Transitions.end(); ++transIt) { bool found = false; for (StateMap::iterator stateIt = allStates->begin(); stateIt != allStates->end(); ++stateIt) { if ((*stateIt)->GetName() == (*transIt)->GetNextStateName()) { (*transIt)->SetNextState(*stateIt); found = true; break; } } if (!found) { MITK_WARN<< "Target State not found in StateMachine."; return false; // only reached if no state matching the string is found } } return true; } diff --git a/Core/Code/Interactions/mitkStateMachineState.h b/Core/Code/Interactions/mitkStateMachineState.h index 3d7a810b8a..b83c100ec1 100755 --- a/Core/Code/Interactions/mitkStateMachineState.h +++ b/Core/Code/Interactions/mitkStateMachineState.h @@ -1,86 +1,90 @@ /*=================================================================== 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 SMSTATE_H_HEADER_INCLUDED_C19A8A5D #define SMSTATE_H_HEADER_INCLUDED_C19A8A5D #include #include #include #include #include #include "mitkStateMachineTransition.h" namespace mitk { - - // Dispatcher and State Modes + /** + * \class StateMachineState + * Represents a state of a state machine pattern. + * It holds transitions to other states (mitk::StateMachineTransition) and the mode of the current state, see + * m_StateMode . + */ class MITK_CORE_EXPORT StateMachineState : public itk::Object { public: mitkClassMacro(StateMachineState, itk::Object); mitkNewMacro2Param(Self, std::string, std::string); typedef std::vector StateMap; typedef std::vector TransitionVector; bool AddTransition( StateMachineTransition::Pointer transition ); /** * @brief Return Transition which matches given event description. **/ - StateMachineTransition::Pointer GetTransition(std::string eventClass, std::string eventVariant); + StateMachineTransition::Pointer GetTransition(const std::string eventClass,const std::string eventVariant); /** * @brief Returns the name. **/ - std::string GetName(); + std::string GetName() const; - std::string GetMode(); + std::string GetMode() const; /** * @brief Searches dedicated States of all Transitions and sets *nextState of these Transitions. * Required for this is a List of all build States of that StateMachine (allStates). This way the StateMachine can be build up. **/ bool ConnectTransitions(StateMap* allStates); protected: StateMachineState(std::string name, std::string stateMode); ~StateMachineState(); private: /** * @brief Name of this State. **/ std::string m_Name; /** * State Modus, which determines the behavior of the dispatcher. A State can be in three different modes: * REGULAR - standard dispatcher behavior * GRAB_INPUT - all events are given to the statemachine in this modus, if they are not processed by this statemachine the events are dropped. * PREFER_INPUT - events are first given to this statemachine, and if not processed, offered to the other statemachines. */ std::string m_StateMode; /** * @brief map of transitions that lead from this state to the next state **/ TransitionVector m_Transitions; }; } // namespace mitk #endif /* SMSTATE_H_HEADER_INCLUDED_C19A8A5D */ diff --git a/Core/Code/Interactions/mitkStateMachineTransition.cpp b/Core/Code/Interactions/mitkStateMachineTransition.cpp index e8e73cf893..fcce659d99 100755 --- a/Core/Code/Interactions/mitkStateMachineTransition.cpp +++ b/Core/Code/Interactions/mitkStateMachineTransition.cpp @@ -1,96 +1,96 @@ /*=================================================================== 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 "mitkStateMachineTransition.h" #include "mitkStateMachineAction.h" #include "mitkStateMachineState.h" #include "mitkEventFactory.h" #include "mitkInteractionEventConst.h" mitk::StateMachineTransition::StateMachineTransition(std::string nextStateName, std::string eventClass, std::string eventVariant) : m_EventClass(eventClass), m_EventVariant(eventVariant), m_NextStateName(nextStateName) { PropertyList::Pointer propertyList = PropertyList::New(); propertyList->SetStringProperty(xmlParameterEventClass.c_str(), eventClass.c_str()); m_TransitionEvent = EventFactory::CreateEvent(propertyList); } -bool mitk::StateMachineTransition::operator ==(const StateMachineTransition& transition) +bool mitk::StateMachineTransition::operator ==(const StateMachineTransition& transition) const { // Create event based on incoming event type, // then try to cast it to the type of event that this transition holds, // if this is possible, the variant is checked // check for NULL since a corrupted state machine might cause an empty event if (m_TransitionEvent.IsNull()) { return false; } PropertyList::Pointer propertyList = PropertyList::New(); propertyList->SetStringProperty(xmlParameterEventClass.c_str(), transition.m_EventClass.c_str()); InteractionEvent::Pointer tmpEvent = EventFactory::CreateEvent(propertyList); if (tmpEvent.IsNull()) { return false; } - if (tmpEvent->IsSubClassOf(m_TransitionEvent.GetPointer())) + if (m_TransitionEvent->IsSuperClassOf(tmpEvent.GetPointer())) { return (this->m_EventVariant == transition.m_EventVariant); } else { // if event variants match, but super class condition is violated // this means that the configuration file, implements a class that does not // support the type in the state machine. if (this->m_EventVariant == transition.m_EventVariant) { MITK_WARN<< "Event type in Statemachine " << m_EventClass << " is not compatible to configuration class " << transition.m_EventClass; } return false; } } mitk::StateMachineTransition::~StateMachineTransition() { //needed for correct reference counting of mitkState//, for real??? m_NextState = NULL; m_Actions.clear(); } void mitk::StateMachineTransition::AddAction(StateMachineAction::Pointer action) { m_Actions.push_back(action); } -mitk::StateMachineState::Pointer mitk::StateMachineTransition::GetNextState() +mitk::StateMachineState::Pointer mitk::StateMachineTransition::GetNextState() const { return m_NextState; } std::string mitk::StateMachineTransition::GetNextStateName() const { return m_NextStateName; } std::vector mitk::StateMachineTransition::GetActions() const { return m_Actions; } void mitk::StateMachineTransition::SetNextState(SpStateMachineState nextState) { m_NextState = nextState; } diff --git a/Core/Code/Interactions/mitkStateMachineTransition.h b/Core/Code/Interactions/mitkStateMachineTransition.h index a533ef0532..fdc94e2802 100755 --- a/Core/Code/Interactions/mitkStateMachineTransition.h +++ b/Core/Code/Interactions/mitkStateMachineTransition.h @@ -1,94 +1,94 @@ /*=================================================================== 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 SMTRANSITION_H_HEADER_INCLUDED #define SMTRANSITION_H_HEADER_INCLUDED #include #include "mitkCommon.h" #include #include #include #include "mitkStateMachineAction.h" #include "mitkInteractionEvent.h" namespace mitk { class StateMachineState; typedef std::vector ActionVectorType; typedef itk::SmartPointer SpStateMachineState; /** * \class StateMachineTransition * @brief Connects two states, and holds references to actions that are executed on transition. * * @ingroup Interaction **/ class MITK_CORE_EXPORT StateMachineTransition: public itk::Object { public: mitkClassMacro(StateMachineTransition, itk::Object); mitkNewMacro3Param(Self, std::string,std::string,std::string); void AddAction(StateMachineAction::Pointer action); - SpStateMachineState GetNextState(); + SpStateMachineState GetNextState() const; std::string GetNextStateName() const; /** * Check for equality. Equality is given if event variant is the same and * classes are the same or the first argument is a superclass of the second. * \warn Here the order of arguments matters. ! */ - bool operator==(const StateMachineTransition& transition); + bool operator==(const StateMachineTransition& transition) const; /** * @brief Get an iterator on the first action in list. **/ ActionVectorType GetActions() const; /** * @brief Set the next state of this object. **/ void SetNextState(SpStateMachineState nextState); protected: StateMachineTransition(std::string nextStateName, std::string eventClass, std::string eventVariant); virtual ~StateMachineTransition(); // Triggering Event std::string m_EventClass; std::string m_EventVariant; private: SpStateMachineState m_NextState; std::string m_NextStateName; InteractionEvent::Pointer m_TransitionEvent; /** * @brief The list of actions, that are executed if this transition is done. **/ std::vector m_Actions; }; } // namespace mitk #endif /* SMTRANSITION_H_HEADER_INCLUDED */ diff --git a/Core/Code/Interactions/mitkTransition.h b/Core/Code/Interactions/mitkTransition.h index d4233365ae..ce9cfb5132 100755 --- a/Core/Code/Interactions/mitkTransition.h +++ b/Core/Code/Interactions/mitkTransition.h @@ -1,140 +1,144 @@ /*=================================================================== 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 TRANSITION_H_HEADER_INCLUDED_C19AE06B #define TRANSITION_H_HEADER_INCLUDED_C19AE06B #include #include #include #include #include "mitkAction.h" namespace mitk { class State; /** * @brief Connection of two states * * A transition connects two states. * Several actions are stored, that have to be executed after the statechange. * @ingroup Interaction - **/ + * + * \deprecatedSince{2013_03} mitk::Transition is deprecated. Use mitk::StateMachineTransition instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT Transition { public: typedef std::vector< mitk::Action::Pointer > ActionVectorType; typedef ActionVectorType::iterator ActionVectorIterator; typedef const ActionVectorIterator ActionVectorConstIterator; /** * @brief Add the action to this object. **/ void AddAction( Action* action ); /** * @brief Return the name of this object. **/ std::string GetName() const; /** * @brief Get the next state of this object. **/ State* GetNextState() const; /** * @brief Get the Id of the next state of this object. **/ int GetNextStateId() const; /** * @brief Get the eventId of this object. **/ int GetEventId() const; /** * @brief Get the number of actions. **/ unsigned int GetActionCount() const; /** * @brief Get an interator on the first action in list. **/ ActionVectorIterator GetActionBeginIterator() const; /** * @brief Get an interator behind the last action in list. **/ ActionVectorConstIterator GetActionEndIterator() const; /** * @brief Returns true if the given eventId is equal to this eventId. **/ bool IsEvent(int eventId) const; /** * @brief Set the next state of this object. **/ void SetNextState(State* state); /** * @brief Default Constructor * Sets the necessary informations name (to enhance readability during debug), * nextStateId (the Id of the next state) and eventId (the Id of the event that causes the statechange). **/ Transition(std::string name, int nextStateId, int eventId); /** * @brief Default Denstructor **/ ~Transition(); private: /** * @brief For better debugging and reading it stores the name of this. **/ std::string m_Name; /** * @brief a Pointer to the next state of this object. **/ itk::WeakPointer m_NextState; /** * @brief The Id of the next state. **/ int m_NextStateId; /** * @brief The eventId which is associated to this object. **/ int m_EventId; /** * @brief The list of actions, that are executed if this transition is done. **/ mutable std::vector m_Actions; }; } // namespace mitk #endif /* TRANSITION_H_HEADER_INCLUDED_C19AE06B */ diff --git a/Core/Code/Interactions/mitkVtkEventAdapter.h b/Core/Code/Interactions/mitkVtkEventAdapter.h index 7ba8e0e22e..4fc6265f35 100644 --- a/Core/Code/Interactions/mitkVtkEventAdapter.h +++ b/Core/Code/Interactions/mitkVtkEventAdapter.h @@ -1,81 +1,81 @@ /*=================================================================== 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 MITKVTKEVENTADAPTER_H_ #define MITKVTKEVENTADAPTER_H_ // INTERACTION LEGACY #include #include #include #include "mitkMousePressEvent.h" #include "mitkMouseReleaseEvent.h" #include "mitkMouseMoveEvent.h" #include "mitkMouseWheelEvent.h" #include "mitkInteractionKeyEvent.h" #include "vtkRenderWindowInteractor.h" //##Documentation //## @brief Generates MITK events from VTK //## //## This class is the NON-QT dependent pendant to QmitkEventAdapter. //## It provides static functions to set up MITK events from VTK source data //## //## @ingroup Interaction namespace mitk { class BaseRenderer; class MITK_EXPORT VtkEventAdapter { public: /** - * \deprecated{Please switch to the appropriate AdaptMousePress/Move/Release-Event function.} + \deprecatedSince{2013_03} This method can be replaced by mitk::AdaptMousePressEvent / mitk::AdaptMouseMoveEvent / mitk::AdaptMouseReleaseEvent + */ + DEPRECATED(static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi)); + /** + \deprecatedSince{2013_03} This method can be replaced by mitk::AdaptMouseWheelEvent */ - static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); - /** - * \deprecated{Please switch to the AdaptMouseWheelEvent function.} - */ - static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); - /** - * \deprecated{Please switch to the AdaptInteractionKeyEvent function.} + DEPRECATED(static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi)); + /** + \deprecatedSince{2013_03} This method can be replaced by mitk::AdaptInteractionKeyEvent */ - static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); + DEPRECATED(static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi)); /** New events compatible with the revised interaction scheme */ static mitk::MousePressEvent::Pointer AdaptMousePressEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::MouseMoveEvent::Pointer AdaptMouseMoveEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::MouseReleaseEvent::Pointer AdaptMouseReleaseEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::MouseWheelEvent::Pointer AdaptMouseWheelEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::InteractionKeyEvent::Pointer AdaptInteractionKeyEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); /** * Vtk events do not provide a button state for MouseMove events, therefore this map is used to keep a record of the * button state, which then can be used to provide information for MITK MouseMove events. */ static std::map buttonStateMap; }; } #endif /*QMITKEVENTADAPTER_H_*/ diff --git a/Core/Code/Interactions/mitkWheelEvent.h b/Core/Code/Interactions/mitkWheelEvent.h index 79ca75c1d2..4425703d26 100644 --- a/Core/Code/Interactions/mitkWheelEvent.h +++ b/Core/Code/Interactions/mitkWheelEvent.h @@ -1,55 +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 WheelEvent_H_HEADER_INCLUDED_C184F366 #define WheelEvent_H_HEADER_INCLUDED_C184F366 #include #include "mitkDisplayPositionEvent.h" #include "mitkVector.h" namespace mitk { //##Documentation //## @brief Event that stores coordinates and rotation on mouse wheel events //## //## Stores display position of the mouse and 3D world position in mm. //## @ingroup Interaction + /** + * \deprecatedSince{2013_03} mitk::WheelEvent is deprecated. Use mitk::MouseWheelEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT WheelEvent : public DisplayPositionEvent { public: //##Documentation //## @brief Constructor with all necessary arguments. //## //## @param sender: the widget, that caused that event, so that it can be asked for worldCoordinates. changed later to a focus //## @param type, button, buttonState, key: information from the Event //## @param displPosition: the 2D Position e.g. from the mouse //## @param worldPosition: the 3D position e.g. from a picking //## @param delta: the movement of the mousewheel WheelEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, const Point2D& displPosition, int delta); int GetDelta() const; protected: int m_Delta; }; } // namespace mitk #endif /* WheelEvent_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkEventObserver.cpp b/Core/Code/Interfaces/mitkInteractionEventObserver.cpp similarity index 60% rename from Core/Code/Interactions/mitkEventObserver.cpp rename to Core/Code/Interfaces/mitkInteractionEventObserver.cpp index cda48cae0d..785f1ef263 100644 --- a/Core/Code/Interactions/mitkEventObserver.cpp +++ b/Core/Code/Interfaces/mitkInteractionEventObserver.cpp @@ -1,34 +1,22 @@ /*=================================================================== 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 "mitkEventObserver.h" +#include "mitkInteractionEventObserver.h" -void mitk::EventObserver::Notify(InteractionEvent::Pointer /*interactionEvent*/, bool /*isHandled*/) -{ -} - -mitk::EventObserver::EventObserver() -{ -} - -mitk::EventObserver::~EventObserver() -{ -} -bool mitk::EventObserver::FilterEvents(InteractionEvent* /*interactionEvent*/, DataNode* /*dataNode*/) +mitk::InteractionEventObserver::~InteractionEventObserver() { - return true; } diff --git a/Core/Code/Interactions/mitkEventObserver.h b/Core/Code/Interfaces/mitkInteractionEventObserver.h similarity index 58% rename from Core/Code/Interactions/mitkEventObserver.h rename to Core/Code/Interfaces/mitkInteractionEventObserver.h index fd479a0238..49f44208fc 100644 --- a/Core/Code/Interactions/mitkEventObserver.h +++ b/Core/Code/Interfaces/mitkInteractionEventObserver.h @@ -1,80 +1,62 @@ /*=================================================================== 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 EventObserver_h -#define EventObserver_h +#ifndef InteractionEventObserver_h +#define InteractionEventObserver_h -#include "itkObject.h" -#include "itkObjectFactory.h" -#include "mitkCommon.h" -#include "mitkEventStateMachine.h" -#include "mitkInteractionEvent.h" #include +#include "mitkServiceInterface.h" +#include "mitkInteractionEvent.h" namespace mitk { /** - * \class EventObserver - * \brief Base class to implement EventObservers. + * \class InteractionEventObserver + * \brief Base class to implement InteractionEventObservers. * * This class also provides state machine infrastructure, * but usage thereof is optional. See the Notify method for more information. */ - class MITK_CORE_EXPORT EventObserver : public EventStateMachine { - - public: - mitkClassMacro(EventObserver,EventHandler); - itkNewMacro(Self); - /** + struct MITK_CORE_EXPORT InteractionEventObserver + { + virtual ~InteractionEventObserver(); + /** * By this method all registered EventObersers are notified about every InteractionEvent, * the isHandled flag indicates if a DataInteractor has already handled that event. - * EventObserver that trigger an action when observing an event may consider + * InteractionEventObserver that trigger an action when observing an event may consider * this in order to not confuse the user by, triggering several independent action with one * single user event (such as a mouse click) * - * If you want to use the EventObserver as a state machine give the event to the state machine by implementing, e.g. + * If you want to use the InteractionEventObserver as a state machine give the event to the state machine by implementing, e.g. \code - void mitk::EventObserver::Notify(InteractionEvent::Pointer interactionEvent, bool isHandled) + void mitk::InteractionEventObserver::Notify(InteractionEvent::Pointer interactionEvent, bool isHandled) { if (!isHandled) { this->HandleEvent(interactionEvent, NULL); } } \endcode - */ - virtual void Notify(InteractionEvent::Pointer interactionEvent,bool isHandled); - - protected: - EventObserver(); - virtual ~EventObserver(); - - /** - * This overwrites the FilterEvents function of the EventStateMachine to ignore the DataNode, since EventObservers are not associated with one. - */ + * This overwrites the FilterEvents function of the EventStateMachine to ignore the DataNode, since InteractionEventObservers are not associated with one. virtual bool FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode); - - protected: - - - private: - + */ + virtual void Notify(InteractionEvent* interactionEvent,bool isHandled) = 0; }; } /* namespace mitk */ - -#endif /* EventObserver_h */ +US_DECLARE_SERVICE_INTERFACE(mitk::InteractionEventObserver, "org.mitk.InteractionEventObserver") +#endif /* InteractionEventObserver_h */ diff --git a/Core/Code/Rendering/mitkBaseRenderer.cpp b/Core/Code/Rendering/mitkBaseRenderer.cpp index 845a0b27e2..d6c516ed04 100644 --- a/Core/Code/Rendering/mitkBaseRenderer.cpp +++ b/Core/Code/Rendering/mitkBaseRenderer.cpp @@ -1,830 +1,835 @@ /*=================================================================== 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 "mitkBaseRenderer.h" #include "mitkMapper.h" #include "mitkResliceMethodProperty.h" // Geometries #include "mitkPlaneGeometry.h" #include "mitkSlicedGeometry3D.h" // Controllers #include "mitkCameraController.h" #include "mitkSliceNavigationController.h" #include "mitkCameraRotationController.h" #include "mitkVtkInteractorCameraController.h" #ifdef MITK_USE_TD_MOUSE #include "mitkTDMouseVtkCameraController.h" #else #include "mitkCameraController.h" #endif #include "mitkVtkLayerController.h" // Events // TODO: INTERACTION_LEGACY #include "mitkEventMapper.h" #include "mitkGlobalInteraction.h" #include "mitkPositionEvent.h" #include "mitkDisplayPositionEvent.h" #include "mitkProperties.h" #include "mitkWeakPointerProperty.h" #include "mitkInteractionConst.h" // VTK #include #include #include #include #include #include #include mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap; mitk::BaseRenderer* mitk::BaseRenderer::GetInstance(vtkRenderWindow * renWin) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).first == renWin) return (*mapit).second; } return NULL; } void mitk::BaseRenderer::AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer) { if (renWin == NULL || baseRenderer == NULL) return; // ensure that no BaseRenderer is managed twice mitk::BaseRenderer::RemoveInstance(renWin); baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer)); } void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow* renWin) { BaseRendererMapType::iterator mapit = baseRendererMap.find(renWin); if (mapit != baseRendererMap.end()) baseRendererMap.erase(mapit); } mitk::BaseRenderer* mitk::BaseRenderer::GetByName(const std::string& name) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).second->m_Name == name) return (*mapit).second; } return NULL; } vtkRenderWindow* mitk::BaseRenderer::GetRenderWindowByName(const std::string& name) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).second->m_Name == name) return (*mapit).first; } return NULL; } mitk::BaseRenderer::BaseRenderer(const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm) : m_RenderWindow(NULL), m_VtkRenderer(NULL), m_MapperID(defaultMapper), m_DataStorage(NULL), m_RenderingManager(rm), m_LastUpdateTime(0), m_CameraController( NULL), m_SliceNavigationController(NULL), m_CameraRotationController(NULL), /*m_Size(),*/ m_Focused(false), m_WorldGeometry(NULL), m_TimeSlicedWorldGeometry(NULL), m_CurrentWorldGeometry(NULL), m_CurrentWorldGeometry2D(NULL), m_DisplayGeometry( NULL), m_Slice(0), m_TimeStep(), m_CurrentWorldGeometry2DUpdateTime(), m_DisplayGeometryUpdateTime(), m_TimeStepUpdateTime(), m_WorldGeometryData( NULL), m_DisplayGeometryData(NULL), m_CurrentWorldGeometry2DData(NULL), m_WorldGeometryNode(NULL), m_DisplayGeometryNode(NULL), m_CurrentWorldGeometry2DNode( NULL), m_DisplayGeometryTransformTime(0), m_CurrentWorldGeometry2DTransformTime(0), m_Name(name), /*m_Bounds(),*/m_EmptyWorldGeometry( true), m_DepthPeelingEnabled(true), m_MaxNumberOfPeels(100), m_NumberOfVisibleLODEnabledMappers(0) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; if (name != NULL) { m_Name = name; } else { m_Name = "unnamed renderer"; itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name."); } if (renWin != NULL) { m_RenderWindow = renWin; m_RenderWindow->Register(NULL); } else { itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present."); } m_Size[0] = 0; m_Size[1] = 0; //instances.insert( this ); //adding this BaseRenderer to the List of all BaseRenderer // TODO: INTERACTION_LEGACY m_RenderingManager->GetGlobalInteraction()->AddFocusElement(this); - m_BindDispatcherInteractor = mitk::BindDispatcherInteractor::New(); + m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor(); WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object*) this); m_CurrentWorldGeometry2D = mitk::PlaneGeometry::New(); m_CurrentWorldGeometry2DData = mitk::Geometry2DData::New(); m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D); m_CurrentWorldGeometry2DNode = mitk::DataNode::New(); m_CurrentWorldGeometry2DNode->SetData(m_CurrentWorldGeometry2DData); m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000)); m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New()); m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1)); m_CurrentWorldGeometry2DTransformTime = m_CurrentWorldGeometry2DNode->GetVtkTransform()->GetMTime(); m_DisplayGeometry = mitk::DisplayGeometry::New(); m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D); m_DisplayGeometryData = mitk::Geometry2DData::New(); m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry); m_DisplayGeometryNode = mitk::DataNode::New(); m_DisplayGeometryNode->SetData(m_DisplayGeometryData); m_DisplayGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_DisplayGeometryTransformTime = m_DisplayGeometryNode->GetVtkTransform()->GetMTime(); mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::SliceNavigationController::New("navigation"); sliceNavigationController->SetRenderer(this); sliceNavigationController->ConnectGeometrySliceEvent(this); sliceNavigationController->ConnectGeometryUpdateEvent(this); sliceNavigationController->ConnectGeometryTimeEvent(this, false); m_SliceNavigationController = sliceNavigationController; m_CameraRotationController = mitk::CameraRotationController::New(); m_CameraRotationController->SetRenderWindow(m_RenderWindow); m_CameraRotationController->AcquireCamera(); //if TD Mouse Interaction is activated, then call TDMouseVtkCameraController instead of VtkInteractorCameraController #ifdef MITK_USE_TD_MOUSE m_CameraController = mitk::TDMouseVtkCameraController::New(); #else m_CameraController = mitk::CameraController::New(NULL); #endif m_VtkRenderer = vtkRenderer::New(); if (mitk::VtkLayerController::GetInstance(m_RenderWindow) == NULL) { mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer); mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } else mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } mitk::BaseRenderer::~BaseRenderer() { if (m_VtkRenderer != NULL) { m_VtkRenderer->Delete(); m_VtkRenderer = NULL; } if (m_CameraController.IsNotNull()) m_CameraController->SetRenderer(NULL); m_RenderingManager->GetGlobalInteraction()->RemoveFocusElement(this); mitk::VtkLayerController::RemoveInstance(m_RenderWindow); RemoveAllLocalStorages(); m_DataStorage = NULL; + if (m_BindDispatcherInteractor != NULL) + { + delete m_BindDispatcherInteractor; + } + if (m_RenderWindow != NULL) { m_RenderWindow->Delete(); m_RenderWindow = NULL; } } void mitk::BaseRenderer::RemoveAllLocalStorages() { this->InvokeEvent(mitk::BaseRenderer::RendererResetEvent()); std::list::iterator it; for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); it++) (*it)->ClearLocalStorage(this, false); m_RegisteredLocalStorageHandlers.clear(); } void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.push_back(lsh); } -mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() +mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const { return m_BindDispatcherInteractor->GetDispatcher(); } mitk::Point3D mitk::BaseRenderer::Map2DRendererPositionTo3DWorldPosition(Point2D* mousePosition) const { Point2D p_mm; Point3D position; if (m_MapperID == 1) { GetDisplayGeometry()->ULDisplayToDisplay(*mousePosition, *mousePosition); GetDisplayGeometry()->DisplayToWorld(*mousePosition, p_mm); GetDisplayGeometry()->Map(p_mm, position); } else if (m_MapperID == 2) { GetDisplayGeometry()->ULDisplayToDisplay(*mousePosition, *mousePosition); PickWorldPoint(*mousePosition, position); } return position; } void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.remove(lsh); } void mitk::BaseRenderer::SetDataStorage(DataStorage* storage) { if (storage != NULL) { m_DataStorage = storage; m_BindDispatcherInteractor->SetDataStorage(m_DataStorage); this->Modified(); } } const mitk::BaseRenderer::MapperSlotId mitk::BaseRenderer::defaultMapper = 1; void mitk::BaseRenderer::Paint() { } void mitk::BaseRenderer::Initialize() { } void mitk::BaseRenderer::Resize(int w, int h) { m_Size[0] = w; m_Size[1] = h; if (m_CameraController) m_CameraController->Resize(w, h); //(formerly problematic on windows: vtkSizeBug) GetDisplayGeometry()->SetSizeInDisplayUnits(w, h); } void mitk::BaseRenderer::InitRenderer(vtkRenderWindow* renderwindow) { if (m_RenderWindow != NULL) { m_RenderWindow->Delete(); } m_RenderWindow = renderwindow; if (m_RenderWindow != NULL) { m_RenderWindow->Register(NULL); } RemoveAllLocalStorages(); if (m_CameraController.IsNotNull()) { m_CameraController->SetRenderer(this); } //BUG (#1551) added settings for depth peeling m_RenderWindow->SetAlphaBitPlanes(1); m_VtkRenderer->SetUseDepthPeeling(m_DepthPeelingEnabled); m_VtkRenderer->SetMaximumNumberOfPeels(m_MaxNumberOfPeels); m_VtkRenderer->SetOcclusionRatio(0.1); } void mitk::BaseRenderer::InitSize(int w, int h) { m_Size[0] = w; m_Size[1] = h; GetDisplayGeometry()->SetSizeInDisplayUnits(w, h, false); GetDisplayGeometry()->Fit(); } void mitk::BaseRenderer::SetSlice(unsigned int slice) { if (m_Slice != slice) { m_Slice = slice; if (m_TimeSlicedWorldGeometry.IsNotNull()) { SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep)); if (slicedWorldGeometry != NULL) { if (m_Slice >= slicedWorldGeometry->GetSlices()) m_Slice = slicedWorldGeometry->GetSlices() - 1; SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) { if (m_TimeStep != timeStep) { m_TimeStep = timeStep; m_TimeStepUpdateTime.Modified(); if (m_TimeSlicedWorldGeometry.IsNotNull()) { if (m_TimeStep >= m_TimeSlicedWorldGeometry->GetTimeSteps()) m_TimeStep = m_TimeSlicedWorldGeometry->GetTimeSteps() - 1; SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep)); if (slicedWorldGeometry != NULL) { SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } int mitk::BaseRenderer::GetTimeStep(const mitk::BaseData* data) const { if ((data == NULL) || (data->IsInitialized() == false)) { return -1; } return data->GetTimeSlicedGeometry()->MSToTimeStep(GetTime()); } mitk::ScalarType mitk::BaseRenderer::GetTime() const { if (m_TimeSlicedWorldGeometry.IsNull()) { return 0; } else { ScalarType timeInMS = m_TimeSlicedWorldGeometry->TimeStepToMS(GetTimeStep()); if (timeInMS == ScalarTypeNumericTraits::NonpositiveMin()) return 0; else return timeInMS; } } void mitk::BaseRenderer::SetWorldGeometry(mitk::Geometry3D* geometry) { itkDebugMacro("setting WorldGeometry to " << geometry); if (m_WorldGeometry != geometry) { if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0) return; m_WorldGeometry = geometry; m_TimeSlicedWorldGeometry = dynamic_cast(geometry); SlicedGeometry3D* slicedWorldGeometry; if (m_TimeSlicedWorldGeometry.IsNotNull()) { itkDebugMacro("setting TimeSlicedWorldGeometry to " << m_TimeSlicedWorldGeometry); if (m_TimeStep >= m_TimeSlicedWorldGeometry->GetTimeSteps()) m_TimeStep = m_TimeSlicedWorldGeometry->GetTimeSteps() - 1; slicedWorldGeometry = dynamic_cast(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep)); } else { slicedWorldGeometry = dynamic_cast(geometry); } Geometry2D::Pointer geometry2d; if (slicedWorldGeometry != NULL) { if (m_Slice >= slicedWorldGeometry->GetSlices() && (m_Slice != 0)) m_Slice = slicedWorldGeometry->GetSlices() - 1; geometry2d = slicedWorldGeometry->GetGeometry2D(m_Slice); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->InitializeStandardPlane(slicedWorldGeometry); geometry2d = plane; } SetCurrentWorldGeometry(slicedWorldGeometry); } else { geometry2d = dynamic_cast(geometry); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = PlaneGeometry::New(); plane->InitializeStandardPlane(geometry); geometry2d = plane; } SetCurrentWorldGeometry(geometry); } SetCurrentWorldGeometry2D(geometry2d); // calls Modified() } if (m_CurrentWorldGeometry2D.IsNull()) itkWarningMacro("m_CurrentWorldGeometry2D is NULL"); } void mitk::BaseRenderer::SetDisplayGeometry(mitk::DisplayGeometry* geometry2d) { itkDebugMacro("setting DisplayGeometry to " << geometry2d); if (m_DisplayGeometry != geometry2d) { m_DisplayGeometry = geometry2d; m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry); m_DisplayGeometryUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SetCurrentWorldGeometry2D(mitk::Geometry2D* geometry2d) { if (m_CurrentWorldGeometry2D != geometry2d) { m_CurrentWorldGeometry2D = geometry2d; m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D); m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D); m_CurrentWorldGeometry2DUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SendUpdateSlice() { m_DisplayGeometryUpdateTime.Modified(); m_CurrentWorldGeometry2DUpdateTime.Modified(); } void mitk::BaseRenderer::SetCurrentWorldGeometry(mitk::Geometry3D* geometry) { m_CurrentWorldGeometry = geometry; if (geometry == NULL) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; m_EmptyWorldGeometry = true; return; } BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(NULL); const BoundingBox::BoundsArrayType& worldBounds = boundingBox->GetBounds(); m_Bounds[0] = worldBounds[0]; m_Bounds[1] = worldBounds[1]; m_Bounds[2] = worldBounds[2]; m_Bounds[3] = worldBounds[3]; m_Bounds[4] = worldBounds[4]; m_Bounds[5] = worldBounds[5]; if (boundingBox->GetDiagonalLength2() <= mitk::eps) m_EmptyWorldGeometry = true; else m_EmptyWorldGeometry = false; } void mitk::BaseRenderer::SetGeometry(const itk::EventObject & geometrySendEvent) { const SliceNavigationController::GeometrySendEvent* sendEvent = dynamic_cast(&geometrySendEvent); assert(sendEvent!=NULL); SetWorldGeometry(sendEvent->GetTimeSlicedGeometry()); } void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject & geometryUpdateEvent) { const SliceNavigationController::GeometryUpdateEvent* updateEvent = dynamic_cast(&geometryUpdateEvent); if (updateEvent == NULL) return; if (m_CurrentWorldGeometry.IsNotNull()) { SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); if (slicedWorldGeometry) { Geometry2D* geometry2D = slicedWorldGeometry->GetGeometry2D(m_Slice); SetCurrentWorldGeometry2D(geometry2D); // calls Modified() } } } void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject & geometrySliceEvent) { const SliceNavigationController::GeometrySliceEvent* sliceEvent = dynamic_cast(&geometrySliceEvent); assert(sliceEvent!=NULL); SetSlice(sliceEvent->GetPos()); } void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject & geometryTimeEvent) { const SliceNavigationController::GeometryTimeEvent * timeEvent = dynamic_cast(&geometryTimeEvent); assert(timeEvent!=NULL); SetTimeStep(timeEvent->GetPos()); } const double* mitk::BaseRenderer::GetBounds() const { return m_Bounds; } void mitk::BaseRenderer::MousePressEvent(mitk::MouseEvent *me) { //set the Focus on the renderer /*bool success =*/m_RenderingManager->GetGlobalInteraction()->SetFocus(this); /* if (! success) mitk::StatusBar::GetInstance()->DisplayText("Warning! from mitkBaseRenderer.cpp: Couldn't focus this BaseRenderer!"); */ //if (m_CameraController) //{ // if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MousePressEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID > 1) //==2 for 3D and ==5 for stencil { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::MouseReleaseEvent(mitk::MouseEvent *me) { //if (m_CameraController) //{ // if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MouseReleaseEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::MouseMoveEvent(mitk::MouseEvent *me) { //if (m_CameraController) //{ // if((me->GetButtonState()<=512) || (me->GetButtonState()>=516))// provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MouseMoveEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::PickWorldPoint(const mitk::Point2D& displayPoint, mitk::Point3D& worldPoint) const { mitk::Point2D worldPoint2D; GetDisplayGeometry()->DisplayToWorld(displayPoint, worldPoint2D); GetDisplayGeometry()->Map(worldPoint2D, worldPoint); } void mitk::BaseRenderer::WheelEvent(mitk::WheelEvent * we) { if (m_MapperID == 1) { Point2D p(we->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, we->GetType(), we->GetButton(), we->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction()); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(we->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); we->SetDisplayPosition(p); mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::KeyPressEvent(mitk::KeyEvent *ke) { if (m_MapperID == 1) { Point2D p(ke->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::KeyEvent event(this, ke->GetType(), ke->GetButton(), ke->GetButtonState(), ke->GetKey(), ke->GetText(), p); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(ke->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); ke->SetDisplayPosition(p); mitk::EventMapper::MapEvent(ke, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D& itkNotUsed(p2d)) { MITK_INFO<<"BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer."<RequestUpdate(this->m_RenderWindow); } void mitk::BaseRenderer::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow); } unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const { return m_NumberOfVisibleLODEnabledMappers; } mitk::RenderingManager* mitk::BaseRenderer::GetRenderingManager() const { return m_RenderingManager.GetPointer(); } /*! Sets the new Navigation controller */ void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController) { if (SlicenavigationController == NULL) return; //disconnect old from globalinteraction m_RenderingManager->GetGlobalInteraction()->RemoveListener(SlicenavigationController); //copy worldgeometry SlicenavigationController->SetInputWorldGeometry(SlicenavigationController->GetCreatedWorldGeometry()); SlicenavigationController->Update(); //set new m_SliceNavigationController = SlicenavigationController; m_SliceNavigationController->SetRenderer(this); if (m_SliceNavigationController.IsNotNull()) { m_SliceNavigationController->ConnectGeometrySliceEvent(this); m_SliceNavigationController->ConnectGeometryUpdateEvent(this); m_SliceNavigationController->ConnectGeometryTimeEvent(this, false); } } /*! Sets the new camera controller and deletes the vtkRenderWindowInteractor in case of the VTKInteractorCameraController */ void mitk::BaseRenderer::SetCameraController(CameraController* cameraController) { mitk::VtkInteractorCameraController::Pointer vtkInteractorCameraController = dynamic_cast(cameraController); if (vtkInteractorCameraController.IsNotNull()) MITK_INFO<<"!!!WARNING!!!: RenderWindow interaction events are no longer handled via CameraController (See Bug #954)."<SetRenderer(NULL); m_CameraController = NULL; m_CameraController = cameraController; m_CameraController->SetRenderer(this); } void mitk::BaseRenderer::PrintSelf(std::ostream& os, itk::Indent indent) const { os << indent << " MapperID: " << m_MapperID << std::endl; os << indent << " Slice: " << m_Slice << std::endl; os << indent << " TimeStep: " << m_TimeStep << std::endl; os << indent << " WorldGeometry: "; if (m_WorldGeometry.IsNull()) os << "NULL" << std::endl; else m_WorldGeometry->Print(os, indent); os << indent << " CurrentWorldGeometry2D: "; if (m_CurrentWorldGeometry2D.IsNull()) os << "NULL" << std::endl; else m_CurrentWorldGeometry2D->Print(os, indent); os << indent << " CurrentWorldGeometry2DUpdateTime: " << m_CurrentWorldGeometry2DUpdateTime << std::endl; os << indent << " CurrentWorldGeometry2DTransformTime: " << m_CurrentWorldGeometry2DTransformTime << std::endl; os << indent << " DisplayGeometry: "; if (m_DisplayGeometry.IsNull()) os << "NULL" << std::endl; else m_DisplayGeometry->Print(os, indent); os << indent << " DisplayGeometryTransformTime: " << m_DisplayGeometryTransformTime << std::endl; Superclass::PrintSelf(os, indent); } void mitk::BaseRenderer::SetDepthPeelingEnabled(bool enabled) { m_DepthPeelingEnabled = enabled; m_VtkRenderer->SetUseDepthPeeling(enabled); } void mitk::BaseRenderer::SetMaxNumberOfPeels(int maxNumber) { m_MaxNumberOfPeels = maxNumber; m_VtkRenderer->SetMaximumNumberOfPeels(maxNumber); } diff --git a/Core/Code/Rendering/mitkBaseRenderer.h b/Core/Code/Rendering/mitkBaseRenderer.h index 33ba6ea9d3..be2274f90e 100644 --- a/Core/Code/Rendering/mitkBaseRenderer.h +++ b/Core/Code/Rendering/mitkBaseRenderer.h @@ -1,633 +1,611 @@ /*=================================================================== 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 BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #define BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #include "mitkDataStorage.h" #include "mitkGeometry2D.h" #include "mitkTimeSlicedGeometry.h" #include "mitkDisplayGeometry.h" #include "mitkGeometry2DData.h" #include "mitkCameraController.h" #include "mitkDisplayPositionEvent.h" #include "mitkWheelEvent.h" //#include "mitkMapper.h" #include "mitkSliceNavigationController.h" #include "mitkCameraController.h" #include "mitkCameraRotationController.h" #include "mitkBindDispatcherInteractor.h" #include "mitkDispatcher.h" #include #include #include #include namespace mitk { class NavigationController; class SliceNavigationController; class CameraRotationController; class CameraController; class DataStorage; class Mapper; class BaseLocalStorageHandler; //##Documentation //## @brief Organizes the rendering process //## //## Organizes the rendering process. A Renderer contains a reference to a //## DataStorage and asks the mappers of the data objects to render //## the data into the renderwindow it is associated to. //## //## \#Render() checks if rendering is currently allowed by calling //## RenderWindow::PrepareRendering(). Initialization of a rendering context //## can also be performed in this method. //## //## The actual rendering code has been moved to \#Repaint() //## Both \#Repaint() and \#Update() are declared protected now. //## //## Note: Separation of the Repaint and Update processes (rendering vs //## creating a vtk prop tree) still needs to be worked on. The whole //## rendering process also should be reworked to use VTK based classes for //## both 2D and 3D rendering. //## @ingroup Renderer class MITK_CORE_EXPORT BaseRenderer: public itk::Object { public: typedef std::map BaseRendererMapType; static BaseRendererMapType baseRendererMap; static BaseRenderer* GetInstance(vtkRenderWindow * renWin); static void AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer); static void RemoveInstance(vtkRenderWindow* renWin); static BaseRenderer* GetByName(const std::string& name); static vtkRenderWindow* GetRenderWindowByName(const std::string& name); #pragma GCC visibility push(default) itkEventMacro( RendererResetEvent, itk::AnyEvent ); #pragma GCC visibility pop /** Standard class typedefs. */ mitkClassMacro(BaseRenderer, itk::Object); BaseRenderer(const char* name = NULL, vtkRenderWindow * renWin = NULL, mitk::RenderingManager* rm = NULL); //##Documentation //## @brief MapperSlotId defines which kind of mapper (e.g., 2D or 3D) shoud be used. typedef int MapperSlotId; enum StandardMapperSlot { Standard2D = 1, Standard3D = 2 }; virtual void SetDataStorage(DataStorage* storage); ///< set the datastorage that will be used for rendering //##Documentation //## return the DataStorage that is used for rendering virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); - }; + } //##Documentation //## @brief Access the RenderWindow into which this renderer renders. vtkRenderWindow* GetRenderWindow() const { return m_RenderWindow; } vtkRenderer* GetVtkRenderer() const { return m_VtkRenderer; } //##Documentation //## @brief Returns the Dispatcher which handles Events for this BaseRenderer - Dispatcher::Pointer GetDispatcher(); + Dispatcher::Pointer GetDispatcher() const; //##Documentation //## @brief Default mapper id to use. static const MapperSlotId defaultMapper; //##Documentation //## @brief Do the rendering and flush the result. virtual void Paint(); //##Documentation //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. virtual void Initialize(); //##Documentation //## @brief Called to inform the renderer that the RenderWindow has been resized. virtual void Resize(int w, int h); //##Documentation //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). virtual void InitRenderer(vtkRenderWindow* renderwindow); //##Documentation //## @brief Set the initial size. Called by RenderWindow after it has become //## visible for the first time. virtual void InitSize(int w, int h); //##Documentation //## @brief Draws a point on the widget. //## Should be used during conferences to show the position of the remote mouse virtual void DrawOverlayMouse(Point2D& p2d); //##Documentation //## @brief Set/Get the WorldGeometry (m_WorldGeometry) for 3D and 2D rendering, that describing the //## (maximal) area to be rendered. //## //## Depending of the type of the passed Geometry3D more or less information can be extracted: //## \li if it is a Geometry2D (which is a sub-class of Geometry3D), m_CurrentWorldGeometry2D is //## also set to point to it. m_TimeSlicedWorldGeometry is set to NULL. //## \li if it is a TimeSlicedGeometry, m_TimeSlicedWorldGeometry is also set to point to it. //## If m_TimeSlicedWorldGeometry contains instances of SlicedGeometry3D, m_CurrentWorldGeometry2D is set to //## one of geometries stored in the SlicedGeometry3D according to the value of m_Slice; otherwise //## a PlaneGeometry describing the top of the bounding-box of the Geometry3D is set as the //## m_CurrentWorldGeometry2D. //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the Geometry3D //## is set as the m_CurrentWorldGeometry2D. m_TimeSlicedWorldGeometry is set to NULL. //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the Geometry3D //## when the passed Geometry3D is not sliced. //## \sa m_WorldGeometry //## \sa m_TimeSlicedWorldGeometry //## \sa m_CurrentWorldGeometry2D virtual void SetWorldGeometry(Geometry3D* geometry); itkGetConstObjectMacro(WorldGeometry, Geometry3D) - ; //##Documentation //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering itkGetConstObjectMacro(CurrentWorldGeometry, Geometry3D) - ; //##Documentation //## @brief Get the current 2D-worldgeometry (m_CurrentWorldGeometry2D) used for 2D-rendering itkGetConstObjectMacro(CurrentWorldGeometry2D, Geometry2D) - ; //##Documentation //## Calculates the bounds of the DataStorage (if it contains any valid data), //## creates a geometry from these bounds and sets it as world geometry of the renderer. //## //## Call this method to re-initialize the renderer to the current DataStorage //## (e.g. after loading an additional dataset), to ensure that the view is //## aligned correctly. //## \warn This is not implemented yet. virtual bool SetWorldGeometryToDataStorageBounds() { return false; } //##Documentation //## @brief Set/Get the DisplayGeometry (for 2D rendering) //## //## The DisplayGeometry describes which part of the Geometry2D m_CurrentWorldGeometry2D //## is displayed. virtual void SetDisplayGeometry(DisplayGeometry* geometry2d); itkGetConstObjectMacro(DisplayGeometry, DisplayGeometry) - ; - itkGetObjectMacro(DisplayGeometry, DisplayGeometry) - ; //##Documentation //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry //## stored in m_TimeSlicedWorldGeometry used as m_CurrentWorldGeometry2D //## //## \sa m_Slice virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int) - ; //##Documentation //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry //## stored in m_TimeSlicedWorldGeometry used as m_CurrentWorldGeometry2D //## //## \sa m_TimeStep virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int) - ; //##Documentation //## @brief Get the time-step of a BaseData object which //## exists at the time of the currently displayed content //## //## Returns -1 or mitk::BaseData::m_TimeSteps if there //## is no data at the current time. //## \sa GetTimeStep, m_TimeStep int GetTimeStep(const BaseData* data) const; //##Documentation //## @brief Get the time in ms of the currently displayed content //## //## \sa GetTimeStep, m_TimeStep ScalarType GetTime() const; //##Documentation //## @brief SetWorldGeometry is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySendEvent virtual void SetGeometry(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the //## slice navigation controller virtual void UpdateGeometry(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief SetSlice is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySliceEvent virtual void SetGeometrySlice(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief SetTimeStep is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometryTimeEvent virtual void SetGeometryTime(const itk::EventObject & geometryTimeEvent); //##Documentation //## @brief Get a data object containing the DisplayGeometry (for 2D rendering) itkGetObjectMacro(DisplayGeometryData, Geometry2DData) - ; //##Documentation //## @brief Get a data object containing the WorldGeometry (for 2D rendering) itkGetObjectMacro(WorldGeometryData, Geometry2DData) - ; //##Documentation //## @brief Get a DataNode pointing to a data object containing the WorldGeometry (3D and 2D rendering) itkGetObjectMacro(WorldGeometryNode, DataNode) - ; //##Documentation //## @brief Get a DataNode pointing to a data object containing the DisplayGeometry (for 2D rendering) itkGetObjectMacro(DisplayGeometryNode, DataNode) - ; //##Documentation //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry m_CurrentWorldGeometry2D (for 2D rendering) itkGetObjectMacro(CurrentWorldGeometry2DNode, DataNode) - ; //##Documentation //## @brief Sets timestamp of CurrentWorldGeometry2D and DisplayGeometry and forces so reslicing in that renderwindow void SendUpdateSlice(); //##Documentation //## @brief Get timestamp of last call of SetCurrentWorldGeometry2D unsigned long GetCurrentWorldGeometry2DUpdateTime() { return m_CurrentWorldGeometry2DUpdateTime; } - ; //##Documentation //## @brief Get timestamp of last call of SetDisplayGeometry unsigned long GetDisplayGeometryUpdateTime() { return m_CurrentWorldGeometry2DUpdateTime; } - ; //##Documentation //## @brief Get timestamp of last change of current TimeStep unsigned long GetTimeStepUpdateTime() { return m_TimeStepUpdateTime; } - ; //##Documentation //## @brief Perform a picking: find the x,y,z world coordinate of a //## display x,y coordinate. //## @warning Has to be overwritten in subclasses for the 3D-case. //## //## Implemented here only for 2D-rendering by using //## m_DisplayGeometry virtual void PickWorldPoint(const Point2D& diplayPosition, Point3D& worldPosition) const; /** \brief Determines the object (mitk::DataNode) closest to the current * position by means of picking * * \warning Implementation currently empty for 2D rendering; intended to be * implemented for 3D renderers */ virtual DataNode* PickObject(const Point2D& /*displayPosition*/, Point3D& /*worldPosition*/) const { return NULL; } - ; //##Documentation //## @brief Get the MapperSlotId to use. itkGetMacro(MapperID, MapperSlotId) - ;itkGetConstMacro(MapperID, MapperSlotId) - ; + itkGetConstMacro(MapperID, MapperSlotId) + //##Documentation //## @brief Set the MapperSlotId to use. itkSetMacro(MapperID, MapperSlotId) - ; //##Documentation //## @brief Has the renderer the focus? itkGetMacro(Focused, bool) - ; //##Documentation //## @brief Tell the renderer that it is focused. The caller is responsible for focus management, //## not the renderer itself. itkSetMacro(Focused, bool) - ; //##Documentation //## @brief Sets whether depth peeling is enabled or not void SetDepthPeelingEnabled(bool enabled); //##Documentation //## @brief Sets maximal number of peels void SetMaxNumberOfPeels(int maxNumber); itkGetMacro(Size, int*) - ; void SetSliceNavigationController(SliceNavigationController* SlicenavigationController); - void SetCameraController(CameraController* cameraController);itkGetObjectMacro(CameraController, CameraController) - ;itkGetObjectMacro(SliceNavigationController, SliceNavigationController) - ;itkGetObjectMacro(CameraRotationController, CameraRotationController) - ; + void SetCameraController(CameraController* cameraController); + itkGetObjectMacro(CameraController, CameraController) + itkGetObjectMacro(SliceNavigationController, SliceNavigationController) + itkGetObjectMacro(CameraRotationController, CameraRotationController) itkGetMacro(EmptyWorldGeometry, bool) - ; //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MousePressEvent(MouseEvent*); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MouseReleaseEvent(MouseEvent*); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MouseMoveEvent(MouseEvent*); //##Documentation //## @brief Wheel event dispatcher //## @note for internal use only. preliminary. virtual void WheelEvent(mitk::WheelEvent* we); //##Documentation //## @brief Key event dispatcher //## @note for internal use only. preliminary. virtual void KeyPressEvent(KeyEvent*); //##Documentation //## @brief get the name of the Renderer //## @note const char * GetName() const { return m_Name.c_str(); } //##Documentation //## @brief get the x_size of the RendererWindow //## @note int GetSizeX() const { return m_Size[0]; } //##Documentation //## @brief get the y_size of the RendererWindow //## @note int GetSizeY() const { return m_Size[1]; } const double* GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); /** Returns number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; ///** //* \brief Setter for the RenderingManager that handles this instance of BaseRenderer //*/ //void SetRenderingManager( mitk::RenderingManager* ); /** * \brief Getter for the RenderingManager that handles this instance of BaseRenderer */ virtual mitk::RenderingManager* GetRenderingManager() const; /** * \brief Provides (1) world coordinates for a given mouse position and (2) * translates mousePosition to Display coordinates */ virtual Point3D Map2DRendererPositionTo3DWorldPosition(Point2D* mousePosition) const; protected: virtual ~BaseRenderer(); //##Documentation //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; vtkRenderWindow* m_RenderWindow; vtkRenderer* m_VtkRenderer; //##Documentation //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; //##Documentation //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; //##Documentation //## @brief The RenderingManager that manages this instance RenderingManager::Pointer m_RenderingManager; //##Documentation //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; //##Documentation //## @brief CameraController for 3D rendering //## @note preliminary. CameraController::Pointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; //##Documentation //## @brief Size of the RenderWindow. int m_Size[2]; //##Documentation //## @brief Contains whether the renderer that it is focused. The caller of //## SetFocused is responsible for focus management, not the renderer itself. //## is doubled because of mitk::FocusManager in GlobalInteraction!!! (ingmar) bool m_Focused; //##Documentation //## @brief Sets m_CurrentWorldGeometry2D virtual void SetCurrentWorldGeometry2D(Geometry2D* geometry2d); //##Documentation //## @brief Sets m_CurrentWorldGeometry virtual void SetCurrentWorldGeometry(Geometry3D* geometry); private: //##Documentation //## Pointer to the worldgeometry, describing the maximal area to be rendered //## (3D as well as 2D). //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). //## \sa SetWorldGeometry Geometry3D::Pointer m_WorldGeometry; //##Documentation //## m_TimeSlicedWorldGeometry is set by SetWorldGeometry if the passed Geometry3D is a //## TimeSlicedGeometry (or a sub-class of it). If it contains instances of SlicedGeometry3D, //## m_Slice and m_TimeStep (set via SetSlice and SetTimeStep, respectively) define //## which 2D geometry stored in m_TimeSlicedWorldGeometry (if available) //## is used as m_CurrentWorldGeometry2D. //## \sa m_CurrentWorldGeometry2D TimeSlicedGeometry::Pointer m_TimeSlicedWorldGeometry; //##Documentation //## Pointer to the current 3D-worldgeometry. Geometry3D::Pointer m_CurrentWorldGeometry; //##Documentation //## Pointer to the current 2D-worldgeometry. The 2D-worldgeometry //## describes the maximal area (2D manifold) to be rendered in case we //## are doing 2D-rendering. More precisely, a subpart of this according //## to m_DisplayGeometry is displayed. //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). Geometry2D::Pointer m_CurrentWorldGeometry2D; //##Documentation //## Pointer to the displaygeometry. The displaygeometry describes the //## geometry of the \em visible area in the window controlled by the renderer //## in case we are doing 2D-rendering. //## It is const, since we are not allowed to change it. DisplayGeometry::Pointer m_DisplayGeometry; //##Documentation //## Defines together with m_Slice which 2D geometry stored in m_TimeSlicedWorldGeometry //## is used as m_CurrentWorldGeometry2D: m_TimeSlicedWorldGeometry->GetGeometry2D(m_Slice, m_TimeStep). //## \sa m_TimeSlicedWorldGeometry unsigned int m_Slice; //##Documentation //## Defines together with m_TimeStep which 2D geometry stored in m_TimeSlicedWorldGeometry //## is used as m_CurrentWorldGeometry2D: m_TimeSlicedWorldGeometry->GetGeometry2D(m_Slice, m_TimeStep). //## \sa m_TimeSlicedWorldGeometry unsigned int m_TimeStep; //##Documentation //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldGeometry2DUpdateTime; //##Documentation //## @brief timestamp of last call of SetDisplayGeometry itk::TimeStamp m_DisplayGeometryUpdateTime; //##Documentation //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; //##Documentation //## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage. - BindDispatcherInteractor::Pointer m_BindDispatcherInteractor; + BindDispatcherInteractor* m_BindDispatcherInteractor; protected: virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; //##Documentation //## Data object containing the m_WorldGeometry defined above. Geometry2DData::Pointer m_WorldGeometryData; //##Documentation //## Data object containing the m_DisplayGeometry defined above. Geometry2DData::Pointer m_DisplayGeometryData; //##Documentation //## Data object containing the m_CurrentWorldGeometry2D defined above. Geometry2DData::Pointer m_CurrentWorldGeometry2DData; //##Documentation //## DataNode objects containing the m_WorldGeometryData defined above. DataNode::Pointer m_WorldGeometryNode; //##Documentation //## DataNode objects containing the m_DisplayGeometryData defined above. DataNode::Pointer m_DisplayGeometryNode; //##Documentation //## DataNode objects containing the m_CurrentWorldGeometry2DData defined above. DataNode::Pointer m_CurrentWorldGeometry2DNode; //##Documentation //## @brief test only unsigned long m_DisplayGeometryTransformTime; //##Documentation //## @brief test only unsigned long m_CurrentWorldGeometry2DTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; bool m_DepthPeelingEnabled; int m_MaxNumberOfPeels; typedef std::set LODEnabledMappersType; /** Number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int m_NumberOfVisibleLODEnabledMappers; // Local Storage Handling for mappers protected: std::list m_RegisteredLocalStorageHandlers; public: void RemoveAllLocalStorages(); void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); }; } // namespace mitk #endif /* BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 */ diff --git a/Core/Code/Resources/Interactions/DisplayConfig.xml b/Core/Code/Resources/Interactions/DisplayConfig.xml index 3a402dac02..5e76716816 100644 --- a/Core/Code/Resources/Interactions/DisplayConfig.xml +++ b/Core/Code/Resources/Interactions/DisplayConfig.xml @@ -1,73 +1,73 @@ - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigMITK.xml b/Core/Code/Resources/Interactions/DisplayConfigMITK.xml index 6f9e94ebea..025b59f5fc 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigMITK.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigMITK.xml @@ -1,43 +1,43 @@ - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACS.xml b/Core/Code/Resources/Interactions/DisplayConfigPACS.xml index 3f1b91e99f..32a58497d0 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACS.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACS.xml @@ -1,60 +1,60 @@ - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml index 095f574ece..b8604d340f 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml @@ -1,11 +1,11 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml index 04a0c04045..35eaa333c5 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml @@ -1,11 +1,11 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml index a85aeef7e9..a3a5e3cf9c 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml @@ -1,13 +1,13 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml index 17bc572c40..c5defb7806 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml @@ -1,11 +1,11 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/PointSetConfig.xml b/Core/Code/Resources/Interactions/PointSetConfig.xml index dfd8c206a2..f38f80b075 100644 --- a/Core/Code/Resources/Interactions/PointSetConfig.xml +++ b/Core/Code/Resources/Interactions/PointSetConfig.xml @@ -1,40 +1,40 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml b/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml index a87fec05e8..b0e0095457 100644 --- a/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml +++ b/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml @@ -1,19 +1,19 @@ - + - - + + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/Tests/globalConfig.xml b/Core/Code/Resources/Interactions/Tests/globalConfig.xml index 6d7ef6fd3f..34d543270c 100644 --- a/Core/Code/Resources/Interactions/Tests/globalConfig.xml +++ b/Core/Code/Resources/Interactions/Tests/globalConfig.xml @@ -1,70 +1,70 @@ - + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - - + + - + - + - - + + - + diff --git a/Core/Code/Resources/Interactions/globalConfig.xml b/Core/Code/Resources/Interactions/globalConfig.xml index 6d7ef6fd3f..34d543270c 100644 --- a/Core/Code/Resources/Interactions/globalConfig.xml +++ b/Core/Code/Resources/Interactions/globalConfig.xml @@ -1,70 +1,70 @@ - + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - - + + - + - + - - + + - + diff --git a/Core/Code/Testing/Testing/Temporary/CTestCostData.txt b/Core/Code/Testing/Testing/Temporary/CTestCostData.txt deleted file mode 100644 index ed97d539c0..0000000000 --- a/Core/Code/Testing/Testing/Temporary/CTestCostData.txt +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/Core/Code/Testing/Testing/Temporary/LastTest.log b/Core/Code/Testing/Testing/Temporary/LastTest.log deleted file mode 100644 index 83c8c4ffeb..0000000000 --- a/Core/Code/Testing/Testing/Temporary/LastTest.log +++ /dev/null @@ -1,3 +0,0 @@ -Start testing: Nov 23 15:04 CET ----------------------------------------------------------- -End testing: Nov 23 15:04 CET diff --git a/Core/Code/Testing/files.cmake b/Core/Code/Testing/files.cmake index a11495c505..b2539a95ed 100644 --- a/Core/Code/Testing/files.cmake +++ b/Core/Code/Testing/files.cmake @@ -1,128 +1,128 @@ # tests with no extra command line parameter set(MODULE_TESTS mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkDispatcherTest.cpp mitkEnumerationPropertyTest.cpp mitkEventTest.cpp - mitkEventConfigTest.cpp + #mitkEventConfigTest.cpp ## needs to be re-written, test indirect since EventConfig is no longer exported as interface Bug 14529 mitkFocusManagerTest.cpp mitkGenericPropertyTest.cpp mitkGeometry3DTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkGlobalInteractionTest.cpp mitkImageDataItemTest.cpp #mitkImageMapper2DTest.cpp mitkImageGeneratorTest.cpp mitkBaseDataTest.cpp #mitkImageToItkTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkInteractorTest.cpp mitkInteractionEventTest.cpp mitkITKThreadingTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp #mitkPipelineSmartPointerCorrectnessTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetInteractorTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp #mitkRegistrationBaseTest.cpp #mitkSegmentationInterpolationTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkStateMachineTest.cpp - mitkStateMachineContainerTest.cpp + ##mitkStateMachineContainerTest.cpp ## rewrite test, indirect since no longer exported Bug 14529 mitkStateTest.cpp mitkSurfaceTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeSlicedGeometryTest.cpp mitkTransitionTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp #mitkAbstractTransformGeometryTest.cpp mitkStepperTest.cpp itkTotalVariationDenoisingImageFilterTest.cpp mitkRenderingManagerTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp #QmitkRenderingTestHelper.cpp mitkExceptionTest.cpp mitkExtractSliceFilterTest.cpp mitkLogTest.cpp mitkImageDimensionConverterTest.cpp mitkLoggingAdapterTest.cpp mitkUIDGeneratorTest.cpp ) # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkPlanePositionManagerTest.cpp mitkSurfaceVtkWriterTest.cpp #mitkImageSliceSelectorTest.cpp mitkImageTimeSelectorTest.cpp # mitkVtkPropRendererTest.cpp mitkDataNodeFactoryTest.cpp #mitkSTLFileReaderTest.cpp mitkImageAccessorTest.cpp ) # list of images for which the tests are run set(MODULE_TESTIMAGES # Pic-Factory no more available in Core, test images now in .nrrd format US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS #mitkLabeledImageToSurfaceFilterTest.cpp #mitkExternalToolsTest.cpp mitkDataStorageTest.cpp mitkDataNodeTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkEventMapperTest.cpp mitkNodeDependentPointSetInteractorTest.cpp mitkStateMachineFactoryTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp mitkImageWriterTest.cpp mitkImageVtkMapper2DTest.cpp mitkImageVtkMapper2DLevelWindowTest.cpp mitkImageVtkMapper2DOpacityTest.cpp mitkImageVtkMapper2DColorTest.cpp mitkImageVtkMapper2DSwivelTest.cpp mitkIOUtilTest.cpp mitkSurfaceVtkMapper3DTest mitkSurfaceVtkMapper3DTexturedSphereTest.cpp mitkVolumeCalculatorTest.cpp mitkLevelWindowManagerTest.cpp ) # Create an artificial module initializing class for # the usServiceListenerTest.cpp usFunctionGenerateModuleInit(testdriver_init_file NAME ${MODULE_NAME}TestDriver DEPENDS "Mitk" VERSION "0.1.0" EXECUTABLE ) set(TEST_CPP_FILES ${testdriver_init_file} mitkRenderingTestHelper.cpp) diff --git a/Core/Code/files.cmake b/Core/Code/files.cmake index e9bc744796..ea68d73a03 100644 --- a/Core/Code/files.cmake +++ b/Core/Code/files.cmake @@ -1,357 +1,357 @@ set(H_FILES Algorithms/itkImportMitkImageContainer.h Algorithms/itkImportMitkImageContainer.txx Algorithms/itkLocalVariationImageFilter.h Algorithms/itkLocalVariationImageFilter.txx Algorithms/itkMITKScalarImageToHistogramGenerator.h Algorithms/itkMITKScalarImageToHistogramGenerator.txx Algorithms/itkTotalVariationDenoisingImageFilter.h Algorithms/itkTotalVariationDenoisingImageFilter.txx Algorithms/itkTotalVariationSingleIterationImageFilter.h Algorithms/itkTotalVariationSingleIterationImageFilter.txx Algorithms/mitkBilateralFilter.h Algorithms/mitkBilateralFilter.cpp Algorithms/mitkInstantiateAccessFunctions.h Algorithms/mitkPixelTypeList.h # Preprocessor macros taken from Boost Algorithms/mitkPPArithmeticDec.h Algorithms/mitkPPArgCount.h Algorithms/mitkPPCat.h Algorithms/mitkPPConfig.h Algorithms/mitkPPControlExprIIf.h Algorithms/mitkPPControlIf.h Algorithms/mitkPPControlIIf.h Algorithms/mitkPPDebugError.h Algorithms/mitkPPDetailAutoRec.h Algorithms/mitkPPDetailDMCAutoRec.h Algorithms/mitkPPExpand.h Algorithms/mitkPPFacilitiesEmpty.h Algorithms/mitkPPFacilitiesExpand.h Algorithms/mitkPPLogicalBool.h Algorithms/mitkPPRepetitionDetailDMCFor.h Algorithms/mitkPPRepetitionDetailEDGFor.h Algorithms/mitkPPRepetitionDetailFor.h Algorithms/mitkPPRepetitionDetailMSVCFor.h Algorithms/mitkPPRepetitionFor.h Algorithms/mitkPPSeqElem.h Algorithms/mitkPPSeqForEach.h Algorithms/mitkPPSeqForEachProduct.h Algorithms/mitkPPSeq.h Algorithms/mitkPPSeqEnum.h Algorithms/mitkPPSeqSize.h Algorithms/mitkPPSeqToTuple.h Algorithms/mitkPPStringize.h Algorithms/mitkPPTupleEat.h Algorithms/mitkPPTupleElem.h Algorithms/mitkPPTupleRem.h Algorithms/mitkClippedSurfaceBoundsCalculator.h Algorithms/mitkExtractSliceFilter.h Algorithms/mitkConvert2Dto3DImageFilter.h Algorithms/mitkPlaneClipping.h Common/mitkExceptionMacro.h Common/mitkServiceBaseObject.h Common/mitkTestingMacros.h DataManagement/mitkImageAccessByItk.h DataManagement/mitkImageCast.h DataManagement/mitkImagePixelAccessor.h DataManagement/mitkImagePixelReadAccessor.h DataManagement/mitkImagePixelWriteAccessor.h DataManagement/mitkImageReadAccessor.h DataManagement/mitkImageWriteAccessor.h DataManagement/mitkITKImageImport.h DataManagement/mitkITKImageImport.txx DataManagement/mitkImageToItk.h DataManagement/mitkImageToItk.txx Interactions/mitkEventMapperAddOn.h Interfaces/mitkIDataNodeReader.h IO/mitkPixelTypeTraits.h ) set(CPP_FILES Algorithms/mitkBaseDataSource.cpp Algorithms/mitkBaseProcess.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkExtractSliceFilter.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkCoreActivator.cpp Controllers/mitkFocusManager.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkSlicesRotator.cpp Controllers/mitkSlicesSwiveller.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkInteractorCameraController.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataStorage.cpp #DataManagement/mitkDataTree.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataNodeFactory.cpp #DataManagement/mitkDataTreeStorage.cpp DataManagement/mitkDisplayGeometry.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkGeometry2D.cpp DataManagement/mitkGeometry2DData.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkLandmarkBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModeOperation.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStateTransitionOperation.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeSlicedGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkVector.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkShaderProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkMaterial.cpp Interactions/mitkAction.cpp Interactions/mitkAffineInteractor.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkCoordinateSupplier.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkDisplayPositionEvent.cpp # Interactions/mitkDisplayVectorInteractorLevelWindow.cpp # legacy, prob even now unneeded # Interactions/mitkDisplayVectorInteractorScroll.cpp Interactions/mitkEvent.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventDescription.cpp Interactions/mitkEventFactory.cpp - Interactions/mitkEventHandler.cpp - Interactions/mitkEventObserver.cpp + Interactions/mitkInteractionEventHandler.cpp Interactions/mitkEventMapper.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkGlobalInteraction.cpp - Interactions/mitkInformer.cpp Interactions/mitkInteractor.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkMouseModeSwitcher.cpp Interactions/mitkMouseMovePointSetInteractor.cpp Interactions/mitkMoveBaseDataInteractor.cpp Interactions/mitkNodeDepententPointSetInteractor.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkPointSetInteractor.cpp Interactions/mitkPositionEvent.cpp Interactions/mitkPositionTracker.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkState.cpp -# Interactions/mitkStatedEventObserver.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateEvent.cpp Interactions/mitkStateMachine.cpp Interactions/mitkStateMachineFactory.cpp Interactions/mitkTransition.cpp Interactions/mitkWheelEvent.cpp Interactions/mitkKeyEvent.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkCrosshairPositionEvent.cpp + + Interfaces/mitkInteractionEventObserver.cpp + IO/mitkBaseDataIOFactory.cpp IO/mitkCoreDataNodeReader.cpp IO/mitkDicomSeriesReader.cpp IO/mitkFileReader.cpp IO/mitkFileSeriesReader.cpp IO/mitkFileWriter.cpp #IO/mitkIpPicGet.c IO/mitkImageGenerator.cpp IO/mitkImageWriter.cpp IO/mitkImageWriterFactory.cpp IO/mitkItkImageFileIOFactory.cpp IO/mitkItkImageFileReader.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkItkPictureWrite.cpp IO/mitkIOUtil.cpp IO/mitkLookupTableProperty.cpp IO/mitkOperation.cpp #IO/mitkPicFileIOFactory.cpp #IO/mitkPicFileReader.cpp #IO/mitkPicFileWriter.cpp #IO/mitkPicHelper.cpp #IO/mitkPicVolumeTimeSeriesIOFactory.cpp #IO/mitkPicVolumeTimeSeriesReader.cpp IO/mitkPixelType.cpp IO/mitkPointSetIOFactory.cpp IO/mitkPointSetReader.cpp IO/mitkPointSetWriter.cpp IO/mitkPointSetWriterFactory.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSTLFileIOFactory.cpp IO/mitkSTLFileReader.cpp IO/mitkSurfaceVtkWriter.cpp IO/mitkSurfaceVtkWriterFactory.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkVtiFileIOFactory.cpp IO/mitkVtiFileReader.cpp IO/mitkVtkImageIOFactory.cpp IO/mitkVtkImageReader.cpp IO/mitkVtkSurfaceIOFactory.cpp IO/mitkVtkSurfaceReader.cpp IO/vtkPointSetXMLParser.cpp IO/mitkLog.cpp Rendering/mitkBaseRenderer.cpp Rendering/mitkVtkMapper2D.cpp Rendering/mitkVtkMapper3D.cpp Rendering/mitkRenderWindowFrame.cpp Rendering/mitkGeometry2DDataMapper2D.cpp Rendering/mitkGeometry2DDataVtkMapper3D.cpp Rendering/mitkGLMapper2D.cpp Rendering/mitkGradientBackground.cpp Rendering/mitkManufacturerLogo.cpp Rendering/mitkMapper2D.cpp Rendering/mitkMapper3D.cpp Rendering/mitkMapper.cpp Rendering/mitkPointSetGLMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkPolyDataGLMapper2D.cpp Rendering/mitkSurfaceGLMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVolumeDataVtkMapper3D.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkShaderRepository.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp Common/mitkException.cpp Common/mitkCommon.h Common/mitkCoreObjectFactoryBase.cpp Common/mitkCoreObjectFactory.cpp ) list(APPEND CPP_FILES ${CppMicroServices_SOURCES}) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfig.xml Interactions/DisplayConfigPACS.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigMITK.xml Interactions/PointSet.xml Interactions/Legacy/StateMachine.xml Interactions/PointSetConfig.xml Interactions/Tests/AddAndRemovePoints.xml Interactions/Tests/globalConfig.xml Interactions/Tests/StatemachineTest.xml Interactions/Tests/StatemachineConfigTest.xml ) diff --git a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox index ffe736f286..6c74c6b905 100644 --- a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox +++ b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox @@ -1,204 +1,204 @@ /** \page DataInteractionPage Interaction Concepts \tableofcontents \section InteractionPage_Introduction Introduction to Interaction in MITK Interaction is a very important task in medical image processing software. Therefore MITK provides a special interaction concept that provides the developer with an easy way to develop and maintain user interaction separately from the algorithms processing the input. This allows e.g. for common interaction schemes to be re-used in different contexts. The core of the interaction concept is based on entities called \b DataInteractors that listen for certain pre-defined events and execute actions when such an event is triggered.\n In the following the different components of the interaction concept are explained. First a a high-level overview about how the different components interact is given, then some parts are explained in more detail. \subsection FurtherReadingInteraction Topics related to interaction - further information: See the \ref DataInteractionTechnicalPage page for a more technical explanation. \n Consult \ref HowToUseDataInteractor for usage information.\n See \ref SectionImplementationDataInteractor for an example on how to implement a new DataInteractor \n for information about how to create new events refer to ImplementNewEventsPage.\n The documentation of the depricated former concept can be found at \ref InteractionPage. \section HandlingSection Event Handling & Window Manager Abstraction The following sequence diagram gives an examplary overview of the process from creating an event until executing an action in the DataInteractor. This diagram assumes the usage of the Qt framework, but also shows that the interaction concept itself is implemented independent of any specific window manager. \image html event_handling.png
  1. a user event is triggered and send to MITK
  2. this layler serves as an adapter from window manager (here Qt) events to MITK internal events (later refered to as InteractionEvents).
  3. once the event is adapted it is send to a Dispatcher, which is linked to a render window, to be handled.
  4. on Dispatcher level all objects are known that can react to incoming events (DataInteractors)
  5. a DataInteractor is offered an event and checks its EventConfig object, which returns if a variant if this event has been defined for this DataInteractor.
  6. if the DataInteractor has a variant for the event, it consults its state machine to check if the input can be handled in the current state
  7. the actions asociated with a state change (transition) are executed and the event is successfully handled.
\section EventPage Events Events can describe any sort of user input, such as key strokes, mouse clicks or touch gestures. These events are mapped from an UI framework like Qt to an MITK internal representation and send to the Dispatcher which in turn deals with further processing of the event. These events are not limited to classical input devices but can be extened at will, by introducing new classes which e.g. describe events from tracking devices, etc. Refer to \subpage ImplementNewEventsPage to see how new events and thereby input devices can be integrated. For an overview of available Events see mitk::InteractionEvent, for on overview of parameters see the \subpage DataInteractionTechnicalPage. -\section EventHandlerSection EventHandler +\section InteractionEventHandlerSection InteractionEventHandler Is the term describing objects in general that can handle events. These objects can be devided into two groups, namely -DataInteractors and EventObserver. Their difference is that DataInteractors are linked with a DataNode which they manipulate, -whereas EventObserver do not have a DataNode and therefore are not supposed to manipulate any data. +DataInteractors and InteractionEventObserver. Their difference is that DataInteractors are linked with a DataNode which they manipulate, +whereas InteractionEventObserver do not have a DataNode and therefore are not supposed to manipulate any data. \dot digraph linker_deps { node [shape=record, fontname=Helvetica, fontsize=10]; - a [ label="EventHandler" ]; + a [ label="InteractionEventHandler" ]; d [ label="{StateMachine|HandleEvent()}" ]; b [ label="{DataInteractor|HandleEvent()}" ]; - c [ label="{EventObserver|Notify()}" ]; + c [ label="{InteractionEventObserver|Notify()}" ]; a -> d; d -> b; d -> c; } \enddot \subsection DataInteractorsSection DataInteractors -DataInteractors are specialized EventHandler which handle events for one spefific DataNode. They are implemented following a concept called state machines +DataInteractors are specialized InteractionEventHandler which handle events for one spefific DataNode. They are implemented following a concept called state machines (see e.g. Wikipedia ). \subsubsection StateMachinesSection StateMachines A specific events action is usually desired to dependent on the content of the data object the state of the interaction. For example if the when adding a line by clicking with the mouse, the first to clicks are supposed to add a point. But the second click should additionally finish the interaction and a subsequent third click should be ignored. State machines provide a great way to model such interaction in which the same user interaction can trigger different actions depending on the current state. Therefore DataInteractors work with so called state machine patterns. The basic idea here is that each interaction can be described by states and transitions which in turn trigger actions. These patterns define a workflow and different patterns can be applied to the same DataInteractor and cause this DataInteractor to perform different user interactions. This principle is best described by an example. Imagine a DataInteractor with the functionality (1) to add Points at a given mouse position and connect them by a line and (2) check if two points are on the same position. Using this DataInteractor, different StateMachine patterns/descriptions can be given which each cause the DataInteractor to perform different interaction schemes. State machine pattern 1: We want the user to draw a line. A simple state machine could express this by three states like this: \dot digraph linker_deps { node [shape=circle, fontname=Helvetica, fontsize=10]; a [ label="NoPoints" ]; b [ label="OnePoint" ]; c [ label="TwoPoints" ]; a -> b [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; b -> c [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; { rank=same; a b c } } \enddot With each MousePress event the AddPoint function is called and adds a point at the mouse position, unless two points already exist. State machine pattern 2: The same DataInteractor can also operate after the following state machine, which models the interaction to input a closed contour. The DataInteractor can detect an AddPoint event on an already existing point and will trigger a PointsMatch event. \dot digraph { node [shape=circle, fontname=Helvetica, fontsize=10]; a [ label="StartState" ]; b [ label="ClosedContour"]; a -> a [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; a -> b [label="PointsMatch/AddPoint",fontname=Helvetica, fontsize=10]; } \enddot In this way state machines provide both, a nice and structured way to represent interaction tasks and description of the interaction which is separated from the code. One DataInteractor can be re-used for different tasks by simply exchanging the state machine pattern. These patterns are described in XML files. \subsubsection DefinitionStateMachine Definition of a State Machine The definition is made up out of three components.
  • States - represent the current status of the interaction
  • Transitions - describe the events needed to change from one state to another
  • Actions - are executed, when a transition is taken
Each state machine needs exactly one designated start state into which the state machine is set in the beginning. An example of a state machine describing the interaction of example 2 looks like this: \code \endcode Example 1: State machine pattern, that describes adding points to a contour until the PointsMatch event is triggered. For a more detailed desciption of state machine patterns see here. -\subsection EventObserverSection EventObserver +\subsection InteractionEventObserverSection InteractionEventObserver -EventObserver are objects which will receive all user input and are intented for observation only, they should never modify any DataNodes. -For EventObserver it is optional to use the state machine functionality, the default is without. How to use the state machine functionality - is described in the documentation of mitk::EventObserver::Notify. +InteractionEventObserver are objects which will receive all user input and are intented for observation only, they should never modify any DataNodes. +For InteractionEventObserver it is optional to use the state machine functionality, the default is without. How to use the state machine functionality + is described in the documentation of mitk::InteractionEventObserver::Notify. \subsection ConfigurationSection Configuration In a lot of cases it is preferable to implement interactions independent of a specific event (e.g. left click with mouse), such that is it possible -to easily change this. This is achieved through configuration of EventHandlers. This allows to change the behavior at runtime. -The EventHandler provides an interface to easily modify the user input that triggers an action by loading a different configuration, this allows to implement +to easily change this. This is achieved through configuration of InteractionEventHandlers. This allows to change the behavior at runtime. +The InteractionEventHandler provides an interface to easily modify the user input that triggers an action by loading a different configuration, this allows to implement user-specific behavior of the software on an abstract level and to switch in at runtime. -This is achieved through XML files describing a configuration. These files can be loaded by the EventHandler and will lead to an internal mapping +This is achieved through XML files describing a configuration. These files can be loaded by the InteractionEventHandler and will lead to an internal mapping from specific user input to an absract description of the event given in the config file. In order to do this we distinguish between a spefic event and an event variant. A specific event is described by its event class, which determines the category of an event, e.g. the class MousePressEvent, and its parameter which make this event unique, e.g. LeftMouseButton pressed and no modifier keys pressed. -The event variant is a name that is assigned to a spefific event, and to which an EventHandler listens. +The event variant is a name that is assigned to a spefific event, and to which an InteractionEventHandler listens. -To illustrate this, an example is given here for two different configuration files. We assume an EventHandler that listens to the event variant 'AddPoint', +To illustrate this, an example is given here for two different configuration files. We assume an InteractionEventHandler that listens to the event variant 'AddPoint', two possible config files could then look like this: \code - + - + \endcode Example 2: Event description of a left click with the mouse and \code - + - + \endcode Example 3: Event description of a left click with the mouse while pressing the shift-key -If the EventHandler is loaded with the first configuration the event variant 'MousePress' is triggered when the user performs a mouse click, +If the InteractionEventHandler is loaded with the first configuration the event variant 'MousePress' is triggered when the user performs a mouse click, while when the second configuration is loaded 'MousePress' is triggered when the user performs a right click while pressing the shift button. -In this way all objects derived by EventHandler can be configured. For a detailed description about how to create the XML file see \ref ConfigurationTechnical . +In this way all objects derived by InteractionEventHandler can be configured. For a detailed description about how to create the XML file see \ref ConfigurationTechnical . \section DispatcherSection Dispatcher This unit receives all events and distributes them to the DataInteractors. This is done by ordering the DataInteractors according to the layer of their DataNode in descending order. Then the event is offered to the first DataInteractor, which in turn checks if it can handle the event. This is done -for each DataInteractor until the first processes the event, after this the other DataInteractors are skipped and all EventObservers are notified. +for each DataInteractor until the first processes the event, after this the other DataInteractors are skipped and all InteractionEventObservers are notified. */ diff --git a/Core/Documentation/Doxygen/Concepts/NewEvents.dox b/Core/Documentation/Doxygen/Concepts/NewEvents.dox index 2f7992c126..cb42cb550a 100644 --- a/Core/Documentation/Doxygen/Concepts/NewEvents.dox +++ b/Core/Documentation/Doxygen/Concepts/NewEvents.dox @@ -1,56 +1,72 @@ /** \page ImplementNewEventsPage What needs to be done to implement a new event? \tableofcontents \section WhenUseEvents When to use this guide In general there are no restriction about how events are created and processed. The intention of this page is to provide how to contruct Events in order to use them with the MITK Interaction Concept. \section OriginEvents Origin and processing of Events \ref DataInteractionPage gives a brief description of how events are generated and proccessed. After events are created they need to be send via mitk::RenderWindowBase::HandleEvent() so that they are relayed to a Dispatcher which handles the event distribution to the DataInteractors. \section EventImplementation Event Implementation The only prerequisite for a new event to be accepted is that it is derived from the mitk::InteractionEvent class. Further it is neccessary to provide a unique string identifier for this event class -(this string will identify this class/super-class in a state machine pattern by the event_class tag), and it needs to implement at least one function, +(this string will identify this class/super-class in a state machine pattern by the event_class tag), and it needs to implement at least two functions, as shown at the example of the MousePressEvent. Implementation of equality for each event class by implementing isEqual. Equality does \b not mean an exact copy or pointer equality. Equality is determined by agreement in all attributes that are necessary to describe the event for a state machine transition. Here, for example, for the a mouse event press event, it is important which modifiers are used, which mouse button was used to triggered the event, but the mouse position is irrelevant. \code bool mitk::MousePressEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { // cast to your event class here mitk::MousePressEvent* mpe = dynamic_cast(interactionEvent.GetPointer()); if (mpe == NULL) { return false; } // Checking relevant attributes, such as EventButton and Modifiers, but omitting the mouse coordinates // Replace this to check for your event class' attributes return (this->GetEventButton() == mpe->GetEventButton() && this->GetModifiers() == mpe->GetModifiers() && this->GetButtonStates() == mpe->GetButtonStates()); } \endcode +The function IsSuperClassOf() implements an up cast to check if the provided baseClass object is derived from this class. +This function is used to support polymorphism on state machine pattern (XML) level. + +\code +bool mitk::MousePressEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + // Replace with your class, or implement some rules which classes are accepted. + MousePressEvent* event = dynamic_cast(baseClass.GetPointer()); + if (event != NULL) + { + return true; + } + return false; +} +\endcode + \section EventConstruction Configuration File & Event Factory Regarding the state machine and the state machine pattern parser there are no changes necessary. To be able to parse the new event, changes have to be made in the mitk::EventConfig and mitk::EventFactory classes. The mitk::EventConfig class has to be adapted in a way such that the parameters that describe the event are parsed. The parsing can be easily extended, and should provide a mitk::PropertyList for each event parsed. Lastly the mitk::EventFactory has to be extended to use this mitk::PropertyList and construct an event based on it. */ diff --git a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox index 82ee944421..493da74bde 100644 --- a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox @@ -1,432 +1,432 @@ /** \page Step10Page MITK Tutorial - Step 10: Adding new Interaction \tableofcontents \section HowToUseDataInteractor How to use an existing DataInteractor MITK provides finished DataInteractors for a variety of tasks, they can be found in Code/Core/Interactors. They can be used with state machine patterns and config files located under Resources/Interaction. A DataInteractor consists of four parts. The class describing the functionality and two XML files; one describes the state machine pattern, that is the workflow of an interaction and the second describes the user events which trigger an action. Lastly every DataInteractor works on a DataNode in which it stores and manipulates data. To use a DataInteractor these parts have to be brought together. This code demonstrates the use of an existing DataInteractor exemplary for the PointSetDataInteractor: First we need a DataNode that is added to the DataStorage. \code mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); GetDataStorage()->Add(dataNode.GetPointer()); \endcode Then we create an instance of to PointSetDataInteractor and load a statemachine pattern as well as a configuration for it: \code m_CurrentInteractor = mitk::PointSetDataInteractor::New(); m_CurrentInteractor->LoadStateMachine("PointSet.xml"); m_CurrentInteractor->LoadEventConfig("PointSetConfig.xml"); \endcode Lastly the DataNode is added to the DataInteractor \code m_CurrentInteractor->SetDataNode(dataNode); \endcode now the DataInteractor is ready for usage. \section SectionImplementationDataInteractor How to implement a new DataInteractor This second part of the tutorial step goes beyond the activation of an interactor, that modifies data by user interaction) as shown above. It shows what needs to be implemented to add a new way of interaction within your MITK application. Please see \ref DataInteractionPage as an introduction to the MITK interaction mechanism, you may also want to read \ref DataInteractionTechnicalPage. This tutorial is structured as follows: The first section deals with config files, describing all the parameters of events and how to use them in a configuration file. In the second section the basics are described that are needed to write a state machine pattern. The last section deals with brining configuration, state machine pattern and code together and gives an examplary implementation of a DataInteractor. \section ConfigFileDescriptionSection How to create a Config-File \subsection EventDescriptionSection Event Description Events are described by their parameters. Each event type has its own set of parameters that can be set in the configuration file. If a parameter is ommitted it is set to its default value. Following all possible parameters are listed and described, to which parameters events have is decribed in their respective documentation. Mandatory for each event description is the event class and the event variant. The parameters of an event are set by attribute tags. \note Refer to \ref EventClassSection for the meaning of event class. \b Mouse \b Buttons \n mitk::MouseButtons represent the buttons. They can be used for two attributes. First the EventButton which describes the button that triggered the event, this allways is a single button. Secondly the ButtonState attribute that describes which buttons were pressed at the moment the event has been generated. For example assume the right mouse button and the middle mouse button are already pressed, now also the left mouse button is pressed too and generates a second event, this would be described as follows: \code \endcode Note: Technically the LeftMouseButton is also pressed and should be listed in the ButtonState, but this is taken care of by the mitk:EventFactory . Key Events \n mitk::InteractionKeyEvent represents a pressed key, which key is pressed is provided with the Key attribute like this \code \endcode or \code \endcode \note Key Events do not require an explicit configuration all, for all key events there exists a predefined event variant with the name 'Std' + value, that is key a is named 'StdA'. The names for special keys are listed here: \dontinclude mitkInteractionEventConst.h \skipline // Special Keys \until // End special keys Modifier Keys \n mitk::ModifierKeys represent the combination of pressed modifier keys, several modifier keys pressed at the same time are denoted by listing them all separated by commas. \code \endcode \b ScrollDirection \n This attribute is unique to the mitk::MouseWheelEvent and describes the direction in which the mouse wheel is rotated. In the event description actual only the direction is provided, but the event is generated with the actual value, and this value can be retrieved from the object. \code \endcode \subsection ExamplesSection Examples Examples for key events: \code - + - + - + - + \endcode Examples for MousePress events: \code - + - + - + - + \endcode There exists a standard configuration file for the most common events called GlobalConfig.xml that can be used to as a default and can be extended by a specific definition. \subsection ParameterDescriptionSection Parameter Description It is also possible to store parameters in the config file. Those are stored using the param-tag, like this: \code \endcode Within the application these properties can then be access via a mitk::PropertyList like this: \code // sm - state machine loaded with config file example2 mitk::PropertyList::Pointer properties = GetAttributes(); std::string prop1; properties->GetStringProperty("property1",prop1); \endcode \section HowToStateMachine HowTo Write a State Machine A state machine pattern is described in a XML file. \subsection StateSection States States are described using the state-tag. Each state has to have a name. Exactly one state has to be as start state in each state machine to indicate the state in which the state machine is set when it is constructed. So a valid, but rather useless state machine would like like this: \code \endcode Optionally a state can be assigned a special mode that influences the event distribution. These modes are GRAB_INPUT , PREFER_INPUT and REGULAR (where REGULAR is default and does not need to be indicated). See \ref DispatcherEventDistSection for a description of these modes. Use the special modes only when necessary as they prevent other DataInteractors to receive events. \code \endcode \subsection TransitionSection Transitions Transitions are part of a state and describe all possible state switches, and are therefore important for modelling an interaction scheme. Transitions consist a part that describes the event which triggers the transition (event class and event variant) and a target which is state to which the state machine switches after executing a transition. An event class describes the event type (see mitk::InteractionEvent for the different classes) and the event variant is a specification thereof and the exact description is taken from a config file. Together they determine which event can trigger this transition. For example this state machine will switch from state A to state B when the StdMousePressPrimaryButton event (left mouse button is pressed) occurs. \subsubsection EventClassSection Event Class The event class description supports the polymorphism of the event classes. Therefore state machine patters should be written in the most general ways possible. So for a given class hierarchy like this: \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="{PositionEvent}"]; b [ label="{MousePressEvent}" ]; c [ label="MouseReleaseEvent" ]; d [ label="TouchEvent", style=dotted ]; a -> b; a -> c; a -> d; } \enddot in the state machine pattern the PositionEvent can be declared as event class to restrict to the events which hold a position information. The actual implementation is then given in the configuration file. In this case it allows to define event of the classes PositionEvent itself, or MousePressEvent,MouseReleaseEvent,TouchEvent. This has the advantage that the patterns remain the same no matter what input devices are used, and the state machine patterns can be configured for newly added event classes as long as they match the class hierachy (this ensures they hold the neccessary properties). \code \endcode \subsection ActionSection Actions Actions can be added to transitions and represent functions in the DataInteractor that are executed on taking a transition. The following simple state machine will listen for left mouse clicks and execute two actions (and actually never stop). \code \endcode In order to tell the DataInteractor which function to execute these actions are made known to the DataInteractor using the CONNECT_FUNCTION macro. This example assumes that there exists an ExampleInteractor which inherits from DataInteractor. This class implements the functions AddPoint and CountClicks. The actions are introduced by implementing the virtual method ConnectActionsAndFunctions(): \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("countClicks", CountClicks); } \endcode \section HowToDataInteractor Implementation a new DataInteractor DataInteractors are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent PointSetDataInteractor To provide a useful example the mitk::PointSetDataInteractor is annotated with comments that describe the important parts for an implementation of a DataInteractor. This step assumes knowlege of the Interaction concept described in \ref DataInteractionPage and some background of the implementation which is described in \ref DataInteractionPageTechnical. Please refer to these pages before proceeding. DataInteractor are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent Example Interactor using InternalEvent A useful tool in creating DataInteractors are mitk::InternalEvents which allow to the DataInteractor send signals on its own. The following will describe how to build a DataInteractor that allows to add points until a certain number of points is reached. The number of accepted points is provided in the config file as a parameter. So we start by writing a state machine pattern that add points until it receives an InternalEvent telling it, that enough points have been added. \code <--! dead state, nothing happens any more, once we reached this --> \endcode In our config file we set the number of maximal points to 10, and define AddPointClick as a right mouse click with the ctrl button pressed. \code - + - + \endcode The implementation is desribed in the following. \see Step10.h \see Step10.cpp \dontinclude Step10.h Implementation of protected functions: \skipline protected: \until virtual void ConfigurationChanged(); ConnectActionsAndFunctions - Is inherited from mitk::InteractionStateMachine, here action strings from the xml are connected with functions in the Interactor (as seen above). In our example this looks like this: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConnectActionsAndFunctions() \until } - ConfigurationChanged - Is called whenever a new configuration file is loaded (by the mitk::EventHandler super class), + ConfigurationChanged - Is called whenever a new configuration file is loaded (by the mitk::InteractionEventHandler super class), this function allows to implement initialization code that depends on configuration values. In our example we want to set the limit of allowed points: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConfigurationChang \until } Next the actual functionality of the DataInteractor is implemented, by providing one function per action, following this prototype: \code bool FUNCTION_NAME (StateMachineAction* , InteractionEvent*); \endcode \dontinclude Step10.h \skipline private: \until bool EnoughPoints(StateMac Each function has to return a boolean value. True if the action has been executed, and false if the action has not been executed. \dontinclude Step10.cpp \skipline bool mitk::ExampleInteractor::AddPoint(StateM \until //- Here we see an internal event used to signal that the point set reached the maximal number of allowed points. The event is created and added to the Dispatchers event queue. \dontinclude Step10.cpp \skipline // create internal \until positionEvent->GetSender( \note That internal events do not need any mapping to event variants. Their signal same is equivalent with the event variant. - There are also two documented classes implementing a DataInteractor and an EventObserver which can be looked at for further + There are also two documented classes implementing a DataInteractor and an InteractionEventObserver which can be looked at for further understanding: \see mitk::PointSetDataInteractor \see mitk::DisplayInteractor Have fun with creating your own interaction and please think about contributing it to MITK! If you meet any difficulties during this step, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! People there are kind and will try to help you. \ref Step09Page "[Previous step]" \ref TutorialPage "[Main tutorial page]" */ \ No newline at end of file diff --git a/Modules/Qmitk/QmitkEventAdapter.h b/Modules/Qmitk/QmitkEventAdapter.h index 01cd98d741..f83ca791c5 100644 --- a/Modules/Qmitk/QmitkEventAdapter.h +++ b/Modules/Qmitk/QmitkEventAdapter.h @@ -1,37 +1,41 @@ /*=================================================================== 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 QMITKEVENTADAPTER_H_ #define QMITKEVENTADAPTER_H_ #include #include #include #include #include #include - +/** +* \deprecatedSince{2013_03} mitk::QmitkEventAdapter is deprecated. It will become obsolete. Adaption of events is now handeled (for Qt events) in +* QmitkRenderWindow. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation + */ class QMITK_EXPORT QmitkEventAdapter { public: static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, QMouseEvent* mouseEvent); static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, QWheelEvent* wheelEvent); static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, QKeyEvent* keyEvent, const QPoint& point); }; #endif /*QMITKEVENTADAPTER_H_*/ diff --git a/Modules/Qmitk/QmitkRenderWindow.h b/Modules/Qmitk/QmitkRenderWindow.h index 398f0df3c2..1af9baba04 100644 --- a/Modules/Qmitk/QmitkRenderWindow.h +++ b/Modules/Qmitk/QmitkRenderWindow.h @@ -1,181 +1,180 @@ /*=================================================================== 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 QMITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66 #define QMITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66 #include "mitkRenderWindowBase.h" #include #include "QVTKWidget.h" #include "QmitkRenderWindowMenu.h" #include "mitkInteractionEventConst.h" -#include class QmitkStdMultiWidget; class QDragEnterEvent; class QDropEvent; /** * \brief MITK implementation of the QVTKWidget * \ingroup Renderer */ class QMITK_EXPORT QmitkRenderWindow: public QVTKWidget, public mitk::RenderWindowBase { Q_OBJECT public: QmitkRenderWindow(QWidget *parent = 0, QString name = "unnamed renderwindow", mitk::VtkPropRenderer* renderer = NULL, mitk::RenderingManager* renderingManager = NULL); virtual ~QmitkRenderWindow(); /** * \brief Whether Qt events should be passed to parent (default: true) * * With introduction of the QVTKWidget the behaviour regarding Qt events changed. * QVTKWidget "accepts" Qt events like mouse clicks (i.e. set an "accepted" flag). * When this flag is set, Qt fininshed handling of this event -- otherwise it is * reached through to the widget's parent. * * This reaching through to the parent was implicitly required by QmitkMaterialWidget / QmitkMaterialShowCase. *QmitkStdMultiWidget * The default behaviour of QmitkRenderWindow is now to clear the "accepted" flag * of Qt events after they were handled by QVTKWidget. This way parents can also * handle events. * * If you don't want this behaviour, call SetResendQtEvents(true) on your render window. */ virtual void SetResendQtEvents(bool resend); // Set Layout Index to define the Layout Type void SetLayoutIndex(unsigned int layoutIndex); // Get Layout Index to define the Layout Type unsigned int GetLayoutIndex(); //MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged(int layoutDesignIndex); void HideRenderWindowMenu(); //Activate or Deactivate MenuWidget. void ActivateMenuWidget(bool state, QmitkStdMultiWidget* stdMultiWidget = 0); bool GetActivateMenuWidgetFlag() { return m_MenuWidgetActivated; } // Get it from the QVTKWidget parent virtual vtkRenderWindow* GetVtkRenderWindow() { return GetRenderWindow(); } virtual vtkRenderWindowInteractor* GetVtkRenderWindowInteractor() { return NULL; } void FullScreenMode(bool state); protected: // overloaded move handler virtual void moveEvent(QMoveEvent* event); // overloaded show handler void showEvent(QShowEvent* event); // overloaded resize handler virtual void resizeEvent(QResizeEvent* event); // overloaded paint handler virtual void paintEvent(QPaintEvent* event); // overloaded mouse press handler virtual void mousePressEvent(QMouseEvent* event); // overloaded mouse move handler virtual void mouseMoveEvent(QMouseEvent* event); // overloaded mouse release handler virtual void mouseReleaseEvent(QMouseEvent* event); // overloaded key press handler virtual void keyPressEvent(QKeyEvent* event); // overloaded enter handler virtual void enterEvent(QEvent*); // overloaded leave handler virtual void leaveEvent(QEvent*); /// \brief Simply says we accept the event type. virtual void dragEnterEvent(QDragEnterEvent *event); /// \brief If the dropped type is application/x-mitk-datanodes we process the request by converting to mitk::DataNode pointers and emitting the NodesDropped signal. virtual void dropEvent(QDropEvent * event); #ifndef QT_NO_WHEELEVENT // overload wheel mouse event virtual void wheelEvent(QWheelEvent*); #endif void AdjustRenderWindowMenuVisibility(const QPoint& pos); signals: void ResetView(); // \brief int parameters are enum from QmitkStdMultiWidget void ChangeCrosshairRotationMode(int); void SignalLayoutDesignChanged(int layoutDesignIndex); void moved(); void resized(); /// \brief Emits a signal to say that this window has had the following nodes dropped on it. void NodesDropped(QmitkRenderWindow *thisWindow, std::vector nodes); protected slots: void OnChangeLayoutDesign(int layoutDesignIndex); void OnWidgetPlaneModeChanged(int); void DeferredHideMenu(); private: // Helper Functions to Convert Qt-Events to Mitk-Events mitk::Point2D GetMousePosition(QMouseEvent* me); mitk::Point2D GetMousePosition(QWheelEvent* we); mitk::MouseButtons GetEventButton(QMouseEvent* me); mitk::MouseButtons GetButtonState(QMouseEvent* me); mitk::ModifierKeys GetModifiers(QMouseEvent* me); mitk::MouseButtons GetButtonState(QWheelEvent* we); mitk::ModifierKeys GetModifiers(QWheelEvent* we); mitk::ModifierKeys GetModifiers(QKeyEvent* ke); std::string GetKeyLetter(QKeyEvent* ke); int GetDelta(QWheelEvent* we); bool m_ResendQtEvents; QmitkRenderWindowMenu* m_MenuWidget; bool m_MenuWidgetActivated; unsigned int m_LayoutIndex; }; #endif diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 9d8945ce55..8cbc12ed8b 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,46 +1,45 @@ # Plug-ins must be ordered according to their dependencies set(MITK_EXT_PLUGINS org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dtiatlasapp:OFF org.mitk.gui.qt.examples:OFF org.mitk.gui.qt.examplesopencv:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.meshdecimation:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.python.console:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF - org.mitk.gui.InteractionTests:OFF ) diff --git a/Plugins/org.mitk.gui.InteractionTests/CMakeLists.txt b/Plugins/org.mitk.gui.InteractionTests/CMakeLists.txt deleted file mode 100644 index 60181330b7..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -project(org_mitk_gui_InteractionTests) - -MACRO_CREATE_MITK_CTK_PLUGIN( - EXPORT_DIRECTIVE INTERACTIONTESTS_EXPORT - EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDENCIES QmitkExt -) diff --git a/Plugins/org.mitk.gui.InteractionTests/Resources/PointsConfigRightClick.xml b/Plugins/org.mitk.gui.InteractionTests/Resources/PointsConfigRightClick.xml deleted file mode 100644 index a8684eef4a..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/Resources/PointsConfigRightClick.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/Manual.dox deleted file mode 100644 index abdf834276..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/Manual.dox +++ /dev/null @@ -1,18 +0,0 @@ -/** -\page org_mitk_gui_InteractionTests InteractionTests - -\image html icon.xpm "Icon of InteractionTests" - -Available sections: - - \ref org_mitk_gui_InteractionTestsOverview - -\section org_mitk_gui_InteractionTestsOverview -Describe the features of your awesome plugin here -
    -
  • Increases productivity -
  • Creates beautiful images -
  • Generates PhD thesis -
  • Brings world peace -
- -*/ \ No newline at end of file diff --git a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/icon.xpm deleted file mode 100644 index 9057c20bc6..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/icon.xpm +++ /dev/null @@ -1,21 +0,0 @@ -/* XPM */ -static const char * icon_xpm[] = { -"16 16 2 1", -" c #FF0000", -". c #000000", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; diff --git a/Plugins/org.mitk.gui.InteractionTests/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.InteractionTests/documentation/doxygen/modules.dox deleted file mode 100644 index abdd614931..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/documentation/doxygen/modules.dox +++ /dev/null @@ -1,16 +0,0 @@ -/** - \defgroup org_mitk_gui_InteractionTests org.mitk.gui.InteractionTests - \ingroup MITKPlugins - - \brief Describe your plugin here. - -*/ - -/** - \defgroup org_mitk_gui_InteractionTests_internal Internal - \ingroup org_mitk_gui_InteractionTests - - \brief This subcategory includes the internal classes of the org.mitk.gui.InteractionTests plugin. Other - plugins must not rely on these classes. They contain implementation details and their interface - may change at any time. We mean it. -*/ diff --git a/Plugins/org.mitk.gui.InteractionTests/files.cmake b/Plugins/org.mitk.gui.InteractionTests/files.cmake deleted file mode 100644 index ff5dcd2c35..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/files.cmake +++ /dev/null @@ -1,46 +0,0 @@ -set(SRC_CPP_FILES - -) - -set(INTERNAL_CPP_FILES - org_mitk_gui_InteractionTests_Activator.cpp - InteractionTests.cpp -) - -set(UI_FILES - src/internal/InteractionTestsControls.ui -) - -set(MOC_H_FILES - src/internal/org_mitk_gui_InteractionTests_Activator.h - src/internal/InteractionTests.h -) - -# list of resource files which can be used by the plug-in -# system without loading the plug-ins shared library, -# for example the icon used in the menu and tabs for the -# plug-in views in the workbench -set(CACHED_RESOURCE_FILES - resources/icon.xpm - plugin.xml -) - -# list of Qt .qrc files which contain additional resources -# specific to this plugin -set(QRC_FILES - -) - -set(CPP_FILES ) - -foreach(file ${SRC_CPP_FILES}) - set(CPP_FILES ${CPP_FILES} src/${file}) -endforeach(file ${SRC_CPP_FILES}) - -foreach(file ${INTERNAL_CPP_FILES}) - set(CPP_FILES ${CPP_FILES} src/internal/${file}) -endforeach(file ${INTERNAL_CPP_FILES}) - -set(RESOURCE_FILES -PointsConfigRightClick.xml -) diff --git a/Plugins/org.mitk.gui.InteractionTests/manifest_headers.cmake b/Plugins/org.mitk.gui.InteractionTests/manifest_headers.cmake deleted file mode 100644 index 5fc129013f..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/manifest_headers.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(Plugin-Name "InteractionTests") -set(Plugin-Version "0.1") -set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") -set(Plugin-ContactAddress "") -set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.common.legacy) diff --git a/Plugins/org.mitk.gui.InteractionTests/plugin.xml b/Plugins/org.mitk.gui.InteractionTests/plugin.xml deleted file mode 100644 index 9ad93e2b56..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/plugin.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Plugins/org.mitk.gui.InteractionTests/resources/icon.xpm b/Plugins/org.mitk.gui.InteractionTests/resources/icon.xpm deleted file mode 100644 index 9057c20bc6..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/resources/icon.xpm +++ /dev/null @@ -1,21 +0,0 @@ -/* XPM */ -static const char * icon_xpm[] = { -"16 16 2 1", -" c #FF0000", -". c #000000", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.cpp b/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.cpp deleted file mode 100644 index ce3178be7b..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/*=================================================================== - - 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. - - ===================================================================*/ - -// Blueberry -#include -#include - -// Qmitk -#include "InteractionTests.h" - -// Qt -#include - -// rest - -#include "mitkDataNode.h" -#include - -// us -#include "mitkGetModuleContext.h" -#include "mitkModule.h" -#include "mitkModuleRegistry.h" -#include "mitkInformer.h" - -#include "mitkEventObserver.h" - -//#include "mitkInformerActivator.h" - -const std::string InteractionTests::VIEW_ID = "org.mitk.views.interactiontests"; - -void InteractionTests::SetFocus() -{ - m_Controls.buttonPerformImageProcessing->setFocus(); -} - -void InteractionTests::CreateQtPartControl(QWidget *parent) -{ - // create GUI widgets from the Qt Designer's .ui file - m_Controls.setupUi(parent); - connect(m_Controls.buttonPerformImageProcessing, SIGNAL(clicked()), this, SLOT(DrawLines())); - connect(m_Controls.toggleConfig, SIGNAL(clicked()), this, SLOT(ToggleConfig())); - connect(m_Controls.grabInput, SIGNAL(clicked()), this, SLOT(GrabInput())); - m_Controls.buttonPerformImageProcessing->setText(QString("Line Interactor (Left Click)")); - m_ConfigChoice = true; -} - -void InteractionTests::ToggleConfig() -{ - std::vector selections = GetDataManagerSelection(); - for (std::vector::iterator it = selections.begin(); it != selections.end(); ++it) - { - if ((*it)->GetDataInteractor().IsNotNull()) - { - if (!m_ConfigChoice) - { - (*it)->GetDataInteractor()->LoadEventConfig("globalConfig.xml"); - (*it)->GetDataInteractor()->AddEventConfig("PointSetConfig.xml"); - m_Controls.buttonPerformImageProcessing->setText(QString("Line Interactor (Left Click)")); - m_ConfigChoice = true; - } - else - { - (*it)->GetDataInteractor()->LoadEventConfig("globalConfig.xml"); - (*it)->GetDataInteractor()->AddEventConfig("PointSetConfig.xml"); - m_Controls.buttonPerformImageProcessing->setText(QString("Line Interactor (Right Click)")); - m_ConfigChoice = false; - } - } - } -} - -void InteractionTests::GrabInput() -{ -// m_CurrentDataNode = mitk::DataNode::New(); -// GetDataStorage()->Add(m_CurrentDataNode.GetPointer(), m_CurrentImage); -// -// m_CurrentInteractor = mitk::PointSetDataInteractor::New(); -// if (!m_CurrentInteractor->LoadStateMachine("/home.local/webechr.local/EclipseTest/test/LineSMGrab.xml")) -// { -// return; -// } -// m_CurrentInteractor->LoadEventConfig("/home.local/webechr.local/EclipseTest/test/PointsConfig.xml"); -// m_CurrentInteractor->AddEventConfig("/home.local/webechr.local/EclipseTest/test/globalConfig.xml"); -// m_CurrentInteractor->SetDataNode(m_CurrentDataNode); -} - -void InteractionTests::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& nodes) -{ - // iterate all selected objects, adjust warning visibility - foreach ( mitk::DataNode::Pointer node, nodes ){ - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) - { - m_CurrentImage = node; - m_Controls.labelWarning->setVisible( false ); - m_Controls.buttonPerformImageProcessing->setEnabled( true ); - return; - } -} -m_Controls.labelWarning->setVisible( true ); -m_Controls.buttonPerformImageProcessing->setEnabled( false ); -} - -void InteractionTests::DrawLines() -{ - m_CurrentDataNode = mitk::DataNode::New(); - GetDataStorage()->Add(m_CurrentDataNode.GetPointer(), m_CurrentImage); - //m_CurrentInteractor = mitk::TestInteractor::New(); - m_CurrentInteractor = mitk::PointSetDataInteractor::New(); - m_CurrentInteractor->LoadStateMachine("PointSet.xml"); - - if (m_ConfigChoice) - { - m_CurrentInteractor->LoadEventConfig("globalConfig.xml"); - m_CurrentInteractor->AddEventConfig("PointSetConfig.xml"); - } - else - { - m_CurrentInteractor->LoadEventConfig("globalConfig.xml"); - m_CurrentInteractor->AddEventConfig("PointSetConfig.xml"); - } - m_CurrentInteractor->SetDataNode(m_CurrentDataNode); - - mitk::EventObserver::Pointer eO = mitk::EventObserver::New(); - mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - mitk::ServiceReference serviceRef = context->GetServiceReference(); - mitk::InformerService* service = dynamic_cast(context->GetService(serviceRef)); - service->RegisterObserver(eO); - -} diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.h b/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.h deleted file mode 100644 index 9125363275..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.h +++ /dev/null @@ -1,70 +0,0 @@ -/*=================================================================== - - 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 InteractionTests_h -#define InteractionTests_h - -#include - -#include - -#include "mitkPointSetDataInteractor.h" - -#include "ui_InteractionTestsControls.h" - -/*! - \brief InteractionTests - - \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. - - \sa QmitkFunctionality - \ingroup ${plugin_target}_internal - */ -class InteractionTests: public QmitkFunctionality -{ - // this is needed for all Qt objects that should have a Qt meta-object - // (everything that derives from QObject and wants to have signal/slots) -Q_OBJECT - -public: - - static const std::string VIEW_ID; - - virtual void CreateQtPartControl(QWidget *parent); - -protected slots: - - /// \brief Called when the user clicks the GUI button - void DrawLines(); - void ToggleConfig(); - void GrabInput(); - -protected: - - virtual void SetFocus(); - - /// \brief called by QmitkFunctionality when DataManager's selection has changed - virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList& nodes); - - Ui::InteractionTestsControls m_Controls; -private: - mitk::DataNode::Pointer m_CurrentDataNode; - mitk::PointSetDataInteractor::Pointer m_CurrentInteractor; - mitk::DataNode::Pointer m_CurrentImage; - bool m_ConfigChoice; -}; - -#endif // InteractionTests_h diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTestsControls.ui b/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTestsControls.ui deleted file mode 100644 index f1ced7fe57..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTestsControls.ui +++ /dev/null @@ -1,78 +0,0 @@ - - - InteractionTestsControls - - - - 0 - 0 - 234 - 161 - - - - - 0 - 0 - - - - QmitkTemplate - - - - - - QLabel { color: rgb(255, 0, 0) } - - - Please select an image! - - - - - - - - - - Line Interactor - - - - - - - Toggle Config of Selected - - - - - - - Line Interactor (Grab Input) - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 220 - - - - - - - - - - diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.cpp b/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.cpp deleted file mode 100644 index 75e26a9aea..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/*=================================================================== - -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 "org_mitk_gui_InteractionTests_Activator.h" - -#include - -#include "InteractionTests.h" - -namespace mitk { - -void org_mitk_gui_InteractionTests_Activator::start(ctkPluginContext* context) -{ - BERRY_REGISTER_EXTENSION_CLASS(InteractionTests, context) -} - -void org_mitk_gui_InteractionTests_Activator::stop(ctkPluginContext* context) -{ - Q_UNUSED(context) -} - -} - -Q_EXPORT_PLUGIN2(org_mitk_gui_InteractionTests, mitk::org_mitk_gui_InteractionTests_Activator) diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.h b/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.h deleted file mode 100644 index bc6fcc4e66..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.h +++ /dev/null @@ -1,40 +0,0 @@ -/*=================================================================== - -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 org_mitk_gui_InteractionTests_Activator_h -#define org_mitk_gui_InteractionTests_Activator_h - -#include - -namespace mitk { - -class org_mitk_gui_InteractionTests_Activator : - public QObject, public ctkPluginActivator -{ - Q_OBJECT - Q_INTERFACES(ctkPluginActivator) - -public: - - void start(ctkPluginContext* context); - void stop(ctkPluginContext* context); - -}; // org_mitk_gui_InteractionTests_Activator - -} - -#endif // org_mitk_gui_InteractionTests_Activator_h