+void wxVListBoxComboPopup::CalcWidths()
+{
+ 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;
+ }
+}
+