Author: AlbrechtS
Date: 2010-10-12 01:12:44 -0700 (Tue, 12 Oct 2010)
New Revision: 7718
Log:
Optimized Fl_Group::clear() and Fl_Scroll::clear(). This speeds
up mass deletes (lots of children in a group) significantly.
See also STR #2409.


Modified:
   branches/branch-1.3/src/Fl_Group.cxx
   branches/branch-1.3/src/Fl_Scroll.cxx

Modified: branches/branch-1.3/src/Fl_Group.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Group.cxx        2010-10-11 20:37:18 UTC (rev 
7717)
+++ branches/branch-1.3/src/Fl_Group.cxx        2010-10-12 08:12:44 UTC (rev 
7718)
@@ -387,16 +387,51 @@
   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
+
 }
 
 /**

Modified: branches/branch-1.3/src/Fl_Scroll.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Scroll.cxx       2010-10-11 20:37:18 UTC (rev 
7717)
+++ branches/branch-1.3/src/Fl_Scroll.cxx       2010-10-12 08:12:44 UTC (rev 
7718)
@@ -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 */

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to