Merge branch 'dvc-last-col-resize'

Improve resizing of the last column in generic wxDataViewCtrl.

See https://github.com/wxWidgets/wxWidgets/pull/1077

Closes #18295.
This commit is contained in:
Vadim Zeitlin 2018-12-20 18:57:48 +01:00
commit 9877f207d1
3 changed files with 52 additions and 28 deletions

View File

@ -12,7 +12,6 @@
#include "wx/defs.h" #include "wx/defs.h"
#include "wx/object.h" #include "wx/object.h"
#include "wx/list.h"
#include "wx/control.h" #include "wx/control.h"
#include "wx/scrolwin.h" #include "wx/scrolwin.h"
#include "wx/icon.h" #include "wx/icon.h"
@ -74,6 +73,11 @@ public:
// UpdateWidth() if the width didn't really change, even if we don't // UpdateWidth() if the width didn't really change, even if we don't
// care about its return value. // care about its return value.
(void)WXUpdateWidth(width); (void)WXUpdateWidth(width);
// Do remember the last explicitly set width: this is used to prevent
// UpdateColumnSizes() from resizing the last column to be smaller than
// this size.
m_manuallySetWidth = width;
} }
virtual int GetWidth() const wxOVERRIDE; virtual int GetWidth() const wxOVERRIDE;
@ -137,9 +141,15 @@ public:
m_width = width; m_width = width;
UpdateWidth(); UpdateWidth();
// We must not update m_manuallySetWidth here as this method is called by
// UpdateColumnSizes() which resizes the column automatically, and not
// "manually".
return true; return true;
} }
int WXGetManuallySetWidth() const { return m_manuallySetWidth; }
private: private:
// common part of all ctors // common part of all ctors
void Init(int width, wxAlignment align, int flags); void Init(int width, wxAlignment align, int flags);
@ -152,6 +162,7 @@ private:
wxString m_title; wxString m_title;
int m_width, int m_width,
m_manuallySetWidth,
m_minWidth; m_minWidth;
wxAlignment m_align; wxAlignment m_align;
int m_flags; int m_flags;
@ -167,9 +178,6 @@ private:
// wxDataViewCtrl // wxDataViewCtrl
// --------------------------------------------------------- // ---------------------------------------------------------
WX_DECLARE_LIST_WITH_DECL(wxDataViewColumn, wxDataViewColumnList,
class WXDLLIMPEXP_CORE);
class WXDLLIMPEXP_CORE wxDataViewCtrl : public wxDataViewCtrlBase, class WXDLLIMPEXP_CORE wxDataViewCtrl : public wxDataViewCtrlBase,
public wxScrollHelper public wxScrollHelper
{ {
@ -354,7 +362,9 @@ private:
void InvalidateColBestWidth(int idx); void InvalidateColBestWidth(int idx);
void UpdateColWidths(); void UpdateColWidths();
wxDataViewColumnList m_cols; void DoClearColumns();
wxVector<wxDataViewColumn*> m_cols;
// cached column best widths information, 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
struct CachedColWidthInfo struct CachedColWidthInfo

View File

@ -793,7 +793,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
lc->AppendColumn(colRadio, "bool"); lc->AppendColumn(colRadio, "bool");
lc->AppendTextColumn( "Text" ); lc->AppendTextColumn( "Text" );
lc->AppendProgressColumn( "Progress" ); lc->AppendProgressColumn( "Progress" )->SetMinWidth(100);
wxVector<wxVariant> data; wxVector<wxVariant> data;
for (unsigned int i=0; i<10; i++) for (unsigned int i=0; i<10; i++)

View File

@ -180,7 +180,8 @@ wxTextCtrl *CreateEditorTextCtrl(wxWindow *parent, const wxRect& labelRect, cons
void wxDataViewColumn::Init(int width, wxAlignment align, int flags) void wxDataViewColumn::Init(int width, wxAlignment align, int flags)
{ {
m_width = width; m_width =
m_manuallySetWidth = width;
m_minWidth = 0; m_minWidth = 0;
m_align = align; m_align = align;
m_flags = flags; m_flags = flags;
@ -5022,20 +5023,25 @@ void wxDataViewMainWindow::UpdateColumnSizes()
int lastColX = colswidth - lastCol->GetWidth(); int lastColX = colswidth - lastCol->GetWidth();
if ( lastColX < fullWinWidth ) if ( lastColX < fullWinWidth )
{ {
int desiredWidth = wxMax(fullWinWidth - lastColX, lastCol->GetMinWidth()); const int availableWidth = fullWinWidth - lastColX;
if ( !lastCol->WXUpdateWidth(desiredWidth) )
// Never make the column automatically smaller than the last width it
// was explicitly given nor its minimum width.
if ( availableWidth <= wxMax(lastCol->GetMinWidth(),
lastCol->WXGetManuallySetWidth()) )
{ {
// The column width didn't change, no need to do anything else.
return; return;
} }
lastCol->WXUpdateWidth(availableWidth);
// All columns fit on screen, so we don't need horizontal scrolling. // All columns fit on screen, so we don't need horizontal scrolling.
// To prevent flickering scrollbar when resizing the window to be // To prevent flickering scrollbar when resizing the window to be
// narrower, force-set the virtual width to 0 here. It will eventually // narrower, force-set the virtual width to 0 here. It will eventually
// be corrected at idle time. // be corrected at idle time.
SetVirtualSize(0, m_virtualSize.y); SetVirtualSize(0, m_virtualSize.y);
RefreshRect(wxRect(lastColX, 0, fullWinWidth - lastColX, GetSize().y)); RefreshRect(wxRect(lastColX, 0, availableWidth, GetSize().y));
} }
else else
{ {
@ -5048,8 +5054,6 @@ void wxDataViewMainWindow::UpdateColumnSizes()
// wxDataViewCtrl // wxDataViewCtrl
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
WX_DEFINE_LIST(wxDataViewColumnList)
wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase); wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase);
wxBEGIN_EVENT_TABLE(wxDataViewCtrl, wxDataViewCtrlBase) wxBEGIN_EVENT_TABLE(wxDataViewCtrl, wxDataViewCtrlBase)
EVT_SIZE(wxDataViewCtrl::OnSize) EVT_SIZE(wxDataViewCtrl::OnSize)
@ -5060,8 +5064,7 @@ wxDataViewCtrl::~wxDataViewCtrl()
if (m_notifier) if (m_notifier)
GetModel()->RemoveNotifier( m_notifier ); GetModel()->RemoveNotifier( m_notifier );
m_cols.Clear(); DoClearColumns();
m_colsBestWidths.clear();
#if wxUSE_ACCESSIBILITY #if wxUSE_ACCESSIBILITY
SetAccessible(NULL); SetAccessible(NULL);
@ -5071,7 +5074,6 @@ wxDataViewCtrl::~wxDataViewCtrl()
void wxDataViewCtrl::Init() void wxDataViewCtrl::Init()
{ {
m_cols.DeleteContents(true);
m_notifier = NULL; m_notifier = NULL;
m_headerArea = NULL; m_headerArea = NULL;
@ -5172,9 +5174,6 @@ wxSize wxDataViewCtrl::GetSizeAvailableForScrollTarget(const wxSize& size)
void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) ) void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
{ {
if ( m_clientArea && GetColumnCount() )
m_clientArea->UpdateColumnSizes();
// We need to override OnSize so that our scrolled // We need to override OnSize so that our scrolled
// window a) does call Layout() to use sizers for // window a) does call Layout() to use sizers for
// positioning the controls but b) does not query // positioning the controls but b) does not query
@ -5186,6 +5185,11 @@ void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
AdjustScrollbars(); AdjustScrollbars();
// Update the last column size to take all the available space. Note that
// this must be done after calling Layout() to update m_clientArea size.
if ( m_clientArea && GetColumnCount() )
m_clientArea->UpdateColumnSizes();
// We must redraw the headers if their height changed. Normally this // We must redraw the headers if their height changed. Normally this
// shouldn't happen as the control shouldn't let itself be resized beneath // shouldn't happen as the control shouldn't let itself be resized beneath
// its minimal height but avoid the display artefacts that appear if it // its minimal height but avoid the display artefacts that appear if it
@ -5321,7 +5325,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
if (!wxDataViewCtrlBase::AppendColumn(col)) if (!wxDataViewCtrlBase::AppendColumn(col))
return false; return false;
m_cols.Append( col ); m_cols.push_back( col );
m_colsBestWidths.push_back(CachedColWidthInfo()); m_colsBestWidths.push_back(CachedColWidthInfo());
OnColumnsCountChanged(); OnColumnsCountChanged();
return true; return true;
@ -5332,7 +5336,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
if (!wxDataViewCtrlBase::PrependColumn(col)) if (!wxDataViewCtrlBase::PrependColumn(col))
return false; return false;
m_cols.Insert( col ); m_cols.insert(m_cols.begin(), col);
m_colsBestWidths.insert(m_colsBestWidths.begin(), CachedColWidthInfo()); m_colsBestWidths.insert(m_colsBestWidths.begin(), CachedColWidthInfo());
OnColumnsCountChanged(); OnColumnsCountChanged();
return true; return true;
@ -5343,7 +5347,7 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
if (!wxDataViewCtrlBase::InsertColumn(pos,col)) if (!wxDataViewCtrlBase::InsertColumn(pos,col))
return false; return false;
m_cols.Insert( pos, col ); m_cols.insert(m_cols.begin() + pos, col);
m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, CachedColWidthInfo()); m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, CachedColWidthInfo());
OnColumnsCountChanged(); OnColumnsCountChanged();
return true; return true;
@ -5392,7 +5396,7 @@ void wxDataViewCtrl::DoSetIndent()
unsigned int wxDataViewCtrl::GetColumnCount() const unsigned int wxDataViewCtrl::GetColumnCount() const
{ {
return m_cols.GetCount(); return m_cols.size();
} }
bool wxDataViewCtrl::SetRowHeight( int lineHeight ) bool wxDataViewCtrl::SetRowHeight( int lineHeight )
@ -5544,12 +5548,12 @@ void wxDataViewCtrl::ColumnMoved(wxDataViewColumn *col, unsigned int new_pos)
bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
{ {
wxDataViewColumnList::compatibility_iterator ret = m_cols.Find( column ); const int idx = GetColumnIndex(column);
if (!ret) if ( idx == wxNOT_FOUND )
return false; return false;
m_colsBestWidths.erase(m_colsBestWidths.begin() + GetColumnIndex(column)); m_colsBestWidths.erase(m_colsBestWidths.begin() + idx);
m_cols.Erase(ret); m_cols.erase(m_cols.begin() + idx);
if ( m_clientArea->GetCurrentColumn() == column ) if ( m_clientArea->GetCurrentColumn() == column )
m_clientArea->ClearCurrentColumn(); m_clientArea->ClearCurrentColumn();
@ -5559,10 +5563,20 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
return true; return true;
} }
void wxDataViewCtrl::DoClearColumns()
{
typedef wxVector<wxDataViewColumn*>::const_iterator citer;
for ( citer it = m_cols.begin(); it != m_cols.end(); ++it )
delete *it;
}
bool wxDataViewCtrl::ClearColumns() bool wxDataViewCtrl::ClearColumns()
{ {
SetExpanderColumn(NULL); SetExpanderColumn(NULL);
m_cols.Clear();
DoClearColumns();
m_cols.clear();
m_sortingColumnIdxs.clear(); m_sortingColumnIdxs.clear();
m_colsBestWidths.clear(); m_colsBestWidths.clear();