Panda3D
 All Classes Functions Variables Enumerations
eventHandler.cxx
00001 // Filename: eventHandler.cxx
00002 // Created by:  drose (08Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "eventHandler.h"
00016 #include "eventQueue.h"
00017 #include "config_event.h"
00018 
00019 TypeHandle EventHandler::_type_handle;
00020 
00021 EventHandler *EventHandler::_global_event_handler = 0;
00022 
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: EventHandler::Constructor
00026 //       Access: Public
00027 //  Description:
00028 ////////////////////////////////////////////////////////////////////
00029 EventHandler::
00030 EventHandler(EventQueue *ev_queue) : _queue(*ev_queue) {
00031 }
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: EventHandler::process_events
00035 //       Access: Public
00036 //  Description: The main processing loop of the EventHandler.  This
00037 //               function must be called periodically to service
00038 //               events.  Walks through each pending event and calls
00039 //               its assigned hooks.
00040 ////////////////////////////////////////////////////////////////////
00041 void EventHandler::
00042 process_events() {
00043   while (!_queue.is_queue_empty()) {
00044     dispatch_event(_queue.dequeue_event());
00045   }
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: EventHandler::dispatch_event
00050 //       Access: Public, Virtual
00051 //  Description: Calls the hooks assigned to the indicated single
00052 //               event.
00053 ////////////////////////////////////////////////////////////////////
00054 void EventHandler::
00055 dispatch_event(const Event *event) {
00056   nassertv(event != (Event *)NULL);
00057 
00058   // Is the event name defined in the hook table?  It will be if
00059   // anyone has ever assigned a hook to this particular event name.
00060   Hooks::const_iterator hi;
00061   hi = _hooks.find(event->get_name());
00062 
00063   if (hi != _hooks.end()) {
00064     // Yes, it is!  Now walk through all the functions assigned to
00065     // that event name.
00066     Functions copy_functions = (*hi).second;
00067 
00068     Functions::const_iterator fi;
00069     for (fi = copy_functions.begin(); fi != copy_functions.end(); ++fi) {
00070       if (event_cat.is_spam()) {
00071         event_cat->spam()
00072           << "calling callback 0x" << (void*)(*fi)
00073           << " for event '" << event->get_name() << "'"
00074           << endl;
00075       }
00076       (*fi)(event);
00077     }
00078   }
00079 
00080   // now for callback hooks
00081   CallbackHooks::const_iterator chi;
00082   chi = _cbhooks.find(event->get_name());
00083 
00084   if (chi != _cbhooks.end()) {
00085     // found one
00086     CallbackFunctions copy_functions = (*chi).second;
00087 
00088     CallbackFunctions::const_iterator cfi;
00089     for (cfi = copy_functions.begin(); cfi != copy_functions.end(); ++cfi) {
00090       ((*cfi).first)(event, (*cfi).second);
00091     }
00092   }
00093 }
00094 
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: EventHandler::write
00098 //       Access: Public
00099 //  Description:
00100 ////////////////////////////////////////////////////////////////////
00101 void EventHandler::
00102 write(ostream &out) const {
00103   Hooks::const_iterator hi;
00104   hi = _hooks.begin();
00105 
00106   CallbackHooks::const_iterator chi;
00107   chi = _cbhooks.begin();
00108 
00109   while (hi != _hooks.end() && chi != _cbhooks.end()) {
00110     if ((*hi).first < (*chi).first) {
00111       write_hook(out, *hi);
00112       ++hi;
00113     } else if ((*chi).first < (*hi).first) {
00114       write_cbhook(out, *chi);
00115       ++chi;
00116     } else {
00117       write_hook(out, *hi);
00118       write_cbhook(out, *chi);
00119       ++hi;
00120       ++chi;
00121     }
00122   }
00123 
00124   while (hi != _hooks.end()) {
00125     write_hook(out, *hi);
00126     ++hi;
00127   }
00128 
00129   while (chi != _cbhooks.end()) {
00130     write_cbhook(out, *chi);
00131     ++chi;
00132   }
00133 }
00134 
00135 
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: EventHandler::add_hook
00139 //       Access: Public
00140 //  Description: Adds the indicated function to the list of those that
00141 //               will be called when the named event is thrown.
00142 //               Returns true if the function was successfully added,
00143 //               false if it was already defined on the indicated
00144 //               event name.
00145 ////////////////////////////////////////////////////////////////////
00146 bool EventHandler::
00147 add_hook(const string &event_name, EventFunction *function) {
00148   if (event_cat.is_debug()) {
00149     event_cat.debug()
00150       << "adding hook for event '" << event_name
00151       << "' with function 0x" << (void*)function << endl;
00152   }
00153   assert(!event_name.empty());
00154   assert(function);
00155   return _hooks[event_name].insert(function).second;
00156 }
00157 
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: EventHandler::add_hook
00161 //       Access: Public
00162 //  Description: Adds the indicated function to the list of those that
00163 //               will be called when the named event is thrown.
00164 //               Returns true if the function was successfully added,
00165 //               false if it was already defined on the indicated
00166 //               event name.  This version records an untyped pointer
00167 //               to user callback data.
00168 ////////////////////////////////////////////////////////////////////
00169 bool EventHandler::
00170 add_hook(const string &event_name, EventCallbackFunction *function,
00171          void *data) {
00172   assert(!event_name.empty());
00173   assert(function);
00174   return _cbhooks[event_name].insert(CallbackFunction(function, data)).second;
00175 }
00176 
00177 ////////////////////////////////////////////////////////////////////
00178 //     Function: EventHandler::has_hook
00179 //       Access: Public
00180 //  Description: Returns true if there is any hook added on the
00181 //               indicated event name, false otherwise.
00182 ////////////////////////////////////////////////////////////////////
00183 bool EventHandler::
00184 has_hook(const string &event_name) const {
00185   assert(!event_name.empty());
00186   Hooks::const_iterator hi;
00187   hi = _hooks.find(event_name);
00188   if (hi != _hooks.end()) {
00189     if (!(*hi).second.empty()) {
00190       return true;
00191     }
00192   }
00193 
00194   CallbackHooks::const_iterator chi;
00195   chi = _cbhooks.find(event_name);
00196   if (chi != _cbhooks.end()) {
00197     if (!(*chi).second.empty()) {
00198       return true;
00199     }
00200   }
00201 
00202   return false;
00203 }
00204 
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //     Function: EventHandler::remove_hook
00208 //       Access: Public
00209 //  Description: Removes the indicated function from the named event
00210 //               hook.  Returns true if the hook was removed, false if
00211 //               it wasn't there in the first place.
00212 ////////////////////////////////////////////////////////////////////
00213 bool EventHandler::
00214 remove_hook(const string &event_name, EventFunction *function) {
00215   assert(!event_name.empty());
00216   assert(function);
00217   return _hooks[event_name].erase(function) != 0;
00218 }
00219 
00220 
00221 ////////////////////////////////////////////////////////////////////
00222 //     Function: EventHandler::remove_hook
00223 //       Access: Public
00224 //  Description: Removes the indicated function from the named event
00225 //               hook.  Returns true if the hook was removed, false if
00226 //               it wasn't there in the first place.  This version
00227 //               takes an untyped pointer to user callback data.
00228 ////////////////////////////////////////////////////////////////////
00229 bool EventHandler::
00230 remove_hook(const string &event_name, EventCallbackFunction *function,
00231             void *data) {
00232   assert(!event_name.empty());
00233   assert(function);
00234   return _cbhooks[event_name].erase(CallbackFunction(function, data)) != 0;
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: EventHandler::remove_hooks
00239 //       Access: Public
00240 //  Description: Removes all functions from the named event hook.
00241 //               Returns true if any functions were removed, false if
00242 //               there were no functions added to the hook.
00243 ////////////////////////////////////////////////////////////////////
00244 bool EventHandler::
00245 remove_hooks(const string &event_name) {
00246   assert(!event_name.empty());
00247   bool any_removed = false;
00248 
00249   Hooks::iterator hi = _hooks.find(event_name);
00250   if (hi != _hooks.end()) {
00251     if (!(*hi).second.empty()) {
00252       any_removed = true;
00253     }
00254     _hooks.erase(hi);
00255   }
00256 
00257   CallbackHooks::iterator chi = _cbhooks.find(event_name);
00258   if (chi != _cbhooks.end()) {
00259     if (!(*chi).second.empty()) {
00260       any_removed = true;
00261     }
00262     _cbhooks.erase(chi);
00263   }
00264 
00265   return any_removed;
00266 }
00267 
00268 ////////////////////////////////////////////////////////////////////
00269 //     Function: EventHandler::remove_hooks_with
00270 //       Access: Public
00271 //  Description: Removes all CallbackFunction hooks that have the
00272 //               indicated pointer as the associated data pointer.
00273 ////////////////////////////////////////////////////////////////////
00274 bool EventHandler::
00275 remove_hooks_with(void *data) {
00276   bool any_removed = false;
00277 
00278   CallbackHooks::iterator chi;
00279   for (chi = _cbhooks.begin(); chi != _cbhooks.end(); ++chi) {
00280     CallbackFunctions &funcs = (*chi).second;
00281     CallbackFunctions::iterator cfi;
00282 
00283     CallbackFunctions new_funcs;
00284     for (cfi = funcs.begin(); cfi != funcs.end(); ++cfi) {
00285       if ((*cfi).second == data) {
00286         any_removed = true;
00287       } else {
00288         new_funcs.insert(*cfi);
00289       }
00290     }
00291     funcs.swap(new_funcs);
00292   }
00293 
00294   return any_removed;
00295 }
00296 
00297 
00298 ////////////////////////////////////////////////////////////////////
00299 //     Function: EventHandler::remove_all_hooks
00300 //       Access: Public
00301 //  Description: Removes all hooks assigned to all events.
00302 ////////////////////////////////////////////////////////////////////
00303 void EventHandler::
00304 remove_all_hooks() {
00305   _hooks.clear();
00306   _cbhooks.clear();
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: EventHandler::make_global_event_handler
00311 //       Access: Protected, Static
00312 //  Description:
00313 ////////////////////////////////////////////////////////////////////
00314 void EventHandler::
00315 make_global_event_handler() {
00316   _global_event_handler = new EventHandler(EventQueue::get_global_event_queue());
00317 }
00318 
00319 
00320 ////////////////////////////////////////////////////////////////////
00321 //     Function: EventHandler::write_hook
00322 //       Access: Private
00323 //  Description:
00324 ////////////////////////////////////////////////////////////////////
00325 void EventHandler::
00326 write_hook(ostream &out, const EventHandler::Hooks::value_type &hook) const {
00327   if (!hook.second.empty()) {
00328     out << hook.first << " has " << hook.second.size() << " functions.\n";
00329   }
00330 }
00331 
00332 ////////////////////////////////////////////////////////////////////
00333 //     Function: EventHandler::write_cbhook
00334 //       Access: Private
00335 //  Description:
00336 ////////////////////////////////////////////////////////////////////
00337 void EventHandler::
00338 write_cbhook(ostream &out, const EventHandler::CallbackHooks::value_type &hook) const {
00339   if (!hook.second.empty()) {
00340     out << hook.first << " has " << hook.second.size() << " callback functions.\n";
00341   }
00342 }
 All Classes Functions Variables Enumerations