allow to test changing combobox selection too
[wxWidgets.git] / samples / widgets / combobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: combobox.cpp
4 // Purpose: Part of the widgets sample showing wxComboBox
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_COMBOBOX
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/radiobox.h"
38 #include "wx/statbox.h"
39 #include "wx/textctrl.h"
40 #endif
41
42 #include "wx/sizer.h"
43
44 #include "widgets.h"
45 #if 1
46 #include "icons/combobox.xpm"
47
48 // ----------------------------------------------------------------------------
49 // constants
50 // ----------------------------------------------------------------------------
51
52 // control ids
53 enum
54 {
55 ComboPage_Reset = wxID_HIGHEST,
56 ComboPage_SetCurrent,
57 ComboPage_CurText,
58 ComboPage_InsertionPointText,
59 ComboPage_Insert,
60 ComboPage_InsertText,
61 ComboPage_Add,
62 ComboPage_AddText,
63 ComboPage_AddSeveral,
64 ComboPage_AddMany,
65 ComboPage_Clear,
66 ComboPage_Change,
67 ComboPage_ChangeText,
68 ComboPage_Delete,
69 ComboPage_DeleteText,
70 ComboPage_DeleteSel,
71 ComboPage_Combo
72 };
73
74 // kinds of comboboxes
75 enum
76 {
77 ComboKind_Default,
78 ComboKind_Simple,
79 ComboKind_DropDown
80 };
81
82 // ----------------------------------------------------------------------------
83 // ComboboxWidgetsPage
84 // ----------------------------------------------------------------------------
85
86 class ComboboxWidgetsPage : public WidgetsPage
87 {
88 public:
89 ComboboxWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
90
91 virtual wxControl *GetWidget() const { return m_combobox; }
92 virtual void RecreateWidget() { CreateCombo(); }
93
94 // lazy creation of the content
95 virtual void CreateContent();
96
97 protected:
98 // event handlers
99 void OnButtonReset(wxCommandEvent& event);
100 void OnButtonChange(wxCommandEvent& event);
101 void OnButtonDelete(wxCommandEvent& event);
102 void OnButtonDeleteSel(wxCommandEvent& event);
103 void OnButtonClear(wxCommandEvent& event);
104 void OnButtonInsert(wxCommandEvent &event);
105 void OnButtonAdd(wxCommandEvent& event);
106 void OnButtonAddSeveral(wxCommandEvent& event);
107 void OnButtonAddMany(wxCommandEvent& event);
108 void OnButtonSetCurrent(wxCommandEvent& event);
109
110 void OnComboBox(wxCommandEvent& event);
111 void OnComboText(wxCommandEvent& event);
112
113 void OnCheckOrRadioBox(wxCommandEvent& event);
114
115 void OnUpdateUIInsertionPointText(wxUpdateUIEvent& event);
116
117 void OnUpdateUIInsert(wxUpdateUIEvent& event);
118 void OnUpdateUIAddSeveral(wxUpdateUIEvent& event);
119 void OnUpdateUIClearButton(wxUpdateUIEvent& event);
120 void OnUpdateUIDeleteButton(wxUpdateUIEvent& event);
121 void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event);
122 void OnUpdateUIResetButton(wxUpdateUIEvent& event);
123 void OnUpdateUISetCurrent(wxUpdateUIEvent& event);
124
125 // reset the combobox parameters
126 void Reset();
127
128 // (re)create the combobox
129 void CreateCombo();
130
131 // the controls
132 // ------------
133
134 // the sel mode radiobox
135 wxRadioBox *m_radioKind;
136
137 // the checkboxes for styles
138 wxCheckBox *m_chkSort,
139 *m_chkReadonly,
140 *m_chkFilename;
141
142 // the combobox itself and the sizer it is in
143 wxComboBox *m_combobox;
144 wxSizer *m_sizerCombo;
145
146 // the text entries for "Add/change string" and "Delete" buttons
147 wxTextCtrl *m_textInsert,
148 *m_textAdd,
149 *m_textChange,
150 *m_textDelete,
151 *m_textCur;
152
153 private:
154 DECLARE_EVENT_TABLE()
155 DECLARE_WIDGETS_PAGE(ComboboxWidgetsPage)
156 };
157
158 // ----------------------------------------------------------------------------
159 // event tables
160 // ----------------------------------------------------------------------------
161
162 BEGIN_EVENT_TABLE(ComboboxWidgetsPage, WidgetsPage)
163 EVT_BUTTON(ComboPage_Reset, ComboboxWidgetsPage::OnButtonReset)
164 EVT_BUTTON(ComboPage_Change, ComboboxWidgetsPage::OnButtonChange)
165 EVT_BUTTON(ComboPage_Delete, ComboboxWidgetsPage::OnButtonDelete)
166 EVT_BUTTON(ComboPage_DeleteSel, ComboboxWidgetsPage::OnButtonDeleteSel)
167 EVT_BUTTON(ComboPage_Clear, ComboboxWidgetsPage::OnButtonClear)
168 EVT_BUTTON(ComboPage_Insert, ComboboxWidgetsPage::OnButtonInsert)
169 EVT_BUTTON(ComboPage_Add, ComboboxWidgetsPage::OnButtonAdd)
170 EVT_BUTTON(ComboPage_AddSeveral, ComboboxWidgetsPage::OnButtonAddSeveral)
171 EVT_BUTTON(ComboPage_AddMany, ComboboxWidgetsPage::OnButtonAddMany)
172 EVT_BUTTON(ComboPage_SetCurrent, ComboboxWidgetsPage::OnButtonSetCurrent)
173
174 EVT_TEXT_ENTER(ComboPage_InsertText, ComboboxWidgetsPage::OnButtonInsert)
175 EVT_TEXT_ENTER(ComboPage_AddText, ComboboxWidgetsPage::OnButtonAdd)
176 EVT_TEXT_ENTER(ComboPage_DeleteText, ComboboxWidgetsPage::OnButtonDelete)
177
178 EVT_UPDATE_UI(ComboPage_InsertionPointText, ComboboxWidgetsPage::OnUpdateUIInsertionPointText)
179
180 EVT_UPDATE_UI(ComboPage_Reset, ComboboxWidgetsPage::OnUpdateUIResetButton)
181 EVT_UPDATE_UI(ComboPage_Insert, ComboboxWidgetsPage::OnUpdateUIInsert)
182 EVT_UPDATE_UI(ComboPage_AddSeveral, ComboboxWidgetsPage::OnUpdateUIAddSeveral)
183 EVT_UPDATE_UI(ComboPage_Clear, ComboboxWidgetsPage::OnUpdateUIClearButton)
184 EVT_UPDATE_UI(ComboPage_DeleteText, ComboboxWidgetsPage::OnUpdateUIClearButton)
185 EVT_UPDATE_UI(ComboPage_Delete, ComboboxWidgetsPage::OnUpdateUIDeleteButton)
186 EVT_UPDATE_UI(ComboPage_Change, ComboboxWidgetsPage::OnUpdateUIDeleteSelButton)
187 EVT_UPDATE_UI(ComboPage_ChangeText, ComboboxWidgetsPage::OnUpdateUIDeleteSelButton)
188 EVT_UPDATE_UI(ComboPage_DeleteSel, ComboboxWidgetsPage::OnUpdateUIDeleteSelButton)
189 EVT_UPDATE_UI(ComboPage_SetCurrent, ComboboxWidgetsPage::OnUpdateUISetCurrent)
190
191 EVT_COMBOBOX(ComboPage_Combo, ComboboxWidgetsPage::OnComboBox)
192 EVT_TEXT(ComboPage_Combo, ComboboxWidgetsPage::OnComboText)
193 EVT_TEXT_ENTER(ComboPage_Combo, ComboboxWidgetsPage::OnComboText)
194
195 EVT_CHECKBOX(wxID_ANY, ComboboxWidgetsPage::OnCheckOrRadioBox)
196 EVT_RADIOBOX(wxID_ANY, ComboboxWidgetsPage::OnCheckOrRadioBox)
197 END_EVENT_TABLE()
198
199 // ============================================================================
200 // implementation
201 // ============================================================================
202
203 #if defined(__WXUNIVERSAL__)
204 #define FAMILY_CTRLS UNIVERSAL_CTRLS
205 #else
206 #define FAMILY_CTRLS NATIVE_CTRLS
207 #endif
208
209 IMPLEMENT_WIDGETS_PAGE(ComboboxWidgetsPage, _T("Combobox"),
210 FAMILY_CTRLS | WITH_ITEMS_CTRLS | COMBO_CTRLS
211 );
212
213 ComboboxWidgetsPage::ComboboxWidgetsPage(WidgetsBookCtrl *book,
214 wxImageList *imaglist)
215 : WidgetsPage(book, imaglist, combobox_xpm)
216 {
217 // init everything
218 m_chkSort =
219 m_chkReadonly =
220 m_chkFilename = (wxCheckBox *)NULL;
221
222 m_combobox = (wxComboBox *)NULL;
223 m_sizerCombo = (wxSizer *)NULL;
224 }
225
226 void ComboboxWidgetsPage::CreateContent()
227 {
228 /*
229 What we create here is a frame having 3 panes: style pane is the
230 leftmost one, in the middle the pane with buttons allowing to perform
231 miscellaneous combobox operations and the pane containing the combobox
232 itself to the right
233 */
234 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
235
236 // left pane
237 wxStaticBox *box = new wxStaticBox(this, wxID_ANY, _T("&Set style"));
238
239 // should be in sync with ComboKind_XXX values
240 static const wxString kinds[] =
241 {
242 _T("default"),
243 _T("simple"),
244 _T("drop down"),
245 };
246
247 m_radioKind = new wxRadioBox(this, wxID_ANY, _T("Combobox &kind:"),
248 wxDefaultPosition, wxDefaultSize,
249 WXSIZEOF(kinds), kinds,
250 1, wxRA_SPECIFY_COLS);
251
252 wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
253
254 m_chkSort = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Sort items"));
255 m_chkReadonly = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Read only"));
256 m_chkFilename = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&File name"));
257 m_chkFilename->Disable(); // not implemented yet
258
259 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
260 sizerLeft->Add(m_radioKind, 0, wxGROW | wxALL, 5);
261
262 wxButton *btn = new wxButton(this, ComboPage_Reset, _T("&Reset"));
263 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
264
265 // middle pane
266 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY,
267 _T("&Change combobox contents"));
268 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
269
270 wxSizer *sizerRow;
271
272 sizerRow = CreateSizerWithTextAndButton(ComboPage_SetCurrent,
273 _T("Current &selection"),
274 ComboPage_CurText,
275 &m_textCur);
276
277 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
278
279 wxTextCtrl *text;
280 sizerRow = CreateSizerWithTextAndLabel(_T("Insertion Point"),
281 ComboPage_InsertionPointText,
282 &text);
283 text->SetEditable(false);
284
285 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
286
287 sizerRow = CreateSizerWithTextAndButton(ComboPage_Insert,
288 _T("&Insert this string"),
289 ComboPage_InsertText,
290 &m_textInsert);
291 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
292
293 sizerRow = CreateSizerWithTextAndButton(ComboPage_Add,
294 _T("&Add this string"),
295 ComboPage_AddText,
296 &m_textAdd);
297 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
298
299 btn = new wxButton(this, ComboPage_AddSeveral, _T("&Append a few strings"));
300 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
301
302 btn = new wxButton(this, ComboPage_AddMany, _T("Append &many strings"));
303 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
304
305 sizerRow = CreateSizerWithTextAndButton(ComboPage_Change,
306 _T("C&hange current"),
307 ComboPage_ChangeText,
308 &m_textChange);
309 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
310
311 sizerRow = CreateSizerWithTextAndButton(ComboPage_Delete,
312 _T("&Delete this item"),
313 ComboPage_DeleteText,
314 &m_textDelete);
315 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
316
317 btn = new wxButton(this, ComboPage_DeleteSel, _T("Delete &selection"));
318 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
319
320 btn = new wxButton(this, ComboPage_Clear, _T("&Clear"));
321 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
322
323 // right pane
324 wxSizer *sizerRight = new wxBoxSizer(wxVERTICAL);
325 m_combobox = new wxComboBox(this, ComboPage_Combo, wxEmptyString,
326 wxDefaultPosition, wxDefaultSize,
327 0, NULL,
328 0);
329 sizerRight->Add(m_combobox, 0, wxGROW | wxALL, 5);
330 sizerRight->SetMinSize(150, 0);
331 m_sizerCombo = sizerRight; // save it to modify it later
332
333 // the 3 panes panes compose the window
334 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
335 sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
336 sizerTop->Add(sizerRight, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
337
338 // final initializations
339 Reset();
340
341 SetSizer(sizerTop);
342 }
343
344 // ----------------------------------------------------------------------------
345 // operations
346 // ----------------------------------------------------------------------------
347
348 void ComboboxWidgetsPage::Reset()
349 {
350 m_chkSort->SetValue(false);
351 m_chkReadonly->SetValue(false);
352 m_chkFilename->SetValue(false);
353 }
354
355 void ComboboxWidgetsPage::CreateCombo()
356 {
357 int flags = ms_defaultFlags;
358
359 if ( m_chkSort->GetValue() )
360 flags |= wxCB_SORT;
361 if ( m_chkReadonly->GetValue() )
362 flags |= wxCB_READONLY;
363
364 switch ( m_radioKind->GetSelection() )
365 {
366 default:
367 wxFAIL_MSG( _T("unknown combo kind") );
368 // fall through
369
370 case ComboKind_Default:
371 break;
372
373 case ComboKind_Simple:
374 flags |= wxCB_SIMPLE;
375 break;
376
377 case ComboKind_DropDown:
378 flags = wxCB_DROPDOWN;
379 break;
380 }
381
382 wxArrayString items;
383 if ( m_combobox )
384 {
385 unsigned int count = m_combobox->GetCount();
386 for ( unsigned int n = 0; n < count; n++ )
387 {
388 items.Add(m_combobox->GetString(n));
389 }
390
391 m_sizerCombo->Detach( m_combobox );
392 delete m_combobox;
393 }
394
395 m_combobox = new wxComboBox(this, ComboPage_Combo, wxEmptyString,
396 wxDefaultPosition, wxDefaultSize,
397 0, NULL,
398 flags);
399
400 #if 0
401 if ( m_chkFilename->GetValue() )
402 ;
403 #endif // TODO
404
405 unsigned int count = items.GetCount();
406 for ( unsigned int n = 0; n < count; n++ )
407 {
408 m_combobox->Append(items[n]);
409 }
410
411 m_sizerCombo->Add(m_combobox, 1, wxGROW | wxALL, 5);
412 m_sizerCombo->Layout();
413 }
414
415 // ----------------------------------------------------------------------------
416 // event handlers
417 // ----------------------------------------------------------------------------
418
419 void ComboboxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
420 {
421 Reset();
422
423 CreateCombo();
424 }
425
426 void ComboboxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
427 {
428 int sel = m_combobox->GetSelection();
429 if ( sel != wxNOT_FOUND )
430 {
431 #ifndef __WXGTK__
432 m_combobox->SetString(sel, m_textChange->GetValue());
433 #else
434 wxLogMessage(_T("Not implemented in wxGTK"));
435 #endif
436 }
437 }
438
439 void ComboboxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
440 {
441 unsigned long n;
442 if ( !m_textDelete->GetValue().ToULong(&n) ||
443 (n >= m_combobox->GetCount()) )
444 {
445 return;
446 }
447
448 m_combobox->Delete(n);
449 }
450
451 void ComboboxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
452 {
453 int sel = m_combobox->GetSelection();
454 if ( sel != wxNOT_FOUND )
455 {
456 m_combobox->Delete(sel);
457 }
458 }
459
460 void ComboboxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
461 {
462 m_combobox->Clear();
463 }
464
465 void ComboboxWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
466 {
467 static unsigned int s_item = 0;
468
469 wxString s = m_textInsert->GetValue();
470 if ( !m_textInsert->IsModified() )
471 {
472 // update the default string
473 m_textInsert->SetValue(wxString::Format(_T("test item %u"), ++s_item));
474 }
475
476 if (m_combobox->GetSelection() >= 0)
477 m_combobox->Insert(s, m_combobox->GetSelection());
478 }
479
480 void ComboboxWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
481 {
482 static unsigned int s_item = 0;
483
484 wxString s = m_textAdd->GetValue();
485 if ( !m_textAdd->IsModified() )
486 {
487 // update the default string
488 m_textAdd->SetValue(wxString::Format(_T("test item %u"), ++s_item));
489 }
490
491 m_combobox->Append(s);
492 }
493
494 void ComboboxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
495 {
496 // "many" means 1000 here
497 for ( unsigned int n = 0; n < 1000; n++ )
498 {
499 m_combobox->Append(wxString::Format(_T("item #%u"), n));
500 }
501 }
502
503 void ComboboxWidgetsPage::OnButtonSetCurrent(wxCommandEvent& WXUNUSED(event))
504 {
505 long n;
506 if ( !m_textCur->GetValue().ToLong(&n) )
507 return;
508
509 m_combobox->SetSelection(n);
510 }
511
512 void ComboboxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
513 {
514 m_combobox->Append(_T("First"));
515 m_combobox->Append(_T("another one"));
516 m_combobox->Append(_T("and the last (very very very very very very very very very very long) one"));
517 }
518
519 void ComboboxWidgetsPage::OnUpdateUIInsertionPointText(wxUpdateUIEvent& event)
520 {
521 if (m_combobox)
522 event.SetText( wxString::Format(_T("%ld"), m_combobox->GetInsertionPoint()) );
523 }
524
525 void ComboboxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
526 {
527 event.Enable( m_chkSort->GetValue() ||
528 m_chkReadonly->GetValue() ||
529 m_chkFilename->GetValue() );
530 }
531
532 void ComboboxWidgetsPage::OnUpdateUIInsert(wxUpdateUIEvent& event)
533 {
534 if (m_combobox)
535 {
536 bool enable = !(m_combobox->GetWindowStyle() & wxCB_SORT) &&
537 (m_combobox->GetSelection() >= 0);
538
539 event.Enable(enable);
540 }
541 }
542
543 void ComboboxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
544 {
545 if (m_combobox)
546 {
547 unsigned long n;
548 event.Enable(m_textDelete->GetValue().ToULong(&n) &&
549 (n < (unsigned)m_combobox->GetCount()));
550 }
551 }
552
553 void ComboboxWidgetsPage::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event)
554 {
555 if (m_combobox)
556 event.Enable(m_combobox->GetSelection() != wxNOT_FOUND);
557 }
558
559 void ComboboxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
560 {
561 if (m_combobox)
562 event.Enable(m_combobox->GetCount() != 0);
563 }
564
565 void ComboboxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
566 {
567 if (m_combobox)
568 event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
569 }
570
571 void ComboboxWidgetsPage::OnUpdateUISetCurrent(wxUpdateUIEvent& event)
572 {
573 long n;
574 event.Enable( m_textCur->GetValue().ToLong(&n) &&
575 (n == wxNOT_FOUND ||
576 (n >= 0 && (unsigned)n < m_combobox->GetCount())) );
577 }
578
579 void ComboboxWidgetsPage::OnComboText(wxCommandEvent& event)
580 {
581 if (!m_combobox)
582 return;
583
584 wxString s = event.GetString();
585
586 wxASSERT_MSG( s == m_combobox->GetValue(),
587 _T("event and combobox values should be the same") );
588
589 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
590 wxLogMessage(_T("Combobox enter pressed (now '%s')"), s.c_str());
591 else
592 wxLogMessage(_T("Combobox text changed (now '%s')"), s.c_str());
593 }
594
595 void ComboboxWidgetsPage::OnComboBox(wxCommandEvent& event)
596 {
597 long sel = event.GetInt();
598 const wxString selstr = wxString::Format(_T("%ld"), sel);
599 m_textDelete->SetValue(selstr);
600 m_textCur->SetValue(selstr);
601
602 wxLogMessage(_T("Combobox item %ld selected"), sel);
603
604 wxLogMessage(_T("Combobox GetValue(): %s"), m_combobox->GetValue().c_str() );
605 }
606
607 void ComboboxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
608 {
609 CreateCombo();
610 }
611
612 #endif //wxUSE_COMBOBOX
613
614 #endif