From 4f37a20b74fc6159f92ca0397018bc9dd5d32b6e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 19 Oct 2000 23:58:42 +0000 Subject: [PATCH] added listbox test/demo git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8589 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- samples/listbox/lboxtest.cpp | 687 +++++++++++++++++++++++++++++++++++ 1 file changed, 687 insertions(+) create mode 100644 samples/listbox/lboxtest.cpp diff --git a/samples/listbox/lboxtest.cpp b/samples/listbox/lboxtest.cpp new file mode 100644 index 0000000000..85e6832751 --- /dev/null +++ b/samples/listbox/lboxtest.cpp @@ -0,0 +1,687 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: lboxtest.cpp +// Purpose: wxListBox sample +// Author: Vadim Zeitlin +// Id: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +/* + Current bugs: + + +1. horz scrollbar doesn't appear in listbox + +2. truncating text ctrl doesn't update display + +3. deleting last listbox item doesn't update display + 4. text ctrl background corrupted after resize + */ + +// ============================================================================ +// declarations +// ============================================================================ + +#ifdef __GNUG__ + #pragma implementation "lboxtest.cpp" + #pragma interface "lboxtest.cpp" +#endif + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/frame.h" + #include "wx/dcclient.h" + + #include "wx/button.h" + #include "wx/checkbox.h" + #include "wx/checklst.h" + #include "wx/listbox.h" + #include "wx/radiobox.h" + #include "wx/radiobut.h" + #include "wx/statbox.h" + #include "wx/stattext.h" + #include "wx/textctrl.h" +#endif + +#include "wx/sizer.h" + +#ifdef __WXUNIVERSAL__ + #include "wx/univ/theme.h" +#endif // __WXUNIVERSAL__ + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// control ids +enum +{ + LboxTest_Reset = 100, + LboxTest_Create, + LboxTest_Add, + LboxTest_AddText, + LboxTest_AddSeveral, + LboxTest_AddMany, + LboxTest_Clear, + LboxTest_ClearLog, + LboxTest_Change, + LboxTest_ChangeText, + LboxTest_Delete, + LboxTest_DeleteText, + LboxTest_DeleteSel, + LboxTest_Listbox, + LboxTest_Quit +}; + +// ---------------------------------------------------------------------------- +// our classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp +class LboxTestApp : public wxApp +{ +public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); +}; + +// Define a new frame type: this is going to be our main frame +class LboxTestFrame : public wxFrame +{ +public: + // ctor(s) and dtor + LboxTestFrame(const wxString& title); + virtual ~LboxTestFrame(); + +protected: + // event handlers + void OnButtonReset(wxCommandEvent& event); + void OnButtonCreate(wxCommandEvent& event); + void OnButtonChange(wxCommandEvent& event); + void OnButtonDelete(wxCommandEvent& event); + void OnButtonDeleteSel(wxCommandEvent& event); + void OnButtonClear(wxCommandEvent& event); + void OnButtonClearLog(wxCommandEvent& event); + void OnButtonAdd(wxCommandEvent& event); + void OnButtonAddSeveral(wxCommandEvent& event); + void OnButtonAddMany(wxCommandEvent& event); + void OnButtonQuit(wxCommandEvent& event); + + void OnListbox(wxCommandEvent& event); + void OnListboxDClick(wxCommandEvent& event); + + void OnCheckOrRadioBox(wxCommandEvent& event); + + void OnUpdateUIAddSeveral(wxUpdateUIEvent& event); + void OnUpdateUICreateButton(wxUpdateUIEvent& event); + void OnUpdateUIClearButton(wxUpdateUIEvent& event); + void OnUpdateUIDeleteButton(wxUpdateUIEvent& event); + void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event); + + // reset the listbox parameters + void Reset(); + + // (re)create the listbox + void CreateLbox(); + + // listbox parameters + // ------------------ + + // the selection mode + enum LboxSelection + { + LboxSel_Single, + LboxSel_Extended, + LboxSel_Multiple + } m_lboxSelMode; + + // should it be sorted? + bool m_sorted; + + // should it have horz scroll/vert scrollbar permanently shown? + bool m_horzScroll, + m_vertScrollAlways; + + // should the recreate button be enabled? + bool m_dirty; + + // the controls + // ------------ + + // the sel mode radiobox + wxRadioBox *m_radioSelMode; + + // the checkboxes + wxCheckBox *m_chkSort, + *m_chkHScroll, + *m_chkVScroll; + + // the listbox itself and the sizer it is in + wxListBox *m_lbox; + wxSizer *m_sizerLbox; + + // the listbox for logging messages + wxListBox *m_lboxLog; + + // the text entries for "Add/change string" and "Delete" buttons + wxTextCtrl *m_textAdd, + *m_textChange, + *m_textDelete; + +private: + // the log target we use to redirect messages to the listbox + wxLog *m_logTarget; + + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() +}; + +// A log target which just redirects the messages to a listbox +class LboxLogger : public wxLog +{ +public: + LboxLogger(wxListBox *lbox, wxLog *logOld) + { + m_lbox = lbox; + //m_lbox->Disable(); -- looks ugly under MSW + m_logOld = logOld; + } + + virtual ~LboxLogger() + { + wxLog::SetActiveTarget(m_logOld); + } + +private: + // implement sink functions + virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t) + { + // don't put trace messages into listbox or we can get into infinite + // recursion + if ( level == wxLOG_Trace ) + { + if ( m_logOld ) + { + // cast is needed to call protected method + ((LboxLogger *)m_logOld)->DoLog(level, szString, t); + } + } + else + { + wxLog::DoLog(level, szString, t); + } + } + + virtual void DoLogString(const wxChar *szString, time_t t) + { + wxString msg; + TimeStamp(&msg); + msg += szString; + #ifdef __WXUNIVERSAL__ + m_lbox->AppendAndEnsureVisible(msg); + #else // other ports don't have this method yet + m_lbox->Append(msg); + + // SetFirstItem() isn't implemented in wxGTK + #ifndef __WXGTK__ + m_lbox->SetFirstItem(m_lbox->GetCount() - 1); + #endif + #endif + } + + // the control we use + wxListBox *m_lbox; + + // the old log target + wxLog *m_logOld; +}; + +// ---------------------------------------------------------------------------- +// misc macros +// ---------------------------------------------------------------------------- + +IMPLEMENT_APP(LboxTestApp) + +#ifdef __WXUNIVERSAL__ + WX_USE_THEME(win32); + WX_USE_THEME(gtk); +#endif // __WXUNIVERSAL__ + +// ---------------------------------------------------------------------------- +// event tables +// ---------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(LboxTestFrame, wxFrame) + EVT_BUTTON(LboxTest_Reset, LboxTestFrame::OnButtonReset) + EVT_BUTTON(LboxTest_Create, LboxTestFrame::OnButtonCreate) + EVT_BUTTON(LboxTest_Change, LboxTestFrame::OnButtonChange) + EVT_BUTTON(LboxTest_Delete, LboxTestFrame::OnButtonDelete) + EVT_BUTTON(LboxTest_DeleteSel, LboxTestFrame::OnButtonDeleteSel) + EVT_BUTTON(LboxTest_Clear, LboxTestFrame::OnButtonClear) + EVT_BUTTON(LboxTest_ClearLog, LboxTestFrame::OnButtonClearLog) + EVT_BUTTON(LboxTest_Add, LboxTestFrame::OnButtonAdd) + EVT_BUTTON(LboxTest_AddSeveral, LboxTestFrame::OnButtonAddSeveral) + EVT_BUTTON(LboxTest_AddMany, LboxTestFrame::OnButtonAddMany) + EVT_BUTTON(LboxTest_Quit, LboxTestFrame::OnButtonQuit) + + EVT_TEXT_ENTER(LboxTest_AddText, LboxTestFrame::OnButtonAdd) + EVT_TEXT_ENTER(LboxTest_DeleteText, LboxTestFrame::OnButtonDelete) + + EVT_UPDATE_UI_RANGE(LboxTest_Reset, LboxTest_Create, + LboxTestFrame::OnUpdateUICreateButton) + + EVT_UPDATE_UI(LboxTest_AddSeveral, LboxTestFrame::OnUpdateUIAddSeveral) + EVT_UPDATE_UI(LboxTest_Clear, LboxTestFrame::OnUpdateUIClearButton) + EVT_UPDATE_UI(LboxTest_DeleteText, LboxTestFrame::OnUpdateUIClearButton) + EVT_UPDATE_UI(LboxTest_Delete, LboxTestFrame::OnUpdateUIDeleteButton) + EVT_UPDATE_UI(LboxTest_Change, LboxTestFrame::OnUpdateUIDeleteSelButton) + EVT_UPDATE_UI(LboxTest_ChangeText, LboxTestFrame::OnUpdateUIDeleteSelButton) + EVT_UPDATE_UI(LboxTest_DeleteSel, LboxTestFrame::OnUpdateUIDeleteSelButton) + + EVT_LISTBOX(LboxTest_Listbox, LboxTestFrame::OnListbox) + EVT_LISTBOX_DCLICK(-1, LboxTestFrame::OnListboxDClick) + EVT_CHECKBOX(-1, LboxTestFrame::OnCheckOrRadioBox) + EVT_RADIOBOX(-1, LboxTestFrame::OnCheckOrRadioBox) +END_EVENT_TABLE() + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// app class +// ---------------------------------------------------------------------------- + +bool LboxTestApp::OnInit() +{ + wxFrame *frame = new LboxTestFrame(_T("wxListBox sample")); + frame->Show(); + + //wxLog::AddTraceMask(_T("listbox")); + wxLog::AddTraceMask(_T("scrollbar")); + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// top level frame class +// ---------------------------------------------------------------------------- + +LboxTestFrame::LboxTestFrame(const wxString& title) + : wxFrame(NULL, -1, title, wxPoint(100, 100)) +{ + // init everything + m_dirty = FALSE; + m_radioSelMode = (wxRadioBox *)NULL; + + m_chkVScroll = + m_chkHScroll = + m_chkSort = (wxCheckBox *)NULL; + + m_lbox = + m_lboxLog = (wxListBox *)NULL; + m_sizerLbox = (wxSizer *)NULL; + + m_logTarget = (wxLog *)NULL; + + wxPanel *panel = new wxPanel(this, -1); + + /* + 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(wxVERTICAL), + *sizerUp = new wxBoxSizer(wxHORIZONTAL), + *sizerLeft, + *sizerRight = new wxBoxSizer(wxVERTICAL); + + // upper left pane + static const wxString modes[] = + { + _T("single"), + _T("extended"), + _T("multiple"), + }; + + wxStaticBox *box = new wxStaticBox(panel, -1, _T("&Set listbox parameters")); + m_radioSelMode = new wxRadioBox(panel, -1, _T("Selection &mode:"), + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(modes), modes, + 1, wxRA_SPECIFY_COLS); + + m_chkVScroll = new wxCheckBox(panel, -1, _T("Always show &vertical scrollbar")); + m_chkHScroll = new wxCheckBox(panel, -1, _T("Show &horizontal scrollbar")); + m_chkSort = new wxCheckBox(panel, -1, _T("&Sort items")); + + sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL); + + 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(panel, LboxTest_Reset, _T("&Reset")); + sizerBtn->Add(btn, 0, wxLEFT | wxRIGHT, 5); + btn = new wxButton(panel, LboxTest_Create, _T("&Create")); + sizerBtn->Add(btn, 0, wxLEFT | wxRIGHT, 5); + sizerLeft->Add(sizerBtn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); + + // middle pane + wxStaticBox *box2 = new wxStaticBox(panel, -1, _T("&Change listbox contents")); + wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL); + + wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL); + 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); + + btn = new wxButton(panel, LboxTest_AddSeveral, _T("&Insert a few strings")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + btn = new wxButton(panel, LboxTest_AddMany, _T("Add &many strings")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + sizerRow = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(panel, LboxTest_Change, _T("C&hange current")); + m_textChange = new wxTextCtrl(panel, LboxTest_ChangeText, _T("")); + sizerRow->Add(btn, 0, wxRIGHT, 5); + sizerRow->Add(m_textChange, 1, wxLEFT, 5); + sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + + sizerRow = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(panel, LboxTest_Delete, _T("&Delete this item")); + m_textDelete = new wxTextCtrl(panel, LboxTest_DeleteText, _T("")); + sizerRow->Add(btn, 0, wxRIGHT, 5); + sizerRow->Add(m_textDelete, 1, wxLEFT, 5); + sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + + btn = new wxButton(panel, LboxTest_DeleteSel, _T("Delete &selection")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + btn = new wxButton(panel, LboxTest_Clear, _T("&Clear")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + // right pane + m_lbox = new wxListBox(panel, LboxTest_Listbox, + wxDefaultPosition, wxDefaultSize, + 0, NULL, + wxLB_HSCROLL); + sizerRight->Add(m_lbox, 1, wxGROW | wxALL, 5); + sizerRight->SetMinSize(250, 0); + m_sizerLbox = sizerRight; // save it to modify it later + + // the 3 panes panes compose the upper part of the window + sizerUp->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10); + sizerUp->Add(sizerMiddle, 1, wxGROW | wxALL, 10); + sizerUp->Add(sizerRight, 1, wxGROW | (wxALL & ~wxRIGHT), 10); + + // the lower one only has the log listbox and a button to clear it + wxSizer *sizerDown = new wxStaticBoxSizer + ( + new wxStaticBox(panel, -1, _T("&Log window")), + wxVERTICAL + ); + m_lboxLog = new wxListBox(panel, -1); + sizerDown->Add(m_lboxLog, 1, wxGROW | wxALL, 5); + wxBoxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(panel, LboxTest_ClearLog, _T("Clear &log")); + sizerBtns->Add(btn); + sizerBtns->Add(10, 0); // spacer + btn = new wxButton(panel, LboxTest_Quit, _T("E&xit")); + sizerBtns->Add(btn); + sizerDown->Add(sizerBtns, 0, wxALL | wxALIGN_RIGHT, 5); + + // put everything together + sizerTop->Add(sizerUp, 1, wxGROW | (wxALL & ~wxBOTTOM), 10); + sizerTop->Add(0, 5, 0, wxGROW); // spacer in between + sizerTop->Add(sizerDown, 0, wxGROW | (wxALL & ~wxTOP), 10); + + // final initialization + Reset(); + m_dirty = FALSE; + + panel->SetAutoLayout(TRUE); + panel->SetSizer(sizerTop); + + sizerTop->Fit(this); + sizerTop->SetSizeHints(this); + + // now that everything is created we can redirect the log messages to the + // listbox + m_logTarget = new LboxLogger(m_lboxLog, wxLog::GetActiveTarget()); + wxLog::SetActiveTarget(m_logTarget); +} + +LboxTestFrame::~LboxTestFrame() +{ + delete m_logTarget; +} + +// ---------------------------------------------------------------------------- +// operations +// ---------------------------------------------------------------------------- + +void LboxTestFrame::Reset() +{ + if ( m_radioSelMode->GetSelection() == LboxSel_Single && + !m_chkSort->GetValue() && + m_chkHScroll->GetValue() && + !m_chkVScroll->GetValue() ) + { + // nothing to do + return; + } + + m_radioSelMode->SetSelection(LboxSel_Single); + m_chkSort->SetValue(FALSE); + m_chkHScroll->SetValue(TRUE); + m_chkVScroll->SetValue(FALSE); + + m_dirty = TRUE; +} + +void LboxTestFrame::CreateLbox() +{ + int flags = 0; + switch ( m_radioSelMode->GetSelection() ) + { + default: + wxFAIL_MSG( _T("unexpected radio box selection") ); + + case LboxSel_Single: flags |= wxLB_SINGLE; break; + case LboxSel_Extended: flags |= wxLB_EXTENDED; break; + case LboxSel_Multiple: flags |= wxLB_MULTIPLE; break; + } + + if ( m_chkVScroll->GetValue() ) + flags |= wxLB_ALWAYS_SB; + if ( m_chkHScroll->GetValue() ) + flags |= wxLB_HSCROLL; + if ( m_chkSort->GetValue() ) + flags |= wxLB_SORT; + + wxArrayString items; + if ( m_lbox ) + { + int count = m_lbox->GetCount(); + for ( int n = 0; n < count; n++ ) + { + items.Add(m_lbox->GetString(n)); + } + + m_sizerLbox->Remove(m_lbox); + delete m_lbox; + } + + m_lbox = new wxListBox(this, -1, + wxDefaultPosition, wxDefaultSize, + 0, NULL, + flags); + m_lbox->Set(items); + m_sizerLbox->Add(m_lbox, 1, wxGROW | wxALL, 5); + m_sizerLbox->Layout(); + + m_dirty = FALSE; +} + +// ---------------------------------------------------------------------------- +// event handlers +// ---------------------------------------------------------------------------- + +void LboxTestFrame::OnButtonQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(); +} + +void LboxTestFrame::OnButtonReset(wxCommandEvent& WXUNUSED(event)) +{ + Reset(); +} + +void LboxTestFrame::OnButtonCreate(wxCommandEvent& WXUNUSED(event)) +{ + CreateLbox(); +} + +void LboxTestFrame::OnButtonChange(wxCommandEvent& WXUNUSED(event)) +{ + wxArrayInt selections; + int count = m_lbox->GetSelections(selections); + wxString s = m_textChange->GetValue(); + for ( int n = 0; n < count; n++ ) + { + m_lbox->SetString(selections[n], s); + } +} + +void LboxTestFrame::OnButtonDelete(wxCommandEvent& WXUNUSED(event)) +{ + unsigned long n; + if ( !m_textDelete->GetValue().ToULong(&n) || + (n >= (unsigned)m_lbox->GetCount()) ) + { + return; + } + + m_lbox->Delete(n); +} + +void LboxTestFrame::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(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(); +} + +void LboxTestFrame::OnButtonClearLog(wxCommandEvent& event) +{ + m_lboxLog->Clear(); +} + +void LboxTestFrame::OnButtonAdd(wxCommandEvent& event) +{ + static size_t s_item = 0; + + wxString s = m_textAdd->GetValue(); + if ( !m_textAdd->IsModified() ) + { + // update the default string + m_textAdd->SetValue(wxString::Format(_T("test item %u"), ++s_item)); + } + + m_lbox->Append(s); +} + +void LboxTestFrame::OnButtonAddMany(wxCommandEvent& WXUNUSED(event)) +{ + // "many" means 1000 here + for ( size_t n = 0; n < 1000; n++ ) + { + m_lbox->Append(wxString::Format(_T("item #%u"), n)); + } +} + +void LboxTestFrame::OnButtonAddSeveral(wxCommandEvent& event) +{ + wxArrayString items; + items.Add(_T("First")); + items.Add(_T("another one")); + items.Add(_T("and the last (very very very very very very very very very very long) one")); + m_lbox->InsertItems(items, 0); +} + +void LboxTestFrame::OnUpdateUICreateButton(wxUpdateUIEvent& event) +{ + event.Enable(m_dirty); +} + +void LboxTestFrame::OnUpdateUIDeleteButton(wxUpdateUIEvent& event) +{ + unsigned long n; + event.Enable(m_textDelete->GetValue().ToULong(&n) && + (n < (unsigned)m_lbox->GetCount())); +} + +void LboxTestFrame::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event) +{ + wxArrayInt selections; + event.Enable(m_lbox->GetSelections(selections) != 0); +} + +void LboxTestFrame::OnUpdateUIClearButton(wxUpdateUIEvent& event) +{ + event.Enable(m_lbox->GetCount() != 0); +} + +void LboxTestFrame::OnUpdateUIAddSeveral(wxUpdateUIEvent& event) +{ + event.Enable(!(m_lbox->GetWindowStyle() & wxLB_SORT)); +} + +void LboxTestFrame::OnListbox(wxCommandEvent& event) +{ + int sel = event.GetInt(); + m_textDelete->SetValue(wxString::Format(_T("%ld"), sel)); + + wxLogMessage(_T("Listbox item %d selected"), sel); +} + +void LboxTestFrame::OnListboxDClick(wxCommandEvent& event) +{ + wxLogMessage(_T("Listbox item %d double clicked"), event.GetInt()); +} + +void LboxTestFrame::OnCheckOrRadioBox(wxCommandEvent& event) +{ + m_dirty = TRUE; +} + -- 2.45.2