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).
- Fix handling of fast consecutive clicks in wxRibbonBar (atobi).
- 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 wxPixelData<wxImage>::Offset() for alpha (Markus Rollmann).
- Fix bug in wxImage::ClearAlpha() for shared data (Markus Rollmann).

View File

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

View File

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

View File

@@ -519,11 +519,11 @@ void MyFrame::InitWithReportItems()
itemCol.SetImage(-1);
m_listCtrl->InsertColumn(0, itemCol);
itemCol.SetText(wxT("Column 2"));
itemCol.SetText(wxT("Column 2 (auto size excluding header)"));
itemCol.SetAlign(wxLIST_FORMAT_CENTRE);
m_listCtrl->InsertColumn(1, itemCol);
itemCol.SetText(wxT("Column 3"));
itemCol.SetText(wxT("Column 3 (auto size including header)"));
itemCol.SetAlign(wxLIST_FORMAT_RIGHT);
m_listCtrl->InsertColumn(2, itemCol);
@@ -558,10 +558,6 @@ void MyFrame::InitWithReportItems()
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
m_listCtrl->SetItemColumnImage(1, 1, 0);
@@ -573,6 +569,10 @@ void MyFrame::InitWithReportItems()
// test SetItemFont too
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)
@@ -671,11 +671,11 @@ void MyFrame::InitWithVirtualItems()
}
else
{
m_listCtrl->AppendColumn(wxT("First Column"));
m_listCtrl->AppendColumn(wxT("Second Column"));
m_listCtrl->SetColumnWidth(0, 150);
m_listCtrl->SetColumnWidth(1, 150);
m_listCtrl->AppendColumn(wxT("First Column (size auto)"));
m_listCtrl->AppendColumn(wxT("Second Column (150px)"));
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/renderer.h"
#include "wx/generic/private/listctrl.h"
#include "wx/generic/private/widthcalc.h"
#ifdef __WXMAC__
#include "wx/osx/private.h"
@@ -3193,6 +3194,35 @@ void wxListMainWindow::SetColumn( int col, const wxListItem &item )
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 )
{
wxCHECK_RET( col >= 0 && col < GetColumnCount(),
@@ -3214,48 +3244,42 @@ void wxListMainWindow::SetColumnWidth( int col, int width )
size_t count = GetItemCount();
if (width == wxLIST_AUTOSIZE_USEHEADER)
if ( width == wxLIST_AUTOSIZE_USEHEADER || width == wxLIST_AUTOSIZE )
{
width = ComputeMinHeaderWidth(column);
}
else if ( width == wxLIST_AUTOSIZE )
{
width = ComputeMinHeaderWidth(column);
wxListCtrlMaxWidthCalculator calculator(this, col);
if ( !IsVirtual() )
calculator.UpdateWithWidth(AUTOSIZE_COL_MARGIN);
if ( width == wxLIST_AUTOSIZE_USEHEADER )
calculator.UpdateWithWidth(ComputeMinHeaderWidth(column));
// if the cached column width isn't valid then recalculate it
wxColWidthInfo* const pWidthInfo = m_aColWidths.Item(col);
if ( pWidthInfo->bNeedsUpdate )
{
wxClientDC dc(this);
dc.SetFont( GetFont() );
size_t first_visible, last_visible;
GetVisibleLinesRange(&first_visible, &last_visible);
int max = AUTOSIZE_COL_MARGIN;
// if the cached column width isn't valid then recalculate it
if (m_aColWidths.Item(col)->bNeedsUpdate)
{
for (size_t i = 0; i < count; i++)
{
wxListLineData *line = GetLine( i );
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;
m_aColWidths.Item(col)->nMaxWidth = max;
}
max = m_aColWidths.Item(col)->nMaxWidth + AUTOSIZE_COL_MARGIN;
if ( width < max )
width = max;
calculator.ComputeBestColumnWidth(count, first_visible, last_visible);
pWidthInfo->nMaxWidth = calculator.GetMaxWidth();
pWidthInfo->bNeedsUpdate = false;
}
else
{
calculator.UpdateWithWidth(pWidthInfo->nMaxWidth);
}
// expand the last column to fit the client size
// 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();
}
width = wxMax(margin, calculator.GetMaxWidth() + AUTOSIZE_COL_MARGIN);
}
column->SetWidth( width );
@@ -3322,8 +3346,12 @@ void wxListMainWindow::SetItem( wxListItem &item )
// update the Max Width Cache if needed
int width = GetItemWidthWithImage(&item);
if (width > m_aColWidths.Item(item.m_col)->nMaxWidth)
m_aColWidths.Item(item.m_col)->nMaxWidth = width;
wxColWidthInfo* const pWidthInfo = m_aColWidths.Item(item.m_col);
if ( width > pWidthInfo->nMaxWidth )
{
pWidthInfo->nMaxWidth = width;
pWidthInfo->bNeedsUpdate = true;
}
}
}
@@ -3966,8 +3994,9 @@ void wxListMainWindow::DeleteItem( long lindex )
itemWidth = GetItemWidthWithImage(&item);
if (itemWidth >= m_aColWidths.Item(i)->nMaxWidth)
m_aColWidths.Item(i)->bNeedsUpdate = true;
wxColWidthInfo *pWidthInfo = m_aColWidths.Item(i);
if ( itemWidth >= pWidthInfo->nMaxWidth )
pWidthInfo->bNeedsUpdate = true;
}
ResetVisibleLinesRange();
@@ -4040,6 +4069,13 @@ void wxListMainWindow::DeleteColumn( int col )
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() )
// nothing to do - in particular, don't send the event
return;
@@ -4062,13 +4098,7 @@ void wxListMainWindow::DoDeleteAllItems()
}
if ( InReportView() )
{
ResetVisibleLinesRange();
for (size_t i = 0; i < m_aColWidths.GetCount(); i++)
{
m_aColWidths.Item(i)->bNeedsUpdate = true;
}
}
m_lines.Clear();
}
@@ -4232,7 +4262,10 @@ void wxListMainWindow::InsertItem( wxListItem &item )
int width = GetItemWidthWithImage(&item);
item.SetWidth(width);
if (width > pWidthInfo->nMaxWidth)
{
pWidthInfo->nMaxWidth = width;
pWidthInfo->bNeedsUpdate = true;
}
}
wxListLineData *line = new wxListLineData(this);
@@ -4278,7 +4311,7 @@ long wxListMainWindow::InsertColumn( long col, const wxListItem &item )
if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
column->SetWidth(ComputeMinHeaderWidth(column));
wxColWidthInfo *colWidthInfo = new wxColWidthInfo();
wxColWidthInfo *colWidthInfo = new wxColWidthInfo(0, IsVirtual());
bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount());
if ( insert )