Widgets now remove themselves from their parent group (if any), when destroyed

(STR #1894). Fl_Group::clear() removes widget by widget (one at a time) to
allow widgets to remove other related widgets from the same group, when they
are deleted.
Also fixed a bug in Fl_Value_Input (added a destructor), because it used
a non-Fl_Group widget as parent of another widget.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6623 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Albrecht Schlosser 2009-01-08 17:12:34 +00:00
parent 601a0f0d3e
commit eec7f80e94
5 changed files with 42 additions and 15 deletions

View File

@ -1,5 +1,7 @@
CHANGES IN FLTK 1.3.0
- Widgets now remove themselves from their parent group (if any),
when destroyed (STR #1894)
- Added flexible gap size for text buffer (STR #2046)
- Fixed static linking of image libraries (STR #1962)
- Fixed fl_set_spot() for Windows (STR #2101)

View File

@ -76,6 +76,7 @@ public:
void draw();
void resize(int,int,int,int);
Fl_Value_Input(int x,int y,int w,int h,const char *l=0);
~Fl_Value_Input();
/** See void Fl_Value_Input::soft(char s) */
void soft(char s) {soft_ = s;}

View File

@ -383,21 +383,23 @@ Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l)
affects all child widgets and deletes them from memory.
*/
void Fl_Group::clear() {
Fl_Widget*const* old_array = array();
int old_children = children();
// clear everything now, in case fl_fix_focus recursively calls us:
children_ = 0;
//array_ = 0; //dont do this, it will clobber old_array if only one child
savedfocus_ = 0;
resizable_ = this;
init_sizes();
// okay, now it is safe to destroy the children:
Fl_Widget*const* a = old_array;
for (int i=old_children; i--;) {
Fl_Widget* o = *a++;
if (o->parent() == this) delete o;
while (children_) {
Fl_Widget* o = child(0); // *first* child widget
if (o->parent() == this) { // should always be true
remove(o); // remove child widget first
delete o; // then delete it
} else { // this should never happen !
#ifdef DEBUG_CLEAR
printf ("Fl_Group::clear() widget:%p, parent: %p != this (%p)\n",
o, o->parent(), this); fflush(stdout);
#endif // DEBUG_CLEAR
remove(o); // remove it
}
}
if (old_children > 1) free((void*)old_array);
}
/**
@ -466,7 +468,18 @@ void Fl_Group::remove(Fl_Widget &o) {
int i = find(o);
if (i >= children_) return;
if (&o == savedfocus_) savedfocus_ = 0;
o.parent_ = 0;
if (o.parent_ == this) { // this should always be true
o.parent_ = 0;
}
#ifdef DEBUG_REMOVE
else { // this should never happen !
printf ("Fl_Group::remove(): widget %p, parent_ (%p) != this (%p)\n",
&o, o.parent_, this);
}
#endif // DEBUG_REMOVE
// remove the widget from the group
children_--;
if (children_ == 1) { // go from 2 to 1 child
Fl_Widget *t = array_[!i];

View File

@ -136,6 +136,12 @@ Fl_Value_Input::Fl_Value_Input(int X, int Y, int W, int H, const char* l)
set_flag(SHORTCUT_LABEL);
}
Fl_Value_Input::~Fl_Value_Input() {
if (input.parent() == (Fl_Group *)this)
input.parent(0); // *revert* ctor kludge!
}
//
// End of "$Id$".
//

View File

@ -135,14 +135,19 @@ extern void fl_throw_focus(Fl_Widget*); // in Fl_x.cxx
/**
Destroys the widget, taking care of throwing focus before if any.
Destruction does not remove from any parent group! And groups when
destroyed destroy all their children. This is convenient and fast.
However, it is only legal to destroy a "root" such as an Fl_Window,
and automatic destructors may be called.
Destruction removes the widget from any parent group! And groups when
destroyed destroy all their children. This is convenient and fast.
*/
Fl_Widget::~Fl_Widget() {
Fl::clear_widget_pointer(this);
if (flags() & COPIED_LABEL) free((void *)(label_.value));
// remove from parent group
if (parent_) parent_->remove(this);
#ifdef DEBUG_DELETE
if (parent_) { // this should never happen
printf("*** Fl_Widget: parent_->remove(this) failed [%p,%p]\n",parent_,this);
}
#endif // DEBUG_DELETE
parent_ = 0; // Don't throw focus to a parent widget.
fl_throw_focus(this);
}