fix initial layout of the widgets pages: avoid calling Fit() on them
[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
339 // ----------------------------------------------------------------------------
340 // operations
341 // ----------------------------------------------------------------------------
342
343 void 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
353 void 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
414 void ListboxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
415 {
416 Reset();
417
418 CreateLbox();
419 }
420
421 void 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
432 void 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
444 void 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
454 void ListboxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
455 {
456 m_lbox->Clear();
457 }
458
459 void 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
473 void 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
482 void 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
491 void 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
500 void 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
507 void ListboxWidgetsPage::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event)
508 {
509 wxArrayInt selections;
510 event.Enable(m_lbox->GetSelections(selections) != 0);
511 }
512
513 void ListboxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
514 {
515 event.Enable(m_lbox->GetCount() != 0);
516 }
517
518 void ListboxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
519 {
520 event.Enable(!(m_lbox->GetWindowStyle() & wxLB_SORT));
521 }
522
523 void 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
534 void ListboxWidgetsPage::OnListboxDClick(wxCommandEvent& event)
535 {
536 wxLogMessage( _T("Listbox item %d double clicked"), event.GetInt() );
537 }
538
539 void ListboxWidgetsPage::OnCheckListbox(wxCommandEvent& event)
540 {
541 wxLogMessage( _T("Listbox item %d toggled"), event.GetInt() );
542 }
543
544 void ListboxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
545 {
546 CreateLbox();
547 }
548
549 #endif // wxUSE_LISTBOX