Guide to the event system
An event system allows communication between unknown parties. By having a standard system a producer can signal events that interested parts may receive. The sender doesn't know who will receive events and the receiver doesn't need to know the concrete sender. The system is typically modeled by the observer pattern [GoF 293].
The event system in OpenEngine consists of a hierarchy of template classes.
The use of templates allows the event system to pass varying structures to varying receivers, all while still performing static type checking.
To use the event system one must make use of several components. We will explain each in turn while referring to the usage of events in the IKeyboard interface.
Event structure
Each event is represented as some data structure. This data structure is event specific and the following is a simple example hereof:
#!cpp
struct SomeEventArg {
int x, y, z; // event data fields
};
We use the post fix arg because the event structure is received as an argument to a event handler method as seen below.
The IKeyboard interface makes use of KeyboardEventArg.
Event handler
The usual usage of the system is to receive events. To do that some custom structure must serve as a handler. The handler must have a method that accepts a single argument corresponding to the type of the event structure. This structure is not restricted to being a handler and may be responsible for other things at the same time.
A simple example could be as follows:
#!cpp
class SomeEventHandler {
public:
void HandleSomeEvent(SomeEventArg event) {
// do something on each received event
}
// ... other class functions ...
};
Event list
For each event to be listened on a list must exist that allows handlers to register them selves.
The list is made with the Event template parametrized by the type of the event structure. The list will usually be a static field of some interface or it could be a global variable.
#!cpp
#include <EventSystem/Event.h>
Event<SomeEventArg> someEvent;
The IKeyboard interface supplies two events. One for up and one for down.
Event listener
Finally we need to bind the handler to the event. To preserve typing we create a wrapper we call a Listener that couples the handler and the event argument. It is parametrized by the handler class, the event structure. The constructor takes a reference to the handler object and the address of the handler method.
#!cpp
// create an instance of the handler
SomeEventHandler* handler = new SomeEventHandler();
// create a wrapper
Listener<SomeEventHandler, SomeEventArg> someListener
= new Listener<SomeEventHandler, SomeEventArg>(*handler, &SomeEventHandler::HandleSomeEvent);
// bind it to the event
someEvent.Add(someListener);
Sending events
Now triggering an event is as simple as:
#!cpp // create new event date SomeEventArg e; e.x = 1; e.y = 2; e.z = 3; // fire the event someEvent.Notify(e);
All handlers registered to the event will now have the body of their handler functions executed.
