diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2009-02-08 14:44:15 +0000 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2009-02-08 14:44:15 +0000 |
| commit | 9f1eeaee19576584fab930b6d407d0c5b307dacb (patch) | |
| tree | 8c3df25fb2177c024cc7fcd50918748d90699409 /FL | |
| parent | b30b9e170a0961493c1b256d9c53a1e8309f52b1 (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.H | 112 | ||||
| -rw-r--r-- | FL/Fl_Widget.H | 19 |
2 files changed, 108 insertions, 23 deletions
@@ -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(); |
