EventHandling: .h

Q: What is this ugly C-like sorcery?

A: This is a header-only implementation of an event library. These macros and classes ease the use of event handling; no need to keep track of handler names and registration; just use these macros! (and don’t look at what’s under the hood, please)

How to use it?

Well, if you don’t have to, this is made just for GUI purposes. Else:

Defining new events

Events are structs inheriting from Event. To define a new one, simply inherit from it, add the required data and call the REGISTER_EVENT(x) like so:

struct MouseDownEvent : public Event {
        MouseDownEvent(int x, int y) : mX(x), mY(y) { REGISTER_EVENT(MouseDownEvent) }

        int mX, mY;
};

(note the placement of the REGISTER_EVENT(x) macro (it’s in the constructor))

Note

Event names have to end with Event; this is a technical limitation of the library.

Setting up listeners

Every class that recieves events is a listener. To set up one, use the LISTENER and LISTENER_INIT(x) macros:

class MyClass {
        LISTENER;
        ...
        MyClass() : ..., LISTENER_INIT(forwardEventToChilldren), ... {}
}

where forwardEventToChildren is a function with the signature of:

bool forwardEventToChildren(Event* e);

which raises the event to all or some of the children of your listener class.

Note

Pass nullptr if you are a bad parent and don’t want to pass events to children.

Setting up handlers

Simply use the EVENT_HANDLER(x, y) macros in your class’ body:

...
EVENT_HANDLER(MouseDown, {
        event->something = Something();
        if (doSomethingWith(event)) {
                return true;
        }
        return false
});

You can see that the name of the handler consists of the name of the event it handles without the Event part at the end. For example, a handler that handles SomethingHappensEvent will pass the name SomethingHappens to EVENT_HANDLER(x, y).

The handler itself returns a bool. Return true if you were able to handle the event (or if you ignored it). The return value will be forwarded back up as the return value of the RAISE_EVENT macro.

Inside the macro’s block, you now have access to a pointer pre-casted to the required derived Event class named event; no need to dynamic_cast anything!

Note

To enable event handling for any specific event, in your constructor do:

...
HANDLES_EVENT(MouseDown);
...
//To stop (temporarily or permanently):
DOES_NOT_HANDLE_EVENT(MouseDown);

Raising Events

Use the RAISE_EVENT(x, y) macro like so:

RAISE_EVENT(someObjectInstancePointer, new MouseDown(132, 168));

The first argument is the object instance you wish to send the event to, and the second is the event itself.

Notes

There is also a MASTER_* set of macros that allow whole parent systems to operate as listeners outside of any class. Its usage is similar to the normal set of macros, so check the macros for details if you want to know more.