From 96de24d1bb4cf61d6accaccdcb338ce4d660d770 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 13 Jun 2020 16:10:14 +0200 Subject: [PATCH] Add wxGridCellChoiceRenderer to optimize column size calculation Previously columns using a set of predetermined values used plain wxGridCellStringRenderer, which didn't allow to determine their best size efficiently, as wxGrid had to iterate over all the rows of the table, even if they only took a couple of possible values. Add wxGridCellChoiceRenderer (refactoring wxGridCellEnumRenderer to extract the common code from it in the process) which implements GetMaxBestSize() by just finding the best size of all of these values, which is much faster for large grids. This does result in a change in behaviour, as the column now adapts to its "theoretical" best size and not just the size of the values actually shown in it, but this seems to be a worthwhile trade-off and could even be seen as an advantage, as editing a cell won't make its value overflow the auto-sized column width any more, as it is wide enough to show any of the column values. --- include/wx/generic/gridctrl.h | 41 ++++++++++++++++------ src/generic/grid.cpp | 2 +- src/generic/gridctrl.cpp | 64 +++++++++++++++++------------------ 3 files changed, 63 insertions(+), 44 deletions(-) diff --git a/include/wx/generic/gridctrl.h b/include/wx/generic/gridctrl.h index 68e3f08323..0991110ba8 100644 --- a/include/wx/generic/gridctrl.h +++ b/include/wx/generic/gridctrl.h @@ -221,8 +221,37 @@ protected: #endif // wxUSE_DATETIME +// Renderer for fields taking one of a limited set of values: this is the same +// as the renderer for strings, except that it can implement GetMaxBestSize(). +class WXDLLIMPEXP_ADV wxGridCellChoiceRenderer : public wxGridCellStringRenderer +{ +public: + wxGridCellChoiceRenderer() { } + + virtual wxSize GetMaxBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc) wxOVERRIDE; + + // Parameters string is a comma-separated list of values. + virtual void SetParameters(const wxString& params) wxOVERRIDE; + + virtual wxGridCellRenderer *Clone() const wxOVERRIDE + { + return new wxGridCellChoiceRenderer(*this); + } + +protected: + wxGridCellChoiceRenderer(const wxGridCellChoiceRenderer& other) + : m_choices(other.m_choices) + { + } + + wxArrayString m_choices; +}; + + // renders a number using the corresponding text string -class WXDLLIMPEXP_ADV wxGridCellEnumRenderer : public wxGridCellStringRenderer +class WXDLLIMPEXP_ADV wxGridCellEnumRenderer : public wxGridCellChoiceRenderer { public: wxGridCellEnumRenderer( const wxString& choices = wxEmptyString ); @@ -240,20 +269,10 @@ public: wxDC& dc, int row, int col) wxOVERRIDE; - virtual wxSize GetMaxBestSize(wxGrid& grid, - wxGridCellAttr& attr, - wxDC& dc) wxOVERRIDE; - virtual wxGridCellRenderer *Clone() const wxOVERRIDE; - // parameters string format is "item1[,item2[...,itemN]]" where itemN will - // be used if the cell value is N-1 - virtual void SetParameters(const wxString& params) wxOVERRIDE; - protected: wxString GetString(const wxGrid& grid, int row, int col); - - wxArrayString m_choices; }; diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index cbf2658f7b..ec8aeaddbc 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -11017,7 +11017,7 @@ int wxGridTypeRegistry::FindDataType(const wxString& typeName) if ( typeName == wxGRID_VALUE_CHOICE ) { RegisterDataType(wxGRID_VALUE_CHOICE, - new wxGridCellStringRenderer, + new wxGridCellChoiceRenderer, new wxGridCellChoiceEditor); } else diff --git a/src/generic/gridctrl.cpp b/src/generic/gridctrl.cpp index bb9e3dd12c..4f2860912c 100644 --- a/src/generic/gridctrl.cpp +++ b/src/generic/gridctrl.cpp @@ -212,6 +212,38 @@ bool wxGridCellDateTimeRenderer::Parse(const wxString& text, wxDateTime& result) #endif // wxUSE_DATETIME +// ---------------------------------------------------------------------------- +// wxGridCellChoiceRenderer +// ---------------------------------------------------------------------------- + +wxSize wxGridCellChoiceRenderer::GetMaxBestSize(wxGrid& WXUNUSED(grid), + wxGridCellAttr& attr, + wxDC& dc) +{ + wxSize size; + + for ( size_t n = 0; n < m_choices.size(); ++n ) + { + size.IncTo(DoGetBestSize(attr, dc, m_choices[n])); + } + + return size; +} + +void wxGridCellChoiceRenderer::SetParameters(const wxString& params) +{ + m_choices.clear(); + + if ( params.empty() ) + return; + + wxStringTokenizer tk(params, wxT(',')); + while ( tk.HasMoreTokens() ) + { + m_choices.Add(tk.GetNextToken()); + } +} + // ---------------------------------------------------------------------------- // wxGridCellEnumRenderer // ---------------------------------------------------------------------------- @@ -278,38 +310,6 @@ wxSize wxGridCellEnumRenderer::GetBestSize(wxGrid& grid, return DoGetBestSize(attr, dc, GetString(grid, row, col)); } -wxSize wxGridCellEnumRenderer::GetMaxBestSize(wxGrid& WXUNUSED(grid), - wxGridCellAttr& attr, - wxDC& dc) -{ - wxSize size; - - for ( size_t n = 0; n < m_choices.size(); ++n ) - { - size.IncTo(DoGetBestSize(attr, dc, m_choices[n])); - } - - return size; -} - -void wxGridCellEnumRenderer::SetParameters(const wxString& params) -{ - if ( !params ) - { - // what can we do? - return; - } - - m_choices.Empty(); - - wxStringTokenizer tk(params, wxT(',')); - while ( tk.HasMoreTokens() ) - { - m_choices.Add(tk.GetNextToken()); - } -} - - // ---------------------------------------------------------------------------- // wxGridCellAutoWrapStringRenderer // ----------------------------------------------------------------------------