added tests for setting fg/bg colours
[wxWidgets.git] / samples / widgets / slider.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: slider.cpp
4 // Purpose: Part of the widgets sample showing wxSlider
5 // Author: Vadim Zeitlin
6 // Created: 16.04.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 // for all others, include the necessary headers
28 #ifndef WX_PRECOMP
29 #include "wx/log.h"
30
31 #include "wx/bitmap.h"
32 #include "wx/button.h"
33 #include "wx/checkbox.h"
34 #include "wx/radiobox.h"
35 #include "wx/slider.h"
36 #include "wx/statbox.h"
37 #include "wx/textctrl.h"
38 #endif
39
40 #if wxUSE_TOOLTIPS
41 #include "wx/tooltip.h"
42 #endif
43
44 #include "wx/sizer.h"
45
46 #include "widgets.h"
47 #if wxUSE_SLIDER
48 #include "icons/slider.xpm"
49
50 // ----------------------------------------------------------------------------
51 // constants
52 // ----------------------------------------------------------------------------
53
54 // control ids
55 enum
56 {
57 SliderPage_Reset = wxID_HIGHEST,
58 SliderPage_Clear,
59 SliderPage_SetValue,
60 SliderPage_SetMinAndMax,
61 SliderPage_SetTickFreq,
62 SliderPage_SetThumbLen,
63 SliderPage_CurValueText,
64 SliderPage_ValueText,
65 SliderPage_MinText,
66 SliderPage_MaxText,
67 SliderPage_TickFreqText,
68 SliderPage_ThumbLenText,
69 SliderPage_RadioSides,
70 SliderPage_BothSides,
71 SliderPage_Slider
72 };
73
74 // sides radiobox values
75 enum
76 {
77 StaticSides_Top,
78 StaticSides_Bottom,
79 StaticSides_Left,
80 StaticSides_Right
81 };
82
83 // ----------------------------------------------------------------------------
84 // SliderWidgetsPage
85 // ----------------------------------------------------------------------------
86
87 class SliderWidgetsPage : public WidgetsPage
88 {
89 public:
90 SliderWidgetsPage(wxNotebook *notebook, wxImageList *imaglist);
91 virtual ~SliderWidgetsPage(){};
92
93 virtual wxControl *GetWidget() const { return m_slider; }
94
95 protected:
96 // event handlers
97 void OnButtonReset(wxCommandEvent& event);
98 void OnButtonClear(wxCommandEvent& event);
99 void OnButtonSetValue(wxCommandEvent& event);
100 void OnButtonSetMinAndMax(wxCommandEvent& event);
101 void OnButtonSetTickFreq(wxCommandEvent& event);
102 void OnButtonSetThumbLen(wxCommandEvent& event);
103
104 void OnCheckOrRadioBox(wxCommandEvent& event);
105
106 void OnSlider(wxScrollEvent& event);
107
108 void OnUpdateUIValueButton(wxUpdateUIEvent& event);
109 void OnUpdateUIMinMaxButton(wxUpdateUIEvent& event);
110 void OnUpdateUITickFreq(wxUpdateUIEvent& event);
111 void OnUpdateUIThumbLen(wxUpdateUIEvent& event);
112 void OnUpdateUIRadioSides(wxUpdateUIEvent& event);
113 void OnUpdateUIBothSides(wxUpdateUIEvent& event);
114
115 void OnUpdateUIResetButton(wxUpdateUIEvent& event);
116
117 void OnUpdateUICurValueText(wxUpdateUIEvent& event);
118
119 // reset the slider parameters
120 void Reset();
121
122 // (re)create the slider
123 void CreateSlider();
124
125 // set the tick frequency from the text field value
126 void DoSetTickFreq();
127
128 // set the thumb len from the text field value
129 void DoSetThumbLen();
130
131 // is this slider value in range?
132 bool IsValidValue(int val) const
133 { return (val >= m_min) && (val <= m_max); }
134
135 // the slider range
136 int m_min, m_max;
137
138 // the controls
139 // ------------
140
141 // the check/radio boxes for styles
142 wxCheckBox *m_chkLabels,
143 *m_chkVert,
144 *m_chkTicks,
145 *m_chkBothSides;
146
147 wxRadioBox *m_radioSides;
148
149 // the slider itself and the sizer it is in
150 wxSlider *m_slider;
151 wxSizer *m_sizerSlider;
152
153 // the text entries for set value/range
154 wxTextCtrl *m_textValue,
155 *m_textMin,
156 *m_textMax,
157 *m_textTickFreq,
158 *m_textThumbLen;
159
160 private:
161 DECLARE_EVENT_TABLE()
162 DECLARE_WIDGETS_PAGE(SliderWidgetsPage)
163 };
164
165 // ----------------------------------------------------------------------------
166 // event tables
167 // ----------------------------------------------------------------------------
168
169 BEGIN_EVENT_TABLE(SliderWidgetsPage, WidgetsPage)
170 EVT_BUTTON(SliderPage_Reset, SliderWidgetsPage::OnButtonReset)
171 EVT_BUTTON(SliderPage_SetValue, SliderWidgetsPage::OnButtonSetValue)
172 EVT_BUTTON(SliderPage_SetMinAndMax, SliderWidgetsPage::OnButtonSetMinAndMax)
173 EVT_BUTTON(SliderPage_SetTickFreq, SliderWidgetsPage::OnButtonSetTickFreq)
174 EVT_BUTTON(SliderPage_SetThumbLen, SliderWidgetsPage::OnButtonSetThumbLen)
175
176 EVT_UPDATE_UI(SliderPage_SetValue, SliderWidgetsPage::OnUpdateUIValueButton)
177 EVT_UPDATE_UI(SliderPage_SetMinAndMax, SliderWidgetsPage::OnUpdateUIMinMaxButton)
178 EVT_UPDATE_UI(SliderPage_SetTickFreq, SliderWidgetsPage::OnUpdateUITickFreq)
179 EVT_UPDATE_UI(SliderPage_SetThumbLen, SliderWidgetsPage::OnUpdateUIThumbLen)
180 EVT_UPDATE_UI(SliderPage_TickFreqText, SliderWidgetsPage::OnUpdateUITickFreq)
181 EVT_UPDATE_UI(SliderPage_RadioSides, SliderWidgetsPage::OnUpdateUIRadioSides)
182 EVT_UPDATE_UI(SliderPage_BothSides, SliderWidgetsPage::OnUpdateUIBothSides)
183
184 EVT_UPDATE_UI(SliderPage_Reset, SliderWidgetsPage::OnUpdateUIResetButton)
185
186 EVT_UPDATE_UI(SliderPage_CurValueText, SliderWidgetsPage::OnUpdateUICurValueText)
187
188 EVT_COMMAND_SCROLL(SliderPage_Slider, SliderWidgetsPage::OnSlider)
189
190 EVT_CHECKBOX(wxID_ANY, SliderWidgetsPage::OnCheckOrRadioBox)
191 EVT_RADIOBOX(wxID_ANY, SliderWidgetsPage::OnCheckOrRadioBox)
192 END_EVENT_TABLE()
193
194 // ============================================================================
195 // implementation
196 // ============================================================================
197
198 IMPLEMENT_WIDGETS_PAGE(SliderWidgetsPage, _T("Slider"));
199
200 SliderWidgetsPage::SliderWidgetsPage(wxNotebook *notebook,
201 wxImageList *imaglist)
202 : WidgetsPage(notebook)
203 {
204 imaglist->Add(wxBitmap(slider_xpm));
205
206 // init everything
207 m_min = 0;
208 m_max = 100;
209
210 m_chkVert =
211 m_chkTicks =
212 m_chkLabels =
213 m_chkBothSides = (wxCheckBox *)NULL;
214
215 m_radioSides = (wxRadioBox *)NULL;
216
217 m_slider = (wxSlider *)NULL;
218 m_sizerSlider = (wxSizer *)NULL;
219
220 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
221
222 // left pane
223 wxStaticBox *box = new wxStaticBox(this, wxID_ANY, _T("&Set style"));
224 wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
225
226 m_chkVert = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Vertical"));
227 m_chkTicks = CreateCheckBoxAndAddToSizer(sizerLeft, _T("Show &ticks"));
228 m_chkLabels = CreateCheckBoxAndAddToSizer(sizerLeft, _T("Show &labels"));
229 static const wxString sides[] =
230 {
231 _T("top"),
232 _T("bottom"),
233 _T("left"),
234 _T("right"),
235 };
236 m_radioSides = new wxRadioBox(this, SliderPage_RadioSides, _T("&Ticks/Labels"),
237 wxDefaultPosition, wxDefaultSize,
238 WXSIZEOF(sides), sides,
239 1, wxRA_SPECIFY_COLS);
240 sizerLeft->Add(m_radioSides, 0, wxGROW | wxALL, 5);
241 m_chkBothSides = CreateCheckBoxAndAddToSizer
242 (sizerLeft, _T("&Both sides"), SliderPage_BothSides);
243 #if wxUSE_TOOLTIPS
244 m_chkBothSides->SetToolTip( _T("\"Both sides\" is only supported \nin Win95 and Universal") );
245 #endif // wxUSE_TOOLTIPS
246
247 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
248
249 wxButton *btn = new wxButton(this, SliderPage_Reset, _T("&Reset"));
250 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
251
252 // middle pane
253 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, _T("&Change slider value"));
254 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
255
256 wxTextCtrl *text;
257 wxSizer *sizerRow = CreateSizerWithTextAndLabel(_T("Current value"),
258 SliderPage_CurValueText,
259 &text);
260 text->SetEditable(false);
261
262 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
263
264 sizerRow = CreateSizerWithTextAndButton(SliderPage_SetValue,
265 _T("Set &value"),
266 SliderPage_ValueText,
267 &m_textValue);
268 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
269
270 sizerRow = CreateSizerWithTextAndButton(SliderPage_SetMinAndMax,
271 _T("&Min and max"),
272 SliderPage_MinText,
273 &m_textMin);
274
275 m_textMax = new wxTextCtrl(this, SliderPage_MaxText, wxEmptyString);
276 sizerRow->Add(m_textMax, 1, wxLEFT | wxALIGN_CENTRE_VERTICAL, 5);
277
278 m_textMin->SetValue( wxString::Format(_T("%d"), m_min) );
279 m_textMax->SetValue( wxString::Format(_T("%d"), m_max) );
280
281 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
282
283 sizerRow = CreateSizerWithTextAndButton(SliderPage_SetTickFreq,
284 _T("Tick &frequency"),
285 SliderPage_TickFreqText,
286 &m_textTickFreq);
287
288 m_textTickFreq->SetValue(_T("10"));
289
290 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
291
292 sizerRow = CreateSizerWithTextAndButton(SliderPage_SetThumbLen,
293 _T("Thumb &length"),
294 SliderPage_ThumbLenText,
295 &m_textThumbLen);
296
297 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
298
299 // right pane
300 wxSizer *sizerRight = new wxBoxSizer(wxHORIZONTAL);
301 sizerRight->SetMinSize(150, 40);
302 m_sizerSlider = sizerRight; // save it to modify it later
303
304 Reset();
305 CreateSlider();
306
307 // the 3 panes panes compose the window
308 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
309 sizerTop->Add(sizerMiddle, 0, wxGROW | wxALL, 10);
310 sizerTop->Add(sizerRight, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
311
312 // final initializations
313 SetSizer(sizerTop);
314
315 sizerTop->Fit(this);
316 }
317
318 // ----------------------------------------------------------------------------
319 // operations
320 // ----------------------------------------------------------------------------
321
322 void SliderWidgetsPage::Reset()
323 {
324 m_chkVert->SetValue(false);
325 m_chkTicks->SetValue(true);
326 m_chkLabels->SetValue(true);
327 m_chkBothSides->SetValue(false);
328
329 m_radioSides->SetSelection(StaticSides_Top);
330 }
331
332 void SliderWidgetsPage::CreateSlider()
333 {
334 int flags = 0;
335
336 bool isVert = m_chkVert->GetValue();
337 if ( isVert )
338 flags |= wxSL_VERTICAL;
339 else
340 flags |= wxSL_HORIZONTAL;
341
342 if ( m_chkLabels->GetValue() )
343 {
344 flags |= wxSL_LABELS;
345 }
346
347 if ( m_chkTicks->GetValue() )
348 {
349 flags |= wxSL_AUTOTICKS;
350 }
351
352 switch ( m_radioSides->GetSelection() )
353 {
354 case StaticSides_Top:
355 flags |= wxSL_TOP;
356 break;
357 case StaticSides_Left:
358 flags |= wxSL_LEFT;
359 break;
360 case StaticSides_Bottom:
361 flags |= wxSL_BOTTOM;
362 break;
363 case StaticSides_Right:
364 flags |= wxSL_RIGHT;
365 break;
366 default:
367 wxFAIL_MSG(_T("unexpected radiobox selection"));
368 // fall through
369 }
370
371 if ( m_chkBothSides->GetValue() )
372 {
373 flags |= wxSL_BOTH;
374 }
375
376 int val = m_min;
377 if ( m_slider )
378 {
379 int valOld = m_slider->GetValue();
380 if ( !IsValidValue(valOld) )
381 {
382 val = valOld;
383 }
384
385 m_sizerSlider->Detach( m_slider );
386
387 if ( m_sizerSlider->GetChildren().GetCount() )
388 {
389 // we have 2 spacers, remove them too
390 m_sizerSlider->Remove( 0 );
391 m_sizerSlider->Remove( 0 );
392 }
393
394 delete m_slider;
395 }
396
397 m_slider = new wxSlider(this, SliderPage_Slider,
398 val, m_min, m_max,
399 wxDefaultPosition, wxDefaultSize,
400 flags);
401
402 if ( isVert )
403 {
404 m_sizerSlider->Add(0, 0, 1);
405 m_sizerSlider->Add(m_slider, 0, wxGROW | wxALL, 5);
406 m_sizerSlider->Add(0, 0, 1);
407 }
408 else
409 {
410 m_sizerSlider->Add(m_slider, 1, wxCENTRE | wxALL, 5);
411 }
412
413 if ( m_chkTicks->GetValue() )
414 {
415 DoSetTickFreq();
416 }
417
418 m_sizerSlider->Layout();
419 }
420
421 void SliderWidgetsPage::DoSetTickFreq()
422 {
423 long freq;
424 if ( !m_textTickFreq->GetValue().ToLong(&freq) )
425 {
426 wxLogWarning(_T("Invalid slider tick frequency"));
427
428 return;
429 }
430
431 m_slider->SetTickFreq(freq, 0 /* unused */);
432 }
433
434 void SliderWidgetsPage::DoSetThumbLen()
435 {
436 long len;
437 if ( !m_textThumbLen->GetValue().ToLong(&len) )
438 {
439 wxLogWarning(_T("Invalid slider thumb length"));
440
441 return;
442 }
443
444 m_slider->SetThumbLength(len);
445 }
446
447 // ----------------------------------------------------------------------------
448 // event handlers
449 // ----------------------------------------------------------------------------
450
451 void SliderWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
452 {
453 Reset();
454
455 CreateSlider();
456 }
457
458 void SliderWidgetsPage::OnButtonSetTickFreq(wxCommandEvent& WXUNUSED(event))
459 {
460 DoSetTickFreq();
461 }
462
463 void SliderWidgetsPage::OnButtonSetThumbLen(wxCommandEvent& WXUNUSED(event))
464 {
465 DoSetThumbLen();
466 }
467
468 void SliderWidgetsPage::OnButtonSetMinAndMax(wxCommandEvent& WXUNUSED(event))
469 {
470 long minNew,
471 maxNew = 0; // init to suppress compiler warning
472 if ( !m_textMin->GetValue().ToLong(&minNew) ||
473 !m_textMax->GetValue().ToLong(&maxNew) ||
474 minNew >= maxNew )
475 {
476 wxLogWarning(_T("Invalid min/max values for the slider."));
477
478 return;
479 }
480
481 m_min = minNew;
482 m_max = maxNew;
483
484 m_slider->SetRange(minNew, maxNew);
485 }
486
487 void SliderWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event))
488 {
489 long val;
490 if ( !m_textValue->GetValue().ToLong(&val) || !IsValidValue(val) )
491 {
492 wxLogWarning(_T("Invalid slider value."));
493
494 return;
495 }
496
497 m_slider->SetValue(val);
498 }
499
500 void SliderWidgetsPage::OnUpdateUIValueButton(wxUpdateUIEvent& event)
501 {
502 long val;
503 event.Enable( m_textValue->GetValue().ToLong(&val) && IsValidValue(val) );
504 }
505
506 void SliderWidgetsPage::OnUpdateUITickFreq(wxUpdateUIEvent& event)
507 {
508 long freq;
509 event.Enable( m_chkTicks->GetValue() &&
510 m_textTickFreq->GetValue().ToLong(&freq) &&
511 (freq > 0) && (freq <= m_max - m_min) );
512 }
513
514 void SliderWidgetsPage::OnUpdateUIThumbLen(wxUpdateUIEvent& event)
515 {
516 long val;
517 event.Enable( m_textThumbLen->GetValue().ToLong(&val));
518 }
519
520 void SliderWidgetsPage::OnUpdateUIMinMaxButton(wxUpdateUIEvent& event)
521 {
522 long mn, mx;
523 event.Enable( m_textMin->GetValue().ToLong(&mn) &&
524 m_textMax->GetValue().ToLong(&mx) &&
525 mn < mx);
526 }
527
528 void SliderWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
529 {
530 event.Enable( m_chkVert->GetValue() ||
531 !m_chkTicks->GetValue() ||
532 !m_chkLabels->GetValue() ||
533 m_chkBothSides->GetValue() );
534 }
535
536 void SliderWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
537 {
538 CreateSlider();
539 }
540
541 void SliderWidgetsPage::OnUpdateUICurValueText(wxUpdateUIEvent& event)
542 {
543 event.SetText( wxString::Format(_T("%d"), m_slider->GetValue()) );
544 }
545
546 void SliderWidgetsPage::OnUpdateUIRadioSides(wxUpdateUIEvent& event)
547 {
548 event.Enable( m_chkLabels->GetValue() || m_chkTicks->GetValue() );
549 }
550
551 void SliderWidgetsPage::OnUpdateUIBothSides(wxUpdateUIEvent& event)
552 {
553 #if defined(__WIN95__) || defined(__WXUNIVERSAL__)
554 event.Enable( m_chkTicks->GetValue() );
555 #else
556 event.Enable( false );
557 #endif // defined(__WIN95__) || defined(__WXUNIVERSAL__)
558 }
559
560 void SliderWidgetsPage::OnSlider(wxScrollEvent& event)
561 {
562 wxASSERT_MSG( event.GetInt() == m_slider->GetValue(),
563 wxT("slider value should be the same") );
564
565 wxEventType eventType = event.GetEventType();
566
567 /*
568 This array takes the EXACT order of the declarations in
569 include/wx/event.h
570 (section "wxScrollBar and wxSlider event identifiers")
571 */
572 static const wxChar *eventNames[] =
573 {
574 wxT("wxEVT_SCROLL_TOP"),
575 wxT("wxEVT_SCROLL_BOTTOM"),
576 wxT("wxEVT_SCROLL_LINEUP"),
577 wxT("wxEVT_SCROLL_LINEDOWN"),
578 wxT("wxEVT_SCROLL_PAGEUP"),
579 wxT("wxEVT_SCROLL_PAGEDOWN"),
580 wxT("wxEVT_SCROLL_THUMBTRACK"),
581 wxT("wxEVT_SCROLL_THUMBRELEASE"),
582 wxT("wxEVT_SCROLL_ENDSCROLL")
583 };
584
585 int index = eventType - wxEVT_SCROLL_TOP;
586
587 /*
588 If this assert is triggered, there is an unknown slider event which
589 should be added to the above eventNames array.
590 */
591 wxASSERT_MSG(index >= 0 && (size_t)index < WXSIZEOF(eventNames),
592 wxT("Unknown slider event") );
593
594
595 static int s_numSliderEvents = 0;
596
597 wxLogMessage(wxT("Slider event #%d: %s (pos = %d)"),
598 s_numSliderEvents++,
599 eventNames[index],
600 event.GetPosition());
601 }
602
603 #endif
604 // wxUSE_SLIDER