FLUID: Add support for lambda callbacks.
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:
parent
d0d2e104e9
commit
33199dab78
@ -552,11 +552,10 @@ int xyz_data;
|
||||
button->callback(xyz_callback, &xyz_data);
|
||||
\endcode
|
||||
|
||||
\note You cannot delete a widget inside a callback, as the
|
||||
widget may still be accessed by FLTK after your callback
|
||||
is completed. Instead, use the Fl::delete_widget()
|
||||
method to mark your widget for deletion when it is safe
|
||||
to do so.
|
||||
It's also possible to use a non-capturing lambda function directly, for example:
|
||||
```
|
||||
button->callback( [](Fl_Widget*, void*) { puts("Hello"); } , nullptr );
|
||||
```
|
||||
|
||||
Many programmers new to FLTK or C++ try to use a
|
||||
non-static class method instead of a static class method
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -7,6 +7,7 @@ i18n_gnu_function gettext
|
||||
i18n_gnu_static_function gettext_noop
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
include_guard {}
|
||||
comment {About test/preferences:
|
||||
|
||||
The preferences app shows two features of FLTK and FLUID.
|
||||
@ -184,6 +185,10 @@ Fl_Input::paste_menu_text = gettext("Paste");} {}
|
||||
}
|
||||
MenuItem {} {
|
||||
label sandals
|
||||
callback {[](Fl_Widget*, void*)
|
||||
{
|
||||
puts("The shoe is the sign!");
|
||||
}} selected
|
||||
xywh {0 0 100 20}
|
||||
}
|
||||
MenuItem {} {
|
||||
@ -203,7 +208,7 @@ Fl_Input::paste_menu_text = gettext("Paste");} {}
|
||||
xywh {35 112 100 24} type Radio down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Round_Button wRight {
|
||||
label {right side} selected
|
||||
label {right side}
|
||||
xywh {35 136 100 24} type Radio down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Box {} {
|
||||
@ -217,6 +222,15 @@ Fl_Input::paste_menu_text = gettext("Paste");} {}
|
||||
}
|
||||
Fl_Check_Button wShave {
|
||||
label shave
|
||||
callback {[](Fl_Widget* w, void*)->void {
|
||||
auto* btn = static_cast<Fl_Check_Button*>(w);
|
||||
if (btn->value()) {
|
||||
puts("Shave.");
|
||||
} else {
|
||||
puts("Don't shave.");
|
||||
}
|
||||
}}
|
||||
comment {// Testing lambdas for callbacks}
|
||||
xywh {25 212 105 24} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Check_Button wBrush {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user