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