xref: /aoo41x/main/vcl/source/control/slider.cxx (revision cdf0e10c)
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