1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield
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.
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.
14// Code by: Jeremy Moles (cubicool) 2007-2008
16#ifndef OSGWIDGET_EVENT_INTERFACE
17#define OSGWIDGET_EVENT_INTERFACE
21#include <osg/observer_ptr>
22#include <osg/Referenced>
24#include <osgWidget/Export>
36 EVENT_UNFOCUS = 0x0002,
37 EVENT_MOUSE_ENTER = 0x0004,
38 EVENT_MOUSE_OVER = 0x0008,
39 EVENT_MOUSE_LEAVE = 0x0010,
40 EVENT_MOUSE_DRAG = 0x0020,
41 EVENT_MOUSE_PUSH = 0x0040,
42 EVENT_MOUSE_RELEASE = 0x0080,
43 EVENT_MOUSE_SCROLL = 0x0100,
44 EVENT_KEY_DOWN = 0x0200,
45 EVENT_KEY_UP = 0x0400,
49// Helpful wrapper around using the raw types, since it often doesn't make sense to
50// use some without the others.
53 EVENT_MASK_FOCUS = EVENT_FOCUS | EVENT_UNFOCUS,
54 EVENT_MASK_MOUSE_MOVE = EVENT_MOUSE_ENTER | EVENT_MOUSE_OVER | EVENT_MOUSE_LEAVE,
55 EVENT_MASK_MOUSE_CLICK = EVENT_MOUSE_PUSH | EVENT_MOUSE_RELEASE,
56 EVENT_MASK_MOUSE_DRAG = EVENT_MASK_MOUSE_MOVE | EVENT_MASK_MOUSE_CLICK | EVENT_MOUSE_DRAG,
57 EVENT_MASK_KEY = EVENT_KEY_UP | EVENT_KEY_DOWN
60class OSGWIDGET_EXPORT Event
69 Event(WindowManager* wm, EventType _type = EVENT_NONE):
81 Event& makeType(EventType _type) {
82 if(_type != EVENT_NONE) type = _type;
87 Event& makeMouse(double _x, double _y, EventType _type = EVENT_NONE) {
91 if(_type != EVENT_NONE) type = _type;
96 Event& makeKey(int _key, int _keyMask, EventType _type = EVENT_NONE) {
100 if(_type != EVENT_NONE) type = _type;
105 WindowManager* getWindowManager() { return _wm; }
107 const WindowManager* getWindowManager() const {
111 Window* getWindow() {
115 const Window* getWindow() const {
119 Widget* getWidget() {
123 const Widget* getWidget() const {
131 const void* getData() const {
135 void setData(void* data) {
141 friend class WindowManager;
151// The Callback interface was inspired by the CEGUI project:
153// http://www.cegui.org.uk/wiki/index.php/Main_Page
155// It's a great little way to cleanly implement callbacks for events, although
156// I did change the names a bit to make them more appropriate for OSG. MANY THANKS
157// to the CEGUI project!
159// The CallbackInterface, which the highest-level functor keeps a pointer to.
160struct CallbackInterface: public osg::Referenced
162 virtual ~CallbackInterface() {}
164 virtual const char* className() const { return "osgWidget::CallbackInterface"; }
166 virtual bool operator()(Event&) = 0;
169// The object that facilitates a class method as a callback.
171class ObjectCallback: public CallbackInterface
174 typedef bool (T::*ObjectCallbackType)(Event&);
176 ObjectCallback(ObjectCallbackType callback, T* obj):
178 _callback (callback) {}
180 virtual bool operator()(Event& ev) {
181 return (_object->*_callback)(ev);
186 ObjectCallbackType _callback;
189// The object that facilitates general functions as callbacks.
191class FunctionCallback: public CallbackInterface
194 FunctionCallback(T* callback):
195 _callback(callback) {
198 virtual bool operator()(Event& ev) {
199 return (*_callback)(ev);
205// The highlevel functor.
206class OSGWIDGET_EXPORT Callback: public osg::Referenced
209 Callback(): _type(EVENT_NONE), _data(0), _callback(0) {}
210 Callback(const Callback& rhs): osg::Referenced(rhs), _type(rhs._type), _data(rhs._data), _callback(rhs._callback) {}
212 virtual const char* className() const { return "osgWidget::Callback"; }
214 // The more traditional style of OSG Callbacks.
215 Callback(EventType type, void* data=0):
221 // Creates a Callback that is bound to a member function.
223 Callback(bool (T::*function)(Event&), T* obj, EventType type, void* data=0):
226 _callback (new ObjectCallback<T>(function, obj)) {
229 // Creates a Callback that is bound to a functor pointer.
231 Callback(T* functor, EventType type, void* data=0):
234 _callback (new FunctionCallback<T>(functor)) {
237 virtual ~Callback() {}
239 virtual bool operator()(Event& ev) {
240 if(!_callback) return false;
242 return (*_callback)(ev);
245 EventType getType() const {
253 const void* getData() const {
261 // We use a ref_ptr here so that we don't have to worry about memory.
262 osg::ref_ptr<CallbackInterface> _callback;
267class OSGWIDGET_EXPORT EventInterface
270 EventInterface(): _eventMask(EVENT_NONE) {}
272 EventInterface(const EventInterface& ei):
273 _eventMask (ei._eventMask),
274 _callbacks (ei._callbacks) {}
276 virtual ~EventInterface() {}
278 // These functions take as their final argument the WindowManager which issued the
279 // request. This is sometimes useful to get information about key state, etc.
281 // Notify the EventInterface object that is has been focused or unfocused; since
282 // this isn't always bound to a mouse event (i.e., if you want to be able to use
283 // the TAB key to focus), we need separate events here.
284 virtual bool focus (const WindowManager*) { return false; }
285 virtual bool unfocus (const WindowManager*) { return false; }
287 // Mouse events, pretty self-explanatory.
288 virtual bool mouseEnter (double, double, const WindowManager*) { return false; }
289 virtual bool mouseOver (double, double, const WindowManager*) { return false; }
290 virtual bool mouseLeave (double, double, const WindowManager*) { return false; }
291 virtual bool mouseDrag (double, double, const WindowManager*) { return false; }
292 virtual bool mousePush (double, double, const WindowManager*) { return false; }
293 virtual bool mouseRelease (double, double, const WindowManager*) { return false; }
294 virtual bool mouseScroll (double, double, const WindowManager*) { return false; }
296 // These functions pass the osgGA::GUIEventAdapter::KeySymbol and KeyModMask and,
297 // as above, the WindowManager.
298 virtual bool keyDown (int, int, const WindowManager*) { return false; }
299 virtual bool keyUp (int, int, const WindowManager*) { return false; }
301 void setEventMask(unsigned int mask) {
305 void addEventMask(unsigned int mask) {
309 void removeEventMask(unsigned int mask) {
313 unsigned int getEventMask() const {
317 typedef std::list<osg::ref_ptr<Callback> > CallbackList;
319 inline CallbackList& getCallbacks() { return _callbacks; }
320 inline const CallbackList& getCallbacks() const { return _callbacks; }
322 void addCallback(Callback* cb) {
323 _callbacks.push_back(cb);
326 bool callCallbacks(Event& ev) {
327 if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
329 for(CallbackList::iterator i = _callbacks.begin(); i != _callbacks.end(); i++) {
330 // This is the OLD method; testing a new method below.
331 // if(i->getType() == ev.type && (*i)(ev)) return true;
333 if(i->get()->getType() & ev.type) {
334 ev.setData(i->get()->getData());
336 if((*i->get())(ev)) return true;
343 bool callMethodAndCallbacks(Event& ev) {
344 if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
346 bool handled = false;
348 if(ev.type == EVENT_FOCUS) handled = focus(ev.getWindowManager());
350 else if(ev.type == EVENT_UNFOCUS) handled = unfocus(ev.getWindowManager());
352 else if(ev.type == EVENT_MOUSE_ENTER)
353 handled = mouseEnter(ev.x, ev.y, ev.getWindowManager())
356 else if(ev.type == EVENT_MOUSE_OVER)
357 handled = mouseOver(ev.x, ev.y, ev.getWindowManager())
360 else if(ev.type == EVENT_MOUSE_LEAVE)
361 handled = mouseLeave(ev.x, ev.y, ev.getWindowManager())
364 else if(ev.type == EVENT_MOUSE_DRAG)
365 handled = mouseDrag(ev.x, ev.y, ev.getWindowManager())
368 else if(ev.type == EVENT_MOUSE_PUSH)
369 handled = mousePush(ev.x, ev.y, ev.getWindowManager())
372 else if(ev.type == EVENT_MOUSE_RELEASE)
373 handled = mouseRelease(ev.x, ev.y, ev.getWindowManager())
376 else if(ev.type == EVENT_MOUSE_SCROLL)
377 handled = mouseScroll(ev.x, ev.y, ev.getWindowManager())
380 else if(ev.type == EVENT_KEY_DOWN)
381 handled = keyDown(ev.key, ev.keyMask, ev.getWindowManager())
384 else if(ev.type == EVENT_KEY_UP)
385 handled = keyUp(ev.key, ev.keyMask, ev.getWindowManager())
390 return callCallbacks(ev) || handled;
393 bool canFocus () const { return (_eventMask & EVENT_FOCUS) != 0; }
394 bool canUnfocus () const { return (_eventMask & EVENT_UNFOCUS) != 0; }
396 bool canMouseEnter () const { return (_eventMask & EVENT_MOUSE_ENTER) != 0; }
397 bool canMouseOver () const { return (_eventMask & EVENT_MOUSE_OVER) != 0; }
398 bool canMouseLeave () const { return (_eventMask & EVENT_MOUSE_LEAVE) != 0; }
399 bool canMouseDrag () const { return (_eventMask & EVENT_MOUSE_DRAG) != 0; }
400 bool canMousePush () const { return (_eventMask & EVENT_MOUSE_PUSH) != 0; }
401 bool canMouseRelease () const { return (_eventMask & EVENT_MOUSE_RELEASE) != 0; }
402 bool canMouseScroll () const { return (_eventMask & EVENT_MOUSE_SCROLL) != 0; }
404 bool canKeyDown () const { return (_eventMask & EVENT_KEY_DOWN) != 0; }
405 bool canKeyUp () const { return (_eventMask & EVENT_KEY_UP) != 0; }
409 unsigned int _eventMask;
410 CallbackList _callbacks;