summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2010-10-12 08:12:44 +0000
committerAlbrecht Schlosser <albrechts.fltk@online.de>2010-10-12 08:12:44 +0000
commitaea80474f83432b6a858358c45d9117a598f2aaf (patch)
tree0993a81356f8fa110f562e16e3befa3ea24581e9 /src
parente1e119e1df89fee4d0111504fb3ce57a2c65bed0 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Group.cxx49
-rw-r--r--src/Fl_Scroll.cxx17
2 files changed, 52 insertions, 14 deletions
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; i<children_/2; i++,j--) {
+ temp = a[i];
+ a[i] = a[j];
+ a[j] = temp;
}
}
+#endif // REVERSE_CHILDREN
+
+ while (children_) { // delete all children
+ int idx = children_-1; // last child's index
+ Fl_Widget* w = child(idx); // last child widget
+ if (w->parent()==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 */