Medical Imaging Interaction Toolkit  2018.4.99-86eb38db
Medical Imaging Interaction Toolkit
Migration Guide to new Interaction Concept

General Changes

StatemachineDefinitions

Previously the statemachine pattern along with the event description has been stored in a single file (StateMachine.xml). Now the pattern and the events are separated from each other. The statemachine pattern describes the workflow and the configuration file describes which specific event triggers an action in the workflow. Every pattern is now put into a single file (for inclusion refer to Register statemachine patterns and configuration w/o the build system ).

The pattern description has to be completely rewritten, but is pretty straight forward based on the old one, how to do this is explained here HowTo Write a State Machine . Here an example is shown for a simple state containing a transition and a parameter.

<state NAME="neutral" ID="1" START_STATE="TRUE">
<transition NAME="Shift+press" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="10" />
<intParameter NAME="DIRECTION_X" VALUE="0" />
</transition>
</state>

Example snippet (old)

<state name="neutral" startstate="true">
<transition event_class="MousePressEvent" event_variant="MouseLeftButtonPressed" target="neutral">
<action name="addPoint"/>
</transition>
</state>

Example snippet (new)

Changes:

  • ID is dropped, states are referenced now by their name
  • transition now longer have names
  • NEXT_STATE_ID becomes target
  • action ids become names, these names are used in the interactor to connect an action with a function
  • parameters are stored in the configuration file
  • EVENT_ID is replaced by event_class and event_variant (see below)

Event_class describes the class of the event (see Event Class ) - the event_variant provides a name that is used in the configuration file to give an explicit description of the event (or the globalConfig.xml is loaded as configuration file and standard values are used).

Configuration files for state machines are described here: How to create a Config-File .

Structure of an Interactor

Actions are now directly connected to functions in the DataInteractors, so the classic switch statement becomes obsolete:

bool mitk::SomeInteractor::ExecuteAction(Action* action, mitk::StateEvent const* stateEvent)
{
switch (action->GetActionId())
{
case Action1:
...
case Action2:
...
}
}

changes to

{
CONNECT_FUNCTION("stringOfActionFromXmlFile", Action1);
CONNECT_FUNCTION("stringOfActionFromXmlFile2", Action2);
...
}
void Action1(StateMachineAction* , InteractionEvent*)
{
...
}
...

where each action is implemented as a function. See Implementation of a new mitk::DataInteractor .

Guard States / Conditions

Formerly there where so called guard states, which cause a transition only if certain conditions are met. These states have been removed, as a replacement serve the InternalEvents which can be triggered from within a data interactor. An example showing how to use them is given in Example Interactor using InternalEvent .

In most cases, guard states can be eliminated by using transition conditions.

Register statemachine patterns and configuration w/o the build system

There are different ways to load a statemachine pattern or configuration objects from files. If you are working in a module you can use the resources to easily load patterns and configurations. To use this place your XML file in the 'Resources/Interactions' folder of the respective module, and add the file path to the corresponding files.cmake in the resource section like this:

set(RESOURCE_FILES
Interactions/dummyStatemachine.xml
)

Loading the statemachine pattern can then be done by simply calling

#include "mitkModule.h"
#include <mitkGetModuleContext.h>
Module* module = GetModuleContext()->GetModule();
mitk::PointSetDataInteractor::m_CurrentInteractor = mitk::PointSetDataInteractor::New();
m_CurrentInteractor->LoadStateMachine("dummyStatemachine.xml", module);

here module is optional, if none is provided the core module is assumed.

The third possibility is to build up a configuration by vector of mitk::PropertyLists, where each item describes an event configuration.

In the following example a configuration is build which defines two event variants using basic properties, for a full list of usable properties see mitkInteractionEventConst.h

// First event
// Setting the EventClass property to 'MousePressEvent'
propertyList1->SetStringProperty(mitk::InteractionEventConst::xmlParameterEventClass.c_str(), "MousePressEvent");
// Setting the Event variant value to 'MousePressEventVariantÄ
propertyList1->SetStringProperty(mitk::InteractionEventConst::xmlParameterEventVariant.c_str(), "MousePressEventVariant");
// set control and alt buttons as modifiers
propertyList1->SetStringProperty("Modifiers","CTRL,ALT");
// Second event
propertyList2->SetStringProperty(mitk::InteractionEventConst::xmlParameterEventClass.c_str(), "MouseReleaseEvent");
propertyList2->SetStringProperty(mitk::InteractionEventConst::xmlParameterEventVariant.c_str(), "MouseReleaseEventVariant");
propertyList2->SetStringProperty("Modifiers","SHIFT");
// putting both descriptions in a vector
std::vector<mitk::PropertyList::Pointer>* configDescription = new std::vector<mitk::PropertyList::Pointer>();
configDescription->push_back(propertyList1);
configDescription->push_back(propertyList2);
// create the config object
mitk::EventConfig newConfig(configDescription);