Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "vcl/event.hxx"
21 : #include "vcl/decoview.hxx"
22 : #include "vcl/scrbar.hxx"
23 : #include "vcl/timer.hxx"
24 : #include "vcl/settings.hxx"
25 :
26 : #include "svdata.hxx"
27 :
28 : #include "rtl/string.hxx"
29 : #include "tools/rc.h"
30 :
31 : /* #i77549#
32 : HACK: for scrollbars in case of thumb rect, page up and page down rect we
33 : abuse the HitTestNativeControl interface. All theming engines but OS X
34 : are actually able to draw the thumb according to our internal representation.
35 : However OS X draws a little outside. The canonical way would be to enhance the
36 : HitTestNativeControl passing a ScrollbarValue additionally so all necessary
37 : information is available in the call.
38 : .
39 : However since there is only this one small exception we will deviate a little and
40 : instead pass the respective rect as control region to allow for a small correction.
41 :
42 : So all places using HitTestNativeControl on PART_THUMB_HORZ, PART_THUMB_VERT,
43 : PART_TRACK_HORZ_LEFT, PART_TRACK_HORZ_RIGHT, PART_TRACK_VERT_UPPER, PART_TRACK_VERT_LOWER
44 : do not use the control rectangle as region but the actuall part rectangle, making
45 : only small deviations feasible.
46 : */
47 :
48 : #include "thumbpos.hxx"
49 :
50 : #define SCRBAR_DRAW_BTN1 ((sal_uInt16)0x0001)
51 : #define SCRBAR_DRAW_BTN2 ((sal_uInt16)0x0002)
52 : #define SCRBAR_DRAW_PAGE1 ((sal_uInt16)0x0004)
53 : #define SCRBAR_DRAW_PAGE2 ((sal_uInt16)0x0008)
54 : #define SCRBAR_DRAW_THUMB ((sal_uInt16)0x0010)
55 : #define SCRBAR_DRAW_BACKGROUND ((sal_uInt16)0x0020)
56 : #define SCRBAR_DRAW_ALL (SCRBAR_DRAW_BTN1 | SCRBAR_DRAW_BTN2 | \
57 : SCRBAR_DRAW_PAGE1 | SCRBAR_DRAW_PAGE2 |\
58 : SCRBAR_DRAW_THUMB | SCRBAR_DRAW_BACKGROUND )
59 :
60 : #define SCRBAR_STATE_BTN1_DOWN ((sal_uInt16)0x0001)
61 : #define SCRBAR_STATE_BTN1_DISABLE ((sal_uInt16)0x0002)
62 : #define SCRBAR_STATE_BTN2_DOWN ((sal_uInt16)0x0004)
63 : #define SCRBAR_STATE_BTN2_DISABLE ((sal_uInt16)0x0008)
64 : #define SCRBAR_STATE_PAGE1_DOWN ((sal_uInt16)0x0010)
65 : #define SCRBAR_STATE_PAGE2_DOWN ((sal_uInt16)0x0020)
66 : #define SCRBAR_STATE_THUMB_DOWN ((sal_uInt16)0x0040)
67 :
68 : #define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
69 :
70 35650 : struct ImplScrollBarData
71 : {
72 : AutoTimer maTimer; // Timer
73 : bool mbHide;
74 : Rectangle maTrackRect; // TODO: move to ScrollBar class when binary incompatibility of ScrollBar class is no longer problematic
75 : };
76 :
77 17843 : void ScrollBar::ImplInit( vcl::Window* pParent, WinBits nStyle )
78 : {
79 17843 : mpData = NULL;
80 17843 : mnThumbPixRange = 0;
81 17843 : mnThumbPixPos = 0;
82 17843 : mnThumbPixSize = 0;
83 17843 : mnMinRange = 0;
84 17843 : mnMaxRange = 100;
85 17843 : mnThumbPos = 0;
86 17843 : mnVisibleSize = 0;
87 17843 : mnLineSize = 1;
88 17843 : mnPageSize = 1;
89 17843 : mnDelta = 0;
90 17843 : mnDragDraw = 0;
91 17843 : mnStateFlags = 0;
92 17843 : meScrollType = SCROLL_DONTKNOW;
93 17843 : meDDScrollType = SCROLL_DONTKNOW;
94 17843 : mbCalcSize = true;
95 17843 : mbFullDrag = false;
96 :
97 17843 : if( !mpData ) // TODO: remove when maTrackRect is no longer in mpData
98 : {
99 17843 : mpData = new ImplScrollBarData;
100 17843 : mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
101 17843 : mpData->mbHide = false;
102 : }
103 :
104 17843 : ImplInitStyle( nStyle );
105 17843 : Control::ImplInit( pParent, nStyle, NULL );
106 :
107 17843 : long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
108 17843 : SetSizePixel( Size( nScrollSize, nScrollSize ) );
109 17843 : }
110 :
111 17844 : void ScrollBar::ImplInitStyle( WinBits nStyle )
112 : {
113 17844 : if ( nStyle & WB_DRAG )
114 9001 : mbFullDrag = true;
115 : else
116 8843 : mbFullDrag = bool(GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Scroll);
117 17844 : }
118 :
119 17843 : ScrollBar::ScrollBar( vcl::Window* pParent, WinBits nStyle ) :
120 17843 : Control( WINDOW_SCROLLBAR )
121 : {
122 17843 : ImplInit( pParent, nStyle );
123 17843 : }
124 :
125 47847 : ScrollBar::~ScrollBar()
126 : {
127 17807 : disposeOnce();
128 30040 : }
129 :
130 17807 : void ScrollBar::dispose()
131 : {
132 17807 : delete mpData; mpData = NULL;
133 17807 : Control::dispose();
134 17807 : }
135 :
136 32261 : void ScrollBar::ImplUpdateRects( bool bUpdate )
137 : {
138 32261 : sal_uInt16 nOldStateFlags = mnStateFlags;
139 32261 : Rectangle aOldPage1Rect = maPage1Rect;
140 32261 : Rectangle aOldPage2Rect = maPage2Rect;
141 32261 : Rectangle aOldThumbRect = maThumbRect;
142 :
143 32261 : mnStateFlags &= ~SCRBAR_STATE_BTN1_DISABLE;
144 32261 : mnStateFlags &= ~SCRBAR_STATE_BTN2_DISABLE;
145 :
146 32261 : Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
147 32261 : if ( mnThumbPixRange )
148 : {
149 30548 : if ( GetStyle() & WB_HORZ )
150 : {
151 14823 : maThumbRect.Left() = maTrackRect.Left()+mnThumbPixPos;
152 14823 : maThumbRect.Right() = maThumbRect.Left()+mnThumbPixSize-1;
153 14823 : if ( !mnThumbPixPos )
154 13730 : maPage1Rect.Right() = RECT_EMPTY;
155 : else
156 1093 : maPage1Rect.Right() = maThumbRect.Left()-1;
157 14823 : if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
158 369 : maPage2Rect.Right() = RECT_EMPTY;
159 : else
160 : {
161 14454 : maPage2Rect.Left() = maThumbRect.Right()+1;
162 14454 : maPage2Rect.Right() = maTrackRect.Right();
163 : }
164 : }
165 : else
166 : {
167 15725 : maThumbRect.Top() = maTrackRect.Top()+mnThumbPixPos;
168 15725 : maThumbRect.Bottom() = maThumbRect.Top()+mnThumbPixSize-1;
169 15725 : if ( !mnThumbPixPos )
170 14698 : maPage1Rect.Bottom() = RECT_EMPTY;
171 : else
172 1027 : maPage1Rect.Bottom() = maThumbRect.Top()-1;
173 15725 : if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
174 288 : maPage2Rect.Bottom() = RECT_EMPTY;
175 : else
176 : {
177 15437 : maPage2Rect.Top() = maThumbRect.Bottom()+1;
178 15437 : maPage2Rect.Bottom() = maTrackRect.Bottom();
179 : }
180 : }
181 : }
182 : else
183 : {
184 1713 : if ( GetStyle() & WB_HORZ )
185 : {
186 895 : const long nSpace = maTrackRect.Right() - maTrackRect.Left();
187 895 : if ( nSpace > 0 )
188 : {
189 0 : maPage1Rect.Left() = maTrackRect.Left();
190 0 : maPage1Rect.Right() = maTrackRect.Left() + (nSpace/2);
191 0 : maPage2Rect.Left() = maPage1Rect.Right() + 1;
192 0 : maPage2Rect.Right() = maTrackRect.Right();
193 : }
194 : }
195 : else
196 : {
197 818 : const long nSpace = maTrackRect.Bottom() - maTrackRect.Top();
198 818 : if ( nSpace > 0 )
199 : {
200 0 : maPage1Rect.Top() = maTrackRect.Top();
201 0 : maPage1Rect.Bottom() = maTrackRect.Top() + (nSpace/2);
202 0 : maPage2Rect.Top() = maPage1Rect.Bottom() + 1;
203 0 : maPage2Rect.Bottom() = maTrackRect.Bottom();
204 : }
205 : }
206 : }
207 :
208 32261 : if( !IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
209 : {
210 : // disable scrollbar buttons only in VCL's own 'theme'
211 : // as it is uncommon on other platforms
212 32255 : if ( mnThumbPos == mnMinRange )
213 30115 : mnStateFlags |= SCRBAR_STATE_BTN1_DISABLE;
214 32255 : if ( mnThumbPos >= (mnMaxRange-mnVisibleSize) )
215 758 : mnStateFlags |= SCRBAR_STATE_BTN2_DISABLE;
216 : }
217 :
218 32261 : if ( bUpdate )
219 : {
220 76 : sal_uInt16 nDraw = 0;
221 76 : if ( (nOldStateFlags & SCRBAR_STATE_BTN1_DISABLE) !=
222 : (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
223 7 : nDraw |= SCRBAR_DRAW_BTN1;
224 76 : if ( (nOldStateFlags & SCRBAR_STATE_BTN2_DISABLE) !=
225 : (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
226 22 : nDraw |= SCRBAR_DRAW_BTN2;
227 76 : if ( aOldPage1Rect != maPage1Rect )
228 53 : nDraw |= SCRBAR_DRAW_PAGE1;
229 76 : if ( aOldPage2Rect != maPage2Rect )
230 54 : nDraw |= SCRBAR_DRAW_PAGE2;
231 76 : if ( aOldThumbRect != maThumbRect )
232 54 : nDraw |= SCRBAR_DRAW_THUMB;
233 76 : Invalidate();
234 : }
235 32261 : }
236 :
237 0 : long ScrollBar::ImplCalcThumbPos( long nPixPos )
238 : {
239 : // Calculate position
240 : long nCalcThumbPos;
241 0 : nCalcThumbPos = ImplMulDiv( nPixPos, mnMaxRange-mnVisibleSize-mnMinRange,
242 0 : mnThumbPixRange-mnThumbPixSize );
243 0 : nCalcThumbPos += mnMinRange;
244 0 : return nCalcThumbPos;
245 : }
246 :
247 29967 : long ScrollBar::ImplCalcThumbPosPix( long nPos )
248 : {
249 : long nCalcThumbPos;
250 :
251 : // Calculate position
252 : nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-mnThumbPixSize,
253 29967 : mnMaxRange-mnVisibleSize-mnMinRange );
254 :
255 : // At the start and end of the ScrollBar, we try to show the display correctly
256 29967 : if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
257 11 : nCalcThumbPos = 1;
258 32090 : if ( nCalcThumbPos &&
259 2199 : ((nCalcThumbPos+mnThumbPixSize) >= mnThumbPixRange) &&
260 76 : (mnThumbPos < (mnMaxRange-mnVisibleSize)) )
261 3 : nCalcThumbPos--;
262 :
263 29967 : return nCalcThumbPos;
264 : }
265 :
266 32261 : void ScrollBar::ImplCalc( bool bUpdate )
267 : {
268 32261 : const Size aSize = GetOutputSizePixel();
269 32261 : const long nMinThumbSize = GetSettings().GetStyleSettings().GetMinThumbSize();
270 :
271 32261 : Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
272 32261 : if ( mbCalcSize )
273 : {
274 17976 : Size aOldSize = getCurrentCalcSize();
275 :
276 17976 : const Rectangle aControlRegion( Point(0,0), aSize );
277 17976 : Rectangle aBtn1Region, aBtn2Region, aTrackRegion, aBoundingRegion;
278 :
279 17976 : if ( GetStyle() & WB_HORZ )
280 : {
281 26415 : if ( GetNativeControlRegion( CTRL_SCROLLBAR, IsRTLEnabled()? PART_BUTTON_RIGHT: PART_BUTTON_LEFT,
282 35226 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(), aBoundingRegion, aBtn1Region ) &&
283 2 : GetNativeControlRegion( CTRL_SCROLLBAR, IsRTLEnabled()? PART_BUTTON_LEFT: PART_BUTTON_RIGHT,
284 8811 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(), aBoundingRegion, aBtn2Region ) )
285 : {
286 2 : maBtn1Rect = aBtn1Region;
287 2 : maBtn2Rect = aBtn2Region;
288 : }
289 : else
290 : {
291 8803 : Size aBtnSize( aSize.Height(), aSize.Height() );
292 8803 : maBtn2Rect.Top() = maBtn1Rect.Top();
293 8803 : maBtn2Rect.Left() = aSize.Width()-aSize.Height();
294 8803 : maBtn1Rect.SetSize( aBtnSize );
295 8803 : maBtn2Rect.SetSize( aBtnSize );
296 : }
297 :
298 17610 : if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_HORZ_AREA,
299 17610 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(), aBoundingRegion, aTrackRegion ) )
300 0 : maTrackRect = aTrackRegion;
301 : else
302 8805 : maTrackRect = Rectangle( maBtn1Rect.TopRight(), maBtn2Rect.BottomLeft() );
303 :
304 : // Check if available space is big enough for thumb ( min thumb size = ScrBar width/height )
305 8805 : mnThumbPixRange = maTrackRect.Right() - maTrackRect.Left();
306 8805 : if( mnThumbPixRange > 0 )
307 : {
308 7985 : maPage1Rect.Left() = maTrackRect.Left();
309 7985 : maPage1Rect.Bottom() =
310 7985 : maPage2Rect.Bottom() =
311 7985 : maThumbRect.Bottom() = maTrackRect.Bottom();
312 : }
313 : else
314 : {
315 820 : mnThumbPixRange = 0;
316 820 : maPage1Rect.SetEmpty();
317 820 : maPage2Rect.SetEmpty();
318 : }
319 : }
320 : else
321 : {
322 18342 : if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_UP,
323 27519 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(), aBoundingRegion, aBtn1Region ) &&
324 : GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_DOWN,
325 9177 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(), aBoundingRegion, aBtn2Region ) )
326 : {
327 2 : maBtn1Rect = aBtn1Region;
328 2 : maBtn2Rect = aBtn2Region;
329 : }
330 : else
331 : {
332 9169 : const Size aBtnSize( aSize.Width(), aSize.Width() );
333 9169 : maBtn2Rect.Left() = maBtn1Rect.Left();
334 9169 : maBtn2Rect.Top() = aSize.Height()-aSize.Width();
335 9169 : maBtn1Rect.SetSize( aBtnSize );
336 9169 : maBtn2Rect.SetSize( aBtnSize );
337 : }
338 :
339 18342 : if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_VERT_AREA,
340 18342 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(), aBoundingRegion, aTrackRegion ) )
341 0 : maTrackRect = aTrackRegion;
342 : else
343 9171 : maTrackRect = Rectangle( maBtn1Rect.BottomLeft()+Point(0,1), maBtn2Rect.TopRight() );
344 :
345 : // Check if available space is big enough for thumb
346 9171 : mnThumbPixRange = maTrackRect.Bottom() - maTrackRect.Top();
347 9171 : if( mnThumbPixRange > 0 )
348 : {
349 8361 : maPage1Rect.Top() = maTrackRect.Top();
350 8361 : maPage1Rect.Right() =
351 8361 : maPage2Rect.Right() =
352 8361 : maThumbRect.Right() = maTrackRect.Right();
353 : }
354 : else
355 : {
356 810 : mnThumbPixRange = 0;
357 810 : maPage1Rect.SetEmpty();
358 810 : maPage2Rect.SetEmpty();
359 : }
360 : }
361 :
362 17976 : if ( !mnThumbPixRange )
363 1630 : maThumbRect.SetEmpty();
364 :
365 17976 : mbCalcSize = false;
366 :
367 17976 : Size aNewSize = getCurrentCalcSize();
368 17976 : if (aOldSize != aNewSize)
369 : {
370 17087 : queue_resize();
371 : }
372 : }
373 :
374 32261 : if ( mnThumbPixRange )
375 : {
376 : // Calculate values
377 60516 : if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) ||
378 29968 : ((mnMaxRange-mnMinRange) <= 0) )
379 : {
380 581 : mnThumbPos = mnMinRange;
381 581 : mnThumbPixPos = 0;
382 581 : mnThumbPixSize = mnThumbPixRange;
383 : }
384 : else
385 : {
386 29967 : if ( mnVisibleSize )
387 29745 : mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange );
388 : else
389 : {
390 222 : if ( GetStyle() & WB_HORZ )
391 40 : mnThumbPixSize = maThumbRect.GetWidth();
392 : else
393 182 : mnThumbPixSize = maThumbRect.GetHeight();
394 : }
395 29967 : if ( mnThumbPixSize < nMinThumbSize )
396 396 : mnThumbPixSize = nMinThumbSize;
397 29967 : if ( mnThumbPixSize > mnThumbPixRange )
398 3 : mnThumbPixSize = mnThumbPixRange;
399 29967 : mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
400 : }
401 : }
402 :
403 : // If we're ought to ouput again and we have been triggered
404 : // a Paint event via an Action, we don't output directly,
405 : // but invalidate everything
406 32261 : if ( bUpdate && HasPaintEvent() )
407 : {
408 14246 : Invalidate();
409 14246 : bUpdate = false;
410 : }
411 32261 : ImplUpdateRects( bUpdate );
412 32261 : }
413 :
414 0 : void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& /* rSize */, DrawFlags nFlags )
415 : {
416 0 : Point aPos = pDev->LogicToPixel( rPos );
417 :
418 0 : pDev->Push();
419 0 : pDev->SetMapMode();
420 0 : if ( !(nFlags & DrawFlags::Mono) )
421 : {
422 : // DecoView uses the FaceColor...
423 0 : AllSettings aSettings = pDev->GetSettings();
424 0 : StyleSettings aStyleSettings = aSettings.GetStyleSettings();
425 0 : if ( IsControlBackground() )
426 0 : aStyleSettings.SetFaceColor( GetControlBackground() );
427 : else
428 0 : aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
429 :
430 0 : aSettings.SetStyleSettings( aStyleSettings );
431 0 : pDev->SetSettings( aSettings );
432 : }
433 :
434 : // For printing:
435 : // - calculate the size of the rects
436 : // - because this is zero-based add the correct offset
437 : // - print
438 : // - force recalculate
439 :
440 0 : if ( mbCalcSize )
441 0 : ImplCalc( false );
442 :
443 0 : maBtn1Rect+=aPos;
444 0 : maBtn2Rect+=aPos;
445 0 : maThumbRect+=aPos;
446 0 : mpData->maTrackRect+=aPos; // TODO: update when maTrackRect is no longer in mpData
447 0 : maPage1Rect+=aPos;
448 0 : maPage2Rect+=aPos;
449 :
450 0 : ImplDraw(*pDev, SCRBAR_DRAW_ALL);
451 0 : pDev->Pop();
452 :
453 0 : mbCalcSize = true;
454 0 : }
455 :
456 87055 : bool ScrollBar::ImplDrawNative(vcl::RenderContext& rRenderContext, sal_uInt16 nDrawFlags)
457 : {
458 87055 : ScrollbarValue scrValue;
459 :
460 87055 : bool bNativeOK = rRenderContext.IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL);
461 87055 : if (!bNativeOK)
462 87055 : return false;
463 :
464 0 : bool bHorz = (GetStyle() & WB_HORZ) != 0;
465 :
466 : // Draw the entire background if the control supports it
467 0 : if (rRenderContext.IsNativeControlSupported(CTRL_SCROLLBAR, bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT))
468 : {
469 0 : ControlState nState = (IsEnabled() ? ControlState::ENABLED : ControlState::NONE)
470 0 : | (HasFocus() ? ControlState::FOCUSED : ControlState::NONE);
471 :
472 0 : scrValue.mnMin = mnMinRange;
473 0 : scrValue.mnMax = mnMaxRange;
474 0 : scrValue.mnCur = mnThumbPos;
475 0 : scrValue.mnVisibleSize = mnVisibleSize;
476 0 : scrValue.maThumbRect = maThumbRect;
477 0 : scrValue.maButton1Rect = maBtn1Rect;
478 0 : scrValue.maButton2Rect = maBtn2Rect;
479 0 : scrValue.mnButton1State = ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? ControlState::PRESSED : ControlState::NONE) |
480 0 : ((!(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)) ? ControlState::ENABLED : ControlState::NONE);
481 0 : scrValue.mnButton2State = ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? ControlState::PRESSED : ControlState::NONE) |
482 0 : ((!(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)) ? ControlState::ENABLED : ControlState::NONE);
483 0 : scrValue.mnThumbState = nState | ((mnStateFlags & SCRBAR_STATE_THUMB_DOWN) ? ControlState::PRESSED : ControlState::NONE);
484 0 : scrValue.mnPage1State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? ControlState::PRESSED : ControlState::NONE);
485 0 : scrValue.mnPage2State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? ControlState::PRESSED : ControlState::NONE);
486 :
487 0 : if (IsMouseOver())
488 : {
489 0 : Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
490 0 : if (pRect)
491 : {
492 0 : if (pRect == &maThumbRect)
493 0 : scrValue.mnThumbState |= ControlState::ROLLOVER;
494 0 : else if (pRect == &maBtn1Rect)
495 0 : scrValue.mnButton1State |= ControlState::ROLLOVER;
496 0 : else if (pRect == &maBtn2Rect)
497 0 : scrValue.mnButton2State |= ControlState::ROLLOVER;
498 0 : else if (pRect == &maPage1Rect)
499 0 : scrValue.mnPage1State |= ControlState::ROLLOVER;
500 0 : else if (pRect == &maPage2Rect)
501 0 : scrValue.mnPage2State |= ControlState::ROLLOVER;
502 : }
503 : }
504 :
505 0 : Rectangle aCtrlRegion;
506 0 : aCtrlRegion.Union(maBtn1Rect);
507 0 : aCtrlRegion.Union(maBtn2Rect);
508 0 : aCtrlRegion.Union(maPage1Rect);
509 0 : aCtrlRegion.Union(maPage2Rect);
510 0 : aCtrlRegion.Union(maThumbRect);
511 :
512 0 : Rectangle aRequestedRegion(Point(0,0), rRenderContext.GetOutputSizePixel());
513 : // if the actual native control region is smaller then the region that
514 : // we requested the control to draw in, then draw a background rectangle
515 : // to avoid drawing artifacts in the uncovered region
516 0 : if (aCtrlRegion.GetWidth() < aRequestedRegion.GetWidth() ||
517 0 : aCtrlRegion.GetHeight() < aRequestedRegion.GetHeight())
518 : {
519 0 : Color aFaceColor = rRenderContext.GetSettings().GetStyleSettings().GetFaceColor();
520 0 : rRenderContext.SetFillColor(aFaceColor);
521 0 : rRenderContext.SetLineColor(aFaceColor);
522 0 : rRenderContext.DrawRect(aRequestedRegion);
523 : }
524 :
525 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_SCROLLBAR, (bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT),
526 0 : aCtrlRegion, nState, scrValue, OUString());
527 : }
528 : else
529 : {
530 0 : if ((nDrawFlags & SCRBAR_DRAW_PAGE1) || (nDrawFlags & SCRBAR_DRAW_PAGE2))
531 : {
532 0 : sal_uInt32 part1 = bHorz ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER;
533 0 : sal_uInt32 part2 = bHorz ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER;
534 0 : Rectangle aCtrlRegion1(maPage1Rect);
535 0 : Rectangle aCtrlRegion2(maPage2Rect);
536 0 : ControlState nState1 = (IsEnabled() ? ControlState::ENABLED : ControlState::NONE)
537 0 : | (HasFocus() ? ControlState::FOCUSED : ControlState::NONE);
538 0 : ControlState nState2 = nState1;
539 :
540 0 : nState1 |= ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? ControlState::PRESSED : ControlState::NONE);
541 0 : nState2 |= ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? ControlState::PRESSED : ControlState::NONE);
542 :
543 0 : if (IsMouseOver())
544 : {
545 0 : Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
546 0 : if (pRect)
547 : {
548 0 : if (pRect == &maPage1Rect)
549 0 : nState1 |= ControlState::ROLLOVER;
550 0 : else if (pRect == &maPage2Rect)
551 0 : nState2 |= ControlState::ROLLOVER;
552 : }
553 : }
554 :
555 0 : if (nDrawFlags & SCRBAR_DRAW_PAGE1)
556 0 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1, scrValue, OUString());
557 :
558 0 : if (nDrawFlags & SCRBAR_DRAW_PAGE2)
559 0 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2, scrValue, OUString());
560 : }
561 0 : if ((nDrawFlags & SCRBAR_DRAW_BTN1) || (nDrawFlags & SCRBAR_DRAW_BTN2))
562 : {
563 0 : sal_uInt32 part1 = bHorz ? PART_BUTTON_LEFT : PART_BUTTON_UP;
564 0 : sal_uInt32 part2 = bHorz ? PART_BUTTON_RIGHT : PART_BUTTON_DOWN;
565 0 : Rectangle aCtrlRegion1(maBtn1Rect);
566 0 : Rectangle aCtrlRegion2(maBtn2Rect);
567 0 : ControlState nState1 = HasFocus() ? ControlState::FOCUSED : ControlState::NONE;
568 0 : ControlState nState2 = nState1;
569 :
570 0 : if (!Window::IsEnabled() || !IsEnabled())
571 0 : nState1 = (nState2 &= ~ControlState::ENABLED);
572 : else
573 0 : nState1 = (nState2 |= ControlState::ENABLED);
574 :
575 0 : nState1 |= ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? ControlState::PRESSED : ControlState::NONE);
576 0 : nState2 |= ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? ControlState::PRESSED : ControlState::NONE);
577 :
578 0 : if (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)
579 0 : nState1 &= ~ControlState::ENABLED;
580 0 : if (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)
581 0 : nState2 &= ~ControlState::ENABLED;
582 :
583 0 : if (IsMouseOver())
584 : {
585 0 : Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
586 0 : if (pRect)
587 : {
588 0 : if (pRect == &maBtn1Rect)
589 0 : nState1 |= ControlState::ROLLOVER;
590 0 : else if (pRect == &maBtn2Rect)
591 0 : nState2 |= ControlState::ROLLOVER;
592 : }
593 : }
594 :
595 0 : if (nDrawFlags & SCRBAR_DRAW_BTN1)
596 0 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1, scrValue, OUString());
597 :
598 0 : if (nDrawFlags & SCRBAR_DRAW_BTN2)
599 0 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2, scrValue, OUString());
600 : }
601 0 : if ((nDrawFlags & SCRBAR_DRAW_THUMB) && !maThumbRect.IsEmpty())
602 : {
603 0 : ControlState nState = IsEnabled() ? ControlState::ENABLED : ControlState::NONE;
604 0 : Rectangle aCtrlRegion(maThumbRect);
605 :
606 0 : if (mnStateFlags & SCRBAR_STATE_THUMB_DOWN)
607 0 : nState |= ControlState::PRESSED;
608 :
609 0 : if (HasFocus())
610 0 : nState |= ControlState::FOCUSED;
611 :
612 0 : if (IsMouseOver())
613 : {
614 0 : Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
615 0 : if (pRect)
616 : {
617 0 : if (pRect == &maThumbRect)
618 0 : nState |= ControlState::ROLLOVER;
619 : }
620 : }
621 :
622 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_SCROLLBAR, (bHorz ? PART_THUMB_HORZ : PART_THUMB_VERT),
623 0 : aCtrlRegion, nState, scrValue, OUString());
624 : }
625 : }
626 0 : return bNativeOK;
627 : }
628 :
629 17411 : void ScrollBar::ImplDraw(vcl::RenderContext& rRenderContext, sal_uInt16 nDrawFlags)
630 : {
631 17411 : DecorationView aDecoView(&rRenderContext);
632 17411 : Rectangle aTempRect;
633 : DrawButtonFlags nStyle;
634 17411 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
635 : SymbolType eSymbolType;
636 17411 : bool bEnabled = IsEnabled();
637 :
638 : // Finish some open calculations (if any)
639 17411 : if (mbCalcSize)
640 378 : ImplCalc(false);
641 :
642 : //vcl::Window *pWin = NULL;
643 : //if (rRenderContext.GetOutDevType() == OUTDEV_WINDOW)
644 : // pWin = static_cast<vcl::Window*>(&rRenderContext);
645 :
646 : // Draw the entire control if the native theme engine needs it
647 17411 : if (nDrawFlags && rRenderContext.IsNativeControlSupported(CTRL_SCROLLBAR, PART_DRAW_BACKGROUND_HORZ))
648 : {
649 0 : ImplDrawNative(rRenderContext, SCRBAR_DRAW_BACKGROUND);
650 17411 : return;
651 : }
652 :
653 17411 : if ((nDrawFlags & SCRBAR_DRAW_BTN1) && (!ImplDrawNative(rRenderContext, SCRBAR_DRAW_BTN1)))
654 : {
655 17411 : nStyle = DrawButtonFlags::NoLightBorder;
656 17411 : if (mnStateFlags & SCRBAR_STATE_BTN1_DOWN)
657 0 : nStyle |= DrawButtonFlags::Pressed;
658 17411 : aTempRect = aDecoView.DrawButton( maBtn1Rect, nStyle );
659 17411 : ImplCalcSymbolRect( aTempRect );
660 17411 : DrawSymbolFlags nSymbolStyle = DrawSymbolFlags::NONE;
661 17411 : if ((mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) || !bEnabled)
662 16935 : nSymbolStyle |= DrawSymbolFlags::Disable;
663 17411 : if (rStyleSettings.GetOptions() & StyleSettingsOptions::ScrollArrow)
664 : {
665 0 : if (GetStyle() & WB_HORZ)
666 0 : eSymbolType = SymbolType::ARROW_LEFT;
667 : else
668 0 : eSymbolType = SymbolType::ARROW_UP;
669 : }
670 : else
671 : {
672 17411 : if (GetStyle() & WB_HORZ)
673 6294 : eSymbolType = SymbolType::SPIN_LEFT;
674 : else
675 11117 : eSymbolType = SymbolType::SPIN_UP;
676 : }
677 17411 : aDecoView.DrawSymbol(aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nSymbolStyle);
678 : }
679 :
680 17411 : if ((nDrawFlags & SCRBAR_DRAW_BTN2) && (!ImplDrawNative(rRenderContext, SCRBAR_DRAW_BTN2)))
681 : {
682 17411 : nStyle = DrawButtonFlags::NoLightBorder;
683 17411 : if (mnStateFlags & SCRBAR_STATE_BTN2_DOWN)
684 0 : nStyle |= DrawButtonFlags::Pressed;
685 17411 : aTempRect = aDecoView.DrawButton(maBtn2Rect, nStyle);
686 17411 : ImplCalcSymbolRect(aTempRect);
687 17411 : DrawSymbolFlags nSymbolStyle = DrawSymbolFlags::NONE;
688 17411 : if ((mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) || !bEnabled)
689 291 : nSymbolStyle |= DrawSymbolFlags::Disable;
690 17411 : if (rStyleSettings.GetOptions() & StyleSettingsOptions::ScrollArrow)
691 : {
692 0 : if (GetStyle() & WB_HORZ)
693 0 : eSymbolType = SymbolType::ARROW_RIGHT;
694 : else
695 0 : eSymbolType = SymbolType::ARROW_DOWN;
696 : }
697 : else
698 : {
699 17411 : if (GetStyle() & WB_HORZ)
700 6294 : eSymbolType = SymbolType::SPIN_RIGHT;
701 : else
702 11117 : eSymbolType = SymbolType::SPIN_DOWN;
703 : }
704 17411 : aDecoView.DrawSymbol(aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nSymbolStyle);
705 : }
706 :
707 17411 : rRenderContext.SetLineColor();
708 :
709 17411 : if ((nDrawFlags & SCRBAR_DRAW_THUMB) && (!ImplDrawNative(rRenderContext, SCRBAR_DRAW_THUMB)))
710 : {
711 17411 : if (!maThumbRect.IsEmpty())
712 : {
713 17391 : if (bEnabled)
714 : {
715 17219 : nStyle = DrawButtonFlags::NoLightBorder;
716 17219 : aTempRect = aDecoView.DrawButton(maThumbRect, nStyle);
717 : }
718 : else
719 : {
720 172 : rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
721 172 : rRenderContext.DrawRect(maThumbRect);
722 : }
723 : }
724 : }
725 :
726 17411 : if ((nDrawFlags & SCRBAR_DRAW_PAGE1) && (!ImplDrawNative(rRenderContext, SCRBAR_DRAW_PAGE1)))
727 : {
728 17411 : if (mnStateFlags & SCRBAR_STATE_PAGE1_DOWN)
729 0 : rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
730 : else
731 17411 : rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
732 17411 : rRenderContext.DrawRect(maPage1Rect);
733 : }
734 17411 : if ((nDrawFlags & SCRBAR_DRAW_PAGE2) && (!ImplDrawNative(rRenderContext, SCRBAR_DRAW_PAGE2)))
735 : {
736 17411 : if (mnStateFlags & SCRBAR_STATE_PAGE2_DOWN)
737 0 : rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
738 : else
739 17411 : rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
740 17411 : rRenderContext.DrawRect(maPage2Rect);
741 17411 : }
742 : }
743 :
744 2 : long ScrollBar::ImplScroll( long nNewPos, bool bCallEndScroll )
745 : {
746 2 : long nOldPos = mnThumbPos;
747 2 : SetThumbPos( nNewPos );
748 2 : long nDelta = mnThumbPos-nOldPos;
749 2 : if ( nDelta )
750 : {
751 2 : mnDelta = nDelta;
752 2 : Scroll();
753 2 : if ( bCallEndScroll )
754 2 : EndScroll();
755 2 : mnDelta = 0;
756 : }
757 2 : return nDelta;
758 : }
759 :
760 2 : long ScrollBar::ImplDoAction( bool bCallEndScroll )
761 : {
762 2 : long nDelta = 0;
763 :
764 2 : switch ( meScrollType )
765 : {
766 : case SCROLL_LINEUP:
767 0 : nDelta = ImplScroll( mnThumbPos-mnLineSize, bCallEndScroll );
768 0 : break;
769 :
770 : case SCROLL_LINEDOWN:
771 2 : nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll );
772 2 : break;
773 :
774 : case SCROLL_PAGEUP:
775 0 : nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll );
776 0 : break;
777 :
778 : case SCROLL_PAGEDOWN:
779 0 : nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll );
780 0 : break;
781 : default:
782 : ;
783 : }
784 :
785 2 : return nDelta;
786 : }
787 :
788 0 : void ScrollBar::ImplDoMouseAction( const Point& rMousePos, bool bCallAction )
789 : {
790 0 : sal_uInt16 nOldStateFlags = mnStateFlags;
791 0 : bool bAction = false;
792 0 : bool bHorizontal = ( GetStyle() & WB_HORZ ) != 0;
793 0 : bool bIsInside = false;
794 :
795 0 : Point aPoint( 0, 0 );
796 0 : Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
797 :
798 0 : switch ( meScrollType )
799 : {
800 : case SCROLL_LINEUP:
801 0 : if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_RIGHT: PART_BUTTON_LEFT): PART_BUTTON_UP,
802 0 : aControlRegion, rMousePos, bIsInside )?
803 : bIsInside:
804 0 : maBtn1Rect.IsInside( rMousePos ) )
805 : {
806 0 : bAction = bCallAction;
807 0 : mnStateFlags |= SCRBAR_STATE_BTN1_DOWN;
808 : }
809 : else
810 0 : mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN;
811 0 : break;
812 :
813 : case SCROLL_LINEDOWN:
814 0 : if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_LEFT: PART_BUTTON_RIGHT): PART_BUTTON_DOWN,
815 0 : aControlRegion, rMousePos, bIsInside )?
816 : bIsInside:
817 0 : maBtn2Rect.IsInside( rMousePos ) )
818 : {
819 0 : bAction = bCallAction;
820 0 : mnStateFlags |= SCRBAR_STATE_BTN2_DOWN;
821 : }
822 : else
823 0 : mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN;
824 0 : break;
825 :
826 : case SCROLL_PAGEUP:
827 : // HitTestNativeControl, see remark at top of file
828 0 : if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT: PART_TRACK_VERT_UPPER,
829 0 : maPage1Rect, rMousePos, bIsInside )?
830 : bIsInside:
831 0 : maPage1Rect.IsInside( rMousePos ) )
832 : {
833 0 : bAction = bCallAction;
834 0 : mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN;
835 : }
836 : else
837 0 : mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN;
838 0 : break;
839 :
840 : case SCROLL_PAGEDOWN:
841 : // HitTestNativeControl, see remark at top of file
842 0 : if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_RIGHT: PART_TRACK_VERT_LOWER,
843 0 : maPage2Rect, rMousePos, bIsInside )?
844 : bIsInside:
845 0 : maPage2Rect.IsInside( rMousePos ) )
846 : {
847 0 : bAction = bCallAction;
848 0 : mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
849 : }
850 : else
851 0 : mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
852 0 : break;
853 : default:
854 : ;
855 : }
856 :
857 0 : if ( nOldStateFlags != mnStateFlags )
858 0 : Invalidate();
859 0 : if ( bAction )
860 0 : ImplDoAction( false );
861 0 : }
862 :
863 0 : void ScrollBar::ImplDragThumb( const Point& rMousePos )
864 : {
865 : long nMovePix;
866 0 : if ( GetStyle() & WB_HORZ )
867 0 : nMovePix = rMousePos.X()-(maThumbRect.Left()+mnMouseOff);
868 : else
869 0 : nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff);
870 :
871 : // Move thumb if necessary
872 0 : if ( nMovePix )
873 : {
874 0 : mnThumbPixPos += nMovePix;
875 0 : if ( mnThumbPixPos < 0 )
876 0 : mnThumbPixPos = 0;
877 0 : if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) )
878 0 : mnThumbPixPos = mnThumbPixRange-mnThumbPixSize;
879 0 : long nOldPos = mnThumbPos;
880 0 : mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
881 0 : ImplUpdateRects();
882 0 : if ( mbFullDrag && (nOldPos != mnThumbPos) )
883 : {
884 0 : mnDelta = mnThumbPos-nOldPos;
885 0 : Scroll();
886 0 : mnDelta = 0;
887 : }
888 : }
889 0 : }
890 :
891 0 : void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
892 : {
893 0 : bool bPrimaryWarps = GetSettings().GetStyleSettings().GetPrimaryButtonWarpsSlider();
894 0 : bool bWarp = bPrimaryWarps ? rMEvt.IsLeft() : rMEvt.IsMiddle();
895 0 : bool bPrimaryWarping = bWarp && rMEvt.IsLeft();
896 0 : bool bPage = bPrimaryWarps ? rMEvt.IsRight() : rMEvt.IsLeft();
897 :
898 0 : if (rMEvt.IsLeft() || rMEvt.IsMiddle() || rMEvt.IsRight())
899 : {
900 0 : const Point& rMousePos = rMEvt.GetPosPixel();
901 0 : StartTrackingFlags nTrackFlags = StartTrackingFlags::NONE;
902 0 : bool bHorizontal = ( GetStyle() & WB_HORZ ) != 0;
903 0 : bool bIsInside = false;
904 0 : bool bDragToMouse = false;
905 :
906 0 : Point aPoint( 0, 0 );
907 0 : Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
908 :
909 0 : if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_RIGHT: PART_BUTTON_LEFT): PART_BUTTON_UP,
910 0 : aControlRegion, rMousePos, bIsInside )?
911 : bIsInside:
912 0 : maBtn1Rect.IsInside( rMousePos ) )
913 : {
914 0 : if (rMEvt.IsLeft() && !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
915 : {
916 0 : nTrackFlags = StartTrackingFlags::ButtonRepeat;
917 0 : meScrollType = SCROLL_LINEUP;
918 0 : mnDragDraw = SCRBAR_DRAW_BTN1;
919 : }
920 : }
921 0 : else if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_LEFT: PART_BUTTON_RIGHT): PART_BUTTON_DOWN,
922 0 : aControlRegion, rMousePos, bIsInside )?
923 : bIsInside:
924 0 : maBtn2Rect.IsInside( rMousePos ) )
925 : {
926 0 : if (rMEvt.IsLeft() && !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
927 : {
928 0 : nTrackFlags = StartTrackingFlags::ButtonRepeat;
929 0 : meScrollType = SCROLL_LINEDOWN;
930 0 : mnDragDraw = SCRBAR_DRAW_BTN2;
931 : }
932 : }
933 : else
934 : {
935 : bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT,
936 0 : maThumbRect, rMousePos, bIsInside )
937 0 : ? bIsInside : maThumbRect.IsInside( rMousePos );
938 :
939 0 : bool bThumbAction = bWarp || bPage;
940 :
941 0 : bool bDragHandling = bWarp || (bThumbHit && bThumbAction);
942 0 : if( bDragHandling )
943 : {
944 0 : if( mpData )
945 : {
946 0 : mpData->mbHide = true; // disable focus blinking
947 0 : if (HasFocus())
948 : {
949 0 : mnStateFlags |= SCRBAR_DRAW_THUMB; // paint without focus
950 0 : Invalidate();
951 : }
952 : }
953 :
954 0 : if ( mnVisibleSize < mnMaxRange-mnMinRange )
955 : {
956 0 : nTrackFlags = StartTrackingFlags::NONE;
957 0 : meScrollType = SCROLL_DRAG;
958 0 : mnDragDraw = SCRBAR_DRAW_THUMB;
959 :
960 : // calculate mouse offset
961 0 : if (bWarp && (!bThumbHit || !bPrimaryWarping))
962 : {
963 0 : bDragToMouse = true;
964 0 : if ( GetStyle() & WB_HORZ )
965 0 : mnMouseOff = maThumbRect.GetWidth()/2;
966 : else
967 0 : mnMouseOff = maThumbRect.GetHeight()/2;
968 : }
969 : else
970 : {
971 0 : if ( GetStyle() & WB_HORZ )
972 0 : mnMouseOff = rMousePos.X()-maThumbRect.Left();
973 : else
974 0 : mnMouseOff = rMousePos.Y()-maThumbRect.Top();
975 : }
976 :
977 0 : mnStateFlags |= SCRBAR_STATE_THUMB_DOWN;
978 0 : Invalidate();
979 : }
980 : }
981 0 : else if(bPage && (!HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA,
982 0 : aControlRegion, rMousePos, bIsInside ) ||
983 : bIsInside) )
984 : {
985 0 : nTrackFlags = StartTrackingFlags::ButtonRepeat;
986 :
987 : // HitTestNativeControl, see remark at top of file
988 0 : if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
989 0 : maPage1Rect, rMousePos, bIsInside )?
990 : bIsInside:
991 0 : maPage1Rect.IsInside( rMousePos ) )
992 : {
993 0 : meScrollType = SCROLL_PAGEUP;
994 0 : mnDragDraw = SCRBAR_DRAW_PAGE1;
995 : }
996 : else
997 : {
998 0 : meScrollType = SCROLL_PAGEDOWN;
999 0 : mnDragDraw = SCRBAR_DRAW_PAGE2;
1000 : }
1001 : }
1002 : }
1003 :
1004 : // Should we start Tracking?
1005 0 : if ( meScrollType != SCROLL_DONTKNOW )
1006 : {
1007 : // store original position for cancel and EndScroll delta
1008 0 : mnStartPos = mnThumbPos;
1009 : // #92906# Call StartTracking() before ImplDoMouseAction(), otherwise
1010 : // MouseButtonUp() / EndTracking() may be called if somebody is spending
1011 : // a lot of time in the scroll handler
1012 0 : StartTracking( nTrackFlags );
1013 0 : ImplDoMouseAction( rMousePos );
1014 :
1015 0 : if( bDragToMouse )
1016 0 : ImplDragThumb( rMousePos );
1017 : }
1018 : }
1019 0 : }
1020 :
1021 0 : void ScrollBar::Tracking( const TrackingEvent& rTEvt )
1022 : {
1023 0 : if ( rTEvt.IsTrackingEnded() )
1024 : {
1025 : // Restore Button and PageRect status
1026 0 : sal_uInt16 nOldStateFlags = mnStateFlags;
1027 : mnStateFlags &= ~(SCRBAR_STATE_BTN1_DOWN | SCRBAR_STATE_BTN2_DOWN |
1028 : SCRBAR_STATE_PAGE1_DOWN | SCRBAR_STATE_PAGE2_DOWN |
1029 0 : SCRBAR_STATE_THUMB_DOWN);
1030 0 : if ( nOldStateFlags != mnStateFlags )
1031 0 : Invalidate();
1032 0 : mnDragDraw = 0;
1033 :
1034 : // Restore the old ThumbPosition when canceled
1035 0 : if ( rTEvt.IsTrackingCanceled() )
1036 : {
1037 0 : long nOldPos = mnThumbPos;
1038 0 : SetThumbPos( mnStartPos );
1039 0 : mnDelta = mnThumbPos-nOldPos;
1040 0 : Scroll();
1041 : }
1042 :
1043 0 : if ( meScrollType == SCROLL_DRAG )
1044 : {
1045 : // On a SCROLLDRAG we recalculate the Thumb, so that it's back to a
1046 : // rounded ThumbPosition
1047 0 : ImplCalc();
1048 :
1049 0 : if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
1050 : {
1051 0 : mnDelta = mnThumbPos-mnStartPos;
1052 0 : Scroll();
1053 0 : mnDelta = 0;
1054 : }
1055 : }
1056 :
1057 0 : mnDelta = mnThumbPos-mnStartPos;
1058 0 : EndScroll();
1059 0 : mnDelta = 0;
1060 0 : meScrollType = SCROLL_DONTKNOW;
1061 :
1062 0 : if( mpData )
1063 0 : mpData->mbHide = false; // re-enable focus blinking
1064 : }
1065 : else
1066 : {
1067 0 : const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1068 :
1069 : // Dragging is treated in a special way
1070 0 : if ( meScrollType == SCROLL_DRAG )
1071 0 : ImplDragThumb( rMousePos );
1072 : else
1073 0 : ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
1074 :
1075 : // If ScrollBar values are translated in a way that there's
1076 : // nothing left to track, we cancel here
1077 0 : if ( !IsVisible() || (mnVisibleSize >= (mnMaxRange-mnMinRange)) )
1078 0 : EndTracking();
1079 : }
1080 0 : }
1081 :
1082 0 : void ScrollBar::KeyInput( const KeyEvent& rKEvt )
1083 : {
1084 0 : if ( !rKEvt.GetKeyCode().GetModifier() )
1085 : {
1086 0 : switch ( rKEvt.GetKeyCode().GetCode() )
1087 : {
1088 : case KEY_HOME:
1089 0 : DoScroll( 0 );
1090 0 : break;
1091 :
1092 : case KEY_END:
1093 0 : DoScroll( GetRangeMax() );
1094 0 : break;
1095 :
1096 : case KEY_LEFT:
1097 : case KEY_UP:
1098 0 : DoScrollAction( SCROLL_LINEUP );
1099 0 : break;
1100 :
1101 : case KEY_RIGHT:
1102 : case KEY_DOWN:
1103 0 : DoScrollAction( SCROLL_LINEDOWN );
1104 0 : break;
1105 :
1106 : case KEY_PAGEUP:
1107 0 : DoScrollAction( SCROLL_PAGEUP );
1108 0 : break;
1109 :
1110 : case KEY_PAGEDOWN:
1111 0 : DoScrollAction( SCROLL_PAGEDOWN );
1112 0 : break;
1113 :
1114 : default:
1115 0 : Control::KeyInput( rKEvt );
1116 0 : break;
1117 : }
1118 : }
1119 : else
1120 0 : Control::KeyInput( rKEvt );
1121 0 : }
1122 :
1123 17202 : void ScrollBar::ApplySettings(vcl::RenderContext& rRenderContext)
1124 : {
1125 17202 : rRenderContext.SetBackground();
1126 17202 : }
1127 :
1128 17411 : void ScrollBar::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
1129 : {
1130 17411 : ImplDraw(rRenderContext, SCRBAR_DRAW_ALL);
1131 17411 : }
1132 :
1133 24406 : void ScrollBar::Resize()
1134 : {
1135 24406 : Control::Resize();
1136 24406 : mbCalcSize = true;
1137 24406 : if ( IsReallyVisible() )
1138 9666 : ImplCalc( false );
1139 24406 : Invalidate();
1140 24406 : }
1141 :
1142 0 : IMPL_LINK_NOARG_TYPED(ScrollBar, ImplAutoTimerHdl, Timer *, void)
1143 : {
1144 0 : if( mpData && mpData->mbHide )
1145 0 : return;
1146 0 : ImplInvert();
1147 : }
1148 :
1149 0 : void ScrollBar::ImplInvert()
1150 : {
1151 0 : Rectangle aRect( maThumbRect );
1152 0 : if( aRect.getWidth() > 4 )
1153 : {
1154 0 : aRect.Left() += 2;
1155 0 : aRect.Right() -= 2;
1156 : }
1157 0 : if( aRect.getHeight() > 4 )
1158 : {
1159 0 : aRect.Top() += 2;
1160 0 : aRect.Bottom() -= 2;
1161 : }
1162 :
1163 0 : Invert( aRect );
1164 0 : }
1165 :
1166 0 : void ScrollBar::GetFocus()
1167 : {
1168 0 : if( !mpData )
1169 : {
1170 0 : mpData = new ImplScrollBarData;
1171 0 : mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
1172 0 : mpData->mbHide = false;
1173 : }
1174 0 : ImplInvert(); // react immediately
1175 0 : mpData->maTimer.SetTimeout( GetSettings().GetStyleSettings().GetCursorBlinkTime() );
1176 0 : mpData->maTimer.Start();
1177 0 : Control::GetFocus();
1178 0 : }
1179 :
1180 0 : void ScrollBar::LoseFocus()
1181 : {
1182 0 : if( mpData )
1183 0 : mpData->maTimer.Stop();
1184 0 : Invalidate();
1185 :
1186 0 : Control::LoseFocus();
1187 0 : }
1188 :
1189 73436 : void ScrollBar::StateChanged( StateChangedType nType )
1190 : {
1191 73436 : Control::StateChanged( nType );
1192 :
1193 73436 : if ( nType == StateChangedType::InitShow )
1194 6702 : ImplCalc( false );
1195 66734 : else if ( nType == StateChangedType::Data )
1196 : {
1197 41858 : if ( IsReallyVisible() && IsUpdateMode() )
1198 14322 : ImplCalc( true );
1199 : }
1200 24876 : else if ( nType == StateChangedType::UpdateMode )
1201 : {
1202 0 : if ( IsReallyVisible() && IsUpdateMode() )
1203 : {
1204 0 : ImplCalc( false );
1205 0 : Invalidate();
1206 : }
1207 : }
1208 24876 : else if ( nType == StateChangedType::Enable )
1209 : {
1210 4733 : if ( IsReallyVisible() && IsUpdateMode() )
1211 2574 : Invalidate();
1212 : }
1213 20143 : else if ( nType == StateChangedType::Style )
1214 : {
1215 1 : ImplInitStyle( GetStyle() );
1216 1 : if ( IsReallyVisible() && IsUpdateMode() )
1217 : {
1218 0 : if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) !=
1219 0 : (GetStyle() & SCRBAR_VIEW_STYLE) )
1220 : {
1221 0 : mbCalcSize = true;
1222 0 : ImplCalc( false );
1223 0 : Invalidate();
1224 : }
1225 : }
1226 : }
1227 73436 : }
1228 :
1229 1202 : void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt )
1230 : {
1231 1202 : Control::DataChanged( rDCEvt );
1232 :
1233 4808 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1234 4808 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1235 : {
1236 1193 : mbCalcSize = true;
1237 1193 : ImplCalc( false );
1238 1193 : Invalidate();
1239 : }
1240 1202 : }
1241 :
1242 0 : Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt )
1243 : {
1244 0 : bool bHorizontal = ( GetStyle() & WB_HORZ ) != 0;
1245 0 : bool bIsInside = false;
1246 :
1247 0 : Point aPoint( 0, 0 );
1248 0 : Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
1249 :
1250 0 : if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_RIGHT: PART_BUTTON_LEFT): PART_BUTTON_UP,
1251 0 : aControlRegion, rPt, bIsInside )?
1252 : bIsInside:
1253 0 : maBtn1Rect.IsInside( rPt ) )
1254 0 : return &maBtn1Rect;
1255 0 : else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_LEFT: PART_BUTTON_RIGHT): PART_BUTTON_DOWN,
1256 0 : aControlRegion, rPt, bIsInside )?
1257 : bIsInside:
1258 0 : maBtn2Rect.IsInside( rPt ) )
1259 0 : return &maBtn2Rect;
1260 : // HitTestNativeControl, see remark at top of file
1261 0 : else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
1262 0 : maPage1Rect, rPt, bIsInside)?
1263 : bIsInside:
1264 0 : maPage1Rect.IsInside( rPt ) )
1265 0 : return &maPage1Rect;
1266 : // HitTestNativeControl, see remark at top of file
1267 0 : else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER,
1268 0 : maPage2Rect, rPt, bIsInside)?
1269 : bIsInside:
1270 0 : maPage2Rect.IsInside( rPt ) )
1271 0 : return &maPage2Rect;
1272 : // HitTestNativeControl, see remark at top of file
1273 0 : else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_THUMB_HORZ : PART_THUMB_VERT,
1274 0 : maThumbRect, rPt, bIsInside)?
1275 : bIsInside:
1276 0 : maThumbRect.IsInside( rPt ) )
1277 0 : return &maThumbRect;
1278 : else
1279 0 : return NULL;
1280 : }
1281 :
1282 0 : bool ScrollBar::PreNotify( NotifyEvent& rNEvt )
1283 : {
1284 0 : const MouseEvent* pMouseEvt = NULL;
1285 :
1286 0 : if( (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
1287 : {
1288 0 : if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
1289 : {
1290 : // Trigger a redraw if mouse over state has changed
1291 0 : if( IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
1292 : {
1293 0 : Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
1294 0 : Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
1295 0 : if( pRect != pLastRect || pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
1296 : {
1297 0 : vcl::Region aRgn( GetActiveClipRegion() );
1298 0 : vcl::Region aClipRegion;
1299 :
1300 0 : if ( pRect )
1301 0 : aClipRegion.Union( *pRect );
1302 0 : if ( pLastRect )
1303 0 : aClipRegion.Union( *pLastRect );
1304 :
1305 : // Support for 3-button scroll bars
1306 0 : bool bHas3Buttons = IsNativeControlSupported( CTRL_SCROLLBAR, HAS_THREE_BUTTONS );
1307 0 : if ( bHas3Buttons && ( pRect == &maBtn1Rect || pLastRect == &maBtn1Rect ) )
1308 : {
1309 0 : aClipRegion.Union( maBtn2Rect );
1310 : }
1311 :
1312 0 : SetClipRegion( aClipRegion );
1313 0 : Invalidate(aClipRegion.GetBoundRect());
1314 :
1315 0 : SetClipRegion( aRgn );
1316 : }
1317 : }
1318 : }
1319 : }
1320 :
1321 0 : return Control::PreNotify(rNEvt);
1322 : }
1323 :
1324 2 : void ScrollBar::Scroll()
1325 : {
1326 2 : ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_SCROLL, maScrollHdl, this );
1327 2 : }
1328 :
1329 2 : void ScrollBar::EndScroll()
1330 : {
1331 2 : ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_ENDSCROLL, maEndScrollHdl, this );
1332 2 : }
1333 :
1334 0 : long ScrollBar::DoScroll( long nNewPos )
1335 : {
1336 0 : if ( meScrollType != SCROLL_DONTKNOW )
1337 0 : return 0;
1338 :
1339 : SAL_INFO("vcl.scrollbar", "DoScroll(" << nNewPos << ")");
1340 0 : meScrollType = SCROLL_DRAG;
1341 0 : long nDelta = ImplScroll( nNewPos, true );
1342 0 : meScrollType = SCROLL_DONTKNOW;
1343 0 : return nDelta;
1344 : }
1345 :
1346 2 : long ScrollBar::DoScrollAction( ScrollType eScrollType )
1347 : {
1348 2 : if ( (meScrollType != SCROLL_DONTKNOW) ||
1349 2 : (eScrollType == SCROLL_DONTKNOW) ||
1350 : (eScrollType == SCROLL_DRAG) )
1351 0 : return 0;
1352 :
1353 2 : meScrollType = eScrollType;
1354 2 : long nDelta = ImplDoAction( true );
1355 2 : meScrollType = SCROLL_DONTKNOW;
1356 2 : return nDelta;
1357 : }
1358 :
1359 264 : void ScrollBar::SetRangeMin( long nNewRange )
1360 : {
1361 264 : SetRange( Range( nNewRange, GetRangeMax() ) );
1362 264 : }
1363 :
1364 4933 : void ScrollBar::SetRangeMax( long nNewRange )
1365 : {
1366 4933 : SetRange( Range( GetRangeMin(), nNewRange ) );
1367 4933 : }
1368 :
1369 78384 : void ScrollBar::SetRange( const Range& rRange )
1370 : {
1371 : // Adapt Range
1372 78384 : Range aRange = rRange;
1373 78384 : aRange.Justify();
1374 78384 : long nNewMinRange = aRange.Min();
1375 78384 : long nNewMaxRange = aRange.Max();
1376 :
1377 : // If Range differs, set a new one
1378 156613 : if ( (mnMinRange != nNewMinRange) ||
1379 78229 : (mnMaxRange != nNewMaxRange) )
1380 : {
1381 12919 : mnMinRange = nNewMinRange;
1382 12919 : mnMaxRange = nNewMaxRange;
1383 :
1384 : // Adapt Thumb
1385 12919 : if ( mnThumbPos > mnMaxRange-mnVisibleSize )
1386 1434 : mnThumbPos = mnMaxRange-mnVisibleSize;
1387 12919 : if ( mnThumbPos < mnMinRange )
1388 1399 : mnThumbPos = mnMinRange;
1389 :
1390 12919 : CompatStateChanged( StateChangedType::Data );
1391 : }
1392 78384 : }
1393 :
1394 67939 : void ScrollBar::SetThumbPos( long nNewThumbPos )
1395 : {
1396 67939 : if ( nNewThumbPos > mnMaxRange-mnVisibleSize )
1397 1458 : nNewThumbPos = mnMaxRange-mnVisibleSize;
1398 67939 : if ( nNewThumbPos < mnMinRange )
1399 1463 : nNewThumbPos = mnMinRange;
1400 :
1401 67939 : if ( mnThumbPos != nNewThumbPos )
1402 : {
1403 5890 : mnThumbPos = nNewThumbPos;
1404 5890 : CompatStateChanged( StateChangedType::Data );
1405 : }
1406 67939 : }
1407 :
1408 47065 : void ScrollBar::SetVisibleSize( long nNewSize )
1409 : {
1410 47065 : if ( mnVisibleSize != nNewSize )
1411 : {
1412 23049 : mnVisibleSize = nNewSize;
1413 :
1414 : // Adapt Thumb
1415 23049 : if ( mnThumbPos > mnMaxRange-mnVisibleSize )
1416 756 : mnThumbPos = mnMaxRange-mnVisibleSize;
1417 23049 : if ( mnThumbPos < mnMinRange )
1418 690 : mnThumbPos = mnMinRange;
1419 23049 : CompatStateChanged( StateChangedType::Data );
1420 : }
1421 47065 : }
1422 :
1423 0 : Size ScrollBar::GetOptimalSize() const
1424 : {
1425 0 : if (mbCalcSize)
1426 0 : const_cast<ScrollBar*>(this)->ImplCalc(false);
1427 :
1428 0 : Size aRet = getCurrentCalcSize();
1429 :
1430 0 : const long nMinThumbSize = GetSettings().GetStyleSettings().GetMinThumbSize();
1431 :
1432 0 : if (GetStyle() & WB_HORZ)
1433 : {
1434 0 : aRet.Width() = maBtn1Rect.GetWidth() + nMinThumbSize + maBtn2Rect.GetWidth();
1435 : }
1436 : else
1437 : {
1438 0 : aRet.Height() = maBtn1Rect.GetHeight() + nMinThumbSize + maBtn2Rect.GetHeight();
1439 : }
1440 :
1441 0 : return aRet;
1442 : }
1443 :
1444 35952 : Size ScrollBar::getCurrentCalcSize() const
1445 : {
1446 35952 : Rectangle aCtrlRegion;
1447 35952 : aCtrlRegion.Union(maBtn1Rect);
1448 35952 : aCtrlRegion.Union(maBtn2Rect);
1449 35952 : aCtrlRegion.Union(maPage1Rect);
1450 35952 : aCtrlRegion.Union(maPage2Rect);
1451 35952 : aCtrlRegion.Union(maThumbRect);
1452 35952 : return aCtrlRegion.GetSize();
1453 : }
1454 :
1455 6737 : void ScrollBarBox::ImplInit(vcl::Window* pParent, WinBits nStyle)
1456 : {
1457 6737 : Window::ImplInit( pParent, nStyle, NULL );
1458 :
1459 6737 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1460 6737 : long nScrollSize = rStyleSettings.GetScrollBarSize();
1461 6737 : SetSizePixel(Size(nScrollSize, nScrollSize));
1462 6737 : }
1463 :
1464 6737 : ScrollBarBox::ScrollBarBox( vcl::Window* pParent, WinBits nStyle ) :
1465 6737 : Window( WINDOW_SCROLLBARBOX )
1466 : {
1467 6737 : ImplInit( pParent, nStyle );
1468 6737 : }
1469 :
1470 6108 : void ScrollBarBox::ApplySettings(vcl::RenderContext& rRenderContext)
1471 : {
1472 6108 : if (rRenderContext.IsBackground())
1473 : {
1474 6108 : Color aColor = rRenderContext.GetSettings().GetStyleSettings().GetFaceColor();
1475 6108 : ApplyControlBackground(rRenderContext, aColor);
1476 : }
1477 6108 : }
1478 :
1479 8307 : void ScrollBarBox::StateChanged( StateChangedType nType )
1480 : {
1481 8307 : Window::StateChanged( nType );
1482 :
1483 8307 : if (nType == StateChangedType::ControlBackground)
1484 : {
1485 0 : Invalidate();
1486 : }
1487 8307 : }
1488 :
1489 394 : void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt )
1490 : {
1491 394 : Window::DataChanged( rDCEvt );
1492 :
1493 1576 : if ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1494 1576 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1495 : {
1496 391 : Invalidate();
1497 : }
1498 394 : }
1499 :
1500 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|