From eec7f80e949dd78874741a6c17fe66ec74cec3a5 Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Thu, 8 Jan 2009 17:12:34 +0000 Subject: 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 --- CHANGES | 2 ++ FL/Fl_Value_Input.H | 1 + src/Fl_Group.cxx | 35 ++++++++++++++++++++++++----------- src/Fl_Value_Input.cxx | 6 ++++++ src/Fl_Widget.cxx | 13 +++++++++---- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index c0ef45bc6..8acb7ebc4 100644 --- a/CHANGES +++ b/CHANGES @@ -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) diff --git a/FL/Fl_Value_Input.H b/FL/Fl_Value_Input.H index 82b5cc8f2..6cba43e6d 100644 --- a/FL/Fl_Value_Input.H +++ b/FL/Fl_Value_Input.H @@ -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;} diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx index cc2a12bf0..891e0cce8 100644 --- a/src/Fl_Group.cxx +++ b/src/Fl_Group.cxx @@ -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]; diff --git a/src/Fl_Value_Input.cxx b/src/Fl_Value_Input.cxx index eb741c1c7..1ac7a6958 100644 --- a/src/Fl_Value_Input.cxx +++ b/src/Fl_Value_Input.cxx @@ -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$". // diff --git a/src/Fl_Widget.cxx b/src/Fl_Widget.cxx index 8f76527ca..550f1eb1c 100644 --- a/src/Fl_Widget.cxx +++ b/src/Fl_Widget.cxx @@ -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); } -- cgit v1.2.3