#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