Panda3D
 All Classes Functions Variables Enumerations
eventHandler.cxx
1 // Filename: eventHandler.cxx
2 // Created by: drose (08Feb99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eventHandler.h"
16 #include "eventQueue.h"
17 #include "config_event.h"
18 
19 TypeHandle EventHandler::_type_handle;
20 
21 EventHandler *EventHandler::_global_event_handler = NULL;
22 
23 
24 ////////////////////////////////////////////////////////////////////
25 // Function: EventHandler::Constructor
26 // Access: Public
27 // Description:
28 ////////////////////////////////////////////////////////////////////
29 EventHandler::
30 EventHandler(EventQueue *ev_queue) : _queue(*ev_queue) {
31 }
32 
33 ////////////////////////////////////////////////////////////////////
34 // Function: EventHandler::process_events
35 // Access: Public
36 // Description: The main processing loop of the EventHandler. This
37 // function must be called periodically to service
38 // events. Walks through each pending event and calls
39 // its assigned hooks.
40 ////////////////////////////////////////////////////////////////////
41 void EventHandler::
43  while (!_queue.is_queue_empty()) {
44  dispatch_event(_queue.dequeue_event());
45  }
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: EventHandler::dispatch_event
50 // Access: Public, Virtual
51 // Description: Calls the hooks assigned to the indicated single
52 // event.
53 ////////////////////////////////////////////////////////////////////
54 void EventHandler::
55 dispatch_event(const Event *event) {
56  nassertv(event != (Event *)NULL);
57 
58  // Is the event name defined in the hook table? It will be if
59  // anyone has ever assigned a hook to this particular event name.
60  Hooks::const_iterator hi;
61  hi = _hooks.find(event->get_name());
62 
63  if (hi != _hooks.end()) {
64  // Yes, it is! Now walk through all the functions assigned to
65  // that event name.
66  Functions copy_functions = (*hi).second;
67 
68  Functions::const_iterator fi;
69  for (fi = copy_functions.begin(); fi != copy_functions.end(); ++fi) {
70  if (event_cat.is_spam()) {
71  event_cat->spam()
72  << "calling callback 0x" << (void*)(*fi)
73  << " for event '" << event->get_name() << "'"
74  << endl;
75  }
76  (*fi)(event);
77  }
78  }
79 
80  // now for callback hooks
81  CallbackHooks::const_iterator chi;
82  chi = _cbhooks.find(event->get_name());
83 
84  if (chi != _cbhooks.end()) {
85  // found one
86  CallbackFunctions copy_functions = (*chi).second;
87 
88  CallbackFunctions::const_iterator cfi;
89  for (cfi = copy_functions.begin(); cfi != copy_functions.end(); ++cfi) {
90  ((*cfi).first)(event, (*cfi).second);
91  }
92  }
93 }
94 
95 
96 ////////////////////////////////////////////////////////////////////
97 // Function: EventHandler::write
98 // Access: Public
99 // Description:
100 ////////////////////////////////////////////////////////////////////
101 void EventHandler::
102 write(ostream &out) const {
103  Hooks::const_iterator hi;
104  hi = _hooks.begin();
105 
106  CallbackHooks::const_iterator chi;
107  chi = _cbhooks.begin();
108 
109  while (hi != _hooks.end() && chi != _cbhooks.end()) {
110  if ((*hi).first < (*chi).first) {
111  write_hook(out, *hi);
112  ++hi;
113  } else if ((*chi).first < (*hi).first) {
114  write_cbhook(out, *chi);
115  ++chi;
116  } else {
117  write_hook(out, *hi);
118  write_cbhook(out, *chi);
119  ++hi;
120  ++chi;
121  }
122  }
123 
124  while (hi != _hooks.end()) {
125  write_hook(out, *hi);
126  ++hi;
127  }
128 
129  while (chi != _cbhooks.end()) {
130  write_cbhook(out, *chi);
131  ++chi;
132  }
133 }
134 
135 
136 
137 ////////////////////////////////////////////////////////////////////
138 // Function: EventHandler::add_hook
139 // Access: Public
140 // Description: Adds the indicated function to the list of those that
141 // will be called when the named event is thrown.
142 // Returns true if the function was successfully added,
143 // false if it was already defined on the indicated
144 // event name.
145 ////////////////////////////////////////////////////////////////////
146 bool EventHandler::
147 add_hook(const string &event_name, EventFunction *function) {
148  if (event_cat.is_debug()) {
149  event_cat.debug()
150  << "adding hook for event '" << event_name
151  << "' with function 0x" << (void*)function << endl;
152  }
153  assert(!event_name.empty());
154  assert(function);
155  return _hooks[event_name].insert(function).second;
156 }
157 
158 
159 ////////////////////////////////////////////////////////////////////
160 // Function: EventHandler::add_hook
161 // Access: Public
162 // Description: Adds the indicated function to the list of those that
163 // will be called when the named event is thrown.
164 // Returns true if the function was successfully added,
165 // false if it was already defined on the indicated
166 // event name. This version records an untyped pointer
167 // to user callback data.
168 ////////////////////////////////////////////////////////////////////
169 bool EventHandler::
170 add_hook(const string &event_name, EventCallbackFunction *function,
171  void *data) {
172  assert(!event_name.empty());
173  assert(function);
174  return _cbhooks[event_name].insert(CallbackFunction(function, data)).second;
175 }
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: EventHandler::has_hook
179 // Access: Public
180 // Description: Returns true if there is any hook added on the
181 // indicated event name, false otherwise.
182 ////////////////////////////////////////////////////////////////////
183 bool EventHandler::
184 has_hook(const string &event_name) const {
185  assert(!event_name.empty());
186  Hooks::const_iterator hi;
187  hi = _hooks.find(event_name);
188  if (hi != _hooks.end()) {
189  if (!(*hi).second.empty()) {
190  return true;
191  }
192  }
193 
194  CallbackHooks::const_iterator chi;
195  chi = _cbhooks.find(event_name);
196  if (chi != _cbhooks.end()) {
197  if (!(*chi).second.empty()) {
198  return true;
199  }
200  }
201 
202  return false;
203 }
204 
205 
206 ////////////////////////////////////////////////////////////////////
207 // Function: EventHandler::remove_hook
208 // Access: Public
209 // Description: Removes the indicated function from the named event
210 // hook. Returns true if the hook was removed, false if
211 // it wasn't there in the first place.
212 ////////////////////////////////////////////////////////////////////
213 bool EventHandler::
214 remove_hook(const string &event_name, EventFunction *function) {
215  assert(!event_name.empty());
216  assert(function);
217  return _hooks[event_name].erase(function) != 0;
218 }
219 
220 
221 ////////////////////////////////////////////////////////////////////
222 // Function: EventHandler::remove_hook
223 // Access: Public
224 // Description: Removes the indicated function from the named event
225 // hook. Returns true if the hook was removed, false if
226 // it wasn't there in the first place. This version
227 // takes an untyped pointer to user callback data.
228 ////////////////////////////////////////////////////////////////////
229 bool EventHandler::
230 remove_hook(const string &event_name, EventCallbackFunction *function,
231  void *data) {
232  assert(!event_name.empty());
233  assert(function);
234  return _cbhooks[event_name].erase(CallbackFunction(function, data)) != 0;
235 }
236 
237 ////////////////////////////////////////////////////////////////////
238 // Function: EventHandler::remove_hooks
239 // Access: Public
240 // Description: Removes all functions from the named event hook.
241 // Returns true if any functions were removed, false if
242 // there were no functions added to the hook.
243 ////////////////////////////////////////////////////////////////////
244 bool EventHandler::
245 remove_hooks(const string &event_name) {
246  assert(!event_name.empty());
247  bool any_removed = false;
248 
249  Hooks::iterator hi = _hooks.find(event_name);
250  if (hi != _hooks.end()) {
251  if (!(*hi).second.empty()) {
252  any_removed = true;
253  }
254  _hooks.erase(hi);
255  }
256 
257  CallbackHooks::iterator chi = _cbhooks.find(event_name);
258  if (chi != _cbhooks.end()) {
259  if (!(*chi).second.empty()) {
260  any_removed = true;
261  }
262  _cbhooks.erase(chi);
263  }
264 
265  return any_removed;
266 }
267 
268 ////////////////////////////////////////////////////////////////////
269 // Function: EventHandler::remove_hooks_with
270 // Access: Public
271 // Description: Removes all CallbackFunction hooks that have the
272 // indicated pointer as the associated data pointer.
273 ////////////////////////////////////////////////////////////////////
274 bool EventHandler::
275 remove_hooks_with(void *data) {
276  bool any_removed = false;
277 
278  CallbackHooks::iterator chi;
279  for (chi = _cbhooks.begin(); chi != _cbhooks.end(); ++chi) {
280  CallbackFunctions &funcs = (*chi).second;
281  CallbackFunctions::iterator cfi;
282 
283  CallbackFunctions new_funcs;
284  for (cfi = funcs.begin(); cfi != funcs.end(); ++cfi) {
285  if ((*cfi).second == data) {
286  any_removed = true;
287  } else {
288  new_funcs.insert(*cfi);
289  }
290  }
291  funcs.swap(new_funcs);
292  }
293 
294  return any_removed;
295 }
296 
297 
298 ////////////////////////////////////////////////////////////////////
299 // Function: EventHandler::remove_all_hooks
300 // Access: Public
301 // Description: Removes all hooks assigned to all events.
302 ////////////////////////////////////////////////////////////////////
303 void EventHandler::
305  _hooks.clear();
306  _cbhooks.clear();
307 }
308 
309 ////////////////////////////////////////////////////////////////////
310 // Function: EventHandler::make_global_event_handler
311 // Access: Protected, Static
312 // Description:
313 ////////////////////////////////////////////////////////////////////
314 void EventHandler::
315 make_global_event_handler() {
316  _global_event_handler = new EventHandler(EventQueue::get_global_event_queue());
317 }
318 
319 
320 ////////////////////////////////////////////////////////////////////
321 // Function: EventHandler::write_hook
322 // Access: Private
323 // Description:
324 ////////////////////////////////////////////////////////////////////
325 void EventHandler::
326 write_hook(ostream &out, const EventHandler::Hooks::value_type &hook) const {
327  if (!hook.second.empty()) {
328  out << hook.first << " has " << hook.second.size() << " functions.\n";
329  }
330 }
331 
332 ////////////////////////////////////////////////////////////////////
333 // Function: EventHandler::write_cbhook
334 // Access: Private
335 // Description:
336 ////////////////////////////////////////////////////////////////////
337 void EventHandler::
338 write_cbhook(ostream &out, const EventHandler::CallbackHooks::value_type &hook) const {
339  if (!hook.second.empty()) {
340  out << hook.first << " has " << hook.second.size() << " callback functions.\n";
341  }
342 }
void remove_all_hooks()
Removes all hooks assigned to all events.
A class to monitor events from the C++ side of things.
Definition: eventHandler.h:41
bool has_hook(const string &event_name) const
Returns true if there is any hook added on the indicated event name, false otherwise.
bool add_hook(const string &event_name, EventFunction *function)
Adds the indicated function to the list of those that will be called when the named event is thrown...
static EventQueue * get_global_event_queue()
Returns a pointer to the one global EventQueue object.
Definition: eventQueue.I:24
virtual void dispatch_event(const Event *)
Calls the hooks assigned to the indicated single event.
A queue of pending events.
Definition: eventQueue.h:32
bool remove_hooks_with(void *data)
Removes all CallbackFunction hooks that have the indicated pointer as the associated data pointer...
bool remove_hooks(const string &event_name)
Removes all functions from the named event hook.
A named event, possibly with parameters.
Definition: event.h:36
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
bool remove_hook(const string &event_name, EventFunction *function)
Removes the indicated function from the named event hook.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void process_events()
The main processing loop of the EventHandler.