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