Correct implement wxLIST_AUTOSIZE_XXX in the generic wxListCtrl.

Use both the contents and the header width when wxLIST_AUTOSIZE_USEHEADER is
given instead of just the latter.

Also make both wxLIST_AUTOSIZE_USEHEADER and the previously implemented
wxLIST_AUTOSIZE work efficiently for the virtual list controls by reusing
wxMaxWidthCalculatorBase already used in the generic wxDataViewCtrl.

Closes #10326.

(this is a backport of de7e315557 and
0e2d9e539c from master)
This commit is contained in:
Kinaou Hervé
2015-03-11 22:02:23 +01:00
committed by Vadim Zeitlin
parent c21ad5d9c2
commit b64e030f0c
5 changed files with 95 additions and 60 deletions

View File

@@ -596,6 +596,7 @@ All (GUI):
wxGenericFileDialog which was accidentally lost some time ago (Carl Godkin). wxGenericFileDialog which was accidentally lost some time ago (Carl Godkin).
- Fix handling of fast consecutive clicks in wxRibbonBar (atobi). - Fix handling of fast consecutive clicks in wxRibbonBar (atobi).
- Fix updating nested window scrollbars in some cases (sbrowne). - Fix updating nested window scrollbars in some cases (sbrowne).
- Improve wxLIST_AUTOSIZE_XXX support in generic wxListCtrl (Kinaou Hervé).
- Fix wxPGChoices copy ctor (Snoits). - Fix wxPGChoices copy ctor (Snoits).
- Fix wxPixelData<wxImage>::Offset() for alpha (Markus Rollmann). - Fix wxPixelData<wxImage>::Offset() for alpha (Markus Rollmann).
- Fix bug in wxImage::ClearAlpha() for shared data (Markus Rollmann). - Fix bug in wxImage::ClearAlpha() for shared data (Markus Rollmann).

View File

@@ -863,6 +863,7 @@ private:
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
friend class wxGenericListCtrl; friend class wxGenericListCtrl;
friend class wxListCtrlMaxWidthCalculator;
}; };
#endif // wxUSE_LISTCTRL #endif // wxUSE_LISTCTRL

View File

@@ -11,7 +11,7 @@
#include "wx/defs.h" #include "wx/defs.h"
#if wxUSE_DATAVIEWCTRL #if wxUSE_DATAVIEWCTRL || wxUSE_LISTCTRL
#include "wx/timer.h" #include "wx/timer.h"
@@ -117,6 +117,6 @@ private:
wxDECLARE_NO_COPY_CLASS(wxMaxWidthCalculatorBase); wxDECLARE_NO_COPY_CLASS(wxMaxWidthCalculatorBase);
}; };
#endif // wxUSE_DATAVIEWCTRL #endif // wxUSE_DATAVIEWCTRL || wxUSE_LISTCTRL
#endif // _WX_GENERIC_PRIVATE_WIDTHCALC_H_ #endif // _WX_GENERIC_PRIVATE_WIDTHCALC_H_

View File

@@ -519,11 +519,11 @@ void MyFrame::InitWithReportItems()
itemCol.SetImage(-1); itemCol.SetImage(-1);
m_listCtrl->InsertColumn(0, itemCol); m_listCtrl->InsertColumn(0, itemCol);
itemCol.SetText(wxT("Column 2")); itemCol.SetText(wxT("Column 2 (auto size excluding header)"));
itemCol.SetAlign(wxLIST_FORMAT_CENTRE); itemCol.SetAlign(wxLIST_FORMAT_CENTRE);
m_listCtrl->InsertColumn(1, itemCol); m_listCtrl->InsertColumn(1, itemCol);
itemCol.SetText(wxT("Column 3")); itemCol.SetText(wxT("Column 3 (auto size including header)"));
itemCol.SetAlign(wxLIST_FORMAT_RIGHT); itemCol.SetAlign(wxLIST_FORMAT_RIGHT);
m_listCtrl->InsertColumn(2, itemCol); m_listCtrl->InsertColumn(2, itemCol);
@@ -558,10 +558,6 @@ void MyFrame::InitWithReportItems()
m_listCtrl->SetTextColour(*wxBLUE); m_listCtrl->SetTextColour(*wxBLUE);
m_listCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE );
m_listCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE );
m_listCtrl->SetColumnWidth( 2, wxLIST_AUTOSIZE );
// Set images in columns // Set images in columns
m_listCtrl->SetItemColumnImage(1, 1, 0); m_listCtrl->SetItemColumnImage(1, 1, 0);
@@ -573,6 +569,10 @@ void MyFrame::InitWithReportItems()
// test SetItemFont too // test SetItemFont too
m_listCtrl->SetItemFont(0, *wxITALIC_FONT); m_listCtrl->SetItemFont(0, *wxITALIC_FONT);
m_listCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE );
m_listCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE );
m_listCtrl->SetColumnWidth( 2, wxLIST_AUTOSIZE_USEHEADER );
} }
void MyFrame::InitWithIconItems(bool withText, bool sameIcon) void MyFrame::InitWithIconItems(bool withText, bool sameIcon)
@@ -671,11 +671,11 @@ void MyFrame::InitWithVirtualItems()
} }
else else
{ {
m_listCtrl->AppendColumn(wxT("First Column")); m_listCtrl->AppendColumn(wxT("First Column (size auto)"));
m_listCtrl->AppendColumn(wxT("Second Column")); m_listCtrl->AppendColumn(wxT("Second Column (150px)"));
m_listCtrl->SetColumnWidth(0, 150);
m_listCtrl->SetColumnWidth(1, 150);
m_listCtrl->SetItemCount(1000000); m_listCtrl->SetItemCount(1000000);
m_listCtrl->SetColumnWidth(0, wxLIST_AUTOSIZE_USEHEADER);
m_listCtrl->SetColumnWidth(1, 150);
} }
} }

