FLTK 1.4.4

Loading...
Searching...
No Matches
fl_callback_macros.H
Go to the documentation of this file.
1/*
2 * Macros for easy callbacks for the Fast Light Tool Kit (FLTK).
3 *
4 * Copyright 2023 by Bill Spitzak and others.
5 *
6 * This library is free software. Distribution and use rights are outlined in
7 * the file "COPYING" which should have been included with this file. If this
8 * file is missing or damaged, see the license at:
9 *
10 * https://www.fltk.org/COPYING.php
11 *
12 * Please see the following page on how to report bugs and issues:
13 *
14 * https://www.fltk.org/bugs.php
15 */
16
17#ifndef _FL_FL_CALLBACK_MACROS_H_
18#define _FL_FL_CALLBACK_MACROS_H_
19
20#include <stdlib.h>
21
27
28#ifdef FL_DOXYGEN
29
77#define FL_FUNCTION_CALLBACK_3(WIDGET, FUNC, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2)
78
122#define FL_METHOD_CALLBACK_1(WIDGET, CLASS, SELF, METH, TYPE0, VALUE0)
123
175#define FL_INLINE_CALLBACK_2(WIDGET, TYPE0, NAME0, VALUE0, TYPE1, NAME1, VALUE1, LAMBDA)
176
177#else // FL_DOXYGEN
178
179/*
180 These two macros make it possible to call macros with names that are created
181 by concatenating the name in x and (in this context) the number in y.
182 */
183#define _FL_CBD_CONCAT_IMPL(x, y) x##y
184#define _FL_CBD_CONCAT(x, y) _FL_CBD_CONCAT_IMPL(x, y)
185
186/*
187 Create a unique name for the derived class based on the current source code
188 line number.
189 */
190#define _FL_CBD_CLASS_NAME _FL_CBD_CONCAT(Fl_Callback_User_Data_,__LINE__)
191
192
193/*
194 These macros create boilerplate code for callbacks to functions and
195 static class methods with up to five arguments.
196
197 This macro invocation for example
198 ```
199 FL_FUNCTION_CALLBACK_2( func_cb_btn_2, hello_2_args_cb,
200 const char *, text, "FLTK",
201 int, number, 2 );
202 ```
203 will generate the following code:
204
205 ```
206 do {
207 class Fl_Callback_User_Data_92 : public Fl_Callback_User_Data {
208 public:
209 const char * p0_;
210 int p1_;
211 static void cb(Fl_Widget *w, void *user_data) {
212 Fl_Callback_User_Data_92 *d = (Fl_Callback_User_Data_92*)user_data;
213 hello_2_args_cb(d->p0_, d->p1_);
214 };
215 Fl_Callback_User_Data_92(const char * p0, int p1)
216 : p0_(p0),
217 p1_(p1)
218 { }
219 };
220 func_cb_btn_2->callback(Fl_Callback_User_Data_92::cb,
221 new Fl_Callback_User_Data_92("FLTK", 2),
222 true);
223 } while(0)
224 ```
225
226 Clicking the Fl_Button `func_cb_btn_2` will call `hello_2_args_cb("FLTK", 2)`.
227 Deleting the button will also delete the data that was created in our
228 boilerplate code.
229 */
230#define FL_FUNCTION_CALLBACK_5(WIDGET, FUNC, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2, TYPE3, VALUE3, TYPE4, VALUE4) \
231 do { \
232 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
233 public: \
234 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; TYPE3 p3_; TYPE4 p4_; \
235 static void cb(Fl_Widget *w, void *user_data) { \
236 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
237 FUNC(d->p0_, d->p1_, d->p2_, d->p3_, d->p4_); \
238 }; \
239 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1, TYPE2 p2, TYPE3 p3, TYPE4 p4) \
240 : p0_(p0), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { }; \
241 }; \
242 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1, VALUE2, VALUE3, VALUE4), true); \
243 } while(0)
244
245#define FL_FUNCTION_CALLBACK_4(WIDGET, FUNC, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2, TYPE3, VALUE3) \
246 do { \
247 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
248 public: \
249 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; TYPE3 p3_; \
250 static void cb(Fl_Widget *w, void *user_data) { \
251 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
252 FUNC(d->p0_, d->p1_, d->p2_, d->p3_); \
253 }; \
254 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1, TYPE2 p2, TYPE3 p3) \
255 : p0_(p0), p1_(p1), p2_(p2), p3_(p3) { }; \
256 }; \
257 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1, VALUE2, VALUE3), true); \
258 } while(0)
259
260#define FL_FUNCTION_CALLBACK_3(WIDGET, FUNC, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2) \
261 do { \
262 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
263 public: \
264 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; \
265 static void cb(Fl_Widget *w, void *user_data) { \
266 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
267 FUNC(d->p0_, d->p1_, d->p2_); \
268 }; \
269 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1, TYPE2 p2) \
270 : p0_(p0), p1_(p1), p2_(p2) { }; \
271 }; \
272 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1, VALUE2), true); \
273 } while(0)
274
275#define FL_FUNCTION_CALLBACK_2(WIDGET, FUNC, TYPE0, VALUE0, TYPE1, VALUE1) \
276 do { \
277 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
278 public: \
279 TYPE0 p0_; TYPE1 p1_; \
280 static void cb(Fl_Widget *w, void *user_data) { \
281 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
282 FUNC(d->p0_, d->p1_); \
283 }; \
284 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1) \
285 : p0_(p0), p1_(p1) { }; \
286 }; \
287 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1), true); \
288 } while(0)
289
290#define FL_FUNCTION_CALLBACK_1(WIDGET, FUNC, TYPE0, VALUE0) \
291 do { \
292 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
293 public: \
294 TYPE0 p0_; \
295 static void cb(Fl_Widget *w, void *user_data) { \
296 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
297 FUNC(d->p0_); \
298 }; \
299 _FL_CBD_CLASS_NAME(TYPE0 p0) \
300 : p0_(p0) { }; \
301 }; \
302 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0), true); \
303 } while(0)
304
305#define FL_FUNCTION_CALLBACK_0(WIDGET, FUNC) \
306 do { \
307 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
308 public: \
309 static void cb(Fl_Widget *w, void *user_data) { \
310 FUNC(); \
311 }; \
312 _FL_CBD_CLASS_NAME() { }; \
313 }; \
314 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(), true); \
315 } while(0)
316
317/*
318 These macros create boilerplate code for callbacks to class methods
319 with up to five arguments.
320
321 This macro invocation for example
322 ```
323 FL_METHOD_CALLBACK_4(btn,
324 MyWindow, win, resize,
325 int, test_x+10,
326 int, test_y+10,
327 int, 320,
328 int, 400);
329 ```
330 will generate the following code:
331
332 ```
333 do {
334 class Fl_Callback_User_Data_73 : public Fl_Callback_User_Data {
335 public:
336 int p0_;
337 int p1_;
338 int p2_;
339 int p3_;
340 MyWindow *self_;
341 static void cb(Fl_Widget *w, void *user_data) {
342 Fl_Callback_User_Data_73 *d = (Fl_Callback_User_Data_73*)user_data;
343 d->self_->resize(d->p0_, d->p1_, d->p2_, d->p3_);
344 };
345 Fl_Callback_User_Data_73(MyWindow *self, int p0, int p1, int p2, int p3)
346 : self_(self), p0_(p0), p1_(p1), p2_(p2), p3_(p3) { }
347 };
348 btn->callback(Fl_Callback_User_Data_73::cb,
349 new Fl_Callback_User_Data_73(win, test_x+10, test_y+10, 320, 400),
350 true);
351 } while(0);
352 ```
353
354 Clicking the Fl_Button `btn` will call
355 `win->resize(test_x+10, test_y+10, 320, 400);`.
356 Deleting the button will also delete the data that was created in our
357 boilerplate code.
358 */
359
360#define FL_METHOD_CALLBACK_5(WIDGET, CLASS, SELF, METHOD, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2, TYPE3, VALUE3, TYPE4, VALUE4) \
361 do { \
362 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
363 public: \
364 CLASS *self_; \
365 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; TYPE3 p3_; TYPE4 p4_; \
366 static void cb(Fl_Widget *w, void *user_data) { \
367 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
368 d->self_->METHOD(d->p0_, d->p1_, d->p2_, d->p3_, d->p4_); \
369 }; \
370 _FL_CBD_CLASS_NAME(CLASS *self, TYPE0 p0, TYPE1 p1, TYPE2 p2, TYPE3 p3, TYPE4 p4) \
371 : self_(self), p0_(p0), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { }; \
372 }; \
373 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(SELF, VALUE0, VALUE1, VALUE2, VALUE3, VALUE4), true); \
374 } while(0)
375
376#define FL_METHOD_CALLBACK_4(WIDGET, CLASS, SELF, METHOD, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2, TYPE3, VALUE3) \
377 do { \
378 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
379 public: \
380 CLASS *self_; \
381 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; TYPE3 p3_; \
382 static void cb(Fl_Widget *w, void *user_data) { \
383 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
384 d->self_->METHOD(d->p0_, d->p1_, d->p2_, d->p3_); \
385 }; \
386 _FL_CBD_CLASS_NAME(CLASS *self, TYPE0 p0, TYPE1 p1, TYPE2 p2, TYPE3 p3) \
387 : self_(self), p0_(p0), p1_(p1), p2_(p2), p3_(p3) { }; \
388 }; \
389 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(SELF, VALUE0, VALUE1, VALUE2, VALUE3), true); \
390 } while(0)
391
392#define FL_METHOD_CALLBACK_3(WIDGET, CLASS, SELF, METHOD, TYPE0, VALUE0, TYPE1, VALUE1, TYPE2, VALUE2) \
393 do { \
394 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
395 public: \
396 CLASS *self_; \
397 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; \
398 static void cb(Fl_Widget *w, void *user_data) { \
399 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
400 d->self_->METHOD(d->p0_, d->p1_, d->p2_); \
401 }; \
402 _FL_CBD_CLASS_NAME(CLASS *self, TYPE0 p0, TYPE1 p1, TYPE2 p2) \
403 : self_(self), p0_(p0), p1_(p1), p2_(p2) { }; \
404 }; \
405 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(SELF, VALUE0, VALUE1, VALUE2), true); \
406 } while(0)
407
408#define FL_METHOD_CALLBACK_2(WIDGET, CLASS, SELF, METHOD, TYPE0, VALUE0, TYPE1, VALUE1) \
409 do { \
410 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
411 public: \
412 CLASS *self_; \
413 TYPE0 p0_; TYPE1 p1_; \
414 static void cb(Fl_Widget *w, void *user_data) { \
415 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
416 d->self_->METHOD(d->p0_, d->p1_); \
417 }; \
418 _FL_CBD_CLASS_NAME(CLASS *self, TYPE0 p0, TYPE1 p1) \
419 : self_(self), p0_(p0), p1_(p1) { }; \
420 }; \
421 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(SELF, VALUE0, VALUE1), true); \
422 } while(0)
423
424#define FL_METHOD_CALLBACK_1(WIDGET, CLASS, SELF, METHOD, TYPE0, VALUE0) \
425 do { \
426 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
427 public: \
428 CLASS *self_; \
429 TYPE0 p0_; \
430 static void cb(Fl_Widget *w, void *user_data) { \
431 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
432 d->self_->METHOD(d->p0_); \
433 }; \
434 _FL_CBD_CLASS_NAME(CLASS *self, TYPE0 p0) \
435 : self_(self), p0_(p0) { }; \
436 }; \
437 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(SELF, VALUE0), true); \
438 } while(0)
439
440#define FL_METHOD_CALLBACK_0(WIDGET, CLASS, SELF, METHOD) \
441 do { \
442 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
443 public: \
444 CLASS *self_; \
445 static void cb(Fl_Widget *w, void *user_data) { \
446 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
447 d->self_->METHOD(); \
448 }; \
449 _FL_CBD_CLASS_NAME(CLASS *self) \
450 : self_(self) { }; \
451 }; \
452 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(SELF), true); \
453 } while(0)
454
455/*
456 These macros create boilerplate code for callback functions inlined into
457 the widget creation code (similar to lambda functions in C++11 and up)
458 with up to five arguments.
459
460 This macro invocation for example
461 ```
462 FL_INLINE_CALLBACK_2( // callback has two parameters
463 btn, // attach callback to this button
464 const char *, text, "FLTK", // first parameter (type, name, value)
465 int, number, 2, // second parameter
466 { // function body
467 fl_message("We received the message %s with %d!", text, number);
468 }
469 );
470 ```
471 will generate the following code:
472 ```
473 do {
474 class Fl_Callback_User_Data_133 : public Fl_Callback_User_Data {
475 public:
476 const char * p0_; // store first parameter here
477 int p1_; // store second parameter here
478 // lambda style function
479 static void fn(const char * text, int number ) {
480 fl_message("We received the message %s with %d!", text, number);
481 };
482 // FLTK style callback
483 static void cb(Fl_Widget *w, void *user_data) {
484 Fl_Callback_User_Data_133 *d = (Fl_Callback_User_Data_133*)user_data;
485 fn(d->p0_, d->p1_);
486 };
487 // class constructor
488 Fl_Callback_User_Data_133(const char * p0, int p1)
489 : p0_(p0), // copy parameter 0
490 p1_(p1) // copy parameter 1
491 { } // constructor body
492 };
493 // connect our class to the widget callback
494 btn->callback(Fl_Callback_User_Data_133::cb,
495 new Fl_Callback_User_Data_133("FLTK", 2),
496 true);
497 } while(0); // user code adds semicolon
498 ```
499
500 Clicking the Fl_Button `btn` will call
501 `fl_message("We received the message %s with %d!", "FLTK", 2);`.
502 Deleting the button will also delete the data that was created in our
503 boilerplate code.
504 */
505
506#define FL_INLINE_CALLBACK_5(WIDGET, TYPE0, NAME0, VALUE0, TYPE1, NAME1, VALUE1, TYPE2, NAME2, VALUE2, TYPE3, NAME3, VALUE3, TYPE4, NAME4, VALUE4, LAMBDA) \
507 do { \
508 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
509 public: \
510 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; TYPE3 p3_; TYPE4 p4_; \
511 static void fn(TYPE0 NAME0, TYPE1 NAME1, TYPE2 NAME2, TYPE3 NAME3, TYPE4 NAME4) \
512 LAMBDA; \
513 static void cb(Fl_Widget *w, void *user_data) { \
514 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
515 _FL_CBD_CLASS_NAME::fn(d->p0_, d->p1_, d->p2_, d->p3_, d->p4_); \
516 }; \
517 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1, TYPE2 p2, TYPE3 p3, TYPE4 p4) \
518 : p0_(p0), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { }; \
519 }; \
520 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1, VALUE2, VALUE3, VALUE4), true); \
521 } while(0)
522
523#define FL_INLINE_CALLBACK_4(WIDGET, TYPE0, NAME0, VALUE0, TYPE1, NAME1, VALUE1, TYPE2, NAME2, VALUE2, TYPE3, NAME3, VALUE3, LAMBDA) \
524 do { \
525 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
526 public: \
527 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; TYPE3 p3_; \
528 static void fn(TYPE0 NAME0, TYPE1 NAME1, TYPE2 NAME2, TYPE3 NAME3) \
529 LAMBDA; \
530 static void cb(Fl_Widget *w, void *user_data) { \
531 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
532 _FL_CBD_CLASS_NAME::fn(d->p0_, d->p1_, d->p2_, d->p3_); \
533 }; \
534 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1, TYPE2 p2, TYPE3 p3) \
535 : p0_(p0), p1_(p1), p2_(p2), p3_(p3) { }; \
536 }; \
537 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1, VALUE2, VALUE3), true); \
538 } while(0)
539
540#define FL_INLINE_CALLBACK_3(WIDGET, TYPE0, NAME0, VALUE0, TYPE1, NAME1, VALUE1, TYPE2, NAME2, VALUE2, LAMBDA) \
541 do { \
542 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
543 public: \
544 TYPE0 p0_; TYPE1 p1_; TYPE2 p2_; \
545 static void fn(TYPE0 NAME0, TYPE1 NAME1, TYPE2 NAME2) \
546 LAMBDA; \
547 static void cb(Fl_Widget *w, void *user_data) { \
548 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
549 _FL_CBD_CLASS_NAME::fn(d->p0_, d->p1_, d->p2_); \
550 }; \
551 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1, TYPE2 p2) \
552 : p0_(p0), p1_(p1), p2_(p2) { }; \
553 }; \
554 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1, VALUE2), true); \
555 } while(0)
556
557#define FL_INLINE_CALLBACK_2(WIDGET, TYPE0, NAME0, VALUE0, TYPE1, NAME1, VALUE1, LAMBDA) \
558 do { \
559 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
560 public: \
561 TYPE0 p0_; TYPE1 p1_; \
562 static void fn(TYPE0 NAME0, TYPE1 NAME1) \
563 LAMBDA; \
564 static void cb(Fl_Widget *w, void *user_data) { \
565 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
566 _FL_CBD_CLASS_NAME::fn(d->p0_, d->p1_); \
567 }; \
568 _FL_CBD_CLASS_NAME(TYPE0 p0, TYPE1 p1) \
569 : p0_(p0), p1_(p1) { }; \
570 }; \
571 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0, VALUE1), true); \
572 } while(0)
573
574#define FL_INLINE_CALLBACK_1(WIDGET, TYPE0, NAME0, VALUE0, LAMBDA) \
575 do { \
576 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
577 public: \
578 TYPE0 p0_; \
579 static void fn(TYPE0 NAME0) \
580 LAMBDA; \
581 static void cb(Fl_Widget *w, void *user_data) { \
582 _FL_CBD_CLASS_NAME *d = (_FL_CBD_CLASS_NAME*)user_data; \
583 _FL_CBD_CLASS_NAME::fn(d->p0_); \
584 }; \
585 _FL_CBD_CLASS_NAME(TYPE0 p0) \
586 : p0_(p0) { }; \
587 }; \
588 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(VALUE0), true); \
589 } while(0)
590
591#define FL_INLINE_CALLBACK_0(WIDGET, LAMBDA) \
592 do { \
593 class _FL_CBD_CLASS_NAME : public Fl_Callback_User_Data { \
594 public: \
595 static void fn() \
596 LAMBDA; \
597 static void cb(Fl_Widget *w, void *user_data) { \
598 _FL_CBD_CLASS_NAME::fn(); \
599 }; \
600 _FL_CBD_CLASS_NAME() { }; \
601 }; \
602 WIDGET->callback(_FL_CBD_CLASS_NAME::cb, new _FL_CBD_CLASS_NAME(), true); \
603 } while(0)
604
605#endif // FL_DOXYGEN
606
607#endif /* !_FL_FL_CALLBACK_MACROS_H_ */