summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2010-02-07 18:52:26 +0000
committerAlbrecht Schlosser <albrechts.fltk@online.de>2010-02-07 18:52:26 +0000
commitce7da76d6a219c5fc0a33f9c5b2701f3b47220d6 (patch)
treef27af939a2a700247d6bcccc525b9072c2a0281d
parent5ec87ac84845728cc004ef2920502a8e4eb4d9a0 (diff)
Optimized Fl_Group::clear() and Fl_Scroll::clear() as discussed in
fltk.development in "Fl_Group::clear SLOW!" on Feb. 06/07, 2010 (no STR) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7038 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CHANGES3
-rw-r--r--src/Fl_Group.cxx33
-rw-r--r--src/Fl_Scroll.cxx17
3 files changed, 35 insertions, 18 deletions
diff --git a/CHANGES b/CHANGES
index d03f28ff7..40acf40ff 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
CHANGES IN FLTK 1.3.0
+ - Optimized Fl_Group::clear() and Fl_Scroll::clear() as
+ discussed in fltk.development in "Fl_Group::clear SLOW!"
+ on Feb. 06/07, 2010 (no STR)
- Replaced _WIN32 symbols that had come with UTF-8 and the
new Fl_Table widget with WIN32
- Fixed a buffer overflow in fl_utf8from_mb() (STR #2279)
diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx
index b42f1caf8..b84fe7e32 100644
--- a/src/Fl_Group.cxx
+++ b/src/Fl_Group.cxx
@@ -382,24 +382,33 @@ Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l)
This method differs from the remove() method in that it
affects all child widgets and deletes them from memory.
*/
+/* Implementation note:
+ This is optimized and does not remove children _during_ the loop.
+ However, deleting one child may also delete other children in the
+ group because a child widget can destroy other children in the same
+ group in its destructor or simply remove them from the parent group.
+ Because of this we must walk forwards through the array of children.
+ The allocated array_ of children is freed after the loop.
+*/
void Fl_Group::clear() {
savedfocus_ = 0;
resizable_ = this;
init_sizes();
// okay, now it is safe to destroy the children:
- 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
+ int i;
+ for (i=0; i<children_; i++) { // delete all children
+ Fl_Widget* o = child(i); // get child widget
+ if (o->parent()==this) { // should always be true
+ o->parent_ = 0; // reset child's parent
+ delete o; // delete it
}
}
+ // now free the array_ of children (if any)
+ if (children_ > 1) {
+ free((void*)array_);
+ }
+ array_ = 0;
+ children_ = 0;
}
/**
@@ -469,6 +478,8 @@ void Fl_Group::add(Fl_Widget &o) {insert(o, children_);}
This method differs from the clear() method in that it only affects
a single widget and does not delete it from memory.
*/
+// Note: if you change this, be sure to do similar changes in
+// Fl_Group::clear() as well, if applicable.
void Fl_Group::remove(Fl_Widget &o) {
if (!children_) return;
int i = find(o);
diff --git a/src/Fl_Scroll.cxx b/src/Fl_Scroll.cxx
index 085d47bf0..333c4892d 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. Finally they are added
+ // to the Fl_Scroll's group again.
+ // This is MUCH faster than removing each widget.
+ remove(scrollbar);
+ remove(hscrollbar);
+ Fl_Group::clear();
+ add(hscrollbar);
+ add(scrollbar);
}
/** Insure the scrollbars are the last children */