FLUID: Add support for lambda callbacks.
Build and Test / build-linux (push) Has been cancelled
Build and Test / build-wayland (push) Has been cancelled
Build and Test / build-macos (push) Has been cancelled
Build and Test / build-windows (push) Has been cancelled

Starting the callback text with a '[' assumes that
the rest of the callback is a lambda and generates
inlined code for it.
This commit is contained in:
Matthias Melcher
2025-12-22 23:12:25 +01:00
parent d0d2e104e9
commit 33199dab78
5 changed files with 55 additions and 19 deletions
+10 -5
View File
@@ -369,13 +369,18 @@
\image html wp_cpp_callback.png
\image latex wp_cpp_callback.png "" width=7cm
The callback field can be interpreted in two ways. If the callback text is only
a single word, FLUID assumes that this is the name of an external callback
function and declares it in the header as
The callback field can be interpreted in three ways. If the callback text is
only a single word, FLUID assumes that this is the name of an external
callback function and declares it in the header as
`extern void my_button_action(Fl_Button*, void*);`.
Otherwise, FLUID assumes that the text is the body of a C++ callback function
and instead creates a local static callback function. The name of the callback
If the first letter of the callback text is a '[', FLUID expects a lambda
function which will be inlined into the widget creation code. The lambda
signature must be `[](Fl_Widget*, void*)->void { ... }`. The widget pointer
can be casted to another type inside the lambda.
Otherwise, FLUID assumes that the text is the body of a C++ function,
and a local static callback function is created. The name of the callback
function is generated by FLUID and guaranteed to be unique within the file.
```
static void cb_input(Fl_Input *o, void *v) {
+15 -6
View File
@@ -329,7 +329,7 @@ void Menu_Item_Node::write_static(fld::io::Code_Writer& f) {
if (extra_code(n) && isdeclare(extra_code(n)))
f.write_h_once("%s", extra_code(n));
}
if (callback() && !is_name(callback())) {
if (callback() && !is_name(callback()) && (callback()[0] != '[')) {
// see if 'o' or 'v' used, to prevent unused argument warnings:
int use_o = 0;
int use_v = 0;
@@ -520,11 +520,20 @@ void Menu_Item_Node::write_item(fld::io::Code_Writer& f) {
f.write_c(", 0, ");
}
if (callback()) {
const char* k = is_name(callback()) ? nullptr : class_name(1);
if (k) {
f.write_c(" (Fl_Callback*)%s::%s,", k, callback_name(f));
if (callback()[0] == '[') {
f.write_c("\n");
f.tag(Mergeback::Tag::GENERIC, Mergeback::Tag::WIDGET_CALLBACK, 0);
f.write_c_indented(callback(), 1, 0);
f.write_c("\n");
f.tag(Mergeback::Tag::WIDGET_CALLBACK, Mergeback::Tag::GENERIC, get_uid());
f.write_c("%s, ", f.indent_plus(1));
} else {
f.write_c(" (Fl_Callback*)%s,", callback_name(f));
const char* k = is_name(callback()) ? nullptr : class_name(1);
if (k) {
f.write_c(" (Fl_Callback*)%s::%s,", k, callback_name(f));
} else {
f.write_c(" (Fl_Callback*)%s,", callback_name(f));
}
}
} else
f.write_c(" 0,");
@@ -571,7 +580,7 @@ void Menu_Item_Node::write_code1(fld::io::Code_Writer& f) {
}
if (callback()) {
if (!is_name(callback()) && class_name(1)) {
if (!is_name(callback()) && (callback()[0] != '[') && class_name(1)) {
const char* cn = callback_name(f);
const char* ut = user_data_type() ? user_data_type() : "void*";
f.write_public(0);
+11 -2
View File
@@ -1499,7 +1499,7 @@ void Widget_Node::write_static(fld::io::Code_Writer& f) {
if (strchr(c, '[') == nullptr) f.write_c("%s *%s=(%s *)0;\n", t, c, t);
else f.write_c("%s *%s={(%s *)0};\n", t, c, t);
}
if (callback() && !is_name(callback())) {
if (callback() && !is_name(callback()) && (callback()[0] != '[')) {
// see if 'o' or 'v' used, to prevent unused argument warnings:
int use_o = 0;
int use_v = 0;
@@ -1883,7 +1883,16 @@ void Widget_Node::write_widget_code(fld::io::Code_Writer& f) {
const char* ud = user_data();
if (class_name(1) && !parent->is_widget()) ud = "this";
if (callback()) {
f.write_c("%s%s->callback((Fl_Callback*)%s", f.indent(), var, callback_name(f));
if (callback()[0] == '[') {
f.write_c("%s%s->callback(\n", f.indent(), var);
f.tag(Mergeback::Tag::GENERIC, Mergeback::Tag::WIDGET_CALLBACK, 0);
f.write_c_indented(callback(), 1, 0);
f.write_c("\n");
f.tag(Mergeback::Tag::WIDGET_CALLBACK, Mergeback::Tag::GENERIC, get_uid());
f.write_c("%s", f.indent_plus(1));
} else {
f.write_c("%s%s->callback((Fl_Callback*)%s", f.indent(), var, callback_name(f));
}
if (ud)
f.write_c(", (void*)(%s));\n", ud);
else