summaryrefslogtreecommitdiff
path: root/documentation
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2023-08-15 11:36:58 +0200
committerGitHub <noreply@github.com>2023-08-15 11:36:58 +0200
commit10d9010ed9a7624bebebcb0f86fc86d362672027 (patch)
tree4303c6f36947046d2baab01f02defd0d4bdb9ab2 /documentation
parente6440ca0a89874e2593b2dc9cf5a3b0e87df94a2 (diff)
Improved, yet compatible, widget callback system using macros (#729)
* adds FL/fl_callback.macros.H * adds FL_FUNCTION_CALLBACK_n(widget, function, [type, data]) * adds FL_METHOD_CALLBACK_n(widget, class, instance, method, [type, data]) * adds FL_INLINE_CALLBACK_n(widget, [type, name, data], callback_body) * adds `examples/callback` * full documentation
Diffstat (limited to 'documentation')
-rw-r--r--documentation/src/common.dox108
1 files changed, 71 insertions, 37 deletions
diff --git a/documentation/src/common.dox b/documentation/src/common.dox
index d8a5c0940..dcad4b1fe 100644
--- a/documentation/src/common.dox
+++ b/documentation/src/common.dox
@@ -550,6 +550,72 @@ 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.
+
+Many programmers new to FLTK or C++ try to use a
+non-static class method instead of a static class method
+or function for their callback. Since callbacks are done
+outside a C++ class, the `this` pointer is not
+initialized for class methods.
+
+To work around this problem, define a static method
+in your class that accepts a pointer to the class, and
+then have the static method call the class method(s) as
+needed. The data pointer you provide to the
+\p callback() method of the widget can be a
+pointer to the instance of your class.
+
+\code
+class Foo {
+ void my_callback(Fl_Widget *w);
+ static void my_static_callback(Fl_Widget *w, void *f) { ((Foo *)f)->my_callback(w); }
+ ...
+}
+...
+w->callback(my_static_callback, (void *)this);
+\endcode
+
+In an effort to make callbacks easier, more flexible, and type safe, FLTK
+provides three groups of macros that generate the code needed to call class
+methods directly with up to five custom parameters.
+
+ - `FL_FUNCTION_CALLBACK_#(WIDGET, FUNCTION, ...)` creates code for callbacks to
+ functions and static class methods with up to five arguments. The `#` must
+ be replaced by the number of callback arguments.
+ - `FL_METHOD_CALLBACK_#(WIDGET, CLASS, SELF, METH, ...)` creates code for
+ callbacks to arbitrary public class methods
+ - `FL_INLINE_CALLBACK_#(WIDGET, ..., FUNCTION_BODY)` creates code for callback
+ functions that are very close to (almost in the same line) the widget
+ creation code, similar to lambda function in C++11. The last argument of
+ this macro is the callback code.
+
+The syntax is a bit unconventional, but the resulting code is flexible and
+needs no additional maintenance. It is also C++98 compatible. For example:
+
+\code
+#include <FL/fl_callback_macros.H>
+...
+Fl_String *str = new Fl_String("FLTK");
+Fl_Button *btn = new Fl_Button(10, 10, 100, 100);
+FL_METHOD_CALLBACK_2(btn, Fl_String, str, insert, int, 2, const char*, "...");
+...
+Fl_Button *inline_cb_btn_2 = new Fl_Button(390, 60, 180, 25, "2 args");
+FL_INLINE_CALLBACK_2( inline_cb_btn_2,
+ const char *, text, "FLTK", int, number, 2,
+ {
+ fl_message("We received the message %s with %d!", text, number);
+ }
+ );
+\endcode
+
+\see Fl_Widget::callback(Fl_Callback*, void*), FL_FUNCTION_CALLBACK_3, FL_METHOD_CALLBACK_1, FL_INLINE_CALLBACK_2
+
+\section common_when When and Reason
+
Normally callbacks are performed only when the value of the
widget changes. You can change this using the Fl_Widget::when()
method:
@@ -564,45 +630,13 @@ button->when(FL_WHEN_ENTER_KEY_ALWAYS);
button->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED);
\endcode
-<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc">
-<TR>
- <TD><B>Note:</B>
-
- 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.
-
- <B>Hint:</B>
+Within the callback, you can query why the callback was called using
+Fl::callback_reason(). For example, setting
- Many programmers new to FLTK or C++ try to use a
- non-static class method instead of a static class method
- or function for their callback. Since callbacks are done
- outside a C++ class, the <tt>this</tt> pointer is not
- initialized for class methods.
+\code myInput->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED) \endcode
- To work around this problem, define a static method
- in your class that accepts a pointer to the class, and
- then have the static method call the class method(s) as
- needed. The data pointer you provide to the
- \p callback() method of the widget can be a
- pointer to the instance of your class.
-
-\code
-class Foo {
- void my_callback(Fl_Widget *w);
- static void my_static_callback(Fl_Widget *w, void *f) { ((Foo *)f)->my_callback(w); }
- ...
-}
-
-...
-
-w->callback(my_static_callback, (void *)this);
-\endcode
- </TD>
-</TR>
-</TABLE></CENTER>
+for a text input field may return \ref FL_REASON_LOST_FOCUS or
+\ref FL_REASON_CHANGED as a callback reason.
\section common_shortcuts Shortcuts