diff options
| -rw-r--r-- | FL/Fl_Widget.H | 106 | ||||
| -rw-r--r-- | src/Fl_Widget.cxx | 61 |
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(); |
