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