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