Optimizations for very large Fl_Tree's

(Adding 60k items took forever, and drawing them
 caused wraparound drawing issues and scrolling slowness)


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9216 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Greg Ercolano 2011-12-25 01:10:45 +00:00
parent a0be94eebe
commit fc135a498b
2 changed files with 27 additions and 18 deletions

View File

@ -293,7 +293,7 @@ Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_labe
/// \returns the item added.
///
Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) {
int t = find_child(*arr);
int t = (*arr && *(arr+1)) ? find_child(*arr) : -1;
Fl_Tree_Item *item = 0;
if ( t == -1 ) {
item = (Fl_Tree_Item*)add(prefs, *arr);
@ -583,27 +583,30 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
// See if we should draw this item
// If this item is root, and showroot() is disabled, don't draw.
// 'clipped' is an optimization to prevent drawing anything offscreen.
//
char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
char clipped = ((Y+H) < tree->y()) || (Y>(tree->y()+tree->h())) ? 1 : 0;
if ( drawthis ) {
// Draw connectors
if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
// Horiz connector between center of icon and text
// if this is root, the connector should not dangle in thin air on the left
if (is_root())
draw_horizontal_connector(hcenterx, hendx, textycenter, prefs);
else
draw_horizontal_connector(hstartx, hendx, textycenter, prefs);
if (is_root()) {
if (!clipped) draw_horizontal_connector(hcenterx, hendx, textycenter, prefs);
} else {
if (!clipped) draw_horizontal_connector(hstartx, hendx, textycenter, prefs);
}
if ( has_children() && is_open() ) {
// Small vertical line down to children
draw_vertical_connector(hcenterx, textycenter, Y+H, prefs);
if (!clipped) draw_vertical_connector(hcenterx, textycenter, Y+H, prefs);
}
// Connectors for last child
if ( ! is_root() ) {
if ( lastchild ) {
draw_vertical_connector(hstartx, Y, textycenter, prefs);
if (!clipped) draw_vertical_connector(hstartx, Y, textycenter, prefs);
} else {
draw_vertical_connector(hstartx, Y, Y+H, prefs);
if (!clipped) draw_vertical_connector(hstartx, Y, Y+H, prefs);
}
}
}
@ -611,9 +614,9 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
if ( has_children() && prefs.showcollapse() ) {
// Draw icon image
if ( is_open() ) {
prefs.closeicon()->draw(icon_x,icon_y);
if (!clipped) prefs.closeicon()->draw(icon_x,icon_y);
} else {
prefs.openicon()->draw(icon_x,icon_y);
if (!clipped) prefs.openicon()->draw(icon_x,icon_y);
}
}
// Background for this item
@ -627,11 +630,13 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
if ( bg != tree->color() || is_selected() ) {
if ( is_selected() ) {
// Selected? Use selectbox() style
fl_draw_box(prefs.selectbox(), bx, by, bw, bh, bg);
if (!clipped) fl_draw_box(prefs.selectbox(), bx, by, bw, bh, bg);
} else {
// Not Selected? use plain filled rectangle
fl_color(bg);
fl_rectf(bx, by, bw, bh);
if (!clipped) {
fl_color(bg);
fl_rectf(bx, by, bw, bh);
}
}
}
// Draw user icon (if any)
@ -640,13 +645,13 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
// Item has user icon? Use it
useroff += prefs.usericonmarginleft();
icon_y = textycenter - (usericon()->h() >> 1);
usericon()->draw(X+useroff,icon_y);
if (!clipped) usericon()->draw(X+useroff,icon_y);
useroff += usericon()->w();
} else if ( prefs.usericon() ) {
// Prefs has user icon? Use it
useroff += prefs.usericonmarginleft();
icon_y = textycenter - (prefs.usericon()->h() >> 1);
prefs.usericon()->draw(X+useroff,icon_y);
if (!clipped) prefs.usericon()->draw(X+useroff,icon_y);
useroff += prefs.usericon()->w();
}
useroff += prefs.labelmarginleft();
@ -663,12 +668,15 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
}
} else {
// No label widget? Draw text label
if ( _label ) {
if ( _label && !clipped ) {
fl_color(fg);
fl_draw(_label, X+useroff, Y+H-fl_descent()-1);
}
}
if ( this == itemfocus && Fl::visible_focus() && Fl::focus() == tree) {
if ( !clipped &&
this == itemfocus &&
Fl::visible_focus() &&
Fl::focus() == tree) {
// Draw focus box around this item
draw_item_focus(FL_NO_BOX,bg,bx+1,by+1,bw-1,bh-1);
}
@ -688,7 +696,7 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
Y += prefs.openchild_marginbottom(); // offset below open child tree
}
if ( ! lastchild ) {
draw_vertical_connector(hstartx, child_y_start, Y, prefs);
if (!clipped) draw_vertical_connector(hstartx, child_y_start, Y, prefs);
}
}
}

View File

@ -79,6 +79,7 @@ void Fl_Tree_Item_Array::clear() {
void Fl_Tree_Item_Array::enlarge(int count) {
int newtotal = _total + count; // new total
if ( newtotal >= _size ) { // more than we have allocated?
if ( (newtotal/150) > _chunksize ) _chunksize *= 10;
// Increase size of array
int newsize = _size + _chunksize;
Fl_Tree_Item **newitems = (Fl_Tree_Item**)malloc(newsize * sizeof(Fl_Tree_Item*));