diff --git a/docs/changes.txt b/docs/changes.txt index d8e4d5c588..80b4a01b36 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -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::Offset() for alpha (Markus Rollmann). - Fix bug in wxImage::ClearAlpha() for shared data (Markus Rollmann). diff --git a/include/wx/generic/private/listctrl.h b/include/wx/generic/private/listctrl.h index 5cd210f486..f34e293bfc 100644 --- a/include/wx/generic/private/listctrl.h +++ b/include/wx/generic/private/listctrl.h @@ -863,6 +863,7 @@ private: DECLARE_EVENT_TABLE() friend class wxGenericListCtrl; + friend class wxListCtrlMaxWidthCalculator; }; #endif // wxUSE_LISTCTRL diff --git a/include/wx/generic/private/widthcalc.h b/include/wx/generic/private/widthcalc.h index 05621dcf1d..ed5dc50a69 100644 --- a/include/wx/generic/private/widthcalc.h +++ b/include/wx/generic/private/widthcalc.h @@ -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_ diff --git a/samples/listctrl/listtest.cpp b/samples/listctrl/listtest.cpp index 26e1a3f264..ef9ee66949 100644 --- a/samples/listctrl/listtest.cpp +++ b/samples/listctrl/listtest.cpp @@ -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); } } diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index d21a8c6fae..5f46e738a5 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -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 )