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
This commit is contained in:
@@ -242,10 +242,18 @@ private:
|
|||||||
void UpdateColWidths();
|
void UpdateColWidths();
|
||||||
|
|
||||||
wxDataViewColumnList m_cols;
|
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
|
// respective columns from m_cols and the arrays have same size
|
||||||
wxVector<int> m_colsBestWidths;
|
struct CachedColWidthInfo
|
||||||
// m_colsBestWidths partially invalid, needs recomputing
|
{
|
||||||
|
CachedColWidthInfo() : width(0), dirty(true) {}
|
||||||
|
int width; // cached width or 0 if not computed
|
||||||
|
bool dirty; // column was invalidated, header needs updating
|
||||||
|
};
|
||||||
|
wxVector<CachedColWidthInfo> 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;
|
bool m_colsDirty;
|
||||||
|
|
||||||
wxDataViewModelNotifier *m_notifier;
|
wxDataViewModelNotifier *m_notifier;
|
||||||
|
@@ -4547,7 +4547,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_cols.Append( col );
|
m_cols.Append( col );
|
||||||
m_colsBestWidths.push_back(0);
|
m_colsBestWidths.push_back(CachedColWidthInfo());
|
||||||
OnColumnsCountChanged();
|
OnColumnsCountChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -4558,7 +4558,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_cols.Insert( col );
|
m_cols.Insert( col );
|
||||||
m_colsBestWidths.insert(m_colsBestWidths.begin(), 0);
|
m_colsBestWidths.insert(m_colsBestWidths.begin(), CachedColWidthInfo());
|
||||||
OnColumnsCountChanged();
|
OnColumnsCountChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -4569,7 +4569,7 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_cols.Insert( pos, col );
|
m_cols.Insert( pos, col );
|
||||||
m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, 0);
|
m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, CachedColWidthInfo());
|
||||||
OnColumnsCountChanged();
|
OnColumnsCountChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -4644,8 +4644,8 @@ int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn *column) const
|
|||||||
|
|
||||||
unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
|
unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
|
||||||
{
|
{
|
||||||
if ( m_colsBestWidths[idx] != 0 )
|
if ( m_colsBestWidths[idx].width != 0 )
|
||||||
return m_colsBestWidths[idx];
|
return m_colsBestWidths[idx].width;
|
||||||
|
|
||||||
const int count = m_clientArea->GetRowCount();
|
const int count = m_clientArea->GetRowCount();
|
||||||
wxDataViewColumn *column = GetColumn(idx);
|
wxDataViewColumn *column = GetColumn(idx);
|
||||||
@@ -4795,7 +4795,7 @@ unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
|
|||||||
if ( max_width > 0 )
|
if ( max_width > 0 )
|
||||||
max_width += 2 * PADDING_RIGHTLEFT;
|
max_width += 2 * PADDING_RIGHTLEFT;
|
||||||
|
|
||||||
const_cast<wxDataViewCtrl*>(this)->m_colsBestWidths[idx] = max_width;
|
const_cast<wxDataViewCtrl*>(this)->m_colsBestWidths[idx].width = max_width;
|
||||||
return max_width;
|
return max_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4840,12 +4840,14 @@ bool wxDataViewCtrl::ClearColumns()
|
|||||||
|
|
||||||
void wxDataViewCtrl::InvalidateColBestWidth(int idx)
|
void wxDataViewCtrl::InvalidateColBestWidth(int idx)
|
||||||
{
|
{
|
||||||
m_colsBestWidths[idx] = 0;
|
m_colsBestWidths[idx].width = 0;
|
||||||
|
m_colsBestWidths[idx].dirty = true;
|
||||||
m_colsDirty = true;
|
m_colsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDataViewCtrl::InvalidateColBestWidths()
|
void wxDataViewCtrl::InvalidateColBestWidths()
|
||||||
{
|
{
|
||||||
|
// mark all columns as dirty:
|
||||||
m_colsBestWidths.clear();
|
m_colsBestWidths.clear();
|
||||||
m_colsBestWidths.resize(m_cols.size());
|
m_colsBestWidths.resize(m_cols.size());
|
||||||
m_colsDirty = true;
|
m_colsDirty = true;
|
||||||
@@ -4853,14 +4855,27 @@ void wxDataViewCtrl::InvalidateColBestWidths()
|
|||||||
|
|
||||||
void wxDataViewCtrl::UpdateColWidths()
|
void wxDataViewCtrl::UpdateColWidths()
|
||||||
{
|
{
|
||||||
|
m_colsDirty = false;
|
||||||
|
|
||||||
if ( !m_headerArea )
|
if ( !m_headerArea )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unsigned len = m_colsBestWidths.size();
|
const unsigned len = m_colsBestWidths.size();
|
||||||
for ( unsigned i = 0; i < len; i++ )
|
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_headerArea->UpdateColumn(i);
|
||||||
|
m_colsBestWidths[i].dirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4869,11 +4884,8 @@ void wxDataViewCtrl::OnInternalIdle()
|
|||||||
wxDataViewCtrlBase::OnInternalIdle();
|
wxDataViewCtrlBase::OnInternalIdle();
|
||||||
|
|
||||||
if ( m_colsDirty )
|
if ( m_colsDirty )
|
||||||
{
|
|
||||||
m_colsDirty = false;
|
|
||||||
UpdateColWidths();
|
UpdateColWidths();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
|
int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user