#ifndef FL_CALLBACK_H
#define FL_CALLBACK_H
// EASY HACK TO PLACE CALLBACKS INSIDE OF CLASS AS NON-STATIC FUNCTION:
#define FL_CALLBACK(classname) \
\
typedef void (classname::*cbfun_t)(Fl_Widget*, void*); \
\
typedef struct { \
classname* inst; \
cbfun_t func; \
void* data; \
Fl_Widget* widget; \
} d$; \
\
inline static void x$(Fl_Widget* widget, void* data) { \
CB_DATA* cb_data = (CB_DATA*)data; \
cb_data->widget = widget; \
(cb_data->inst->*(cb_data->func))(cb_data->widget, cb_data->data); \
} \
// EXAMPLE USAGE:
//
//#include <FL/Fl.H>
//#include <FL/Fl_Input.H>
//#include <FL/Fl_Button.H>
//#include <FL/Fl_Return_Button.H>
//#include <FL/Fl_Text_Editor.H>
//#include <FL/Fl_Menu_Bar.H>
//#include <Fl/Fl_Window.H>
//#include <Fl/Fl_Double_Window.H>
//#include <iostream>
//using std::cout;
//
//class EditorWindow : public Fl_Double_Window
//{
//public:
// FL_CALLBACK(EditorWindow);
//
// EditorWindow(int w, int h, const char* t) :
// Fl_Double_Window{w, h, t}
// {
// create_menu();
// }
//
// ~EditorWindow() {
// }
// void create_menu();
//
// Fl_Window* replace_dlg;
// Fl_Input* replace_find;
// Fl_Input* replace_with;
// Fl_Button* replace_all;
// Fl_Return_Button* replace_next;
// Fl_Button* replace_cancel;
// Fl_Text_Editor* editor;
// Fl_Menu_Item* menuitems;
// Fl_Menu_Bar* menubar;
// char search[256];
//
// void cb_new (Fl_Widget* widget, void* data) {cout << "new\n";}
// void cb_open (Fl_Widget* widget, void* data) {cout << "open\n";}
// void cb_insert (Fl_Widget* widget, void* data) {cout << "insert\n";}
// void cb_save (Fl_Widget* widget, void* data) {cout << "save\n";}
// void cb_saveas (Fl_Widget* widget, void* data) {cout << "saveas\n";}
// void cb_view (Fl_Widget* widget, void* data) {cout << "view\n";}
// void cb_close (Fl_Widget* widget, void* data) {cout << "close\n";}
// void cb_quit (Fl_Widget* widget, void* data) {cout << "quit\n";}
// void cb_undo (Fl_Widget* widget, void* data) {cout << "undo\n";}
// void cb_cut (Fl_Widget* widget, void* data) {cout << "cut\n";}
// void cb_copy (Fl_Widget* widget, void* data) {cout << "copy\n";}
// void cb_paste (Fl_Widget* widget, void* data) {cout << "paste\n";}
// void cb_delete (Fl_Widget* widget, void* data) {cout << "delete\n";}
// void cb_find (Fl_Widget* widget, void* data) {cout << "find\n";}
// void cb_find2 (Fl_Widget* widget, void* data) {cout << "find2\n";}
// void cb_replace (Fl_Widget* widget, void* data) {cout << "replace\n";}
// void cb_replace2 (Fl_Widget* widget, void* data) {cout << "replace2\n";}
//};
//
//#include <Fl/Fl_Menu_Item.H>
//#include <Fl/Fl_Menu_Bar.H>
//
//#include "win_first.h"
//
//
//void EditorWindow::create_menu() {
// menuitems = new Fl_Menu_Item[100] {
// { "&File", 0, 0, 0, FL_SUBMENU },
// { "&New File", 0, x$, new d${this, cb_new, nullptr}, 0},
// { "&Open File...", FL_COMMAND + 'o', x$, new d${this, cb_open, nullptr}, 0},
// { "&Insert File...", FL_COMMAND + 'i', x$, new d${this, cb_insert, nullptr}, FL_MENU_DIVIDER},
// { "&Save File", FL_COMMAND + 's', x$, new d${this, cb_save, nullptr}, 0},
// { "Save File &As...", FL_COMMAND + FL_SHIFT + 's', x$, new d${this, cb_saveas, nullptr}, FL_MENU_DIVIDER},
// { "New &View", FL_ALT + 'v', x$, new d${this, cb_view, nullptr}, 0},
// { "&Close View", FL_COMMAND + 'w', x$, new d${this, cb_close, nullptr}, FL_MENU_DIVIDER},
// { "E&xit", FL_COMMAND + 'q', x$, new d${this, cb_quit, nullptr}, 0},
// { 0 },
//
// { "&Edit", 0, 0, 0, FL_SUBMENU },
// { "&Undo", FL_COMMAND + 'z', x$, new d${this, cb_undo, nullptr}, FL_MENU_DIVIDER},
// { "Cu&t", FL_COMMAND + 'x', x$, new d${this, cb_cut, nullptr}, 0},
// { "&Copy", FL_COMMAND + 'c', x$, new d${this, cb_copy, nullptr}, 0},
// { "&Paste", FL_COMMAND + 'v', x$, new d${this, cb_paste, nullptr}, 0},
// { "&Delete", 0, x$, new d${this, cb_delete, nullptr}, 0},
// { 0 } ,
//
// { "&Search", 0, 0, 0, FL_SUBMENU },
// { "&Find...", FL_COMMAND + 'f', x$, new d${this, cb_find, nullptr}, 0},
// { "F&ind Again", FL_COMMAND + 'g', x$, new d${this, cb_find2, nullptr}, 0},
// { "&Replace...", FL_COMMAND + 'r', x$, new d${this, cb_replace, nullptr}, 0},
// { "Re&place Again", FL_COMMAND + 't', x$, new d${this, cb_replace2, nullptr}, 0},
// { 0 },
//
// { 0 }
// };
//
// menubar = new Fl_Menu_Bar (0, 0, 640, 30);
// menubar->copy (menuitems);
//}
#endif
// EASY HACK TO PLACE CALLBACKS INSIDE OF CLASS AS NON-STATIC FUNCTION:
// Requires: C++11
//
// How to Use:
// (1) Add macro to public section:
// FL_CALLBACK(<name of class>);
//
// (2) add callbacks to class as normal non-static member function
//
// (3) When you need a Callback pointer, Use:
// x$
//
// (3) When you need corresponding callback data, Use:
// new d${this, non_static_class_method_callback, data}
//
// Explanation:
//
// x$ is the static callback method that use d$ data to dispatch
// non_static_call_method as callback with given data
//
// Warning:
// use of "new d${...}" is a memory leak ...
// but most user won't notice
// if you don't create too many windows.
// (Also, Operating system will automatically
// garbage collect when the program is closed.)
//
//Suggestions?
// replace 'new $d' with base class function
// that will create 'new $d struct' and garbage collect
// these pointers when the class destructor is called.
//
//======================================================================