summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2017-07-20 15:16:37 +0000
committerAlbrecht Schlosser <albrechts.fltk@online.de>2017-07-20 15:16:37 +0000
commita8c4f77d503a91b76a1afd2f0c3dcdfad21fab1a (patch)
treee03d26e69e1d934a8a4c5f28d0d83f649d1d490d
parentdb1f29fdb5f0b1cb7cdbdd2caba2bbcd9335574c (diff)
Improve docs of Fl_Widget::callback() and do_callback().
Clarify that all variants of do_callback() call clear_changed() after the callback and that 'long Fl_Widget::argument()' may truncate the user_data value on some (particularly Windows 64-bit) platforms. Some code has been reformatted and refactored with better variable names, but there are no effective code changes. Obsolete, inactive code was removed. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12345 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--FL/Fl_Widget.H106
-rw-r--r--src/Fl_Widget.cxx61
2 files changed, 99 insertions, 68 deletions
diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H
index ac42d3bf5..60beafcd2 100644
--- a/FL/Fl_Widget.H
+++ b/FL/Fl_Widget.H
@@ -549,26 +549,29 @@ public:
\param[in] cb new callback
\param[in] p user data
*/
- void callback(Fl_Callback* cb, void* p) {callback_=cb; user_data_=p;}
+ void callback(Fl_Callback* cb, void* p) {callback_ = cb; user_data_ = p;}
/** Sets the current callback function for the widget.
Each widget has a single callback.
\param[in] cb new callback
*/
- void callback(Fl_Callback* cb) {callback_=cb;}
+ void callback(Fl_Callback* cb) {callback_ = cb;}
/** Sets the current callback function for the widget.
Each widget has a single callback.
\param[in] cb new callback
*/
- void callback(Fl_Callback0*cb) {callback_=(Fl_Callback*)cb;}
+ void callback(Fl_Callback0* cb) {callback_ = (Fl_Callback*)cb;}
/** Sets the current callback function for the widget.
Each widget has a single callback.
\param[in] cb new callback
\param[in] p user data
*/
- void callback(Fl_Callback1*cb, long p=0) {callback_=(Fl_Callback*)cb; user_data_=(void*)(fl_intptr_t)p;}
+ void callback(Fl_Callback1* cb, long p = 0) {
+ callback_ = (Fl_Callback*)cb;
+ user_data_ = (void*)(fl_intptr_t)p;
+ }
/** Gets the user data for this widget.
Gets the current user data (void *) argument that is passed to the callback function.
@@ -583,14 +586,24 @@ public:
void user_data(void* v) {user_data_ = v;}
/** Gets the current user data (long) argument that is passed to the callback function.
- \todo The user data value must be implemented using \em intptr_t or similar
- to avoid 64-bit machine incompatibilities.
- */
+
+ \note On platforms with <tt>sizeof(long) \< sizeof(void*)</tt>, particularly
+ on Windows 64-bit platforms, this method can truncate stored addresses
+ \p (void*) to the size of a \p long value. Use with care and only
+ if you are sure that the stored user_data value fits in a \p long
+ value because it was stored with argument(long) or another method
+ using only \p long values. You may want to use user_data() instead.
+
+ \see user_data()
+
+ \todo [Internal] The user_data value must be implemented using
+ \p fl_intptr_t or similar to avoid 64-bit platform incompatibilities.
+ */
long argument() const {return (long)(fl_intptr_t)user_data_;}
/** Sets the current user data (long) argument that is passed to the callback function.
- \todo The user data value must be implemented using \em intptr_t or similar
- to avoid 64-bit machine incompatibilities.
+
+ \see argument()
*/
void argument(long v) {user_data_ = (void*)(fl_intptr_t)v;}
@@ -747,22 +760,25 @@ public:
*/
unsigned int takesevents() const {return !(flags_&(INACTIVE|INVISIBLE|OUTPUT));}
- /**
+ /**
Checks if the widget value changed since the last callback.
- "Changed" is a flag that is turned on when the user changes the value
- stored in the widget. This is only used by subclasses of Fl_Widget that
- store values, but is in the base class so it is easier to scan all the
- widgets in a panel and do_callback() on the changed ones in response
+ "Changed" is a flag that is turned on when the user changes the value
+ stored in the widget. This is only used by subclasses of Fl_Widget that
+ store values, but is in the base class so it is easier to scan all the
+ widgets in a panel and do_callback() on the changed ones in response
to an "OK" button.
- Most widgets turn this flag off when they do the callback, and when
+ Most widgets turn this flag off when they do the callback, and when
the program sets the stored value.
- \retval 0 if the value did not change
- \see set_changed(), clear_changed()
+ \note do_callback() turns this flag off after the callback.
+
+ \retval 0 if the value did not change
+ \see set_changed(), clear_changed()
+ \see do_callback(Fl_Widget *widget, void *data)
*/
- unsigned int changed() const {return flags_&CHANGED;}
+ unsigned int changed() const {return flags_ & CHANGED;}
/** Marks the value of the widget as changed.
\see changed(), clear_changed()
@@ -819,42 +835,54 @@ public:
\retval 0 if this widget has no visible focus.
\see visible_focus(int), set_visible_focus(), clear_visible_focus()
*/
- unsigned int visible_focus() { return flags_ & VISIBLE_FOCUS; }
+ unsigned int visible_focus() { return flags_ & VISIBLE_FOCUS; }
/** The default callback for all widgets that don't set a callback.
This callback function puts a pointer to the widget on the queue
- returned by Fl::readqueue().
+ returned by Fl::readqueue(). This is the default for all widgets
+ if you don't set a callback.
+
+ You can avoid the overhead of this default handling if you set the
+ callback to \p NULL explicitly.
Relying on the default callback and reading the callback queue with
Fl::readqueue() is not recommended. If you need a callback, you should
set one with Fl_Widget::callback(Fl_Callback *cb, void *data)
or one of its variants.
- \param[in] cb the widget given to the callback
- \param[in] d user data associated with that callback
+ \param[in] widget the Fl_Widget given to the callback
+ \param[in] data user data associated with that callback
- \see callback(), do_callback(), Fl::readqueue()
+ \see callback(), Fl::readqueue()
+ \see do_callback(Fl_Widget *widget, void *data)
*/
- static void default_callback(Fl_Widget *cb, void *d);
+ static void default_callback(Fl_Widget *widget, void *data);
- /** Calls the widget callback.
- Causes a widget to invoke its callback function with default arguments.
- \see callback()
- */
- void do_callback() {do_callback(this,user_data_);}
+ /** Calls the widget callback function with default arguments.
- /** Calls the widget callback.
- Causes a widget to invoke its callback function with arbitrary arguments.
- \param[in] o call the callback with \p o as the widget argument
- \param[in] arg call the callback with \p arg as the user data argument
- \see callback()
- */
- void do_callback(Fl_Widget* o,long arg) {do_callback(o,(void*)(fl_intptr_t)arg);}
+ This is the same as calling
+ \code
+ do_callback(this, user_data());
+ \endcode
+ \see callback()
+ \see do_callback(Fl_Widget *widget, void *data)
+ */
+ void do_callback() {do_callback(this, user_data_);}
+
+ /** Calls the widget callback function with arbitrary arguments.
+ \param[in] widget call the callback with \p widget as the first argument
+ \param[in] arg call the callback with \p arg as the user data (second) argument
+ \see callback()
+ \see do_callback(Fl_Widget *widget, void *data)
+ */
+ void do_callback(Fl_Widget *widget, long arg) {
+ do_callback(widget, (void*)(fl_intptr_t)arg);
+ }
// Causes a widget to invoke its callback function with arbitrary arguments.
// Documentation and implementation in Fl_Widget.cxx
- void do_callback(Fl_Widget* o,void* arg=0);
+ void do_callback(Fl_Widget *widget, void *arg = 0);
/* Internal use only. */
int test_shortcut();
@@ -879,7 +907,7 @@ public:
\param[in] wgt the possible parent widget.
\see contains()
*/
- int inside(const Fl_Widget* wgt) const {return wgt ? wgt->contains(this) : 0;}
+ int inside(const Fl_Widget *wgt) const {return wgt ? wgt->contains(this) : 0;}
/** Schedules the drawing of the widget.
Marks the widget as needing its draw() routine called.
@@ -957,7 +985,7 @@ public:
void my_callback (Fl_Widget *w, void *) {
Fl_Group *g = w->as_group();
if (g)
- printf ("This group has %d children\n",g->children());
+ printf ("This group has %d children\n", g->children());
else
printf ("This widget is not a group!\n");
}
diff --git a/src/Fl_Widget.cxx b/src/Fl_Widget.cxx
index ee6104354..502fe35f7 100644
--- a/src/Fl_Widget.cxx
+++ b/src/Fl_Widget.cxx
@@ -3,7 +3,7 @@
//
// Base widget class for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -36,17 +36,8 @@ const int QUEUE_SIZE = 20;
static Fl_Widget *obj_queue[QUEUE_SIZE];
static int obj_head, obj_tail;
-void Fl_Widget::default_callback(Fl_Widget *o, void * /*v*/) {
-#if 0
- // This is necessary for strict forms compatibility but is confusing.
- // Use the parent's callback if this widget does not have one.
- for (Fl_Widget *p = o->parent(); p; p = p->parent())
- if (p->callback() != default_callback) {
- p->do_callback(o,v);
- return;
- }
-#endif
- obj_queue[obj_head++] = o;
+void Fl_Widget::default_callback(Fl_Widget *widget, void * /*v*/) {
+ obj_queue[obj_head++] = widget;
if (obj_head >= QUEUE_SIZE) obj_head = 0;
if (obj_head == obj_tail) {
obj_tail++;
@@ -75,9 +66,9 @@ void Fl_Widget::default_callback(Fl_Widget *o, void * /*v*/) {
*/
Fl_Widget *Fl::readqueue() {
if (obj_tail==obj_head) return 0;
- Fl_Widget *o = obj_queue[obj_tail++];
+ Fl_Widget *widget = obj_queue[obj_tail++];
if (obj_tail >= QUEUE_SIZE) obj_tail = 0;
- return o;
+ return widget;
}
/*
This static internal function removes all pending callbacks for a
@@ -89,7 +80,7 @@ Fl_Widget *Fl::readqueue() {
static void cleanup_readqueue(Fl_Widget *w) {
if (obj_tail==obj_head) return;
-
+
// Read the entire queue and copy over all valid entries.
// The new head will be determined after the last copied entry.
@@ -192,9 +183,9 @@ Fl_Widget::~Fl_Widget() {
if (callback_ == default_callback) cleanup_readqueue(this);
}
-/** Draws a focus box for the widget at the given position and size */
-void
-Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const {
+/** Draws a focus box for the widget at the given position and size. */
+
+void Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const {
if (!Fl::visible_focus()) return;
switch (B) {
case FL_DOWN_BOX:
@@ -284,8 +275,7 @@ int Fl_Widget::contains(const Fl_Widget *o) const {
}
-void
-Fl_Widget::label(const char *a) {
+void Fl_Widget::label(const char *a) {
if (flags() & COPIED_LABEL) {
// reassigning a copied label remains the same copied label
if (label_.value == a)
@@ -298,8 +288,7 @@ Fl_Widget::label(const char *a) {
}
-void
-Fl_Widget::copy_label(const char *a) {
+void Fl_Widget::copy_label(const char *a) {
// reassigning a copied label remains the same copied label
if ((flags() & COPIED_LABEL) && (label_.value == a))
return;
@@ -311,19 +300,33 @@ Fl_Widget::copy_label(const char *a) {
}
}
-/** Calls the widget callback.
+/** Calls the widget callback function with arbitrary arguments.
- Causes a widget to invoke its callback function with arbitrary arguments.
+ All overloads of do_callback() call this method.
+ It does nothing if the widget's callback() is NULL.
+ It clears the widget's \e changed flag \b after the callback was
+ called unless the callback is the default callback. Hence it is not
+ necessary to call clear_changed() after calling do_callback()
+ in your own widget's handle() method.
- \param[in] o call the callback with \p o as the widget argument
- \param[in] arg use \p arg as the user data argument
+ \note It is legal to delete the widget in the callback (i.e. in user code),
+ but you must not access the widget in the handle() method after
+ calling do_callback() if the widget was deleted in the callback.
+ We recommend to use Fl_Widget_Tracker to check whether the widget
+ was deleted in the callback.
+
+ \param[in] widget call the callback with \p widget as the first argument
+ \param[in] arg use \p arg as the user data (second) argument
+
+ \see default_callback()
\see callback()
+ \see class Fl_Widget_Tracker
*/
-void
-Fl_Widget::do_callback(Fl_Widget* o,void* arg) {
+
+void Fl_Widget::do_callback(Fl_Widget *widget, void *arg) {
if (!callback_) return;
Fl_Widget_Tracker wp(this);
- callback_(o,arg);
+ callback_(widget, arg);
if (wp.deleted()) return;
if (callback_ != default_callback)
clear_changed();