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