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
mitkDispatcher.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 "mitkDispatcher.h"
18 #include "mitkInteractionEvent.h"
20 #include "mitkInternalEvent.h"
21 #include "usGetModuleContext.h"
22 
23 namespace
24 {
25  struct cmp
26  {
27  bool operator()(mitk::DataInteractor *d1, mitk::DataInteractor *d2) { return (d1->GetLayer() > d2->GetLayer()); }
28  };
29 }
30 
31 mitk::Dispatcher::Dispatcher(const std::string &rendererName) : m_ProcessingMode(REGULAR)
32 {
33  // LDAP filter string to find all listeners specific for the renderer
34  // corresponding to this dispatcher
35  std::string specificRenderer = "(rendererName=" + rendererName + ")";
36 
37  // LDAP filter string to find all listeners that are not specific
38  // to any renderer
39  std::string anyRenderer = "(!(rendererName=*))";
40 
41  // LDAP filter string to find only instances of InteractionEventObserver
42  std::string classInteractionEventObserver =
43  "(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid<InteractionEventObserver>() + ")";
44 
45  // Configure the LDAP filter to find all instances of InteractionEventObserver
46  // that are specific to this dispatcher or unspecific to any dispatchers (real global listener)
47  us::LDAPFilter filter("(&(|" + specificRenderer + anyRenderer + ")" + classInteractionEventObserver + ")");
48 
49  // Give the filter to the ObserverTracker
50  m_EventObserverTracker = new us::ServiceTracker<InteractionEventObserver>(us::GetModuleContext(), filter);
51  m_EventObserverTracker->Open();
52 }
53 
55 {
56  RemoveDataInteractor(dataNode);
57  RemoveOrphanedInteractors();
58 
59  auto dataInteractor = dataNode->GetDataInteractor().GetPointer();
60 
61  if (dataInteractor != nullptr)
62  m_Interactors.push_back(dataInteractor);
63 }
64 
65 /*
66  * Note: One DataInteractor can only have one DataNode and vice versa,
67  * BUT the m_Interactors list may contain another DataInteractor that is still connected to this DataNode,
68  * in this case we have to remove >1 DataInteractor. (Some special case of switching DataNodes between DataInteractors
69  * and registering a
70  * DataNode to a DataStorage after assigning it to an DataInteractor)
71  */
72 
74 {
75  for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();)
76  {
77  if ((*it).IsNull() || (*it)->GetDataNode() == nullptr || (*it)->GetDataNode() == dataNode)
78  {
79  it = m_Interactors.erase(it);
80  }
81  else
82  {
83  ++it;
84  }
85  }
86 }
87 
89 {
90  return m_Interactors.size();
91 }
92 
94 {
95  m_EventObserverTracker->Close();
96  delete m_EventObserverTracker;
97 
98  m_Interactors.clear();
99 }
100 
102 {
103  InteractionEvent::Pointer p = event;
104  bool eventIsHandled = false;
105  /* Filter out and handle Internal Events separately */
106  InternalEvent *internalEvent = dynamic_cast<InternalEvent *>(event);
107  if (internalEvent != nullptr)
108  {
109  eventIsHandled = HandleInternalEvent(internalEvent);
110  // InternalEvents that are handled are not sent to the listeners
111  if (eventIsHandled)
112  {
113  return true;
114  }
115  }
116  switch (m_ProcessingMode)
117  {
118  case CONNECTEDMOUSEACTION:
119  // finished connected mouse action
120  if (std::strcmp(p->GetNameOfClass(), "MouseReleaseEvent") == 0)
121  {
122  m_ProcessingMode = REGULAR;
123 
124  if (m_SelectedInteractor.IsNotNull())
125  eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode());
126 
127  m_SelectedInteractor = nullptr;
128  }
129  // give event to selected interactor
130  if (eventIsHandled == false && m_SelectedInteractor.IsNotNull())
131  eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode());
132 
133  break;
134 
135  case GRABINPUT:
136  if (m_SelectedInteractor.IsNotNull())
137  {
138  eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode());
139  SetEventProcessingMode(m_SelectedInteractor);
140  }
141 
142  break;
143 
144  case PREFERINPUT:
145  if (m_SelectedInteractor.IsNotNull() &&
146  m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()) == true)
147  {
148  SetEventProcessingMode(m_SelectedInteractor);
149  eventIsHandled = true;
150  }
151 
152  break;
153 
154  case REGULAR:
155  break;
156  }
157 
158  // Standard behavior. Is executed in STANDARD mode and PREFERINPUT mode, if preferred interactor rejects event.
159  if (m_ProcessingMode == REGULAR || (m_ProcessingMode == PREFERINPUT && eventIsHandled == false))
160  {
161  if (std::strcmp(p->GetNameOfClass(), "MousePressEvent") == 0)
162  event->GetSender()->GetRenderingManager()->SetRenderWindowFocus(event->GetSender()->GetRenderWindow());
163  m_Interactors.sort(cmp()); // sorts interactors by layer (descending);
164 
165  // copy the list to prevent iterator invalidation as executing actions
166  // in HandleEvent() can cause the m_Interactors list to be updated
167  const ListInteractorType tmpInteractorList(m_Interactors);
168  ListInteractorType::const_iterator it;
169  for (it = tmpInteractorList.cbegin(); it != tmpInteractorList.cend(); ++it)
170  {
171  if ((*it).IsNotNull() && (*it)->HandleEvent(event, (*it)->GetDataNode()))
172  {
173  // Interactor can be deleted during HandleEvent(), so check it again
174  if ((*it).IsNotNull())
175  {
176  // if an event is handled several properties are checked, in order to determine the processing mode of the
177  // dispatcher
178  SetEventProcessingMode(*it);
179  }
180  if (std::strcmp(p->GetNameOfClass(), "MousePressEvent") == 0 && m_ProcessingMode == REGULAR)
181  {
182  m_SelectedInteractor = *it;
183  m_ProcessingMode = CONNECTEDMOUSEACTION;
184  }
185  eventIsHandled = true;
186  break;
187  }
188  }
189  }
190 
191  /* Notify InteractionEventObserver */
192  const std::vector<us::ServiceReference<InteractionEventObserver>> listEventObserver =
193  m_EventObserverTracker->GetServiceReferences();
194  for (std::vector<us::ServiceReference<InteractionEventObserver>>::const_iterator it = listEventObserver.cbegin();
195  it != listEventObserver.cend();
196  ++it)
197  {
198  InteractionEventObserver *interactionEventObserver = m_EventObserverTracker->GetService(*it);
199  if (interactionEventObserver != nullptr)
200  {
201  if (interactionEventObserver->IsEnabled())
202  {
203  interactionEventObserver->Notify(event, eventIsHandled);
204  }
205  }
206  }
207 
208  // Process event queue
209  if (!m_QueuedEvents.empty())
210  {
211  InteractionEvent::Pointer e = m_QueuedEvents.front();
212  m_QueuedEvents.pop_front();
213  ProcessEvent(e);
214  }
215  return eventIsHandled;
216 }
217 
218 /*
219  * Checks if DataNodes associated with DataInteractors point back to them.
220  * If not remove the DataInteractors. (This can happen when s.o. tries to set DataNodes to multiple DataInteractors)
221  */
222 void mitk::Dispatcher::RemoveOrphanedInteractors()
223 {
224  for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();)
225  {
226  if ((*it).IsNull())
227  {
228  it = m_Interactors.erase(it);
229  }
230  else
231  {
232  DataNode::Pointer node = (*it)->GetDataNode();
233 
234  if (node.IsNull())
235  {
236  it = m_Interactors.erase(it);
237  }
238  else
239  {
240  DataInteractor::Pointer interactor = node->GetDataInteractor();
241 
242  if (interactor != it->GetPointer())
243  {
244  it = m_Interactors.erase(it);
245  }
246  else
247  {
248  ++it;
249  }
250  }
251  }
252  }
253 }
254 
256 {
257  m_QueuedEvents.push_back(event);
258 }
259 
260 void mitk::Dispatcher::SetEventProcessingMode(DataInteractor *dataInteractor)
261 {
262  m_ProcessingMode = dataInteractor->GetMode();
263  if (dataInteractor->GetMode() != REGULAR)
264  {
265  m_SelectedInteractor = dataInteractor;
266  }
267 }
268 
269 bool mitk::Dispatcher::HandleInternalEvent(InternalEvent *internalEvent)
270 {
271  if (internalEvent->GetSignalName() == DataInteractor::IntDeactivateMe &&
272  internalEvent->GetTargetInteractor() != nullptr)
273  {
274  internalEvent->GetTargetInteractor()->GetDataNode()->SetDataInteractor(nullptr);
275  internalEvent->GetTargetInteractor()->SetDataNode(nullptr);
276 
278  return true;
279  }
280  return false;
281 }
Base class to implement InteractionEventObservers.
BaseRenderer * GetSender() const
std::list< mitk::WeakPointer< DataInteractor > > ListInteractorType
virtual void Notify(InteractionEvent *interactionEvent, bool isHandled)=0
Class to create events from within the application to signal about internal events.
virtual DataInteractor::Pointer GetDataInteractor() const
bool ProcessEvent(InteractionEvent *event)
Base class from with interactors that handle DataNodes are to be derived.
itk::SmartPointer< Self > Pointer
Definition: mitkDataNode.h:81
vcl_size_t GetNumberOfInteractors()
static RenderingManager * GetInstance()
Dispatcher(const std::string &rendererName)
itk::SmartPointer< Self > Pointer
static const std::string IntDeactivateMe
ProcessEventMode GetMode() const
US_Core_EXPORT const std::string & OBJECTCLASS()
void AddDataInteractor(const DataNode *dataNode)
void QueueEvent(InteractionEvent *event)
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
void RemoveDataInteractor(const DataNode *dataNode)
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66