1/////////////////////////////////////////////////////////////////////////////
2// Program:     wxWidgets Widgets Sample
3// Name:        listbox.cpp
4// Purpose:     Part of the widgets sample showing wxListbox
5// Author:      Vadim Zeitlin
6// Created:     27.03.01
7// Id:          $Id: listbox.cpp 43755 2006-12-03 13:43:44Z VZ $
8// Copyright:   (c) 2001 Vadim Zeitlin
9// License:     wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// for compilers that support precompilation, includes "wx/wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24    #pragma hdrstop
25#endif
26
27#if wxUSE_LISTBOX
28
29// for all others, include the necessary headers
30#ifndef WX_PRECOMP
31    #include "wx/log.h"
32
33    #include "wx/bitmap.h"
34    #include "wx/button.h"
35    #include "wx/checkbox.h"
36    #include "wx/combobox.h"
37    #include "wx/listbox.h"
38    #include "wx/radiobox.h"
39    #include "wx/statbox.h"
40    #include "wx/textctrl.h"
41#endif
42
43#include "wx/sizer.h"
44
45#include "wx/checklst.h"
46
47#include "widgets.h"
48
49#include "icons/listbox.xpm"
50
51// ----------------------------------------------------------------------------
52// constants
53// ----------------------------------------------------------------------------
54
55// control ids
56enum
57{
58    ListboxPage_Reset = wxID_HIGHEST,
59    ListboxPage_Add,
60    ListboxPage_AddText,
61    ListboxPage_AddSeveral,
62    ListboxPage_AddMany,
63    ListboxPage_Clear,
64    ListboxPage_Change,
65    ListboxPage_ChangeText,
66    ListboxPage_Delete,
67    ListboxPage_DeleteText,
68    ListboxPage_DeleteSel,
69    ListboxPage_Listbox
70};
71
72// ----------------------------------------------------------------------------
73// ListboxWidgetsPage
74// ----------------------------------------------------------------------------
75
76class ListboxWidgetsPage : public WidgetsPage
77{
78public:
79    ListboxWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
80
81    virtual wxControl *GetWidget() const { return m_lbox; }
82    virtual void RecreateWidget() { CreateLbox(); }
83
84    // lazy creation of the content
85    virtual void CreateContent();
86
87protected:
88    // event handlers
89    void OnButtonReset(wxCommandEvent& event);
90    void OnButtonChange(wxCommandEvent& event);
91    void OnButtonDelete(wxCommandEvent& event);
92    void OnButtonDeleteSel(wxCommandEvent& event);
93    void OnButtonClear(wxCommandEvent& event);
94    void OnButtonAdd(wxCommandEvent& event);
95    void OnButtonAddSeveral(wxCommandEvent& event);
96    void OnButtonAddMany(wxCommandEvent& event);
97
98    void OnListbox(wxCommandEvent& event);
99    void OnListboxDClick(wxCommandEvent& event);
100    void OnCheckListbox(wxCommandEvent& event);
101
102    void OnCheckOrRadioBox(wxCommandEvent& event);
103
104    void OnUpdateUIAddSeveral(wxUpdateUIEvent& event);
105    void OnUpdateUIClearButton(wxUpdateUIEvent& event);
106    void OnUpdateUIDeleteButton(wxUpdateUIEvent& event);
107    void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event);
108    void OnUpdateUIResetButton(wxUpdateUIEvent& event);
109
110    // reset the listbox parameters
111    void Reset();
112
113    // (re)create the listbox
114    void CreateLbox();
115
116    // listbox parameters
117    // ------------------
118
119    // the selection mode
120    enum LboxSelection
121    {
122        LboxSel_Single,
123        LboxSel_Extended,
124        LboxSel_Multiple
125    } m_lboxSelMode;
126
127    // should it be sorted?
128    bool m_sorted;
129
130    // should it have horz scroll/vert scrollbar permanently shown?
131    bool m_horzScroll,
132         m_vertScrollAlways;
133
134    // the controls
135    // ------------
136
137    // the sel mode radiobox
138    wxRadioBox *m_radioSelMode;
139
140    // the checkboxes
141    wxCheckBox *m_chkVScroll,
142               *m_chkHScroll,
143               *m_chkCheck,
144               *m_chkSort,
145               *m_chkOwnerDraw;
146
147    // the listbox itself and the sizer it is in
148#ifdef __WXWINCE__
149    wxListBoxBase
150#else
151    wxListBox
152#endif
153                  *m_lbox;
154
155    wxSizer *m_sizerLbox;
156
157    // the text entries for "Add/change string" and "Delete" buttons
158    wxTextCtrl *m_textAdd,
159               *m_textChange,
160               *m_textDelete;
161
162private:
163    DECLARE_EVENT_TABLE()
164    DECLARE_WIDGETS_PAGE(ListboxWidgetsPage)
165};
166
167// ----------------------------------------------------------------------------
168// event tables
169// ----------------------------------------------------------------------------
170
171BEGIN_EVENT_TABLE(ListboxWidgetsPage, WidgetsPage)
172    EVT_BUTTON(ListboxPage_Reset, ListboxWidgetsPage::OnButtonReset)
173    EVT_BUTTON(ListboxPage_Change, ListboxWidgetsPage::OnButtonChange)
174    EVT_BUTTON(ListboxPage_Delete, ListboxWidgetsPage::OnButtonDelete)
175    EVT_BUTTON(ListboxPage_DeleteSel, ListboxWidgetsPage::OnButtonDeleteSel)
176    EVT_BUTTON(ListboxPage_Clear, ListboxWidgetsPage::OnButtonClear)
177    EVT_BUTTON(ListboxPage_Add, ListboxWidgetsPage::OnButtonAdd)
178    EVT_BUTTON(ListboxPage_AddSeveral, ListboxWidgetsPage::OnButtonAddSeveral)
179    EVT_BUTTON(ListboxPage_AddMany, ListboxWidgetsPage::OnButtonAddMany)
180
181    EVT_TEXT_ENTER(ListboxPage_AddText, ListboxWidgetsPage::OnButtonAdd)
182    EVT_TEXT_ENTER(ListboxPage_DeleteText, ListboxWidgetsPage::OnButtonDelete)
183
184    EVT_UPDATE_UI(ListboxPage_Reset, ListboxWidgetsPage::OnUpdateUIResetButton)
185    EVT_UPDATE_UI(ListboxPage_AddSeveral, ListboxWidgetsPage::OnUpdateUIAddSeveral)
186    EVT_UPDATE_UI(ListboxPage_Clear, ListboxWidgetsPage::OnUpdateUIClearButton)
187    EVT_UPDATE_UI(ListboxPage_DeleteText, ListboxWidgetsPage::OnUpdateUIClearButton)
188    EVT_UPDATE_UI(ListboxPage_Delete, ListboxWidgetsPage::OnUpdateUIDeleteButton)
189    EVT_UPDATE_UI(ListboxPage_Change, ListboxWidgetsPage::OnUpdateUIDeleteSelButton)
190    EVT_UPDATE_UI(ListboxPage_ChangeText, ListboxWidgetsPage::OnUpdateUIDeleteSelButton)
191    EVT_UPDATE_UI(ListboxPage_DeleteSel, ListboxWidgetsPage::OnUpdateUIDeleteSelButton)
192
193    EVT_LISTBOX(ListboxPage_Listbox, ListboxWidgetsPage::OnListbox)
194    EVT_LISTBOX_DCLICK(ListboxPage_Listbox, ListboxWidgetsPage::OnListboxDClick)
195    EVT_CHECKLISTBOX(ListboxPage_Listbox, ListboxWidgetsPage::OnCheckListbox)
196
197    EVT_CHECKBOX(wxID_ANY, ListboxWidgetsPage::OnCheckOrRadioBox)
198    EVT_RADIOBOX(wxID_ANY, ListboxWidgetsPage::OnCheckOrRadioBox)
199END_EVENT_TABLE()
200
201// ============================================================================
202// implementation
203// ============================================================================
204
205#if defined(__WXUNIVERSAL__)
206    #define FAMILY_CTRLS UNIVERSAL_CTRLS
207#else
208    #define FAMILY_CTRLS NATIVE_CTRLS
209#endif
210
211IMPLEMENT_WIDGETS_PAGE(ListboxWidgetsPage, _T("Listbox"),
212                       FAMILY_CTRLS | WITH_ITEMS_CTRLS
213                       );
214
215ListboxWidgetsPage::ListboxWidgetsPage(WidgetsBookCtrl *book,
216                                       wxImageList *imaglist)
217                  : WidgetsPage(book, imaglist, listbox_xpm)
218{
219    // init everything
220    m_radioSelMode = (wxRadioBox *)NULL;
221
222    m_chkVScroll =
223    m_chkHScroll =
224    m_chkCheck =
225    m_chkSort =
226    m_chkOwnerDraw = (wxCheckBox *)NULL;
227
228    m_lbox = NULL;
229    m_sizerLbox = (wxSizer *)NULL;
230
231}
232
233void ListboxWidgetsPage::CreateContent()
234{
235    /*
236       What we create here is a frame having 3 panes: style pane is the
237       leftmost one, in the middle the pane with buttons allowing to perform
238       miscellaneous listbox operations and the pane containing the listbox
239       itself to the right
240    */
241    wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
242
243    // left pane
244    wxStaticBox *box = new wxStaticBox(this, wxID_ANY,
245        _T("&Set listbox parameters"));
246    wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
247
248    static const wxString modes[] =
249    {
250        _T("single"),
251        _T("extended"),
252        _T("multiple"),
253    };
254
255    m_radioSelMode = new wxRadioBox(this, wxID_ANY, _T("Selection &mode:"),
256                                    wxDefaultPosition, wxDefaultSize,
257                                    WXSIZEOF(modes), modes,
258                                    1, wxRA_SPECIFY_COLS);
259
260    m_chkVScroll = CreateCheckBoxAndAddToSizer
261                   (
262                    sizerLeft,
263                    _T("Always show &vertical scrollbar")
264                   );
265    m_chkHScroll = CreateCheckBoxAndAddToSizer
266                   (
267                    sizerLeft,
268                    _T("Show &horizontal scrollbar")
269                   );
270    m_chkCheck = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Check list box"));
271    m_chkSort = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Sort items"));
272    m_chkOwnerDraw = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Owner drawn"));
273
274    sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
275    sizerLeft->Add(m_radioSelMode, 0, wxGROW | wxALL, 5);
276
277    wxButton *btn = new wxButton(this, ListboxPage_Reset, _T("&Reset"));
278    sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
279
280    // middle pane
281    wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY,
282        _T("&Change listbox contents"));
283    wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
284
285    wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
286    btn = new wxButton(this, ListboxPage_Add, _T("&Add this string"));
287    m_textAdd = new wxTextCtrl(this, ListboxPage_AddText, _T("test item 0"));
288    sizerRow->Add(btn, 0, wxRIGHT, 5);
289    sizerRow->Add(m_textAdd, 1, wxLEFT, 5);
290    sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
291
292    btn = new wxButton(this, ListboxPage_AddSeveral, _T("&Insert a few strings"));
293    sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
294
295    btn = new wxButton(this, ListboxPage_AddMany, _T("Add &many strings"));
296    sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
297
298    sizerRow = new wxBoxSizer(wxHORIZONTAL);
299    btn = new wxButton(this, ListboxPage_Change, _T("C&hange current"));
300    m_textChange = new wxTextCtrl(this, ListboxPage_ChangeText, wxEmptyString);
301    sizerRow->Add(btn, 0, wxRIGHT, 5);
302    sizerRow->Add(m_textChange, 1, wxLEFT, 5);
303    sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
304
305    sizerRow = new wxBoxSizer(wxHORIZONTAL);
306    btn = new wxButton(this, ListboxPage_Delete, _T("&Delete this item"));
307    m_textDelete = new wxTextCtrl(this, ListboxPage_DeleteText, wxEmptyString);
308    sizerRow->Add(btn, 0, wxRIGHT, 5);
309    sizerRow->Add(m_textDelete, 1, wxLEFT, 5);
310    sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
311
312    btn = new wxButton(this, ListboxPage_DeleteSel, _T("Delete &selection"));
313    sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
314
315    btn = new wxButton(this, ListboxPage_Clear, _T("&Clear"));
316    sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
317
318    // right pane
319    wxSizer *sizerRight = new wxBoxSizer(wxVERTICAL);
320    m_lbox = new wxListBox(this, ListboxPage_Listbox,
321                           wxDefaultPosition, wxDefaultSize,
322                           0, NULL,
323                           wxLB_HSCROLL);
324    sizerRight->Add(m_lbox, 1, wxGROW | wxALL, 5);
325    sizerRight->SetMinSize(150, 0);
326    m_sizerLbox = sizerRight; // save it to modify it later
327
328    // the 3 panes panes compose the window
329    sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
330    sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
331    sizerTop->Add(sizerRight, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
332
333    // final initializations
334    Reset();
335
336    SetSizer(sizerTop);
337}
338
339// ----------------------------------------------------------------------------
340// operations
341// ----------------------------------------------------------------------------
342
343void ListboxWidgetsPage::Reset()
344{
345    m_radioSelMode->SetSelection(LboxSel_Single);
346    m_chkVScroll->SetValue(false);
347    m_chkHScroll->SetValue(true);
348    m_chkCheck->SetValue(false);
349    m_chkSort->SetValue(false);
350    m_chkOwnerDraw->SetValue(false);
351}
352
353void ListboxWidgetsPage::CreateLbox()
354{
355    int flags = ms_defaultFlags;
356    switch ( m_radioSelMode->GetSelection() )
357    {
358        default:
359            wxFAIL_MSG( _T("unexpected radio box selection") );
360
361        case LboxSel_Single:    flags |= wxLB_SINGLE; break;
362        case LboxSel_Extended:  flags |= wxLB_EXTENDED; break;
363        case LboxSel_Multiple:  flags |= wxLB_MULTIPLE; break;
364    }
365
366    if ( m_chkVScroll->GetValue() )
367        flags |= wxLB_ALWAYS_SB;
368    if ( m_chkHScroll->GetValue() )
369        flags |= wxLB_HSCROLL;
370    if ( m_chkSort->GetValue() )
371        flags |= wxLB_SORT;
372    if ( m_chkOwnerDraw->GetValue() )
373        flags |= wxLB_OWNERDRAW;
374
375    wxArrayString items;
376    if ( m_lbox )
377    {
378        int count = m_lbox->GetCount();
379        for ( int n = 0; n < count; n++ )
380        {
381            items.Add(m_lbox->GetString(n));
382        }
383
384        m_sizerLbox->Detach( m_lbox );
385        delete m_lbox;
386    }
387
388#if wxUSE_CHECKLISTBOX
389    if ( m_chkCheck->GetValue() )
390    {
391        m_lbox = new wxCheckListBox(this, ListboxPage_Listbox,
392                                    wxDefaultPosition, wxDefaultSize,
393                                    0, NULL,
394                                    flags);
395    }
396    else // just a listbox
397#endif
398    {
399        m_lbox = new wxListBox(this, ListboxPage_Listbox,
400                               wxDefaultPosition, wxDefaultSize,
401                               0, NULL,
402                               flags);
403    }
404
405    m_lbox->Set(items);
406    m_sizerLbox->Add(m_lbox, 1, wxGROW | wxALL, 5);
407    m_sizerLbox->Layout();
408}
409
410// ----------------------------------------------------------------------------
411// event handlers
412// ----------------------------------------------------------------------------
413
414void ListboxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
415{
416    Reset();
417
418    CreateLbox();
419}
420
421void ListboxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
422{
423    wxArrayInt selections;
424    int count = m_lbox->GetSelections(selections);
425    wxString s = m_textChange->GetValue();
426    for ( int n = 0; n < count; n++ )
427    {
428        m_lbox->SetString(selections[n], s);
429    }
430}
431
432void ListboxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
433{
434    unsigned long n;
435    if ( !m_textDelete->GetValue().ToULong(&n) ||
436            (n >= (unsigned)m_lbox->GetCount()) )
437    {
438        return;
439    }
440
441    m_lbox->Delete(n);
442}
443
444void ListboxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
445{
446    wxArrayInt selections;
447    int n = m_lbox->GetSelections(selections);
448    while ( n > 0 )
449    {
450        m_lbox->Delete(selections[--n]);
451    }
452}
453
454void ListboxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
455{
456    m_lbox->Clear();
457}
458
459void ListboxWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
460{
461    static unsigned int s_item = 0;
462
463    wxString s = m_textAdd->GetValue();
464    if ( !m_textAdd->IsModified() )
465    {
466        // update the default string
467        m_textAdd->SetValue(wxString::Format(_T("test item %u"), ++s_item));
468    }
469
470    m_lbox->Append(s);
471}
472
473void ListboxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
474{
475    // "many" means 1000 here
476    for ( unsigned int n = 0; n < 1000; n++ )
477    {
478        m_lbox->Append(wxString::Format(_T("item #%u"), n));
479    }
480}
481
482void ListboxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
483{
484    wxArrayString items;
485    items.Add(_T("First"));
486    items.Add(_T("another one"));
487    items.Add(_T("and the last (very very very very very very very very very very long) one"));
488    m_lbox->InsertItems(items, 0);
489}
490
491void ListboxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
492{
493    event.Enable( (m_radioSelMode->GetSelection() != LboxSel_Single) ||
494                  m_chkSort->GetValue() ||
495                  m_chkOwnerDraw->GetValue() ||
496                  !m_chkHScroll->GetValue() ||
497                  m_chkVScroll->GetValue() );
498}
499
500void ListboxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
501{
502    unsigned long n;
503    event.Enable(m_textDelete->GetValue().ToULong(&n) &&
504                    (n < (unsigned)m_lbox->GetCount()));
505}
506
507void ListboxWidgetsPage::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event)
508{
509    wxArrayInt selections;
510    event.Enable(m_lbox->GetSelections(selections) != 0);
511}
512
513void ListboxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
514{
515    event.Enable(m_lbox->GetCount() != 0);
516}
517
518void ListboxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
519{
520    event.Enable(!(m_lbox->GetWindowStyle() & wxLB_SORT));
521}
522
523void ListboxWidgetsPage::OnListbox(wxCommandEvent& event)
524{
525    long sel = event.GetSelection();
526    m_textDelete->SetValue(wxString::Format(_T("%ld"), sel));
527
528    if (event.IsSelection())
529        wxLogMessage(_T("Listbox item %ld selected"), sel);
530    else
531        wxLogMessage(_T("Listbox item %ld deselected"), sel);
532}
533
534void ListboxWidgetsPage::OnListboxDClick(wxCommandEvent& event)
535{
536    wxLogMessage( _T("Listbox item %d double clicked"), event.GetInt() );
537}
538
539void ListboxWidgetsPage::OnCheckListbox(wxCommandEvent& event)
540{
541    wxLogMessage( _T("Listbox item %d toggled"), event.GetInt() );
542}
543
544void ListboxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
545{
546    CreateLbox();
547}
548
549#endif // wxUSE_LISTBOX
550