summaryrefslogtreecommitdiff
path: root/FL/Fl_Widget_Tracker.H
blob: d0aad86c0ee03c8f6893e74d9e14191aaa0b523a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// Widget Tracker header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 2025 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
// file is missing or damaged, see the license at:
//
//     https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
//     https://www.fltk.org/bugs.php
//

/** \file FL/Fl_Widget_Tracker.H
  \brief Track widget deletion.
*/

#ifndef Fl_Widget_Tracker_H
#define Fl_Widget_Tracker_H

#include <FL/fl_config.h> // build configuration
#include <FL/Fl_Export.H>

class Fl_Widget;


/**
  This class should be used to control safe widget deletion.

  You can use an Fl_Widget_Tracker object to watch another widget, if you
  need to know whether 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 automatically
  releases the widget pointer from the widget watch list.

  Fl_Widget_Tracker is intended to be used as an automatic (local/stack)
  variable, such that its 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_Widget_Tracker objects with \c new, but then it
  is your responsibility to delete the object (and thus remove the
  widget pointer from the watch list) when it is no longer needed.

  Example:

  \code
  int MyClass::handle (int event) {

    if (...) {
      Fl_Widget_Tracker 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,
      // and it is safe to access the widget:

      box(FL_FLAT_BOX);
      color(FL_WHITE);
      redraw();
    }
  }
  \endcode

*/
class FL_EXPORT Fl_Widget_Tracker {

  Fl_Widget* wp_;

public:

  Fl_Widget_Tracker(Fl_Widget *wi);
  ~Fl_Widget_Tracker();

  /**
    Returns a pointer to the watched widget.
    \return nullptr if the widget was deleted.
  */
  Fl_Widget *widget() { return wp_; }

  /**
    Check if the widget was deleted since the tracker was created.
    \return 1 if the watched widget has been deleted, otherwise 0
  */
  int deleted() {return wp_ == 0;}

  /**
    Check if the widget exists and was not deleted since the tracker was created.
    \return 1 if the watched widget exists, otherwise 0
  */
  int exists() { return wp_ != 0; }

};

namespace Fl {

/** \defgroup fl_del_widget Safe widget deletion support functions

 These functions, declared in <FL/Fl.H>, support deletion of widgets inside callbacks.

 Fl::delete_widget() should be called when deleting widgets
 or complete widget trees (Fl_Group, Fl_Window, ...) inside
 callbacks.

 The other functions are intended for internal use. The preferred
 way to use them is by using the helper class Fl_Widget_Tracker.

 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_Widget_Tracker:
 - 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_Widget_Tracker.

 @{ */

// Widget deletion:
FL_EXPORT extern void delete_widget(Fl_Widget *w);
FL_EXPORT extern void do_widget_deletion();
FL_EXPORT extern void watch_widget_pointer(Fl_Widget *&w);
FL_EXPORT extern void release_widget_pointer(Fl_Widget *&w);
FL_EXPORT extern void clear_widget_pointer(Fl_Widget const *w);

/** @} */

} // namespace Fl

#endif // !Fl_Widget_Tracker_H