xref: /trunk/main/vcl/source/control/slider.cxx (revision 989b13ef2270bbb43d1b5fb03162470a47d7f4cc)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_vcl.hxx"
24 
25 #ifndef _SV_RC_H
26 #include <tools/rc.h>
27 #endif
28 #include <vcl/event.hxx>
29 #include <vcl/decoview.hxx>
30 #include <vcl/slider.hxx>
31 
32 // =======================================================================
33 
34 static long ImplMulDiv( long nNumber, long nNumerator, long nDenominator )
35 {
36     double n = ((double)nNumber * (double)nNumerator) / (double)nDenominator;
37     return (long)n;
38 }
39 
40 // =======================================================================
41 
42 #define SLIDER_DRAW_THUMB           ((sal_uInt16)0x0001)
43 #define SLIDER_DRAW_CHANNEL1        ((sal_uInt16)0x0002)
44 #define SLIDER_DRAW_CHANNEL2        ((sal_uInt16)0x0004)
45 #define SLIDER_DRAW_CHANNEL         (SLIDER_DRAW_CHANNEL1 | SLIDER_DRAW_CHANNEL2)
46 #define SLIDER_DRAW_ALL             (SLIDER_DRAW_THUMB | SLIDER_DRAW_CHANNEL)
47 
48 #define SLIDER_STATE_CHANNEL1_DOWN  ((sal_uInt16)0x0001)
49 #define SLIDER_STATE_CHANNEL2_DOWN  ((sal_uInt16)0x0002)
50 #define SLIDER_STATE_THUMB_DOWN     ((sal_uInt16)0x0004)
51 
52 #define SLIDER_THUMB_SIZE           9
53 #define SLIDER_THUMB_HALFSIZE       4
54 #define SLIDER_CHANNEL_OFFSET       0
55 #define SLIDER_CHANNEL_SIZE         4
56 #define SLIDER_CHANNEL_HALFSIZE     2
57 
58 #define SLIDER_HEIGHT               16
59 
60 #define SLIDER_VIEW_STYLE           (WB_3DLOOK | WB_HORZ | WB_VERT)
61 
62 // =======================================================================
63 
64 void Slider::ImplInit( Window* pParent, WinBits nStyle )
65 {
66     mnThumbPixOffset    = 0;
67     mnThumbPixRange     = 0;
68     mnThumbPixPos       = 0; // between mnThumbPixOffset and mnThumbPixOffset+mnThumbPixRange
69     mnChannelPixOffset  = 0;
70     mnChannelPixRange   = 0;
71     mnChannelPixTop     = 0;
72     mnChannelPixBottom  = 0;
73 
74     mnMinRange          = 0;
75     mnMaxRange          = 100;
76     mnThumbPos          = 0;
77     mnLineSize          = 1;
78     mnPageSize          = 1;
79     mnDelta             = 0;
80     mnDragDraw          = 0;
81     mnStateFlags        = 0;
82     meScrollType        = SCROLL_DONTKNOW;
83     mbCalcSize          = sal_True;
84     mbFullDrag          = sal_True;
85 
86     Control::ImplInit( pParent, nStyle, NULL );
87 
88     ImplInitSettings();
89     SetSizePixel( CalcWindowSizePixel() );
90 }
91 
92 // -----------------------------------------------------------------------
93 
94 Slider::Slider( Window* pParent, WinBits nStyle ) :
95     Control( WINDOW_SLIDER )
96 {
97     ImplInit( pParent, nStyle );
98 }
99 
100 // -----------------------------------------------------------------------
101 
102 Slider::Slider( Window* pParent, const ResId& rResId ) :
103     Control( WINDOW_SLIDER )
104 {
105     rResId.SetRT( RSC_SCROLLBAR );
106     WinBits nStyle = ImplInitRes( rResId );
107     ImplInit( pParent, nStyle );
108     ImplLoadRes( rResId );
109 
110     if ( !(nStyle & WB_HIDE) )
111         Show();
112 }
113 
114 // -----------------------------------------------------------------------
115 
116 void Slider::ImplLoadRes( const ResId& rResId )
117 {
118     Control::ImplLoadRes( rResId );
119 
120     sal_Int16 nMin          = ReadShortRes();
121     sal_Int16 nMax          = ReadShortRes();
122     sal_Int16 nThumbPos     = ReadShortRes();
123     sal_Int16 nPage         = ReadShortRes();
124     sal_Int16 nStep         = ReadShortRes();
125     /* sal_Int16 nVisibleSize   = */ ReadShortRes();
126 
127     SetRange( Range( nMin, nMax ) );
128     SetLineSize( nStep );
129     SetPageSize( nPage );
130     SetThumbPos( nThumbPos );
131 }
132 
133 // -----------------------------------------------------------------------
134 
135 void Slider::ImplInitSettings()
136 {
137     Window* pParent = GetParent();
138     if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
139     {
140         EnableChildTransparentMode( sal_True );
141         SetParentClipMode( PARENTCLIPMODE_NOCLIP );
142         SetPaintTransparent( sal_True );
143         SetBackground();
144     }
145     else
146     {
147         EnableChildTransparentMode( sal_False );
148         SetParentClipMode( 0 );
149         SetPaintTransparent( sal_False );
150 
151         if ( IsControlBackground() )
152             SetBackground( GetControlBackground() );
153         else
154             SetBackground( pParent->GetBackground() );
155     }
156 }
157 
158 // -----------------------------------------------------------------------
159 
160 void Slider::ImplUpdateRects( sal_Bool bUpdate )
161 {
162     Rectangle aOldThumbRect = maThumbRect;
163     bool bInvalidateAll = false;
164 
165     if ( mnThumbPixRange )
166     {
167         if ( GetStyle() & WB_HORZ )
168         {
169             maThumbRect.Left()      = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
170             maThumbRect.Right()     = maThumbRect.Left()+SLIDER_THUMB_SIZE-1;
171             if ( mnChannelPixOffset < maThumbRect.Left() )
172             {
173                 maChannel1Rect.Left()   = mnChannelPixOffset;
174                 maChannel1Rect.Right()  = maThumbRect.Left()-1;
175                 maChannel1Rect.Top()    = mnChannelPixTop;
176                 maChannel1Rect.Bottom() = mnChannelPixBottom;
177             }
178             else
179                 maChannel1Rect.SetEmpty();
180             if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Right() )
181             {
182                 maChannel2Rect.Left()   = maThumbRect.Right()+1;
183                 maChannel2Rect.Right()  = mnChannelPixOffset+mnChannelPixRange-1;
184                 maChannel2Rect.Top()    = mnChannelPixTop;
185                 maChannel2Rect.Bottom() = mnChannelPixBottom;
186             }
187             else
188                 maChannel2Rect.SetEmpty();
189 
190             const Rectangle aControlRegion( Rectangle( Point(0,0), Size( SLIDER_THUMB_SIZE, 10 ) ) );
191             Rectangle aThumbBounds, aThumbContent;
192             if ( GetNativeControlRegion( CTRL_SLIDER, PART_THUMB_HORZ,
193                                          aControlRegion, 0, ImplControlValue(), rtl::OUString(),
194                                          aThumbBounds, aThumbContent ) )
195             {
196                 maThumbRect.Left() = mnThumbPixPos - aThumbBounds.GetWidth()/2;
197                 maThumbRect.Right() = maThumbRect.Left() + aThumbBounds.GetWidth() - 1;
198                 bInvalidateAll = true;
199             }
200         }
201         else
202         {
203             maThumbRect.Top()       = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
204             maThumbRect.Bottom()    = maThumbRect.Top()+SLIDER_THUMB_SIZE-1;
205             if ( mnChannelPixOffset < maThumbRect.Top() )
206             {
207                 maChannel1Rect.Top()    = mnChannelPixOffset;
208                 maChannel1Rect.Bottom() = maThumbRect.Top()-1;
209                 maChannel1Rect.Left()   = mnChannelPixTop;
210                 maChannel1Rect.Right()  = mnChannelPixBottom;
211             }
212             else
213                 maChannel1Rect.SetEmpty();
214             if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Bottom() )
215             {
216                 maChannel2Rect.Top()    = maThumbRect.Bottom()+1;
217                 maChannel2Rect.Bottom() = mnChannelPixOffset+mnChannelPixRange-1;
218                 maChannel2Rect.Left()   = mnChannelPixTop;
219                 maChannel2Rect.Right()  = mnChannelPixBottom;
220             }
221             else
222                 maChannel2Rect.SetEmpty();
223 
224             const Rectangle aControlRegion( Rectangle( Point(0,0), Size( 10, SLIDER_THUMB_SIZE ) ) );
225             Rectangle aThumbBounds, aThumbContent;
226             if ( GetNativeControlRegion( CTRL_SLIDER, PART_THUMB_VERT,
227                                          aControlRegion, 0, ImplControlValue(), rtl::OUString(),
228                                          aThumbBounds, aThumbContent ) )
229             {
230                 maThumbRect.Top() = mnThumbPixPos - aThumbBounds.GetHeight()/2;
231                 maThumbRect.Bottom() = maThumbRect.Top() + aThumbBounds.GetHeight() - 1;
232                 bInvalidateAll = true;
233             }
234         }
235     }
236     else
237     {
238         maChannel1Rect.SetEmpty();
239         maChannel2Rect.SetEmpty();
240         maThumbRect.SetEmpty();
241     }
242 
243     if ( bUpdate )
244     {
245         if ( aOldThumbRect != maThumbRect )
246         {
247             if( bInvalidateAll )
248                 Invalidate();
249             else
250             {
251                 Region aInvalidRegion( aOldThumbRect );
252                 aInvalidRegion.Union( maThumbRect );
253 
254                 if( !IsBackground() && GetParent() )
255                 {
256                     const Point aPos( GetPosPixel() );
257                     aInvalidRegion.Move( aPos.X(), aPos.Y() );
258                     GetParent()->Invalidate( aInvalidRegion, INVALIDATE_TRANSPARENT | INVALIDATE_UPDATE );
259                 }
260                 else
261                     Invalidate( aInvalidRegion );
262             }
263         }
264     }
265 }
266 
267 // -----------------------------------------------------------------------
268 
269 long Slider::ImplCalcThumbPos( long nPixPos )
270 {
271     // Position berechnen
272     long nCalcThumbPos;
273     nCalcThumbPos = ImplMulDiv( nPixPos-mnThumbPixOffset, mnMaxRange-mnMinRange, mnThumbPixRange-1 );
274     nCalcThumbPos += mnMinRange;
275     return nCalcThumbPos;
276 }
277 
278 // -----------------------------------------------------------------------
279 
280 long Slider::ImplCalcThumbPosPix( long nPos )
281 {
282     // Position berechnen
283     long nCalcThumbPos;
284     nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-1, mnMaxRange-mnMinRange );
285     // Am Anfang und Ende des Sliders versuchen wir die Anzeige korrekt
286     // anzuzeigen
287     if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
288         nCalcThumbPos = 1;
289     if ( nCalcThumbPos &&
290          (nCalcThumbPos == mnThumbPixRange-1) &&
291          (mnThumbPos < mnMaxRange) )
292         nCalcThumbPos--;
293     return nCalcThumbPos+mnThumbPixOffset;
294 }
295 
296 // -----------------------------------------------------------------------
297 
298 void Slider::ImplCalc( sal_Bool bUpdate )
299 {
300     sal_Bool bInvalidateAll = sal_False;
301 
302     if ( mbCalcSize )
303     {
304         long nOldChannelPixOffset   = mnChannelPixOffset;
305         long nOldChannelPixRange    = mnChannelPixRange;
306         long nOldChannelPixTop      = mnChannelPixTop;
307         long nOldChannelPixBottom   = mnChannelPixBottom;
308         long nCalcWidth;
309         long nCalcHeight;
310 
311         maChannel1Rect.SetEmpty();
312         maChannel2Rect.SetEmpty();
313         maThumbRect.SetEmpty();
314 
315         Size aSize = GetOutputSizePixel();
316         if ( GetStyle() & WB_HORZ )
317         {
318             nCalcWidth          = aSize.Width();
319             nCalcHeight         = aSize.Height();
320             maThumbRect.Top()   = 0;
321             maThumbRect.Bottom()= aSize.Height()-1;
322         }
323         else
324         {
325             nCalcWidth          = aSize.Height();
326             nCalcHeight         = aSize.Width();
327             maThumbRect.Left()  = 0;
328             maThumbRect.Right() = aSize.Width()-1;
329         }
330 
331         if ( nCalcWidth >= SLIDER_THUMB_SIZE )
332         {
333             mnThumbPixOffset    = SLIDER_THUMB_HALFSIZE;
334             mnThumbPixRange     = nCalcWidth-(SLIDER_THUMB_HALFSIZE*2);
335             mnThumbPixPos       = 0;
336             mnChannelPixOffset  = SLIDER_CHANNEL_OFFSET;
337             mnChannelPixRange   = nCalcWidth-(SLIDER_CHANNEL_OFFSET*2);
338             mnChannelPixTop     = (nCalcHeight/2)-SLIDER_CHANNEL_HALFSIZE;
339             mnChannelPixBottom  = mnChannelPixTop+SLIDER_CHANNEL_SIZE-1;
340         }
341         else
342         {
343             mnThumbPixRange = 0;
344             mnChannelPixRange = 0;
345         }
346 
347         if ( (nOldChannelPixOffset != mnChannelPixOffset) ||
348              (nOldChannelPixRange != mnChannelPixRange) ||
349              (nOldChannelPixTop != mnChannelPixTop) ||
350              (nOldChannelPixBottom != mnChannelPixBottom) )
351             bInvalidateAll = sal_True;
352 
353         mbCalcSize = sal_False;
354     }
355 
356     if ( mnThumbPixRange )
357         mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
358 
359     if ( bUpdate && bInvalidateAll )
360     {
361         Invalidate();
362         bUpdate = sal_False;
363     }
364     ImplUpdateRects( bUpdate );
365 }
366 
367 // -----------------------------------------------------------------------
368 
369 void Slider::ImplDraw( sal_uInt16 nDrawFlags )
370 {
371     DecorationView          aDecoView( this );
372     sal_uInt16                  nStyle;
373     const StyleSettings&    rStyleSettings = GetSettings().GetStyleSettings();
374     sal_Bool                    bEnabled = IsEnabled();
375 
376     // Evt. noch offene Berechnungen nachholen
377     if ( mbCalcSize )
378         ImplCalc( sal_False );
379 
380     ControlPart nPart = (GetStyle() & WB_HORZ) ? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA;
381     ControlState   nState = ( IsEnabled() ? CTRL_STATE_ENABLED : 0 ) | ( HasFocus() ? CTRL_STATE_FOCUSED : 0 );
382     SliderValue    sldValue;
383 
384     sldValue.mnMin       = mnMinRange;
385     sldValue.mnMax       = mnMaxRange;
386     sldValue.mnCur       = mnThumbPos;
387     sldValue.maThumbRect = maThumbRect;
388 
389     if( IsMouseOver() )
390     {
391         if( maThumbRect.IsInside( GetPointerPosPixel() ) )
392             sldValue.mnThumbState |= CTRL_STATE_ROLLOVER;
393     }
394 
395     const Rectangle aCtrlRegion( Point(0,0), GetOutputSizePixel() );
396     bool bNativeOK = DrawNativeControl( CTRL_SLIDER, nPart,
397                                         aCtrlRegion, nState, sldValue, rtl::OUString() );
398     if( bNativeOK )
399         return;
400 
401     if ( (nDrawFlags & SLIDER_DRAW_CHANNEL1) && !maChannel1Rect.IsEmpty() )
402     {
403         long        nRectSize;
404         Rectangle   aRect = maChannel1Rect;
405         SetLineColor( rStyleSettings.GetShadowColor() );
406         if ( GetStyle() & WB_HORZ )
407         {
408             DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom()-1 ) );
409             DrawLine( aRect.TopLeft(), aRect.TopRight() );
410         }
411         else
412         {
413             DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) );
414             DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
415         }
416         SetLineColor( rStyleSettings.GetLightColor() );
417         if ( GetStyle() & WB_HORZ )
418         {
419             DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
420             nRectSize = aRect.GetWidth();
421         }
422         else
423         {
424             DrawLine( aRect.TopRight(), aRect.BottomRight() );
425             nRectSize = aRect.GetHeight();
426         }
427 
428         if ( nRectSize > 1 )
429         {
430             aRect.Left()++;
431             aRect.Top()++;
432             if ( GetStyle() & WB_HORZ )
433                 aRect.Bottom()--;
434             else
435                 aRect.Right()--;
436             SetLineColor();
437             if ( mnStateFlags & SLIDER_STATE_CHANNEL1_DOWN )
438                 SetFillColor( rStyleSettings.GetShadowColor() );
439             else
440                 SetFillColor( rStyleSettings.GetCheckedColor() );
441             DrawRect( aRect );
442         }
443     }
444 
445     if ( (nDrawFlags & SLIDER_DRAW_CHANNEL2) && !maChannel2Rect.IsEmpty() )
446     {
447         long        nRectSize;
448         Rectangle   aRect = maChannel2Rect;
449         SetLineColor( rStyleSettings.GetLightColor() );
450         if ( GetStyle() & WB_HORZ )
451         {
452             DrawLine( aRect.TopRight(), aRect.BottomRight() );
453             DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
454             nRectSize = aRect.GetWidth();
455         }
456         else
457         {
458             DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
459             DrawLine( aRect.TopRight(), aRect.BottomRight() );
460             nRectSize = aRect.GetHeight();
461         }
462 
463         if ( nRectSize > 1 )
464         {
465             SetLineColor( rStyleSettings.GetShadowColor() );
466             if ( GetStyle() & WB_HORZ )
467                 DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) );
468             else
469                 DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom()-1 ) );
470 
471             aRect.Right()--;
472             aRect.Bottom()--;
473             if ( GetStyle() & WB_HORZ )
474                 aRect.Top()++;
475             else
476                 aRect.Left()++;
477             SetLineColor();
478             if ( mnStateFlags & SLIDER_STATE_CHANNEL2_DOWN )
479                 SetFillColor( rStyleSettings.GetShadowColor() );
480             else
481                 SetFillColor( rStyleSettings.GetCheckedColor() );
482             DrawRect( aRect );
483         }
484     }
485 
486     if ( nDrawFlags & SLIDER_DRAW_THUMB )
487     {
488         if ( !maThumbRect.IsEmpty() )
489         {
490             if ( bEnabled )
491             {
492                 nStyle = 0;
493                 if ( mnStateFlags & SLIDER_STATE_THUMB_DOWN )
494                     nStyle |= BUTTON_DRAW_PRESSED;
495                 aDecoView.DrawButton( maThumbRect, nStyle );
496             }
497             else
498             {
499                 SetLineColor( rStyleSettings.GetShadowColor() );
500                 SetFillColor( rStyleSettings.GetCheckedColor() );
501                 DrawRect( maThumbRect );
502             }
503         }
504     }
505 }
506 
507 // -----------------------------------------------------------------------
508 
509 sal_Bool Slider::ImplIsPageUp( const Point& rPos )
510 {
511     Size aSize = GetOutputSizePixel();
512     Rectangle aRect = maChannel1Rect;
513     if ( GetStyle() & WB_HORZ )
514     {
515         aRect.Top()     = 0;
516         aRect.Bottom()  = aSize.Height()-1;
517     }
518     else
519     {
520         aRect.Left()    = 0;
521         aRect.Right()   = aSize.Width()-1;
522     }
523     return aRect.IsInside( rPos );
524 }
525 
526 // -----------------------------------------------------------------------
527 
528 sal_Bool Slider::ImplIsPageDown( const Point& rPos )
529 {
530     Size aSize = GetOutputSizePixel();
531     Rectangle aRect = maChannel2Rect;
532     if ( GetStyle() & WB_HORZ )
533     {
534         aRect.Top()     = 0;
535         aRect.Bottom()  = aSize.Height()-1;
536     }
537     else
538     {
539         aRect.Left()    = 0;
540         aRect.Right()   = aSize.Width()-1;
541     }
542     return aRect.IsInside( rPos );
543 }
544 
545 // -----------------------------------------------------------------------
546 
547 long Slider::ImplSlide( long nNewPos, sal_Bool bCallEndSlide )
548 {
549     long nOldPos = mnThumbPos;
550     SetThumbPos( nNewPos );
551     long nDelta = mnThumbPos-nOldPos;
552     if ( nDelta )
553     {
554         mnDelta = nDelta;
555         Slide();
556         if ( bCallEndSlide )
557             EndSlide();
558         mnDelta = 0;
559     }
560     return nDelta;
561 }
562 
563 // -----------------------------------------------------------------------
564 
565 long Slider::ImplDoAction( sal_Bool bCallEndSlide )
566 {
567     long nDelta = 0;
568 
569     switch ( meScrollType )
570     {
571         case SCROLL_LINEUP:
572             nDelta = ImplSlide( mnThumbPos-mnLineSize, bCallEndSlide );
573             break;
574 
575         case SCROLL_LINEDOWN:
576             nDelta = ImplSlide( mnThumbPos+mnLineSize, bCallEndSlide );
577             break;
578 
579         case SCROLL_PAGEUP:
580             nDelta = ImplSlide( mnThumbPos-mnPageSize, bCallEndSlide );
581             break;
582 
583         case SCROLL_PAGEDOWN:
584             nDelta = ImplSlide( mnThumbPos+mnPageSize, bCallEndSlide );
585             break;
586 
587         case SCROLL_SET:
588             nDelta = ImplSlide( ImplCalcThumbPos( GetPointerPosPixel().X() ), bCallEndSlide );
589             break;
590         default:
591             break;
592     }
593 
594     return nDelta;
595 }
596 
597 // -----------------------------------------------------------------------
598 
599 void Slider::ImplDoMouseAction( const Point& rMousePos, sal_Bool bCallAction )
600 {
601     sal_uInt16  nOldStateFlags = mnStateFlags;
602     sal_Bool    bAction = sal_False;
603 
604     switch ( meScrollType )
605     {
606         case( SCROLL_SET ):
607         {
608             const bool bUp = ImplIsPageUp( rMousePos ), bDown = ImplIsPageDown( rMousePos );
609 
610             if ( bUp || bDown )
611             {
612                 bAction = bCallAction;
613                 mnStateFlags |= ( bUp ? SLIDER_STATE_CHANNEL1_DOWN : SLIDER_STATE_CHANNEL2_DOWN );
614             }
615             else
616                 mnStateFlags &= ~( SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN );
617             break;
618         }
619 
620         case SCROLL_PAGEUP:
621             if ( ImplIsPageUp( rMousePos ) )
622             {
623                 bAction = bCallAction;
624                 mnStateFlags |= SLIDER_STATE_CHANNEL1_DOWN;
625             }
626             else
627                 mnStateFlags &= ~SLIDER_STATE_CHANNEL1_DOWN;
628             break;
629 
630         case SCROLL_PAGEDOWN:
631             if ( ImplIsPageDown( rMousePos ) )
632             {
633                 bAction = bCallAction;
634                 mnStateFlags |= SLIDER_STATE_CHANNEL2_DOWN;
635             }
636             else
637                 mnStateFlags &= ~SLIDER_STATE_CHANNEL2_DOWN;
638             break;
639         default:
640             break;
641     }
642 
643     if ( bAction )
644     {
645         if ( ImplDoAction( sal_False ) )
646         {
647             // Update the channel complete
648             if ( mnDragDraw & SLIDER_DRAW_CHANNEL )
649             {
650                 Update();
651                 ImplDraw( mnDragDraw );
652             }
653         }
654     }
655     else if ( nOldStateFlags != mnStateFlags )
656         ImplDraw( mnDragDraw );
657 }
658 
659 // -----------------------------------------------------------------------
660 
661 long Slider::ImplDoSlide( long nNewPos )
662 {
663     if ( meScrollType != SCROLL_DONTKNOW )
664         return 0;
665 
666     meScrollType = SCROLL_DRAG;
667     long nDelta = ImplSlide( nNewPos, sal_True );
668     meScrollType = SCROLL_DONTKNOW;
669     return nDelta;
670 }
671 
672 // -----------------------------------------------------------------------
673 
674 long Slider::ImplDoSlideAction( ScrollType eScrollType )
675 {
676     if ( (meScrollType != SCROLL_DONTKNOW) ||
677          (eScrollType == SCROLL_DONTKNOW) ||
678          (eScrollType == SCROLL_DRAG) )
679         return 0;
680 
681     meScrollType = eScrollType;
682     long nDelta = ImplDoAction( sal_True );
683     meScrollType = SCROLL_DONTKNOW;
684     return nDelta;
685 }
686 
687 // -----------------------------------------------------------------------
688 
689 void Slider::MouseButtonDown( const MouseEvent& rMEvt )
690 {
691     if ( rMEvt.IsLeft() )
692     {
693         const Point&    rMousePos = rMEvt.GetPosPixel();
694         sal_uInt16          nTrackFlags = 0;
695 
696         if ( maThumbRect.IsInside( rMousePos ) )
697         {
698             nTrackFlags     = 0;
699             meScrollType    = SCROLL_DRAG;
700             mnDragDraw      = SLIDER_DRAW_THUMB;
701 
702             // Zusaetzliche Daten berechnen
703             Point aCenterPos = maThumbRect.Center();
704             if ( GetStyle() & WB_HORZ )
705                 mnMouseOff = rMousePos.X()-aCenterPos.X();
706             else
707                 mnMouseOff = rMousePos.Y()-aCenterPos.Y();
708         }
709         else if ( ImplIsPageUp( rMousePos ) )
710         {
711             if( GetStyle() & WB_SLIDERSET )
712                 meScrollType = SCROLL_SET;
713             else
714             {
715                 nTrackFlags = STARTTRACK_BUTTONREPEAT;
716                 meScrollType = SCROLL_PAGEUP;
717             }
718 
719             mnDragDraw = SLIDER_DRAW_CHANNEL;
720         }
721         else if ( ImplIsPageDown( rMousePos ) )
722         {
723             if( GetStyle() & WB_SLIDERSET )
724                 meScrollType = SCROLL_SET;
725             else
726             {
727                 nTrackFlags = STARTTRACK_BUTTONREPEAT;
728                 meScrollType = SCROLL_PAGEDOWN;
729             }
730 
731             mnDragDraw = SLIDER_DRAW_CHANNEL;
732         }
733 
734         // Soll Tracking gestartet werden
735         if( meScrollType != SCROLL_DONTKNOW )
736         {
737             // Startposition merken fuer Abbruch und EndScroll-Delta
738             mnStartPos = mnThumbPos;
739             ImplDoMouseAction( rMousePos, meScrollType != SCROLL_SET );
740             Update();
741 
742             if( meScrollType != SCROLL_SET )
743                 StartTracking( nTrackFlags );
744         }
745     }
746 }
747 
748 // -----------------------------------------------------------------------
749 
750 void Slider::MouseButtonUp( const MouseEvent& )
751 {
752     if( SCROLL_SET == meScrollType )
753     {
754         // Button und PageRect-Status wieder herstellen
755         const sal_uInt16 nOldStateFlags = mnStateFlags;
756 
757         mnStateFlags &= ~( SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN | SLIDER_STATE_THUMB_DOWN );
758 
759         if ( nOldStateFlags != mnStateFlags )
760             ImplDraw( mnDragDraw );
761 
762         mnDragDraw = 0;
763         ImplDoAction( sal_True );
764         meScrollType = SCROLL_DONTKNOW;
765     }
766 }
767 
768 // -----------------------------------------------------------------------
769 
770 void Slider::Tracking( const TrackingEvent& rTEvt )
771 {
772     if ( rTEvt.IsTrackingEnded() )
773     {
774         // Button und PageRect-Status wieder herstellen
775         sal_uInt16 nOldStateFlags = mnStateFlags;
776         mnStateFlags &= ~(SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN |
777                           SLIDER_STATE_THUMB_DOWN);
778         if ( nOldStateFlags != mnStateFlags )
779             ImplDraw( mnDragDraw );
780         mnDragDraw = 0;
781 
782         // Bei Abbruch, die alte ThumbPosition wieder herstellen
783         if ( rTEvt.IsTrackingCanceled() )
784         {
785             long nOldPos = mnThumbPos;
786             SetThumbPos( mnStartPos );
787             mnDelta = mnThumbPos-nOldPos;
788             Slide();
789         }
790 
791         if ( meScrollType == SCROLL_DRAG )
792         {
793             // Wenn gedragt wurde, berechnen wir den Thumb neu, damit
794             // er wieder auf einer gerundeten ThumbPosition steht
795             ImplCalc();
796             Update();
797 
798             if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
799             {
800                 mnDelta = mnThumbPos-mnStartPos;
801                 Slide();
802                 mnDelta = 0;
803             }
804         }
805 
806         mnDelta = mnThumbPos-mnStartPos;
807         EndSlide();
808         mnDelta = 0;
809         meScrollType = SCROLL_DONTKNOW;
810     }
811     else
812     {
813         const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
814 
815         // Dragging wird speziell behandelt
816         if ( meScrollType == SCROLL_DRAG )
817         {
818             long nMovePix;
819             Point aCenterPos = maThumbRect.Center();
820             if ( GetStyle() & WB_HORZ )
821                 nMovePix = rMousePos.X()-(aCenterPos.X()+mnMouseOff);
822             else
823                 nMovePix = rMousePos.Y()-(aCenterPos.Y()+mnMouseOff);
824             // Nur wenn sich Maus in die Scrollrichtung bewegt, müssen
825             // wir etwas tun
826             if ( nMovePix )
827             {
828                 mnThumbPixPos += nMovePix;
829                 if ( mnThumbPixPos < mnThumbPixOffset )
830                     mnThumbPixPos = mnThumbPixOffset;
831                 if ( mnThumbPixPos > (mnThumbPixOffset+mnThumbPixRange-1) )
832                     mnThumbPixPos = mnThumbPixOffset+mnThumbPixRange-1;
833                 long nOldPos = mnThumbPos;
834                 mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
835                 if ( nOldPos != mnThumbPos )
836                 {
837                     ImplUpdateRects();
838                     Update();
839                     if ( mbFullDrag && (nOldPos != mnThumbPos) )
840                     {
841                         mnDelta = mnThumbPos-nOldPos;
842                         Slide();
843                         mnDelta = 0;
844                     }
845                 }
846             }
847         }
848         else
849             ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
850 
851         // Wenn Slider-Werte so umgesetzt wurden, dass es nichts
852         // mehr zum Tracking gibt, dann berechen wir hier ab
853         if ( !IsVisible() )
854             EndTracking();
855     }
856 }
857 
858 // -----------------------------------------------------------------------
859 
860 void Slider::KeyInput( const KeyEvent& rKEvt )
861 {
862     if ( !rKEvt.GetKeyCode().GetModifier() )
863     {
864         switch ( rKEvt.GetKeyCode().GetCode() )
865         {
866             case KEY_HOME:
867                 ImplDoSlide( GetRangeMin() );
868                 break;
869             case KEY_END:
870                 ImplDoSlide( GetRangeMax() );
871                 break;
872 
873             case KEY_LEFT:
874             case KEY_UP:
875                 ImplDoSlideAction( SCROLL_LINEUP );
876                 break;
877 
878             case KEY_RIGHT:
879             case KEY_DOWN:
880                 ImplDoSlideAction( SCROLL_LINEDOWN );
881                 break;
882 
883             case KEY_PAGEUP:
884                 ImplDoSlideAction( SCROLL_PAGEUP );
885                 break;
886 
887             case KEY_PAGEDOWN:
888                 ImplDoSlideAction( SCROLL_PAGEDOWN );
889                 break;
890 
891             default:
892                 Control::KeyInput( rKEvt );
893                 break;
894         }
895     }
896     else
897         Control::KeyInput( rKEvt );
898 }
899 
900 // -----------------------------------------------------------------------
901 
902 void Slider::Paint( const Rectangle& )
903 {
904     ImplDraw( SLIDER_DRAW_ALL );
905 }
906 
907 // -----------------------------------------------------------------------
908 
909 void Slider::Resize()
910 {
911     Control::Resize();
912     mbCalcSize = sal_True;
913     if ( IsReallyVisible() )
914         ImplCalc( sal_False );
915     Invalidate();
916 }
917 
918 // -----------------------------------------------------------------------
919 
920 void Slider::RequestHelp( const HelpEvent& rHEvt )
921 {
922     Control::RequestHelp( rHEvt );
923 }
924 
925 // -----------------------------------------------------------------------
926 
927 void Slider::StateChanged( StateChangedType nType )
928 {
929     Control::StateChanged( nType );
930 
931     if ( nType == STATE_CHANGE_INITSHOW )
932         ImplCalc( sal_False );
933     else if ( nType == STATE_CHANGE_DATA )
934     {
935         if ( IsReallyVisible() && IsUpdateMode() )
936             ImplCalc( sal_True );
937     }
938     else if ( nType == STATE_CHANGE_UPDATEMODE )
939     {
940         if ( IsReallyVisible() && IsUpdateMode() )
941         {
942             ImplCalc( sal_False );
943             Invalidate();
944         }
945     }
946     else if ( nType == STATE_CHANGE_ENABLE )
947     {
948         if ( IsReallyVisible() && IsUpdateMode() )
949             Invalidate();
950     }
951     else if ( nType == STATE_CHANGE_STYLE )
952     {
953         if ( IsReallyVisible() && IsUpdateMode() )
954         {
955             if ( (GetPrevStyle() & SLIDER_VIEW_STYLE) !=
956                  (GetStyle() & SLIDER_VIEW_STYLE) )
957             {
958                 mbCalcSize = sal_True;
959                 ImplCalc( sal_False );
960                 Invalidate();
961             }
962         }
963     }
964     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
965     {
966         ImplInitSettings();
967         Invalidate();
968     }
969 }
970 
971 // -----------------------------------------------------------------------
972 
973 void Slider::DataChanged( const DataChangedEvent& rDCEvt )
974 {
975     Control::DataChanged( rDCEvt );
976 
977     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
978          (rDCEvt.GetFlags() & SETTINGS_STYLE) )
979     {
980         ImplInitSettings();
981         Invalidate();
982     }
983 }
984 
985 // -----------------------------------------------------------------------
986 
987 void Slider::Slide()
988 {
989     maSlideHdl.Call( this );
990 }
991 
992 // -----------------------------------------------------------------------
993 
994 void Slider::EndSlide()
995 {
996     maEndSlideHdl.Call( this );
997 }
998 
999 // -----------------------------------------------------------------------
1000 
1001 void Slider::SetRangeMin( long nNewRange )
1002 {
1003     SetRange( Range( nNewRange, GetRangeMax() ) );
1004 }
1005 
1006 // -----------------------------------------------------------------------
1007 
1008 void Slider::SetRangeMax( long nNewRange )
1009 {
1010     SetRange( Range( GetRangeMin(), nNewRange ) );
1011 }
1012 
1013 // -----------------------------------------------------------------------
1014 
1015 void Slider::SetRange( const Range& rRange )
1016 {
1017     // Range einpassen
1018     Range aRange = rRange;
1019     aRange.Justify();
1020     long nNewMinRange = aRange.Min();
1021     long nNewMaxRange = aRange.Max();
1022 
1023     // Wenn Range sich unterscheidet, dann neuen setzen
1024     if ( (mnMinRange != nNewMinRange) ||
1025          (mnMaxRange != nNewMaxRange) )
1026     {
1027         mnMinRange = nNewMinRange;
1028         mnMaxRange = nNewMaxRange;
1029 
1030         // Thumb einpassen
1031         if ( mnThumbPos > mnMaxRange )
1032             mnThumbPos = mnMaxRange;
1033         if ( mnThumbPos < mnMinRange )
1034             mnThumbPos = mnMinRange;
1035 
1036         StateChanged( STATE_CHANGE_DATA );
1037     }
1038 }
1039 
1040 // -----------------------------------------------------------------------
1041 
1042 void Slider::SetThumbPos( long nNewThumbPos )
1043 {
1044     if ( nNewThumbPos < mnMinRange )
1045         nNewThumbPos = mnMinRange;
1046     if ( nNewThumbPos > mnMaxRange )
1047         nNewThumbPos = mnMaxRange;
1048 
1049     if ( mnThumbPos != nNewThumbPos )
1050     {
1051         mnThumbPos = nNewThumbPos;
1052         StateChanged( STATE_CHANGE_DATA );
1053     }
1054 }
1055 
1056 // -----------------------------------------------------------------------
1057 
1058 Size Slider::CalcWindowSizePixel()
1059 {
1060     long nWidth = mnMaxRange-mnMinRange+(SLIDER_THUMB_HALFSIZE*2)+1;
1061     long nHeight = SLIDER_HEIGHT;
1062     Size aSize;
1063     if ( GetStyle() & WB_HORZ )
1064     {
1065         aSize.Width()   = nWidth;
1066         aSize.Height()  = nHeight;
1067     }
1068     else
1069     {
1070         aSize.Height()  = nWidth;
1071         aSize.Width()   = nHeight;
1072     }
1073     return aSize;
1074 }
1075 
1076 /* vim: set noet sw=4 ts=4: */
1077