]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/controls/controls.cpp
Change a Popup menu from using a callback to using events. Can't test
[wxWidgets.git] / samples / controls / controls.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: controls.cpp
3// Purpose: Controls wxWindows sample
4// Author: Robert Roebling
5// Modified by:
6// RCS-ID: $Id$
7// Copyright: (c) Robert Roebling, Julian Smart
8// Licence: wxWindows license
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12 #pragma implementation "controls.h"
13#endif
14
15// For compilers that support precompilation, includes "wx/wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19 #pragma hdrstop
20#endif
21
22#ifndef WX_PRECOMP
23 #include "wx/wx.h"
24#endif
25
26#if !defined( __WXMSW__ ) || defined( __WIN95__ )
27#include "wx/spinbutt.h"
28#endif
29#include "wx/notebook.h"
30#include "wx/imaglist.h"
31
32#if wxUSE_TOOLTIPS
33 #include "wx/tooltip.h"
34#endif
35
36#if defined(__WXGTK__) || defined(__WXMOTIF__)
37 #define USE_XPM
38#endif
39
40#ifdef USE_XPM
41 #include "mondrian.xpm"
42 #include "icons/choice.xpm"
43 #include "icons/combo.xpm"
44 #include "icons/list.xpm"
45 #include "icons/radio.xpm"
46 #include "icons/text.xpm"
47 #include "icons/gauge.xpm"
48#endif
49
50#ifdef __WIN16__
51 // Win16 doesn't have them
52 #undef wxUSE_SPINBUTTON
53 #define wxUSE_SPINBUTTON 0
54#else
55 #if !defined(wxUSE_SPINBUTTON)
56 #define wxUSE_SPINBUTTON 1
57 #endif
58#endif // __WIN16__
59
60#include "wx/progdlg.h"
61
62// VZ: this is a temp. hack, will remove soon
63#define wxUSE_SPINCTRL 1
64
65#if wxUSE_SPINCTRL
66 #include "wx/spinctrl.h"
67#endif // wxUSE_SPINCTRL
68
69//----------------------------------------------------------------------
70// class definitions
71//----------------------------------------------------------------------
72
73class MyApp: public wxApp
74{
75public:
76 bool OnInit();
77};
78
79class MyPanel: public wxPanel
80{
81public:
82 MyPanel(wxFrame *frame, int x, int y, int w, int h);
83 virtual ~MyPanel();
84
85 void OnSize( wxSizeEvent& event );
86 void OnListBox( wxCommandEvent &event );
87 void OnListBoxDoubleClick( wxCommandEvent &event );
88 void OnListBoxButtons( wxCommandEvent &event );
89 void OnChoice( wxCommandEvent &event );
90 void OnChoiceButtons( wxCommandEvent &event );
91 void OnCombo( wxCommandEvent &event );
92 void OnComboButtons( wxCommandEvent &event );
93 void OnRadio( wxCommandEvent &event );
94 void OnRadioButtons( wxCommandEvent &event );
95 void OnSetFont( wxCommandEvent &event );
96 void OnPageChanged( wxNotebookEvent &event );
97 void OnPageChanging( wxNotebookEvent &event );
98 void OnSliderUpdate( wxCommandEvent &event );
99 void OnUpdateLabel( wxCommandEvent &event );
100#if wxUSE_SPINBUTTON
101 void OnSpinUp( wxSpinEvent &event );
102 void OnSpinDown( wxSpinEvent &event );
103 void OnSpinUpdate( wxSpinEvent &event );
104 void OnUpdateShowProgress( wxUpdateUIEvent& event );
105 void OnShowProgress( wxCommandEvent &event );
106#endif // wxUSE_SPINBUTTON
107
108#if wxUSE_SPINCTRL
109 void OnSpinCtrl(wxSpinEvent& event);
110#endif // wxUSE_SPINCTRL
111
112 void OnEnableAll(wxCommandEvent& event);
113 void OnChangeColour(wxCommandEvent& event);
114
115 wxListBox *m_listbox,
116 *m_listboxSorted;
117 wxChoice *m_choice,
118 *m_choiceSorted;
119 wxComboBox *m_combo;
120 wxRadioBox *m_radio;
121 wxGauge *m_gauge;
122 wxSlider *m_slider;
123 wxButton *m_fontButton;
124 wxButton *m_lbSelectNum;
125 wxButton *m_lbSelectThis;
126#if wxUSE_SPINBUTTON
127 wxSpinButton *m_spinbutton;
128 wxButton *m_btnProgress;
129#endif // wxUSE_SPINBUTTON
130
131#if wxUSE_SPINCTRL
132 wxSpinCtrl *m_spinctrl;
133#endif // wxUSE_SPINCTRL
134
135 wxTextCtrl *m_spintext;
136 wxCheckBox *m_checkbox;
137
138 wxTextCtrl *m_text;
139 wxNotebook *m_notebook;
140
141 wxStaticText *m_label;
142
143private:
144 DECLARE_EVENT_TABLE()
145};
146
147class MyFrame: public wxFrame
148{
149public:
150 MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
151
152 void OnQuit(wxCommandEvent& event);
153 void OnAbout(wxCommandEvent& event);
154
155#if wxUSE_TOOLTIPS
156 void OnSetTooltipDelay(wxCommandEvent& event);
157 void OnToggleTooltips(wxCommandEvent& event);
158#endif // wxUSE_TOOLTIPS
159
160 void OnEnableAll(wxCommandEvent& event);
161
162 void OnIdle( wxIdleEvent& event );
163 void OnSize( wxSizeEvent& event );
164
165private:
166 wxPanel *m_panel;
167
168 DECLARE_EVENT_TABLE()
169};
170
171//----------------------------------------------------------------------
172// other
173//----------------------------------------------------------------------
174
175static void SetControlClientData(const char *name,
176 wxControlWithItems *control);
177
178IMPLEMENT_APP(MyApp)
179
180//----------------------------------------------------------------------
181// MyApp
182//----------------------------------------------------------------------
183
184enum
185{
186 MINIMAL_QUIT = 100,
187 MINIMAL_TEXT,
188 MINIMAL_ABOUT,
189
190 // tooltip menu
191 MINIMAL_SET_TOOLTIP_DELAY = 200,
192 MINIMAL_ENABLE_TOOLTIPS,
193
194 // panel menu
195 MINIMAL_ENABLE_ALL
196};
197
198bool MyApp::OnInit()
199{
200 // Create the main frame window
201 MyFrame *frame = new MyFrame((wxFrame *) NULL,
202 "Controls wxWindows App",
203 50, 50, 530, 420);
204
205 // Give it an icon
206 // The wxICON() macros loads an icon from a resource under Windows
207 // and uses an #included XPM image under GTK+ and Motif
208
209 frame->SetIcon( wxICON(mondrian) );
210
211 wxMenu *file_menu = new wxMenu("", wxMENU_TEAROFF );
212 file_menu->Append(MINIMAL_ABOUT, "&About\tF1");
213 file_menu->AppendSeparator();
214 file_menu->Append(MINIMAL_QUIT, "E&xit\tAlt-X", "Quit controls sample");
215
216 wxMenuBar *menu_bar = new wxMenuBar;
217 menu_bar->Append(file_menu, "&File");
218
219#if wxUSE_TOOLTIPS
220 wxMenu *tooltip_menu = new wxMenu;
221 tooltip_menu->Append(MINIMAL_SET_TOOLTIP_DELAY, "Set &delay\tCtrl-D");
222 tooltip_menu->AppendSeparator();
223 tooltip_menu->Append(MINIMAL_ENABLE_TOOLTIPS, "&Toggle tooltips\tCtrl-T",
224 "enable/disable tooltips", TRUE);
225 tooltip_menu->Check(MINIMAL_ENABLE_TOOLTIPS, TRUE);
226 menu_bar->Append(tooltip_menu, "&Tooltips");
227#endif // wxUSE_TOOLTIPS
228
229 wxMenu *panel_menu = new wxMenu;
230 panel_menu->Append(MINIMAL_ENABLE_ALL, "&Disable all\tCtrl-E",
231 "Enable/disable all panel controls", TRUE);
232 menu_bar->Append(panel_menu, "&Panel");
233
234 frame->SetMenuBar(menu_bar);
235
236 frame->Show(TRUE);
237 frame->SetCursor(wxCursor(wxCURSOR_HAND));
238
239 SetTopWindow(frame);
240
241 return TRUE;
242}
243
244//----------------------------------------------------------------------
245// MyPanel
246//----------------------------------------------------------------------
247
248const int ID_NOTEBOOK = 1000;
249
250const int ID_LISTBOX = 130;
251const int ID_LISTBOX_SEL_NUM = 131;
252const int ID_LISTBOX_SEL_STR = 132;
253const int ID_LISTBOX_CLEAR = 133;
254const int ID_LISTBOX_APPEND = 134;
255const int ID_LISTBOX_DELETE = 135;
256const int ID_LISTBOX_FONT = 136;
257const int ID_LISTBOX_ENABLE = 137;
258const int ID_LISTBOX_SORTED = 138;
259
260const int ID_CHOICE = 120;
261const int ID_CHOICE_SEL_NUM = 121;
262const int ID_CHOICE_SEL_STR = 122;
263const int ID_CHOICE_CLEAR = 123;
264const int ID_CHOICE_APPEND = 124;
265const int ID_CHOICE_DELETE = 125;
266const int ID_CHOICE_FONT = 126;
267const int ID_CHOICE_ENABLE = 127;
268const int ID_CHOICE_SORTED = 128;
269
270const int ID_COMBO = 140;
271const int ID_COMBO_SEL_NUM = 141;
272const int ID_COMBO_SEL_STR = 142;
273const int ID_COMBO_CLEAR = 143;
274const int ID_COMBO_APPEND = 144;
275const int ID_COMBO_DELETE = 145;
276const int ID_COMBO_FONT = 146;
277const int ID_COMBO_ENABLE = 147;
278
279const int ID_RADIOBOX = 160;
280const int ID_RADIOBOX_SEL_NUM = 161;
281const int ID_RADIOBOX_SEL_STR = 162;
282const int ID_RADIOBOX_FONT = 163;
283const int ID_RADIOBOX_ENABLE = 164;
284
285const int ID_RADIOBUTTON_1 = 166;
286const int ID_RADIOBUTTON_2 = 167;
287
288const int ID_SET_FONT = 170;
289
290const int ID_GAUGE = 180;
291const int ID_SLIDER = 181;
292
293const int ID_SPIN = 182;
294const int ID_BTNPROGRESS = 183;
295const int ID_BUTTON_LABEL = 184;
296const int ID_SPINCTRL = 185;
297
298const int ID_CHANGE_COLOUR = 200;
299
300BEGIN_EVENT_TABLE(MyPanel, wxPanel)
301EVT_SIZE ( MyPanel::OnSize)
302EVT_NOTEBOOK_PAGE_CHANGING(ID_NOTEBOOK, MyPanel::OnPageChanging)
303EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, MyPanel::OnPageChanged)
304EVT_LISTBOX (ID_LISTBOX, MyPanel::OnListBox)
305EVT_LISTBOX (ID_LISTBOX_SORTED, MyPanel::OnListBox)
306EVT_LISTBOX_DCLICK(ID_LISTBOX, MyPanel::OnListBoxDoubleClick)
307EVT_BUTTON (ID_LISTBOX_SEL_NUM, MyPanel::OnListBoxButtons)
308EVT_BUTTON (ID_LISTBOX_SEL_STR, MyPanel::OnListBoxButtons)
309EVT_BUTTON (ID_LISTBOX_CLEAR, MyPanel::OnListBoxButtons)
310EVT_BUTTON (ID_LISTBOX_APPEND, MyPanel::OnListBoxButtons)
311EVT_BUTTON (ID_LISTBOX_DELETE, MyPanel::OnListBoxButtons)
312EVT_BUTTON (ID_LISTBOX_FONT, MyPanel::OnListBoxButtons)
313EVT_CHECKBOX (ID_LISTBOX_ENABLE, MyPanel::OnListBoxButtons)
314EVT_CHOICE (ID_CHOICE, MyPanel::OnChoice)
315EVT_CHOICE (ID_CHOICE_SORTED, MyPanel::OnChoice)
316EVT_BUTTON (ID_CHOICE_SEL_NUM, MyPanel::OnChoiceButtons)
317EVT_BUTTON (ID_CHOICE_SEL_STR, MyPanel::OnChoiceButtons)
318EVT_BUTTON (ID_CHOICE_CLEAR, MyPanel::OnChoiceButtons)
319EVT_BUTTON (ID_CHOICE_APPEND, MyPanel::OnChoiceButtons)
320EVT_BUTTON (ID_CHOICE_DELETE, MyPanel::OnChoiceButtons)
321EVT_BUTTON (ID_CHOICE_FONT, MyPanel::OnChoiceButtons)
322EVT_CHECKBOX (ID_CHOICE_ENABLE, MyPanel::OnChoiceButtons)
323EVT_COMBOBOX (ID_COMBO, MyPanel::OnCombo)
324EVT_BUTTON (ID_COMBO_SEL_NUM, MyPanel::OnComboButtons)
325EVT_BUTTON (ID_COMBO_SEL_STR, MyPanel::OnComboButtons)
326EVT_BUTTON (ID_COMBO_CLEAR, MyPanel::OnComboButtons)
327EVT_BUTTON (ID_COMBO_APPEND, MyPanel::OnComboButtons)
328EVT_BUTTON (ID_COMBO_DELETE, MyPanel::OnComboButtons)
329EVT_BUTTON (ID_COMBO_FONT, MyPanel::OnComboButtons)
330EVT_CHECKBOX (ID_COMBO_ENABLE, MyPanel::OnComboButtons)
331EVT_RADIOBOX (ID_RADIOBOX, MyPanel::OnRadio)
332EVT_BUTTON (ID_RADIOBOX_SEL_NUM, MyPanel::OnRadioButtons)
333EVT_BUTTON (ID_RADIOBOX_SEL_STR, MyPanel::OnRadioButtons)
334EVT_BUTTON (ID_RADIOBOX_FONT, MyPanel::OnRadioButtons)
335EVT_CHECKBOX (ID_RADIOBOX_ENABLE, MyPanel::OnRadioButtons)
336EVT_BUTTON (ID_SET_FONT, MyPanel::OnSetFont)
337EVT_SLIDER (ID_SLIDER, MyPanel::OnSliderUpdate)
338#if wxUSE_SPINBUTTON
339EVT_SPIN (ID_SPIN, MyPanel::OnSpinUpdate)
340EVT_SPIN_UP (ID_SPIN, MyPanel::OnSpinUp)
341EVT_SPIN_DOWN (ID_SPIN, MyPanel::OnSpinDown)
342EVT_UPDATE_UI (ID_BTNPROGRESS, MyPanel::OnUpdateShowProgress)
343EVT_BUTTON (ID_BTNPROGRESS, MyPanel::OnShowProgress)
344#endif // wxUSE_SPINBUTTON
345#if wxUSE_SPINCTRL
346EVT_SPIN (ID_SPINCTRL, MyPanel::OnSpinCtrl)
347#endif // wxUSE_SPINCTRL
348EVT_BUTTON (ID_BUTTON_LABEL, MyPanel::OnUpdateLabel)
349EVT_CHECKBOX (ID_CHANGE_COLOUR, MyPanel::OnChangeColour)
350END_EVENT_TABLE()
351
352MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
353 : wxPanel( frame, -1, wxPoint(x, y), wxSize(w, h) ),
354 m_text(NULL), m_notebook(NULL)
355{
356 m_text = new wxTextCtrl( this, -1, "This is the log window.\n", wxPoint(0,50), wxSize(100,50), wxTE_MULTILINE );
357 // m_text->SetBackgroundColour("wheat");
358
359 delete wxLog::SetActiveTarget(new wxLogStderr);
360
361 m_notebook = new wxNotebook( this, ID_NOTEBOOK, wxPoint(0,0), wxSize(200,150) );
362
363 wxString choices[] =
364 {
365 "This",
366 "is one of my",
367 "really",
368 "wonderful",
369 "examples."
370 };
371
372#ifdef USE_XPM
373 // image ids
374 enum
375 {
376 Image_List, Image_Choice, Image_Combo, Image_Text, Image_Radio, Image_Gauge, Image_Max
377 };
378
379 // fill the image list
380 wxImageList *imagelist = new wxImageList(32, 32);
381
382 imagelist-> Add( wxBitmap( list_xpm ));
383 imagelist-> Add( wxBitmap( choice_xpm ));
384 imagelist-> Add( wxBitmap( combo_xpm ));
385 imagelist-> Add( wxBitmap( text_xpm ));
386 imagelist-> Add( wxBitmap( radio_xpm ));
387 imagelist-> Add( wxBitmap( gauge_xpm ));
388 m_notebook->SetImageList(imagelist);
389#elif defined(__WXMSW__)
390 // load images from resources
391 enum
392 {
393 Image_List, Image_Choice, Image_Combo, Image_Text, Image_Radio, Image_Gauge, Image_Max
394 };
395 wxImageList *imagelist = new wxImageList(16, 16, FALSE, Image_Max);
396
397 static const char *s_iconNames[Image_Max] =
398 {
399 "list", "choice", "combo", "text", "radio", "gauge"
400 };
401
402 for ( size_t n = 0; n < Image_Max; n++ )
403 {
404 wxBitmap bmp(s_iconNames[n]);
405 if ( !bmp.Ok() || (imagelist->Add(bmp) == -1) )
406 {
407 wxLogWarning("Couldn't load the image '%s' for the notebook page %d.",
408 s_iconNames[n], n);
409 }
410 }
411
412 m_notebook->SetImageList(imagelist);
413#else
414
415 // No images for now
416#define Image_List -1
417#define Image_Choice -1
418#define Image_Combo -1
419#define Image_Text -1
420#define Image_Radio -1
421#define Image_Gauge -1
422#define Image_Max -1
423
424#endif
425
426 wxPanel *panel = new wxPanel(m_notebook);
427 m_listbox = new wxListBox( panel, ID_LISTBOX,
428 wxPoint(10,10), wxSize(120,70),
429 5, choices, wxLB_ALWAYS_SB );
430 m_listboxSorted = new wxListBox( panel, ID_LISTBOX_SORTED,
431 wxPoint(10,90), wxSize(120,70),
432 5, choices, wxLB_SORT );
433
434 SetControlClientData("listbox", m_listbox);
435 SetControlClientData("listbox", m_listboxSorted);
436
437 m_listbox->SetCursor(*wxCROSS_CURSOR);
438#if wxUSE_TOOLTIPS
439 m_listbox->SetToolTip( "This is a list box" );
440#endif // wxUSE_TOOLTIPS
441
442 m_lbSelectNum = new wxButton( panel, ID_LISTBOX_SEL_NUM, "Select #2", wxPoint(180,30), wxSize(140,30) );
443 m_lbSelectThis = new wxButton( panel, ID_LISTBOX_SEL_STR, "Select 'This'", wxPoint(340,30), wxSize(140,30) );
444 (void)new wxButton( panel, ID_LISTBOX_CLEAR, "Clear", wxPoint(180,80), wxSize(140,30) );
445 (void)new wxButton( panel, ID_LISTBOX_APPEND, "Append 'Hi!'", wxPoint(340,80), wxSize(140,30) );
446 (void)new wxButton( panel, ID_LISTBOX_DELETE, "Delete selected item", wxPoint(180,130), wxSize(140,30) );
447 wxButton *button = new wxButton( panel, ID_LISTBOX_FONT, "Set &Italic font", wxPoint(340,130), wxSize(140,30) );
448#if wxUSE_TOOLTIPS
449 button->SetToolTip( "Press here to set italic font" );
450#endif // wxUSE_TOOLTIPS
451
452 m_checkbox = new wxCheckBox( panel, ID_LISTBOX_ENABLE, "&Disable", wxPoint(20,170) );
453 m_checkbox->SetValue(FALSE);
454#if wxUSE_TOOLTIPS
455 m_checkbox->SetToolTip( "Click here to disable the listbox" );
456#endif // wxUSE_TOOLTIPS
457 (void)new wxCheckBox( panel, ID_CHANGE_COLOUR, "&Toggle colour",
458 wxPoint(110,170) );
459 m_notebook->AddPage(panel, "wxListBox", TRUE, Image_List);
460
461 panel = new wxPanel(m_notebook);
462 m_choice = new wxChoice( panel, ID_CHOICE, wxPoint(10,10), wxSize(120,-1), 5, choices );
463 m_choiceSorted = new wxChoice( panel, ID_CHOICE_SORTED, wxPoint(10,70), wxSize(120,-1),
464 5, choices, wxCB_SORT );
465
466 SetControlClientData("choice", m_choice);
467 SetControlClientData("choice", m_choiceSorted);
468
469 m_choice->SetSelection(2);
470 m_choice->SetBackgroundColour( "red" );
471 (void)new wxButton( panel, ID_CHOICE_SEL_NUM, "Select #2", wxPoint(180,30), wxSize(140,30) );
472 (void)new wxButton( panel, ID_CHOICE_SEL_STR, "Select 'This'", wxPoint(340,30), wxSize(140,30) );
473 (void)new wxButton( panel, ID_CHOICE_CLEAR, "Clear", wxPoint(180,80), wxSize(140,30) );
474 (void)new wxButton( panel, ID_CHOICE_APPEND, "Append 'Hi!'", wxPoint(340,80), wxSize(140,30) );
475 (void)new wxButton( panel, ID_CHOICE_DELETE, "Delete selected item", wxPoint(180,130), wxSize(140,30) );
476 (void)new wxButton( panel, ID_CHOICE_FONT, "Set Italic font", wxPoint(340,130), wxSize(140,30) );
477 (void)new wxCheckBox( panel, ID_CHOICE_ENABLE, "Disable", wxPoint(20,130), wxSize(140,30) );
478
479 m_notebook->AddPage(panel, "wxChoice", FALSE, Image_Choice);
480
481 panel = new wxPanel(m_notebook);
482 m_combo = new wxComboBox( panel, ID_COMBO, "This", wxPoint(10,10), wxSize(120,-1), 5, choices, wxCB_READONLY );
483 (void)new wxButton( panel, ID_COMBO_SEL_NUM, "Select #2", wxPoint(180,30), wxSize(140,30) );
484 (void)new wxButton( panel, ID_COMBO_SEL_STR, "Select 'This'", wxPoint(340,30), wxSize(140,30) );
485 (void)new wxButton( panel, ID_COMBO_CLEAR, "Clear", wxPoint(180,80), wxSize(140,30) );
486 (void)new wxButton( panel, ID_COMBO_APPEND, "Append 'Hi!'", wxPoint(340,80), wxSize(140,30) );
487 (void)new wxButton( panel, ID_COMBO_DELETE, "Delete selected item", wxPoint(180,130), wxSize(140,30) );
488 (void)new wxButton( panel, ID_COMBO_FONT, "Set Italic font", wxPoint(340,130), wxSize(140,30) );
489 (void)new wxCheckBox( panel, ID_COMBO_ENABLE, "Disable", wxPoint(20,130), wxSize(140,30) );
490 m_notebook->AddPage(panel, "wxComboBox", FALSE, Image_Combo);
491
492 wxString choices2[] =
493 {
494 "First", "Second",
495 /* "Third",
496 "Fourth", "Fifth", "Sixth",
497 "Seventh", "Eighth", "Nineth", "Tenth" */
498 };
499
500 panel = new wxPanel(m_notebook);
501 (void)new wxRadioBox( panel, ID_RADIOBOX, "That", wxPoint(10,160), wxSize(-1,-1), WXSIZEOF(choices2), choices2, 1, wxRA_SPECIFY_ROWS );
502 m_radio = new wxRadioBox( panel, ID_RADIOBOX, "This", wxPoint(10,10), wxSize(-1,-1), WXSIZEOF(choices), choices, 1, wxRA_SPECIFY_COLS );
503 (void)new wxButton( panel, ID_RADIOBOX_SEL_NUM, "Select #2", wxPoint(180,30), wxSize(140,30) );
504 (void)new wxButton( panel, ID_RADIOBOX_SEL_STR, "Select 'This'", wxPoint(180,80), wxSize(140,30) );
505 m_fontButton = new wxButton( panel, ID_SET_FONT, "Set more Italic font", wxPoint(340,30), wxSize(140,30) );
506 (void)new wxButton( panel, ID_RADIOBOX_FONT, "Set Italic font", wxPoint(340,80), wxSize(140,30) );
507 (void)new wxCheckBox( panel, ID_RADIOBOX_ENABLE, "Disable", wxPoint(340,130), wxSize(140,30) );
508 wxRadioButton *rb = new wxRadioButton( panel, ID_RADIOBUTTON_1, "Radiobutton1", wxPoint(210,170), wxSize(110,30), wxRB_GROUP );
509 rb->SetValue( FALSE );
510 (void)new wxRadioButton( panel, ID_RADIOBUTTON_2, "Radiobutton2", wxPoint(340,170), wxSize(110,30) );
511 m_notebook->AddPage(panel, "wxRadioBox", FALSE, Image_Radio);
512
513 panel = new wxPanel(m_notebook);
514 (void)new wxStaticBox( panel, -1, "wxGauge and wxSlider", wxPoint(10,10), wxSize(200,130) );
515 m_gauge = new wxGauge( panel, -1, 200, wxPoint(18,50), wxSize(155, 30) );
516 m_slider = new wxSlider( panel, ID_SLIDER, 0, 0, 200, wxPoint(18,90), wxSize(155,-1), wxSL_LABELS );
517 (void)new wxStaticBox( panel, -1, "Explanation", wxPoint(220,10), wxSize(270,130) );
518#ifdef __WXMOTIF__
519 // No wrapping text in wxStaticText yet :-(
520 (void)new wxStaticText( panel, -1,
521 "Drag the slider!",
522 wxPoint(228,30),
523 wxSize(240, -1)
524 );
525#else
526 (void)new wxStaticText( panel, -1,
527 "In order see the gauge (aka progress bar)\n"
528 "control do something you have to drag the\n"
529 "handle of the slider to the right.\n"
530 "\n"
531 "This is also supposed to demonstrate how\n"
532 "to use static controls.\n",
533 wxPoint(228,25),
534 wxSize(240, 110)
535 );
536#endif
537 int initialSpinValue = -5;
538 wxString s;
539 s << initialSpinValue;
540 m_spintext = new wxTextCtrl( panel, -1, s, wxPoint(20,160), wxSize(80,-1) );
541#if wxUSE_SPINBUTTON
542 m_spinbutton = new wxSpinButton( panel, ID_SPIN, wxPoint(103,160), wxSize(80, -1) );
543 m_spinbutton->SetRange(-10,30);
544 m_spinbutton->SetValue(initialSpinValue);
545
546 m_btnProgress = new wxButton( panel, ID_BTNPROGRESS, "Show progress dialog",
547 wxPoint(300, 160) );
548#endif // wxUSE_SPINBUTTON
549
550#if wxUSE_SPINCTRL
551 m_spinctrl = new wxSpinCtrl( panel, ID_SPINCTRL, "", wxPoint(200, 160), wxSize(80, -1) );
552 m_spinctrl->SetRange(10,30);
553 m_spinctrl->SetValue(15);
554#endif // wxUSE_SPINCTRL
555
556 m_notebook->AddPage(panel, "wxGauge", FALSE, Image_Gauge);
557
558 panel = new wxPanel(m_notebook);
559
560#ifndef __WXMOTIF__ // wxStaticBitmap not working under Motif yet. MB
561 wxIcon icon = wxTheApp->GetStdIcon(wxICON_INFORMATION);
562 wxStaticBitmap *bmpStatic = new wxStaticBitmap(panel, -1, icon, wxPoint(10, 10));
563
564 bmpStatic = new wxStaticBitmap(panel, -1, wxNullIcon, wxPoint(50, 10));
565 bmpStatic->SetIcon(wxTheApp->GetStdIcon(wxICON_QUESTION));
566#endif // !Motif
567
568 wxBitmap bitmap( 100, 100 );
569 wxMemoryDC dc;
570 dc.SelectObject( bitmap );
571 dc.SetPen(*wxGREEN_PEN);
572 dc.DrawEllipse(5, 5, 90, 90);
573 dc.DrawText("Bitmap", 20, 20);
574 dc.SelectObject( wxNullBitmap );
575
576 (void)new wxBitmapButton(panel, -1, bitmap, wxPoint(100, 20));
577 (void)new wxButton(panel, ID_BUTTON_LABEL, "Toggle label", wxPoint(250, 20));
578 m_label = new wxStaticText(panel, -1, "Label with some long text",
579 wxPoint(250, 60), wxDefaultSize,
580 wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
581
582 m_notebook->AddPage(panel, "wxBitmapXXX");
583
584// --------------- TEST CODE ----------------------
585
586 // layout constraints
587
588 panel = new wxPanel(m_notebook);
589 panel->SetAutoLayout( TRUE );
590
591 wxLayoutConstraints *c;
592 c = new wxLayoutConstraints;
593 c->top.SameAs( panel, wxTop, 10 );
594 c->height.AsIs( );
595 c->left.SameAs( panel, wxLeft, 10 );
596 c->width.PercentOf( panel, wxWidth, 40 );
597
598 wxButton *pMyButton = new wxButton(panel, -1, "Test Button" );
599 pMyButton->SetConstraints( c );
600
601 c = new wxLayoutConstraints;
602 c->top.SameAs( panel, wxTop, 10 );
603 c->bottom.SameAs( panel, wxBottom, 10 );
604 c->right.SameAs( panel, wxRight, 10 );
605 c->width.PercentOf( panel, wxWidth, 40 );
606
607 wxButton *pMyButton2 = new wxButton(panel, -1, "Test Button 2" );
608 pMyButton2->SetConstraints( c );
609
610 m_notebook->AddPage(panel, "wxLayoutConstraint");
611
612 // sizer
613
614 panel = new wxPanel(m_notebook);
615 panel->SetAutoLayout( TRUE );
616
617 wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
618
619 sizer->Add( new wxButton(panel, -1, "Test Button" ), 3, wxALL, 10 );
620 sizer->Add( 20,20, 1 );
621 sizer->Add( new wxButton(panel, -1, "Test Button 2" ), 3, wxGROW|wxALL, 10 );
622
623 panel->SetSizer( sizer );
624
625 m_notebook->AddPage(panel, "wxSizer");
626
627// --------------- TEST CODE ----------------------
628
629}
630
631void MyPanel::OnSize( wxSizeEvent& WXUNUSED(event) )
632{
633 int x = 0;
634 int y = 0;
635 GetClientSize( &x, &y );
636
637 if (m_notebook) m_notebook->SetSize( 2, 2, x-4, y*2/3-4 );
638 if (m_text) m_text->SetSize( 2, y*2/3+2, x-4, y/3-4 );
639}
640
641void MyPanel::OnPageChanging( wxNotebookEvent &event )
642{
643 int selOld = event.GetOldSelection();
644 if ( selOld == 2 )
645 {
646 if ( wxMessageBox("This demonstrates how a program may prevent the\n"
647 "page change from taking place - if you select\n"
648 "[No] the current page will stay the third one\n",
649 "Control sample",
650 wxICON_QUESTION | wxYES_NO) != wxYES )
651 {
652 event.Veto();
653
654 return;
655 }
656 }
657
658 *m_text << "Notebook selection is being changed from " << selOld << "\n";
659}
660
661void MyPanel::OnPageChanged( wxNotebookEvent &event )
662{
663 *m_text << "Notebook selection is " << event.GetSelection() << "\n";
664}
665
666void MyPanel::OnChangeColour(wxCommandEvent& WXUNUSED(event))
667{
668 static wxColour s_colOld;
669
670 // test panel colour changing and propagation to the subcontrols
671 if ( s_colOld.Ok() )
672 {
673 SetBackgroundColour(s_colOld);
674 s_colOld = wxNullColour;
675
676 m_lbSelectThis->SetBackgroundColour("blue");
677 }
678 else
679 {
680 s_colOld = GetBackgroundColour();
681 SetBackgroundColour("green");
682
683 m_lbSelectThis->SetBackgroundColour("red");
684 }
685
686 m_lbSelectThis->Refresh();
687 Refresh();
688}
689
690void MyPanel::OnListBox( wxCommandEvent &event )
691{
692 wxListBox *listbox = event.GetId() == ID_LISTBOX ? m_listbox
693 : m_listboxSorted;
694
695 m_text->AppendText( "ListBox event selection string is: '" );
696 m_text->AppendText( event.GetString() );
697 m_text->AppendText( "'\n" );
698 m_text->AppendText( "ListBox control selection string is: '" );
699 m_text->AppendText( listbox->GetStringSelection() );
700 m_text->AppendText( "'\n" );
701
702 wxStringClientData *obj = ((wxStringClientData *)event.GetClientObject());
703 m_text->AppendText( "ListBox event client data string is: '" );
704 m_text->AppendText( obj ? obj->GetData() : wxString("none"));
705 m_text->AppendText( "'\n" );
706 m_text->AppendText( "ListBox control client data string is: '" );
707 obj = (wxStringClientData *)listbox->GetClientObject(listbox->GetSelection());
708 m_text->AppendText( obj ? obj->GetData() : wxString("none"));
709 m_text->AppendText( "'\n" );
710}
711
712void MyPanel::OnListBoxDoubleClick( wxCommandEvent &event )
713{
714 m_text->AppendText( "ListBox double click string is: " );
715 m_text->AppendText( event.GetString() );
716 m_text->AppendText( "\n" );
717}
718
719void MyPanel::OnListBoxButtons( wxCommandEvent &event )
720{
721 switch (event.GetId())
722 {
723 case ID_LISTBOX_ENABLE:
724 {
725 m_text->AppendText("Checkbox clicked.\n");
726 wxCheckBox *cb = (wxCheckBox*)event.GetEventObject();
727#if wxUSE_TOOLTIPS
728 if (event.GetInt())
729 cb->SetToolTip( "Click to enable listbox" );
730 else
731 cb->SetToolTip( "Click to disable listbox" );
732#endif // wxUSE_TOOLTIPS
733 m_listbox->Enable( event.GetInt() == 0 );
734 m_listboxSorted->Enable( event.GetInt() == 0 );
735 break;
736 }
737 case ID_LISTBOX_SEL_NUM:
738 {
739 m_listbox->SetSelection( 2 );
740 m_listboxSorted->SetSelection( 2 );
741 m_lbSelectThis->WarpPointer( 40, 14 );
742 break;
743 }
744 case ID_LISTBOX_SEL_STR:
745 {
746 m_listbox->SetStringSelection( "This" );
747 m_listboxSorted->SetStringSelection( "This" );
748 m_lbSelectNum->WarpPointer( 40, 14 );
749 break;
750 }
751 case ID_LISTBOX_CLEAR:
752 {
753 m_listbox->Clear();
754 m_listboxSorted->Clear();
755 break;
756 }
757 case ID_LISTBOX_APPEND:
758 {
759 m_listbox->Append( "Hi!" );
760 m_listboxSorted->Append( "Hi!" );
761 break;
762 }
763 case ID_LISTBOX_DELETE:
764 {
765 int idx;
766 idx = m_listbox->GetSelection();
767 m_listbox->Delete( idx );
768 idx = m_listboxSorted->GetSelection();
769 m_listboxSorted->Delete( idx );
770 break;
771 }
772 case ID_LISTBOX_FONT:
773 {
774 m_listbox->SetFont( *wxITALIC_FONT );
775 m_listboxSorted->SetFont( *wxITALIC_FONT );
776 m_checkbox->SetFont( *wxITALIC_FONT );
777 break;
778 }
779 }
780}
781
782void MyPanel::OnChoice( wxCommandEvent &event )
783{
784 wxChoice *choice = event.GetId() == ID_CHOICE ? m_choice
785 : m_choiceSorted;
786
787 m_text->AppendText( "Choice event selection string is: '" );
788 m_text->AppendText( event.GetString() );
789 m_text->AppendText( "'\n" );
790 m_text->AppendText( "Choice control selection string is: '" );
791 m_text->AppendText( choice->GetStringSelection() );
792 m_text->AppendText( "'\n" );
793
794 wxStringClientData *obj = ((wxStringClientData *)event.GetClientObject());
795 m_text->AppendText( "Choice event client data string is: '" );
796 m_text->AppendText( obj ? obj->GetData() : wxString("none"));
797 m_text->AppendText( "'\n" );
798 m_text->AppendText( "Choice control client data string is: '" );
799 obj = (wxStringClientData *)choice->GetClientObject(choice->GetSelection());
800 m_text->AppendText( obj ? obj->GetData() : wxString("none"));
801 m_text->AppendText( "'\n" );
802}
803
804void MyPanel::OnChoiceButtons( wxCommandEvent &event )
805{
806 switch (event.GetId())
807 {
808 case ID_CHOICE_ENABLE:
809 {
810 m_choice->Enable( event.GetInt() == 0 );
811 m_choiceSorted->Enable( event.GetInt() == 0 );
812 break;
813 }
814 case ID_CHOICE_SEL_NUM:
815 {
816 m_choice->SetSelection( 2 );
817 m_choiceSorted->SetSelection( 2 );
818 break;
819 }
820 case ID_CHOICE_SEL_STR:
821 {
822 m_choice->SetStringSelection( "This" );
823 m_choiceSorted->SetStringSelection( "This" );
824 break;
825 }
826 case ID_CHOICE_CLEAR:
827 {
828 m_choice->Clear();
829 m_choiceSorted->Clear();
830 break;
831 }
832 case ID_CHOICE_APPEND:
833 {
834 m_choice->Append( "Hi!" );
835 m_choiceSorted->Append( "Hi!" );
836 break;
837 }
838 case ID_CHOICE_DELETE:
839 {
840 int idx = m_choice->GetSelection();
841 m_choice->Delete( idx );
842 idx = m_choiceSorted->GetSelection();
843 m_choiceSorted->Delete( idx );
844 break;
845 }
846 case ID_CHOICE_FONT:
847 {
848 m_choice->SetFont( *wxITALIC_FONT );
849 m_choiceSorted->SetFont( *wxITALIC_FONT );
850 break;
851 }
852 }
853}
854
855void MyPanel::OnCombo( wxCommandEvent &event )
856{
857 m_text->AppendText( "ComboBox event selection string is: " );
858 m_text->AppendText( event.GetString() );
859 m_text->AppendText( "\n" );
860 m_text->AppendText( "ComboBox control selection string is: " );
861 m_text->AppendText( m_combo->GetStringSelection() );
862 m_text->AppendText( "\n" );
863}
864
865void MyPanel::OnComboButtons( wxCommandEvent &event )
866{
867 switch (event.GetId())
868 {
869 case ID_COMBO_ENABLE:
870 {
871 m_combo->Enable( event.GetInt() == 0 );
872 break;
873 }
874 case ID_COMBO_SEL_NUM:
875 {
876 m_combo->SetSelection( 2 );
877 break;
878 }
879 case ID_COMBO_SEL_STR:
880 {
881 m_combo->SetStringSelection( "This" );
882 break;
883 }
884 case ID_COMBO_CLEAR:
885 {
886 m_combo->Clear();
887 break;
888 }
889 case ID_COMBO_APPEND:
890 {
891 m_combo->Append( "Hi!" );
892 break;
893 }
894 case ID_COMBO_DELETE:
895 {
896 int idx = m_combo->GetSelection();
897 m_combo->Delete( idx );
898 break;
899 }
900 case ID_COMBO_FONT:
901 {
902 m_combo->SetFont( *wxITALIC_FONT );
903 break;
904 }
905 }
906}
907
908void MyPanel::OnRadio( wxCommandEvent &event )
909{
910 m_text->AppendText( "RadioBox selection string is: " );
911 m_text->AppendText( event.GetString() );
912 m_text->AppendText( "\n" );
913}
914
915void MyPanel::OnRadioButtons( wxCommandEvent &event )
916{
917 switch (event.GetId())
918 {
919 case ID_RADIOBOX_ENABLE:
920 {
921 m_radio->Enable( event.GetInt() == 0 );
922 break;
923 }
924 case ID_RADIOBOX_SEL_NUM:
925 {
926 m_radio->SetSelection( 2 );
927 break;
928 }
929 case ID_RADIOBOX_SEL_STR:
930 {
931 m_radio->SetStringSelection( "This" );
932 break;
933 }
934 case ID_RADIOBOX_FONT:
935 {
936 m_radio->SetFont( *wxITALIC_FONT );
937 break;
938 }
939 }
940}
941
942void MyPanel::OnSetFont( wxCommandEvent &WXUNUSED(event) )
943{
944 m_fontButton->SetFont( *wxITALIC_FONT );
945 m_text->SetFont( *wxITALIC_FONT );
946}
947
948void MyPanel::OnUpdateLabel( wxCommandEvent &WXUNUSED(event) )
949{
950 static bool s_long = TRUE;
951
952 s_long = !s_long;
953 m_label->SetLabel(s_long ? "very very very long text" : "shorter text");
954}
955
956void MyPanel::OnSliderUpdate( wxCommandEvent &WXUNUSED(event) )
957{
958 m_gauge->SetValue( m_slider->GetValue() );
959}
960
961#if wxUSE_SPINCTRL
962
963void MyPanel::OnSpinCtrl(wxSpinEvent& event)
964{
965 wxString s;
966 s.Printf(_T("Current value of spin ctrl is %d\n"), m_spinctrl->GetValue());
967 m_text->AppendText(s);
968}
969
970#endif // wxUSE_SPINCTRL
971
972#if wxUSE_SPINBUTTON
973void MyPanel::OnSpinUp( wxSpinEvent &event )
974{
975 wxString value;
976 value.Printf( _T("Spin control up: current = %d\n"),
977 m_spinbutton->GetValue());
978
979 if ( m_spinbutton->GetValue() > 17 )
980 {
981 value += _T("Preventing the spin button from going above 17.\n");
982
983 event.Veto();
984 }
985
986 m_text->AppendText(value);
987}
988
989void MyPanel::OnSpinDown( wxSpinEvent &event )
990{
991 wxString value;
992 value.Printf( _T("Spin control down: current = %d\n"),
993 m_spinbutton->GetValue());
994
995 if ( m_spinbutton->GetValue() < -17 )
996 {
997 value += _T("Preventing the spin button from going below -17.\n");
998
999 event.Veto();
1000 }
1001
1002 m_text->AppendText(value);
1003}
1004
1005void MyPanel::OnSpinUpdate( wxSpinEvent &event )
1006{
1007 wxString value;
1008 value.Printf( _T("%d"), event.GetPosition() );
1009 m_spintext->SetValue( value );
1010
1011 value.Printf( _T("Spin control range: (%d, %d), current = %d\n"),
1012 m_spinbutton->GetMin(), m_spinbutton->GetMax(),
1013 m_spinbutton->GetValue());
1014
1015 m_text->AppendText(value);
1016}
1017
1018void MyPanel::OnUpdateShowProgress( wxUpdateUIEvent& event )
1019{
1020 event.Enable( m_spinbutton->GetValue() > 0 );
1021}
1022
1023void MyPanel::OnShowProgress( wxCommandEvent& WXUNUSED(event) )
1024{
1025 int max = m_spinbutton->GetValue();
1026 wxProgressDialog dialog("Progress dialog example",
1027 "An informative message",
1028 max, // range
1029 this, // parent
1030 wxPD_CAN_ABORT |
1031 wxPD_APP_MODAL |
1032 wxPD_ELAPSED_TIME |
1033 wxPD_ESTIMATED_TIME |
1034 wxPD_REMAINING_TIME);
1035
1036
1037 bool cont = TRUE;
1038 for ( int i = 0; i < max && cont; i++ )
1039 {
1040 wxSleep(1);
1041 if ( i == max - 1 )
1042 {
1043 cont = dialog.Update(i, "That's all, folks!");
1044 }
1045 else if ( i == max / 2 )
1046 {
1047 cont = dialog.Update(i, "Only a half left!");
1048 }
1049 else
1050 {
1051 cont = dialog.Update(i);
1052 }
1053 }
1054
1055 if ( !cont )
1056 {
1057 *m_text << "Progress dialog aborted!\n";
1058 }
1059 else
1060 {
1061 *m_text << "Countdown from " << max << " finished.\n";
1062 }
1063}
1064
1065#endif // wxUSE_SPINBUTTON
1066
1067MyPanel::~MyPanel()
1068{
1069 delete m_notebook->GetImageList();
1070}
1071
1072//----------------------------------------------------------------------
1073// MyFrame
1074//----------------------------------------------------------------------
1075
1076BEGIN_EVENT_TABLE(MyFrame, wxFrame)
1077 EVT_MENU(MINIMAL_QUIT, MyFrame::OnQuit)
1078 EVT_MENU(MINIMAL_ABOUT, MyFrame::OnAbout)
1079#if wxUSE_TOOLTIPS
1080 EVT_MENU(MINIMAL_SET_TOOLTIP_DELAY, MyFrame::OnSetTooltipDelay)
1081 EVT_MENU(MINIMAL_ENABLE_TOOLTIPS, MyFrame::OnToggleTooltips)
1082#endif // wxUSE_TOOLTIPS
1083
1084 EVT_MENU(MINIMAL_ENABLE_ALL, MyFrame::OnEnableAll)
1085
1086 EVT_SIZE(MyFrame::OnSize)
1087 EVT_IDLE(MyFrame::OnIdle)
1088END_EVENT_TABLE()
1089
1090MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
1091: wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h))
1092{
1093 CreateStatusBar(2);
1094
1095 m_panel = new MyPanel( this, 10, 10, 300, 100 );
1096}
1097
1098void MyFrame::OnQuit (wxCommandEvent& WXUNUSED(event) )
1099{
1100 Close(TRUE);
1101}
1102
1103void MyFrame::OnAbout( wxCommandEvent& WXUNUSED(event) )
1104{
1105 wxBeginBusyCursor();
1106
1107 wxMessageDialog dialog(this, "This is a control sample", "About Controls", wxOK );
1108 dialog.ShowModal();
1109
1110 wxEndBusyCursor();
1111}
1112
1113#if wxUSE_TOOLTIPS
1114void MyFrame::OnSetTooltipDelay(wxCommandEvent& event)
1115{
1116 static long s_delay = 5000;
1117
1118 wxString delay;
1119 delay.Printf( _T("%ld"), s_delay);
1120
1121 delay = wxGetTextFromUser("Enter delay (in milliseconds)",
1122 "Set tooltip delay",
1123 delay,
1124 this);
1125 if ( !delay )
1126 return; // cancelled
1127
1128 wxSscanf(delay, _T("%ld"), &s_delay);
1129
1130 wxToolTip::SetDelay(s_delay);
1131
1132 wxLogStatus(this, _T("Tooltip delay set to %ld milliseconds"), s_delay);
1133}
1134
1135void MyFrame::OnToggleTooltips(wxCommandEvent& event)
1136{
1137 static bool s_enabled = TRUE;
1138
1139 s_enabled = !s_enabled;
1140
1141 wxToolTip::Enable(s_enabled);
1142
1143 wxLogStatus(this, _T("Tooltips %sabled"), s_enabled ? _T("en") : _T("dis") );
1144}
1145#endif // tooltips
1146
1147void MyFrame::OnEnableAll(wxCommandEvent& WXUNUSED(event))
1148{
1149 static bool s_enable = TRUE;
1150
1151 s_enable = !s_enable;
1152 m_panel->Enable(s_enable);
1153}
1154
1155void MyFrame::OnSize( wxSizeEvent& event )
1156{
1157 wxString msg;
1158 msg.Printf( _("%dx%d"), event.GetSize().x, event.GetSize().y);
1159 SetStatusText(msg, 1);
1160
1161 event.Skip();
1162}
1163
1164void MyFrame::OnIdle( wxIdleEvent& WXUNUSED(event) )
1165{
1166 // track the window which has the focus in the status bar
1167 static wxWindow *s_windowFocus = (wxWindow *)NULL;
1168 wxWindow *focus = wxWindow::FindFocus();
1169 if ( focus && (focus != s_windowFocus) )
1170 {
1171 s_windowFocus = focus;
1172
1173 wxString msg;
1174 msg.Printf(
1175#ifdef __WXMSW__
1176 _T("Focus: wxWindow = %p, HWND = %08x"),
1177#else
1178 _T("Focus: wxWindow = %p"),
1179#endif
1180 s_windowFocus
1181#ifdef __WXMSW__
1182 , s_windowFocus->GetHWND()
1183#endif
1184 );
1185
1186 SetStatusText(msg);
1187 }
1188}
1189
1190static void SetControlClientData(const char *name,
1191 wxControlWithItems *control)
1192{
1193 size_t count = control->GetCount();
1194 for ( size_t n = 0; n < count; n++ )
1195 {
1196 wxString s;
1197 s.Printf("%s client data for '%s'",
1198 name, control->GetString(n).c_str());
1199
1200 control->SetClientObject(n, new wxStringClientData(s));
1201 }
1202}