Update ooo320-m1
[ooovba.git] / vcl / source / control / scrbar.cxx
blob94a04558e6f21ad4f8034b6b5db72dd6618cb704
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scrbar.cxx,v $
10 * $Revision: 1.25 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include "vcl/event.hxx"
35 #include "vcl/sound.hxx"
36 #include "vcl/decoview.hxx"
37 #include "vcl/scrbar.hxx"
38 #include "vcl/timer.hxx"
39 #include "vcl/svdata.hxx"
41 #include "rtl/string.hxx"
42 #include "tools/rc.h"
46 using namespace rtl;
48 /* #i77549#
49 HACK: for scrollbars in case of thumb rect, page up and page down rect we
50 abuse the HitTestNativeControl interface. All theming engines but aqua
51 are actually able to draw the thumb according to our internal representation.
52 However aqua draws a little outside. The canonical way would be to enhance the
53 HitTestNativeControl passing a ScrollbarValue additionally so all necessary
54 information is available in the call.
56 However since there is only this one small exception we will deviate a little and
57 instead pass the respective rect as control region to allow for a small correction.
59 So all places using HitTestNativeControl on PART_THUMB_HORZ, PART_THUMB_VERT,
60 PART_TRACK_HORZ_LEFT, PART_TRACK_HORZ_RIGHT, PART_TRACK_VERT_UPPER, PART_TRACK_VERT_LOWER
61 do not use the control rectangle as region but the actuall part rectangle, making
62 only small deviations feasible.
66 // =======================================================================
68 static long ImplMulDiv( long nNumber, long nNumerator, long nDenominator )
70 double n = ((double)nNumber * (double)nNumerator) / (double)nDenominator;
71 return (long)n;
74 // =======================================================================
76 #define SCRBAR_DRAW_BTN1 ((USHORT)0x0001)
77 #define SCRBAR_DRAW_BTN2 ((USHORT)0x0002)
78 #define SCRBAR_DRAW_PAGE1 ((USHORT)0x0004)
79 #define SCRBAR_DRAW_PAGE2 ((USHORT)0x0008)
80 #define SCRBAR_DRAW_THUMB ((USHORT)0x0010)
81 #define SCRBAR_DRAW_BACKGROUND ((USHORT)0x0020)
82 #define SCRBAR_DRAW_ALL (SCRBAR_DRAW_BTN1 | SCRBAR_DRAW_BTN2 | \
83 SCRBAR_DRAW_PAGE1 | SCRBAR_DRAW_PAGE2 |\
84 SCRBAR_DRAW_THUMB | SCRBAR_DRAW_BACKGROUND )
86 #define SCRBAR_STATE_BTN1_DOWN ((USHORT)0x0001)
87 #define SCRBAR_STATE_BTN1_DISABLE ((USHORT)0x0002)
88 #define SCRBAR_STATE_BTN2_DOWN ((USHORT)0x0004)
89 #define SCRBAR_STATE_BTN2_DISABLE ((USHORT)0x0008)
90 #define SCRBAR_STATE_PAGE1_DOWN ((USHORT)0x0010)
91 #define SCRBAR_STATE_PAGE2_DOWN ((USHORT)0x0020)
92 #define SCRBAR_STATE_THUMB_DOWN ((USHORT)0x0040)
94 #define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
96 struct ImplScrollBarData
98 AutoTimer maTimer; // Timer
99 BOOL mbHide;
100 Rectangle maTrackRect; // TODO: move to ScrollBar class when binary incompatibility of ScrollBar class is no longer problematic
103 // =======================================================================
105 void ScrollBar::ImplInit( Window* pParent, WinBits nStyle )
107 mpData = NULL;
108 mnThumbPixRange = 0;
109 mnThumbPixPos = 0;
110 mnThumbPixSize = 0;
111 mnMinRange = 0;
112 mnMaxRange = 100;
113 mnThumbPos = 0;
114 mnVisibleSize = 0;
115 mnLineSize = 1;
116 mnPageSize = 1;
117 mnDelta = 0;
118 mnDragDraw = 0;
119 mnStateFlags = 0;
120 meScrollType = SCROLL_DONTKNOW;
121 meDDScrollType = SCROLL_DONTKNOW;
122 mbCalcSize = TRUE;
123 mbFullDrag = 0;
125 if( !mpData ) // TODO: remove when maTrackRect is no longer in mpData
127 mpData = new ImplScrollBarData;
128 mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
129 mpData->mbHide = FALSE;
132 ImplInitStyle( nStyle );
133 Control::ImplInit( pParent, nStyle, NULL );
135 long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
136 SetSizePixel( Size( nScrollSize, nScrollSize ) );
137 SetBackground();
140 // -----------------------------------------------------------------------
142 void ScrollBar::ImplInitStyle( WinBits nStyle )
144 if ( nStyle & WB_DRAG )
145 mbFullDrag = TRUE;
146 else
147 mbFullDrag = (GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SCROLL) != 0;
150 // -----------------------------------------------------------------------
152 ScrollBar::ScrollBar( Window* pParent, WinBits nStyle ) :
153 Control( WINDOW_SCROLLBAR )
155 ImplInit( pParent, nStyle );
158 // -----------------------------------------------------------------------
160 ScrollBar::ScrollBar( Window* pParent, const ResId& rResId ) :
161 Control( WINDOW_SCROLLBAR )
163 rResId.SetRT( RSC_SCROLLBAR );
164 WinBits nStyle = ImplInitRes( rResId );
165 ImplInit( pParent, nStyle );
166 ImplLoadRes( rResId );
168 if ( !(nStyle & WB_HIDE) )
169 Show();
172 // -----------------------------------------------------------------------
174 ScrollBar::~ScrollBar()
176 if( mpData )
177 delete mpData;
180 // -----------------------------------------------------------------------
182 void ScrollBar::ImplLoadRes( const ResId& rResId )
184 Control::ImplLoadRes( rResId );
186 INT16 nMin = ReadShortRes();
187 INT16 nMax = ReadShortRes();
188 INT16 nThumbPos = ReadShortRes();
189 INT16 nPage = ReadShortRes();
190 INT16 nStep = ReadShortRes();
191 INT16 nVisibleSize = ReadShortRes();
193 SetRange( Range( nMin, nMax ) );
194 SetLineSize( nStep );
195 SetPageSize( nPage );
196 SetVisibleSize( nVisibleSize );
197 SetThumbPos( nThumbPos );
200 // -----------------------------------------------------------------------
202 void ScrollBar::ImplUpdateRects( BOOL bUpdate )
204 USHORT nOldStateFlags = mnStateFlags;
205 Rectangle aOldPage1Rect = maPage1Rect;
206 Rectangle aOldPage2Rect = maPage2Rect;
207 Rectangle aOldThumbRect = maThumbRect;
209 mnStateFlags &= ~SCRBAR_STATE_BTN1_DISABLE;
210 mnStateFlags &= ~SCRBAR_STATE_BTN2_DISABLE;
212 Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
213 if ( mnThumbPixRange )
215 if ( GetStyle() & WB_HORZ )
217 maThumbRect.Left() = maTrackRect.Left()+mnThumbPixPos;
218 maThumbRect.Right() = maThumbRect.Left()+mnThumbPixSize-1;
219 if ( !mnThumbPixPos )
220 maPage1Rect.Right() = RECT_EMPTY;
221 else
222 maPage1Rect.Right() = maThumbRect.Left()-1;
223 if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
224 maPage2Rect.Right() = RECT_EMPTY;
225 else
227 maPage2Rect.Left() = maThumbRect.Right()+1;
228 maPage2Rect.Right() = maTrackRect.Right();
231 else
233 maThumbRect.Top() = maTrackRect.Top()+mnThumbPixPos;
234 maThumbRect.Bottom() = maThumbRect.Top()+mnThumbPixSize-1;
235 if ( !mnThumbPixPos )
236 maPage1Rect.Bottom() = RECT_EMPTY;
237 else
238 maPage1Rect.Bottom() = maThumbRect.Top()-1;
239 if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
240 maPage2Rect.Bottom() = RECT_EMPTY;
241 else
243 maPage2Rect.Top() = maThumbRect.Bottom()+1;
244 maPage2Rect.Bottom() = maTrackRect.Bottom();
248 else
250 Size aScrBarSize = GetOutputSizePixel();
251 if ( GetStyle() & WB_HORZ )
253 const long nSpace = maTrackRect.Right() - maTrackRect.Left();
254 if ( nSpace > 0 )
256 maPage1Rect.Left() = maTrackRect.Left();
257 maPage1Rect.Right() = maTrackRect.Left() + (nSpace/2);
258 maPage2Rect.Left() = maPage1Rect.Right() + 1;
259 maPage2Rect.Right() = maTrackRect.Right();
262 else
264 const long nSpace = maTrackRect.Bottom() - maTrackRect.Top();
265 if ( nSpace > 0 )
267 maPage1Rect.Top() = maTrackRect.Top();
268 maPage1Rect.Bottom() = maTrackRect.Top() + (nSpace/2);
269 maPage2Rect.Top() = maPage1Rect.Bottom() + 1;
270 maPage2Rect.Bottom() = maTrackRect.Bottom();
275 if( !IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
277 // disable scrollbar buttons only in VCL's own 'theme'
278 // as it is uncommon on other platforms
279 if ( mnThumbPos == mnMinRange )
280 mnStateFlags |= SCRBAR_STATE_BTN1_DISABLE;
281 if ( mnThumbPos >= (mnMaxRange-mnVisibleSize) )
282 mnStateFlags |= SCRBAR_STATE_BTN2_DISABLE;
285 if ( bUpdate )
287 USHORT nDraw = 0;
288 if ( (nOldStateFlags & SCRBAR_STATE_BTN1_DISABLE) !=
289 (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
290 nDraw |= SCRBAR_DRAW_BTN1;
291 if ( (nOldStateFlags & SCRBAR_STATE_BTN2_DISABLE) !=
292 (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
293 nDraw |= SCRBAR_DRAW_BTN2;
294 if ( aOldPage1Rect != maPage1Rect )
295 nDraw |= SCRBAR_DRAW_PAGE1;
296 if ( aOldPage2Rect != maPage2Rect )
297 nDraw |= SCRBAR_DRAW_PAGE2;
298 if ( aOldThumbRect != maThumbRect )
299 nDraw |= SCRBAR_DRAW_THUMB;
300 ImplDraw( nDraw, this );
304 // -----------------------------------------------------------------------
306 long ScrollBar::ImplCalcThumbPos( long nPixPos )
308 // Position berechnen
309 long nCalcThumbPos;
310 nCalcThumbPos = ImplMulDiv( nPixPos, mnMaxRange-mnVisibleSize-mnMinRange,
311 mnThumbPixRange-mnThumbPixSize );
312 nCalcThumbPos += mnMinRange;
313 return nCalcThumbPos;
316 // -----------------------------------------------------------------------
318 long ScrollBar::ImplCalcThumbPosPix( long nPos )
320 long nCalcThumbPos;
322 // Position berechnen
323 nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-mnThumbPixSize,
324 mnMaxRange-mnVisibleSize-mnMinRange );
326 // Am Anfang und Ende des ScrollBars versuchen wir die Anzeige korrekt
327 // anzuzeigen
328 if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
329 nCalcThumbPos = 1;
330 if ( nCalcThumbPos &&
331 ((nCalcThumbPos+mnThumbPixSize) >= mnThumbPixRange) &&
332 (mnThumbPos < (mnMaxRange-mnVisibleSize)) )
333 nCalcThumbPos--;
335 return nCalcThumbPos;
338 // -----------------------------------------------------------------------
340 void ScrollBar::ImplCalc( BOOL bUpdate )
342 const Size aSize = GetOutputSizePixel();
343 const long nMinThumbSize = GetSettings().GetStyleSettings().GetMinThumbSize();;
345 Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
346 if ( mbCalcSize )
348 const Region aControlRegion( Rectangle( (const Point&)Point(0,0), aSize ) );
349 Region aBtn1Region, aBtn2Region, aTrackRegion, aBoundingRegion;
351 if ( GetStyle() & WB_HORZ )
353 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_LEFT,
354 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) &&
355 GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_RIGHT,
356 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) )
358 maBtn1Rect = aBtn1Region.GetBoundRect();
359 maBtn2Rect = aBtn2Region.GetBoundRect();
361 else
363 Size aBtnSize( aSize.Height(), aSize.Height() );
364 maBtn2Rect.Top() = maBtn1Rect.Top();
365 maBtn2Rect.Left() = aSize.Width()-aSize.Height();
366 maBtn1Rect.SetSize( aBtnSize );
367 maBtn2Rect.SetSize( aBtnSize );
370 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_HORZ_AREA,
371 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) )
372 maTrackRect = aTrackRegion.GetBoundRect();
373 else
374 maTrackRect = Rectangle( maBtn1Rect.TopRight(), maBtn2Rect.BottomLeft() );
376 // Check if available space is big enough for thumb ( min thumb size = ScrBar width/height )
377 mnThumbPixRange = maTrackRect.Right() - maTrackRect.Left();
378 if( mnThumbPixRange > 0 )
380 maPage1Rect.Left() = maTrackRect.Left();
381 maPage1Rect.Bottom() =
382 maPage2Rect.Bottom() =
383 maThumbRect.Bottom() = maTrackRect.Bottom();
385 else
387 mnThumbPixRange = 0;
388 maPage1Rect.SetEmpty();
389 maPage2Rect.SetEmpty();
392 else
394 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_UP,
395 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) &&
396 GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_DOWN,
397 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) )
399 maBtn1Rect = aBtn1Region.GetBoundRect();
400 maBtn2Rect = aBtn2Region.GetBoundRect();
402 else
404 const Size aBtnSize( aSize.Width(), aSize.Width() );
405 maBtn2Rect.Left() = maBtn1Rect.Left();
406 maBtn2Rect.Top() = aSize.Height()-aSize.Width();
407 maBtn1Rect.SetSize( aBtnSize );
408 maBtn2Rect.SetSize( aBtnSize );
411 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_VERT_AREA,
412 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) )
413 maTrackRect = aTrackRegion.GetBoundRect();
414 else
415 maTrackRect = Rectangle( maBtn1Rect.BottomLeft()+Point(0,1), maBtn2Rect.TopRight() );
417 // Check if available space is big enough for thumb
418 mnThumbPixRange = maTrackRect.Bottom() - maTrackRect.Top();
419 if( mnThumbPixRange > 0 )
421 maPage1Rect.Top() = maTrackRect.Top();
422 maPage1Rect.Right() =
423 maPage2Rect.Right() =
424 maThumbRect.Right() = maTrackRect.Right();
426 else
428 mnThumbPixRange = 0;
429 maPage1Rect.SetEmpty();
430 maPage2Rect.SetEmpty();
434 if ( !mnThumbPixRange )
435 maThumbRect.SetEmpty();
437 mbCalcSize = FALSE;
440 if ( mnThumbPixRange )
442 // Werte berechnen
443 if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) ||
444 ((mnMaxRange-mnMinRange) <= 0) )
446 mnThumbPos = mnMinRange;
447 mnThumbPixPos = 0;
448 mnThumbPixSize = mnThumbPixRange;
450 else
452 if ( mnVisibleSize )
453 mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange );
454 else
456 if ( GetStyle() & WB_HORZ )
457 mnThumbPixSize = maThumbRect.GetWidth();
458 else
459 mnThumbPixSize = maThumbRect.GetHeight();
461 if ( mnThumbPixSize < nMinThumbSize )
462 mnThumbPixSize = nMinThumbSize;
463 if ( mnThumbPixSize > mnThumbPixRange )
464 mnThumbPixSize = mnThumbPixRange;
465 mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
469 // Wenn neu ausgegeben werden soll und wir schon ueber eine
470 // Aktion einen Paint-Event ausgeloest bekommen haben, dann
471 // geben wir nicht direkt aus, sondern invalidieren nur alles
472 if ( bUpdate && HasPaintEvent() )
474 Invalidate();
475 bUpdate = FALSE;
477 ImplUpdateRects( bUpdate );
480 // -----------------------------------------------------------------------
482 void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
484 Point aPos = pDev->LogicToPixel( rPos );
485 Size aSize = pDev->LogicToPixel( rSize );
486 Rectangle aRect( aPos, aSize );
488 pDev->Push();
489 pDev->SetMapMode();
490 if ( !(nFlags & WINDOW_DRAW_MONO) )
492 // DecoView uses the FaceColor...
493 AllSettings aSettings = pDev->GetSettings();
494 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
495 if ( IsControlBackground() )
496 aStyleSettings.SetFaceColor( GetControlBackground() );
497 else
498 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
500 aSettings.SetStyleSettings( aStyleSettings );
501 pDev->SetSettings( aSettings );
504 // for printing:
505 // -calculate the size of the rects
506 // -because this is zero-based add the correct offset
507 // -print
508 // -force recalculate
510 if ( mbCalcSize )
511 ImplCalc( FALSE );
513 maBtn1Rect+=aPos;
514 maBtn2Rect+=aPos;
515 maThumbRect+=aPos;
516 mpData->maTrackRect+=aPos; // TODO: update when maTrackRect is no longer in mpData
517 maPage1Rect+=aPos;
518 maPage2Rect+=aPos;
520 ImplDraw( SCRBAR_DRAW_ALL, pDev );
521 pDev->Pop();
523 mbCalcSize = TRUE;
526 // -----------------------------------------------------------------------
528 BOOL ScrollBar::ImplDrawNative( USHORT nDrawFlags )
530 ImplControlValue aControlValue( BUTTONVALUE_DONTKNOW, rtl::OUString(), 0 );
532 BOOL bNativeOK = IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL);
533 if( bNativeOK )
535 BOOL bHorz = (GetStyle() & WB_HORZ ? true : false);
537 // Draw the entire background if the control supports it
538 if( IsNativeControlSupported(CTRL_SCROLLBAR, bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT) )
540 ControlState nState = ( IsEnabled() ? CTRL_STATE_ENABLED : 0 ) | ( HasFocus() ? CTRL_STATE_FOCUSED : 0 );
541 ScrollbarValue scrValue;
543 scrValue.mnMin = mnMinRange;
544 scrValue.mnMax = mnMaxRange;
545 scrValue.mnCur = mnThumbPos;
546 scrValue.mnVisibleSize = mnVisibleSize;
547 scrValue.maThumbRect = maThumbRect;
548 scrValue.maButton1Rect = maBtn1Rect;
549 scrValue.maButton2Rect = maBtn2Rect;
550 scrValue.mnButton1State = ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0) |
551 ((!(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)) ? CTRL_STATE_ENABLED : 0);
552 scrValue.mnButton2State = ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0) |
553 ((!(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)) ? CTRL_STATE_ENABLED : 0);
554 scrValue.mnThumbState = nState | ((mnStateFlags & SCRBAR_STATE_THUMB_DOWN) ? CTRL_STATE_PRESSED : 0);
555 scrValue.mnPage1State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0);
556 scrValue.mnPage2State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0);
558 if( IsMouseOver() )
560 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
561 if( pRect )
563 if( pRect == &maThumbRect )
564 scrValue.mnThumbState |= CTRL_STATE_ROLLOVER;
565 else if( pRect == &maBtn1Rect )
566 scrValue.mnButton1State |= CTRL_STATE_ROLLOVER;
567 else if( pRect == &maBtn2Rect )
568 scrValue.mnButton2State |= CTRL_STATE_ROLLOVER;
569 else if( pRect == &maPage1Rect )
570 scrValue.mnPage1State |= CTRL_STATE_ROLLOVER;
571 else if( pRect == &maPage2Rect )
572 scrValue.mnPage2State |= CTRL_STATE_ROLLOVER;
576 aControlValue.setOptionalVal( (void *)(&scrValue) );
578 #if 1
579 Region aCtrlRegion;
580 aCtrlRegion.Union( maBtn1Rect );
581 aCtrlRegion.Union( maBtn2Rect );
582 aCtrlRegion.Union( maPage1Rect );
583 aCtrlRegion.Union( maPage2Rect );
584 aCtrlRegion.Union( maThumbRect );
585 #else
586 const Region aCtrlRegion( Rectangle( Point(0,0), GetOutputSizePixel() ) );
587 #endif
588 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT),
589 aCtrlRegion, nState, aControlValue, rtl::OUString() );
591 else
593 if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) || (nDrawFlags & SCRBAR_DRAW_PAGE2) )
595 sal_uInt32 part1 = bHorz ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER;
596 sal_uInt32 part2 = bHorz ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER;
597 Region aCtrlRegion1( maPage1Rect );
598 Region aCtrlRegion2( maPage2Rect );
599 ControlState nState1 = (IsEnabled() ? CTRL_STATE_ENABLED : 0) | (HasFocus() ? CTRL_STATE_FOCUSED : 0);
600 ControlState nState2 = nState1;
602 nState1 |= ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0);
603 nState2 |= ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0);
605 if( IsMouseOver() )
607 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
608 if( pRect )
610 if( pRect == &maPage1Rect )
611 nState1 |= CTRL_STATE_ROLLOVER;
612 else if( pRect == &maPage2Rect )
613 nState2 |= CTRL_STATE_ROLLOVER;
617 if ( nDrawFlags & SCRBAR_DRAW_PAGE1 )
618 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1,
619 aControlValue, rtl::OUString() );
621 if ( nDrawFlags & SCRBAR_DRAW_PAGE2 )
622 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
623 aControlValue, rtl::OUString() );
625 if ( (nDrawFlags & SCRBAR_DRAW_BTN1) || (nDrawFlags & SCRBAR_DRAW_BTN2) )
627 sal_uInt32 part1 = bHorz ? PART_BUTTON_LEFT : PART_BUTTON_UP;
628 sal_uInt32 part2 = bHorz ? PART_BUTTON_RIGHT : PART_BUTTON_DOWN;
629 Region aCtrlRegion1( maBtn1Rect );
630 Region aCtrlRegion2( maBtn2Rect );
631 ControlState nState1 = HasFocus() ? CTRL_STATE_FOCUSED : 0;
632 ControlState nState2 = nState1;
634 if ( !Window::IsEnabled() || !IsEnabled() )
635 nState1 = (nState2 &= ~CTRL_STATE_ENABLED);
636 else
637 nState1 = (nState2 |= CTRL_STATE_ENABLED);
639 nState1 |= ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0);
640 nState2 |= ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0);
642 if(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)
643 nState1 &= ~CTRL_STATE_ENABLED;
644 if(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)
645 nState2 &= ~CTRL_STATE_ENABLED;
647 if( IsMouseOver() )
649 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
650 if( pRect )
652 if( pRect == &maBtn1Rect )
653 nState1 |= CTRL_STATE_ROLLOVER;
654 else if( pRect == &maBtn2Rect )
655 nState2 |= CTRL_STATE_ROLLOVER;
659 if ( nDrawFlags & SCRBAR_DRAW_BTN1 )
660 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1,
661 aControlValue, rtl::OUString() );
663 if ( nDrawFlags & SCRBAR_DRAW_BTN2 )
664 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
665 aControlValue, rtl::OUString() );
667 if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && !maThumbRect.IsEmpty() )
669 ControlState nState = IsEnabled() ? CTRL_STATE_ENABLED : 0;
670 Region aCtrlRegion( maThumbRect );
672 if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN )
673 nState |= CTRL_STATE_PRESSED;
675 if ( HasFocus() )
676 nState |= CTRL_STATE_FOCUSED;
678 if( IsMouseOver() )
680 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
681 if( pRect )
683 if( pRect == &maThumbRect )
684 nState |= CTRL_STATE_ROLLOVER;
688 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_THUMB_HORZ : PART_THUMB_VERT),
689 aCtrlRegion, nState, aControlValue, rtl::OUString() );
693 return bNativeOK;
696 void ScrollBar::ImplDraw( USHORT nDrawFlags, OutputDevice* pOutDev )
698 DecorationView aDecoView( pOutDev );
699 Rectangle aTempRect;
700 USHORT nStyle;
701 const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
702 SymbolType eSymbolType;
703 BOOL bEnabled = IsEnabled();
705 // Evt. noch offene Berechnungen nachholen
706 if ( mbCalcSize )
707 ImplCalc( FALSE );
709 Window *pWin = NULL;
710 if( pOutDev->GetOutDevType() == OUTDEV_WINDOW )
711 pWin = (Window*) pOutDev;
713 // Draw the entire control if the native theme engine needs it
714 if ( nDrawFlags && pWin && pWin->IsNativeControlSupported(CTRL_SCROLLBAR, PART_DRAW_BACKGROUND_HORZ) )
716 ImplDrawNative( SCRBAR_DRAW_BACKGROUND );
717 return;
720 if( (nDrawFlags & SCRBAR_DRAW_BTN1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN1 ) ) )
722 nStyle = BUTTON_DRAW_NOLIGHTBORDER;
723 if ( mnStateFlags & SCRBAR_STATE_BTN1_DOWN )
724 nStyle |= BUTTON_DRAW_PRESSED;
725 aTempRect = aDecoView.DrawButton( maBtn1Rect, nStyle );
726 ImplCalcSymbolRect( aTempRect );
727 nStyle = 0;
728 if ( (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) || !bEnabled )
729 nStyle |= SYMBOL_DRAW_DISABLE;
730 if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
732 if ( GetStyle() & WB_HORZ )
733 eSymbolType = SYMBOL_ARROW_LEFT;
734 else
735 eSymbolType = SYMBOL_ARROW_UP;
737 else
739 if ( GetStyle() & WB_HORZ )
740 eSymbolType = SYMBOL_SPIN_LEFT;
741 else
742 eSymbolType = SYMBOL_SPIN_UP;
744 aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
747 if ( (nDrawFlags & SCRBAR_DRAW_BTN2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN2 ) ) )
749 nStyle = BUTTON_DRAW_NOLIGHTBORDER;
750 if ( mnStateFlags & SCRBAR_STATE_BTN2_DOWN )
751 nStyle |= BUTTON_DRAW_PRESSED;
752 aTempRect = aDecoView.DrawButton( maBtn2Rect, nStyle );
753 ImplCalcSymbolRect( aTempRect );
754 nStyle = 0;
755 if ( (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) || !bEnabled )
756 nStyle |= SYMBOL_DRAW_DISABLE;
757 if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
759 if ( GetStyle() & WB_HORZ )
760 eSymbolType = SYMBOL_ARROW_RIGHT;
761 else
762 eSymbolType = SYMBOL_ARROW_DOWN;
764 else
766 if ( GetStyle() & WB_HORZ )
767 eSymbolType = SYMBOL_SPIN_RIGHT;
768 else
769 eSymbolType = SYMBOL_SPIN_DOWN;
771 aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
774 pOutDev->SetLineColor();
776 if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_THUMB ) ) )
778 if ( !maThumbRect.IsEmpty() )
780 if ( bEnabled )
782 nStyle = BUTTON_DRAW_NOLIGHTBORDER;
783 // pressed thumbs only in OS2 style
784 if ( rStyleSettings.GetOptions() & STYLE_OPTION_OS2STYLE )
785 if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN )
786 nStyle |= BUTTON_DRAW_PRESSED;
787 aTempRect = aDecoView.DrawButton( maThumbRect, nStyle );
788 // OS2 style requires pattern on the thumb
789 if ( rStyleSettings.GetOptions() & STYLE_OPTION_OS2STYLE )
791 if ( GetStyle() & WB_HORZ )
793 if ( aTempRect.GetWidth() > 6 )
795 long nX = aTempRect.Center().X();
796 nX -= 6;
797 if ( nX < aTempRect.Left() )
798 nX = aTempRect.Left();
799 for ( int i = 0; i < 6; i++ )
801 if ( nX > aTempRect.Right()-1 )
802 break;
804 pOutDev->SetLineColor( rStyleSettings.GetButtonTextColor() );
805 pOutDev->DrawLine( Point( nX, aTempRect.Top()+1 ),
806 Point( nX, aTempRect.Bottom()-1 ) );
807 nX++;
808 pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
809 pOutDev->DrawLine( Point( nX, aTempRect.Top()+1 ),
810 Point( nX, aTempRect.Bottom()-1 ) );
811 nX++;
815 else
817 if ( aTempRect.GetHeight() > 6 )
819 long nY = aTempRect.Center().Y();
820 nY -= 6;
821 if ( nY < aTempRect.Top() )
822 nY = aTempRect.Top();
823 for ( int i = 0; i < 6; i++ )
825 if ( nY > aTempRect.Bottom()-1 )
826 break;
828 pOutDev->SetLineColor( rStyleSettings.GetButtonTextColor() );
829 pOutDev->DrawLine( Point( aTempRect.Left()+1, nY ),
830 Point( aTempRect.Right()-1, nY ) );
831 nY++;
832 pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
833 pOutDev->DrawLine( Point( aTempRect.Left()+1, nY ),
834 Point( aTempRect.Right()-1, nY ) );
835 nY++;
839 pOutDev->SetLineColor();
842 else
844 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
845 pOutDev->DrawRect( maThumbRect );
850 if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE1 ) ) )
852 if ( mnStateFlags & SCRBAR_STATE_PAGE1_DOWN )
853 pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
854 else
855 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
856 pOutDev->DrawRect( maPage1Rect );
858 if ( (nDrawFlags & SCRBAR_DRAW_PAGE2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE2 ) ) )
860 if ( mnStateFlags & SCRBAR_STATE_PAGE2_DOWN )
861 pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
862 else
863 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
864 pOutDev->DrawRect( maPage2Rect );
868 // -----------------------------------------------------------------------
870 long ScrollBar::ImplScroll( long nNewPos, BOOL bCallEndScroll )
872 long nOldPos = mnThumbPos;
873 SetThumbPos( nNewPos );
874 long nDelta = mnThumbPos-nOldPos;
875 if ( nDelta )
877 mnDelta = nDelta;
878 Scroll();
879 if ( bCallEndScroll )
880 EndScroll();
881 mnDelta = 0;
883 return nDelta;
886 // -----------------------------------------------------------------------
888 long ScrollBar::ImplDoAction( BOOL bCallEndScroll )
890 long nDelta = 0;
892 switch ( meScrollType )
894 case SCROLL_LINEUP:
895 nDelta = ImplScroll( mnThumbPos-mnLineSize, bCallEndScroll );
896 break;
898 case SCROLL_LINEDOWN:
899 nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll );
900 break;
902 case SCROLL_PAGEUP:
903 nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll );
904 break;
906 case SCROLL_PAGEDOWN:
907 nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll );
908 break;
909 default:
913 return nDelta;
916 // -----------------------------------------------------------------------
918 void ScrollBar::ImplDoMouseAction( const Point& rMousePos, BOOL bCallAction )
920 USHORT nOldStateFlags = mnStateFlags;
921 BOOL bAction = FALSE;
922 BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
923 BOOL bIsInside = FALSE;
925 Point aPoint( 0, 0 );
926 Region aControlRegion( Rectangle( aPoint, GetOutputSizePixel() ) );
928 switch ( meScrollType )
930 case SCROLL_LINEUP:
931 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
932 aControlRegion, rMousePos, bIsInside )?
933 bIsInside:
934 maBtn1Rect.IsInside( rMousePos ) )
936 bAction = bCallAction;
937 mnStateFlags |= SCRBAR_STATE_BTN1_DOWN;
939 else
940 mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN;
941 break;
943 case SCROLL_LINEDOWN:
944 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
945 aControlRegion, rMousePos, bIsInside )?
946 bIsInside:
947 maBtn2Rect.IsInside( rMousePos ) )
949 bAction = bCallAction;
950 mnStateFlags |= SCRBAR_STATE_BTN2_DOWN;
952 else
953 mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN;
954 break;
956 case SCROLL_PAGEUP:
957 // HitTestNativeControl, see remark at top of file
958 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT: PART_TRACK_VERT_UPPER,
959 Region( maPage1Rect ), rMousePos, bIsInside )?
960 bIsInside:
961 maPage1Rect.IsInside( rMousePos ) )
963 bAction = bCallAction;
964 mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN;
966 else
967 mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN;
968 break;
970 case SCROLL_PAGEDOWN:
971 // HitTestNativeControl, see remark at top of file
972 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_RIGHT: PART_TRACK_VERT_LOWER,
973 Region( maPage2Rect ), rMousePos, bIsInside )?
974 bIsInside:
975 maPage2Rect.IsInside( rMousePos ) )
977 bAction = bCallAction;
978 mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
980 else
981 mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
982 break;
983 default:
987 if ( nOldStateFlags != mnStateFlags )
988 ImplDraw( mnDragDraw, this );
989 if ( bAction )
990 ImplDoAction( FALSE );
993 // -----------------------------------------------------------------------
995 void ScrollBar::ImplDragThumb( const Point& rMousePos )
997 long nMovePix;
998 if ( GetStyle() & WB_HORZ )
999 nMovePix = rMousePos.X()-(maThumbRect.Left()+mnMouseOff);
1000 else
1001 nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff);
1003 // move thumb if necessary
1004 if ( nMovePix )
1006 mnThumbPixPos += nMovePix;
1007 if ( mnThumbPixPos < 0 )
1008 mnThumbPixPos = 0;
1009 if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) )
1010 mnThumbPixPos = mnThumbPixRange-mnThumbPixSize;
1011 long nOldPos = mnThumbPos;
1012 mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
1013 ImplUpdateRects();
1014 if ( mbFullDrag && (nOldPos != mnThumbPos) )
1016 mnDelta = mnThumbPos-nOldPos;
1017 Scroll();
1018 mnDelta = 0;
1023 // -----------------------------------------------------------------------
1025 void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
1027 if ( rMEvt.IsLeft() || rMEvt.IsMiddle() )
1029 const Point& rMousePos = rMEvt.GetPosPixel();
1030 USHORT nTrackFlags = 0;
1031 BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
1032 BOOL bIsInside = FALSE;
1033 BOOL bDragToMouse = FALSE;
1035 Point aPoint( 0, 0 );
1036 Region aControlRegion( Rectangle( aPoint, GetOutputSizePixel() ) );
1038 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
1039 aControlRegion, rMousePos, bIsInside )?
1040 bIsInside:
1041 maBtn1Rect.IsInside( rMousePos ) )
1043 if ( !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
1045 nTrackFlags = STARTTRACK_BUTTONREPEAT;
1046 meScrollType = SCROLL_LINEUP;
1047 mnDragDraw = SCRBAR_DRAW_BTN1;
1049 else
1050 Sound::Beep( SOUND_DISABLE, this );
1052 else if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
1053 aControlRegion, rMousePos, bIsInside )?
1054 bIsInside:
1055 maBtn2Rect.IsInside( rMousePos ) )
1057 if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
1059 nTrackFlags = STARTTRACK_BUTTONREPEAT;
1060 meScrollType = SCROLL_LINEDOWN;
1061 mnDragDraw = SCRBAR_DRAW_BTN2;
1063 else
1064 Sound::Beep( SOUND_DISABLE, this );
1066 else
1068 bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT,
1069 Region( maThumbRect ), rMousePos, bIsInside )
1070 ? bIsInside : maThumbRect.IsInside( rMousePos );
1071 bool bDragHandling = rMEvt.IsMiddle() || bThumbHit || ImplGetSVData()->maNWFData.mbScrollbarJumpPage;
1072 if( bDragHandling )
1074 if( mpData )
1076 mpData->mbHide = TRUE; // disable focus blinking
1077 if( HasFocus() )
1078 ImplDraw( SCRBAR_DRAW_THUMB, this ); // paint without focus
1081 if ( mnVisibleSize < mnMaxRange-mnMinRange )
1083 nTrackFlags = 0;
1084 meScrollType = SCROLL_DRAG;
1085 mnDragDraw = SCRBAR_DRAW_THUMB;
1087 // calculate mouse offset
1088 if( rMEvt.IsMiddle() || (ImplGetSVData()->maNWFData.mbScrollbarJumpPage && !bThumbHit) )
1090 bDragToMouse = TRUE;
1091 if ( GetStyle() & WB_HORZ )
1092 mnMouseOff = maThumbRect.GetWidth()/2;
1093 else
1094 mnMouseOff = maThumbRect.GetHeight()/2;
1096 else
1098 if ( GetStyle() & WB_HORZ )
1099 mnMouseOff = rMousePos.X()-maThumbRect.Left();
1100 else
1101 mnMouseOff = rMousePos.Y()-maThumbRect.Top();
1104 mnStateFlags |= SCRBAR_STATE_THUMB_DOWN;
1105 ImplDraw( mnDragDraw, this );
1107 else
1108 Sound::Beep( SOUND_DISABLE, this );
1110 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA,
1111 aControlRegion, rMousePos, bIsInside )?
1112 bIsInside : TRUE )
1114 nTrackFlags = STARTTRACK_BUTTONREPEAT;
1116 // HitTestNativeControl, see remark at top of file
1117 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
1118 Region( maPage1Rect ), rMousePos, bIsInside )?
1119 bIsInside:
1120 maPage1Rect.IsInside( rMousePos ) )
1122 meScrollType = SCROLL_PAGEUP;
1123 mnDragDraw = SCRBAR_DRAW_PAGE1;
1125 else
1127 meScrollType = SCROLL_PAGEDOWN;
1128 mnDragDraw = SCRBAR_DRAW_PAGE2;
1133 // Soll Tracking gestartet werden
1134 if ( meScrollType != SCROLL_DONTKNOW )
1136 // remember original position in case of abort or EndScroll-Delta
1137 mnStartPos = mnThumbPos;
1138 // #92906# Call StartTracking() before ImplDoMouseAction(), otherwise
1139 // MouseButtonUp() / EndTracking() may be called if somebody is spending
1140 // a lot of time in the scroll handler
1141 StartTracking( nTrackFlags );
1142 ImplDoMouseAction( rMousePos );
1144 if( bDragToMouse )
1145 ImplDragThumb( rMousePos );
1150 // -----------------------------------------------------------------------
1152 void ScrollBar::Tracking( const TrackingEvent& rTEvt )
1154 if ( rTEvt.IsTrackingEnded() )
1156 // Button und PageRect-Status wieder herstellen
1157 USHORT nOldStateFlags = mnStateFlags;
1158 mnStateFlags &= ~(SCRBAR_STATE_BTN1_DOWN | SCRBAR_STATE_BTN2_DOWN |
1159 SCRBAR_STATE_PAGE1_DOWN | SCRBAR_STATE_PAGE2_DOWN |
1160 SCRBAR_STATE_THUMB_DOWN);
1161 if ( nOldStateFlags != mnStateFlags )
1162 ImplDraw( mnDragDraw, this );
1163 mnDragDraw = 0;
1165 // Bei Abbruch, die alte ThumbPosition wieder herstellen
1166 if ( rTEvt.IsTrackingCanceled() )
1168 long nOldPos = mnThumbPos;
1169 SetThumbPos( mnStartPos );
1170 mnDelta = mnThumbPos-nOldPos;
1171 Scroll();
1174 if ( meScrollType == SCROLL_DRAG )
1176 // Wenn gedragt wurde, berechnen wir den Thumb neu, damit
1177 // er wieder auf einer gerundeten ThumbPosition steht
1178 ImplCalc();
1180 if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
1182 mnDelta = mnThumbPos-mnStartPos;
1183 Scroll();
1184 mnDelta = 0;
1188 mnDelta = mnThumbPos-mnStartPos;
1189 EndScroll();
1190 mnDelta = 0;
1191 meScrollType = SCROLL_DONTKNOW;
1193 if( mpData )
1194 mpData->mbHide = FALSE; // re-enable focus blinking
1196 else
1198 const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1200 // Dragging wird speziell behandelt
1201 if ( meScrollType == SCROLL_DRAG )
1202 ImplDragThumb( rMousePos );
1203 else
1204 ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
1206 // Wenn ScrollBar-Werte so umgesetzt wurden, das es nichts
1207 // mehr zum Tracking gibt, dann berechen wir hier ab
1208 if ( !IsVisible() || (mnVisibleSize >= (mnMaxRange-mnMinRange)) )
1209 EndTracking();
1213 // -----------------------------------------------------------------------
1215 void ScrollBar::KeyInput( const KeyEvent& rKEvt )
1217 if ( !rKEvt.GetKeyCode().GetModifier() )
1219 switch ( rKEvt.GetKeyCode().GetCode() )
1221 case KEY_HOME:
1222 DoScroll( 0 );
1223 break;
1225 case KEY_END:
1226 DoScroll( GetRangeMax() );
1227 break;
1229 case KEY_LEFT:
1230 case KEY_UP:
1231 DoScrollAction( SCROLL_LINEUP );
1232 break;
1234 case KEY_RIGHT:
1235 case KEY_DOWN:
1236 DoScrollAction( SCROLL_LINEDOWN );
1237 break;
1239 case KEY_PAGEUP:
1240 DoScrollAction( SCROLL_PAGEUP );
1241 break;
1243 case KEY_PAGEDOWN:
1244 DoScrollAction( SCROLL_PAGEDOWN );
1245 break;
1247 default:
1248 Control::KeyInput( rKEvt );
1249 break;
1252 else
1253 Control::KeyInput( rKEvt );
1256 // -----------------------------------------------------------------------
1258 void ScrollBar::Paint( const Rectangle& )
1260 ImplDraw( SCRBAR_DRAW_ALL, this );
1263 // -----------------------------------------------------------------------
1265 void ScrollBar::Resize()
1267 Control::Resize();
1268 mbCalcSize = TRUE;
1269 if ( IsReallyVisible() )
1270 ImplCalc( FALSE );
1271 Invalidate();
1274 // -----------------------------------------------------------------------
1276 IMPL_LINK( ScrollBar, ImplAutoTimerHdl, AutoTimer*, EMPTYARG )
1278 if( mpData && mpData->mbHide )
1279 return 0;
1280 ImplInvert();
1281 return 0;
1284 void ScrollBar::ImplInvert()
1286 Rectangle aRect( maThumbRect );
1287 if( aRect.getWidth() > 4 )
1289 aRect.Left() += 2;
1290 aRect.Right() -= 2;
1292 if( aRect.getHeight() > 4 )
1294 aRect.Top() += 2;
1295 aRect.Bottom() -= 2;
1298 Invert( aRect, 0 );
1301 // -----------------------------------------------------------------------
1303 void ScrollBar::GetFocus()
1305 if( !mpData )
1307 mpData = new ImplScrollBarData;
1308 mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
1309 mpData->mbHide = FALSE;
1311 ImplInvert(); // react immediately
1312 mpData->maTimer.SetTimeout( GetSettings().GetStyleSettings().GetCursorBlinkTime() );
1313 mpData->maTimer.Start();
1314 Control::GetFocus();
1317 // -----------------------------------------------------------------------
1319 void ScrollBar::LoseFocus()
1321 if( mpData )
1322 mpData->maTimer.Stop();
1323 ImplDraw( SCRBAR_DRAW_THUMB, this );
1325 Control::LoseFocus();
1328 // -----------------------------------------------------------------------
1330 void ScrollBar::StateChanged( StateChangedType nType )
1332 Control::StateChanged( nType );
1334 if ( nType == STATE_CHANGE_INITSHOW )
1335 ImplCalc( FALSE );
1336 else if ( nType == STATE_CHANGE_DATA )
1338 if ( IsReallyVisible() && IsUpdateMode() )
1339 ImplCalc( TRUE );
1341 else if ( nType == STATE_CHANGE_UPDATEMODE )
1343 if ( IsReallyVisible() && IsUpdateMode() )
1345 ImplCalc( FALSE );
1346 Invalidate();
1349 else if ( nType == STATE_CHANGE_ENABLE )
1351 if ( IsReallyVisible() && IsUpdateMode() )
1352 Invalidate();
1354 else if ( nType == STATE_CHANGE_STYLE )
1356 ImplInitStyle( GetStyle() );
1357 if ( IsReallyVisible() && IsUpdateMode() )
1359 if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) !=
1360 (GetStyle() & SCRBAR_VIEW_STYLE) )
1362 mbCalcSize = TRUE;
1363 ImplCalc( FALSE );
1364 Invalidate();
1370 // -----------------------------------------------------------------------
1372 void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt )
1374 Control::DataChanged( rDCEvt );
1376 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1377 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1379 mbCalcSize = TRUE;
1380 ImplCalc( FALSE );
1381 Invalidate();
1385 // -----------------------------------------------------------------------
1387 Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt )
1389 BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
1390 BOOL bIsInside = FALSE;
1392 Point aPoint( 0, 0 );
1393 Region aControlRegion( Rectangle( aPoint, GetOutputSizePixel() ) );
1395 if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
1396 aControlRegion, rPt, bIsInside )?
1397 bIsInside:
1398 maBtn1Rect.IsInside( rPt ) )
1399 return &maBtn1Rect;
1400 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
1401 aControlRegion, rPt, bIsInside )?
1402 bIsInside:
1403 maBtn2Rect.IsInside( rPt ) )
1404 return &maBtn2Rect;
1405 // HitTestNativeControl, see remark at top of file
1406 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
1407 Region( maPage1Rect ), rPt, bIsInside)?
1408 bIsInside:
1409 maPage1Rect.IsInside( rPt ) )
1410 return &maPage1Rect;
1411 // HitTestNativeControl, see remark at top of file
1412 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER,
1413 Region( maPage2Rect ), rPt, bIsInside)?
1414 bIsInside:
1415 maPage2Rect.IsInside( rPt ) )
1416 return &maPage2Rect;
1417 // HitTestNativeControl, see remark at top of file
1418 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_THUMB_HORZ : PART_THUMB_VERT,
1419 Region( maThumbRect ), rPt, bIsInside)?
1420 bIsInside:
1421 maThumbRect.IsInside( rPt ) )
1422 return &maThumbRect;
1423 else
1424 return NULL;
1427 long ScrollBar::PreNotify( NotifyEvent& rNEvt )
1429 long nDone = 0;
1430 const MouseEvent* pMouseEvt = NULL;
1432 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
1434 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
1436 // trigger redraw if mouse over state has changed
1437 if( IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
1439 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
1440 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
1441 if( pRect != pLastRect || pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
1443 Region aRgn( GetActiveClipRegion() );
1444 Region aClipRegion;
1446 if ( pRect )
1447 aClipRegion.Union( *pRect );
1448 if ( pLastRect )
1449 aClipRegion.Union( *pLastRect );
1451 // Support for 3-button scroll bars
1452 BOOL bHas3Buttons = IsNativeControlSupported( CTRL_SCROLLBAR, HAS_THREE_BUTTONS );
1453 if ( bHas3Buttons && ( pRect == &maBtn1Rect || pLastRect == &maBtn1Rect ) )
1455 aClipRegion.Union( maBtn2Rect );
1458 SetClipRegion( aClipRegion );
1459 Paint( aClipRegion.GetBoundRect() );
1461 SetClipRegion( aRgn );
1467 return nDone ? nDone : Control::PreNotify(rNEvt);
1470 // -----------------------------------------------------------------------
1472 void ScrollBar::Scroll()
1474 ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_SCROLL, maScrollHdl, this );
1477 // -----------------------------------------------------------------------
1479 void ScrollBar::EndScroll()
1481 ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_ENDSCROLL, maEndScrollHdl, this );
1484 // -----------------------------------------------------------------------
1486 long ScrollBar::DoScroll( long nNewPos )
1488 if ( meScrollType != SCROLL_DONTKNOW )
1489 return 0;
1491 meScrollType = SCROLL_DRAG;
1492 long nDelta = ImplScroll( nNewPos, TRUE );
1493 meScrollType = SCROLL_DONTKNOW;
1494 return nDelta;
1497 // -----------------------------------------------------------------------
1499 long ScrollBar::DoScrollAction( ScrollType eScrollType )
1501 if ( (meScrollType != SCROLL_DONTKNOW) ||
1502 (eScrollType == SCROLL_DONTKNOW) ||
1503 (eScrollType == SCROLL_DRAG) )
1504 return 0;
1506 meScrollType = eScrollType;
1507 long nDelta = ImplDoAction( TRUE );
1508 meScrollType = SCROLL_DONTKNOW;
1509 return nDelta;
1512 // -----------------------------------------------------------------------
1514 void ScrollBar::SetRangeMin( long nNewRange )
1516 SetRange( Range( nNewRange, GetRangeMax() ) );
1519 // -----------------------------------------------------------------------
1521 void ScrollBar::SetRangeMax( long nNewRange )
1523 SetRange( Range( GetRangeMin(), nNewRange ) );
1526 // -----------------------------------------------------------------------
1528 void ScrollBar::SetRange( const Range& rRange )
1530 // Range einpassen
1531 Range aRange = rRange;
1532 aRange.Justify();
1533 long nNewMinRange = aRange.Min();
1534 long nNewMaxRange = aRange.Max();
1536 // Wenn Range sich unterscheidet, dann neuen setzen
1537 if ( (mnMinRange != nNewMinRange) ||
1538 (mnMaxRange != nNewMaxRange) )
1540 mnMinRange = nNewMinRange;
1541 mnMaxRange = nNewMaxRange;
1543 // Thumb einpassen
1544 if ( mnThumbPos > mnMaxRange-mnVisibleSize )
1545 mnThumbPos = mnMaxRange-mnVisibleSize;
1546 if ( mnThumbPos < mnMinRange )
1547 mnThumbPos = mnMinRange;
1549 StateChanged( STATE_CHANGE_DATA );
1553 // -----------------------------------------------------------------------
1555 void ScrollBar::SetThumbPos( long nNewThumbPos )
1557 if ( nNewThumbPos > mnMaxRange-mnVisibleSize )
1558 nNewThumbPos = mnMaxRange-mnVisibleSize;
1559 if ( nNewThumbPos < mnMinRange )
1560 nNewThumbPos = mnMinRange;
1562 if ( mnThumbPos != nNewThumbPos )
1564 mnThumbPos = nNewThumbPos;
1565 StateChanged( STATE_CHANGE_DATA );
1569 // -----------------------------------------------------------------------
1571 void ScrollBar::SetVisibleSize( long nNewSize )
1573 if ( mnVisibleSize != nNewSize )
1575 mnVisibleSize = nNewSize;
1577 // Thumb einpassen
1578 if ( mnThumbPos > mnMaxRange-mnVisibleSize )
1579 mnThumbPos = mnMaxRange-mnVisibleSize;
1580 if ( mnThumbPos < mnMinRange )
1581 mnThumbPos = mnMinRange;
1582 StateChanged( STATE_CHANGE_DATA );
1586 // =======================================================================
1588 void ScrollBarBox::ImplInit( Window* pParent, WinBits nStyle )
1590 Window::ImplInit( pParent, nStyle, NULL );
1592 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1593 long nScrollSize = rStyleSettings.GetScrollBarSize();
1594 SetSizePixel( Size( nScrollSize, nScrollSize ) );
1595 ImplInitSettings();
1598 // -----------------------------------------------------------------------
1600 ScrollBarBox::ScrollBarBox( Window* pParent, WinBits nStyle ) :
1601 Window( WINDOW_SCROLLBARBOX )
1603 ImplInit( pParent, nStyle );
1606 // -----------------------------------------------------------------------
1608 ScrollBarBox::ScrollBarBox( Window* pParent, const ResId& rResId ) :
1609 Window( WINDOW_SCROLLBARBOX )
1611 rResId.SetRT( RSC_SCROLLBAR );
1612 ImplInit( pParent, ImplInitRes( rResId ) );
1613 ImplLoadRes( rResId );
1616 // -----------------------------------------------------------------------
1618 void ScrollBarBox::ImplInitSettings()
1620 // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann
1621 // und noch nicht alles umgestellt ist
1622 if ( IsBackground() )
1624 Color aColor;
1625 if ( IsControlBackground() )
1626 aColor = GetControlBackground();
1627 else
1628 aColor = GetSettings().GetStyleSettings().GetFaceColor();
1629 SetBackground( aColor );
1633 // -----------------------------------------------------------------------
1635 void ScrollBarBox::StateChanged( StateChangedType nType )
1637 Window::StateChanged( nType );
1639 if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1641 ImplInitSettings();
1642 Invalidate();
1646 // -----------------------------------------------------------------------
1648 void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt )
1650 Window::DataChanged( rDCEvt );
1652 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1653 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1655 ImplInitSettings();
1656 Invalidate();