View File

@@ -39,6 +39,7 @@
#include "wx/imaglist.h" #include "wx/imaglist.h"
#include "wx/renderer.h" #include "wx/renderer.h"
#include "wx/generic/private/listctrl.h" #include "wx/generic/private/listctrl.h"
#include "wx/generic/private/widthcalc.h"
#ifdef __WXMAC__ #ifdef __WXMAC__
#include "wx/osx/private.h" #include "wx/osx/private.h"
@@ -3193,6 +3194,35 @@ void wxListMainWindow::SetColumn( int col, const wxListItem &item )
m_headerWidth = 0; m_headerWidth = 0;
} }
class wxListCtrlMaxWidthCalculator : public wxMaxWidthCalculatorBase
{
public:
wxListCtrlMaxWidthCalculator(wxListMainWindow *listmain, unsigned int column)
: wxMaxWidthCalculatorBase(column),
m_listmain(listmain)
{
}
virtual void UpdateWithRow(int row) wxOVERRIDE
{
wxListLineData *line = m_listmain->GetLine( row );
wxListItemDataList::compatibility_iterator n = line->m_items.Item( GetColumn() );
wxCHECK_RET( n, wxS("no subitem?") );
wxListItemData* const itemData = n->GetData();
wxListItem item;
itemData->GetItem(item);
UpdateWithWidth(m_listmain->GetItemWidthWithImage(&item));
}
private:
wxListMainWindow* const m_listmain;
};
void wxListMainWindow::SetColumnWidth( int col, int width ) void wxListMainWindow::SetColumnWidth( int col, int width )
{ {
wxCHECK_RET( col >= 0 && col < GetColumnCount(), wxCHECK_RET( col >= 0 && col < GetColumnCount(),
@@ -3214,48 +3244,42 @@ void wxListMainWindow::SetColumnWidth( int col, int width )
size_t count = GetItemCount(); size_t count = GetItemCount();
if ( width == wxLIST_AUTOSIZE_USEHEADER || width == wxLIST_AUTOSIZE )
{
wxListCtrlMaxWidthCalculator calculator(this, col);
calculator.UpdateWithWidth(AUTOSIZE_COL_MARGIN);
if ( width == wxLIST_AUTOSIZE_USEHEADER ) if ( width == wxLIST_AUTOSIZE_USEHEADER )
{ calculator.UpdateWithWidth(ComputeMinHeaderWidth(column));
width = ComputeMinHeaderWidth(column);
}
else if ( width == wxLIST_AUTOSIZE )
{
width = ComputeMinHeaderWidth(column);
if ( !IsVirtual() )
{
wxClientDC dc(this);
dc.SetFont( GetFont() );
int max = AUTOSIZE_COL_MARGIN;
// if the cached column width isn't valid then recalculate it // if the cached column width isn't valid then recalculate it
if (m_aColWidths.Item(col)->bNeedsUpdate) wxColWidthInfo* const pWidthInfo = m_aColWidths.Item(col);
if ( pWidthInfo->bNeedsUpdate )
{ {
for (size_t i = 0; i < count; i++) size_t first_visible, last_visible;
GetVisibleLinesRange(&first_visible, &last_visible);
calculator.ComputeBestColumnWidth(count, first_visible, last_visible);
pWidthInfo->nMaxWidth = calculator.GetMaxWidth();
pWidthInfo->bNeedsUpdate = false;
}
else
{ {
wxListLineData *line = GetLine( i ); calculator.UpdateWithWidth(pWidthInfo->nMaxWidth);
wxListItemDataList::compatibility_iterator n = line->m_items.Item( col );
wxCHECK_RET( n, wxT("no subitem?") );
wxListItemData *itemData = n->GetData();
wxListItem item;
itemData->GetItem(item);
int itemWidth = GetItemWidthWithImage(&item);
if (itemWidth > max)
max = itemWidth;
} }
m_aColWidths.Item(col)->bNeedsUpdate = false; // expand the last column to fit the client size
m_aColWidths.Item(col)->nMaxWidth = max; // only for AUTOSIZE_USEHEADER to mimic MSW behaviour
int margin = 0;
if ( (width == wxLIST_AUTOSIZE_USEHEADER) && (col == GetColumnCount() - 1) )
{
margin = GetClientSize().GetX();
for ( int i = 0; i < col && margin > 0; ++i )
margin -= m_columns.Item(i)->GetData()->GetWidth();
} }
max = m_aColWidths.Item(col)->nMaxWidth + AUTOSIZE_COL_MARGIN; width = wxMax(margin, calculator.GetMaxWidth() + AUTOSIZE_COL_MARGIN);
if ( width < max )
width = max;
}
} }
column->SetWidth( width ); column->SetWidth( width );
@@ -3322,8 +3346,12 @@ void wxListMainWindow::SetItem( wxListItem &item )
// update the Max Width Cache if needed // update the Max Width Cache if needed
int width = GetItemWidthWithImage(&item); int width = GetItemWidthWithImage(&item);
if (width > m_aColWidths.Item(item.m_col)->nMaxWidth) wxColWidthInfo* const pWidthInfo = m_aColWidths.Item(item.m_col);
m_aColWidths.Item(item.m_col)->nMaxWidth = width; if ( width > pWidthInfo->nMaxWidth )
{
pWidthInfo->nMaxWidth = width;
pWidthInfo->bNeedsUpdate = true;
}
} }
} }
@@ -3966,8 +3994,9 @@ void wxListMainWindow::DeleteItem( long lindex )
itemWidth = GetItemWidthWithImage(&item); itemWidth = GetItemWidthWithImage(&item);
if (itemWidth >= m_aColWidths.Item(i)->nMaxWidth) wxColWidthInfo *pWidthInfo = m_aColWidths.Item(i);
m_aColWidths.Item(i)->bNeedsUpdate = true; if ( itemWidth >= pWidthInfo->nMaxWidth )
pWidthInfo->bNeedsUpdate = true;
} }
ResetVisibleLinesRange(); ResetVisibleLinesRange();
@@ -4040,6 +4069,13 @@ void wxListMainWindow::DeleteColumn( int col )
void wxListMainWindow::DoDeleteAllItems() void wxListMainWindow::DoDeleteAllItems()
{ {
// We will need to update all columns if any items are inserted again.
if ( InReportView() )
{
for ( size_t i = 0; i < m_aColWidths.GetCount(); i++ )
m_aColWidths.Item(i)->bNeedsUpdate = true;
}
if ( IsEmpty() ) if ( IsEmpty() )
// nothing to do - in particular, don't send the event // nothing to do - in particular, don't send the event
return; return;
@@ -4062,13 +4098,7 @@ void wxListMainWindow::DoDeleteAllItems()
} }
if ( InReportView() ) if ( InReportView() )
{
ResetVisibleLinesRange(); ResetVisibleLinesRange();
for (size_t i = 0; i < m_aColWidths.GetCount(); i++)
{
m_aColWidths.Item(i)->bNeedsUpdate = true;
}
}
m_lines.Clear(); m_lines.Clear();
} }
@@ -4232,7 +4262,10 @@ void wxListMainWindow::InsertItem( wxListItem &item )
int width = GetItemWidthWithImage(&item); int width = GetItemWidthWithImage(&item);
item.SetWidth(width); item.SetWidth(width);
if (width > pWidthInfo->nMaxWidth) if (width > pWidthInfo->nMaxWidth)
{
pWidthInfo->nMaxWidth = width; pWidthInfo->nMaxWidth = width;
pWidthInfo->bNeedsUpdate = true;
}
} }
wxListLineData *line = new wxListLineData(this); wxListLineData *line = new wxListLineData(this);
@@ -4278,7 +4311,7 @@ long wxListMainWindow::InsertColumn( long col, const wxListItem &item )
if (item.m_width == wxLIST_AUTOSIZE_USEHEADER) if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
column->SetWidth(ComputeMinHeaderWidth(column)); column->SetWidth(ComputeMinHeaderWidth(column));
wxColWidthInfo *colWidthInfo = new wxColWidthInfo(); wxColWidthInfo *colWidthInfo = new wxColWidthInfo(0, IsVirtual());
bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount()); bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount());
if ( insert ) if ( insert )