From 841c14c37c878dff35a552626c77c7d7a44ff558 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 13 Dec 2018 18:50:18 +0100 Subject: [PATCH 1/5] Fix expanding last wxDataViewCtrl column in the generic version The code added in 4156e1a5c94283cb037132518dfb80dbc1403e12 didn't quite work correctly because it used the old size of the window, before it was resized, and not the new size. This was almost unnoticeable when drag-resizing the window, but very noticeable when maximizing the containing TLW, as could be seen on the 3rd page of the dataview sample, for example, where the last column kept its size instead of expanding. See #13904, #18295. --- src/generic/datavgen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index f94700b072..c5aad72db8 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -5172,9 +5172,6 @@ wxSize wxDataViewCtrl::GetSizeAvailableForScrollTarget(const wxSize& size) void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) ) { - if ( m_clientArea && GetColumnCount() ) - m_clientArea->UpdateColumnSizes(); - // We need to override OnSize so that our scrolled // window a) does call Layout() to use sizers for // positioning the controls but b) does not query @@ -5186,6 +5183,11 @@ void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) ) 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 // 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 From 24054c95d8313cc41cb215f34352fc4d206473d1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 13 Dec 2018 23:42:15 +0100 Subject: [PATCH 2/5] Prevent the user from resizing the last wxDataViewCtrl column This is useless as this column will be automatically expanded to fill all the available space anyhow. See #18295. --- include/wx/generic/dataview.h | 2 ++ src/generic/datavgen.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 815dfcb75b..2ee210ceac 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -107,6 +107,8 @@ public: return m_flags; } + virtual bool IsResizeable() const wxOVERRIDE; + virtual bool IsSortKey() const wxOVERRIDE { return m_sort; diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index c5aad72db8..5df51937e1 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -256,6 +256,17 @@ void wxDataViewColumn::SetSortOrder(bool ascending) m_owner->OnColumnChange(idx); } +bool wxDataViewColumn::IsResizeable() const +{ + // The last column in generic wxDataViewCtrl is never resizeable by the + // user because it's always automatically expanded to consume all the + // available space, so prevent the user from resizing it. + if ( this == GetOwner()->GetColumn(GetOwner()->GetColumnCount() - 1) ) + return false; + + return wxDataViewColumnBase::IsResizeable(); +} + //----------------------------------------------------------------------------- // wxDataViewHeaderWindow //----------------------------------------------------------------------------- From 68bb67c009beb850cb5e59ea222071b051f112d4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 13 Dec 2018 23:46:25 +0100 Subject: [PATCH 3/5] Revert "Prevent the user from resizing the last wxDataViewCtrl column" This reverts commit 24054c95d8313cc41cb215f34352fc4d206473d1 as it actually should be possible to increase the size of the last column, even if this shows the horizontal scroll bar. --- include/wx/generic/dataview.h | 2 -- src/generic/datavgen.cpp | 11 ----------- 2 files changed, 13 deletions(-) diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 2ee210ceac..815dfcb75b 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -107,8 +107,6 @@ public: return m_flags; } - virtual bool IsResizeable() const wxOVERRIDE; - virtual bool IsSortKey() const wxOVERRIDE { return m_sort; diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 5df51937e1..c5aad72db8 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -256,17 +256,6 @@ void wxDataViewColumn::SetSortOrder(bool ascending) m_owner->OnColumnChange(idx); } -bool wxDataViewColumn::IsResizeable() const -{ - // The last column in generic wxDataViewCtrl is never resizeable by the - // user because it's always automatically expanded to consume all the - // available space, so prevent the user from resizing it. - if ( this == GetOwner()->GetColumn(GetOwner()->GetColumnCount() - 1) ) - return false; - - return wxDataViewColumnBase::IsResizeable(); -} - //----------------------------------------------------------------------------- // wxDataViewHeaderWindow //----------------------------------------------------------------------------- From 2340a16d180472b1efc4009a693d7aaf0771f21c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 15 Dec 2018 14:27:52 +0100 Subject: [PATCH 4/5] Allow increasing the size of the last column in wxDataViewCtrl Previously, the last column couldn't be effectively resized at all, as its size was always automatically set to the remaining width of the window after subtracting the widths of all the previous columns. Now this is only done if this remaining width is greater than the width given to the column by the user or by the program. Effectively, this means that the user can now drag-resize the column to increase its size (at the price of showing the horizontal scrollbar). See #18295. --- include/wx/generic/dataview.h | 12 ++++++++++++ samples/dataview/dataview.cpp | 2 +- src/generic/datavgen.cpp | 16 +++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 815dfcb75b..bef6ab1f97 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -74,6 +74,11 @@ public: // UpdateWidth() if the width didn't really change, even if we don't // care about its return value. (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; @@ -137,9 +142,15 @@ public: m_width = width; 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; } + int WXGetManuallySetWidth() const { return m_manuallySetWidth; } + private: // common part of all ctors void Init(int width, wxAlignment align, int flags); @@ -152,6 +163,7 @@ private: wxString m_title; int m_width, + m_manuallySetWidth, m_minWidth; wxAlignment m_align; int m_flags; diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 51273a6106..9d654828d6 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -793,7 +793,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l lc->AppendColumn(colRadio, "bool"); lc->AppendTextColumn( "Text" ); - lc->AppendProgressColumn( "Progress" ); + lc->AppendProgressColumn( "Progress" )->SetMinWidth(100); wxVector data; for (unsigned int i=0; i<10; i++) diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index c5aad72db8..80c7c7aa2c 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -180,7 +180,8 @@ wxTextCtrl *CreateEditorTextCtrl(wxWindow *parent, const wxRect& labelRect, cons void wxDataViewColumn::Init(int width, wxAlignment align, int flags) { - m_width = width; + m_width = + m_manuallySetWidth = width; m_minWidth = 0; m_align = align; m_flags = flags; @@ -5022,20 +5023,25 @@ void wxDataViewMainWindow::UpdateColumnSizes() int lastColX = colswidth - lastCol->GetWidth(); if ( lastColX < fullWinWidth ) { - int desiredWidth = wxMax(fullWinWidth - lastColX, lastCol->GetMinWidth()); - if ( !lastCol->WXUpdateWidth(desiredWidth) ) + const int availableWidth = fullWinWidth - lastColX; + + // 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; } + lastCol->WXUpdateWidth(availableWidth); + // All columns fit on screen, so we don't need horizontal scrolling. // To prevent flickering scrollbar when resizing the window to be // narrower, force-set the virtual width to 0 here. It will eventually // be corrected at idle time. SetVirtualSize(0, m_virtualSize.y); - RefreshRect(wxRect(lastColX, 0, fullWinWidth - lastColX, GetSize().y)); + RefreshRect(wxRect(lastColX, 0, availableWidth, GetSize().y)); } else { From 8856715d2d0f4e630de50e81fda4b8bd355060c1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 15 Dec 2018 14:39:38 +0100 Subject: [PATCH 5/5] Use wxVector instead of wxList for wxDataViewCtrl columns storage As wxDataViewColumnList was never public, it should be fine to not define it any more and use a vector instead. This makes the code more clear and also marginally more efficient. --- include/wx/generic/dataview.h | 8 +++----- src/generic/datavgen.cpp | 34 ++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index bef6ab1f97..6742e048ba 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -12,7 +12,6 @@ #include "wx/defs.h" #include "wx/object.h" -#include "wx/list.h" #include "wx/control.h" #include "wx/scrolwin.h" #include "wx/icon.h" @@ -179,9 +178,6 @@ private: // wxDataViewCtrl // --------------------------------------------------------- -WX_DECLARE_LIST_WITH_DECL(wxDataViewColumn, wxDataViewColumnList, - class WXDLLIMPEXP_CORE); - class WXDLLIMPEXP_CORE wxDataViewCtrl : public wxDataViewCtrlBase, public wxScrollHelper { @@ -366,7 +362,9 @@ private: void InvalidateColBestWidth(int idx); void UpdateColWidths(); - wxDataViewColumnList m_cols; + void DoClearColumns(); + + wxVector m_cols; // cached column best widths information, values are for // respective columns from m_cols and the arrays have same size struct CachedColWidthInfo diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 80c7c7aa2c..2ea515ae00 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -5054,8 +5054,6 @@ void wxDataViewMainWindow::UpdateColumnSizes() // wxDataViewCtrl //----------------------------------------------------------------------------- -WX_DEFINE_LIST(wxDataViewColumnList) - wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase); wxBEGIN_EVENT_TABLE(wxDataViewCtrl, wxDataViewCtrlBase) EVT_SIZE(wxDataViewCtrl::OnSize) @@ -5066,8 +5064,7 @@ wxDataViewCtrl::~wxDataViewCtrl() if (m_notifier) GetModel()->RemoveNotifier( m_notifier ); - m_cols.Clear(); - m_colsBestWidths.clear(); + DoClearColumns(); #if wxUSE_ACCESSIBILITY SetAccessible(NULL); @@ -5077,7 +5074,6 @@ wxDataViewCtrl::~wxDataViewCtrl() void wxDataViewCtrl::Init() { - m_cols.DeleteContents(true); m_notifier = NULL; m_headerArea = NULL; @@ -5329,7 +5325,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) if (!wxDataViewCtrlBase::AppendColumn(col)) return false; - m_cols.Append( col ); + m_cols.push_back( col ); m_colsBestWidths.push_back(CachedColWidthInfo()); OnColumnsCountChanged(); return true; @@ -5340,7 +5336,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col ) if (!wxDataViewCtrlBase::PrependColumn(col)) return false; - m_cols.Insert( col ); + m_cols.insert(m_cols.begin(), col); m_colsBestWidths.insert(m_colsBestWidths.begin(), CachedColWidthInfo()); OnColumnsCountChanged(); return true; @@ -5351,7 +5347,7 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col ) if (!wxDataViewCtrlBase::InsertColumn(pos,col)) return false; - m_cols.Insert( pos, col ); + m_cols.insert(m_cols.begin() + pos, col); m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, CachedColWidthInfo()); OnColumnsCountChanged(); return true; @@ -5400,7 +5396,7 @@ void wxDataViewCtrl::DoSetIndent() unsigned int wxDataViewCtrl::GetColumnCount() const { - return m_cols.GetCount(); + return m_cols.size(); } bool wxDataViewCtrl::SetRowHeight( int lineHeight ) @@ -5552,12 +5548,12 @@ void wxDataViewCtrl::ColumnMoved(wxDataViewColumn *col, unsigned int new_pos) bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) { - wxDataViewColumnList::compatibility_iterator ret = m_cols.Find( column ); - if (!ret) + const int idx = GetColumnIndex(column); + if ( idx == wxNOT_FOUND ) return false; - m_colsBestWidths.erase(m_colsBestWidths.begin() + GetColumnIndex(column)); - m_cols.Erase(ret); + m_colsBestWidths.erase(m_colsBestWidths.begin() + idx); + m_cols.erase(m_cols.begin() + idx); if ( m_clientArea->GetCurrentColumn() == column ) m_clientArea->ClearCurrentColumn(); @@ -5567,10 +5563,20 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) return true; } +void wxDataViewCtrl::DoClearColumns() +{ + typedef wxVector::const_iterator citer; + for ( citer it = m_cols.begin(); it != m_cols.end(); ++it ) + delete *it; +} + bool wxDataViewCtrl::ClearColumns() { SetExpanderColumn(NULL); - m_cols.Clear(); + + DoClearColumns(); + + m_cols.clear(); m_sortingColumnIdxs.clear(); m_colsBestWidths.clear();