]> git.saurik.com Git - wxWidgets.git/blob - src/univ/slider.cpp
Added missing wx/frame.h inclusion
[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 wxRect rectThumb;
791 CalcThumbRect(&rectShaft, &rectThumb, NULL);
792
793 // check for possible shaft or thumb hit
794 if (!rectShaft.Inside(pt) && !rectThumb.Inside(pt))
795 {
796 return wxScrollThumb::Shaft_None;
797 }
798
799
800 // the position to test and the start and end of the thumb
801 wxCoord x, x1, x2;
802 if ( IsVert() )
803 {
804 x = pt.y;
805 x1 = rectThumb.GetTop();
806 x2 = rectThumb.GetBottom();
807 }
808 else // horz
809 {
810 x = pt.x;
811 x1 = rectThumb.GetLeft();
812 x2 = rectThumb.GetRight();
813 }
814
815 if ( x < x1 )
816 {
817 // or to the left
818 return wxScrollThumb::Shaft_Above;
819 }
820
821 if ( x > x2 )
822 {
823 // or to the right
824 return wxScrollThumb::Shaft_Below;
825 }
826
827 // where else can it be?
828 return wxScrollThumb::Shaft_Thumb;
829 }
830
831 wxCoord wxSlider::ThumbPosToPixel() const
832 {
833 wxRect rectThumb;
834 CalcThumbRect(NULL, &rectThumb, NULL);
835
836 return IsVert() ? rectThumb.y : rectThumb.x;
837 }
838
839 int wxSlider::PixelToThumbPos(wxCoord x) const
840 {
841 wxRect rectShaft = GetShaftRect();
842 wxSize sizeThumb = GetThumbSize();
843
844 wxCoord x0, len;
845 if ( IsVert() )
846 {
847 x0 = rectShaft.y;
848 len = rectShaft.height - sizeThumb.y;
849 }
850 else // horz
851 {
852 x0 = rectShaft.x;
853 len = rectShaft.width - sizeThumb.x;
854 }
855
856 int pos = m_min;
857 if ( len > 0 )
858 {
859 if ( x > x0 )
860 {
861 pos += ((x - x0) * (m_max - m_min)) / len;
862 if ( pos > m_max )
863 pos = m_max;
864 }
865 //else: x <= x0, leave pos = min
866 }
867
868 return pos;
869 }
870
871 void wxSlider::SetShaftPartState(wxScrollThumb::Shaft shaftPart,
872 int flag,
873 bool set)
874 {
875 // for now we ignore the flags for the shaft as no renderer uses them
876 // anyhow
877 if ( shaftPart == wxScrollThumb::Shaft_Thumb )
878 {
879 if ( set )
880 m_thumbFlags |= flag;
881 else
882 m_thumbFlags &= ~flag;
883
884 RefreshThumb();
885 }
886 }
887
888 void wxSlider::OnThumbDragStart(int pos)
889 {
890 PerformAction(wxACTION_SLIDER_THUMB_DRAG, pos);
891 }
892
893 void wxSlider::OnThumbDrag(int pos)
894 {
895 PerformAction(wxACTION_SLIDER_THUMB_MOVE, pos);
896 }
897
898 void wxSlider::OnThumbDragEnd(int pos)
899 {
900 PerformAction(wxACTION_SLIDER_THUMB_RELEASE, pos);
901 }
902
903 void wxSlider::OnPageScrollStart()
904 {
905 // we do nothing here
906 }
907
908 bool wxSlider::OnPageScroll(int pageInc)
909 {
910 int value = GetValue();
911 PerformAction(wxACTION_SLIDER_PAGE_CHANGE, pageInc);
912
913 return GetValue() != value;
914 }
915
916 // ----------------------------------------------------------------------------
917 // wxStdSliderButtonInputHandler
918 // ----------------------------------------------------------------------------
919
920 bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer,
921 const wxKeyEvent& event,
922 bool pressed)
923 {
924 if ( pressed )
925 {
926 int keycode = event.GetKeyCode();
927
928 wxControlAction action;
929 switch ( keycode )
930 {
931 case WXK_HOME:
932 action = wxACTION_SLIDER_START;
933 break;
934
935 case WXK_END:
936 action = wxACTION_SLIDER_END;
937 break;
938
939 case WXK_LEFT:
940 case WXK_UP:
941 action = wxACTION_SLIDER_LINE_UP;
942 break;
943
944 case WXK_RIGHT:
945 case WXK_DOWN:
946 action = wxACTION_SLIDER_LINE_DOWN;
947 break;
948
949 case WXK_PRIOR:
950 case WXK_PAGEUP:
951 action = wxACTION_SLIDER_PAGE_UP;
952 break;
953
954 case WXK_NEXT:
955 case WXK_PAGEDOWN:
956 action = wxACTION_SLIDER_PAGE_DOWN;
957 break;
958 }
959
960 if ( !!action )
961 {
962 consumer->PerformAction(action);
963
964 return TRUE;
965 }
966 }
967
968 return wxStdInputHandler::HandleKey(consumer, event, pressed);
969 }
970
971 bool wxStdSliderButtonInputHandler::HandleMouse(wxInputConsumer *consumer,
972 const wxMouseEvent& event)
973 {
974 wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider);
975
976 if ( slider->GetThumb().HandleMouse(event) )
977 {
978 // processed by the thumb
979 return FALSE;
980 }
981
982 return wxStdInputHandler::HandleMouse(consumer, event);
983 }
984
985 bool wxStdSliderButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer,
986 const wxMouseEvent& event)
987 {
988 wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider);
989
990 if ( slider->GetThumb().HandleMouseMove(event) )
991 {
992 // processed by the thumb
993 return FALSE;
994 }
995
996 return wxStdInputHandler::HandleMouseMove(consumer, event);
997 }
998
999 bool wxStdSliderButtonInputHandler::HandleFocus(wxInputConsumer *consumer,
1000 const wxFocusEvent& event)
1001 {
1002 // slider's appearance changes when it gets/loses focus
1003 return TRUE;
1004 }
1005
1006 #endif // wxUSE_SLIDER