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