]> git.saurik.com Git - wxWidgets.git/blob - samples/widgets/listbox.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[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 // lazy creation of the content
85 virtual void CreateContent();
86
87 protected:
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
162 private:
163 DECLARE_EVENT_TABLE()
164 DECLARE_WIDGETS_PAGE(ListboxWidgetsPage)
165 };
166
167 // ----------------------------------------------------------------------------
168 // event tables
169 // ----------------------------------------------------------------------------
170
171 BEGIN_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)
199 END_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
211 IMPLEMENT_WIDGETS_PAGE(ListboxWidgetsPage, _T("Listbox"),
212 FAMILY_CTRLS | WITH_ITEMS_CTRLS
213 );
214
215 ListboxWidgetsPage::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
233 void 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 sizerTop->Fit(this);
339 }
340
341 // ----------------------------------------------------------------------------
342 // operations
343 // ----------------------------------------------------------------------------
344
345 void ListboxWidgetsPage::Reset()
346 {
347 m_radioSelMode->SetSelection(LboxSel_Single);
348 m_chkVScroll->SetValue(false);
349 m_chkHScroll->SetValue(true);
350 m_chkCheck->SetValue(false);
351 m_chkSort->SetValue(false);
352 m_chkOwnerDraw->SetValue(false);
353 }
354
355 void ListboxWidgetsPage::CreateLbox()
356 {
357 int flags = ms_defaultFlags;
358 switch ( m_radioSelMode->GetSelection() )
359 {
360 default:
361 wxFAIL_MSG( _T("unexpected radio box selection") );
362
363 case LboxSel_Single: flags |= wxLB_SINGLE; break;
364 case LboxSel_Extended: flags |= wxLB_EXTENDED; break;
365 case LboxSel_Multiple: flags |= wxLB_MULTIPLE; break;
366 }
367
368 if ( m_chkVScroll->GetValue() )
369 flags |= wxLB_ALWAYS_SB;
370 if ( m_chkHScroll->GetValue() )
371 flags |= wxLB_HSCROLL;
372 if ( m_chkSort->GetValue() )
373 flags |= wxLB_SORT;
374 if ( m_chkOwnerDraw->GetValue() )
375 flags |= wxLB_OWNERDRAW;
376
377 wxArrayString items;
378 if ( m_lbox )
379 {
380 int count = m_lbox->GetCount();
381 for ( int n = 0; n < count; n++ )
382 {
383 items.Add(m_lbox->GetString(n));
384 }
385
386 m_sizerLbox->Detach( m_lbox );
387 delete m_lbox;
388 }
389
390 #if wxUSE_CHECKLISTBOX
391 if ( m_chkCheck->GetValue() )
392 {
393 m_lbox = new wxCheckListBox(this, ListboxPage_Listbox,
394 wxDefaultPosition, wxDefaultSize,
395 0, NULL,
396 flags);
397 }
398 else // just a listbox
399 #endif
400 {
401 m_lbox = new wxListBox(this, ListboxPage_Listbox,
402 wxDefaultPosition, wxDefaultSize,
403 0, NULL,
404 flags);
405 }
406
407 m_lbox->Set(items);
408 m_sizerLbox->Add(m_lbox, 1, wxGROW | wxALL, 5);
409 m_sizerLbox->Layout();
410 }
411
412 // ----------------------------------------------------------------------------
413 // event handlers
414 // ----------------------------------------------------------------------------
415
416 void ListboxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
417 {
418 Reset();
419
420 CreateLbox();
421 }
422
423 void ListboxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
424 {
425 wxArrayInt selections;
426 int count = m_lbox->GetSelections(selections);
427 wxString s = m_textChange->GetValue();
428 for ( int n = 0; n < count; n++ )
429 {
430 m_lbox->SetString(selections[n], s);
431 }
432 }
433
434 void ListboxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
435 {
436 unsigned long n;
437 if ( !m_textDelete->GetValue().ToULong(&n) ||
438 (n >= (unsigned)m_lbox->GetCount()) )
439 {
440 return;
441 }
442
443 m_lbox->Delete(n);
444 }
445
446 void ListboxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
447 {
448 wxArrayInt selections;
449 int n = m_lbox->GetSelections(selections);
450 while ( n > 0 )
451 {
452 m_lbox->Delete(selections[--n]);
453 }
454 }
455
456 void ListboxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
457 {
458 m_lbox->Clear();
459 }
460
461 void ListboxWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
462 {
463 static unsigned int s_item = 0;
464
465 wxString s = m_textAdd->GetValue();
466 if ( !m_textAdd->IsModified() )
467 {
468 // update the default string
469 m_textAdd->SetValue(wxString::Format(_T("test item %u"), ++s_item));
470 }
471
472 m_lbox->Append(s);
473 }
474
475 void ListboxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
476 {
477 // "many" means 1000 here
478 for ( unsigned int n = 0; n < 1000; n++ )
479 {
480 m_lbox->Append(wxString::Format(_T("item #%u"), n));
481 }
482 }
483
484 void ListboxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
485 {
486 wxArrayString items;
487 items.Add(_T("First"));
488 items.Add(_T("another one"));
489 items.Add(_T("and the last (very very very very very very very very very very long) one"));
490 m_lbox->InsertItems(items, 0);
491 }
492
493 void ListboxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
494 {
495 event.Enable( (m_radioSelMode->GetSelection() != LboxSel_Single) ||
496 m_chkSort->GetValue() ||
497 m_chkOwnerDraw->GetValue() ||
498 !m_chkHScroll->GetValue() ||
499 m_chkVScroll->GetValue() );
500 }
501
502 void ListboxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
503 {
504 unsigned long n;
505 event.Enable(m_textDelete->GetValue().ToULong(&n) &&
506 (n < (unsigned)m_lbox->GetCount()));
507 }
508
509 void ListboxWidgetsPage::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event)
510 {
511 wxArrayInt selections;
512 event.Enable(m_lbox->GetSelections(selections) != 0);
513 }
514
515 void ListboxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
516 {
517 event.Enable(m_lbox->GetCount() != 0);
518 }
519
520 void ListboxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
521 {
522 event.Enable(!(m_lbox->GetWindowStyle() & wxLB_SORT));
523 }
524
525 void ListboxWidgetsPage::OnListbox(wxCommandEvent& event)
526 {
527 long sel = event.GetSelection();
528 m_textDelete->SetValue(wxString::Format(_T("%ld"), sel));
529
530 if (event.IsSelection())
531 wxLogMessage(_T("Listbox item %ld selected"), sel);
532 else
533 wxLogMessage(_T("Listbox item %ld deselected"), sel);
534 }
535
536 void ListboxWidgetsPage::OnListboxDClick(wxCommandEvent& event)
537 {
538 wxLogMessage( _T("Listbox item %d double clicked"), event.GetInt() );
539 }
540
541 void ListboxWidgetsPage::OnCheckListbox(wxCommandEvent& event)
542 {
543 wxLogMessage( _T("Listbox item %d toggled"), event.GetInt() );
544 }
545
546 void ListboxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
547 {
548 CreateLbox();
549 }
550
551 #endif // wxUSE_LISTBOX