diff --git a/Core/Code/Interactions/mitkDispatcher.h b/Core/Code/Interactions/mitkDispatcher.h index 89a580d88e..50ce960ca8 100644 --- a/Core/Code/Interactions/mitkDispatcher.h +++ b/Core/Code/Interactions/mitkDispatcher.h @@ -1,131 +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 "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; struct 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::LightObject { public: 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 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 + * See \ref DataInteractionTechnicalPage_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 InteractionEventObservers about InteractionEvents */ mitk::ServiceTracker* m_EventObserverTracker; }; } /* namespace mitk */ #endif /* mitkDispatcher_h */ diff --git a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox index 8d4be67bc1..d9a4eaa91c 100644 --- a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox +++ b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox @@ -1,224 +1,224 @@ /** \page DataInteractionPage Interaction Concepts \tableofcontents -\section InteractionPage_Introduction Introduction to Interaction in MITK +\section DataInteractionPage_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 mitk::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. \n For a list of changes with respect to the previous interaction concept please refer to the \ref InteractionMigration -\section HandlingSection Event Handling & GUI Toolkit Abstraction +\section DataInteractionPage_HandlingSection Event Handling & GUI Toolkit Abstraction The following sequence diagram gives an exemplary overview of the process from creating an event until executing an action in the mitk::DataInteractor. This diagram assumes the usage of the Qt framework, but also shows that the interaction concept itself is implemented independent of any specific graphical user interface toolkit. \image html event_handling.png
  1. a user event is triggered and send to MITK
  2. this layer serves as an adapter from the GUI toolkit (here Qt) events to MITK internal events (later referred to as \link mitk::InteractionEvent InteractionEvents\endlink).
  3. once the event is adapted it is send to a mitk::Dispatcher, which is linked to a render window, to be handled.
  4. on the mitk::Dispatcher level all objects are known that can react to incoming events (mitk::DataInteractor and mitk::InteractionEventObserver instances)
  5. a mitk::DataInteractor is offered an event and checks its mitk::EventConfig object, which returns if a variant of 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 associated with a state change (transition) are executed and the event is successfully handled.
