From 840fc4d170537fc613609571f1b47bd1bdc7700b Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Mon, 30 Apr 2012 09:33:30 +0000 Subject: [PATCH] wxDataViewCtrl: always update the header when col best width changes. Have an explicit per-column dirty flag and use that to determine whether we need to call wxHeaderCtrl::UpdateColumn(). Previously, the lack of computed best width was used as an indicator, but this didn't work correctly if some code called GetWidth() after invalidation but before wxDataViewCtrl::UpdateColWidths() was called at idle time. This resulted in header's column widths getting out of sync with the control itself. Fixes #14167. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71335 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/dataview.h | 14 +++++++++++--- src/generic/datavgen.cpp | 34 +++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 89b0461623..9115dcb3ca 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -242,10 +242,18 @@ private: void UpdateColWidths(); wxDataViewColumnList m_cols; - // cached column best widths or 0 if not computed, values are for + // cached column best widths information, values are for // respective columns from m_cols and the arrays have same size - wxVector m_colsBestWidths; - // m_colsBestWidths partially invalid, needs recomputing + struct CachedColWidthInfo + { + CachedColWidthInfo() : width(0), dirty(true) {} + int width; // cached width or 0 if not computed + bool dirty; // column was invalidated, header needs updating + }; + wxVector m_colsBestWidths; + // This indicates that at least one entry in m_colsBestWidths has 'dirty' + // flag set. It's cheaper to check one flag in OnInternalIdle() than to + // iterate over m_colsBestWidths to check if anything needs to be done. bool m_colsDirty; wxDataViewModelNotifier *m_notifier; diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 8d6490805b..f500ec27ee 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -4547,7 +4547,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) return false; m_cols.Append( col ); - m_colsBestWidths.push_back(0); + m_colsBestWidths.push_back(CachedColWidthInfo()); OnColumnsCountChanged(); return true; } @@ -4558,7 +4558,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col ) return false; m_cols.Insert( col ); - m_colsBestWidths.insert(m_colsBestWidths.begin(), 0); + m_colsBestWidths.insert(m_colsBestWidths.begin(), CachedColWidthInfo()); OnColumnsCountChanged(); return true; } @@ -4569,7 +4569,7 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col ) return false; m_cols.Insert( pos, col ); - m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, 0); + m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, CachedColWidthInfo()); OnColumnsCountChanged(); return true; } @@ -4644,8 +4644,8 @@ int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn *column) const unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const { - if ( m_colsBestWidths[idx] != 0 ) - return m_colsBestWidths[idx]; + if ( m_colsBestWidths[idx].width != 0 ) + return m_colsBestWidths[idx].width; const int count = m_clientArea->GetRowCount(); wxDataViewColumn *column = GetColumn(idx); @@ -4795,7 +4795,7 @@ unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const if ( max_width > 0 ) max_width += 2 * PADDING_RIGHTLEFT; - const_cast(this)->m_colsBestWidths[idx] = max_width; + const_cast(this)->m_colsBestWidths[idx].width = max_width; return max_width; } @@ -4840,12 +4840,14 @@ bool wxDataViewCtrl::ClearColumns() void wxDataViewCtrl::InvalidateColBestWidth(int idx) { - m_colsBestWidths[idx] = 0; + m_colsBestWidths[idx].width = 0; + m_colsBestWidths[idx].dirty = true; m_colsDirty = true; } void wxDataViewCtrl::InvalidateColBestWidths() { + // mark all columns as dirty: m_colsBestWidths.clear(); m_colsBestWidths.resize(m_cols.size()); m_colsDirty = true; @@ -4853,14 +4855,27 @@ void wxDataViewCtrl::InvalidateColBestWidths() void wxDataViewCtrl::UpdateColWidths() { + m_colsDirty = false; + if ( !m_headerArea ) return; const unsigned len = m_colsBestWidths.size(); for ( unsigned i = 0; i < len; i++ ) { - if ( m_colsBestWidths[i] == 0 ) + // Note that we have to have an explicit 'dirty' flag here instead of + // checking if the width==0, as is done in GetBestColumnWidth(). + // + // Testing width==0 wouldn't work correctly if some code called + // GetWidth() after col. width invalidation but before + // wxDataViewCtrl::UpdateColWidths() was called at idle time. This + // would result in the header's column width getting out of sync with + // the control itself. + if ( m_colsBestWidths[i].dirty ) + { m_headerArea->UpdateColumn(i); + m_colsBestWidths[i].dirty = false; + } } } @@ -4869,10 +4884,7 @@ void wxDataViewCtrl::OnInternalIdle() wxDataViewCtrlBase::OnInternalIdle(); if ( m_colsDirty ) - { - m_colsDirty = false; UpdateColWidths(); - } } int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const -- 2.45.2