summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2025-12-22 23:12:25 +0100
committerMatthias Melcher <github@matthiasm.com>2025-12-22 23:12:42 +0100
commit33199dab785daaa7c6c5733021ad0cab48e0e1dd (patch)
tree7430470aace60b830659ca4d229727aa1f6f6112 /fluid
parentd0d2e104e9d5303ac897f5d1faca582e619180b2 (diff)
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.
Diffstat (limited to 'fluid')
-rw-r--r--fluid/documentation/src/page_widget_panel.dox15
-rw-r--r--fluid/nodes/Menu_Node.cxx21
-rw-r--r--fluid/nodes/Widget_Node.cxx13
3 files changed, 36 insertions, 13 deletions
diff --git a/fluid/documentation/src/page_widget_panel.dox b/fluid/documentation/src/page_widget_panel.dox
index 7a1261d62..d897037e4 100644
--- a/fluid/documentation/src/page_widget_panel.dox
+++ b/fluid/documentation/src/page_widget_panel.dox
@@ -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) {
diff --git a/fluid/nodes/Menu_Node.cxx b/fluid/nodes/Menu_Node.cxx
index 342fcf014..dcaa2fc55 100644
--- a/fluid/nodes/Menu_Node.cxx
+++ b/fluid/nodes/Menu_Node.cxx
@@ -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);
diff --git a/fluid/nodes/Widget_Node.cxx b/fluid/nodes/Widget_Node.cxx
index e711c03f0..b74560f05 100644
--- a/fluid/nodes/Widget_Node.cxx
+++ b/fluid/nodes/Widget_Node.cxx
@@ -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