From aea80474f83432b6a858358c45d9117a598f2aaf Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Tue, 12 Oct 2010 08:12:44 +0000 Subject: Optimized Fl_Group::clear() and Fl_Scroll::clear(). This speeds up mass deletes (lots of children in a group) significantly. See also STR #2409. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7718 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_Group.cxx | 49 ++++++++++++++++++++++++++++++++++++++++++------- src/Fl_Scroll.cxx | 17 ++++++++++------- 2 files changed, 52 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx index edc2036e7..cd8f94d7d 100644 --- a/src/Fl_Group.cxx +++ b/src/Fl_Group.cxx @@ -387,16 +387,51 @@ void Fl_Group::clear() { savedfocus_ = 0; resizable_ = this; init_sizes(); + + // we must change the Fl::pushed() widget, if it is one of + // the group's children. Otherwise fl_fix_focus() would send + // lots of events to children that are about to be deleted + // anyway. + + Fl_Widget *pushed = Fl::pushed(); // save pushed() widget + if (contains(pushed)) pushed = this; // set it to be the group, if it's a child + Fl::pushed(this); // for fl_fix_focus etc. + // okay, now it is safe to destroy the children: - while (children_) { - Fl_Widget* w = child(0); // *first* child widget - if (w->parent() == this) { // should always be true - remove(0); // remove child widget first - delete w; // then delete it - } else { // this should never happen ! - remove(0); // remove it only + +#define REVERSE_CHILDREN +#ifdef REVERSE_CHILDREN + // Reverse the order of the children. Doing this and deleting + // always the last child is much faster than the other way around. + if (children_ > 1) { + Fl_Widget *temp; + Fl_Widget **a = (Fl_Widget**)array(); + for (int i=0,j=children_-1; iparent()==this) { // should always be true + if (children_>2) { // optimized removal + w->parent_ = 0; // reset child's parent + children_--; // update counter + } else { // slow removal + remove(idx); + } + delete w; // delete the child + } else { // should never happen + remove(idx); // remove it anyway + } + } + + if (pushed != this) Fl::pushed(pushed); // reset pushed() widget + } /** diff --git a/src/Fl_Scroll.cxx b/src/Fl_Scroll.cxx index 085d47bf0..0089524dd 100644 --- a/src/Fl_Scroll.cxx +++ b/src/Fl_Scroll.cxx @@ -32,13 +32,16 @@ /** Clear all but the scrollbars... */ void Fl_Scroll::clear() { - for (int i=children() - 1; i >= 0; i --) { - Fl_Widget* o = child(i); - if (o != &hscrollbar && o != &scrollbar) { - remove(o); - delete o; - } - } + // Note: the scrollbars are removed from the group before calling + // Fl_Group::clear() to take advantage of the optimized widget removal + // and deletion. Finally they are added to Fl_Scroll's group again. This + // is MUCH faster than removing the widgets one by one (STR #2409). + + remove(scrollbar); + remove(hscrollbar); + Fl_Group::clear(); + add(hscrollbar); + add(scrollbar); } /** Insure the scrollbars are the last children */ -- cgit v1.2.3