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