-\section EventPage Events +\section DataInteractionPage_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 mitk::Dispatcher which in turn deals with further processing of the event. These events are not limited to classical input devices but can be extended 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 InteractionEventHandlerSection InteractionEventHandler +\section DataInteractionPage_InteractionEventHandlerSection InteractionEventHandler Is the term describing objects in general that can handle events. These objects can be divided into two groups, namely \link mitk::DataInteractor DataInteractors\endlink and mitk::InteractionEventObserver. Their difference is that mitk::DataInteractor instances are linked with a mitk::DataNode which they manipulate, whereas mitk::InteractionEventObserver instances do not have a mitk::DataNode and therefore are not supposed to manipulate any data. \dot digraph linker_deps { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="InteractionEventHandler" ]; d [ label="{EventStateMachine|HandleEvent()}" ]; b [ label="{DataInteractor|PerformAction()}" ]; a -> d; d -> b; } \enddot -\subsection DataInteractorsSection DataInteractors +\subsection DataInteractionPage_DataInteractorsSection DataInteractors DataInteractors are specialized mitk::InteractionEventHandler which handle events for one spefific DataNode. They are implemented following a concept called state machines (see e.g. Wikipedia ). -\subsubsection StateMachinesSection StateMachines +\subsubsection DataInteractionPage_StateMachinesSection StateMachines A specific events action is usually desired to depend on the content of the data object and the state of the interaction. For example when adding a line by clicking with the mouse, the first two 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 mitk::DataInteractor and cause this mitk::DataInteractor to perform different user interactions. This principle is best described by an example. Imagine a mitk::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 mitk::DataInteractor, different mitk::StateMachine patterns/descriptions can be given which each cause the mitk::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 mitk::DataInteractor can also operate after the following state machine, which models the interaction to input a closed contour. The mitk::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 +\subsubsection DataInteractionPage_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 description of state machine patterns see here. -\subsection InteractionEventObserverSection InteractionEventObserver +\subsection DataInteractionPage_InteractionEventObserverSection InteractionEventObserver mitk::InteractionEventObserver instances are objects which will receive all user input and are intended for observation only, they should never modify any DataNodes. For mitk::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. \dot digraph event_observer { node [shape=record, fontname=Helvetica, fontsize=10]; c [ label="{InteractionEventObserver|Notify()}" ]; a [ label="InteractionEventHandler" ]; b [ label="{EventStateMachine|HandleEvent()}" ]; d [ label="{MyCustomObserver|PerformAction()}" ]; c -> d; a -> b; b -> d [style="dashed",label="optional"]; } \enddot -\subsection ConfigurationSection Configuration +\subsection DataInteractionPage_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 it is possible to easily change this. This is achieved through configuration of \link mitk::InteractioinEventHandler InteractionEventHandlers\endlink. This allows to change the behavior at runtime. The mitk::InteractionEventHandler class 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 it at runtime. This is achieved through XML files describing a configuration. These files can be loaded by the mitk::InteractionEventHandler and will lead to an internal mapping from specific user input to an abstract description of the event given in the config file. In order to do this we distinguish between a specific 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 mitk::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 specific event, and to which an mitk::InteractionEventHandler listens. To illustrate this, an example is given here for two different configuration files. We assume that a mitk::InteractionEventHandler 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 mitk::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 from mitk::InteractionEventHandler can be configured. For a detailed description about how to create the XML file see the \ref DataInteractionTechnicalPage page. -\section DispatcherSection Dispatcher +\section DataInteractionPage_DispatcherSection Dispatcher Instances of mitk::Dispatcher receive all events and distribute them to their related mitk::DataInteractor instances. This is done by ordering the DataInteractors according to the layer of their mitk::DataNode in descending order. Then the event is offered to the first mitk::DataInteractor, which in turn checks if it can handle the event. This is done for each mitk::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/DataInteractionTechnical.dox b/Core/Documentation/Doxygen/Concepts/DataInteractionTechnical.dox index 01447e6b83..44e4d91895 100644 --- a/Core/Documentation/Doxygen/Concepts/DataInteractionTechnical.dox +++ b/Core/Documentation/Doxygen/Concepts/DataInteractionTechnical.dox @@ -1,115 +1,115 @@ /** \page DataInteractionTechnicalPage Interaction Concept Implementation \tableofcontents This page describes some technicalities of the implementation and the workflow, for a detailed list of tutorials see \ref FurtherReadingInteraction . \section DataInteractionTechnicalPage_Introduction Description of Interaction Concept Implementation in MITK -\section DispatcherSection Dispatcher +\section DataInteractionTechnicalPage_DispatcherSection Dispatcher After an event is received by the mitk::Dispatcher it is given to a mitk::DataInteractor that has to decide if it can process this event. On a high level this is done by the mitk::EventStateMachine. First the state machine asks if the received event is known in the configuration. If it is, the matching variant name is returned. Then the state machine checks if there exists a transition in its current state that is triggered by this event variant. If this is the case all actions that are associated with this transition are queried and executed. The actions themselves are implemented on mitk::DataInteractor level. The following diagram illustrates the process: \image html sm_and_config.png Each mitk::BaseRenderer creates a mitk::BindDispatcherInteractor object which encapsulates the connection between the mitk::DataStorage and the mitk::Dispatcher, and thereby allowing a mitk::DataInteractor to register with a mitk::Dispatcher when only knowing the mitk::DataNode. mitk::BindDispatcherInteractor creates a new mitk::Dispatcher object and registers for mitk::DataNode events at the mitk::DataStorage, as a callback function the dispatchers AddDataInteractor() and RemoveDataInteractor() functions are set. \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="{BaseRenderer|m_BindDispatcherInteractor}"]; b [ label="{BindDispatcherInteractor|m_Dispatcher\n m_DataStorage}" ]; c [ label="Dispatcher" ]; d [ label="DataStorage" ]; a -> b; b -> c; b -> d; } \enddot This way the mitk::Dispatcher is notified about all changes regarding DataNodes that are shown in the mitk::BaseRenderer. When a node is added, remove or modified the mitk::Dispatcher can check if a mitk::DataInterator is set, and accordingly add or remove this mitk::DataInteractor from its internal list. \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; d [ label="DataInteractor" ]; a [ label="DataNode" ]; b [ label="DataStorage" ]; c [ label="Dispatcher" ]; e [ label="BaseRenderer"] edge [fontname=Helvetica, fontsize=10] d -> a [label="SetDataInteractor(this)"]; a -> b [label="Modified()"]; b -> c [label="NodeModified(dataNode)"]; e -> c [label="HandleEvent(interactionEvent)"]; { rank=same; b c a } { rank=same; e } } \enddot Events that are generated within the scope of the mitk::BaseRenderer are sent to the associated mitk::Dispatcher to be handled. -\subsection DispatcherEventDistSection Event Distribution +\subsection DataInteractionTechnicalPage_DispatcherEventDistSection Event Distribution A mitk::Dispatcher can operate in different processing modes, which determine how the interactor that receives an event is chosen. These modes are managed and set by the mitk::Dispatcher itself.
  • \b Regular: \n DataInteractors are sorted by their layer, and distribution is stared with the top-most.
  • Connected Mouse Action: \n A connected mouse action is described by the sequence of Mouse-Press, (optionally) Mouse-Move , Mouse-Release Events.\n Within this sequence all events are sent to the same mitk::DataInteractor, the one which received the event from the Mouse-Press action.\n \b m_ConnectedMouseAction - is set to true, when a Mouse-Down Event occurs and a DataInterator takes the event and \b m_SelectedInteractor is then set to this DataInteractor.\n \b m_ConnectedMouseAction is reset to false, after the Mouse-Release Event occurs,\n while it is true, the m_SelectedInteractor is the only one that receives Mouse-Events.
  • Grab Input:\n Whenever a mitk::DataInteractor performs a state change into a state that is marked by the grab input-tag, the mitk::Dispatcher switches into this mode. As long as it is in this mode ONLY the selected mitk::DataInteractor will receive the event. This mode is ended when the mitk::DataInteractor switches back to a state without a tag/ or the REGULAR-tag.\n \note In this mode mitk::InteractionEventObserver instances will NOT receive the events.
  • \b Prefer \b Input: \n Basically works as Grab Input, with the difference that if the mitk::DataInteractor is in the prefer input state but cannot process the event offered, it will be offered to the other interactors in the regular way.\n In this mode mitk::InteractionEventObserver instances ARE informed.
-\section StateMachineSection State Machine & Configuration +\section DataInteractionTechnicalPage_StateMachineSection State Machine & Configuration A mitk::EventStateMachine points to a \b state, which in turn references \b transitions (which describe a change from one state to another) and \b actions (indicating which functions are executed when a transition is taken). \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; d [ label="{StateMachine|m_CurrentState}" ]; a [ label="{StateMachineState|m_Transitions}" ]; b [ label="{StateMachineTransitions|m_Actions}"]; c [ label="{StateMachineAction}"]; edge [fontname=Helvetica, fontsize=10] d -> a [label="1 : 1"]; a -> b [label="1 : n"]; b -> c [label="1 : n"]; } \enddot */ diff --git a/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExtensionPointsIntro.dox b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExtensionPointsIntro.dox index 714b3d367b..c3685a5d21 100644 --- a/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExtensionPointsIntro.dox +++ b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExtensionPointsIntro.dox @@ -1,34 +1,34 @@ /** \page BlueBerryExampleExtensionPoint Extension Points \brief A minimal applictaion that definines an extension point and collects extensions. -# \subpage IntroductionExtensionPoints "Introduction" -# \subpage ExtensionPointDefinition "Extension Point Definition" -# \subpage ExtensionContribution "Extension Contribution" \page IntroductionExtensionPoints Introduction: Extension Point/Extension Concept The BlueBerry application framework provides the concept of extension points and extensions. The main goal is to allow the extension of functionality of a plugin (based on the contract defined by the extension point) by several other plugins. Both the extension point and the extension are defined in the according plugin.xml. \image html ExtensionPoints.png "Extension Point concept" \section SimpleExample Why Extension Points? In the following simple example we have a plugin 'a' and 'b' with two classes 'A' and 'B' in these plugins. \image html ExtensionPointEx.png "Simple Example" Plugin 'a' uses the extension point mechanism and creates an extension point that can be extended by other plugins. Now if class 'A' reaches a part that can be extended it asks 'a' if another plugin is registered. If that's the case the functionality of the plugin 'b' that is defined in class 'B' is executed. A plugin can therefore be arbitrary extended. -\section Examples Examples +\section BlueBerryExampleExtensionPoint_Examples Examples The two following example plugins describe the usage of the BlueBerry Extension Points. One example defines an extension point and the other example extends the created extension point. \li \ref org_mitk_example_gui_extensionpointdefinition \li \ref org_mitk_example_gui_extensionpointcontribution [\ref BlueBerryExampleExtensionPoint] [Next: \ref ExtensionPointDefinition] [\ref BlueBerryExamples] */ diff --git a/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerrySelectionServiceIntro.dox b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerrySelectionServiceIntro.dox index 860c7cc20d..570521ea87 100644 --- a/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerrySelectionServiceIntro.dox +++ b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerrySelectionServiceIntro.dox @@ -1,40 +1,40 @@ /** \page BlueBerrySelectionServiceIntro Selection Service -# \subpage IntroductionSelectionService "Introduction" -# \subpage BlueBerryExampleSelectionServiceQt -# \subpage BlueBerryExampleSelectionServiceMitk \page IntroductionSelectionService Introduction: Selection Service Concept The selection service provided by the BlueBerry workbench allows efficient linking of different parts within the workbench window: View parts that provide additional information for particular objects and update their content automatically whenever such objects are selected somewhere in the workbench window. For example the "Properties" view in MITK applications behaves in this way: Wherever an element is selected in the workbench this view lists the properties of that element. \image html MitkSelectionService.png "DataNode properties" Other aspects of the workbench like the enablement of global actions may also depend on the current selection. Each workbench window has its own selection service instance. The service keeps track of the selection in the currently active part and propagates selection changes to all registered listeners. Such selection events occur when the selection in the current part is changed or when a different part is activated. Both can be triggered by user interaction or programmatically. \image html SelectionServiceDiagram.png "Selection Service Diagram" -\section WhatCanBeSelected What can be selected? +\section BlueBerrySelectionServiceIntro_WhatCanBeSelected What can be selected? From the users point of view a selection is a set of highlighted entries in a viewer like a table or tree widget. A selection can also be a piece of text in an editor. Internally a selection is a data structure holding the model objects which corresponds to the graphical elements selected in the workbench. As pointed out before there are two fundamental different kinds of selections: \li A list of objects \li A piece of text -\section Examples +\section BlueBerrySelectionServiceIntro_Examples The following two examples describe different ways of implementing and using the provided selection services. One example is based on the Qt selection model, the other one is based on the MITK Data node selection. \li \ref org_mitk_example_gui_selectionservicemitk \li \ref org_mitk_example_gui_selectionserviceqt Knowing and using the existing selection mechanisms gives your plug-ins a clean design, smoothly integrates them into the workbench and opens them for future extensions. [\ref BlueBerrySelectionServiceIntro] [Next: \ref BlueBerryExampleSelectionServiceQt] [\ref BlueBerryExamples] */ diff --git a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox index 6ba5548bb1..2818b1b095 100644 --- a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox @@ -1,438 +1,438 @@ /** \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/Interactions. A mitk::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 mitk::DataInteractor works on a mitk::DataNode in which it stores and manipulates data. To use a mitk::DataInteractor these parts have to be brought together. This code demonstrates the use of an existing mitk::DataInteractor exemplary for the mitk::PointSetDataInteractor: First we need a mitk::DataNode that is added to the mitk::DataStorage. \code mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); GetDataStorage()->Add(dataNode.GetPointer()); \endcode Then we create an instance of a mitk::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->SetEventConfig("PointSetConfig.xml"); \endcode Lastly the mitk::DataNode is added to the mitk::DataInteractor \code m_CurrentInteractor->SetDataNode(dataNode); \endcode now the mitk::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 exemplary implementation of a mitk::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 omitted it is set to its default value. All possible parameters are listed and described below. Event parameters are also described in the documentation of the event class itself. 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::InteractionEvent::MouseButtons represent the buttons. They can be used for two attributes. First the EventButton attribute which describes the button that triggered the event, this always 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 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, 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 mitkInteractionEvent.h \skipline // Special Keys \until // End special keys Modifier Keys \n mitk::InteractionEvent::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 +See \ref DataInteractionTechnicalPage_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 modeling 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="{InteractionPositionEvent}"]; b [ label="{MousePressEvent}" ]; c [ label="MouseReleaseEvent" ]; d [ label="TouchEvent", style=dotted ]; a -> b; a -> c; a -> d; } \enddot in the state machine pattern the mitk::InteractionPositionEvent 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 events of the classes mitk::InteractionPositionEvent itself, or mitk::MousePressEvent, mitk::MouseReleaseEvent, mitk::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 hierarchy (this ensures they hold the necessary properties). \code \endcode \subsection ActionSection Actions Actions can be added to transitions and represent functions in the mitk::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 mitk::DataInteractor which function to execute these actions are made known to the mitk::DataInteractor using the CONNECT_FUNCTION macro. This example assumes that there exists an ExampleInteractor which inherits from mitkDataInteractor. 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 ReferenceToIncludeFiles Integration of the pattern and configuration files See \ref IncludeFiles for a description. \section HowToDataInteractor Implementation of a new mitk::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 mitk::DataInteractor. This step assumes knowledge 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 is mitk::InternalEvent which allows the mitk::DataInteractor to send signals on its own. The following will describe how to build a mitk::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 mitk::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 described 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 mitk::DataInteractor (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::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 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 mitk::DataInteractor and a mitk::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]" */ diff --git a/Modules/Segmentation/DataManagement/mitkContourModel.h b/Modules/Segmentation/DataManagement/mitkContourModel.h index f5c04594bb..2530d1cef7 100644 --- a/Modules/Segmentation/DataManagement/mitkContourModel.h +++ b/Modules/Segmentation/DataManagement/mitkContourModel.h @@ -1,397 +1,397 @@ /*=================================================================== 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 _MITK_CONTOURMODEL_H_ #define _MITK_CONTOURMODEL_H_ #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkBaseData.h" #include namespace mitk { /** \brief ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are stored in a mitk::ContourElement is stored for each timestep. The contour line segments are implicitly defined by the given linked vertices. By default two control points are are linked by a straight line.It is possible to add vertices at front and end of the contour and to iterate in both directions. Points are specified containing coordinates and additional (data) information, see mitk::ContourElement. For accessing a specific vertex either an index or a position in 3D Space can be used. The vertices are best accessed by using a VertexIterator. Interaction with the contour is thus available without any mitk interactor class using the api of ContourModel. It is possible to shift single vertices also as shifting the whole contour. A contour can be either open like a single curved line segment or closed. A closed contour can for example represent a jordan curve. - \section mitkPointSetDisplayOptions + \section mitkContourModelDisplayOptions Display Options The default mappers for this data structure are mitk::ContourModelGLMapper2D and mitk::ContourModelMapper3D. See these classes for display options which can can be set via properties. */ class Segmentation_EXPORT ContourModel : public BaseData { public: mitkClassMacro(ContourModel, BaseData); itkNewMacro(Self); mitkCloneMacro(Self); /*+++++++++++++++ typedefs +++++++++++++++++++++++++++++++*/ typedef mitk::ContourElement::VertexType VertexType; typedef mitk::ContourElement::VertexListType VertexListType; typedef mitk::ContourElement::VertexIterator VertexIterator; typedef std::vector< mitk::ContourElement::Pointer > ContourModelSeries; /*+++++++++++++++ END typedefs ++++++++++++++++++++++++++++*/ /** \brief Possible interpolation of the line segments between control points */ enum LineSegmentInterpolation{ LINEAR, B_SPLINE }; /*++++++++++++++++ inline methods +++++++++++++++++++++++*/ /** \brief Get the current selected vertex. */ VertexType* GetSelectedVertex() { return this->m_SelectedVertex; } /** \brief Deselect vertex. */ void Deselect() { this->m_SelectedVertex = NULL; } /** \brief Deselect vertex. */ void SetSelectedVertexAsControlPoint(bool isControlPoint=true) { if(this->m_SelectedVertex && (this->m_SelectedVertex->IsControlPoint != isControlPoint) ) { m_SelectedVertex->IsControlPoint = isControlPoint; this->Modified(); } } /** \brief Set the interpolation of the line segments between control points. */ void SetLineSegmentInterpolation(LineSegmentInterpolation interpolation) { this->m_lineInterpolation = interpolation; this->Modified(); } /** \brief Get the interpolation of the line segments between control points. */ LineSegmentInterpolation GetLineSegmentInterpolation() { return this->m_lineInterpolation; } /*++++++++++++++++ END inline methods +++++++++++++++++++++++*/ /** \brief Add a vertex to the contour at given timestep. The vertex is added at the end of contour. \pararm vertex - coordinate representation of a control point \pararm timestep - the timestep at which the vertex will be add ( default 0) @Note Adding a vertex to a timestep which exceeds the timebounds of the contour will not be added, the TimeSlicedGeometry will not be expanded. */ void AddVertex(mitk::Point3D &vertex, int timestep=0); /** \brief Add a vertex to the contour at given timestep. The vertex is added at the end of contour. \param vertex - coordinate representation of a control point \param timestep - the timestep at which the vertex will be add ( default 0) @Note Adding a vertex to a timestep which exceeds the timebounds of the contour will not be added, the TimeSlicedGeometry will not be expanded. */ void AddVertex(VertexType &vertex, int timestep=0); /** \brief Add a vertex to the contour. \pararm vertex - coordinate representation of a control point \pararm timestep - the timestep at which the vertex will be add ( default 0) \pararm isControlPoint - specifies the vertex to be handled in a special way (e.g. control points will be rendered). @Note Adding a vertex to a timestep which exceeds the timebounds of the contour will not be added, the TimeSlicedGeometry will not be expanded. */ void AddVertex(mitk::Point3D &vertex, bool isControlPoint, int timestep=0); /** \brief Add a vertex to the contour at given timestep AT THE FRONT of the contour. The vertex is added at the FRONT of contour. \pararm vertex - coordinate representation of a control point \pararm timestep - the timestep at which the vertex will be add ( default 0) @Note Adding a vertex to a timestep which exceeds the timebounds of the contour will not be added, the TimeSlicedGeometry will not be expanded. */ void AddVertexAtFront(mitk::Point3D &vertex, int timestep=0); /** \brief Add a vertex to the contour at given timestep AT THE FRONT of the contour. The vertex is added at the FRONT of contour. \pararm vertex - coordinate representation of a control point \pararm timestep - the timestep at which the vertex will be add ( default 0) @Note Adding a vertex to a timestep which exceeds the timebounds of the contour will not be added, the TimeSlicedGeometry will not be expanded. */ void AddVertexAtFront(VertexType &vertex, int timestep=0); /** \brief Add a vertex to the contour at given timestep AT THE FRONT of the contour. \pararm vertex - coordinate representation of a control point \pararm timestep - the timestep at which the vertex will be add ( default 0) \pararm isControlPoint - specifies the vertex to be handled in a special way (e.g. control points will be rendered). @Note Adding a vertex to a timestep which exceeds the timebounds of the contour will not be added, the TimeSlicedGeometry will not be expanded. */ void AddVertexAtFront(mitk::Point3D &vertex, bool isControlPoint, int timestep=0); /** \brief Insert a vertex at given index. */ void InsertVertexAtIndex(mitk::Point3D &vertex, int index, bool isControlPoint=false, int timestep=0); /** \brief Return if the contour is closed or not. */ bool IsClosed( int timestep=0); /** \brief Concatenate two contours. The starting control point of the other will be added at the end of the contour. */ void Concatenate(mitk::ContourModel* other, int timestep=0); /** \brief Returns a const VertexIterator at the start element of the contour. @throw mitk::Exception if the timestep is invalid. */ VertexIterator IteratorBegin( int timestep=0); /** \brief Close the contour. The last control point will be linked with the first point. */ virtual void Close( int timestep=0); /** \brief Set isClosed to false contour. The link between the last control point the first point will be removed. */ virtual void Open( int timestep=0); /** \brief Set isClosed to given boolean. false - The link between the last control point the first point will be removed. true - The last control point will be linked with the first point. */ virtual void SetIsClosed(bool isClosed, int timestep=0); /** \brief Returns a const VertexIterator at the end element of the contour. @throw mitk::Exception if the timestep is invalid. */ VertexIterator IteratorEnd( int timestep=0); /** \brief Returns the number of vertices at a given timestep. \pararm timestep - default = 0 */ int GetNumberOfVertices( int timestep=0); /** \brief Returns the vertex at the index position within the container. */ virtual const VertexType* GetVertexAt(int index, int timestep=0) const; /** \brief Check if there isn't something at this timestep. */ virtual bool IsEmptyTimeStep( int t) const; /** \brief Mark a vertex at an index in the container as selected. */ bool SelectVertexAt(int index, int timestep=0); /** \brief Mark a vertex at a given position in 3D space. \pararm point - query point in 3D space \pararm eps - radius for nearest neighbour search (error bound). \pararm timestep - search at this timestep @return true = vertex found; false = no vertex found */ bool SelectVertexAt(mitk::Point3D &point, float eps, int timestep=0); /** \brief Remove a vertex at given index within the container. @return true = the vertex was successfuly removed; false = wrong index. */ bool RemoveVertexAt(int index, int timestep=0); /** \brief Remove a vertex at given timestep within the container. @return true = the vertex was successfuly removed. */ bool RemoveVertex(VertexType* vertex, int timestep=0); /** \brief Remove a vertex at a query position in 3D space. The vertex to be removed will be search by nearest neighbour search. Note that possibly no vertex at this position and eps is stored inside the contour. @return true = the vertex was successfuly removed; false = no vertex found. */ bool RemoveVertexAt(mitk::Point3D &point, float eps, int timestep=0); /** \brief Shift the currently selected vertex by a translation vector. \pararm translate - the translation vector. */ void ShiftSelectedVertex(mitk::Vector3D &translate); /** \brief Shift the whole contour by a translation vector at given timestep. \pararm translate - the translation vector. \pararm timestep - at this timestep the contour will be shifted. */ void ShiftContour(mitk::Vector3D &translate, int timestep=0); /** \brief Clear the storage container at given timestep. All control points are removed at timestep. */ virtual void Clear(int timestep); /*++++++++++++++++++ method inherit from base data +++++++++++++++++++++++++++*/ /** \brief Inherit from base data - no region support available for contourModel objects. */ virtual void SetRequestedRegionToLargestPossibleRegion (); /** \brief Inherit from base data - no region support available for contourModel objects. */ virtual bool RequestedRegionIsOutsideOfTheBufferedRegion (); /** \brief Inherit from base data - no region support available for contourModel objects. */ virtual bool VerifyRequestedRegion (); /** \brief Get the updated geometry with recomputed bounds. */ virtual const mitk::Geometry3D* GetUpdatedGeometry (int t=0); /** \brief Get the Geometry3D for timestep t. */ virtual mitk::Geometry3D* GetGeometry (int t=0) const; /** \brief Inherit from base data - no region support available for contourModel objects. */ virtual void SetRequestedRegion( const itk::DataObject *data); /** \brief Expand the timebounds of the TimeSlicedGeometry to given number of timesteps. */ virtual void Expand( int timeSteps ); /** \brief Update the OutputInformation of a ContourModel object The BoundingBox of the contour will be updated, if necessary. */ virtual void UpdateOutputInformation(); /** \brief Clear the storage container. The object is set to initial state. All control points are removed and the number of timesteps are set to 1. */ virtual void Clear(); /** \brief overwrite if the Data can be called by an Interactor (StateMachine). */ void ExecuteOperation(Operation* operation); protected: ContourModel(); ContourModel(const mitk::ContourModel &other); virtual ~ContourModel(); //inherit from BaseData. called by Clear() virtual void ClearData(); //inherit from BaseData. Initial state of a contour with no vertices and a single timestep. virtual void InitializeEmpty(); //Shift a vertex void ShiftVertex(VertexType* vertex, mitk::Vector3D &vector); //Storage with time resolved support. ContourModelSeries m_ContourSeries; //The currently selected vertex. VertexType* m_SelectedVertex; //The interpolation of the line segment between control points. LineSegmentInterpolation m_lineInterpolation; }; itkEventMacro( ContourModelEvent, itk::AnyEvent ); itkEventMacro( ContourModelShiftEvent, ContourModelEvent ); itkEventMacro( ContourModelSizeChangeEvent, ContourModelEvent ); itkEventMacro( ContourModelAddEvent, ContourModelSizeChangeEvent ); itkEventMacro( ContourModelRemoveEvent, ContourModelSizeChangeEvent ); itkEventMacro( ContourModelExpandTimeBoundsEvent, ContourModelEvent ); itkEventMacro( ContourModelClosedEvent, ContourModelEvent ); } #endif