root/OpenSceneGraph/trunk/include/osgWidget/EventInterface @ 13041

Revision 13041, 12.3 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
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
14// Code by: Jeremy Moles (cubicool) 2007-2008
15
16#ifndef OSGWIDGET_EVENT_INTERFACE
17#define OSGWIDGET_EVENT_INTERFACE
18
19#include <list>
20#include <osg/ref_ptr>
21#include <osg/observer_ptr>
22#include <osg/Referenced>
23
24#include <osgWidget/Export>
25
26namespace osgWidget {
27
28class WindowManager;
29class Window;
30class Widget;
31
32enum EventType
33{
34    EVENT_NONE          = 0x0000,
35    EVENT_FOCUS         = 0x0001,
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,
46    EVENT_ALL           = 0xFFFF
47};
48
49// Helpful wrapper around using the raw types, since it often doesn't make sense to
50// use some without the others.
51enum EventMask
52{
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
58};
59
60class OSGWIDGET_EXPORT Event
61{
62    public:
63        EventType type;
64        double     x;
65        double     y;
66        int        key;
67        int        keyMask;
68
69        Event(WindowManager* wm, EventType _type = EVENT_NONE):
70        type    (_type),
71        x       (0.0f),
72        y       (0.0f),
73        key     (-1),
74        keyMask (-1),
75        _wm     (wm),
76        _window (0),
77        _widget (0),
78        _data   (0) {
79        }
80
81        Event& makeType(EventType _type) {
82            if(_type != EVENT_NONE) type = _type;
83
84            return *this;
85        }
86
87        Event& makeMouse(double _x, double _y, EventType _type = EVENT_NONE) {
88            x = _x;
89            y = _y;
90
91            if(_type != EVENT_NONE) type = _type;
92
93            return *this;
94        }
95
96        Event& makeKey(int _key, int _keyMask, EventType _type = EVENT_NONE) {
97            key     = _key;
98            keyMask = _keyMask;
99
100            if(_type != EVENT_NONE) type = _type;
101
102            return *this;
103        }
104
105        WindowManager* getWindowManager() { return _wm; }
106
107        const WindowManager* getWindowManager() const {
108            return _wm;
109        }
110
111        Window* getWindow() {
112            return _window;
113        }
114
115        const Window* getWindow() const {
116            return _window;
117        }
118
119        Widget* getWidget() {
120            return _widget;
121        }
122
123        const Widget* getWidget() const {
124            return _widget;
125        }
126
127        void* getData() {
128            return _data;
129        }
130
131        const void* getData() const {
132            return _data;
133        }
134
135        void setData(void* data) {
136            _data = data;
137        }
138
139    protected:
140
141        friend class WindowManager;
142        friend class Window;
143
144        WindowManager* _wm;
145        Window*        _window;
146        Widget*        _widget;
147        void*          _data;
148
149};
150
151// The Callback interface was inspired by the CEGUI project:
152//
153//     http://www.cegui.org.uk/wiki/index.php/Main_Page
154//
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!
158
159// The CallbackInterface, which the highest-level functor keeps a pointer to.
160struct CallbackInterface: public osg::Referenced
161{
162    virtual ~CallbackInterface() {}
163
164    virtual const char* className() const { return "osgWidget::CallbackInterface"; }
165
166    virtual bool operator()(Event&) = 0;
167};
168
169// The object that facilitates a class method as a callback.
170template<typename T>
171class ObjectCallback: public CallbackInterface
172{
173    public:
174        typedef bool (T::*ObjectCallbackType)(Event&);
175
176        ObjectCallback(ObjectCallbackType callback, T* obj):
177        _object   (obj),
178        _callback (callback) {}
179
180        virtual bool operator()(Event& ev) {
181            return (_object->*_callback)(ev);
182        }
183
184    private:
185        T*                 _object;
186        ObjectCallbackType _callback;
187};
188
189// The object that facilitates general functions as callbacks.
190template<typename T>
191class FunctionCallback: public CallbackInterface
192{
193    public:
194        FunctionCallback(T* callback):
195        _callback(callback) {
196        }
197
198        virtual bool operator()(Event& ev) {
199            return (*_callback)(ev);
200        }
201    protected:
202        T* _callback;
203};
204
205// The highlevel functor.
206class OSGWIDGET_EXPORT Callback: public osg::Referenced
207{
208    public:
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) {}
211
212        virtual const char* className() const { return "osgWidget::Callback"; }
213
214        // The more traditional style of OSG Callbacks.
215        Callback(EventType type, void* data=0):
216        _type     (type),
217        _data     (data),
218        _callback (0) {
219        }
220
221        // Creates a Callback that is bound to a member function.
222        template<typename T>
223        Callback(bool (T::*function)(Event&), T* obj, EventType type, void* data=0):
224        _type     (type),
225        _data     (data),
226        _callback (new ObjectCallback<T>(function, obj)) {
227        }
228
229        // Creates a Callback that is bound to a functor pointer.
230        template<typename T>
231        Callback(T* functor, EventType type, void* data=0):
232        _type     (type),
233        _data     (data),
234        _callback (new FunctionCallback<T>(functor)) {
235        }
236
237        virtual ~Callback() {}
238
239        virtual bool operator()(Event& ev) {
240            if(!_callback) return false;
241
242            return (*_callback)(ev);
243        }
244
245        EventType getType() const {
246            return _type;
247        }
248
249        void* getData() {
250            return _data;
251        }
252
253        const void* getData() const {
254            return _data;
255        }
256
257    protected:
258        EventType _type;
259        void*     _data;
260
261        // We use a ref_ptr here so that we don't have to worry about memory.
262        osg::ref_ptr<CallbackInterface> _callback;
263
264};
265
266
267class OSGWIDGET_EXPORT EventInterface
268{
269    public:
270        EventInterface(): _eventMask(EVENT_NONE) {}
271
272        EventInterface(const EventInterface& ei):
273        _eventMask (ei._eventMask),
274        _callbacks (ei._callbacks) {}
275
276        virtual ~EventInterface() {}
277
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.
280
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 seperate events here.
284        virtual bool focus   (const WindowManager*) { return false; }
285        virtual bool unfocus (const WindowManager*) { return false; }
286
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; }
295
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; }
300
301        void setEventMask(unsigned int mask) {
302            _eventMask = mask;
303        }
304
305        void addEventMask(unsigned int mask) {
306            _eventMask |= mask;
307        }
308
309        void removeEventMask(unsigned int mask) {
310            _eventMask ^= mask;
311        }
312
313        unsigned int getEventMask() const {
314            return _eventMask;
315        }
316
317        void addCallback(Callback* cb) {
318            _callbacks.push_back(cb);
319        }
320
321        bool callCallbacks(Event& ev) {
322            if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
323
324            for(CallbackList::iterator i = _callbacks.begin(); i != _callbacks.end(); i++) {
325                // This is the OLD method; testing a new method below.
326                // if(i->getType() == ev.type && (*i)(ev)) return true;
327
328                if(i->get()->getType() & ev.type) {
329                    ev.setData(i->get()->getData());
330
331                    if((*i->get())(ev)) return true;
332                }
333            }
334
335            return false;
336        }
337
338        bool callMethodAndCallbacks(Event& ev) {
339            if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
340
341            bool handled = false;
342
343            if(ev.type == EVENT_FOCUS) handled = focus(ev.getWindowManager());
344
345            else if(ev.type == EVENT_UNFOCUS) handled = unfocus(ev.getWindowManager());
346
347            else if(ev.type == EVENT_MOUSE_ENTER)
348                handled = mouseEnter(ev.x, ev.y, ev.getWindowManager())
349            ;
350
351            else if(ev.type == EVENT_MOUSE_OVER)
352                handled = mouseOver(ev.x, ev.y, ev.getWindowManager())
353            ;
354
355            else if(ev.type == EVENT_MOUSE_LEAVE)
356                handled = mouseLeave(ev.x, ev.y, ev.getWindowManager())
357            ;
358
359            else if(ev.type == EVENT_MOUSE_DRAG)
360                handled = mouseDrag(ev.x, ev.y, ev.getWindowManager())
361            ;
362
363            else if(ev.type == EVENT_MOUSE_PUSH)
364                handled = mousePush(ev.x, ev.y, ev.getWindowManager())
365            ;
366
367            else if(ev.type == EVENT_MOUSE_RELEASE)
368                handled = mouseRelease(ev.x, ev.y, ev.getWindowManager())
369            ;
370
371            else if(ev.type == EVENT_MOUSE_SCROLL)
372                handled = mouseScroll(ev.x, ev.y, ev.getWindowManager())
373            ;
374
375            else if(ev.type == EVENT_KEY_DOWN)
376                handled = keyDown(ev.key, ev.keyMask, ev.getWindowManager())
377            ;
378
379            else if(ev.type == EVENT_KEY_UP)
380                handled = keyUp(ev.key, ev.keyMask, ev.getWindowManager())
381            ;
382
383            else return false;
384
385            return callCallbacks(ev) || handled;
386        }
387
388        bool canFocus   () const { return (_eventMask & EVENT_FOCUS) != 0; }
389        bool canUnfocus () const { return (_eventMask & EVENT_UNFOCUS) != 0; }
390
391        bool canMouseEnter   () const { return (_eventMask & EVENT_MOUSE_ENTER) != 0; }
392        bool canMouseOver    () const { return (_eventMask & EVENT_MOUSE_OVER) != 0; }
393        bool canMouseLeave   () const { return (_eventMask & EVENT_MOUSE_LEAVE) != 0; }
394        bool canMouseDrag    () const { return (_eventMask & EVENT_MOUSE_DRAG) != 0; }
395        bool canMousePush    () const { return (_eventMask & EVENT_MOUSE_PUSH) != 0; }
396        bool canMouseRelease () const { return (_eventMask & EVENT_MOUSE_RELEASE) != 0; }
397        bool canMouseScroll  () const { return (_eventMask & EVENT_MOUSE_SCROLL) != 0; }
398
399        bool canKeyDown () const { return (_eventMask & EVENT_KEY_DOWN) != 0; }
400        bool canKeyUp   () const { return (_eventMask & EVENT_KEY_UP) != 0; }
401
402    private:
403        typedef std::list<osg::observer_ptr<Callback> > CallbackList;
404
405        unsigned int _eventMask;
406        CallbackList _callbacks;
407
408};
409
410}
411
412#endif
Note: See TracBrowser for help on using the browser.