#ifndef GENERATE_CALLBACK_H
#define GENERATE_CALLBACK_H
#include <iostream>
#include <boost/signal.hpp>
#include <boost/bind.hpp>
/*
* These macros generate generate support for callbacks with various numbers of arguments.
* For example, invoke GENERATE_CALLBACK0(MouseClicked) in your button class description
* to generate support for mouse click listeners. Other classes will then be able to call
* the public addMouseClickedListener methods that it generates. The only other thing that
* you will need to do in your observable class is to call the generated fireMouseClicked
* method when you detect a mouse click. It will notify any associated listeners.
*
* For a more interesting example, invoke GENERATE_CALLBACK2(MouseMoved, S32, S32)
* to generate support for mouse tracking callbacks that take X and Y position arguments.
* Just call fireMouseMoved(x, y) for each mouse movement event that you want to send.
*
* To implement listeners to such an observable class, you can either connect any method
* having the appropriate signature via the low-level addMouseClickListener(Boost::slot)
* method or call the high-level addMouseClickListener(MouseClickListener) method with an
* instance of the generated MouseClickedListener class that implements the
* virtual onMouseClicked method.
*
* Currently only zero, one, and two argument callbacks are implemented but more can be
* trivially added if needed by following the pattern.
*
* Author: Melinda Green - Superliminal Software
*/
#define GENERATE_CALLBACK0(NAME) \
private: typedef boost::signal<void()> NAME##Sig; \
public: typedef NAME##Sig::slot_type NAME##_slot_t; \
private: NAME##Sig NAME##_sig; \
public: class NAME##Listener : public boost::signals::trackable { public: virtual void on##NAME()=0; public: virtual ~NAME##Listener(){} }; \
public: boost::signals::connection add##NAME##Listener(NAME##_slot_t slot) { return NAME##_sig.connect(slot); } \
public: void add##NAME##Listener(NAME##Listener *l) { add##NAME##Listener(boost::bind(&NAME##Listener::on##NAME, l)); } \
protected: void fire##NAME() { NAME##_sig(); }
#define GENERATE_CALLBACK1(NAME, ARG1_T) \
private: typedef boost::signal<void(ARG1_T)> NAME##Sig; \
public: typedef NAME##Sig::slot_type NAME##_slot_t; \
private: NAME##Sig NAME##_sig; \
public: class NAME##Listener : public boost::signals::trackable { public: virtual void on##NAME(ARG1_T data1)=0; public: virtual ~NAME##Listener(){} }; \
public: boost::signals::connection add##NAME##Listener(NAME##_slot_t slot) { return NAME##_sig.connect(slot); } \
public: void add##NAME##Listener(NAME##Listener *l) { add##NAME##Listener(boost::bind(&NAME##Listener::on##NAME, l, _1)); } \
protected: void fire##NAME(ARG1_T data1) { NAME##_sig(data1); }
#define GENERATE_CALLBACK2(NAME, ARG1_T, ARG2_T) \
private: typedef boost::signal<void(ARG1_T, ARG2_T)> NAME##Sig; \
public: typedef NAME##Sig::slot_type NAME##_slot_t; \
private: NAME##Sig NAME##_sig; \
public: class NAME##Listener : public boost::signals::trackable { public: virtual void on##NAME(ARG1_T data1, ARG2_T data2)=0; public: virtual ~NAME##Listener(){} }; \
public: boost::signals::connection add##NAME##Listener(NAME##_slot_t slot) { return NAME##_sig.connect(slot); } \
public: void add##NAME##Listener(NAME##Listener *l) { add##NAME##Listener(boost::bind(&NAME##Listener::on##NAME, l, _1, _2)); } \
protected: void fire##NAME(ARG1_T data1, ARG2_T data2) { NAME##_sig(data1, data2); }
#endif // GENERATE_CALLBACK_H