[ 1507736 ] wxOwnerDrawnComboBox improved list item width checking.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39790 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Włodzimierz Skiba
2006-06-19 09:02:10 +00:00
parent 1d39a12a30
commit e5d6334238
2 changed files with 127 additions and 33 deletions

View File

@@ -58,8 +58,9 @@ END_EVENT_TABLE()
void wxVListBoxComboPopup::Init()
{
m_widestWidth = 0;
m_avgCharWidth = 0;
m_baseImageWidth = 0;
m_widestItem = -1;
m_widthsDirty = false;
m_findWidest = false;
m_itemHeight = 0;
m_value = -1;
m_itemHover = -1;
@@ -327,26 +328,6 @@ void wxVListBoxComboPopup::OnKey(wxKeyEvent& event)
event.Skip();
}
void wxVListBoxComboPopup::CheckWidth( int pos )
{
wxCoord x = OnMeasureItemWidth(pos);
if ( x < 0 )
{
if ( !m_useFont.Ok() )
m_useFont = m_combo->GetFont();
wxCoord y;
m_combo->GetTextExtent(m_strings[pos], &x, &y, 0, 0, &m_useFont);
x += 4;
}
if ( m_widestWidth < x )
{
m_widestWidth = x;
}
}
void wxVListBoxComboPopup::Insert( const wxString& item, int pos )
{
// Need to change selection?
@@ -358,12 +339,11 @@ void wxVListBoxComboPopup::Insert( const wxString& item, int pos )
}
m_strings.Insert(item,pos);
m_widths.Insert(-1,pos);
m_widthsDirty = true;
if ( IsCreated() )
wxVListBox::SetItemCount( wxVListBox::GetItemCount()+1 );
// Calculate width
CheckWidth(pos);
}
int wxVListBoxComboPopup::Append(const wxString& item)
@@ -397,6 +377,10 @@ void wxVListBoxComboPopup::Clear()
wxASSERT(m_combo);
m_strings.Empty();
m_widths.Empty();
m_widestWidth = 0;
m_widestItem = -1;
ClearClientDatas();
@@ -427,6 +411,8 @@ void wxVListBoxComboPopup::SetItemClientData( unsigned int n,
m_clientDatas.SetCount(n+1,NULL);
m_clientDatas[n] = clientData;
ItemWidthChanged(n);
}
void* wxVListBoxComboPopup::GetItemClientData(unsigned int n) const
@@ -449,6 +435,10 @@ void wxVListBoxComboPopup::Delete( unsigned int item )
}
m_strings.RemoveAt(item);
m_widths.RemoveAt(item);
if ( (int)item == m_widestItem )
m_findWidest = true;
if ( IsCreated() )
wxVListBox::SetItemCount( wxVListBox::GetItemCount()-1 );
@@ -472,6 +462,7 @@ wxString wxVListBoxComboPopup::GetString( int item ) const
void wxVListBoxComboPopup::SetString( int item, const wxString& str )
{
m_strings[item] = str;
ItemWidthChanged(item);
}
wxString wxVListBoxComboPopup::GetStringValue() const
@@ -537,6 +528,92 @@ wxSize wxVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int
else
height = 50;
bool doFindWidest = m_findWidest;
// Measure items with dirty width.
if ( m_widthsDirty )
{
unsigned int i;
unsigned int n = m_widths.GetCount();
int dirtyHandled = 0;
wxArrayInt& widths = m_widths;
// I think using wxDC::GetTextExtent is faster than
// wxWindow::GetTextExtent (assuming same dc is used
// for all calls, as we do here).
wxClientDC dc(m_combo);
dc.SetFont(m_useFont);
for ( i=0; i<n; i++ )
{
if ( widths[i] < 0 )
{
wxCoord x = OnMeasureItemWidth(i);
if ( x < 0 )
{
const wxString& text = m_strings[i];
// To make sure performance won't suck in extreme scenarios,
// we'll estimate length after some arbitrary number of items
// have been checked precily.
if ( dirtyHandled < 1024 )
{
wxCoord y;
dc.GetTextExtent(text, &x, &y, 0, 0);
x += 4;
}
else
{
x = text.length() * (dc.GetCharWidth()+1);
}
}
widths[i] = x;
if ( x >= m_widestWidth )
{
m_widestWidth = x;
m_widestItem = (int)i;
}
else if ( (int)i == m_widestItem )
{
// Width of previously widest item has been decreased, so
// we'll have to check all to find current widest item.
doFindWidest = true;
}
dirtyHandled++;
}
}
m_widthsDirty = false;
}
if ( doFindWidest )
{
unsigned int i;
unsigned int n = m_widths.GetCount();
int bestWidth = -1;
int bestIndex = -1;
for ( i=0; i<n; i++ )
{
int w = m_widths[i];
if ( w > bestWidth )
{
bestIndex = (int)i;
bestWidth = w;
}
}
m_widestWidth = bestWidth;
m_widestItem = bestIndex;
m_findWidest = false;
}
// Take scrollbar into account in width calculations
int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
return wxSize(minWidth > widestWidth ? minWidth : widestWidth,
@@ -554,9 +631,11 @@ void wxVListBoxComboPopup::Populate( const wxArrayString& choices )
{
const wxString& item = choices.Item(i);
m_strings.Add(item);
CheckWidth(i);
}
m_widths.SetCount(n,-1);
m_widthsDirty = true;
if ( IsCreated() )
wxVListBox::SetItemCount(n);