EventInterface 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. // Code by: Jeremy Moles (cubicool) 2007-2008
  14. #ifndef OSGWIDGET_EVENT_INTERFACE
  15. #define OSGWIDGET_EVENT_INTERFACE
  16. #include <list>
  17. #include <osg/ref_ptr>
  18. #include <osg/observer_ptr>
  19. #include <osg/Referenced>
  20. #include <osgWidget/Export>
  21. namespace osgWidget {
  22. class WindowManager;
  23. class Window;
  24. class Widget;
  25. enum EventType
  26. {
  27. EVENT_NONE = 0x0000,
  28. EVENT_FOCUS = 0x0001,
  29. EVENT_UNFOCUS = 0x0002,
  30. EVENT_MOUSE_ENTER = 0x0004,
  31. EVENT_MOUSE_OVER = 0x0008,
  32. EVENT_MOUSE_LEAVE = 0x0010,
  33. EVENT_MOUSE_DRAG = 0x0020,
  34. EVENT_MOUSE_PUSH = 0x0040,
  35. EVENT_MOUSE_RELEASE = 0x0080,
  36. EVENT_MOUSE_SCROLL = 0x0100,
  37. EVENT_KEY_DOWN = 0x0200,
  38. EVENT_KEY_UP = 0x0400,
  39. EVENT_ALL = 0xFFFF
  40. };
  41. // Helpful wrapper around using the raw types, since it often doesn't make sense to
  42. // use some without the others.
  43. enum EventMask
  44. {
  45. EVENT_MASK_FOCUS = EVENT_FOCUS | EVENT_UNFOCUS,
  46. EVENT_MASK_MOUSE_MOVE = EVENT_MOUSE_ENTER | EVENT_MOUSE_OVER | EVENT_MOUSE_LEAVE,
  47. EVENT_MASK_MOUSE_CLICK = EVENT_MOUSE_PUSH | EVENT_MOUSE_RELEASE,
  48. EVENT_MASK_MOUSE_DRAG = EVENT_MASK_MOUSE_MOVE | EVENT_MASK_MOUSE_CLICK | EVENT_MOUSE_DRAG,
  49. EVENT_MASK_KEY = EVENT_KEY_UP | EVENT_KEY_DOWN
  50. };
  51. class OSGWIDGET_EXPORT Event
  52. {
  53. public:
  54. EventType type;
  55. double x;
  56. double y;
  57. int key;
  58. int keyMask;
  59. Event(WindowManager* wm, EventType _type = EVENT_NONE):
  60. type (_type),
  61. x (0.0f),
  62. y (0.0f),
  63. key (-1),
  64. keyMask (-1),
  65. _wm (wm),
  66. _window (0),
  67. _widget (0),
  68. _data (0) {
  69. }
  70. Event& makeType(EventType _type) {
  71. if(_type != EVENT_NONE) type = _type;
  72. return *this;
  73. }
  74. Event& makeMouse(double _x, double _y, EventType _type = EVENT_NONE) {
  75. x = _x;
  76. y = _y;
  77. if(_type != EVENT_NONE) type = _type;
  78. return *this;
  79. }
  80. Event& makeKey(int _key, int _keyMask, EventType _type = EVENT_NONE) {
  81. key = _key;
  82. keyMask = _keyMask;
  83. if(_type != EVENT_NONE) type = _type;
  84. return *this;
  85. }
  86. WindowManager* getWindowManager() { return _wm; }
  87. const WindowManager* getWindowManager() const {
  88. return _wm;
  89. }
  90. Window* getWindow() {
  91. return _window;
  92. }
  93. const Window* getWindow() const {
  94. return _window;
  95. }
  96. Widget* getWidget() {
  97. return _widget;
  98. }
  99. const Widget* getWidget() const {
  100. return _widget;
  101. }
  102. void* getData() {
  103. return _data;
  104. }
  105. const void* getData() const {
  106. return _data;
  107. }
  108. void setData(void* data) {
  109. _data = data;
  110. }
  111. protected:
  112. friend class WindowManager;
  113. friend class Window;
  114. WindowManager* _wm;
  115. Window* _window;
  116. Widget* _widget;
  117. void* _data;
  118. };
  119. // The Callback interface was inspired by the CEGUI project:
  120. //
  121. // http://www.cegui.org.uk/wiki/index.php/Main_Page
  122. //
  123. // It's a great little way to cleanly implement callbacks for events, although
  124. // I did change the names a bit to make them more appropriate for OSG. MANY THANKS
  125. // to the CEGUI project!
  126. // The CallbackInterface, which the highest-level functor keeps a pointer to.
  127. struct CallbackInterface: public osg::Referenced
  128. {
  129. virtual ~CallbackInterface() {}
  130. virtual const char* className() const { return "osgWidget::CallbackInterface"; }
  131. virtual bool operator()(Event&) = 0;
  132. };
  133. // The object that facilitates a class method as a callback.
  134. template<typename T>
  135. class ObjectCallback: public CallbackInterface
  136. {
  137. public:
  138. typedef bool (T::*ObjectCallbackType)(Event&);
  139. ObjectCallback(ObjectCallbackType callback, T* obj):
  140. _object (obj),
  141. _callback (callback) {}
  142. virtual bool operator()(Event& ev) {
  143. return (_object->*_callback)(ev);
  144. }
  145. private:
  146. T* _object;
  147. ObjectCallbackType _callback;
  148. };
  149. // The object that facilitates general functions as callbacks.
  150. template<typename T>
  151. class FunctionCallback: public CallbackInterface
  152. {
  153. public:
  154. FunctionCallback(T* callback):
  155. _callback(callback) {
  156. }
  157. virtual bool operator()(Event& ev) {
  158. return (*_callback)(ev);
  159. }
  160. protected:
  161. T* _callback;
  162. };
  163. // The highlevel functor.
  164. class OSGWIDGET_EXPORT Callback: public osg::Referenced
  165. {
  166. public:
  167. Callback(): _type(EVENT_NONE), _data(0), _callback(0) {}
  168. Callback(const Callback& rhs): osg::Referenced(rhs), _type(rhs._type), _data(rhs._data), _callback(rhs._callback) {}
  169. virtual const char* className() const { return "osgWidget::Callback"; }
  170. // The more traditional style of OSG Callbacks.
  171. Callback(EventType type, void* data=0):
  172. _type (type),
  173. _data (data),
  174. _callback (0) {
  175. }
  176. // Creates a Callback that is bound to a member function.
  177. template<typename T>
  178. Callback(bool (T::*function)(Event&), T* obj, EventType type, void* data=0):
  179. _type (type),
  180. _data (data),
  181. _callback (new ObjectCallback<T>(function, obj)) {
  182. }
  183. // Creates a Callback that is bound to a functor pointer.
  184. template<typename T>
  185. Callback(T* functor, EventType type, void* data=0):
  186. _type (type),
  187. _data (data),
  188. _callback (new FunctionCallback<T>(functor)) {
  189. }
  190. virtual ~Callback() {}
  191. virtual bool operator()(Event& ev) {
  192. if(!_callback) return false;
  193. return (*_callback)(ev);
  194. }
  195. EventType getType() const {
  196. return _type;
  197. }
  198. void* getData() {
  199. return _data;
  200. }
  201. const void* getData() const {
  202. return _data;
  203. }
  204. protected:
  205. EventType _type;
  206. void* _data;
  207. // We use a ref_ptr here so that we don't have to worry about memory.
  208. osg::ref_ptr<CallbackInterface> _callback;
  209. };
  210. class OSGWIDGET_EXPORT EventInterface
  211. {
  212. public:
  213. EventInterface(): _eventMask(EVENT_NONE) {}
  214. EventInterface(const EventInterface& ei):
  215. _eventMask (ei._eventMask),
  216. _callbacks (ei._callbacks) {}
  217. virtual ~EventInterface() {}
  218. // These functions take as their final argument the WindowManager which issued the
  219. // request. This is sometimes useful to get information about key state, etc.
  220. // Notify the EventInterface object that is has been focused or unfocused; since
  221. // this isn't always bound to a mouse event (i.e., if you want to be able to use
  222. // the TAB key to focus), we need separate events here.
  223. virtual bool focus (const WindowManager*) { return false; }
  224. virtual bool unfocus (const WindowManager*) { return false; }
  225. // Mouse events, pretty self-explanatory.
  226. virtual bool mouseEnter (double, double, const WindowManager*) { return false; }
  227. virtual bool mouseOver (double, double, const WindowManager*) { return false; }
  228. virtual bool mouseLeave (double, double, const WindowManager*) { return false; }
  229. virtual bool mouseDrag (double, double, const WindowManager*) { return false; }
  230. virtual bool mousePush (double, double, const WindowManager*) { return false; }
  231. virtual bool mouseRelease (double, double, const WindowManager*) { return false; }
  232. virtual bool mouseScroll (double, double, const WindowManager*) { return false; }
  233. // These functions pass the osgGA::GUIEventAdapter::KeySymbol and KeyModMask and,
  234. // as above, the WindowManager.
  235. virtual bool keyDown (int, int, const WindowManager*) { return false; }
  236. virtual bool keyUp (int, int, const WindowManager*) { return false; }
  237. void setEventMask(unsigned int mask) {
  238. _eventMask = mask;
  239. }
  240. void addEventMask(unsigned int mask) {
  241. _eventMask |= mask;
  242. }
  243. void removeEventMask(unsigned int mask) {
  244. _eventMask ^= mask;
  245. }
  246. unsigned int getEventMask() const {
  247. return _eventMask;
  248. }
  249. typedef std::list<osg::ref_ptr<Callback> > CallbackList;
  250. inline CallbackList& getCallbacks() { return _callbacks; }
  251. inline const CallbackList& getCallbacks() const { return _callbacks; }
  252. void addCallback(Callback* cb) {
  253. _callbacks.push_back(cb);
  254. }
  255. bool callCallbacks(Event& ev) {
  256. if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
  257. for(CallbackList::iterator i = _callbacks.begin(); i != _callbacks.end(); i++) {
  258. // This is the OLD method; testing a new method below.
  259. // if(i->getType() == ev.type && (*i)(ev)) return true;
  260. if(i->get()->getType() & ev.type) {
  261. ev.setData(i->get()->getData());
  262. if((*i->get())(ev)) return true;
  263. }
  264. }
  265. return false;
  266. }
  267. bool callMethodAndCallbacks(Event& ev) {
  268. if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
  269. bool handled = false;
  270. if(ev.type == EVENT_FOCUS) handled = focus(ev.getWindowManager());
  271. else if(ev.type == EVENT_UNFOCUS) handled = unfocus(ev.getWindowManager());
  272. else if(ev.type == EVENT_MOUSE_ENTER)
  273. handled = mouseEnter(ev.x, ev.y, ev.getWindowManager())
  274. ;
  275. else if(ev.type == EVENT_MOUSE_OVER)
  276. handled = mouseOver(ev.x, ev.y, ev.getWindowManager())
  277. ;
  278. else if(ev.type == EVENT_MOUSE_LEAVE)
  279. handled = mouseLeave(ev.x, ev.y, ev.getWindowManager())
  280. ;
  281. else if(ev.type == EVENT_MOUSE_DRAG)
  282. handled = mouseDrag(ev.x, ev.y, ev.getWindowManager())
  283. ;
  284. else if(ev.type == EVENT_MOUSE_PUSH)
  285. handled = mousePush(ev.x, ev.y, ev.getWindowManager())
  286. ;
  287. else if(ev.type == EVENT_MOUSE_RELEASE)
  288. handled = mouseRelease(ev.x, ev.y, ev.getWindowManager())
  289. ;
  290. else if(ev.type == EVENT_MOUSE_SCROLL)
  291. handled = mouseScroll(ev.x, ev.y, ev.getWindowManager())
  292. ;
  293. else if(ev.type == EVENT_KEY_DOWN)
  294. handled = keyDown(ev.key, ev.keyMask, ev.getWindowManager())
  295. ;
  296. else if(ev.type == EVENT_KEY_UP)
  297. handled = keyUp(ev.key, ev.keyMask, ev.getWindowManager())
  298. ;
  299. else return false;
  300. return callCallbacks(ev) || handled;
  301. }
  302. bool canFocus () const { return (_eventMask & EVENT_FOCUS) != 0; }
  303. bool canUnfocus () const { return (_eventMask & EVENT_UNFOCUS) != 0; }
  304. bool canMouseEnter () const { return (_eventMask & EVENT_MOUSE_ENTER) != 0; }
  305. bool canMouseOver () const { return (_eventMask & EVENT_MOUSE_OVER) != 0; }
  306. bool canMouseLeave () const { return (_eventMask & EVENT_MOUSE_LEAVE) != 0; }
  307. bool canMouseDrag () const { return (_eventMask & EVENT_MOUSE_DRAG) != 0; }
  308. bool canMousePush () const { return (_eventMask & EVENT_MOUSE_PUSH) != 0; }
  309. bool canMouseRelease () const { return (_eventMask & EVENT_MOUSE_RELEASE) != 0; }
  310. bool canMouseScroll () const { return (_eventMask & EVENT_MOUSE_SCROLL) != 0; }
  311. bool canKeyDown () const { return (_eventMask & EVENT_KEY_DOWN) != 0; }
  312. bool canKeyUp () const { return (_eventMask & EVENT_KEY_UP) != 0; }
  313. private:
  314. unsigned int _eventMask;
  315. CallbackList _callbacks;
  316. };
  317. }
  318. #endif