Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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()