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