Medical Imaging Interaction Toolkit  2018.4.99-f51274ea
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkEventFactory.h"
14 #include <algorithm>
18 #include <mitkInternalEvent.h>
20 #include <mitkMouseMoveEvent.h>
21 #include <mitkMousePressEvent.h>
22 #include <mitkMouseReleaseEvent.h>
23 #include <mitkMouseWheelEvent.h>
24 #include <sstream>
25 #include <string>
26 
27 namespace
28 {
29  std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
30  {
31  std::stringstream ss(s);
32  std::string item;
33  while (std::getline(ss, item, delim))
34  {
35  elems.push_back(item);
36  }
37  return elems;
38  }
39 
40  std::vector<std::string> split(const std::string &s, char delim)
41  {
42  std::vector<std::string> elems;
43  return split(s, delim, elems);
44  }
45 }
46 
52 static std::string GetButtonState(mitk::InteractionEvent *event)
53 {
55  std::string eventClass = event->GetNameOfClass();
56  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
57 
58  std::string strButtonState = "";
59  if (eventClass == "MOUSEPRESSEVENT")
60  {
61  auto *mme = dynamic_cast<mitk::MousePressEvent *>(event);
62  buttonState = mme->GetButtonStates();
63  }
64  if (eventClass == "MOUSERELEASEEVENT")
65  {
66  auto *mme = dynamic_cast<mitk::MouseReleaseEvent *>(event);
67  buttonState = mme->GetButtonStates();
68  }
69  if (eventClass == "MOUSEDOUBLECLICKEVENT")
70  {
71  auto *mme = dynamic_cast<mitk::MouseDoubleClickEvent *>(event);
72  buttonState = mme->GetButtonStates();
73  }
74  if (eventClass == "MOUSEMOVEEVENT")
75  {
76  auto *mme = dynamic_cast<mitk::MouseMoveEvent *>(event);
77  buttonState = mme->GetButtonStates();
78  }
79  if (eventClass == "MOUSEWHEELEVENT")
80  {
81  auto *mme = dynamic_cast<mitk::MouseWheelEvent *>(event);
82  buttonState = mme->GetButtonStates();
83  }
84 
86  {
87  strButtonState = "LeftMouseButton";
88  }
90  {
91  if (strButtonState != "")
92  strButtonState += ",";
93 
94  strButtonState += "RightMouseButton";
95  }
97  {
98  if (strButtonState != "")
99  strButtonState += ",";
100 
101  strButtonState += "MiddleMouseButton";
102  }
103  return strButtonState;
104 }
105 
111 static std::string GetModifierState(mitk::InteractionEvent *event)
112 {
114  std::string eventClass = event->GetNameOfClass();
115  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
116  std::string strModKeys = "";
117  // TODO Add InteractionKey
118  if (eventClass == "MOUSEPRESSEVENT")
119  {
120  auto *mme = dynamic_cast<mitk::MousePressEvent *>(event);
121  modifierKeys = mme->GetModifiers();
122  }
123  if (eventClass == "MOUSERELEASEEVENT")
124  {
125  auto *mme = dynamic_cast<mitk::MouseReleaseEvent *>(event);
126  modifierKeys = mme->GetModifiers();
127  }
128  if (eventClass == "MOUSEDOUBLECLICKEVENT")
129  {
130  auto *mme = dynamic_cast<mitk::MouseDoubleClickEvent *>(event);
131  modifierKeys = mme->GetModifiers();
132  }
133  if (eventClass == "MOUSEMOVEEVENT")
134  {
135  auto *mme = dynamic_cast<mitk::MouseMoveEvent *>(event);
136  modifierKeys = mme->GetModifiers();
137  }
138  if (eventClass == "MOUSEWHEELEVENT")
139  {
140  auto *mme = dynamic_cast<mitk::MouseWheelEvent *>(event);
141  modifierKeys = mme->GetModifiers();
142  }
143 
144  if (modifierKeys & mitk::InteractionEvent::ShiftKey)
145  {
146  strModKeys = "SHIFT";
147  }
148  if (modifierKeys & mitk::InteractionEvent::ControlKey)
149  {
150  if (strModKeys != "")
151  strModKeys += ",";
152 
153  strModKeys += "CTRL";
154  }
155  if (modifierKeys & mitk::InteractionEvent::AltKey)
156  {
157  if (strModKeys != "")
158  strModKeys += ",";
159 
160  strModKeys += "ALT";
161  }
162  return strModKeys;
163 }
164 
170 static std::string GetEventButton(mitk::InteractionEvent *event)
171 {
173  std::string eventClass = event->GetNameOfClass();
174  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
175  std::string stdButton = "";
176  // TODO Add InteractionKey
177  if (eventClass == "MOUSEPRESSEVENT")
178  {
179  auto *mme = dynamic_cast<mitk::MousePressEvent *>(event);
180  button = mme->GetEventButton();
181  }
182  if (eventClass == "MOUSERELEASEEVENT")
183  {
184  auto *mme = dynamic_cast<mitk::MouseReleaseEvent *>(event);
185  button = mme->GetEventButton();
186  }
187  if (eventClass == "MOUSEDOUBLECLICKEVENT")
188  {
189  auto *mme = dynamic_cast<mitk::MouseDoubleClickEvent *>(event);
190  button = mme->GetEventButton();
191  }
192 
194  {
195  stdButton = "LeftMouseButton";
196  }
198  {
199  stdButton = "RightMouseButton";
200  }
202  {
203  stdButton = "MiddleMouseButton";
204  }
205  return stdButton;
206 }
207 
213 static std::string GetPositionInWorld(mitk::InteractionEvent *event)
214 {
215  std::stringstream ss;
216  auto *pe = dynamic_cast<mitk::InteractionPositionEvent *>(event);
217  if (pe != nullptr)
218  {
219  mitk::Point3D p = pe->GetPositionInWorld();
220  ss << p[0] << "," << p[1] << "," << p[2];
221  }
222  return ss.str();
223 }
224 
230 static std::string GetPositionOnScreen(mitk::InteractionEvent *event)
231 {
232  std::stringstream ss;
233  auto *pe = dynamic_cast<mitk::InteractionPositionEvent *>(event);
234  if (pe != nullptr)
235  {
236  mitk::Point2D p = pe->GetPointerPositionOnScreen();
237  ss << p[0] << "," << p[1];
238  }
239  return ss.str();
240 }
241 
243 {
244  //
245  std::string eventClass, eventVariant;
246  list->GetStringProperty(InteractionEventConst::xmlParameterEventClass().c_str(), eventClass);
247  list->GetStringProperty(InteractionEventConst::xmlParameterEventVariant().c_str(), eventVariant);
248 
249  // Query all possible attributes, if they are not present, set their default values.
250  // Position Events & Key Events
251  std::string strModifiers;
253  std::string strEventButton;
255  std::string strButtonState;
257  std::string strKey;
258  std::string key;
259  std::string strWheelDelta;
260  int wheelDelta;
261  std::string strSignalName = "";
262 
263  Point2D pos;
264  pos.Fill(0);
265  std::string strPos;
266 
267  // Position on screen
268  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyPositionOnScreen().c_str(), strPos))
269  {
270  // split comma separated string
271  int commaPos;
272  commaPos = strPos.find_first_of(',');
273 
274  pos[0] = static_cast<mitk::ScalarType>(std::atof(strPos.substr(0, commaPos).c_str()));
275  pos[1] = static_cast<mitk::ScalarType>(std::atof(strPos.substr(commaPos + 1, strPos.length()).c_str()));
276  }
277 
278  std::string strWorld;
279  Point3D worldPos;
280  worldPos.Fill(0);
281  // Position in world coordinates
282  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyPositionInWorld().c_str(), strWorld))
283  {
284  const std::vector<std::string> coords = split(strWorld, ',');
285  int i = 0;
286  for (auto it = coords.cbegin(); it != coords.cend(); ++it, ++i)
287  {
288  worldPos[i] = atof((*it).c_str());
289  }
290  }
291 
292  // Parse modifier information
293  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyModifier().c_str(), strModifiers))
294  {
295  std::vector<std::string> mods = split(strModifiers, ',');
296  for (auto it = mods.begin(); it != mods.end(); ++it)
297  {
298  std::transform((*it).cbegin(), (*it).cend(), (*it).begin(), ::toupper);
299  if (*it == "CTRL")
300  {
301  modifiers = modifiers | InteractionEvent::ControlKey;
302  }
303  else if (*it == "ALT")
304  {
305  modifiers = modifiers | InteractionEvent::AltKey;
306  }
307  else if (*it == "SHIFT")
308  {
309  modifiers = modifiers | InteractionEvent::ShiftKey;
310  }
311  else
312  {
313  MITK_WARN << "mitkEventFactory: Invalid event modifier in config file :" << (*it);
314  }
315  }
316  }
317 
318  // Set EventButton
319  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyEventButton().c_str(), strEventButton))
320  {
321  std::transform(strEventButton.cbegin(), strEventButton.cend(), strEventButton.begin(), ::toupper);
322  if (strEventButton == "MIDDLEMOUSEBUTTON")
323  {
325  }
326  else if (strEventButton == "LEFTMOUSEBUTTON")
327  {
328  eventButton = InteractionEvent::LeftMouseButton;
329  }
330  else if (strEventButton == "RIGHTMOUSEBUTTON")
331  {
333  }
334  else
335  {
336  MITK_WARN << "mitkEventFactory: Invalid event button in config file: " << strEventButton;
337  }
338  }
339 
340  // Parse ButtonStates
341  if (list->GetStringProperty(InteractionEventConst::xmlEventPropertyButtonState().c_str(), strButtonState))
342  {
343  std::vector<std::string> mods = split(strButtonState, ',');
344  for (auto it = mods.begin(); it != mods.end(); ++it)
345  {
346  std::transform((*it).cbegin(), (*it).cend(), (*it).begin(), ::toupper);
347  if (*it == "MIDDLEMOUSEBUTTON")
348  {
349  buttonState = buttonState | InteractionEvent::MiddleMouseButton;
350  }
351  else if (*it == "LEFTMOUSEBUTTON")
352  {
353  buttonState = buttonState | InteractionEvent::LeftMouseButton;
354  }
355  else if (*it == "RIGHTMOUSEBUTTON")
356  {
357  buttonState = buttonState | InteractionEvent::RightMouseButton;
358  }
359  else
360  {
361  MITK_WARN << "mitkEventFactory: Invalid event buttonstate in config file:" << (*it);
362  }
363  }
364  }
365 
366  // Key
367  if (!list->GetStringProperty(InteractionEventConst::xmlEventPropertyKey().c_str(), strKey))
368  {
369  key = "";
370  }
371  else
372  {
373  key = strKey;
374  }
375  // WheelDelta
376  if (!list->GetStringProperty(InteractionEventConst::xmlEventPropertyScrollDirection().c_str(), strWheelDelta))
377  {
378  wheelDelta = 0;
379  }
380  else
381  {
382  std::transform(strWheelDelta.cbegin(), strWheelDelta.cend(), strWheelDelta.begin(), ::toupper);
383  if (strWheelDelta == "DOWN")
384  {
385  wheelDelta = -1;
386  }
387  else
388  {
389  wheelDelta = 1;
390  }
391  }
392  // Internal Signals Name
393  list->GetStringProperty(InteractionEventConst::xmlEventPropertySignalName().c_str(), strSignalName);
394 
395  // Get BaseRenderer by name
396  mitk::BaseRenderer *renderer = nullptr;
397  std::string strRenderer;
398 
399  // only search for a renderer if there is at least one renderer registered
401  {
402  if (list->GetStringProperty(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str(), strRenderer))
403  {
404  // look up for renderer registered with the name in xml file
405  renderer = mitk::BaseRenderer::GetByName(strRenderer);
406  }
407 
408  // if not found always use first registered renderer
409  if (renderer == nullptr)
410  renderer = (*(mitk::BaseRenderer::baseRendererMap.cbegin())).second;
411  }
412 
413  /*
414  * Here the objects are created
415  */
416 
418  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
419 
420  if (eventClass == "MOUSEPRESSEVENT")
421  {
422  // buttonstates incorporate the event button (as in Qt)
423  buttonState = buttonState | eventButton;
424  event = MousePressEvent::New(renderer, pos, buttonState, modifiers, eventButton);
425  }
426  else if (eventClass == "MOUSEDOUBLECLICKEVENT")
427  {
428  buttonState = buttonState | eventButton;
429  event = MouseDoubleClickEvent::New(renderer, pos, buttonState, modifiers, eventButton);
430  }
431  else if (eventClass == "MOUSEMOVEEVENT")
432  {
433  event = MouseMoveEvent::New(renderer, pos, buttonState, modifiers);
434  }
435  else if (eventClass == "MOUSERELEASEEVENT")
436  {
437  event = MouseReleaseEvent::New(renderer, pos, buttonState, modifiers, eventButton);
438  }
439  else if (eventClass == "INTERACTIONKEYEVENT")
440  {
441  event = InteractionKeyEvent::New(renderer, key, modifiers);
442  }
443  else if (eventClass == "MOUSEWHEELEVENT")
444  {
445  event = MouseWheelEvent::New(renderer, pos, buttonState, modifiers, wheelDelta);
446  }
447  else if (eventClass == "INTERACTIONPOSITIONEVENT")
448  {
449  event = InteractionPositionEvent::New(renderer, pos);
450  }
451  else if (eventClass == "INTERNALEVENT")
452  {
453  event = InternalEvent::New(renderer, nullptr, strSignalName);
454  }
455  else if (eventClass == "INTERACTIONEVENT")
456  {
457  event = InteractionEvent::New(renderer);
458  }
459  if (event.IsNull())
460  {
461  MITK_WARN << "Event couldn't be constructed. Please check your StateMachine patterns and config files\n for the "
462  "following event class, which is not valid: "
463  << eventClass;
464  return nullptr;
465  }
466  return event;
467 }
468 
470 {
471  auto *ie = dynamic_cast<InternalEvent *>(event);
472  if (ie != nullptr)
473  return "";
474 
475  std::string eventClass = event->GetNameOfClass();
476  std::string eventXML =
478 
479  std::transform(eventClass.cbegin(), eventClass.cend(), eventClass.begin(), ::toupper);
480 
481  eventXML += eventClass + "\" >\n";
482  // here follow event specific attributes
483  if (eventClass == "MOUSEPRESSEVENT" || eventClass == "MOUSERELEASEEVENT" || eventClass == "MOUSEDOUBLECLICKEVENT" ||
484  eventClass == "MOUSEMOVEEVENT" || eventClass == "MOUSEWHEELEVENT")
485  {
486  if (!(eventClass == "MOUSEMOVEEVENT") && !(eventClass == "MOUSEWHEELEVENT"))
487  {
488  // EventButton
491  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
492  eventXML += GetEventButton(event);
493  eventXML += "\"/>\n";
494  }
495  // ButtonState
496  if (GetButtonState(event) != "")
497  {
500  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
501  eventXML += GetButtonState(event);
502  eventXML += "\"/>\n";
503  }
504 
505  // Modifiers
506  if (GetModifierState(event) != "")
507  {
510  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
511  eventXML += GetModifierState(event);
512  eventXML += "\"/>\n";
513  }
514 
515  // Position on Screen
518  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
519  eventXML += GetPositionOnScreen(event);
520  eventXML += "\"/>\n";
521 
522  // Position in World
525  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
526  eventXML += GetPositionInWorld(event);
527  eventXML += "\"/>\n";
528  }
529  else if (eventClass == "INTERACTIONKEYEVENT")
530  {
531  auto *ke = dynamic_cast<mitk::InteractionKeyEvent *>(event);
532 
533  // key
536  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
537  eventXML += ke->GetKey();
538  eventXML += "\"/>\n";
539  }
540  else
541  {
542  MITK_WARN << "Event not recognized, discarding event of type " << event->GetNameOfClass();
543  }
544  if (eventClass == "MOUSEWHEELEVENT")
545  {
546  auto *we = dynamic_cast<MouseWheelEvent *>(event);
547  int delta = we->GetWheelDelta();
548 
549  std::stringstream ss;
550  ss << delta;
551 
554  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
555  eventXML += ss.str();
556  eventXML += "\"/>\n";
557 
560  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
561  eventXML += delta < 0 ? "DOWN" : "UP";
562  eventXML += "\"/>\n";
563  }
564 
565  // Renderer name
568  eventXML += InteractionEventConst::xmlParameterValue() + "=\"";
569  eventXML += event->GetSender()->GetName();
570  eventXML += "\"/>\n";
571 
572  // closing tag:
573  eventXML += "</" + InteractionEventConst::xmlTagEventVariant() + ">";
574  return eventXML;
575 }
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.
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, MouseButtons _arge)
ModifierKeys GetModifiers() const
Organizes the rendering process.
static const std::string xmlEventPropertyModifier()
MouseButtons GetButtonStates() const
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)
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()
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, int _arge)
MouseButtons GetButtonStates() const
#define MITK_WARN
Definition: mitkLogMacros.h:19
static Pointer New(BaseRenderer *_arga, const std::string &_argb, ModifierKeys _argc)
MouseButtons GetButtonStates() const
static BaseRendererMapType baseRendererMap
static const std::string xmlEventPropertyWheelDelta()
static const std::string xmlEventPropertyKey()
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd)
static const std::string xmlTagEventVariant()
static std::string GetModifierState(mitk::InteractionEvent *event)
GetModifierState Return ModifierState as String.
MouseButtons GetEventButton() const
ModifierKeys GetModifiers() const
static Pointer New(BaseRenderer *_arga, const Point2D &_argb, MouseButtons _argc, ModifierKeys _argd, MouseButtons _arge)
ModifierKeys GetModifiers() 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)
MouseButtons GetButtonStates() const
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.
MouseButtons GetEventButton() const
ModifierKeys GetModifiers() const
static const std::string xmlTagAttribute()