]> git.saurik.com Git - wxWidgets.git/blob - samples/widgets/combobox.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[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 sizerTop->Fit(this);
340 }
341
342 // ----------------------------------------------------------------------------
343 // operations
344 // ----------------------------------------------------------------------------
345
346 void ComboboxWidgetsPage::Reset()
347 {
348 m_chkSort->SetValue(false);
349 m_chkReadonly->SetValue(false);
350 m_chkFilename->SetValue(false);
351 }
352
353 void ComboboxWidgetsPage::CreateCombo()
354 {
355 int flags = ms_defaultFlags;
356
357 if ( m_chkSort->GetValue() )
358 flags |= wxCB_SORT;
359 if ( m_chkReadonly->GetValue() )
360 flags |= wxCB_READONLY;
361
362 switch ( m_radioKind->GetSelection() )
363 {
364 default:
365 wxFAIL_MSG( _T("unknown combo kind") );
366 // fall through
367
368 case ComboKind_Default:
369 break;
370
371 case ComboKind_Simple:
372 flags |= wxCB_SIMPLE;
373 break;
374
375 case ComboKind_DropDown:
376 flags = wxCB_DROPDOWN;
377 break;
378 }
379
380 wxArrayString items;
381 if ( m_combobox )
382 {
383 unsigned int count = m_combobox->GetCount();
384 for ( unsigned int n = 0; n < count; n++ )
385 {
386 items.Add(m_combobox->GetString(n));
387 }
388
389 m_sizerCombo->Detach( m_combobox );
390 delete m_combobox;
391 }
392
393 m_combobox = new wxComboBox(this, ComboPage_Combo, wxEmptyString,
394 wxDefaultPosition, wxDefaultSize,
395 0, NULL,
396 flags);
397
398 #if 0
399 if ( m_chkFilename->GetValue() )
400 ;
401 #endif // TODO
402
403 unsigned int count = items.GetCount();
404 for ( unsigned int n = 0; n < count; n++ )
405 {
406 m_combobox->Append(items[n]);
407 }
408
409 m_sizerCombo->Add(m_combobox, 1, wxGROW | wxALL, 5);
410 m_sizerCombo->Layout();
411 }
412
413 // ----------------------------------------------------------------------------
414 // event handlers
415 // ----------------------------------------------------------------------------
416
417 void ComboboxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
418 {
419 Reset();
420
421 CreateCombo();
422 }
423
424 void ComboboxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
425 {
426 int sel = m_combobox->GetSelection();
427 if ( sel != wxNOT_FOUND )
428 {
429 #ifndef __WXGTK__
430 m_combobox->SetString(sel, m_textChange->GetValue());
431 #else
432 wxLogMessage(_T("Not implemented in wxGTK"));
433 #endif
434 }
435 }
436
437 void ComboboxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
438 {
439 unsigned long n;
440 if ( !m_textDelete->GetValue().ToULong(&n) ||
441 (n >= m_combobox->GetCount()) )
442 {
443 return;
444 }
445
446 m_combobox->Delete(n);
447 }
448
449 void ComboboxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
450 {
451 int sel = m_combobox->GetSelection();
452 if ( sel != wxNOT_FOUND )
453 {
454 m_combobox->Delete(sel);
455 }
456 }
457
458 void ComboboxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
459 {
460 m_combobox->Clear();
461 }
462
463 void ComboboxWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
464 {
465 static unsigned int s_item = 0;
466
467 wxString s = m_textInsert->GetValue();
468 if ( !m_textInsert->IsModified() )
469 {
470 // update the default string
471 m_textInsert->SetValue(wxString::Format(_T("test item %u"), ++s_item));
472 }
473
474 if (m_combobox->GetSelection() >= 0)
475 m_combobox->Insert(s, m_combobox->GetSelection());
476 }
477
478 void ComboboxWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
479 {
480 static unsigned int s_item = 0;
481
482 wxString s = m_textAdd->GetValue();
483 if ( !m_textAdd->IsModified() )
484 {
485 // update the default string
486 m_textAdd->SetValue(wxString::Format(_T("test item %u"), ++s_item));
487 }
488
489 m_combobox->Append(s);
490 }
491
492 void ComboboxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
493 {
494 // "many" means 1000 here
495 for ( unsigned int n = 0; n < 1000; n++ )
496 {
497 m_combobox->Append(wxString::Format(_T("item #%u"), n));
498 }
499 }
500
501 void ComboboxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
502 {
503 m_combobox->Append(_T("First"));
504 m_combobox->Append(_T("another one"));
505 m_combobox->Append(_T("and the last (very very very very very very very very very very long) one"));
506 }
507
508 void ComboboxWidgetsPage::OnUpdateUICurText(wxUpdateUIEvent& event)
509 {
510 if (m_combobox)
511 event.SetText( wxString::Format(_T("%d"), m_combobox->GetSelection()) );
512 }
513
514 void ComboboxWidgetsPage::OnUpdateUIInsertionPointText(wxUpdateUIEvent& event)
515 {
516 if (m_combobox)
517 event.SetText( wxString::Format(_T("%ld"), m_combobox->GetInsertionPoint()) );
518 }
519
520 void ComboboxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
521 {
522 event.Enable( m_chkSort->GetValue() ||
523 m_chkReadonly->GetValue() ||
524 m_chkFilename->GetValue() );
525 }
526
527 void ComboboxWidgetsPage::OnUpdateUIInsert(wxUpdateUIEvent& event)
528 {
529 if (m_combobox)
530 {
531 bool enable = !(m_combobox->GetWindowStyle() & wxCB_SORT) &&
532 (m_combobox->GetSelection() >= 0);
533
534 event.Enable(enable);
535 }
536 }
537
538 void ComboboxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
539 {
540 if (m_combobox)
541 {
542 unsigned long n;
543 event.Enable(m_textDelete->GetValue().ToULong(&n) &&
544 (n < (unsigned)m_combobox->GetCount()));
545 }
546 }
547
548 void ComboboxWidgetsPage::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event)
549 {
550 if (m_combobox)
551 event.Enable(m_combobox->GetSelection() != wxNOT_FOUND);
552 }
553
554 void ComboboxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
555 {
556 if (m_combobox)
557 event.Enable(m_combobox->GetCount() != 0);
558 }
559
560 void ComboboxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
561 {
562 if (m_combobox)
563 event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
564 }
565
566 void ComboboxWidgetsPage::OnComboText(wxCommandEvent& event)
567 {
568 if (!m_combobox)
569 return;
570
571 wxString s = event.GetString();
572
573 wxASSERT_MSG( s == m_combobox->GetValue(),
574 _T("event and combobox values should be the same") );
575
576 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
577 wxLogMessage(_T("Combobox enter pressed (now '%s')"), s.c_str());
578 else
579 wxLogMessage(_T("Combobox text changed (now '%s')"), s.c_str());
580 }
581
582 void ComboboxWidgetsPage::OnComboBox(wxCommandEvent& event)
583 {
584 long sel = event.GetInt();
585 m_textDelete->SetValue(wxString::Format(_T("%ld"), sel));
586
587 wxLogMessage(_T("Combobox item %ld selected"), sel);
588
589 wxLogMessage(_T("Combobox GetValue(): %s"), m_combobox->GetValue().c_str() );
590 }
591
592 void ComboboxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
593 {
594 CreateCombo();
595 }
596
597 #endif //wxUSE_COMBOBOX
598
599 #endif