I heard you mention Events? I wrote an event mechanism that someone might like. It is templated and allows users to pass pointers to member functions as handlers (works sort of like .NET event handling with delegates). It uses RAII (RAAI? I can never remember the acronym) principles to make sure that all handlers are cleaned up properly. Feel free to use, refuse, or misuse as you see fit. Hope I can help.
the Event.h is all you need. EventClient.cpp is just a test/example. You will need to enable RTTI.
Enjoy
-- Rick
On 11/2/06, Robert Osfield <[EMAIL PROTECTED]
> wrote:
On 11/2/06, Robert Osfield < [EMAIL PROTECTED]> wrote:
> Perhaps its time for me to refactor the classes, placing them in their
> own osgViewer directory, rather than just hanging off the coat tails
> of an old and tired osgGA library. The upshot of this would be that
> the Xcode projects will need a new project added, but no mods to
> osgGA.
>
> I'll do this refactor today.
It's done and now checked in. Right osgViewer is very basic it just contains
include/osgViewer/SimpleViewer
include/osgViewer/GraphicsWindow
And the standard Export and Version files.
Eventually functionality that is currently in osgGA will be replicated
in osgViewer, some of the classes will map across easily, others will
need a major refactoring to make them properly extensible/reusable.
Candidates are classes like Event, EventHandler, EventQueue and
EventVisitor and the manipulators, once these classes are in place the
dependency on osgGA will disappear.
We have to take things one step at a time though, so if we can reuse
stuff from osgGA to get us up and running quicker then this is what
I'll do. OpenSceneGraph-1.3 will have a basic osgViewer in place, but
will still rely upon osgGA.
Robert.
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/
#ifndef __Event_Included_ #define __Event_Included_ #include <list>
class IEvent
{
protected:
class IEventHandler;
public:
virtual ~IEvent(){}
class HandlerList
{
friend IEvent::IEventHandler;
public:
~HandlerList();
private:
std::list<IEvent::IEventHandler*> _handlerList;
void AddEventHandler(IEvent::IEventHandler*
eh){_handlerList.push_back(eh);}
void RemoveEventHandler(IEvent::IEventHandler*
eh){_handlerList.remove(eh);}
};
protected:
class IEventHandler
{
public:
IEventHandler(IEvent& event, IEvent::HandlerList& ehl) :
_event(event), _ehl(&ehl) {_ehl->AddEventHandler(this);}
virtual ~IEventHandler() {if (_ehl)
_ehl->RemoveEventHandler(this);}
private:
IEvent::HandlerList* _ehl;
IEvent& _event;
friend HandlerList;
};
virtual void RemoveEventHandler(IEventHandler* eh) = 0;
friend HandlerList;
};
inline IEvent::HandlerList::~HandlerList()
{
std::list<IEvent::IEventHandler*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end(); ++pos)
{
IEventHandler* eh = *pos;
eh->_ehl = NULL; // Set to NULL to avoid
circular problems
IEvent& event = eh->_event;
event.RemoveEventHandler(eh); // Note that this will DELETE
the eh
}
_handlerList.clear();
}
class Event0 : public IEvent
{
public:
virtual ~Event0() {ClearAllHandlers();}
void ClearAllHandlers()
{
std::list<IEventHandler0*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler0* eh = *pos;
delete eh;
}
_handlerList.clear();
}
void Fire()
{
std::list<IEventHandler0*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end(); )
{
IEventHandler0* eh = *pos;
++pos; // Placed here in case Firing the event removes
this element
eh->Fire();
}
}
template<class T>
void Subscribe(IEvent::HandlerList& ehl, T& client, void
(T::*delegate)())
{_handlerList.push_back(new EventHandler0<T>(*this, ehl,
client, delegate));}
template<class T>
void Remove(T& client, void (T::*delegate)())
{
std::list<IEventHandler0*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
EventHandler0<T>* posPtr =
dynamic_cast<EventHandler0<T>*>(*pos);
if (posPtr)
{
if ((&posPtr->_client == &client) &&
(posPtr->_delegate == delegate))
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
}
protected:
/// Only called from EventHandlerList when it is destroyed
virtual void RemoveEventHandler(IEvent::IEventHandler* eh)
{
std::list<IEventHandler0*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler0* posPtr = *pos;
if (posPtr == eh)
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
private:
class IEventHandler0 : public IEventHandler
{
public:
IEventHandler0(Event0& event, IEvent::HandlerList& ehl) :
IEventHandler(event, ehl) {}
virtual void Fire() = 0;
};
template<class T>
class EventHandler0 : public IEventHandler0
{
public:
EventHandler0(Event0& event, IEvent::HandlerList& ehl, T&
client, void (T::*delegate)()) :
IEventHandler0(event, ehl), _client(client),
_delegate(delegate) {}
virtual void Fire(){(_client.*_delegate)();}
T& _client;
void (T::*_delegate)();
};
std::list<IEventHandler0*> _handlerList;
};
template<class P1>
class Event1 : public IEvent
{
public:
virtual ~Event1() {ClearAllHandlers();}
void ClearAllHandlers()
{
std::list<IEventHandler1*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler1* eh = *pos;
delete eh;
}
_handlerList.clear();
}
void Fire(P1 p1)
{
std::list<IEventHandler1*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end(); )
{
IEventHandler1* eh = *pos;
++pos; // Placed here in case Firing the event removes
this element
eh->Fire(p1);
}
}
template<class T>
void Subscribe(IEvent::HandlerList& ehl, T& client, void
(T::*delegate)(P1 p1))
{_handlerList.push_back(new EventHandler1<T>(*this, ehl,
client, delegate));}
template<class T>
void Remove(T& client, void (T::*delegate)(P1 p1))
{
std::list<IEventHandler1*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
EventHandler1<T>* posPtr =
dynamic_cast<EventHandler1<T>*>(*pos);
if (posPtr)
{
if ((&posPtr->_client == &client) &&
(posPtr->_delegate == delegate))
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
}
protected:
/// Only called from EventHandlerList when it is destroyed
virtual void RemoveEventHandler(IEvent::IEventHandler* eh)
{
std::list<IEventHandler1*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler1* posPtr = *pos;
if (posPtr == eh)
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
private:
class IEventHandler1 : public IEventHandler
{
public:
IEventHandler1(Event1& event, IEvent::HandlerList& ehl) :
IEventHandler(event, ehl) {}
virtual void Fire(P1 p1) = 0;
};
template<class T>
class EventHandler1 : public IEventHandler1
{
public:
EventHandler1(Event1& event, IEvent::HandlerList& ehl, T&
client, void (T::*delegate)(P1 p1)) :
IEventHandler1(event, ehl), _client(client),
_delegate(delegate) {}
virtual void Fire(P1 p1){(_client.*_delegate)(p1);}
T& _client;
void (T::*_delegate)(P1 p1);
};
std::list<IEventHandler1*> _handlerList;
};
template<class P1, class P2>
class Event2 : public IEvent
{
public:
virtual ~Event2() {ClearAllHandlers();}
void ClearAllHandlers()
{
std::list<IEventHandler2*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler2* eh = *pos;
delete eh;
}
_handlerList.clear();
}
void Fire(P1 p1, P2 p2)
{
std::list<IEventHandler2*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end(); )
{
IEventHandler2* eh = *pos;
++pos; // Placed here in case Firing the event removes
this element
eh->Fire(p1, p2);
}
}
template<class T>
void Subscribe(IEvent::HandlerList& ehl, T& client, void
(T::*delegate)(P1 p1, P2 p2))
{_handlerList.push_back(new EventHandler2<T>(*this, ehl,
client, delegate));}
template<class T>
void Remove(T& client, void (T::*delegate)(P1 p1, P2 p2))
{
std::list<IEventHandler2*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
EventHandler2<T>* posPtr =
dynamic_cast<EventHandler2<T>*>(*pos);
if (posPtr)
{
if ((&posPtr->_client == &client) &&
(posPtr->_delegate == delegate))
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
}
protected:
/// Only called from EventHandlerList when it is destroyed
virtual void RemoveEventHandler(IEvent::IEventHandler* eh)
{
std::list<IEventHandler2*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler2* posPtr = *pos;
if (posPtr == eh)
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
private:
class IEventHandler2 : public IEventHandler
{
public:
IEventHandler2(Event2& event, IEvent::HandlerList& ehl) :
IEventHandler(event, ehl) {}
virtual void Fire(P1 p1, P2 p2) = 0;
};
template<class T>
class EventHandler2 : public IEventHandler2
{
public:
EventHandler2(Event2& event, IEvent::HandlerList& ehl, T&
client, void (T::*delegate)(P1 p1, P2 p2)) :
IEventHandler2(event, ehl), _client(client),
_delegate(delegate) {}
virtual void Fire(P1 p1, P2 p2){(_client.*_delegate)(p1, p2);}
T& _client;
void (T::*_delegate)(P1 p1, P2 p2);
};
std::list<IEventHandler2*> _handlerList;
};
template<class P1, class P2, class P3>
class Event3 : public IEvent
{
public:
virtual ~Event3() {ClearAllHandlers();}
void ClearAllHandlers()
{
std::list<IEventHandler3*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler3* eh = *pos;
delete eh;
}
_handlerList.clear();
}
void Fire(P1 p1, P2 p2, P3 p3)
{
std::list<IEventHandler3*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end(); )
{
IEventHandler3* eh = *pos;
++pos; // Placed here in case Firing the event removes
this element
eh->Fire(p1, p2, p3);
}
}
template<class T>
void Subscribe(IEvent::HandlerList& ehl, T& client, void
(T::*delegate)(P1 p1, P2 p2, P3 p3))
{_handlerList.push_back(new EventHandler3<T>(*this, ehl,
client, delegate));}
template<class T>
void Remove(T& client, void (T::*delegate)(P1 p1, P2 p2, P3 p3))
{
std::list<IEventHandler3*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
EventHandler3<T>* posPtr =
dynamic_cast<EventHandler3<T>*>(*pos);
if (posPtr)
{
if ((&posPtr->_client == &client) &&
(posPtr->_delegate == delegate))
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
}
protected:
/// Only called from EventHandlerList when it is destroyed
virtual void RemoveEventHandler(IEvent::IEventHandler* eh)
{
std::list<IEventHandler3*>::iterator pos;
for (pos = _handlerList.begin(); pos != _handlerList.end();
++pos)
{
IEventHandler3* posPtr = *pos;
if (posPtr == eh)
{
pos = _handlerList.erase(pos);
delete posPtr;
}
}
}
private:
class IEventHandler3 : public IEventHandler
{
public:
IEventHandler3(Event3& event, IEvent::HandlerList& ehl) :
IEventHandler(event, ehl) {}
virtual void Fire(P1 p1, P2 p2, P3 p3) = 0;
};
template<class T>
class EventHandler3 : public IEventHandler3
{
public:
EventHandler3(Event3& event, IEvent::HandlerList& ehl, T&
client, void (T::*delegate)(P1 p1, P2 p2, P3 p3)) :
IEventHandler3(event, ehl), _client(client),
_delegate(delegate) {}
virtual void Fire(P1 p1, P2 p2, P3 p3){(_client.*_delegate)(p1,
p2, p3);}
T& _client;
void (T::*_delegate)(P1 p1, P2 p2, P3 p3);
};
std::list<IEventHandler3*> _handlerList;
};
#endif // __Event_Included_// EventClient.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include "Event.h"
using namespace std;
class HasEvent
{
public:
void FireEvent(const char* msg, int i, float f){iChanged.Fire(msg, i,
f);}
Event3<const char*, int, float> iChanged;
};
class HearsEvent
{
public:
HearsEvent(HasEvent& hasEvent, int id) : _hasEvent(hasEvent), _id(id)
{
_hasEvent.iChanged.Subscribe(ehl, *this,
&HearsEvent::EventCallback);
}
void RemoveHandler()
{
_hasEvent.iChanged.Remove(*this, &HearsEvent::EventCallback);
}
HasEvent& _hasEvent;
int _id;
private:
IEvent::HandlerList ehl;
protected:
virtual void EventCallback(const char* msg, int i, float f)
{
cout << "HearsEvent(" << _id << ")::EventCallback(" << msg <<
", " << i << ", " << f << ")" << endl;
}
};
class HearsEvent2 : public HearsEvent
{
public:
HearsEvent2(HasEvent& hasEvent, int id) : HearsEvent(hasEvent, id) {}
protected:
virtual void EventCallback(const char* msg, int i, float f)
{
cout << "HearsEvent2(" << _id << ")::EventCallback(" << msg <<
", " << i << ", " << f << ")" << endl;
HearsEvent::EventCallback(msg, i, f);
RemoveHandler();
}
};
int main(int argc, const char* argv[])
{
cout << "Event Handling Prototype Client" << endl;
cout << "===============================" << endl << endl;
HasEvent has;
HearsEvent hears(has, 1);
HearsEvent2 hears4(has, 4);
{
HearsEvent hears2(has, 2);
cout << "_tmain sending inner" << endl;
has.FireEvent("inner", -12, 3.1416f);
}
cout << "_tmain removing" << endl;
hears.RemoveHandler();
HearsEvent hears3(has, 3);
cout << "_tmain sending" << endl;
has.FireEvent("outer", 15, -1.111);
cout << "_tmain complete" << endl;
return 0;
}
_______________________________________________ osg-users mailing list [email protected] http://openscenegraph.net/mailman/listinfo/osg-users http://www.openscenegraph.org/
