Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkEventFactory.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3  The Medical Imaging Interaction Toolkit (MITK)
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics.
7  All rights reserved.
8 
9  This software is distributed WITHOUT ANY WARRANTY; without
10  even the implied warranty of MERCHANTABILITY or FITNESS FOR
11  A PARTICULAR PURPOSE.
12 
13  See LICENSE.txt or http://www.mitk.org for details.
14 
15  ===================================================================*/
16 
17 #include "mitkEventFactory.h"
18 #include <algorithm>
22 #include <mitkInternalEvent.h>
24 #include <mitkMouseMoveEvent.h>
25 #include <mitkMousePressEvent.h>
26 #include <mitkMouseReleaseEvent.h>
27 #include <mitkMouseWheelEvent.h>
28 #include <sstream>
29 #include <string>
30 
31 namespace
32 {
33  std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
34  {
35  std::stringstream ss(s);
36  std::string item;
37  while (std::getline(ss, item, delim))
38  {
39  elems.push_back(item);
40  }
41  return elems;
42  }
43 
44  std::vector<std::string> split(const std::string &s, char delim)
45  {
46  std::vector<std::string> elems;
47  return split(s, delim, elems);
48  }
49 }
50 
56 static std::string GetButtonState(mitk::InteractionEvent *event)
57 {
59  std::string eventClass = event->GetNameOfClass();
60  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
61 
62  std::string strButtonState = "";
63  if (eventClass == "MOUSEPRESSEVENT")
64  {
65  mitk::MousePressEvent *mme = dynamic_cast<mitk::MousePressEvent *>(event);
66  buttonState = mme->GetButtonStates();
67  }
68  if (eventClass == "MOUSERELEASEEVENT")
69  {
70  mitk::MouseReleaseEvent *mme = dynamic_cast<mitk::MouseReleaseEvent *>(event);
71  buttonState = mme->GetButtonStates();
72  }
73  if (eventClass == "MOUSEDOUBLECLICKEVENT")
74  {
75  mitk::MouseDoubleClickEvent *mme = dynamic_cast<mitk::MouseDoubleClickEvent *>(event);
76  buttonState = mme->GetButtonStates();
77  }
78  if (eventClass == "MOUSEMOVEEVENT")
79  {
80  mitk::MouseMoveEvent *mme = dynamic_cast<mitk::MouseMoveEvent *>(event);
81  buttonState = mme->GetButtonStates();
82  }
83  if (eventClass == "MOUSEWHEELEVENT")
84  {
85  mitk::MouseWheelEvent *mme = dynamic_cast<mitk::MouseWheelEvent *>(event);
86  buttonState = mme->GetButtonStates();
87  }
88 
90  {
91  strButtonState = "LeftMouseButton";
92  }
94  {
95  if (strButtonState != "")
96  strButtonState += ",";
97 
98  strButtonState += "RightMouseButton";
99  }
101  {
102  if (strButtonState != "")
103  strButtonState += ",";
104 
105  strButtonState += "MiddleMouseButton";
106  }
107  return strButtonState;
108 }
109 
115 static std::string GetModifierState(mitk::InteractionEvent *event)
116 {
118  std::string eventClass = event->GetNameOfClass();
119  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
120  std::string strModKeys = "";
121  // TODO Add InteractionKey
122  if (eventClass == "MOUSEPRESSEVENT")
123  {
124  mitk::MousePressEvent *mme = dynamic_cast<mitk::MousePressEvent *>(event);
125  modifierKeys = mme->GetModifiers();
126  }
127  if (eventClass == "MOUSERELEASEEVENT")
128  {
129  mitk::MouseReleaseEvent *mme = dynamic_cast<mitk::MouseReleaseEvent *>(event);
130  modifierKeys = mme->GetModifiers();
131  }
132  if (eventClass == "MOUSEDOUBLECLICKEVENT")
133  {
134  mitk::MouseDoubleClickEvent *mme = dynamic_cast<mitk::MouseDoubleClickEvent *>(event);
135  modifierKeys = mme->GetModifiers();
136  }
137  if (eventClass == "MOUSEMOVEEVENT")
138  {
139  mitk::MouseMoveEvent *mme = dynamic_cast<mitk::MouseMoveEvent *>(event);
140  modifierKeys = mme->GetModifiers();
141  }
142  if (eventClass == "MOUSEWHEELEVENT")
143  {
144  mitk::MouseWheelEvent *mme = dynamic_cast<mitk::MouseWheelEvent *>(event);
145  modifierKeys = mme->GetModifiers();
146  }
147 
148  if (modifierKeys & mitk::InteractionEvent::ShiftKey)
149  {
150  strModKeys = "SHIFT";
151  }
152  if (modifierKeys & mitk::InteractionEvent::ControlKey)
153  {
154  if (strModKeys != "")
155  strModKeys += ",";
156 
157  strModKeys += "CTRL";
158  }
159  if (modifierKeys & mitk::InteractionEvent::AltKey)
160  {
161  if (strModKeys != "")
162  strModKeys += ",";
163 
164  strModKeys += "ALT";
165  }
166  return strModKeys;
167 }
168 
174 static std::string GetEventButton(mitk::InteractionEvent *event)
175 {
177  std::string eventClass = event->GetNameOfClass();
178  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
179  std::string stdButton = "";
180  // TODO Add InteractionKey
181  if (eventClass == "MOUSEPRESSEVENT")
182  {
183  mitk::MousePressEvent *mme = dynamic_cast<mitk::MousePressEvent *>(event);
184  button = mme->GetEventButton();
185  }
186  if (eventClass == "MOUSERELEASEEVENT")
187  {
188  mitk::MouseReleaseEvent *mme = dynamic_cast<mitk::MouseReleaseEvent *>(event);
189  button = mme->GetEventButton();
190  }
191  if (eventClass == "MOUSEDOUBLECLICKEVENT")
192  {
193  mitk::MouseDoubleClickEvent *mme = dynamic_cast<mitk::MouseDoubleClickEvent *>(event);
194  button = mme->GetEventButton();
195  }
196 
198  {
199  stdButton = "LeftMouseButton";
200  }
202  {
203  stdButton = "RightMouseButton";
204  }
206  {
207  stdButton = "MiddleMouseButton";
208  }
209  return stdButton;
210 }
211 
217 static std::string GetPositionInWorld(mitk::InteractionEvent *event)
218 {
219  std::stringstream ss;
221  if (pe != NULL)
222  {
224  ss << p[0] << "," << p[1] << "," << p[2];
225  }
226  return ss.str();
227 }
228 
234 static std::string GetPositionOnScreen(mitk::InteractionEvent *event)
235 {
236  std::stringstream ss;
238  if (pe != NULL)
239  {
241  ss << p[0] << "," << p[1];
242  }
243  return ss.str();
244 }
245 
247 {
248  //
249  std::string eventClass, eventVariant;
250  list->GetStringProperty(InteractionEventConst::xmlParameterEventClass().c_str(), eventClass);
251  list->GetStringProperty(InteractionEventConst::xmlParameterEventVariant().c_str(), eventVariant);
252 
253  // Query all possible attributes, if they are not present, set their default values.
254  // Position Events & Key Events
255  std::string strModifiers;
257  std::string strEventButton;
259  std::string strButtonState;
261  std::string strKey;
262  std::string key;
263  std::string strWheelDelta;
264  int wheelDelta;
265  std::string strSignalName = "";
266 
267  Point2D pos;
268  pos.Fill(0);
269  std::string strPos;
270 
271  // Position on screen
272  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyPositionOnScreen().c_str(), strPos))
273  {
274  // split comma separated string
275  int commaPos;
276  commaPos = strPos.find_first_of(',');
277 
278  pos[0] = static_cast<mitk::ScalarType>(std::atof(strPos.substr(0, commaPos).c_str()));
279  pos[1] = static_cast<mitk::ScalarType>(std::atof(strPos.substr(commaPos + 1, strPos.length()).c_str()));
280  }
281 
282  std::string strWorld;
283  Point3D worldPos;
284  worldPos.Fill(0);
285  // Position in world coordinates
286  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyPositionInWorld().c_str(), strWorld))
287  {
288  const std::vector<std::string> coords = split(strWorld, ',');
289  int i = 0;
290  for (std::vector<std::string>::const_iterator it = coords.cbegin(); it != coords.cend(); ++it, ++i)
291  {
292  worldPos[i] = atof((*it).c_str());
293  }
294  }
295 
296  // Parse modifier information
297  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyModifier().c_str(), strModifiers))
298  {
299  std::vector<std::string> mods = split(strModifiers, ',');
300  for (std::vector<std::string>::iterator it = mods.begin(); it != mods.end(); ++it)
301  {
302  std::transform((*it).cbegin(), (*it).cend(), (*it).begin(), ::toupper);
303  if (*it == "CTRL")
304  {
305  modifiers = modifiers | InteractionEvent::ControlKey;
306  }
307  else if (*it == "ALT")
308  {
309  modifiers = modifiers | InteractionEvent::AltKey;
310  }
311  else if (*it == "SHIFT")
312  {
313  modifiers = modifiers | InteractionEvent::ShiftKey;
314  }
315  else
316  {
317  MITK_WARN << "mitkEventFactory: Invalid event modifier in config file :" << (*it);
318  }
319  }
320  }
321 
322  // Set EventButton
323  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyEventButton().c_str(), strEventButton))
324  {
325  std::transform(strEventButton.cbegin(), strEventButton.cend(), strEventButton.begin(), ::toupper);
326  if (strEventButton == "MIDDLEMOUSEBUTTON")
327  {
329  }
330  else if (strEventButton == "LEFTMOUSEBUTTON")
331  {
332  eventButton = InteractionEvent::LeftMouseButton;
333  }
334  else if (strEventButton == "RIGHTMOUSEBUTTON")
335  {
337  }
338  else
339  {
340  MITK_WARN << "mitkEventFactory: Invalid event button in config file: " << strEventButton;
341  }
342  }
343 
344  // Parse ButtonStates
345  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyButtonState().c_str(), strButtonState))
346  {
347  std::vector<std::string> mods = split(strButtonState, ',');
348  for (std::vector<std::string>::iterator it = mods.begin(); it != mods.end(); ++it)
349  {
350  std::transform((*it).cbegin(), (*it).cend(), (*it).begin(), ::toupper);
351  if (*it == "MIDDLEMOUSEBUTTON")
352  {
353  buttonState = buttonState | InteractionEvent::MiddleMouseButton;
354  }
355  else if (*it == "LEFTMOUSEBUTTON")
356  {
357  buttonState = buttonState | InteractionEvent::LeftMouseButton;
358  }
359  else if (*it == "RIGHTMOUSEBUTTON")
360  {
361  buttonState = buttonState | InteractionEvent::RightMouseButton;
362  }
363  else
364  {
365  MITK_WARN << "mitkEventFactory: Invalid event buttonstate in config file:" << (*it);
366  }
367  }
368  }
369 
370  // Key
371  if (!list->GetStringProperty(InteractionEventConst::xmlEventPropertyKey().c_str(), strKey))
372  {
373  key = "";
374  }
375  else
376  {
377  key = strKey;
378  }
379  // WheelDelta
380  if (!list->GetStringProperty(InteractionEventConst::xmlEventPropertyScrollDirection().c_str(), strWheelDelta))
381  {
382  wheelDelta = 0;
383  }
384  else
385  {
386  std::transform(strWheelDelta.cbegin(), strWheelDelta.cend(), strWheelDelta.begin(), ::toupper);
387  if (strWheelDelta == "DOWN")
388  {
389  wheelDelta = -1;
390  }
391  else
392  {
393  wheelDelta = 1;
394  }
395  }
396  // Internal Signals Name
397  list->GetStringProperty(InteractionEventConst::xmlEventPropertySignalName().c_str(), strSignalName);
398 
399  // Get BaseRenderer by name
400  mitk::BaseRenderer *renderer = NULL;
401  std::string strRenderer;
402 
403  // only search for a renderer if there is at least one renderer registered
405  {
406  if (list->GetStringProperty(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str(), strRenderer))
407  {
408  // look up for renderer registered with the name in xml file
409  renderer = mitk::BaseRenderer::GetByName(strRenderer);
410  }
411 
412  // if not found always use first registered renderer
413  if (renderer == NULL)
414  renderer = (*(mitk::BaseRenderer::baseRendererMap.cbegin())).second;
415  }
416 
417  /*
418  * Here the objects are created
419  */
420 
422  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
423 
424  if (eventClass == "MOUSEPRESSEVENT")
425  {
426  // buttonstates incorporate the event button (as in Qt)
427  buttonState = buttonState | eventButton;
428  event = MousePressEvent::New(renderer, pos, buttonState, modifiers, eventButton);
429  }
430  else if (eventClass == "MOUSEDOUBLECLICKEVENT")
431  {
432  buttonState = buttonState | eventButton;
433  event = MouseDoubleClickEvent::New(renderer, pos, buttonState, modifiers, eventButton);
434  }
435  else if (eventClass == "MOUSEMOVEEVENT")
436  {
437  event = MouseMoveEvent::New(renderer, pos, buttonState, modifiers);
438  }
439  else if (eventClass == "MOUSERELEASEEVENT")
440  {
441  event = MouseReleaseEvent::New(renderer, pos, buttonState, modifiers, eventButton);
442  }
443  else if (eventClass == "INTERACTIONKEYEVENT")
444  {
445  event = InteractionKeyEvent::New(renderer, key, modifiers);
446  }
447  else if (eventClass == "MOUSEWHEELEVENT")
448  {
449  event = MouseWheelEvent::New(renderer, pos, buttonState, modifiers, wheelDelta);
450  }
451  else if (eventClass == "INTERACTIONPOSITIONEVENT")
452  {
453  event = InteractionPositionEvent::New(renderer, pos);
454  }
455  else if (eventClass == "INTERNALEVENT")
456  {
457  event = InternalEvent::New(renderer, NULL, strSignalName);
458  }
459  else if (eventClass == "INTERACTIONEVENT")
460  {
461  event = InteractionEvent::New(renderer);
462  }
463  if (event.IsNull())
464  {
465  MITK_WARN << "Event couldn't be constructed. Please check your StateMachine patterns and config files\n for the "
466  "following event class, which is not valid: "
467  << eventClass;
468  return NULL;
469  }
470  return event;
471 }
472 
474 {
475  InternalEvent *ie = dynamic_cast<InternalEvent *>(event);
476  if (ie != NULL)
477  return "";
478 
479  std::string eventClass = event->GetNameOfClass();
480  std::string eventXML =
482 
483  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
484 
485  eventXML += eventClass + "\" >\n";
486  // here follow event specific attributes
487  if (eventClass == "MOUSEPRESSEVENT" || eventClass == "MOUSERELEASEEVENT" || eventClass == "MOUSEDOUBLECLICKEVENT" ||
488  eventClass == "MOUSEMOVEEVENT" || eventClass == "MOUSEWHEELEVENT")
489  {
490  if (!(eventClass == "MOUSEMOVEEVENT") && !(eventClass == "MOUSEWHEELEVENT"))
491  {
492  // EventButton
495  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
496  eventXML += GetEventButton(event);
497  eventXML += "\"/>\n";
498  }
499  // ButtonState
500  if (GetButtonState(event) != "")
501  {
504  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
505  eventXML += GetButtonState(event);
506  eventXML += "\"/>\n";
507  }
508 
509  // Modifiers
510  if (GetModifierState(event) != "")
511  {
514  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
515  eventXML += GetModifierState(event);
516  eventXML += "\"/>\n";
517  }
518 
519  // Position on Screen
522  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
523  eventXML += GetPositionOnScreen(event);
524  eventXML += "\"/>\n";
525 
526  // Position in World
529  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
530  eventXML += GetPositionInWorld(event);
531  eventXML += "\"/>\n";
532  }
533  else if (eventClass == "INTERACTIONKEYEVENT")
534  {
535  mitk::InteractionKeyEvent *ke = dynamic_cast<mitk::InteractionKeyEvent *>(event);
536 
537  // key
540  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
541  eventXML += ke->GetKey();
542  eventXML += "\"/>\n";
543  }
544  else
545  {
546  MITK_WARN << "Event not recognized, discarding event of type " << event->GetNameOfClass();
547  }
548  if (eventClass == "MOUSEWHEELEVENT")
549  {
550  MouseWheelEvent *we = dynamic_cast<MouseWheelEvent *>(event);
551  int delta = we->GetWheelDelta();
552 
553  std::stringstream ss;
554  ss << delta;
555 
558  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
559  eventXML += ss.str();
560  eventXML += "\"/>\n";
561 
564  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
565  eventXML += delta < 0 ? "DOWN" : "UP";
566  eventXML += "\"/>\n";
567  }
568 
569  // Renderer name
572  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
573  eventXML += event->GetSender()->GetName();
574  eventXML += "\"/>\n";
575 
576  // closing tag:
577  eventXML += "</" + InteractionEventConst::xmlTagEventVariant() + ">";
578  return eventXML;
579 }
static const std::string xmlEventPropertyPositionInWorld()
static std::string EventToXML(InteractionEvent *event)
EventToXML Transforms an event into a XML tag describing it.
static const std::string xmlEventPropertyPositionOnScreen()
static const std::string xmlParameterName()
Super class for all position events.
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, MouseButtons _arge)
static const std::string xmlEventPropertyRendererName()
static const std::string xmlParameterValue()
static const std::string xmlEventPropertyEventButton()
double ScalarType
static std::string GetPositionOnScreen(mitk::InteractionEvent *event)
GetPositionOnScreen Return PositionOnScreen as String.
ModifierKeys GetModifiers() const
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, MouseButtons _arge)
Organizes the rendering process.
static const std::string xmlEventPropertyModifier()
Class to create events from within the application to signal about internal events.
static std::string GetEventButton(mitk::InteractionEvent *event)
GetEventButton Return EventButton as String.
static Pointer New(BaseRenderer *_arga, const Point2D &_argb)
static const std::string xmlEventPropertyScrollDirection()
static const std::string xmlParameterEventClass()
static InteractionEvent::Pointer CreateEvent(PropertyList::Pointer eventDescription)
MouseButtons GetButtonStates() const
static Pointer New(BaseRenderer *_arg)
static std::string GetButtonState(mitk::InteractionEvent *event)
GetEventButton Return EventButton as String.
static const std::string xmlEventPropertyButtonState()
static const std::string xmlParameterEventVariant()
ModifierKeys GetModifiers() const
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, int _arge)
#define MITK_WARN
Definition: mitkLogMacros.h:23
static Pointer New(BaseRenderer *_arga, const std::string &_argb, ModifierKeys _argc)
static BaseRendererMapType baseRendererMap
MouseButtons GetButtonStates() const
static const std::string xmlEventPropertyWheelDelta()
MouseButtons GetButtonStates() const
static const std::string xmlEventPropertyKey()
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd)
ModifierKeys GetModifiers() const
MouseButtons GetEventButton() const
static const std::string xmlTagEventVariant()
static std::string GetModifierState(mitk::InteractionEvent *event)
GetModifierState Return ModifierState as String.
ModifierKeys GetModifiers() const
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, MouseButtons _arge)
MouseButtons GetEventButton() const
Handles key events. Takes a std::string for pressed key or special key description, mitk::ModifierKeys for modifiers
static BaseRenderer * GetByName(const std::string &name)
static const std::string xmlEventPropertySignalName()
static Pointer New(BaseRenderer *_arga, DataInteractor *_argb, const std::string &_argc)
static std::string GetPositionInWorld(mitk::InteractionEvent *event)
GetPosition Return World Position as String.
static std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
MouseButtons GetButtonStates() const
static const std::string xmlTagAttribute()