Author: greg.ercolano Date: 2011-12-24 17:10:45 -0800 (Sat, 24 Dec 2011) New Revision: 9216 Log: Optimizations for very large Fl_Tree's (Adding 60k items took forever, and drawing them caused wraparound drawing issues and scrolling slowness)
Modified: branches/branch-1.3/src/Fl_Tree_Item.cxx branches/branch-1.3/src/Fl_Tree_Item_Array.cxx Modified: branches/branch-1.3/src/Fl_Tree_Item.cxx =================================================================== --- branches/branch-1.3/src/Fl_Tree_Item.cxx 2011-12-25 00:36:11 UTC (rev 9215) +++ branches/branch-1.3/src/Fl_Tree_Item.cxx 2011-12-25 01:10:45 UTC (rev 9216) @@ -293,7 +293,7 @@ /// \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 @@ // 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 @@ 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 @@ 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 @@ // 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 @@ } } 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 @@ 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); } } } Modified: branches/branch-1.3/src/Fl_Tree_Item_Array.cxx =================================================================== --- branches/branch-1.3/src/Fl_Tree_Item_Array.cxx 2011-12-25 00:36:11 UTC (rev 9215) +++ branches/branch-1.3/src/Fl_Tree_Item_Array.cxx 2011-12-25 01:10:45 UTC (rev 9216) @@ -79,6 +79,7 @@ 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*)); _______________________________________________ fltk-commit mailing list fltk-commit@easysw.com http://lists.easysw.com/mailman/listinfo/fltk-commit