]> git.saurik.com Git - wxWidgets.git/blob - src/univ/slider.cpp
Misc mods for feedback from Marcin Wojdyr <wojdyr@if.pw.edu.pl>
[wxWidgets.git] / src / univ / slider.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: univ/slider.cpp
3 // Purpose: implementation of the universal version of wxSlider
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 09.02.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 /*
13 There is some discrepancy in wxSL_LABELS style handling between wxMSW and
14 wxGTK: the latter handles it natively and shows only the current value of
15 the slider on the side corresponding to wxSL_TOP/BOTTOM/LEFT/RIGHT style
16 given (which can be combined with wxSL_HORIZONTAL/VERTICAL) while wxMSW
17 emulates this somehow and shows the min and max values near the ends of the
18 slider and the current value in a separate static box nearby.
19
20 We currently follow wxGTK except that wxSL_HORIZONTAL slider can only have
21 the label displayed on top or bottom of it and wxSL_VERTICAL - to the left
22 or right.
23
24 What we really need is probably a more fine grain control on labels, i.e. we
25 should be able to select if we show nothign at all, the current value only
26 or the value and the limits - the current approach is just that of the
27 greatest common denominator.
28
29 TODO:
30
31 +0. add ticks support
32 1. support for all orientations
33 2. draw the slider thumb highlighted when it is dragged
34 ?3. manual ticks support?
35 */
36
37 // ============================================================================
38 // declarations
39 // ============================================================================
40
41 // ----------------------------------------------------------------------------
42 // headers
43 // ----------------------------------------------------------------------------
44
45 #ifdef __GNUG__
46 #pragma implementation "univslider.h"
47 #endif
48
49 #include "wx/wxprec.h"
50
51 #ifdef __BORLANDC__
52 #pragma hdrstop
53 #endif
54
55 #ifndef WX_PRECOMP
56 #include "wx/dc.h"
57 #endif
58
59 #include "wx/slider.h"
60
61 #if wxUSE_SLIDER
62
63 #include "wx/univ/renderer.h"
64 #include "wx/univ/inphand.h"
65 #include "wx/univ/theme.h"
66
67 // ----------------------------------------------------------------------------
68 // constants
69 // ----------------------------------------------------------------------------
70
71 // the margin between the slider and the label (FIXME: hardcoded)
72 static const wxCoord SLIDER_LABEL_MARGIN = 2;
73
74 // ============================================================================
75 // implementation of wxSlider
76 // ============================================================================
77
78 IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
79
80 BEGIN_EVENT_TABLE(wxSlider, wxControl)
81 EVT_SIZE(wxSlider::OnSize)
82 END_EVENT_TABLE()
83
84 // ----------------------------------------------------------------------------
85 // wxSlider creation
86 // ----------------------------------------------------------------------------
87
88 #ifdef __VISUALC__
89 // warning C4355: 'this' : used in base member initializer list
90 #pragma warning(disable:4355)
91 #endif
92
93 wxSlider::wxSlider()
94 : m_thumb(this)
95 {
96 Init();
97 }
98
99 wxSlider::wxSlider(wxWindow *parent,
100 wxWindowID id,
101 int value, int minValue, int maxValue,
102 const wxPoint& pos,
103 const wxSize& size,
104 long style,
105 const wxValidator& validator,
106 const wxString& name)
107 : m_thumb(this)
108 {
109 Init();
110
111 (void)Create(parent, id, value, minValue, maxValue,
112 pos, size, style, validator, name);
113 }
114
115 #ifdef __VISUALC__
116 // warning C4355: 'this' : used in base member initializer list
117 #pragma warning(default:4355)
118 #endif
119
120 void wxSlider::Init()
121 {
122 m_min =
123 m_max =
124 m_value = 0;
125
126 m_tickFreq = 1;
127
128 m_lineSize =
129 m_pageSize = 0;
130
131 m_thumbSize = 0;
132 m_thumbFlags = 0;
133 }
134
135 bool wxSlider::Create(wxWindow *parent,
136 wxWindowID id,
137 int value, int minValue, int maxValue,
138 const wxPoint& pos,
139 const wxSize& size,
140 long style,
141 const wxValidator& validator,
142 const wxString& name)
143 {
144 if ( !wxSliderBase::Create(parent, id, pos, size, style,
145 validator, name) )
146 return FALSE;
147
148 SetRange(minValue, maxValue);
149 SetValue(value);
150
151 // call this after setting the range as the best size depends (at least if
152 // we have wxSL_LABELS style) on the range
153 SetBestSize(size);
154
155 CreateInputHandler(wxINP_HANDLER_SLIDER);
156
157 return TRUE;
158 }
159
160 // ----------------------------------------------------------------------------
161 // wxSlider range and value
162 // ----------------------------------------------------------------------------
163
164 int wxSlider::GetValue() const
165 {
166 return m_value;
167 }
168
169 int wxSlider::NormalizeValue(int value) const
170 {
171 if ( value < m_min )
172 return m_min;
173 else if ( value > m_max )
174 return m_max;
175 else
176 return value;
177 }
178
179 bool wxSlider::ChangeValueBy(int inc)
180 {
181 return ChangeValueTo(NormalizeValue(m_value + inc));
182 }
183
184 bool wxSlider::ChangeValueTo(int value)
185 {
186 // this method is protected and we should only call it with normalized
187 // value!
188 wxCHECK_MSG( IsInRange(value), FALSE, _T("invalid slider value") );
189
190 // check if the value is going to change at all
191 if ( value == m_value )
192 return FALSE;
193
194 // refresh the old thumb position
195 RefreshThumb();
196
197 m_value = value;
198
199 // and the new one
200 RefreshThumb();
201
202 // generate the event
203 wxCommandEvent event(wxEVT_COMMAND_SLIDER_UPDATED, GetId());
204 event.SetInt(m_value);
205 event.SetEventObject(this);
206
207 (void)GetEventHandler()->ProcessEvent(event);
208
209 return TRUE;
210 }
211
212 void wxSlider::SetValue(int value)
213 {
214 value = NormalizeValue(value);
215
216 if ( m_value != value )
217 {
218 m_value = value;
219
220 Refresh();
221 }
222 }
223
224 void wxSlider::SetRange(int minValue, int maxValue)
225 {
226 if ( minValue > maxValue )
227 {
228 // swap them, we always want min to be less than max
229 int tmp = minValue;
230 minValue = maxValue;
231 maxValue = tmp;
232 }
233
234 if ( m_min != minValue || m_max != maxValue )
235 {
236 m_min = minValue;
237 m_max = maxValue;
238
239 // reset the value to make sure it is in the new range
240 SetValue(m_value);
241
242 // the size of the label rect might have changed
243 if ( HasLabels() )
244 {
245 CalcGeometry();
246 }
247
248 Refresh();
249 }
250 //else: nothing changed
251 }
252
253 int wxSlider::GetMin() const
254 {
255 return m_min;
256 }
257
258 int wxSlider::GetMax() const
259 {
260 return m_max;
261 }
262
263 // ----------------------------------------------------------------------------
264 // wxSlider line/page/thumb size
265 // ----------------------------------------------------------------------------
266
267 void wxSlider::SetLineSize(int lineSize)
268 {
269 wxCHECK_RET( lineSize > 0, _T("invalid slider line size") );
270
271 m_lineSize = lineSize;
272 }
273
274 void wxSlider::SetPageSize(int pageSize)
275 {
276 wxCHECK_RET( pageSize > 0, _T("invalid slider page size") );
277
278 m_pageSize = pageSize;
279 }
280
281 int wxSlider::GetLineSize() const
282 {
283 if ( !m_lineSize )
284 {
285 // the default line increment is 1
286 wxConstCast(this, wxSlider)->m_lineSize = 1;
287 }
288
289 return m_lineSize;
290 }
291
292 int wxSlider::GetPageSize() const
293 {
294 if ( !m_pageSize )
295 {
296 // the default page increment is 1/10 of the range
297 wxConstCast(this, wxSlider)->m_pageSize = (m_max - m_min) / 10;
298 }
299
300 return m_pageSize;
301 }
302
303 void wxSlider::SetThumbLength(int lenPixels)
304 {
305 wxCHECK_RET( lenPixels > 0, _T("invalid slider thumb size") );
306
307 // use m_thumbSize here directly and not GetThumbLength() to avoid setting
308 // it to the default value as we don't need it
309 if ( lenPixels != m_thumbSize )
310 {
311 m_thumbSize = lenPixels;
312
313 Refresh();
314 }
315 }
316
317 int wxSlider::GetThumbLength() const
318 {
319 if ( !m_thumbSize )
320 {
321 wxSize sz = GetDefaultThumbSize();
322 return IsVert() ? sz.y : sz.x;
323 }
324
325 return m_thumbSize;
326 }
327
328 // ----------------------------------------------------------------------------
329 // wxSlider ticks
330 // ----------------------------------------------------------------------------
331
332 void wxSlider::SetTickFreq(int n, int WXUNUSED(dummy))
333 {
334 if ( n != m_tickFreq )
335 {
336 m_tickFreq = n;
337
338 Refresh();
339 }
340 }
341
342 // ----------------------------------------------------------------------------
343 // wxSlider geometry
344 // ----------------------------------------------------------------------------
345
346 wxSize wxSlider::CalcLabelSize() const
347 {
348 wxSize size;
349
350 // there is no sense in trying to calc the labels size if we haven't got
351 // any, the caller must check for it
352 wxCHECK_MSG( HasLabels(), size, _T("shouldn't be called") );
353
354 wxCoord w1, h1, w2, h2;
355 GetTextExtent(FormatValue(m_min), &w1, &h1);
356 GetTextExtent(FormatValue(m_max), &w2, &h2);
357
358 size.x = wxMax(w1, w2);
359 size.y = wxMax(h1, h2);
360
361 return size;
362 }
363
364 wxSize wxSlider::DoGetBestClientSize() const
365 {
366 // this dimension is completely arbitrary
367 static const wxCoord SLIDER_WIDTH = 100;
368
369 // first calculate the size of the slider itself: i.e. the shaft and the
370 // thumb
371 wxCoord height = GetRenderer()->GetSliderDim();
372
373 wxSize size;
374 if ( IsVert() )
375 {
376 size.x = height;
377 size.y = SLIDER_WIDTH;
378 }
379 else // horizontal
380 {
381 size.x = SLIDER_WIDTH;
382 size.y = height;
383 }
384
385 // add space for ticks
386 if ( HasTicks() )
387 {
388 wxCoord lenTick = GetRenderer()->GetSliderTickLen();
389
390 if ( IsVert() )
391 size.x += lenTick;
392 else
393 size.y += lenTick;
394 }
395
396 // if we have the label, reserve enough space for it
397 if ( HasLabels() )
398 {
399 wxSize sizeLabels = CalcLabelSize();
400
401 if ( IsVert() )
402 size.x += sizeLabels.x + SLIDER_LABEL_MARGIN;
403 else
404 size.y += sizeLabels.y + SLIDER_LABEL_MARGIN;
405 }
406
407 return size;
408 }
409
410 void wxSlider::OnSize(wxSizeEvent& event)
411 {
412 CalcGeometry();
413
414 event.Skip();
415 }
416
417 const wxRect& wxSlider::GetSliderRect() const
418 {
419 if ( m_rectSlider.width < 0 )
420 {
421 wxConstCast(this, wxSlider)->CalcGeometry();
422 }
423
424 return m_rectSlider;
425 }
426
427 void wxSlider::CalcGeometry()
428 {
429 /*
430 recalc the label and slider positions, this looks like this for
431 wxSL_HORIZONTAL | wxSL_TOP slider:
432
433 LLL lll
434 -------------------------
435 | T | <-- this is the slider rect
436 | HHHHHHHHHHHHHHHTHHHHH |
437 | T |
438 | * * * * * * * *|
439 -------------------------
440
441 LLL is m_rectLabel as calculated here and lll is the real rect used for
442 label drawing in OnDraw() (TTT indicated the thumb position and *s are
443 the ticks)
444
445 in the wxSL_VERTICAL | wxSL_RIGHT case the picture is like this:
446
447 ------ LLL
448 | H |
449 | H *|
450 | H |
451 | H *|
452 | H |
453 | H *|
454 | H |
455 |TTT*| lll
456 | H |
457 | H *|
458 ------
459 */
460
461 wxRect rectTotal = GetClientRect();
462 if ( HasLabels() )
463 {
464 wxSize sizeLabels = CalcLabelSize();
465
466 m_rectSlider = rectTotal;
467 m_rectLabel = wxRect(rectTotal.GetPosition(), sizeLabels);
468
469 // split the rect
470 if ( IsVert() )
471 {
472 sizeLabels.x += SLIDER_LABEL_MARGIN;
473
474 if ( GetWindowStyle() & wxSL_LEFT )
475 {
476 // shrink and offset the slider to the right
477 m_rectSlider.x += sizeLabels.x;
478 m_rectSlider.width -= sizeLabels.x;
479 }
480 else // wxSL_RIGHT
481 {
482 // just shrink the slider and move the label to the right
483 m_rectSlider.width -= sizeLabels.x;
484
485 m_rectLabel.x += m_rectSlider.width + SLIDER_LABEL_MARGIN;
486 }
487 }
488 else // horizontal
489 {
490 // same logic as above but x/y are trasnposed
491 sizeLabels.y += SLIDER_LABEL_MARGIN;
492
493 if ( GetWindowStyle() & wxSL_TOP )
494 {
495 m_rectSlider.y += sizeLabels.y;
496 m_rectSlider.height -= sizeLabels.y;
497 }
498 else // wxSL_BOTTOM
499 {
500 m_rectSlider.height -= sizeLabels.y;
501
502 m_rectLabel.y += m_rectSlider.height + SLIDER_LABEL_MARGIN;
503 }
504 }
505 }
506 else // no labels
507 {
508 // the slider takes the whole client rect
509 m_rectSlider = rectTotal;
510 }
511
512 // now adjust for ticks too
513 if ( HasTicks() )
514 {
515 wxCoord lenTick = GetRenderer()->GetSliderTickLen();
516
517 if ( IsVert() )
518 {
519 m_rectSlider.width -= lenTick;
520 }
521 else // horizontal
522 {
523 m_rectSlider.height -= lenTick;
524 }
525
526 // note that we must compute m_rectSlider first as GetShaftRect() uses
527 // it
528 m_rectTicks = GetShaftRect();
529
530 if ( IsVert() )
531 {
532 m_rectTicks.x = m_rectSlider.x + m_rectSlider.width;
533 m_rectTicks.width = lenTick;
534 }
535 else // horizontal
536 {
537 m_rectTicks.y = m_rectSlider.y + m_rectSlider.height;
538 m_rectTicks.height = lenTick;
539 }
540
541 }
542 }
543
544 wxSize wxSlider::GetDefaultThumbSize() const
545 {
546 return GetRenderer()->GetSliderThumbSize(GetSliderRect(), GetOrientation());
547 }
548
549 wxSize wxSlider::GetThumbSize() const
550 {
551 wxSize sizeThumb = GetDefaultThumbSize();
552
553 // if we have our own thumb length (set by the user), use it instead of the
554 // default value
555 if ( m_thumbSize )
556 {
557 if ( IsVert() )
558 sizeThumb.y = m_thumbSize;
559 else
560 sizeThumb.x = m_thumbSize;
561 }
562
563 return sizeThumb;
564 }
565
566 // ----------------------------------------------------------------------------
567 // wxSlider thumb geometry
568 // ----------------------------------------------------------------------------
569
570 wxRect wxSlider::GetShaftRect() const
571 {
572 return GetRenderer()->GetSliderShaftRect(m_rectSlider, GetOrientation());
573 }
574
575 void wxSlider::CalcThumbRect(const wxRect *rectShaftIn,
576 wxRect *rectThumbOut,
577 wxRect *rectLabelOut,
578 int value) const
579 {
580 if ( value == INVALID_THUMB_VALUE )
581 {
582 // use the current if not specified
583 value = m_value;
584 }
585
586 bool isVertical = IsVert();
587
588 wxRect rectShaft;
589 if ( rectShaftIn )
590 {
591 rectShaft = *rectShaftIn;
592 }
593 else // no shaft rect provided, calc it
594 {
595 rectShaft = GetShaftRect();
596 }
597
598 wxCoord lenShaft,
599 lenThumb,
600 *p;
601 wxRect rectThumb(rectShaft.GetPosition(), GetThumbSize());
602 if ( isVertical )
603 {
604 rectThumb.x += (rectShaft.width - rectThumb.width) / 2;
605
606 lenThumb = rectThumb.height;
607 lenShaft = rectShaft.height;
608 p = &rectThumb.y;
609 }
610 else // horz
611 {
612 rectThumb.y += (rectShaft.height - rectThumb.height) / 2;
613
614 lenThumb = rectThumb.width;
615 lenShaft = rectShaft.width;
616 p = &rectThumb.x;
617 }
618
619 // the thumb must always be entirely inside the shaft limits, so the max
620 // position is not at lenShaft but at lenShaft - thumbSize
621 if ( m_max != m_min )
622 {
623 *p += ((lenShaft - lenThumb)*(value - m_min))/(m_max - m_min);
624 }
625
626 // calc the label rect
627 if ( HasLabels() && rectLabelOut )
628 {
629 wxRect rectLabel = m_rectLabel;
630
631 // centre the label relatively to the thumb position
632 if ( isVertical )
633 {
634 rectLabel.y =
635 rectThumb.y + (rectThumb.height - m_rectLabel.height)/2;
636 }
637 else // horz
638 {
639 rectLabel.x =
640 rectThumb.x + (rectThumb.width - m_rectLabel.width)/2;
641 }
642
643 *rectLabelOut = rectLabel;
644 }
645
646 if ( rectThumbOut )
647 *rectThumbOut = rectThumb;
648 }
649
650 // ----------------------------------------------------------------------------
651 // wxSlider drawing
652 // ----------------------------------------------------------------------------
653
654 wxString wxSlider::FormatValue(int value) const
655 {
656 return wxString::Format(_T("%d"), value);
657 }
658
659 void wxSlider::DoDraw(wxControlRenderer *renderer)
660 {
661 wxRenderer *rend = GetRenderer();
662 wxDC& dc = renderer->GetDC();
663 wxRect rectUpdate = GetUpdateClientRect();
664
665 bool isVertical = IsVert();
666 wxOrientation orient = GetOrientation();
667 int flags = GetStateFlags();
668
669 // first draw the shaft
670 wxRect rectShaft = rend->GetSliderShaftRect(m_rectSlider, orient);
671 if ( rectUpdate.Intersects(rectShaft) )
672 {
673 rend->DrawSliderShaft(dc, m_rectSlider, orient, flags);
674 }
675
676 // calculate the thumb position in pixels and draw it
677 wxRect rectThumb, rectLabel;
678 CalcThumbRect(&rectShaft, &rectThumb, &rectLabel);
679
680 if ( rectUpdate.Intersects(rectThumb) )
681 {
682 rend->DrawSliderThumb(dc, rectThumb, orient, flags | m_thumbFlags);
683 }
684
685 // then draw the ticks
686 if ( HasTicks() && rectUpdate.Intersects(m_rectTicks) )
687 {
688 rend->DrawSliderTicks(dc, m_rectTicks, rectThumb.GetSize(), orient,
689 m_min, m_max, m_tickFreq);
690 }
691
692 // finally, draw the label near the thumb
693 if ( HasLabels() && rectUpdate.Intersects(rectLabel) )
694 {
695 // align it to be close to the shaft
696 int align;
697 if ( isVertical )
698 {
699 align = wxALIGN_CENTRE_VERTICAL |
700 (GetWindowStyle() & wxSL_RIGHT ? wxALIGN_LEFT
701 : wxALIGN_RIGHT);
702 }
703 else // horz
704 {
705 align = wxALIGN_CENTRE;
706 }
707
708 dc.SetFont(GetFont());
709 dc.SetTextForeground(GetForegroundColour());
710
711 // the slider label is never drawn focused
712 rend->DrawLabel(dc, FormatValue(m_value), rectLabel,
713 flags & ~wxCONTROL_FOCUSED, align);
714 }
715 }
716
717 void wxSlider::RefreshThumb()
718 {
719 wxRect rectThumb, rectLabel;
720 CalcThumbRect(NULL, &rectThumb, &rectLabel);
721
722 Refresh(TRUE /* erase background */, &rectThumb);
723 if ( HasLabels() )
724 {
725 Refresh(TRUE, &rectLabel);
726 }
727 }
728
729 // ----------------------------------------------------------------------------
730 // wxSlider input processing
731 // ----------------------------------------------------------------------------
732
733 bool wxSlider::PerformAction(const wxControlAction& action,
734 long numArg,
735 const wxString& strArg)
736 {
737 if ( action == wxACTION_SLIDER_START )
738 {
739 ChangeValueTo(m_min);
740 }
741 else if ( action == wxACTION_SLIDER_END )
742 {
743 ChangeValueTo(m_max);
744 }
745 else if ( action == wxACTION_SLIDER_PAGE_CHANGE )
746 {
747 ChangeValueBy(numArg * GetPageSize());
748 }
749 else if ( action == wxACTION_SLIDER_LINE_UP )
750 {
751 ChangeValueBy(-GetLineSize());
752 }
753 else if ( action == wxACTION_SLIDER_PAGE_UP )
754 {
755 return PerformAction(wxACTION_SLIDER_PAGE_CHANGE, -1);
756 }
757 else if ( action == wxACTION_SLIDER_LINE_DOWN )
758 {
759 ChangeValueBy(GetLineSize());
760 }
761 else if ( action == wxACTION_SLIDER_PAGE_DOWN )
762 {
763 return PerformAction(wxACTION_SLIDER_PAGE_CHANGE, 1);
764 }
765 else if ( action == wxACTION_SLIDER_THUMB_DRAG )
766 {
767 // no special processing for it
768 return TRUE;
769 }
770 else if ( action == wxACTION_SLIDER_THUMB_MOVE ||
771 action == wxACTION_SLIDER_THUMB_RELEASE )
772 {
773 ChangeValueTo((int)numArg);
774 }
775 else
776 {
777 return wxControl::PerformAction(action, numArg, strArg);
778 }
779
780 return TRUE;
781 }
782
783 // ----------------------------------------------------------------------------
784 // wxSlider implementation of wxControlWithThumb interface
785 // ----------------------------------------------------------------------------
786
787 wxScrollThumb::Shaft wxSlider::HitTest(const wxPoint& pt) const
788 {
789 wxRect rectShaft = GetShaftRect();
790 if ( !rectShaft.Inside(pt) )
791 {
792 return wxScrollThumb::Shaft_None;
793 }
794
795 // inside the shaft, where is it relatively to the thumb?
796 wxRect rectThumb;
797 CalcThumbRect(&rectShaft, &rectThumb, NULL);
798
799 // the position to test and the start and end of the thumb
800 wxCoord x, x1, x2;
801 if ( IsVert() )
802 {
803 x = pt.y;
804 x1 = rectThumb.GetTop();
805 x2 = rectThumb.GetBottom();
806 }
807 else // horz
808 {
809 x = pt.x;
810 x1 = rectThumb.GetLeft();
811 x2 = rectThumb.GetRight();
812 }
813
814 if ( x < x1 )
815 {
816 // or to the left
817 return wxScrollThumb::Shaft_Above;
818 }
819
820 if ( x > x2 )
821 {
822 // or to the right
823 return wxScrollThumb::Shaft_Below;
824 }
825
826 // where else can it be?
827 return wxScrollThumb::Shaft_Thumb;
828 }
829
830 wxCoord wxSlider::ThumbPosToPixel() const
831 {
832 wxRect rectThumb;
833 CalcThumbRect(NULL, &rectThumb, NULL);
834
835 return IsVert() ? rectThumb.y : rectThumb.x;
836 }
837
838 int wxSlider::PixelToThumbPos(wxCoord x) const
839 {
840 wxRect rectShaft = GetShaftRect();
841 wxSize sizeThumb = GetThumbSize();
842
843 wxCoord x0, len;
844 if ( IsVert() )
845 {
846 x0 = rectShaft.y;
847 len = rectShaft.height - sizeThumb.y;
848 }
849 else // horz
850 {
851 x0 = rectShaft.x;
852 len = rectShaft.width - sizeThumb.x;
853 }
854
855 int pos = m_min;
856 if ( len > 0 )
857 {
858 if ( x > x0 )
859 {
860 pos += ((x - x0) * (m_max - m_min)) / len;
861 if ( pos > m_max )
862 pos = m_max;
863 }
864 //else: x <= x0, leave pos = min
865 }
866
867 return pos;
868 }
869
870 void wxSlider::SetShaftPartState(wxScrollThumb::Shaft shaftPart,
871 int flag,
872 bool set)
873 {
874 // for now we ignore the flags for the shaft as no renderer uses them
875 // anyhow
876 if ( shaftPart == wxScrollThumb::Shaft_Thumb )
877 {
878 if ( set )
879 m_thumbFlags |= flag;
880 else
881 m_thumbFlags &= ~flag;
882
883 RefreshThumb();
884 }
885 }
886
887 void wxSlider::OnThumbDragStart(int pos)
888 {
889 PerformAction(wxACTION_SLIDER_THUMB_DRAG, pos);
890 }
891
892 void wxSlider::OnThumbDrag(int pos)
893 {
894 PerformAction(wxACTION_SLIDER_THUMB_MOVE, pos);
895 }
896
897 void wxSlider::OnThumbDragEnd(int pos)
898 {
899 PerformAction(wxACTION_SLIDER_THUMB_RELEASE, pos);
900 }
901
902 void wxSlider::OnPageScrollStart()
903 {
904 // we do nothing here
905 }
906
907 bool wxSlider::OnPageScroll(int pageInc)
908 {
909 int value = GetValue();
910 PerformAction(wxACTION_SLIDER_PAGE_CHANGE, pageInc);
911
912 return GetValue() != value;
913 }
914
915 // ----------------------------------------------------------------------------
916 // wxStdSliderButtonInputHandler
917 // ----------------------------------------------------------------------------
918
919 bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer,
920 const wxKeyEvent& event,
921 bool pressed)
922 {
923 if ( pressed )
924 {
925 int keycode = event.GetKeyCode();
926
927 wxControlAction action;
928 switch ( keycode )
929 {
930 case WXK_HOME:
931 action = wxACTION_SLIDER_START;
932 break;
933
934 case WXK_END:
935 action = wxACTION_SLIDER_END;
936 break;
937
938 case WXK_LEFT:
939 case WXK_UP:
940 action = wxACTION_SLIDER_LINE_UP;
941 break;
942
943 case WXK_RIGHT:
944 case WXK_DOWN:
945 action = wxACTION_SLIDER_LINE_DOWN;
946 break;
947
948 case WXK_PRIOR:
949 case WXK_PAGEUP:
950 action = wxACTION_SLIDER_PAGE_UP;
951 break;
952
953 case WXK_NEXT:
954 case WXK_PAGEDOWN:
955 action = wxACTION_SLIDER_PAGE_DOWN;
956 break;
957 }
958
959 if ( !!action )
960 {
961 consumer->PerformAction(action);
962
963 return TRUE;
964 }
965 }
966
967 return wxStdInputHandler::HandleKey(consumer, event, pressed);
968 }
969
970 bool wxStdSliderButtonInputHandler::HandleMouse(wxInputConsumer *consumer,
971 const wxMouseEvent& event)
972 {
973 wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider);
974
975 if ( slider->GetThumb().HandleMouse(event) )
976 {
977 // processed by the thumb
978 return FALSE;
979 }
980
981 return wxStdInputHandler::HandleMouse(consumer, event);
982 }
983
984 bool wxStdSliderButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer,
985 const wxMouseEvent& event)
986 {
987 wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider);
988
989 if ( slider->GetThumb().HandleMouseMove(event) )
990 {
991 // processed by the thumb
992 return FALSE;
993 }
994
995 return wxStdInputHandler::HandleMouseMove(consumer, event);
996 }
997
998 bool wxStdSliderButtonInputHandler::HandleFocus(wxInputConsumer *consumer,
999 const wxFocusEvent& event)
1000 {
1001 // slider's appearance changes when it gets/loses focus
1002 return TRUE;
1003 }
1004
1005 #endif // wxUSE_SLIDER