summaryrefslogtreecommitdiff
path: root/FL
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2009-02-08 14:44:15 +0000
committerAlbrecht Schlosser <albrechts.fltk@online.de>2009-02-08 14:44:15 +0000
commit9f1eeaee19576584fab930b6d407d0c5b307dacb (patch)
tree8c3df25fb2177c024cc7fcd50918748d90699409 /FL
parentb30b9e170a0961493c1b256d9c53a1e8309f52b1 (diff)
Added the helper class Fl_Watch to simplify safe handling of widget deletion
in callbacks. This is used e.g. in Fl_Widget::do_callback() to prevent accessing widgets after deletion in the callback. Documentation adjusted, Fl_Menu_Button.cxx changed to use Fl_Watch instead of Fl::watch_widget_pointer. Fl::watch_widget_pointer() and Fl::release_widget_pointer() have been modified to use an array without "holes" (NULL pointers) for storing the widget pointers for faster access: Fl::release_widget_pointer() now shifts pointers to close gaps of freed pointers. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6651 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'FL')
-rw-r--r--FL/Fl.H112
-rw-r--r--FL/Fl_Widget.H19
2 files changed, 108 insertions, 23 deletions
diff --git a/FL/Fl.H b/FL/Fl.H
index 1773a3744..2e5815687 100644
--- a/FL/Fl.H
+++ b/FL/Fl.H
@@ -849,17 +849,31 @@ public:
/** \defgroup fl_del_widget Safe widget deletion support functions
- These functions support deletion of widgets inside callbacks.
+ These functions support deletion of widgets inside callbacks.
- There are two groups of related methods:
+ Fl::delete_widget() should be called when deleting widgets
+ or complete widget trees (Fl_Group, Fl_Window, ...) inside
+ callbacks.
- -# scheduled widget deletion
- - Fl::delete_widget() schedules widgets for deletion
- - Fl::do_widget_deletion() deletes all scheduled widgets
- -# widget watch list ("smart pointers")
- - Fl::watch_widget_pointer() adds a widget pointer to the watch list
- - Fl::release_widget_pointer() removes a widget pointer from the watch list
- - Fl::clear_widget_pointer() clears a widget pointer \e in the watch list
+ The other functions are intended for internal use. The preferred
+ way to use them is by using the helper class Fl_Watch.
+
+ The following is to show how it works ...
+
+ There are three groups of related methods:
+
+ -# scheduled widget deletion
+ - Fl::delete_widget() schedules widgets for deletion
+ - Fl::do_widget_deletion() deletes all scheduled widgets
+ -# widget watch list ("smart pointers")
+ - Fl::watch_widget_pointer() adds a widget pointer to the watch list
+ - Fl::release_widget_pointer() removes a widget pointer from the watch list
+ - Fl::clear_widget_pointer() clears a widget pointer \e in the watch list
+ -# the class Fl_Watch:
+ - the constructor calls Fl::watch_widget_pointer()
+ - the destructor calls Fl::release_widget_pointer()
+ - the access methods can be used to test, if a widget has been deleted
+ \see Fl_Watch.
@{ */
// Widget deletion:
@@ -919,6 +933,86 @@ public:
};
+/**
+ This class should be used to control safe widget deletion.
+
+ You can use an Fl_Watch object to watch another widget, if you
+ need to know, if this widget has been deleted during a callback.
+
+ This simplifies the use of the "safe widget deletion" methods
+ Fl::watch_widget_pointer() and Fl::release_widget_pointer() and
+ makes their use more reliable, because the destructor autmatically
+ releases the widget pointer from the widget watch list.
+
+ It is intended to be used as an automatic (local/stack) variable,
+ such that the automatic destructor is called when the object's
+ scope is left. This ensures that no stale widget pointers are
+ left in the widget watch list (see example below).
+
+ You can also create Fl_Watch objects with \e \b new, but then it
+ is your responsibility to delete the object (and thus remove the
+ widget pointer from the watch list) when it is not needed any more.
+
+ Example:
+
+ \code
+ int MyClass::handle (int event) {
+
+ if (...) {
+ Fl_Watch wp(this); // watch myself
+ do_callback(); // call the callback
+
+ if (wp.deleted()) return 1; // exit, if deleted
+
+ // Now we are sure that the widget has not been deleted.
+ // It is safe to access the widget
+
+ clear_changed(); // access the widget
+ }
+ }
+ \endcode
+
+*/
+class FL_EXPORT Fl_Watch {
+
+ Fl_Widget* wp_;
+
+public:
+
+ Fl_Watch(Fl_Widget *wi);
+ ~Fl_Watch();
+
+ /**
+ returns a pointer to the watched widget.
+
+ This pointer is NULL, if the widget has been deleted.
+ */
+ Fl_Widget *widget() {return wp_;}
+
+ /**
+ returns 1, if the watched widget has been deleted.
+
+ This is a convenience method. You can also use something like
+
+ if (watch.widget() == 0) // ...
+
+ where watch is an Fl_Watch object.
+ */
+ int deleted() {return wp_ == 0;}
+
+ /**
+ returns 1, if the watched widget exists (has not been deleted).
+
+ This is a convenience method. You can also use something like
+
+ if (watch.widget() != 0) // ...
+
+ where watch is an Fl_Watch object.
+ */
+ int exists() {return wp_ != 0;}
+
+};
+
#endif // !Fl_H
//
diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H
index f8d3fa4ed..7fe67ce11 100644
--- a/FL/Fl_Widget.H
+++ b/FL/Fl_Widget.H
@@ -793,29 +793,20 @@ public:
static void default_callback(Fl_Widget *cb, void *d);
/** Calls the widget callback.
- Causes a widget to invoke its callback function, optionally
- with arbitrary arguments.
+ Causes a widget to invoke its callback function with default arguments.
\see callback()
*/
- void do_callback() {callback_(this,user_data_); if (callback_ != default_callback) clear_changed();}
+ void do_callback() {do_callback(this,user_data_);}
/** Calls the widget callback.
- Causes a widget to invoke its callback function, optionally
- with arbitrary arguments.
+ Causes a widget to invoke its callback function with arbitrary arguments.
\param[in] o call the callback with \em o as the widget argument
\param[in] arg call the callback with \em arg as the user data argument
\see callback()
*/
- void do_callback(Fl_Widget* o,void* arg=0) {callback_(o,arg); if (callback_ != default_callback) clear_changed();}
+ void do_callback(Fl_Widget* o,long arg) {do_callback(o,(void*)arg);}
- /** Calls the widget callback.
- Causes a widget to invoke its callback function, optionally
- with arbitrary arguments.
- \param[in] o call the callback with \em o as the widget argument
- \param[in] arg call the callback with \em arg as the user data argument
- \see callback()
- */
- void do_callback(Fl_Widget* o,long arg) {callback_(o,(void*)arg); if (callback_ != default_callback) clear_changed();}
+ void do_callback(Fl_Widget* o,void* arg=0); // impl. in Fl_Widget.cxx
/** Internal use only. */
int test_shortcut();