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 #include "vcl/event.hxx"
28 #include "vcl/sound.hxx"
29 #include "vcl/decoview.hxx"
30 #include "vcl/scrbar.hxx"
31 #include "vcl/timer.hxx"
32
33 #include "svdata.hxx"
34
35 #include "rtl/string.hxx"
36 #include "tools/rc.h"
37
38
39
40 using namespace rtl;
41
42 /* #i77549#
43 HACK: for scrollbars in case of thumb rect, page up and page down rect we
44 abuse the HitTestNativeControl interface. All theming engines but aqua
45 are actually able to draw the thumb according to our internal representation.
46 However aqua draws a little outside. The canonical way would be to enhance the
47 HitTestNativeControl passing a ScrollbarValue additionally so all necessary
48 information is available in the call.
49 .
50 However since there is only this one small exception we will deviate a little and
51 instead pass the respective rect as control region to allow for a small correction.
52
53 So all places using HitTestNativeControl on PART_THUMB_HORZ, PART_THUMB_VERT,
54 PART_TRACK_HORZ_LEFT, PART_TRACK_HORZ_RIGHT, PART_TRACK_VERT_UPPER, PART_TRACK_VERT_LOWER
55 do not use the control rectangle as region but the actuall part rectangle, making
56 only small deviations feasible.
57 */
58
59
60 // =======================================================================
61
ImplMulDiv(long nNumber,long nNumerator,long nDenominator)62 static long ImplMulDiv( long nNumber, long nNumerator, long nDenominator )
63 {
64 double n = ((double)nNumber * (double)nNumerator) / (double)nDenominator;
65 return (long)n;
66 }
67
68 // =======================================================================
69
70 #define SCRBAR_DRAW_BTN1 ((sal_uInt16)0x0001)
71 #define SCRBAR_DRAW_BTN2 ((sal_uInt16)0x0002)
72 #define SCRBAR_DRAW_PAGE1 ((sal_uInt16)0x0004)
73 #define SCRBAR_DRAW_PAGE2 ((sal_uInt16)0x0008)
74 #define SCRBAR_DRAW_THUMB ((sal_uInt16)0x0010)
75 #define SCRBAR_DRAW_BACKGROUND ((sal_uInt16)0x0020)
76 #define SCRBAR_DRAW_ALL (SCRBAR_DRAW_BTN1 | SCRBAR_DRAW_BTN2 | \
77 SCRBAR_DRAW_PAGE1 | SCRBAR_DRAW_PAGE2 |\
78 SCRBAR_DRAW_THUMB | SCRBAR_DRAW_BACKGROUND )
79
80 #define SCRBAR_STATE_BTN1_DOWN ((sal_uInt16)0x0001)
81 #define SCRBAR_STATE_BTN1_DISABLE ((sal_uInt16)0x0002)
82 #define SCRBAR_STATE_BTN2_DOWN ((sal_uInt16)0x0004)
83 #define SCRBAR_STATE_BTN2_DISABLE ((sal_uInt16)0x0008)
84 #define SCRBAR_STATE_PAGE1_DOWN ((sal_uInt16)0x0010)
85 #define SCRBAR_STATE_PAGE2_DOWN ((sal_uInt16)0x0020)
86 #define SCRBAR_STATE_THUMB_DOWN ((sal_uInt16)0x0040)
87
88 #define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
89
90 struct ImplScrollBarData
91 {
92 AutoTimer maTimer; // Timer
93 sal_Bool mbHide;
94 Rectangle maTrackRect; // TODO: move to ScrollBar class when binary incompatibility of ScrollBar class is no longer problematic
95 };
96
97 // =======================================================================
98
ImplInit(Window * pParent,WinBits nStyle)99 void ScrollBar::ImplInit( Window* pParent, WinBits nStyle )
100 {
101 mpData = NULL;
102 mnThumbPixRange = 0;
103 mnThumbPixPos = 0;
104 mnThumbPixSize = 0;
105 mnMinRange = 0;
106 mnMaxRange = 100;
107 mnThumbPos = 0;
108 mnVisibleSize = 0;
109 mnLineSize = 1;
110 mnPageSize = 1;
111 mnDelta = 0;
112 mnDragDraw = 0;
113 mnStateFlags = 0;
114 meScrollType = SCROLL_DONTKNOW;
115 meDDScrollType = SCROLL_DONTKNOW;
116 mbCalcSize = sal_True;
117 mbFullDrag = 0;
118
119 if( !mpData ) // TODO: remove when maTrackRect is no longer in mpData
120 {
121 mpData = new ImplScrollBarData;
122 mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
123 mpData->mbHide = sal_False;
124 }
125
126 ImplInitStyle( nStyle );
127 Control::ImplInit( pParent, nStyle, NULL );
128
129 long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
130 SetSizePixel( Size( nScrollSize, nScrollSize ) );
131 SetBackground();
132 }
133
134 // -----------------------------------------------------------------------
135
ImplInitStyle(WinBits nStyle)136 void ScrollBar::ImplInitStyle( WinBits nStyle )
137 {
138 if ( nStyle & WB_DRAG )
139 mbFullDrag = sal_True;
140 else
141 mbFullDrag = (GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SCROLL) != 0;
142 }
143
144 // -----------------------------------------------------------------------
145
ScrollBar(Window * pParent,WinBits nStyle)146 ScrollBar::ScrollBar( Window* pParent, WinBits nStyle ) :
147 Control( WINDOW_SCROLLBAR )
148 {
149 ImplInit( pParent, nStyle );
150 }
151
152 // -----------------------------------------------------------------------
153
ScrollBar(Window * pParent,const ResId & rResId)154 ScrollBar::ScrollBar( Window* pParent, const ResId& rResId ) :
155 Control( WINDOW_SCROLLBAR )
156 {
157 rResId.SetRT( RSC_SCROLLBAR );
158 WinBits nStyle = ImplInitRes( rResId );
159 ImplInit( pParent, nStyle );
160 ImplLoadRes( rResId );
161
162 if ( !(nStyle & WB_HIDE) )
163 Show();
164 }
165
166 // -----------------------------------------------------------------------
167
~ScrollBar()168 ScrollBar::~ScrollBar()
169 {
170 if( mpData )
171 delete mpData;
172 }
173
174 // -----------------------------------------------------------------------
175
ImplLoadRes(const ResId & rResId)176 void ScrollBar::ImplLoadRes( const ResId& rResId )
177 {
178 Control::ImplLoadRes( rResId );
179
180 sal_Int16 nMin = ReadShortRes();
181 sal_Int16 nMax = ReadShortRes();
182 sal_Int16 nThumbPos = ReadShortRes();
183 sal_Int16 nPage = ReadShortRes();
184 sal_Int16 nStep = ReadShortRes();
185 sal_Int16 nVisibleSize = ReadShortRes();
186
187 SetRange( Range( nMin, nMax ) );
188 SetLineSize( nStep );
189 SetPageSize( nPage );
190 SetVisibleSize( nVisibleSize );
191 SetThumbPos( nThumbPos );
192 }
193
194 // -----------------------------------------------------------------------
195
ImplUpdateRects(sal_Bool bUpdate)196 void ScrollBar::ImplUpdateRects( sal_Bool bUpdate )
197 {
198 sal_uInt16 nOldStateFlags = mnStateFlags;
199 Rectangle aOldPage1Rect = maPage1Rect;
200 Rectangle aOldPage2Rect = maPage2Rect;
201 Rectangle aOldThumbRect = maThumbRect;
202
203 mnStateFlags &= ~SCRBAR_STATE_BTN1_DISABLE;
204 mnStateFlags &= ~SCRBAR_STATE_BTN2_DISABLE;
205
206 Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
207 if ( mnThumbPixRange )
208 {
209 if ( GetStyle() & WB_HORZ )
210 {
211 maThumbRect.Left() = maTrackRect.Left()+mnThumbPixPos;
212 maThumbRect.Right() = maThumbRect.Left()+mnThumbPixSize-1;
213 if ( !mnThumbPixPos )
214 maPage1Rect.Right() = RECT_EMPTY;
215 else
216 maPage1Rect.Right() = maThumbRect.Left()-1;
217 if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
218 maPage2Rect.Right() = RECT_EMPTY;
219 else
220 {
221 maPage2Rect.Left() = maThumbRect.Right()+1;
222 maPage2Rect.Right() = maTrackRect.Right();
223 }
224 }
225 else
226 {
227 maThumbRect.Top() = maTrackRect.Top()+mnThumbPixPos;
228 maThumbRect.Bottom() = maThumbRect.Top()+mnThumbPixSize-1;
229 if ( !mnThumbPixPos )
230 maPage1Rect.Bottom() = RECT_EMPTY;
231 else
232 maPage1Rect.Bottom() = maThumbRect.Top()-1;
233 if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
234 maPage2Rect.Bottom() = RECT_EMPTY;
235 else
236 {
237 maPage2Rect.Top() = maThumbRect.Bottom()+1;
238 maPage2Rect.Bottom() = maTrackRect.Bottom();
239 }
240 }
241 }
242 else
243 {
244 Size aScrBarSize = GetOutputSizePixel();
245 if ( GetStyle() & WB_HORZ )
246 {
247 const long nSpace = maTrackRect.Right() - maTrackRect.Left();
248 if ( nSpace > 0 )
249 {
250 maPage1Rect.Left() = maTrackRect.Left();
251 maPage1Rect.Right() = maTrackRect.Left() + (nSpace/2);
252 maPage2Rect.Left() = maPage1Rect.Right() + 1;
253 maPage2Rect.Right() = maTrackRect.Right();
254 }
255 }
256 else
257 {
258 const long nSpace = maTrackRect.Bottom() - maTrackRect.Top();
259 if ( nSpace > 0 )
260 {
261 maPage1Rect.Top() = maTrackRect.Top();
262 maPage1Rect.Bottom() = maTrackRect.Top() + (nSpace/2);
263 maPage2Rect.Top() = maPage1Rect.Bottom() + 1;
264 maPage2Rect.Bottom() = maTrackRect.Bottom();
265 }
266 }
267 }
268
269 if( !IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
270 {
271 // disable scrollbar buttons only in VCL's own 'theme'
272 // as it is uncommon on other platforms
273 if ( mnThumbPos == mnMinRange )
274 mnStateFlags |= SCRBAR_STATE_BTN1_DISABLE;
275 if ( mnThumbPos >= (mnMaxRange-mnVisibleSize) )
276 mnStateFlags |= SCRBAR_STATE_BTN2_DISABLE;
277 }
278
279 if ( bUpdate )
280 {
281 sal_uInt16 nDraw = 0;
282 if ( (nOldStateFlags & SCRBAR_STATE_BTN1_DISABLE) !=
283 (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
284 nDraw |= SCRBAR_DRAW_BTN1;
285 if ( (nOldStateFlags & SCRBAR_STATE_BTN2_DISABLE) !=
286 (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
287 nDraw |= SCRBAR_DRAW_BTN2;
288 if ( aOldPage1Rect != maPage1Rect )
289 nDraw |= SCRBAR_DRAW_PAGE1;
290 if ( aOldPage2Rect != maPage2Rect )
291 nDraw |= SCRBAR_DRAW_PAGE2;
292 if ( aOldThumbRect != maThumbRect )
293 nDraw |= SCRBAR_DRAW_THUMB;
294 ImplDraw( nDraw, this );
295 }
296 }
297
298 // -----------------------------------------------------------------------
299
ImplCalcThumbPos(long nPixPos)300 long ScrollBar::ImplCalcThumbPos( long nPixPos )
301 {
302 // Position berechnen
303 long nCalcThumbPos;
304 nCalcThumbPos = ImplMulDiv( nPixPos, mnMaxRange-mnVisibleSize-mnMinRange,
305 mnThumbPixRange-mnThumbPixSize );
306 nCalcThumbPos += mnMinRange;
307 return nCalcThumbPos;
308 }
309
310 // -----------------------------------------------------------------------
311
ImplCalcThumbPosPix(long nPos)312 long ScrollBar::ImplCalcThumbPosPix( long nPos )
313 {
314 long nCalcThumbPos;
315
316 // Position berechnen
317 nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-mnThumbPixSize,
318 mnMaxRange-mnVisibleSize-mnMinRange );
319
320 // Am Anfang und Ende des ScrollBars versuchen wir die Anzeige korrekt
321 // anzuzeigen
322 if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
323 nCalcThumbPos = 1;
324 if ( nCalcThumbPos &&
325 ((nCalcThumbPos+mnThumbPixSize) >= mnThumbPixRange) &&
326 (mnThumbPos < (mnMaxRange-mnVisibleSize)) )
327 nCalcThumbPos--;
328
329 return nCalcThumbPos;
330 }
331
332 // -----------------------------------------------------------------------
333
ImplCalc(sal_Bool bUpdate)334 void ScrollBar::ImplCalc( sal_Bool bUpdate )
335 {
336 const Size aSize = GetOutputSizePixel();
337 const long nMinThumbSize = GetSettings().GetStyleSettings().GetMinThumbSize();;
338
339 Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
340 if ( mbCalcSize )
341 {
342 const Rectangle aControlRegion( Point(0,0), aSize );
343 Rectangle aBtn1Region, aBtn2Region, aTrackRegion, aBoundingRegion;
344
345 if ( GetStyle() & WB_HORZ )
346 {
347 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_LEFT,
348 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) &&
349 GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_RIGHT,
350 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) )
351 {
352 maBtn1Rect = aBtn1Region;
353 maBtn2Rect = aBtn2Region;
354 }
355 else
356 {
357 if (aBtn1Region.IsEmpty() && aBtn2Region.IsEmpty())
358 {
359 Size aBtnSize( aSize.Height(), aSize.Height() );
360 maBtn2Rect.Top() = maBtn1Rect.Top();
361 maBtn2Rect.Left() = aSize.Width()-aSize.Height();
362 maBtn1Rect.SetSize( aBtnSize );
363 maBtn2Rect.SetSize( aBtnSize );
364 }
365 else
366 {
367 maBtn1Rect.SetEmpty();
368 maBtn2Rect.SetEmpty();
369 }
370 }
371
372 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_HORZ_AREA,
373 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) )
374 {
375 maTrackRect = aTrackRegion;
376 }
377 else
378 {
379 if ( ! maBtn1Rect.IsEmpty())
380 maTrackRect = Rectangle( maBtn1Rect.TopRight(), maBtn2Rect.BottomLeft() );
381 else
382 maTrackRect = aControlRegion;
383 }
384
385 // Check if available space is big enough for thumb ( min thumb size = ScrBar width/height )
386 mnThumbPixRange = maTrackRect.Right() - maTrackRect.Left();
387 if( mnThumbPixRange > 0 )
388 {
389 maPage1Rect.Left() = maTrackRect.Left();
390 maPage1Rect.Bottom() =
391 maPage2Rect.Bottom() =
392 maThumbRect.Bottom() = maTrackRect.Bottom();
393 }
394 else
395 {
396 mnThumbPixRange = 0;
397 maPage1Rect.SetEmpty();
398 maPage2Rect.SetEmpty();
399 }
400 }
401 else
402 {
403 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_UP,
404 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) &&
405 GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_DOWN,
406 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) )
407 {
408 maBtn1Rect = aBtn1Region;
409 maBtn2Rect = aBtn2Region;
410 }
411 else
412 {
413 if (aBtn1Region.IsEmpty() && aBtn2Region.IsEmpty())
414 {
415 const Size aBtnSize( aSize.Width(), aSize.Width() );
416 maBtn2Rect.Left() = maBtn1Rect.Left();
417 maBtn2Rect.Top() = aSize.Height()-aSize.Width();
418 maBtn1Rect.SetSize( aBtnSize );
419 maBtn2Rect.SetSize( aBtnSize );
420 }
421 else
422 {
423 maBtn1Rect.SetEmpty();
424 maBtn2Rect.SetEmpty();
425 }
426 }
427
428 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_VERT_AREA,
429 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) )
430 maTrackRect = aTrackRegion;
431 else
432 {
433 if ( ! maBtn1Rect.IsEmpty())
434 maTrackRect = Rectangle( maBtn1Rect.BottomLeft()+Point(0,1), maBtn2Rect.TopRight() );
435 else
436 maTrackRect = aControlRegion;
437 }
438
439 // Check if available space is big enough for thumb
440 mnThumbPixRange = maTrackRect.Bottom() - maTrackRect.Top();
441 if( mnThumbPixRange > 0 )
442 {
443 maPage1Rect.Top() = maTrackRect.Top();
444 maPage1Rect.Right() =
445 maPage2Rect.Right() =
446 maThumbRect.Right() = maTrackRect.Right();
447 }
448 else
449 {
450 mnThumbPixRange = 0;
451 maPage1Rect.SetEmpty();
452 maPage2Rect.SetEmpty();
453 }
454 }
455
456 if ( !mnThumbPixRange )
457 maThumbRect.SetEmpty();
458
459 mbCalcSize = sal_False;
460 }
461
462 if ( mnThumbPixRange )
463 {
464 // Werte berechnen
465 if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) ||
466 ((mnMaxRange-mnMinRange) <= 0) )
467 {
468 mnThumbPos = mnMinRange;
469 mnThumbPixPos = 0;
470 mnThumbPixSize = mnThumbPixRange;
471 }
472 else
473 {
474 if ( mnVisibleSize )
475 mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange );
476 else
477 {
478 if ( GetStyle() & WB_HORZ )
479 mnThumbPixSize = maThumbRect.GetWidth();
480 else
481 mnThumbPixSize = maThumbRect.GetHeight();
482 }
483 if ( mnThumbPixSize < nMinThumbSize )
484 mnThumbPixSize = nMinThumbSize;
485 if ( mnThumbPixSize > mnThumbPixRange )
486 mnThumbPixSize = mnThumbPixRange;
487 mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
488 }
489 }
490
491 // Wenn neu ausgegeben werden soll und wir schon ueber eine
492 // Aktion einen Paint-Event ausgeloest bekommen haben, dann
493 // geben wir nicht direkt aus, sondern invalidieren nur alles
494 if ( bUpdate && HasPaintEvent() )
495 {
496 Invalidate();
497 bUpdate = sal_False;
498 }
499 ImplUpdateRects( bUpdate );
500 }
501
502 // -----------------------------------------------------------------------
503
Draw(OutputDevice * pDev,const Point & rPos,const Size & rSize,sal_uLong nFlags)504 void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
505 {
506 Point aPos = pDev->LogicToPixel( rPos );
507 Size aSize = pDev->LogicToPixel( rSize );
508 Rectangle aRect( aPos, aSize );
509
510 pDev->Push();
511 pDev->SetMapMode();
512 if ( !(nFlags & WINDOW_DRAW_MONO) )
513 {
514 // DecoView uses the FaceColor...
515 AllSettings aSettings = pDev->GetSettings();
516 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
517 if ( IsControlBackground() )
518 aStyleSettings.SetFaceColor( GetControlBackground() );
519 else
520 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
521
522 aSettings.SetStyleSettings( aStyleSettings );
523 pDev->SetSettings( aSettings );
524 }
525
526 // for printing:
527 // -calculate the size of the rects
528 // -because this is zero-based add the correct offset
529 // -print
530 // -force recalculate
531
532 if ( mbCalcSize )
533 ImplCalc( sal_False );
534
535 maBtn1Rect+=aPos;
536 maBtn2Rect+=aPos;
537 maThumbRect+=aPos;
538 mpData->maTrackRect+=aPos; // TODO: update when maTrackRect is no longer in mpData
539 maPage1Rect+=aPos;
540 maPage2Rect+=aPos;
541
542 ImplDraw( SCRBAR_DRAW_ALL, pDev );
543 pDev->Pop();
544
545 mbCalcSize = sal_True;
546 }
547
548 // -----------------------------------------------------------------------
549
ImplDrawNative(sal_uInt16 nDrawFlags)550 sal_Bool ScrollBar::ImplDrawNative( sal_uInt16 nDrawFlags )
551 {
552 ScrollbarValue scrValue;
553
554 sal_Bool bNativeOK = IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL);
555 if( bNativeOK )
556 {
557 sal_Bool bHorz = (GetStyle() & WB_HORZ ? true : false);
558
559 // Draw the entire background if the control supports it
560 if( IsNativeControlSupported(CTRL_SCROLLBAR, bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT) )
561 {
562 ControlState nState = ( IsEnabled() ? CTRL_STATE_ENABLED : 0 ) | ( HasFocus() ? CTRL_STATE_FOCUSED : 0 );
563
564 scrValue.mnMin = mnMinRange;
565 scrValue.mnMax = mnMaxRange;
566 scrValue.mnCur = mnThumbPos;
567 scrValue.mnVisibleSize = mnVisibleSize;
568 scrValue.maThumbRect = maThumbRect;
569 scrValue.maButton1Rect = maBtn1Rect;
570 scrValue.maButton2Rect = maBtn2Rect;
571 scrValue.mnButton1State = ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0) |
572 ((!(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)) ? CTRL_STATE_ENABLED : 0);
573 scrValue.mnButton2State = ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0) |
574 ((!(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)) ? CTRL_STATE_ENABLED : 0);
575 scrValue.mnThumbState = nState | ((mnStateFlags & SCRBAR_STATE_THUMB_DOWN) ? CTRL_STATE_PRESSED : 0);
576 scrValue.mnPage1State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0);
577 scrValue.mnPage2State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0);
578
579 if( IsMouseOver() )
580 {
581 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
582 if( pRect )
583 {
584 if( pRect == &maThumbRect )
585 scrValue.mnThumbState |= CTRL_STATE_ROLLOVER;
586 else if( pRect == &maBtn1Rect )
587 scrValue.mnButton1State |= CTRL_STATE_ROLLOVER;
588 else if( pRect == &maBtn2Rect )
589 scrValue.mnButton2State |= CTRL_STATE_ROLLOVER;
590 else if( pRect == &maPage1Rect )
591 scrValue.mnPage1State |= CTRL_STATE_ROLLOVER;
592 else if( pRect == &maPage2Rect )
593 scrValue.mnPage2State |= CTRL_STATE_ROLLOVER;
594 }
595 }
596
597 Rectangle aCtrlRegion;
598 aCtrlRegion.Union( maBtn1Rect );
599 aCtrlRegion.Union( maBtn2Rect );
600 aCtrlRegion.Union( maPage1Rect );
601 aCtrlRegion.Union( maPage2Rect );
602 aCtrlRegion.Union( maThumbRect );
603 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT),
604 aCtrlRegion, nState, scrValue, rtl::OUString() );
605 }
606 else
607 {
608 if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) || (nDrawFlags & SCRBAR_DRAW_PAGE2) )
609 {
610 sal_uInt32 part1 = bHorz ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER;
611 sal_uInt32 part2 = bHorz ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER;
612 Rectangle aCtrlRegion1( maPage1Rect );
613 Rectangle aCtrlRegion2( maPage2Rect );
614 ControlState nState1 = (IsEnabled() ? CTRL_STATE_ENABLED : 0) | (HasFocus() ? CTRL_STATE_FOCUSED : 0);
615 ControlState nState2 = nState1;
616
617 nState1 |= ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0);
618 nState2 |= ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0);
619
620 if( IsMouseOver() )
621 {
622 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
623 if( pRect )
624 {
625 if( pRect == &maPage1Rect )
626 nState1 |= CTRL_STATE_ROLLOVER;
627 else if( pRect == &maPage2Rect )
628 nState2 |= CTRL_STATE_ROLLOVER;
629 }
630 }
631
632 if ( nDrawFlags & SCRBAR_DRAW_PAGE1 )
633 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1,
634 scrValue, rtl::OUString() );
635
636 if ( nDrawFlags & SCRBAR_DRAW_PAGE2 )
637 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
638 scrValue, rtl::OUString() );
639 }
640 if ( (nDrawFlags & SCRBAR_DRAW_BTN1) || (nDrawFlags & SCRBAR_DRAW_BTN2) )
641 {
642 sal_uInt32 part1 = bHorz ? PART_BUTTON_LEFT : PART_BUTTON_UP;
643 sal_uInt32 part2 = bHorz ? PART_BUTTON_RIGHT : PART_BUTTON_DOWN;
644 Rectangle aCtrlRegion1( maBtn1Rect );
645 Rectangle aCtrlRegion2( maBtn2Rect );
646 ControlState nState1 = HasFocus() ? CTRL_STATE_FOCUSED : 0;
647 ControlState nState2 = nState1;
648
649 if ( !Window::IsEnabled() || !IsEnabled() )
650 nState1 = (nState2 &= ~CTRL_STATE_ENABLED);
651 else
652 nState1 = (nState2 |= CTRL_STATE_ENABLED);
653
654 nState1 |= ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0);
655 nState2 |= ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0);
656
657 if(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)
658 nState1 &= ~CTRL_STATE_ENABLED;
659 if(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)
660 nState2 &= ~CTRL_STATE_ENABLED;
661
662 if( IsMouseOver() )
663 {
664 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
665 if( pRect )
666 {
667 if( pRect == &maBtn1Rect )
668 nState1 |= CTRL_STATE_ROLLOVER;
669 else if( pRect == &maBtn2Rect )
670 nState2 |= CTRL_STATE_ROLLOVER;
671 }
672 }
673
674 if ( nDrawFlags & SCRBAR_DRAW_BTN1 )
675 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1,
676 scrValue, rtl::OUString() );
677
678 if ( nDrawFlags & SCRBAR_DRAW_BTN2 )
679 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
680 scrValue, rtl::OUString() );
681 }
682 if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && !maThumbRect.IsEmpty() )
683 {
684 ControlState nState = IsEnabled() ? CTRL_STATE_ENABLED : 0;
685 Rectangle aCtrlRegion( maThumbRect );
686
687 if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN )
688 nState |= CTRL_STATE_PRESSED;
689
690 if ( HasFocus() )
691 nState |= CTRL_STATE_FOCUSED;
692
693 if( IsMouseOver() )
694 {
695 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
696 if( pRect )
697 {
698 if( pRect == &maThumbRect )
699 nState |= CTRL_STATE_ROLLOVER;
700 }
701 }
702
703 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_THUMB_HORZ : PART_THUMB_VERT),
704 aCtrlRegion, nState, scrValue, rtl::OUString() );
705 }
706 }
707 }
708 return bNativeOK;
709 }
710
ImplDraw(sal_uInt16 nDrawFlags,OutputDevice * pOutDev)711 void ScrollBar::ImplDraw( sal_uInt16 nDrawFlags, OutputDevice* pOutDev )
712 {
713 DecorationView aDecoView( pOutDev );
714 Rectangle aTempRect;
715 sal_uInt16 nStyle;
716 const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
717 SymbolType eSymbolType;
718 sal_Bool bEnabled = IsEnabled();
719
720 // Evt. noch offene Berechnungen nachholen
721 if ( mbCalcSize )
722 ImplCalc( sal_False );
723
724 Window *pWin = NULL;
725 if( pOutDev->GetOutDevType() == OUTDEV_WINDOW )
726 pWin = (Window*) pOutDev;
727
728 // Draw the entire control if the native theme engine needs it
729 if ( nDrawFlags && pWin && pWin->IsNativeControlSupported(CTRL_SCROLLBAR, PART_DRAW_BACKGROUND_HORZ) )
730 {
731 ImplDrawNative( SCRBAR_DRAW_BACKGROUND );
732 return;
733 }
734
735 if( (nDrawFlags & SCRBAR_DRAW_BTN1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN1 ) ) )
736 {
737 nStyle = BUTTON_DRAW_NOLIGHTBORDER;
738 if ( mnStateFlags & SCRBAR_STATE_BTN1_DOWN )
739 nStyle |= BUTTON_DRAW_PRESSED;
740 aTempRect = aDecoView.DrawButton( maBtn1Rect, nStyle );
741 ImplCalcSymbolRect( aTempRect );
742 nStyle = 0;
743 if ( (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) || !bEnabled )
744 nStyle |= SYMBOL_DRAW_DISABLE;
745 if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
746 {
747 if ( GetStyle() & WB_HORZ )
748 eSymbolType = SYMBOL_ARROW_LEFT;
749 else
750 eSymbolType = SYMBOL_ARROW_UP;
751 }
752 else
753 {
754 if ( GetStyle() & WB_HORZ )
755 eSymbolType = SYMBOL_SPIN_LEFT;
756 else
757 eSymbolType = SYMBOL_SPIN_UP;
758 }
759 aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
760 }
761
762 if ( (nDrawFlags & SCRBAR_DRAW_BTN2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN2 ) ) )
763 {
764 nStyle = BUTTON_DRAW_NOLIGHTBORDER;
765 if ( mnStateFlags & SCRBAR_STATE_BTN2_DOWN )
766 nStyle |= BUTTON_DRAW_PRESSED;
767 aTempRect = aDecoView.DrawButton( maBtn2Rect, nStyle );
768 ImplCalcSymbolRect( aTempRect );
769 nStyle = 0;
770 if ( (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) || !bEnabled )
771 nStyle |= SYMBOL_DRAW_DISABLE;
772 if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
773 {
774 if ( GetStyle() & WB_HORZ )
775 eSymbolType = SYMBOL_ARROW_RIGHT;
776 else
777 eSymbolType = SYMBOL_ARROW_DOWN;
778 }
779 else
780 {
781 if ( GetStyle() & WB_HORZ )
782 eSymbolType = SYMBOL_SPIN_RIGHT;
783 else
784 eSymbolType = SYMBOL_SPIN_DOWN;
785 }
786 aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
787 }
788
789 pOutDev->SetLineColor();
790
791 if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_THUMB ) ) )
792 {
793 if ( !maThumbRect.IsEmpty() )
794 {
795 if ( bEnabled )
796 {
797 nStyle = BUTTON_DRAW_NOLIGHTBORDER;
798 aTempRect = aDecoView.DrawButton( maThumbRect, nStyle );
799 }
800 else
801 {
802 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
803 pOutDev->DrawRect( maThumbRect );
804 }
805 }
806 }
807
808 if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE1 ) ) )
809 {
810 if ( mnStateFlags & SCRBAR_STATE_PAGE1_DOWN )
811 pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
812 else
813 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
814 pOutDev->DrawRect( maPage1Rect );
815 }
816 if ( (nDrawFlags & SCRBAR_DRAW_PAGE2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE2 ) ) )
817 {
818 if ( mnStateFlags & SCRBAR_STATE_PAGE2_DOWN )
819 pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
820 else
821 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
822 pOutDev->DrawRect( maPage2Rect );
823 }
824 }
825
826 // -----------------------------------------------------------------------
827
ImplScroll(long nNewPos,sal_Bool bCallEndScroll)828 long ScrollBar::ImplScroll( long nNewPos, sal_Bool bCallEndScroll )
829 {
830 long nOldPos = mnThumbPos;
831 SetThumbPos( nNewPos );
832 long nDelta = mnThumbPos-nOldPos;
833 if ( nDelta )
834 {
835 mnDelta = nDelta;
836 Scroll();
837 if ( bCallEndScroll )
838 EndScroll();
839 mnDelta = 0;
840 }
841 return nDelta;
842 }
843
844 // -----------------------------------------------------------------------
845
ImplDoAction(sal_Bool bCallEndScroll)846 long ScrollBar::ImplDoAction( sal_Bool bCallEndScroll )
847 {
848 long nDelta = 0;
849
850 switch ( meScrollType )
851 {
852 case SCROLL_LINEUP:
853 nDelta = ImplScroll( mnThumbPos-mnLineSize, bCallEndScroll );
854 break;
855
856 case SCROLL_LINEDOWN:
857 nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll );
858 break;
859
860 case SCROLL_PAGEUP:
861 nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll );
862 break;
863
864 case SCROLL_PAGEDOWN:
865 nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll );
866 break;
867 default:
868 ;
869 }
870
871 return nDelta;
872 }
873
874 // -----------------------------------------------------------------------
875
ImplDoMouseAction(const Point & rMousePos,sal_Bool bCallAction)876 void ScrollBar::ImplDoMouseAction( const Point& rMousePos, sal_Bool bCallAction )
877 {
878 sal_uInt16 nOldStateFlags = mnStateFlags;
879 sal_Bool bAction = sal_False;
880 sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False;
881 sal_Bool bIsInside = sal_False;
882
883 Point aPoint( 0, 0 );
884 Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
885
886 switch ( meScrollType )
887 {
888 case SCROLL_LINEUP:
889 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
890 aControlRegion, rMousePos, bIsInside )?
891 bIsInside:
892 maBtn1Rect.IsInside( rMousePos ) )
893 {
894 bAction = bCallAction;
895 mnStateFlags |= SCRBAR_STATE_BTN1_DOWN;
896 }
897 else
898 mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN;
899 break;
900
901 case SCROLL_LINEDOWN:
902 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
903 aControlRegion, rMousePos, bIsInside )?
904 bIsInside:
905 maBtn2Rect.IsInside( rMousePos ) )
906 {
907 bAction = bCallAction;
908 mnStateFlags |= SCRBAR_STATE_BTN2_DOWN;
909 }
910 else
911 mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN;
912 break;
913
914 case SCROLL_PAGEUP:
915 // HitTestNativeControl, see remark at top of file
916 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT: PART_TRACK_VERT_UPPER,
917 maPage1Rect, rMousePos, bIsInside )?
918 bIsInside:
919 maPage1Rect.IsInside( rMousePos ) )
920 {
921 bAction = bCallAction;
922 mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN;
923 }
924 else
925 mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN;
926 break;
927
928 case SCROLL_PAGEDOWN:
929 // HitTestNativeControl, see remark at top of file
930 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_RIGHT: PART_TRACK_VERT_LOWER,
931 maPage2Rect, rMousePos, bIsInside )?
932 bIsInside:
933 maPage2Rect.IsInside( rMousePos ) )
934 {
935 bAction = bCallAction;
936 mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
937 }
938 else
939 mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
940 break;
941 default:
942 ;
943 }
944
945 if ( nOldStateFlags != mnStateFlags )
946 ImplDraw( mnDragDraw, this );
947 if ( bAction )
948 ImplDoAction( sal_False );
949 }
950
951 // -----------------------------------------------------------------------
952
ImplDragThumb(const Point & rMousePos)953 void ScrollBar::ImplDragThumb( const Point& rMousePos )
954 {
955 long nMovePix;
956 if ( GetStyle() & WB_HORZ )
957 nMovePix = rMousePos.X()-(maThumbRect.Left()+mnMouseOff);
958 else
959 nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff);
960
961 // move thumb if necessary
962 if ( nMovePix )
963 {
964 mnThumbPixPos += nMovePix;
965 if ( mnThumbPixPos < 0 )
966 mnThumbPixPos = 0;
967 if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) )
968 mnThumbPixPos = mnThumbPixRange-mnThumbPixSize;
969 long nOldPos = mnThumbPos;
970 mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
971 ImplUpdateRects();
972 if ( mbFullDrag && (nOldPos != mnThumbPos) )
973 {
974 mnDelta = mnThumbPos-nOldPos;
975 Scroll();
976 mnDelta = 0;
977 }
978 }
979 }
980
981 // -----------------------------------------------------------------------
982
MouseButtonDown(const MouseEvent & rMEvt)983 void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
984 {
985 if ( rMEvt.IsLeft() || rMEvt.IsMiddle() )
986 {
987 const Point& rMousePos = rMEvt.GetPosPixel();
988 sal_uInt16 nTrackFlags = 0;
989 sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False;
990 sal_Bool bIsInside = sal_False;
991 sal_Bool bDragToMouse = sal_False;
992
993 Point aPoint( 0, 0 );
994 Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
995
996 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
997 aControlRegion, rMousePos, bIsInside )?
998 bIsInside:
999 maBtn1Rect.IsInside( rMousePos ) )
1000 {
1001 if ( !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
1002 {
1003 nTrackFlags = STARTTRACK_BUTTONREPEAT;
1004 meScrollType = SCROLL_LINEUP;
1005 mnDragDraw = SCRBAR_DRAW_BTN1;
1006 }
1007 else
1008 Sound::Beep( SOUND_DISABLE, this );
1009 }
1010 else if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
1011 aControlRegion, rMousePos, bIsInside )?
1012 bIsInside:
1013 maBtn2Rect.IsInside( rMousePos ) )
1014 {
1015 if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
1016 {
1017 nTrackFlags = STARTTRACK_BUTTONREPEAT;
1018 meScrollType = SCROLL_LINEDOWN;
1019 mnDragDraw = SCRBAR_DRAW_BTN2;
1020 }
1021 else
1022 Sound::Beep( SOUND_DISABLE, this );
1023 }
1024 else
1025 {
1026 bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT,
1027 maThumbRect, rMousePos, bIsInside )
1028 ? bIsInside : maThumbRect.IsInside( rMousePos );
1029 bool bDragHandling = rMEvt.IsMiddle() || bThumbHit || ImplGetSVData()->maNWFData.mbScrollbarJumpPage;
1030 if( bDragHandling )
1031 {
1032 if( mpData )
1033 {
1034 mpData->mbHide = sal_True; // disable focus blinking
1035 if( HasFocus() )
1036 ImplDraw( SCRBAR_DRAW_THUMB, this ); // paint without focus
1037 }
1038
1039 if ( mnVisibleSize < mnMaxRange-mnMinRange )
1040 {
1041 nTrackFlags = 0;
1042 meScrollType = SCROLL_DRAG;
1043 mnDragDraw = SCRBAR_DRAW_THUMB;
1044
1045 // calculate mouse offset
1046 if( rMEvt.IsMiddle() || (ImplGetSVData()->maNWFData.mbScrollbarJumpPage && !bThumbHit) )
1047 {
1048 bDragToMouse = sal_True;
1049 if ( GetStyle() & WB_HORZ )
1050 mnMouseOff = maThumbRect.GetWidth()/2;
1051 else
1052 mnMouseOff = maThumbRect.GetHeight()/2;
1053 }
1054 else
1055 {
1056 if ( GetStyle() & WB_HORZ )
1057 mnMouseOff = rMousePos.X()-maThumbRect.Left();
1058 else
1059 mnMouseOff = rMousePos.Y()-maThumbRect.Top();
1060 }
1061
1062 mnStateFlags |= SCRBAR_STATE_THUMB_DOWN;
1063 ImplDraw( mnDragDraw, this );
1064 }
1065 else
1066 Sound::Beep( SOUND_DISABLE, this );
1067 }
1068 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA,
1069 aControlRegion, rMousePos, bIsInside )?
1070 bIsInside : sal_True )
1071 {
1072 nTrackFlags = STARTTRACK_BUTTONREPEAT;
1073
1074 // HitTestNativeControl, see remark at top of file
1075 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
1076 maPage1Rect, rMousePos, bIsInside )?
1077 bIsInside:
1078 maPage1Rect.IsInside( rMousePos ) )
1079 {
1080 meScrollType = SCROLL_PAGEUP;
1081 mnDragDraw = SCRBAR_DRAW_PAGE1;
1082 }
1083 else
1084 {
1085 meScrollType = SCROLL_PAGEDOWN;
1086 mnDragDraw = SCRBAR_DRAW_PAGE2;
1087 }
1088 }
1089 }
1090
1091 // Soll Tracking gestartet werden
1092 if ( meScrollType != SCROLL_DONTKNOW )
1093 {
1094 // remember original position in case of abort or EndScroll-Delta
1095 mnStartPos = mnThumbPos;
1096 // #92906# Call StartTracking() before ImplDoMouseAction(), otherwise
1097 // MouseButtonUp() / EndTracking() may be called if somebody is spending
1098 // a lot of time in the scroll handler
1099 StartTracking( nTrackFlags );
1100 ImplDoMouseAction( rMousePos );
1101
1102 if( bDragToMouse )
1103 ImplDragThumb( rMousePos );
1104 }
1105 }
1106 }
1107
1108 // -----------------------------------------------------------------------
1109
Tracking(const TrackingEvent & rTEvt)1110 void ScrollBar::Tracking( const TrackingEvent& rTEvt )
1111 {
1112 if ( rTEvt.IsTrackingEnded() )
1113 {
1114 // Button und PageRect-Status wieder herstellen
1115 sal_uInt16 nOldStateFlags = mnStateFlags;
1116 mnStateFlags &= ~(SCRBAR_STATE_BTN1_DOWN | SCRBAR_STATE_BTN2_DOWN |
1117 SCRBAR_STATE_PAGE1_DOWN | SCRBAR_STATE_PAGE2_DOWN |
1118 SCRBAR_STATE_THUMB_DOWN);
1119 if ( nOldStateFlags != mnStateFlags )
1120 ImplDraw( mnDragDraw, this );
1121 mnDragDraw = 0;
1122
1123 // Bei Abbruch, die alte ThumbPosition wieder herstellen
1124 if ( rTEvt.IsTrackingCanceled() )
1125 {
1126 long nOldPos = mnThumbPos;
1127 SetThumbPos( mnStartPos );
1128 mnDelta = mnThumbPos-nOldPos;
1129 Scroll();
1130 }
1131
1132 if ( meScrollType == SCROLL_DRAG )
1133 {
1134 // Wenn gedragt wurde, berechnen wir den Thumb neu, damit
1135 // er wieder auf einer gerundeten ThumbPosition steht
1136 ImplCalc();
1137
1138 if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
1139 {
1140 mnDelta = mnThumbPos-mnStartPos;
1141 Scroll();
1142 mnDelta = 0;
1143 }
1144 }
1145
1146 mnDelta = mnThumbPos-mnStartPos;
1147 EndScroll();
1148 mnDelta = 0;
1149 meScrollType = SCROLL_DONTKNOW;
1150
1151 if( mpData )
1152 mpData->mbHide = sal_False; // re-enable focus blinking
1153 }
1154 else
1155 {
1156 const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1157
1158 // Dragging wird speziell behandelt
1159 if ( meScrollType == SCROLL_DRAG )
1160 ImplDragThumb( rMousePos );
1161 else
1162 ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
1163
1164 // Wenn ScrollBar-Werte so umgesetzt wurden, das es nichts
1165 // mehr zum Tracking gibt, dann berechen wir hier ab
1166 if ( !IsVisible() || (mnVisibleSize >= (mnMaxRange-mnMinRange)) )
1167 EndTracking();
1168 }
1169 }
1170
1171 // -----------------------------------------------------------------------
1172
KeyInput(const KeyEvent & rKEvt)1173 void ScrollBar::KeyInput( const KeyEvent& rKEvt )
1174 {
1175 if ( !rKEvt.GetKeyCode().GetModifier() )
1176 {
1177 switch ( rKEvt.GetKeyCode().GetCode() )
1178 {
1179 case KEY_HOME:
1180 DoScroll( 0 );
1181 break;
1182
1183 case KEY_END:
1184 DoScroll( GetRangeMax() );
1185 break;
1186
1187 case KEY_LEFT:
1188 case KEY_UP:
1189 DoScrollAction( SCROLL_LINEUP );
1190 break;
1191
1192 case KEY_RIGHT:
1193 case KEY_DOWN:
1194 DoScrollAction( SCROLL_LINEDOWN );
1195 break;
1196
1197 case KEY_PAGEUP:
1198 DoScrollAction( SCROLL_PAGEUP );
1199 break;
1200
1201 case KEY_PAGEDOWN:
1202 DoScrollAction( SCROLL_PAGEDOWN );
1203 break;
1204
1205 default:
1206 Control::KeyInput( rKEvt );
1207 break;
1208 }
1209 }
1210 else
1211 Control::KeyInput( rKEvt );
1212 }
1213
1214 // -----------------------------------------------------------------------
1215
Paint(const Rectangle &)1216 void ScrollBar::Paint( const Rectangle& )
1217 {
1218 ImplDraw( SCRBAR_DRAW_ALL, this );
1219 }
1220
1221 // -----------------------------------------------------------------------
1222
Resize()1223 void ScrollBar::Resize()
1224 {
1225 Control::Resize();
1226 mbCalcSize = sal_True;
1227 if ( IsReallyVisible() )
1228 ImplCalc( sal_False );
1229 Invalidate();
1230 }
1231
1232 // -----------------------------------------------------------------------
1233
IMPL_LINK(ScrollBar,ImplAutoTimerHdl,AutoTimer *,EMPTYARG)1234 IMPL_LINK( ScrollBar, ImplAutoTimerHdl, AutoTimer*, EMPTYARG )
1235 {
1236 if( mpData && mpData->mbHide )
1237 return 0;
1238 ImplInvert();
1239 return 0;
1240 }
1241
ImplInvert()1242 void ScrollBar::ImplInvert()
1243 {
1244 Rectangle aRect( maThumbRect );
1245 if( aRect.getWidth() > 4 )
1246 {
1247 aRect.Left() += 2;
1248 aRect.Right() -= 2;
1249 }
1250 if( aRect.getHeight() > 4 )
1251 {
1252 aRect.Top() += 2;
1253 aRect.Bottom() -= 2;
1254 }
1255
1256 Invert( aRect, 0 );
1257 }
1258
1259 // -----------------------------------------------------------------------
1260
GetFocus()1261 void ScrollBar::GetFocus()
1262 {
1263 if( !mpData )
1264 {
1265 mpData = new ImplScrollBarData;
1266 mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
1267 mpData->mbHide = sal_False;
1268 }
1269 ImplInvert(); // react immediately
1270 mpData->maTimer.SetTimeout( GetSettings().GetStyleSettings().GetCursorBlinkTime() );
1271 mpData->maTimer.Start();
1272 Control::GetFocus();
1273 }
1274
1275 // -----------------------------------------------------------------------
1276
LoseFocus()1277 void ScrollBar::LoseFocus()
1278 {
1279 if( mpData )
1280 mpData->maTimer.Stop();
1281 ImplDraw( SCRBAR_DRAW_THUMB, this );
1282
1283 Control::LoseFocus();
1284 }
1285
1286 // -----------------------------------------------------------------------
1287
StateChanged(StateChangedType nType)1288 void ScrollBar::StateChanged( StateChangedType nType )
1289 {
1290 Control::StateChanged( nType );
1291
1292 if ( nType == STATE_CHANGE_INITSHOW )
1293 ImplCalc( sal_False );
1294 else if ( nType == STATE_CHANGE_DATA )
1295 {
1296 if ( IsReallyVisible() && IsUpdateMode() )
1297 ImplCalc( sal_True );
1298 }
1299 else if ( nType == STATE_CHANGE_UPDATEMODE )
1300 {
1301 if ( IsReallyVisible() && IsUpdateMode() )
1302 {
1303 ImplCalc( sal_False );
1304 Invalidate();
1305 }
1306 }
1307 else if ( nType == STATE_CHANGE_ENABLE )
1308 {
1309 if ( IsReallyVisible() && IsUpdateMode() )
1310 Invalidate();
1311 }
1312 else if ( nType == STATE_CHANGE_STYLE )
1313 {
1314 ImplInitStyle( GetStyle() );
1315 if ( IsReallyVisible() && IsUpdateMode() )
1316 {
1317 if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) !=
1318 (GetStyle() & SCRBAR_VIEW_STYLE) )
1319 {
1320 mbCalcSize = sal_True;
1321 ImplCalc( sal_False );
1322 Invalidate();
1323 }
1324 }
1325 }
1326 }
1327
1328 // -----------------------------------------------------------------------
1329
DataChanged(const DataChangedEvent & rDCEvt)1330 void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt )
1331 {
1332 Control::DataChanged( rDCEvt );
1333
1334 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1335 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1336 {
1337 mbCalcSize = sal_True;
1338 ImplCalc( sal_False );
1339 Invalidate();
1340 }
1341 }
1342
1343 // -----------------------------------------------------------------------
1344
ImplFindPartRect(const Point & rPt)1345 Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt )
1346 {
1347 sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False;
1348 sal_Bool bIsInside = sal_False;
1349
1350 Point aPoint( 0, 0 );
1351 Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
1352
1353 if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
1354 aControlRegion, rPt, bIsInside )?
1355 bIsInside:
1356 maBtn1Rect.IsInside( rPt ) )
1357 return &maBtn1Rect;
1358 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
1359 aControlRegion, rPt, bIsInside )?
1360 bIsInside:
1361 maBtn2Rect.IsInside( rPt ) )
1362 return &maBtn2Rect;
1363 // HitTestNativeControl, see remark at top of file
1364 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
1365 maPage1Rect, rPt, bIsInside)?
1366 bIsInside:
1367 maPage1Rect.IsInside( rPt ) )
1368 return &maPage1Rect;
1369 // HitTestNativeControl, see remark at top of file
1370 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER,
1371 maPage2Rect, rPt, bIsInside)?
1372 bIsInside:
1373 maPage2Rect.IsInside( rPt ) )
1374 return &maPage2Rect;
1375 // HitTestNativeControl, see remark at top of file
1376 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_THUMB_HORZ : PART_THUMB_VERT,
1377 maThumbRect, rPt, bIsInside)?
1378 bIsInside:
1379 maThumbRect.IsInside( rPt ) )
1380 return &maThumbRect;
1381 else
1382 return NULL;
1383 }
1384
PreNotify(NotifyEvent & rNEvt)1385 long ScrollBar::PreNotify( NotifyEvent& rNEvt )
1386 {
1387 long nDone = 0;
1388 const MouseEvent* pMouseEvt = NULL;
1389
1390 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
1391 {
1392 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
1393 {
1394 // trigger redraw if mouse over state has changed
1395 if( IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
1396 {
1397 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
1398 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
1399 if( pRect != pLastRect || pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
1400 {
1401 Region aRgn( GetActiveClipRegion() );
1402 Region aClipRegion;
1403
1404 if ( pRect )
1405 aClipRegion.Union( *pRect );
1406 if ( pLastRect )
1407 aClipRegion.Union( *pLastRect );
1408
1409 // Support for 3-button scroll bars
1410 sal_Bool bHas3Buttons = IsNativeControlSupported( CTRL_SCROLLBAR, HAS_THREE_BUTTONS );
1411 if ( bHas3Buttons && ( pRect == &maBtn1Rect || pLastRect == &maBtn1Rect ) )
1412 {
1413 aClipRegion.Union( maBtn2Rect );
1414 }
1415
1416 SetClipRegion( aClipRegion );
1417 Paint( aClipRegion.GetBoundRect() );
1418
1419 SetClipRegion( aRgn );
1420 }
1421 }
1422 }
1423 }
1424
1425 return nDone ? nDone : Control::PreNotify(rNEvt);
1426 }
1427
1428 // -----------------------------------------------------------------------
1429
Scroll()1430 void ScrollBar::Scroll()
1431 {
1432 ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_SCROLL, maScrollHdl, this );
1433 }
1434
1435 // -----------------------------------------------------------------------
1436
EndScroll()1437 void ScrollBar::EndScroll()
1438 {
1439 ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_ENDSCROLL, maEndScrollHdl, this );
1440 }
1441
1442 // -----------------------------------------------------------------------
1443
DoScroll(long nNewPos)1444 long ScrollBar::DoScroll( long nNewPos )
1445 {
1446 if ( meScrollType != SCROLL_DONTKNOW )
1447 return 0;
1448
1449 meScrollType = SCROLL_DRAG;
1450 long nDelta = ImplScroll( nNewPos, sal_True );
1451 meScrollType = SCROLL_DONTKNOW;
1452 return nDelta;
1453 }
1454
1455 // -----------------------------------------------------------------------
1456
DoScrollAction(ScrollType eScrollType)1457 long ScrollBar::DoScrollAction( ScrollType eScrollType )
1458 {
1459 if ( (meScrollType != SCROLL_DONTKNOW) ||
1460 (eScrollType == SCROLL_DONTKNOW) ||
1461 (eScrollType == SCROLL_DRAG) )
1462 return 0;
1463
1464 meScrollType = eScrollType;
1465 long nDelta = ImplDoAction( sal_True );
1466 meScrollType = SCROLL_DONTKNOW;
1467 return nDelta;
1468 }
1469
1470 // -----------------------------------------------------------------------
1471
SetRangeMin(long nNewRange)1472 void ScrollBar::SetRangeMin( long nNewRange )
1473 {
1474 SetRange( Range( nNewRange, GetRangeMax() ) );
1475 }
1476
1477 // -----------------------------------------------------------------------
1478
SetRangeMax(long nNewRange)1479 void ScrollBar::SetRangeMax( long nNewRange )
1480 {
1481 SetRange( Range( GetRangeMin(), nNewRange ) );
1482 }
1483
1484 // -----------------------------------------------------------------------
1485
SetRange(const Range & rRange)1486 void ScrollBar::SetRange( const Range& rRange )
1487 {
1488 // Range einpassen
1489 Range aRange = rRange;
1490 aRange.Justify();
1491 long nNewMinRange = aRange.Min();
1492 long nNewMaxRange = aRange.Max();
1493
1494 // Wenn Range sich unterscheidet, dann neuen setzen
1495 if ( (mnMinRange != nNewMinRange) ||
1496 (mnMaxRange != nNewMaxRange) )
1497 {
1498 mnMinRange = nNewMinRange;
1499 mnMaxRange = nNewMaxRange;
1500
1501 // Thumb einpassen
1502 if ( mnThumbPos > mnMaxRange-mnVisibleSize )
1503 mnThumbPos = mnMaxRange-mnVisibleSize;
1504 if ( mnThumbPos < mnMinRange )
1505 mnThumbPos = mnMinRange;
1506
1507 StateChanged( STATE_CHANGE_DATA );
1508 }
1509 }
1510
1511 // -----------------------------------------------------------------------
1512
SetThumbPos(long nNewThumbPos)1513 void ScrollBar::SetThumbPos( long nNewThumbPos )
1514 {
1515 if ( nNewThumbPos > mnMaxRange-mnVisibleSize )
1516 nNewThumbPos = mnMaxRange-mnVisibleSize;
1517 if ( nNewThumbPos < mnMinRange )
1518 nNewThumbPos = mnMinRange;
1519
1520 if ( mnThumbPos != nNewThumbPos )
1521 {
1522 mnThumbPos = nNewThumbPos;
1523 StateChanged( STATE_CHANGE_DATA );
1524 }
1525 }
1526
1527 // -----------------------------------------------------------------------
1528
SetVisibleSize(long nNewSize)1529 void ScrollBar::SetVisibleSize( long nNewSize )
1530 {
1531 if ( mnVisibleSize != nNewSize )
1532 {
1533 mnVisibleSize = nNewSize;
1534
1535 // Thumb einpassen
1536 if ( mnThumbPos > mnMaxRange-mnVisibleSize )
1537 mnThumbPos = mnMaxRange-mnVisibleSize;
1538 if ( mnThumbPos < mnMinRange )
1539 mnThumbPos = mnMinRange;
1540 StateChanged( STATE_CHANGE_DATA );
1541 }
1542 }
1543
1544 // =======================================================================
1545
ImplInit(Window * pParent,WinBits nStyle)1546 void ScrollBarBox::ImplInit( Window* pParent, WinBits nStyle )
1547 {
1548 Window::ImplInit( pParent, nStyle, NULL );
1549
1550 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1551 long nScrollSize = rStyleSettings.GetScrollBarSize();
1552 SetSizePixel( Size( nScrollSize, nScrollSize ) );
1553 ImplInitSettings();
1554 }
1555
1556 // -----------------------------------------------------------------------
1557
ScrollBarBox(Window * pParent,WinBits nStyle)1558 ScrollBarBox::ScrollBarBox( Window* pParent, WinBits nStyle ) :
1559 Window( WINDOW_SCROLLBARBOX )
1560 {
1561 ImplInit( pParent, nStyle );
1562 }
1563
1564 // -----------------------------------------------------------------------
1565
ScrollBarBox(Window * pParent,const ResId & rResId)1566 ScrollBarBox::ScrollBarBox( Window* pParent, const ResId& rResId ) :
1567 Window( WINDOW_SCROLLBARBOX )
1568 {
1569 rResId.SetRT( RSC_SCROLLBAR );
1570 ImplInit( pParent, ImplInitRes( rResId ) );
1571 ImplLoadRes( rResId );
1572 }
1573
1574 // -----------------------------------------------------------------------
1575
ImplInitSettings()1576 void ScrollBarBox::ImplInitSettings()
1577 {
1578 // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann
1579 // und noch nicht alles umgestellt ist
1580 if ( IsBackground() )
1581 {
1582 Color aColor;
1583 if ( IsControlBackground() )
1584 aColor = GetControlBackground();
1585 else
1586 aColor = GetSettings().GetStyleSettings().GetFaceColor();
1587 SetBackground( aColor );
1588 }
1589 }
1590
1591 // -----------------------------------------------------------------------
1592
StateChanged(StateChangedType nType)1593 void ScrollBarBox::StateChanged( StateChangedType nType )
1594 {
1595 Window::StateChanged( nType );
1596
1597 if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1598 {
1599 ImplInitSettings();
1600 Invalidate();
1601 }
1602 }
1603
1604 // -----------------------------------------------------------------------
1605
DataChanged(const DataChangedEvent & rDCEvt)1606 void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt )
1607 {
1608 Window::DataChanged( rDCEvt );
1609
1610 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1611 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1612 {
1613 ImplInitSettings();
1614 Invalidate();
1615 }
1616 }
1617