diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 3411de34ee..6ebf09a1d0 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -1065,6 +1065,16 @@ public: return wxGridCellAttrPtr(GetAttr(row, col, kind)); } + // This is an optimization for a common case when the entire column uses + // roughly the same attribute, which can thus be reused for measuring all + // the cells in this column. Override this to return true (possibly for + // some columns only) to speed up AutoSizeColumns() for the grids using + // this table. + virtual bool CanMeasureColUsingSameAttr(int WXUNUSED(col)) const + { + return false; + } + // these functions take ownership of the pointer virtual void SetAttr(wxGridCellAttr* attr, int row, int col); virtual void SetRowAttr(wxGridCellAttr *attr, int row); diff --git a/interface/wx/grid.h b/interface/wx/grid.h index 33edf24f5f..c15e466735 100644 --- a/interface/wx/grid.h +++ b/interface/wx/grid.h @@ -2517,6 +2517,25 @@ public: returns @true. */ virtual bool CanHaveAttributes(); + + /** + Override to return true if the same attribute can be used for measuring + all cells in the given column. + + This function is provided for optimization purposes: it returns @false + by default, but can be overridden to return @true when all the cells in + the same grid column use sensibly the same attribute, i.e. they use the + same renderer (either explicitly, or implicitly, due to their type as + returned by GetTypeName()) and the font of the same size. + + Returning @true from this function allows AutoSizeColumns() to skip + looking up the attribute and the renderer for each individual cell, + which results in very noticeable performance improvements for the grids + with many rows. + + @since 3.1.4 + */ + virtual bool CanMeasureColUsingSameAttr(int col) const; }; diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 80d26edf90..ec102e3f69 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -9967,6 +9967,14 @@ wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction) col = -1; } + // If possible, reuse the same attribute and renderer for all cells: this + // is an important optimization (resulting in up to 80% speed up of + // AutoSizeColumns()) as finding the attribute and renderer for the cell + // are very slow operations, due to the number of steps involved in them. + const bool canReuseAttr = column && m_table->CanMeasureColUsingSameAttr(col); + wxGridCellAttrPtr attr; + wxGridCellRendererPtr renderer; + wxCoord extent, extentMax = 0; int max = column ? m_numRows : m_numCols; for ( int rowOrCol = 0; rowOrCol < max; rowOrCol++ ) @@ -10005,8 +10013,12 @@ wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction) } // get cell ( main cell if CellSpan_Inside ) renderer best size - wxGridCellAttrPtr attr = GetCellAttrPtr(row, col); - wxGridCellRendererPtr renderer = attr->GetRendererPtr(this, row, col); + if ( !canReuseAttr || !attr ) + { + attr = GetCellAttrPtr(row, col); + renderer = attr->GetRendererPtr(this, row, col); + } + if ( renderer ) { extent = column