From 943240b264ec3de6e3369d08fdcfb5cfff52f38a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 6 Oct 2000 16:24:25 +0000 Subject: [PATCH] 1. listbox sample fixed, now seems to work more or less (except for wxSizer problem) 2. wxRadioBox lays out items correctly 3. wxListBox::DoInsertItems() refreshes correctly 4. list box scrollbars are now refreshed correctly too git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8482 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/univ/listbox.h | 10 +++ samples/listbox/lboxtest.cpp | 100 +++++++++++++++-------- src/univ/listbox.cpp | 152 ++++++++++++++++++++--------------- src/univ/radiobox.cpp | 10 ++- src/univ/themes/gtk.cpp | 4 +- 5 files changed, 170 insertions(+), 106 deletions(-) diff --git a/include/wx/univ/listbox.h b/include/wx/univ/listbox.h index d35e8f8321..4957a2b40a 100644 --- a/include/wx/univ/listbox.h +++ b/include/wx/univ/listbox.h @@ -200,6 +200,12 @@ protected: virtual void DoDrawRange(wxControlRenderer *renderer, int itemFirst, int itemLast); + // update (show/hide/adjust) the scrollbars + void UpdateScrollbars(); + + // refresh the items specified by m_updateCount and m_updateFrom + void UpdateItems(); + // the array containing all items (it is sorted if the listbox has // wxLB_SORT style) wxArrayString m_strings; @@ -228,6 +234,10 @@ private: // the maximal width of a listbox item wxCoord m_maxWidth; + // the extents of horz and vert scrollbars + int m_scrollRangeX, + m_scrollRangeY; + // the number of items per page size_t m_itemsPerPage; diff --git a/samples/listbox/lboxtest.cpp b/samples/listbox/lboxtest.cpp index 755138b4f2..af76209008 100644 --- a/samples/listbox/lboxtest.cpp +++ b/samples/listbox/lboxtest.cpp @@ -94,11 +94,16 @@ protected: // event handlers void OnButtonReset(wxCommandEvent& event); void OnButtonCreate(wxCommandEvent& event); + void OnButtonDelete(wxCommandEvent& event); void OnButtonClear(wxCommandEvent& event); void OnButtonAdd(wxCommandEvent& event); void OnButtonAddSeveral(wxCommandEvent& event); + void OnCheckOrRadioBox(wxCommandEvent& event); - void OnUpdateUIButtons(wxUpdateUIEvent& event); + + void OnUpdateUICreateButton(wxUpdateUIEvent& event); + void OnUpdateUIClearButton(wxUpdateUIEvent& event); + void OnUpdateUIDeleteButton(wxUpdateUIEvent& event); // reset the listbox parameters void Reset(); @@ -169,12 +174,16 @@ IMPLEMENT_APP(LboxTestApp) BEGIN_EVENT_TABLE(LboxTestFrame, wxFrame) EVT_BUTTON(LboxTest_Reset, LboxTestFrame::OnButtonReset) EVT_BUTTON(LboxTest_Create, LboxTestFrame::OnButtonCreate) + EVT_BUTTON(LboxTest_Delete, LboxTestFrame::OnButtonDelete) EVT_BUTTON(LboxTest_Clear, LboxTestFrame::OnButtonClear) EVT_BUTTON(LboxTest_Add, LboxTestFrame::OnButtonAdd) EVT_BUTTON(LboxTest_AddSeveral, LboxTestFrame::OnButtonAddSeveral) EVT_UPDATE_UI_RANGE(LboxTest_Reset, LboxTest_Create, - LboxTestFrame::OnUpdateUIButtons) + LboxTestFrame::OnUpdateUICreateButton) + + EVT_UPDATE_UI(LboxTest_Clear, LboxTestFrame::OnUpdateUIClearButton) + EVT_UPDATE_UI(LboxTest_Delete, LboxTestFrame::OnUpdateUIDeleteButton) EVT_CHECKBOX(-1, LboxTestFrame::OnCheckOrRadioBox) EVT_RADIOBOX(-1, LboxTestFrame::OnCheckOrRadioBox) @@ -203,7 +212,7 @@ bool LboxTestApp::OnInit() // ---------------------------------------------------------------------------- LboxTestFrame::LboxTestFrame(const wxString& title) - : wxFrame(NULL, -1, title) + : wxFrame(NULL, -1, title, wxPoint(100, 100)) { // init everything m_dirty = FALSE; @@ -217,16 +226,13 @@ LboxTestFrame::LboxTestFrame(const wxString& title) m_sizerLbox = (wxSizer *)NULL; /* - What we create here is a frame having 2 panes: the explanatory pane to - the left allowing to set the listbox styles and recreate the control - and the pane containing the listbox itself and the control used for log - output to the right. - - The left pane is divided, itself, in 2 parts with the upper one - allowing to recreate the listbox and the lower one to add/change/delete - strings to/from it. + What we create here is a frame having 3 panes: the explanatory pane to + the left allowing to set the listbox styles and recreate the control, + the pane containing the listbox itself and the lower pane containing + the buttons which allow to add/change/delete strings to/from it. */ - wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL), + wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL), + *sizerUp = new wxBoxSizer(wxHORIZONTAL), *sizerLeft = new wxBoxSizer(wxVERTICAL), *sizerRight = new wxBoxSizer(wxVERTICAL); @@ -238,6 +244,7 @@ LboxTestFrame::LboxTestFrame(const wxString& title) _T("multiple"), }; + wxStaticBox *box = new wxStaticBox(this, -1, _T("&Set listbox parameters")); m_radioSelMode = new wxRadioBox(this, -1, _T("Selection &mode:"), wxDefaultPosition, wxDefaultSize, WXSIZEOF(modes), modes, @@ -247,44 +254,46 @@ LboxTestFrame::LboxTestFrame(const wxString& title) m_chkHScroll = new wxCheckBox(this, -1, _T("Show &horizontal scrollbar")); m_chkSort = new wxCheckBox(this, -1, _T("&Sort items")); - wxStaticBox *box = new wxStaticBox(this, -1, _T("&Set listbox parameters")); - wxSizer *sizerUp = new wxStaticBoxSizer(box, wxVERTICAL); + sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL); - sizerUp->Add(m_chkVScroll, 0, wxLEFT | wxRIGHT, 5); - sizerUp->Add(m_chkHScroll, 0, wxLEFT | wxRIGHT, 5); - sizerUp->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer - sizerUp->Add(m_radioSelMode, 0, wxALL, 5); - sizerUp->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer - sizerUp->Add(m_chkSort, 0, wxLEFT | wxRIGHT, 5); + sizerLeft->Add(m_chkVScroll, 0, wxLEFT | wxRIGHT, 5); + sizerLeft->Add(m_chkHScroll, 0, wxLEFT | wxRIGHT, 5); + sizerLeft->Add(m_chkSort, 0, wxLEFT | wxRIGHT, 5); + sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer + sizerLeft->Add(m_radioSelMode, 0, wxGROW | wxALL, 5); wxSizer *sizerBtn = new wxBoxSizer(wxHORIZONTAL); wxButton *btn = new wxButton(this, LboxTest_Reset, _T("&Reset")); sizerBtn->Add(btn, 0, wxLEFT | wxRIGHT, 5); btn = new wxButton(this, LboxTest_Create, _T("&Create")); sizerBtn->Add(btn, 0, wxLEFT | wxRIGHT, 5); - sizerUp->Add(sizerBtn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 5); + sizerLeft->Add(sizerBtn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); - // lower left pane + // right pane + m_lbox = new wxListBox(this, -1); + sizerRight->Add(m_lbox, 1, wxGROW | wxALL, 5); + sizerRight->SetMinSize(250, 0); + m_sizerLbox = sizerRight; // save it to modify it later + + // left + right panes compose the upper one + sizerUp->Add(sizerLeft, 0, wxGROW | wxALL, 10); + sizerUp->Add(sizerRight, 1, wxGROW | wxALL, 10); + + // lower pane wxStaticBox *box2 = new wxStaticBox(this, -1, _T("&Change listbox contents")); wxSizer *sizerDown = new wxStaticBoxSizer(box2, wxVERTICAL); btn = new wxButton(this, LboxTest_Add, _T("&Add string...")); sizerDown->Add(btn, 0, wxALL | wxGROW, 5); - btn = new wxButton(this, LboxTest_AddSeveral, _T("Add a &few string")); + btn = new wxButton(this, LboxTest_AddSeveral, _T("Add a &few strings")); + sizerDown->Add(btn, 0, wxALL | wxGROW, 5); + btn = new wxButton(this, LboxTest_Delete, _T("&Delete")); sizerDown->Add(btn, 0, wxALL | wxGROW, 5); btn = new wxButton(this, LboxTest_Clear, _T("&Clear")); sizerDown->Add(btn, 0, wxALL | wxGROW, 5); - sizerLeft->Add(sizerUp, 0, wxGROW | wxTOP | wxBOTTOM, 5); - sizerLeft->Add(sizerDown, 0, wxGROW | wxTOP | wxBOTTOM, 5); - - // right pane - m_lbox = new wxListBox(this, -1); - sizerRight->Add(m_lbox, 1, wxGROW | wxALL, 5); - m_sizerLbox = sizerRight; - - sizerTop->Add(sizerLeft, 0, wxGROW | wxALL, 10); - sizerTop->Add(sizerRight, 1, wxGROW | wxALL, 10); + sizerTop->Add(sizerUp, 1, wxGROW | wxALL, 10); + sizerTop->Add(sizerDown, 0, wxGROW | wxALL, 10); // final initialization Reset(); @@ -369,6 +378,16 @@ void LboxTestFrame::OnButtonCreate(wxCommandEvent& event) CreateLbox(); } +void LboxTestFrame::OnButtonDelete(wxCommandEvent& event) +{ + wxArrayInt selections; + int n = m_lbox->GetSelections(selections); + while ( n > 0 ) + { + m_lbox->Delete(selections[--n]); + } +} + void LboxTestFrame::OnButtonClear(wxCommandEvent& event) { m_lbox->Clear(); @@ -385,15 +404,26 @@ void LboxTestFrame::OnButtonAddSeveral(wxCommandEvent& event) wxArrayString items; items.Add(_T("First")); items.Add(_T("another one")); - items.Add(_T("and the last (very long) one")); + items.Add(_T("and the last (very very very very very long) one")); m_lbox->InsertItems(items, 0); } -void LboxTestFrame::OnUpdateUIButtons(wxUpdateUIEvent& event) +void LboxTestFrame::OnUpdateUICreateButton(wxUpdateUIEvent& event) { event.Enable(m_dirty); } +void LboxTestFrame::OnUpdateUIDeleteButton(wxUpdateUIEvent& event) +{ + wxArrayInt selections; + event.Enable(m_lbox->GetSelections(selections) != 0); +} + +void LboxTestFrame::OnUpdateUIClearButton(wxUpdateUIEvent& event) +{ + event.Enable(m_lbox->GetCount() != 0); +} + void LboxTestFrame::OnCheckOrRadioBox(wxCommandEvent& event) { m_dirty = TRUE; diff --git a/src/univ/listbox.cpp b/src/univ/listbox.cpp index 488c3e2bee..ca729c2d3a 100644 --- a/src/univ/listbox.cpp +++ b/src/univ/listbox.cpp @@ -63,6 +63,7 @@ void wxListBox::Init() m_lineHeight = 0; m_itemsPerPage = 0; m_maxWidth = 0; + m_scrollRangeY = 0; // no items hence no current item m_current = -1; @@ -159,7 +160,7 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos) m_itemsClientData.Insert(NULL, pos + n); } - // the number of items has changed + // the number of items has changed so we might have to show the scrollbar m_updateScrollbarY = TRUE; // the max width also might have changed - just recalculate it instead of @@ -168,7 +169,9 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos) m_maxWidth = 0; m_updateScrollbarX = TRUE; - RefreshItems(pos, count); + // note that we have to refresh all the items after the ones we inserted, + // not just these items + RefreshItems(pos, GetCount() - pos); } void wxListBox::DoSetItems(const wxArrayString& items, void **clientData) @@ -424,50 +427,90 @@ void wxListBox::RefreshAll() m_updateCount = -1; } +void wxListBox::UpdateScrollbars() +{ + wxSize size = GetClientSize(); + + // is our height enough to show all items? + int nLines = GetCount(); + wxCoord lineHeight = GetLineHeight(); + bool showScrollbarY = nLines*lineHeight > size.y; + + // check the width too if required + wxCoord charWidth, maxWidth; + bool showScrollbarX; + if ( HasHorzScrollbar() ) + { + charWidth = GetCharWidth(); + maxWidth = GetMaxWidth(); + showScrollbarX = maxWidth > size.x; + } + else // never show it + { + charWidth = maxWidth = 0; + showScrollbarX = FALSE; + } + + // what should be the scrollbar range now? + int scrollRangeX = showScrollbarX + ? (maxWidth + 2*charWidth - 1) / charWidth + : 0; + int scrollRangeY = showScrollbarY ? nLines : 0; + + // reset scrollbars if something changed: either the visibility status + // or the range of a scrollbar which is shown + if ( (showScrollbarY != m_showScrollbarY) || + (showScrollbarX != m_showScrollbarX) || + (showScrollbarY && (scrollRangeY != m_scrollRangeY)) || + (showScrollbarX && (scrollRangeX != m_scrollRangeX)) ) + { + int x, y; + GetViewStart(&x, &y); + SetScrollbars(charWidth, lineHeight, + scrollRangeX, scrollRangeY, + x, y); + + m_showScrollbarX = showScrollbarX; + m_showScrollbarY = showScrollbarY; + + m_scrollRangeX = scrollRangeX; + m_scrollRangeY = scrollRangeY; + } +} + +void wxListBox::UpdateItems() +{ + // only refresh the items which must be refreshed + if ( m_updateCount == -1 ) + { + // refresh all + wxLogTrace(_T("listbox"), _T("Refreshing all")); + + Refresh(); + } + else + { + wxSize size = GetClientSize(); + wxRect rect; + rect.width = size.x; + rect.height = size.y; + rect.y += m_updateFrom*GetLineHeight(); + rect.height = m_updateCount*GetLineHeight(); + CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y); + + wxLogTrace(_T("listbox"), _T("Refreshing items %d..%d (%d-%d)"), + m_updateFrom, m_updateFrom + m_updateCount - 1, + rect.GetTop(), rect.GetBottom()); + + Refresh(TRUE, &rect); + } +} + void wxListBox::OnIdle(wxIdleEvent& event) { if ( m_updateScrollbarY || m_updateScrollbarX ) { - wxSize size = GetClientSize(); - - // is our height enough to show all items? - int nLines = GetCount(); - wxCoord lineHeight = GetLineHeight(); - bool showScrollbarY = nLines*lineHeight > size.y; - - // check the width too if required - wxCoord charWidth, maxWidth; - bool showScrollbarX; - if ( HasHorzScrollbar() ) - { - charWidth = GetCharWidth(); - maxWidth = GetMaxWidth(); - showScrollbarX = maxWidth > size.x; - } - else // never show it - { - charWidth = maxWidth = 0; - showScrollbarX = FALSE; - } - - // reset scrollbars if something changed - if ( (showScrollbarY != m_showScrollbarY) || - (showScrollbarX != m_showScrollbarX) ) - { - int x, y; - GetViewStart(&x, &y); - SetScrollbars(charWidth, lineHeight, - showScrollbarX - ? (maxWidth + 2*charWidth - 1) / charWidth - : 0, - showScrollbarY - ? nLines - : 0, - x, y); - - m_showScrollbarX = showScrollbarX; - m_showScrollbarY = showScrollbarY; - } + UpdateScrollbars(); m_updateScrollbarX = FALSE; m_updateScrollbarY = FALSE; @@ -482,30 +525,7 @@ void wxListBox::OnIdle(wxIdleEvent& event) if ( m_updateCount ) { - // only refresh the items which must be refreshed - if ( m_updateCount == -1 ) - { - // refresh all - wxLogTrace(_T("listbox"), _T("Refreshing all")); - - Refresh(); - } - else - { - wxSize size = GetClientSize(); - wxRect rect; - rect.width = size.x; - rect.height = size.y; - rect.y += m_updateFrom*GetLineHeight(); - rect.height = m_updateCount*GetLineHeight(); - CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y); - - wxLogTrace(_T("listbox"), _T("Refreshing items %d..%d (%d-%d)"), - m_updateFrom, m_updateFrom + m_updateCount - 1, - rect.GetTop(), rect.GetBottom()); - - Refresh(TRUE, &rect); - } + UpdateItems(); m_updateCount = 0; } diff --git a/src/univ/radiobox.cpp b/src/univ/radiobox.cpp index 4f7081b0ea..4c615ab5e8 100644 --- a/src/univ/radiobox.cpp +++ b/src/univ/radiobox.cpp @@ -140,7 +140,9 @@ void wxRadioBox::SetSelection(int n) { wxCHECK_RET( IsValid(n), _T("invalid index in wxRadioBox::SetSelection") ); - // this will unselect the previously selected button in our group + m_selection = n; + + // this will also unselect the previously selected button in our group m_buttons[n]->SetValue(TRUE); } @@ -278,9 +280,9 @@ void wxRadioBox::DoMoveWindow(int x0, int y0, int width, int height) if ( GetWindowStyle() & wxRA_SPECIFY_COLS ) { // from to to bottom - if ( n % m_numRows ) + if ( (n == 0) || (n % m_numRows) ) { - // continue in this column + // continue (or start if n == 0) in this column y += sizeBtn.y; } else @@ -293,7 +295,7 @@ void wxRadioBox::DoMoveWindow(int x0, int y0, int width, int height) else // wxRA_SPECIFY_ROWS: mirror the code above { // from left to right - if ( n % m_numCols ) + if ( (n == 0) || (n % m_numCols) ) { // continue in this row x += sizeBtn.x; diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index 88695e91b7..7294f012e7 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -1649,7 +1649,9 @@ void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window) { // TODO: this is ad hoc... size->x += 3*window->GetCharWidth(); - wxCoord minBtnHeight = (11*(window->GetCharHeight() + 8))/10; + if ( size->x < 80 ) + size->x = 80; + wxCoord minBtnHeight = 22; if ( size->y < minBtnHeight ) size->y = minBtnHeight;