diff --git a/TODO b/TODO index 0898396b8f..a29b8bb5d9 100644 --- a/TODO +++ b/TODO @@ -27,8 +27,6 @@ GTK * listbox scrolling leaves unpainted areas -+ wxCheckListBox::HitTest doesn't work (clicking the check) - ---------------------------------------------------------------------------- DONE ---------------------------------------------------------------------------- @@ -46,3 +44,4 @@ MSW GTK + check/radio box remains pressed in win32 mode ++ wxCheckListBox::HitTest doesn't work (clicking the check) diff --git a/include/wx/univ/listbox.h b/include/wx/univ/listbox.h index 18e46d066e..a68a43266b 100644 --- a/include/wx/univ/listbox.h +++ b/include/wx/univ/listbox.h @@ -175,6 +175,7 @@ protected: void Init(); // event handlers + void OnChar(wxKeyEvent& event); void OnIdle(wxIdleEvent& event); void OnSize(wxSizeEvent& event); @@ -201,6 +202,9 @@ protected: virtual void DoDrawRange(wxControlRenderer *renderer, int itemFirst, int itemLast); + // mark horz scrollbar for updating + void RefreshHorzScrollbar(); + // update (show/hide/adjust) the scrollbars void UpdateScrollbars(); @@ -232,8 +236,9 @@ private: // the height of one line in the listbox (all lines have the same height) wxCoord m_lineHeight; - // the maximal width of a listbox item + // the maximal width of a listbox item and the item which has it wxCoord m_maxWidth; + int m_maxWidthItem; // the extents of horz and vert scrollbars int m_scrollRangeX, diff --git a/samples/listbox/lboxtest.cpp b/samples/listbox/lboxtest.cpp index 588d6a629c..4776ddf260 100644 --- a/samples/listbox/lboxtest.cpp +++ b/samples/listbox/lboxtest.cpp @@ -370,8 +370,8 @@ LboxTestFrame::LboxTestFrame(const wxString& title) wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL); wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL); - btn = new wxButton(panel, LboxTest_Add, _T("&Add panel string")); - m_textAdd = new wxTextCtrl(panel, LboxTest_AddText, _T("test string 0")); + btn = new wxButton(panel, LboxTest_Add, _T("&Add this string")); + m_textAdd = new wxTextCtrl(panel, LboxTest_AddText, _T("test item 0")); sizerRow->Add(btn, 0, wxRIGHT, 5); sizerRow->Add(m_textAdd, 1, wxLEFT, 5); sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); diff --git a/src/univ/listbox.cpp b/src/univ/listbox.cpp index 28a16dd483..dcdf3c75df 100644 --- a/src/univ/listbox.cpp +++ b/src/univ/listbox.cpp @@ -48,6 +48,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase) + EVT_CHAR(wxListBox::OnChar) + EVT_SIZE(wxListBox::OnSize) EVT_IDLE(wxListBox::OnIdle) @@ -64,6 +66,7 @@ void wxListBox::Init() m_itemsPerPage = 0; m_maxWidth = 0; m_scrollRangeY = 0; + m_maxWidthItem = -1; // no items hence no current item m_current = -1; @@ -138,6 +141,7 @@ int wxListBox::DoAppend(const wxString& item) if ( width > m_maxWidth ) { m_maxWidth = width; + m_maxWidthItem = index; m_updateScrollbarX = TRUE; } } @@ -166,8 +170,7 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos) // the max width also might have changed - just recalculate it instead of // keeping track of it here, this is probably more efficient for a typical // use pattern - m_maxWidth = 0; - m_updateScrollbarX = TRUE; + RefreshHorzScrollbar(); // note that we have to refresh all the items after the ones we inserted, // not just these items @@ -201,25 +204,21 @@ void wxListBox::SetString(int n, const wxString& s) { // we need to update m_maxWidth as changing the string may cause the // horz scrollbar [dis]appear - wxCoord widthOld; - GetTextExtent(m_strings[n], &widthOld, NULL); - m_strings[n] = s; - - // has the max length changed? wxCoord width; + m_strings[n] = s; GetTextExtent(s, &width, NULL); // it might have increased if the new string is long if ( width > m_maxWidth ) { m_maxWidth = width; + m_maxWidthItem = n; m_updateScrollbarX = TRUE; } // or also decreased if the old string was the longest one - else if ( (width < m_maxWidth) && (widthOld == m_maxWidth) ) + else if ( n == m_maxWidthItem ) { - m_maxWidth = 0; - m_updateScrollbarX = TRUE; + RefreshHorzScrollbar(); } } else // no horz scrollbar @@ -256,6 +255,8 @@ void wxListBox::Clear() m_updateScrollbarY = TRUE; + RefreshHorzScrollbar(); + RefreshAll(); } @@ -313,6 +314,12 @@ void wxListBox::Delete(int n) // the number of items has changed, hence the scrollbar may disappear m_updateScrollbarY = TRUE; + + // finally, if the longest item was deleted the scrollbar may disappear + if ( n == m_maxWidthItem ) + { + RefreshHorzScrollbar(); + } } // ---------------------------------------------------------------------------- @@ -478,6 +485,12 @@ void wxListBox::RefreshAll() m_updateCount = -1; } +void wxListBox::RefreshHorzScrollbar() +{ + m_maxWidth = 0; // recalculate it + m_updateScrollbarX = TRUE; +} + void wxListBox::UpdateScrollbars() { wxSize size = GetClientSize(); @@ -681,14 +694,16 @@ wxCoord wxListBox::GetMaxWidth() const { if ( m_maxWidth == 0 ) { + wxListBox *self = wxConstCast(this, wxListBox); wxCoord width; size_t count = m_strings.GetCount(); - for ( size_t n =0; n < count; n++ ) + for ( size_t n = 0; n < count; n++ ) { GetTextExtent(m_strings[n], &width, NULL); if ( width > m_maxWidth ) { - wxConstCast(this, wxListBox)->m_maxWidth = width; + self->m_maxWidth = width; + self->m_maxWidthItem = n; } } } @@ -938,6 +953,35 @@ void wxListBox::Activate(int item) } } +// ---------------------------------------------------------------------------- +// built-in keyboard interface (should it be implemented in the inp handler?) +// ---------------------------------------------------------------------------- + +void wxListBox::OnChar(wxKeyEvent& event) +{ + int keycode = event.GetKeyCode(); + if ( isalnum(keycode) ) + { + // find the next item after this one which starts with this letter + int count = GetCount(); + int last = m_current == -1 ? count : m_current; + for ( int n = m_current + 1; n != last; n++ ) + { + if ( n == count ) + n = 0; + + wxString str = m_strings[n]; + if ( !str.empty() && (str[0u] == (wxChar)keycode) ) + { + SetCurrentItem(n); + return; + } + } + } + + event.Skip(); +} + // ---------------------------------------------------------------------------- // input handling // ----------------------------------------------------------------------------