diff --git a/FL/Fl_Text_Display.H b/FL/Fl_Text_Display.H index 21f0d63d8..7bc254723 100644 --- a/FL/Fl_Text_Display.H +++ b/FL/Fl_Text_Display.H @@ -431,7 +431,8 @@ public: int wrapped_row(int row) const; void wrap_mode(int wrap, int wrap_margin); - virtual void recalc_display(); + virtual void recalc_display(); // does actual recalc + virtual void needs_recalc_display(); // schedules recalc during draw() virtual void resize(int X, int Y, int W, int H); /** @@ -654,6 +655,9 @@ protected: Fl_Color linenumber_bgcolor_; Fl_Align linenumber_align_; const char* linenumber_format_; + +protected: + bool needs_recalc_display_; }; #endif diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index 1f02c34f5..9a277e060 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -169,6 +169,7 @@ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l) secondary_selection_color_ = FL_GRAY; mLineNumLeft = 0; // XXX: UNUSED mLineNumWidth = 0; + needs_recalc_display_ = false; linenumber_font_ = FL_HELVETICA; linenumber_size_ = FL_NORMAL_SIZE; @@ -223,7 +224,7 @@ Fl_Text_Display::~Fl_Text_Display() { void Fl_Text_Display::linenumber_width(int width) { if (width < 0) return; mLineNumWidth = width; - recalc_display(); // recalc line#s // resize(x(), y(), w(), h()); + needs_recalc_display(); // recalc line#s // resize(x(), y(), w(), h()); } /** @@ -376,7 +377,7 @@ void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) { } /* Resize the widget to update the screen... */ - recalc_display(); // resize(x(), y(), w(), h()); + needs_recalc_display(); // resize(x(), y(), w(), h()); } @@ -478,11 +479,22 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) { Fl_Widget::resize(X,Y,W,H); mColumnScale = 0; // force recomputation of the width of a column when display is rescaled - recalc_display(); + needs_recalc_display(); +} + +/** + Schedule a recalc_display() to be done on next draw(). + Call this from methods that might be called repeatedly, to defers potentially + cpu intensive recalc_display() until it's actually needed just before draw(). + */ +void Fl_Text_Display::needs_recalc_display() { + needs_recalc_display_ = true; } /** Recalculate the display's visible lines and scrollbar sizes. + Beware calling this directly may cause a lot of CPU if called repeatedly (issue 300). + Better to call needs_recalc_display() to flag a recalc to be done during next draw(). */ void Fl_Text_Display::recalc_display() { if (!buffer()) return; @@ -969,7 +981,7 @@ void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) { mAbsTopLineNum = 1; // changed from 0 to 1 -- LZA / STR#2621 } - recalc_display(); // resize(x(), y(), w(), h()); + needs_recalc_display(); // resize(x(), y(), w(), h()); } @@ -1278,7 +1290,7 @@ void Fl_Text_Display::display_insert() { */ void Fl_Text_Display::show_insert_position() { display_insert_position_hint = 1; - recalc_display(); // resize(x(), y(), w(), h()); + needs_recalc_display(); // resize(x(), y(), w(), h()); } @@ -1746,7 +1758,7 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, } // refigure scrollbars & stuff - textD->resize(textD->x(), textD->y(), textD->w(), textD->h()); + textD->needs_recalc_display(); // textD->resize(textD->x(), textD->y(), textD->w(), textD->h()); // don't need to do anything else if not visible? if (!textD->visible_r()) return; @@ -3004,7 +3016,7 @@ void Fl_Text_Display::calc_last_char() { void Fl_Text_Display::scroll(int topLineNum, int horizOffset) { mTopLineNumHint = topLineNum; mHorizOffsetHint = horizOffset; - recalc_display(); // resize(x(), y(), w(), h()); + needs_recalc_display(); // resize(x(), y(), w(), h()); } @@ -3836,6 +3848,13 @@ void Fl_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { This function tries to limit drawing to smaller areas if possible. */ void Fl_Text_Display::draw(void) { + + // recalc if needed -- issue #300 + if (needs_recalc_display_) { + needs_recalc_display_ = false; + recalc_display(); + } + // don't even try if there is no associated text buffer! if (!buffer()) { draw_box(); return; } @@ -3846,7 +3865,7 @@ void Fl_Text_Display::draw(void) { // draw the non-text, non-scrollbar areas. if (damage() & FL_DAMAGE_ALL) { - recalc_display(); + needs_recalc_display(); // printf("drawing all (box = %d)\n", box()); if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if to printer, draw the background