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 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 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 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 146 ScrollBar::ScrollBar( Window* pParent, WinBits nStyle ) : 147 Control( WINDOW_SCROLLBAR ) 148 { 149 ImplInit( pParent, nStyle ); 150 } 151 152 // ----------------------------------------------------------------------- 153 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 168 ScrollBar::~ScrollBar() 169 { 170 if( mpData ) 171 delete mpData; 172 } 173 174 // ----------------------------------------------------------------------- 175 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 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 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 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 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 Size aBtnSize( aSize.Height(), aSize.Height() ); 358 maBtn2Rect.Top() = maBtn1Rect.Top(); 359 maBtn2Rect.Left() = aSize.Width()-aSize.Height(); 360 maBtn1Rect.SetSize( aBtnSize ); 361 maBtn2Rect.SetSize( aBtnSize ); 362 } 363 364 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_HORZ_AREA, 365 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) ) 366 maTrackRect = aTrackRegion; 367 else 368 maTrackRect = Rectangle( maBtn1Rect.TopRight(), maBtn2Rect.BottomLeft() ); 369 370 // Check if available space is big enough for thumb ( min thumb size = ScrBar width/height ) 371 mnThumbPixRange = maTrackRect.Right() - maTrackRect.Left(); 372 if( mnThumbPixRange > 0 ) 373 { 374 maPage1Rect.Left() = maTrackRect.Left(); 375 maPage1Rect.Bottom() = 376 maPage2Rect.Bottom() = 377 maThumbRect.Bottom() = maTrackRect.Bottom(); 378 } 379 else 380 { 381 mnThumbPixRange = 0; 382 maPage1Rect.SetEmpty(); 383 maPage2Rect.SetEmpty(); 384 } 385 } 386 else 387 { 388 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_UP, 389 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) && 390 GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_DOWN, 391 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) ) 392 { 393 maBtn1Rect = aBtn1Region; 394 maBtn2Rect = aBtn2Region; 395 } 396 else 397 { 398 const Size aBtnSize( aSize.Width(), aSize.Width() ); 399 maBtn2Rect.Left() = maBtn1Rect.Left(); 400 maBtn2Rect.Top() = aSize.Height()-aSize.Width(); 401 maBtn1Rect.SetSize( aBtnSize ); 402 maBtn2Rect.SetSize( aBtnSize ); 403 } 404 405 if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_VERT_AREA, 406 aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) ) 407 maTrackRect = aTrackRegion; 408 else 409 maTrackRect = Rectangle( maBtn1Rect.BottomLeft()+Point(0,1), maBtn2Rect.TopRight() ); 410 411 // Check if available space is big enough for thumb 412 mnThumbPixRange = maTrackRect.Bottom() - maTrackRect.Top(); 413 if( mnThumbPixRange > 0 ) 414 { 415 maPage1Rect.Top() = maTrackRect.Top(); 416 maPage1Rect.Right() = 417 maPage2Rect.Right() = 418 maThumbRect.Right() = maTrackRect.Right(); 419 } 420 else 421 { 422 mnThumbPixRange = 0; 423 maPage1Rect.SetEmpty(); 424 maPage2Rect.SetEmpty(); 425 } 426 } 427 428 if ( !mnThumbPixRange ) 429 maThumbRect.SetEmpty(); 430 431 mbCalcSize = sal_False; 432 } 433 434 if ( mnThumbPixRange ) 435 { 436 // Werte berechnen 437 if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) || 438 ((mnMaxRange-mnMinRange) <= 0) ) 439 { 440 mnThumbPos = mnMinRange; 441 mnThumbPixPos = 0; 442 mnThumbPixSize = mnThumbPixRange; 443 } 444 else 445 { 446 if ( mnVisibleSize ) 447 mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange ); 448 else 449 { 450 if ( GetStyle() & WB_HORZ ) 451 mnThumbPixSize = maThumbRect.GetWidth(); 452 else 453 mnThumbPixSize = maThumbRect.GetHeight(); 454 } 455 if ( mnThumbPixSize < nMinThumbSize ) 456 mnThumbPixSize = nMinThumbSize; 457 if ( mnThumbPixSize > mnThumbPixRange ) 458 mnThumbPixSize = mnThumbPixRange; 459 mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos ); 460 } 461 } 462 463 // Wenn neu ausgegeben werden soll und wir schon ueber eine 464 // Aktion einen Paint-Event ausgeloest bekommen haben, dann 465 // geben wir nicht direkt aus, sondern invalidieren nur alles 466 if ( bUpdate && HasPaintEvent() ) 467 { 468 Invalidate(); 469 bUpdate = sal_False; 470 } 471 ImplUpdateRects( bUpdate ); 472 } 473 474 // ----------------------------------------------------------------------- 475 476 void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) 477 { 478 Point aPos = pDev->LogicToPixel( rPos ); 479 Size aSize = pDev->LogicToPixel( rSize ); 480 Rectangle aRect( aPos, aSize ); 481 482 pDev->Push(); 483 pDev->SetMapMode(); 484 if ( !(nFlags & WINDOW_DRAW_MONO) ) 485 { 486 // DecoView uses the FaceColor... 487 AllSettings aSettings = pDev->GetSettings(); 488 StyleSettings aStyleSettings = aSettings.GetStyleSettings(); 489 if ( IsControlBackground() ) 490 aStyleSettings.SetFaceColor( GetControlBackground() ); 491 else 492 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() ); 493 494 aSettings.SetStyleSettings( aStyleSettings ); 495 pDev->SetSettings( aSettings ); 496 } 497 498 // for printing: 499 // -calculate the size of the rects 500 // -because this is zero-based add the correct offset 501 // -print 502 // -force recalculate 503 504 if ( mbCalcSize ) 505 ImplCalc( sal_False ); 506 507 maBtn1Rect+=aPos; 508 maBtn2Rect+=aPos; 509 maThumbRect+=aPos; 510 mpData->maTrackRect+=aPos; // TODO: update when maTrackRect is no longer in mpData 511 maPage1Rect+=aPos; 512 maPage2Rect+=aPos; 513 514 ImplDraw( SCRBAR_DRAW_ALL, pDev ); 515 pDev->Pop(); 516 517 mbCalcSize = sal_True; 518 } 519 520 // ----------------------------------------------------------------------- 521 522 sal_Bool ScrollBar::ImplDrawNative( sal_uInt16 nDrawFlags ) 523 { 524 ScrollbarValue scrValue; 525 526 sal_Bool bNativeOK = IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL); 527 if( bNativeOK ) 528 { 529 sal_Bool bHorz = (GetStyle() & WB_HORZ ? true : false); 530 531 // Draw the entire background if the control supports it 532 if( IsNativeControlSupported(CTRL_SCROLLBAR, bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT) ) 533 { 534 ControlState nState = ( IsEnabled() ? CTRL_STATE_ENABLED : 0 ) | ( HasFocus() ? CTRL_STATE_FOCUSED : 0 ); 535 536 scrValue.mnMin = mnMinRange; 537 scrValue.mnMax = mnMaxRange; 538 scrValue.mnCur = mnThumbPos; 539 scrValue.mnVisibleSize = mnVisibleSize; 540 scrValue.maThumbRect = maThumbRect; 541 scrValue.maButton1Rect = maBtn1Rect; 542 scrValue.maButton2Rect = maBtn2Rect; 543 scrValue.mnButton1State = ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0) | 544 ((!(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)) ? CTRL_STATE_ENABLED : 0); 545 scrValue.mnButton2State = ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0) | 546 ((!(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)) ? CTRL_STATE_ENABLED : 0); 547 scrValue.mnThumbState = nState | ((mnStateFlags & SCRBAR_STATE_THUMB_DOWN) ? CTRL_STATE_PRESSED : 0); 548 scrValue.mnPage1State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0); 549 scrValue.mnPage2State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0); 550 551 if( IsMouseOver() ) 552 { 553 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 554 if( pRect ) 555 { 556 if( pRect == &maThumbRect ) 557 scrValue.mnThumbState |= CTRL_STATE_ROLLOVER; 558 else if( pRect == &maBtn1Rect ) 559 scrValue.mnButton1State |= CTRL_STATE_ROLLOVER; 560 else if( pRect == &maBtn2Rect ) 561 scrValue.mnButton2State |= CTRL_STATE_ROLLOVER; 562 else if( pRect == &maPage1Rect ) 563 scrValue.mnPage1State |= CTRL_STATE_ROLLOVER; 564 else if( pRect == &maPage2Rect ) 565 scrValue.mnPage2State |= CTRL_STATE_ROLLOVER; 566 } 567 } 568 569 Rectangle aCtrlRegion; 570 aCtrlRegion.Union( maBtn1Rect ); 571 aCtrlRegion.Union( maBtn2Rect ); 572 aCtrlRegion.Union( maPage1Rect ); 573 aCtrlRegion.Union( maPage2Rect ); 574 aCtrlRegion.Union( maThumbRect ); 575 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT), 576 aCtrlRegion, nState, scrValue, rtl::OUString() ); 577 } 578 else 579 { 580 if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) || (nDrawFlags & SCRBAR_DRAW_PAGE2) ) 581 { 582 sal_uInt32 part1 = bHorz ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER; 583 sal_uInt32 part2 = bHorz ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER; 584 Rectangle aCtrlRegion1( maPage1Rect ); 585 Rectangle aCtrlRegion2( maPage2Rect ); 586 ControlState nState1 = (IsEnabled() ? CTRL_STATE_ENABLED : 0) | (HasFocus() ? CTRL_STATE_FOCUSED : 0); 587 ControlState nState2 = nState1; 588 589 nState1 |= ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0); 590 nState2 |= ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0); 591 592 if( IsMouseOver() ) 593 { 594 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 595 if( pRect ) 596 { 597 if( pRect == &maPage1Rect ) 598 nState1 |= CTRL_STATE_ROLLOVER; 599 else if( pRect == &maPage2Rect ) 600 nState2 |= CTRL_STATE_ROLLOVER; 601 } 602 } 603 604 if ( nDrawFlags & SCRBAR_DRAW_PAGE1 ) 605 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1, 606 scrValue, rtl::OUString() ); 607 608 if ( nDrawFlags & SCRBAR_DRAW_PAGE2 ) 609 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2, 610 scrValue, rtl::OUString() ); 611 } 612 if ( (nDrawFlags & SCRBAR_DRAW_BTN1) || (nDrawFlags & SCRBAR_DRAW_BTN2) ) 613 { 614 sal_uInt32 part1 = bHorz ? PART_BUTTON_LEFT : PART_BUTTON_UP; 615 sal_uInt32 part2 = bHorz ? PART_BUTTON_RIGHT : PART_BUTTON_DOWN; 616 Rectangle aCtrlRegion1( maBtn1Rect ); 617 Rectangle aCtrlRegion2( maBtn2Rect ); 618 ControlState nState1 = HasFocus() ? CTRL_STATE_FOCUSED : 0; 619 ControlState nState2 = nState1; 620 621 if ( !Window::IsEnabled() || !IsEnabled() ) 622 nState1 = (nState2 &= ~CTRL_STATE_ENABLED); 623 else 624 nState1 = (nState2 |= CTRL_STATE_ENABLED); 625 626 nState1 |= ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0); 627 nState2 |= ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0); 628 629 if(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) 630 nState1 &= ~CTRL_STATE_ENABLED; 631 if(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) 632 nState2 &= ~CTRL_STATE_ENABLED; 633 634 if( IsMouseOver() ) 635 { 636 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 637 if( pRect ) 638 { 639 if( pRect == &maBtn1Rect ) 640 nState1 |= CTRL_STATE_ROLLOVER; 641 else if( pRect == &maBtn2Rect ) 642 nState2 |= CTRL_STATE_ROLLOVER; 643 } 644 } 645 646 if ( nDrawFlags & SCRBAR_DRAW_BTN1 ) 647 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1, 648 scrValue, rtl::OUString() ); 649 650 if ( nDrawFlags & SCRBAR_DRAW_BTN2 ) 651 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2, 652 scrValue, rtl::OUString() ); 653 } 654 if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && !maThumbRect.IsEmpty() ) 655 { 656 ControlState nState = IsEnabled() ? CTRL_STATE_ENABLED : 0; 657 Rectangle aCtrlRegion( maThumbRect ); 658 659 if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN ) 660 nState |= CTRL_STATE_PRESSED; 661 662 if ( HasFocus() ) 663 nState |= CTRL_STATE_FOCUSED; 664 665 if( IsMouseOver() ) 666 { 667 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 668 if( pRect ) 669 { 670 if( pRect == &maThumbRect ) 671 nState |= CTRL_STATE_ROLLOVER; 672 } 673 } 674 675 bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_THUMB_HORZ : PART_THUMB_VERT), 676 aCtrlRegion, nState, scrValue, rtl::OUString() ); 677 } 678 } 679 } 680 return bNativeOK; 681 } 682 683 void ScrollBar::ImplDraw( sal_uInt16 nDrawFlags, OutputDevice* pOutDev ) 684 { 685 DecorationView aDecoView( pOutDev ); 686 Rectangle aTempRect; 687 sal_uInt16 nStyle; 688 const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings(); 689 SymbolType eSymbolType; 690 sal_Bool bEnabled = IsEnabled(); 691 692 // Evt. noch offene Berechnungen nachholen 693 if ( mbCalcSize ) 694 ImplCalc( sal_False ); 695 696 Window *pWin = NULL; 697 if( pOutDev->GetOutDevType() == OUTDEV_WINDOW ) 698 pWin = (Window*) pOutDev; 699 700 // Draw the entire control if the native theme engine needs it 701 if ( nDrawFlags && pWin && pWin->IsNativeControlSupported(CTRL_SCROLLBAR, PART_DRAW_BACKGROUND_HORZ) ) 702 { 703 ImplDrawNative( SCRBAR_DRAW_BACKGROUND ); 704 return; 705 } 706 707 if( (nDrawFlags & SCRBAR_DRAW_BTN1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN1 ) ) ) 708 { 709 nStyle = BUTTON_DRAW_NOLIGHTBORDER; 710 if ( mnStateFlags & SCRBAR_STATE_BTN1_DOWN ) 711 nStyle |= BUTTON_DRAW_PRESSED; 712 aTempRect = aDecoView.DrawButton( maBtn1Rect, nStyle ); 713 ImplCalcSymbolRect( aTempRect ); 714 nStyle = 0; 715 if ( (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) || !bEnabled ) 716 nStyle |= SYMBOL_DRAW_DISABLE; 717 if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW ) 718 { 719 if ( GetStyle() & WB_HORZ ) 720 eSymbolType = SYMBOL_ARROW_LEFT; 721 else 722 eSymbolType = SYMBOL_ARROW_UP; 723 } 724 else 725 { 726 if ( GetStyle() & WB_HORZ ) 727 eSymbolType = SYMBOL_SPIN_LEFT; 728 else 729 eSymbolType = SYMBOL_SPIN_UP; 730 } 731 aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle ); 732 } 733 734 if ( (nDrawFlags & SCRBAR_DRAW_BTN2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN2 ) ) ) 735 { 736 nStyle = BUTTON_DRAW_NOLIGHTBORDER; 737 if ( mnStateFlags & SCRBAR_STATE_BTN2_DOWN ) 738 nStyle |= BUTTON_DRAW_PRESSED; 739 aTempRect = aDecoView.DrawButton( maBtn2Rect, nStyle ); 740 ImplCalcSymbolRect( aTempRect ); 741 nStyle = 0; 742 if ( (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) || !bEnabled ) 743 nStyle |= SYMBOL_DRAW_DISABLE; 744 if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW ) 745 { 746 if ( GetStyle() & WB_HORZ ) 747 eSymbolType = SYMBOL_ARROW_RIGHT; 748 else 749 eSymbolType = SYMBOL_ARROW_DOWN; 750 } 751 else 752 { 753 if ( GetStyle() & WB_HORZ ) 754 eSymbolType = SYMBOL_SPIN_RIGHT; 755 else 756 eSymbolType = SYMBOL_SPIN_DOWN; 757 } 758 aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle ); 759 } 760 761 pOutDev->SetLineColor(); 762 763 if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_THUMB ) ) ) 764 { 765 if ( !maThumbRect.IsEmpty() ) 766 { 767 if ( bEnabled ) 768 { 769 nStyle = BUTTON_DRAW_NOLIGHTBORDER; 770 aTempRect = aDecoView.DrawButton( maThumbRect, nStyle ); 771 } 772 else 773 { 774 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() ); 775 pOutDev->DrawRect( maThumbRect ); 776 } 777 } 778 } 779 780 if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE1 ) ) ) 781 { 782 if ( mnStateFlags & SCRBAR_STATE_PAGE1_DOWN ) 783 pOutDev->SetFillColor( rStyleSettings.GetShadowColor() ); 784 else 785 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() ); 786 pOutDev->DrawRect( maPage1Rect ); 787 } 788 if ( (nDrawFlags & SCRBAR_DRAW_PAGE2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE2 ) ) ) 789 { 790 if ( mnStateFlags & SCRBAR_STATE_PAGE2_DOWN ) 791 pOutDev->SetFillColor( rStyleSettings.GetShadowColor() ); 792 else 793 pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() ); 794 pOutDev->DrawRect( maPage2Rect ); 795 } 796 } 797 798 // ----------------------------------------------------------------------- 799 800 long ScrollBar::ImplScroll( long nNewPos, sal_Bool bCallEndScroll ) 801 { 802 long nOldPos = mnThumbPos; 803 SetThumbPos( nNewPos ); 804 long nDelta = mnThumbPos-nOldPos; 805 if ( nDelta ) 806 { 807 mnDelta = nDelta; 808 Scroll(); 809 if ( bCallEndScroll ) 810 EndScroll(); 811 mnDelta = 0; 812 } 813 return nDelta; 814 } 815 816 // ----------------------------------------------------------------------- 817 818 long ScrollBar::ImplDoAction( sal_Bool bCallEndScroll ) 819 { 820 long nDelta = 0; 821 822 switch ( meScrollType ) 823 { 824 case SCROLL_LINEUP: 825 nDelta = ImplScroll( mnThumbPos-mnLineSize, bCallEndScroll ); 826 break; 827 828 case SCROLL_LINEDOWN: 829 nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll ); 830 break; 831 832 case SCROLL_PAGEUP: 833 nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll ); 834 break; 835 836 case SCROLL_PAGEDOWN: 837 nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll ); 838 break; 839 default: 840 ; 841 } 842 843 return nDelta; 844 } 845 846 // ----------------------------------------------------------------------- 847 848 void ScrollBar::ImplDoMouseAction( const Point& rMousePos, sal_Bool bCallAction ) 849 { 850 sal_uInt16 nOldStateFlags = mnStateFlags; 851 sal_Bool bAction = sal_False; 852 sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False; 853 sal_Bool bIsInside = sal_False; 854 855 Point aPoint( 0, 0 ); 856 Rectangle aControlRegion( aPoint, GetOutputSizePixel() ); 857 858 switch ( meScrollType ) 859 { 860 case SCROLL_LINEUP: 861 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP, 862 aControlRegion, rMousePos, bIsInside )? 863 bIsInside: 864 maBtn1Rect.IsInside( rMousePos ) ) 865 { 866 bAction = bCallAction; 867 mnStateFlags |= SCRBAR_STATE_BTN1_DOWN; 868 } 869 else 870 mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN; 871 break; 872 873 case SCROLL_LINEDOWN: 874 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN, 875 aControlRegion, rMousePos, bIsInside )? 876 bIsInside: 877 maBtn2Rect.IsInside( rMousePos ) ) 878 { 879 bAction = bCallAction; 880 mnStateFlags |= SCRBAR_STATE_BTN2_DOWN; 881 } 882 else 883 mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN; 884 break; 885 886 case SCROLL_PAGEUP: 887 // HitTestNativeControl, see remark at top of file 888 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT: PART_TRACK_VERT_UPPER, 889 maPage1Rect, rMousePos, bIsInside )? 890 bIsInside: 891 maPage1Rect.IsInside( rMousePos ) ) 892 { 893 bAction = bCallAction; 894 mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN; 895 } 896 else 897 mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN; 898 break; 899 900 case SCROLL_PAGEDOWN: 901 // HitTestNativeControl, see remark at top of file 902 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_RIGHT: PART_TRACK_VERT_LOWER, 903 maPage2Rect, rMousePos, bIsInside )? 904 bIsInside: 905 maPage2Rect.IsInside( rMousePos ) ) 906 { 907 bAction = bCallAction; 908 mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN; 909 } 910 else 911 mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN; 912 break; 913 default: 914 ; 915 } 916 917 if ( nOldStateFlags != mnStateFlags ) 918 ImplDraw( mnDragDraw, this ); 919 if ( bAction ) 920 ImplDoAction( sal_False ); 921 } 922 923 // ----------------------------------------------------------------------- 924 925 void ScrollBar::ImplDragThumb( const Point& rMousePos ) 926 { 927 long nMovePix; 928 if ( GetStyle() & WB_HORZ ) 929 nMovePix = rMousePos.X()-(maThumbRect.Left()+mnMouseOff); 930 else 931 nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff); 932 933 // move thumb if necessary 934 if ( nMovePix ) 935 { 936 mnThumbPixPos += nMovePix; 937 if ( mnThumbPixPos < 0 ) 938 mnThumbPixPos = 0; 939 if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) ) 940 mnThumbPixPos = mnThumbPixRange-mnThumbPixSize; 941 long nOldPos = mnThumbPos; 942 mnThumbPos = ImplCalcThumbPos( mnThumbPixPos ); 943 ImplUpdateRects(); 944 if ( mbFullDrag && (nOldPos != mnThumbPos) ) 945 { 946 mnDelta = mnThumbPos-nOldPos; 947 Scroll(); 948 mnDelta = 0; 949 } 950 } 951 } 952 953 // ----------------------------------------------------------------------- 954 955 void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt ) 956 { 957 if ( rMEvt.IsLeft() || rMEvt.IsMiddle() ) 958 { 959 const Point& rMousePos = rMEvt.GetPosPixel(); 960 sal_uInt16 nTrackFlags = 0; 961 sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False; 962 sal_Bool bIsInside = sal_False; 963 sal_Bool bDragToMouse = sal_False; 964 965 Point aPoint( 0, 0 ); 966 Rectangle aControlRegion( aPoint, GetOutputSizePixel() ); 967 968 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP, 969 aControlRegion, rMousePos, bIsInside )? 970 bIsInside: 971 maBtn1Rect.IsInside( rMousePos ) ) 972 { 973 if ( !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) ) 974 { 975 nTrackFlags = STARTTRACK_BUTTONREPEAT; 976 meScrollType = SCROLL_LINEUP; 977 mnDragDraw = SCRBAR_DRAW_BTN1; 978 } 979 else 980 Sound::Beep( SOUND_DISABLE, this ); 981 } 982 else if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN, 983 aControlRegion, rMousePos, bIsInside )? 984 bIsInside: 985 maBtn2Rect.IsInside( rMousePos ) ) 986 { 987 if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) ) 988 { 989 nTrackFlags = STARTTRACK_BUTTONREPEAT; 990 meScrollType = SCROLL_LINEDOWN; 991 mnDragDraw = SCRBAR_DRAW_BTN2; 992 } 993 else 994 Sound::Beep( SOUND_DISABLE, this ); 995 } 996 else 997 { 998 bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT, 999 maThumbRect, rMousePos, bIsInside ) 1000 ? bIsInside : maThumbRect.IsInside( rMousePos ); 1001 bool bDragHandling = rMEvt.IsMiddle() || bThumbHit || ImplGetSVData()->maNWFData.mbScrollbarJumpPage; 1002 if( bDragHandling ) 1003 { 1004 if( mpData ) 1005 { 1006 mpData->mbHide = sal_True; // disable focus blinking 1007 if( HasFocus() ) 1008 ImplDraw( SCRBAR_DRAW_THUMB, this ); // paint without focus 1009 } 1010 1011 if ( mnVisibleSize < mnMaxRange-mnMinRange ) 1012 { 1013 nTrackFlags = 0; 1014 meScrollType = SCROLL_DRAG; 1015 mnDragDraw = SCRBAR_DRAW_THUMB; 1016 1017 // calculate mouse offset 1018 if( rMEvt.IsMiddle() || (ImplGetSVData()->maNWFData.mbScrollbarJumpPage && !bThumbHit) ) 1019 { 1020 bDragToMouse = sal_True; 1021 if ( GetStyle() & WB_HORZ ) 1022 mnMouseOff = maThumbRect.GetWidth()/2; 1023 else 1024 mnMouseOff = maThumbRect.GetHeight()/2; 1025 } 1026 else 1027 { 1028 if ( GetStyle() & WB_HORZ ) 1029 mnMouseOff = rMousePos.X()-maThumbRect.Left(); 1030 else 1031 mnMouseOff = rMousePos.Y()-maThumbRect.Top(); 1032 } 1033 1034 mnStateFlags |= SCRBAR_STATE_THUMB_DOWN; 1035 ImplDraw( mnDragDraw, this ); 1036 } 1037 else 1038 Sound::Beep( SOUND_DISABLE, this ); 1039 } 1040 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA, 1041 aControlRegion, rMousePos, bIsInside )? 1042 bIsInside : sal_True ) 1043 { 1044 nTrackFlags = STARTTRACK_BUTTONREPEAT; 1045 1046 // HitTestNativeControl, see remark at top of file 1047 if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER, 1048 maPage1Rect, rMousePos, bIsInside )? 1049 bIsInside: 1050 maPage1Rect.IsInside( rMousePos ) ) 1051 { 1052 meScrollType = SCROLL_PAGEUP; 1053 mnDragDraw = SCRBAR_DRAW_PAGE1; 1054 } 1055 else 1056 { 1057 meScrollType = SCROLL_PAGEDOWN; 1058 mnDragDraw = SCRBAR_DRAW_PAGE2; 1059 } 1060 } 1061 } 1062 1063 // Soll Tracking gestartet werden 1064 if ( meScrollType != SCROLL_DONTKNOW ) 1065 { 1066 // remember original position in case of abort or EndScroll-Delta 1067 mnStartPos = mnThumbPos; 1068 // #92906# Call StartTracking() before ImplDoMouseAction(), otherwise 1069 // MouseButtonUp() / EndTracking() may be called if somebody is spending 1070 // a lot of time in the scroll handler 1071 StartTracking( nTrackFlags ); 1072 ImplDoMouseAction( rMousePos ); 1073 1074 if( bDragToMouse ) 1075 ImplDragThumb( rMousePos ); 1076 } 1077 } 1078 } 1079 1080 // ----------------------------------------------------------------------- 1081 1082 void ScrollBar::Tracking( const TrackingEvent& rTEvt ) 1083 { 1084 if ( rTEvt.IsTrackingEnded() ) 1085 { 1086 // Button und PageRect-Status wieder herstellen 1087 sal_uInt16 nOldStateFlags = mnStateFlags; 1088 mnStateFlags &= ~(SCRBAR_STATE_BTN1_DOWN | SCRBAR_STATE_BTN2_DOWN | 1089 SCRBAR_STATE_PAGE1_DOWN | SCRBAR_STATE_PAGE2_DOWN | 1090 SCRBAR_STATE_THUMB_DOWN); 1091 if ( nOldStateFlags != mnStateFlags ) 1092 ImplDraw( mnDragDraw, this ); 1093 mnDragDraw = 0; 1094 1095 // Bei Abbruch, die alte ThumbPosition wieder herstellen 1096 if ( rTEvt.IsTrackingCanceled() ) 1097 { 1098 long nOldPos = mnThumbPos; 1099 SetThumbPos( mnStartPos ); 1100 mnDelta = mnThumbPos-nOldPos; 1101 Scroll(); 1102 } 1103 1104 if ( meScrollType == SCROLL_DRAG ) 1105 { 1106 // Wenn gedragt wurde, berechnen wir den Thumb neu, damit 1107 // er wieder auf einer gerundeten ThumbPosition steht 1108 ImplCalc(); 1109 1110 if ( !mbFullDrag && (mnStartPos != mnThumbPos) ) 1111 { 1112 mnDelta = mnThumbPos-mnStartPos; 1113 Scroll(); 1114 mnDelta = 0; 1115 } 1116 } 1117 1118 mnDelta = mnThumbPos-mnStartPos; 1119 EndScroll(); 1120 mnDelta = 0; 1121 meScrollType = SCROLL_DONTKNOW; 1122 1123 if( mpData ) 1124 mpData->mbHide = sal_False; // re-enable focus blinking 1125 } 1126 else 1127 { 1128 const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel(); 1129 1130 // Dragging wird speziell behandelt 1131 if ( meScrollType == SCROLL_DRAG ) 1132 ImplDragThumb( rMousePos ); 1133 else 1134 ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() ); 1135 1136 // Wenn ScrollBar-Werte so umgesetzt wurden, das es nichts 1137 // mehr zum Tracking gibt, dann berechen wir hier ab 1138 if ( !IsVisible() || (mnVisibleSize >= (mnMaxRange-mnMinRange)) ) 1139 EndTracking(); 1140 } 1141 } 1142 1143 // ----------------------------------------------------------------------- 1144 1145 void ScrollBar::KeyInput( const KeyEvent& rKEvt ) 1146 { 1147 if ( !rKEvt.GetKeyCode().GetModifier() ) 1148 { 1149 switch ( rKEvt.GetKeyCode().GetCode() ) 1150 { 1151 case KEY_HOME: 1152 DoScroll( 0 ); 1153 break; 1154 1155 case KEY_END: 1156 DoScroll( GetRangeMax() ); 1157 break; 1158 1159 case KEY_LEFT: 1160 case KEY_UP: 1161 DoScrollAction( SCROLL_LINEUP ); 1162 break; 1163 1164 case KEY_RIGHT: 1165 case KEY_DOWN: 1166 DoScrollAction( SCROLL_LINEDOWN ); 1167 break; 1168 1169 case KEY_PAGEUP: 1170 DoScrollAction( SCROLL_PAGEUP ); 1171 break; 1172 1173 case KEY_PAGEDOWN: 1174 DoScrollAction( SCROLL_PAGEDOWN ); 1175 break; 1176 1177 default: 1178 Control::KeyInput( rKEvt ); 1179 break; 1180 } 1181 } 1182 else 1183 Control::KeyInput( rKEvt ); 1184 } 1185 1186 // ----------------------------------------------------------------------- 1187 1188 void ScrollBar::Paint( const Rectangle& ) 1189 { 1190 ImplDraw( SCRBAR_DRAW_ALL, this ); 1191 } 1192 1193 // ----------------------------------------------------------------------- 1194 1195 void ScrollBar::Resize() 1196 { 1197 Control::Resize(); 1198 mbCalcSize = sal_True; 1199 if ( IsReallyVisible() ) 1200 ImplCalc( sal_False ); 1201 Invalidate(); 1202 } 1203 1204 // ----------------------------------------------------------------------- 1205 1206 IMPL_LINK( ScrollBar, ImplAutoTimerHdl, AutoTimer*, EMPTYARG ) 1207 { 1208 if( mpData && mpData->mbHide ) 1209 return 0; 1210 ImplInvert(); 1211 return 0; 1212 } 1213 1214 void ScrollBar::ImplInvert() 1215 { 1216 Rectangle aRect( maThumbRect ); 1217 if( aRect.getWidth() > 4 ) 1218 { 1219 aRect.Left() += 2; 1220 aRect.Right() -= 2; 1221 } 1222 if( aRect.getHeight() > 4 ) 1223 { 1224 aRect.Top() += 2; 1225 aRect.Bottom() -= 2; 1226 } 1227 1228 Invert( aRect, 0 ); 1229 } 1230 1231 // ----------------------------------------------------------------------- 1232 1233 void ScrollBar::GetFocus() 1234 { 1235 if( !mpData ) 1236 { 1237 mpData = new ImplScrollBarData; 1238 mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) ); 1239 mpData->mbHide = sal_False; 1240 } 1241 ImplInvert(); // react immediately 1242 mpData->maTimer.SetTimeout( GetSettings().GetStyleSettings().GetCursorBlinkTime() ); 1243 mpData->maTimer.Start(); 1244 Control::GetFocus(); 1245 } 1246 1247 // ----------------------------------------------------------------------- 1248 1249 void ScrollBar::LoseFocus() 1250 { 1251 if( mpData ) 1252 mpData->maTimer.Stop(); 1253 ImplDraw( SCRBAR_DRAW_THUMB, this ); 1254 1255 Control::LoseFocus(); 1256 } 1257 1258 // ----------------------------------------------------------------------- 1259 1260 void ScrollBar::StateChanged( StateChangedType nType ) 1261 { 1262 Control::StateChanged( nType ); 1263 1264 if ( nType == STATE_CHANGE_INITSHOW ) 1265 ImplCalc( sal_False ); 1266 else if ( nType == STATE_CHANGE_DATA ) 1267 { 1268 if ( IsReallyVisible() && IsUpdateMode() ) 1269 ImplCalc( sal_True ); 1270 } 1271 else if ( nType == STATE_CHANGE_UPDATEMODE ) 1272 { 1273 if ( IsReallyVisible() && IsUpdateMode() ) 1274 { 1275 ImplCalc( sal_False ); 1276 Invalidate(); 1277 } 1278 } 1279 else if ( nType == STATE_CHANGE_ENABLE ) 1280 { 1281 if ( IsReallyVisible() && IsUpdateMode() ) 1282 Invalidate(); 1283 } 1284 else if ( nType == STATE_CHANGE_STYLE ) 1285 { 1286 ImplInitStyle( GetStyle() ); 1287 if ( IsReallyVisible() && IsUpdateMode() ) 1288 { 1289 if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) != 1290 (GetStyle() & SCRBAR_VIEW_STYLE) ) 1291 { 1292 mbCalcSize = sal_True; 1293 ImplCalc( sal_False ); 1294 Invalidate(); 1295 } 1296 } 1297 } 1298 } 1299 1300 // ----------------------------------------------------------------------- 1301 1302 void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt ) 1303 { 1304 Control::DataChanged( rDCEvt ); 1305 1306 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && 1307 (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 1308 { 1309 mbCalcSize = sal_True; 1310 ImplCalc( sal_False ); 1311 Invalidate(); 1312 } 1313 } 1314 1315 // ----------------------------------------------------------------------- 1316 1317 Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt ) 1318 { 1319 sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False; 1320 sal_Bool bIsInside = sal_False; 1321 1322 Point aPoint( 0, 0 ); 1323 Rectangle aControlRegion( aPoint, GetOutputSizePixel() ); 1324 1325 if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP, 1326 aControlRegion, rPt, bIsInside )? 1327 bIsInside: 1328 maBtn1Rect.IsInside( rPt ) ) 1329 return &maBtn1Rect; 1330 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN, 1331 aControlRegion, rPt, bIsInside )? 1332 bIsInside: 1333 maBtn2Rect.IsInside( rPt ) ) 1334 return &maBtn2Rect; 1335 // HitTestNativeControl, see remark at top of file 1336 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER, 1337 maPage1Rect, rPt, bIsInside)? 1338 bIsInside: 1339 maPage1Rect.IsInside( rPt ) ) 1340 return &maPage1Rect; 1341 // HitTestNativeControl, see remark at top of file 1342 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER, 1343 maPage2Rect, rPt, bIsInside)? 1344 bIsInside: 1345 maPage2Rect.IsInside( rPt ) ) 1346 return &maPage2Rect; 1347 // HitTestNativeControl, see remark at top of file 1348 else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_THUMB_HORZ : PART_THUMB_VERT, 1349 maThumbRect, rPt, bIsInside)? 1350 bIsInside: 1351 maThumbRect.IsInside( rPt ) ) 1352 return &maThumbRect; 1353 else 1354 return NULL; 1355 } 1356 1357 long ScrollBar::PreNotify( NotifyEvent& rNEvt ) 1358 { 1359 long nDone = 0; 1360 const MouseEvent* pMouseEvt = NULL; 1361 1362 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) 1363 { 1364 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() ) 1365 { 1366 // trigger redraw if mouse over state has changed 1367 if( IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) ) 1368 { 1369 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 1370 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); 1371 if( pRect != pLastRect || pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() ) 1372 { 1373 Region aRgn( GetActiveClipRegion() ); 1374 Region aClipRegion; 1375 1376 if ( pRect ) 1377 aClipRegion.Union( *pRect ); 1378 if ( pLastRect ) 1379 aClipRegion.Union( *pLastRect ); 1380 1381 // Support for 3-button scroll bars 1382 sal_Bool bHas3Buttons = IsNativeControlSupported( CTRL_SCROLLBAR, HAS_THREE_BUTTONS ); 1383 if ( bHas3Buttons && ( pRect == &maBtn1Rect || pLastRect == &maBtn1Rect ) ) 1384 { 1385 aClipRegion.Union( maBtn2Rect ); 1386 } 1387 1388 SetClipRegion( aClipRegion ); 1389 Paint( aClipRegion.GetBoundRect() ); 1390 1391 SetClipRegion( aRgn ); 1392 } 1393 } 1394 } 1395 } 1396 1397 return nDone ? nDone : Control::PreNotify(rNEvt); 1398 } 1399 1400 // ----------------------------------------------------------------------- 1401 1402 void ScrollBar::Scroll() 1403 { 1404 ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_SCROLL, maScrollHdl, this ); 1405 } 1406 1407 // ----------------------------------------------------------------------- 1408 1409 void ScrollBar::EndScroll() 1410 { 1411 ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_ENDSCROLL, maEndScrollHdl, this ); 1412 } 1413 1414 // ----------------------------------------------------------------------- 1415 1416 long ScrollBar::DoScroll( long nNewPos ) 1417 { 1418 if ( meScrollType != SCROLL_DONTKNOW ) 1419 return 0; 1420 1421 meScrollType = SCROLL_DRAG; 1422 long nDelta = ImplScroll( nNewPos, sal_True ); 1423 meScrollType = SCROLL_DONTKNOW; 1424 return nDelta; 1425 } 1426 1427 // ----------------------------------------------------------------------- 1428 1429 long ScrollBar::DoScrollAction( ScrollType eScrollType ) 1430 { 1431 if ( (meScrollType != SCROLL_DONTKNOW) || 1432 (eScrollType == SCROLL_DONTKNOW) || 1433 (eScrollType == SCROLL_DRAG) ) 1434 return 0; 1435 1436 meScrollType = eScrollType; 1437 long nDelta = ImplDoAction( sal_True ); 1438 meScrollType = SCROLL_DONTKNOW; 1439 return nDelta; 1440 } 1441 1442 // ----------------------------------------------------------------------- 1443 1444 void ScrollBar::SetRangeMin( long nNewRange ) 1445 { 1446 SetRange( Range( nNewRange, GetRangeMax() ) ); 1447 } 1448 1449 // ----------------------------------------------------------------------- 1450 1451 void ScrollBar::SetRangeMax( long nNewRange ) 1452 { 1453 SetRange( Range( GetRangeMin(), nNewRange ) ); 1454 } 1455 1456 // ----------------------------------------------------------------------- 1457 1458 void ScrollBar::SetRange( const Range& rRange ) 1459 { 1460 // Range einpassen 1461 Range aRange = rRange; 1462 aRange.Justify(); 1463 long nNewMinRange = aRange.Min(); 1464 long nNewMaxRange = aRange.Max(); 1465 1466 // Wenn Range sich unterscheidet, dann neuen setzen 1467 if ( (mnMinRange != nNewMinRange) || 1468 (mnMaxRange != nNewMaxRange) ) 1469 { 1470 mnMinRange = nNewMinRange; 1471 mnMaxRange = nNewMaxRange; 1472 1473 // Thumb einpassen 1474 if ( mnThumbPos > mnMaxRange-mnVisibleSize ) 1475 mnThumbPos = mnMaxRange-mnVisibleSize; 1476 if ( mnThumbPos < mnMinRange ) 1477 mnThumbPos = mnMinRange; 1478 1479 StateChanged( STATE_CHANGE_DATA ); 1480 } 1481 } 1482 1483 // ----------------------------------------------------------------------- 1484 1485 void ScrollBar::SetThumbPos( long nNewThumbPos ) 1486 { 1487 if ( nNewThumbPos > mnMaxRange-mnVisibleSize ) 1488 nNewThumbPos = mnMaxRange-mnVisibleSize; 1489 if ( nNewThumbPos < mnMinRange ) 1490 nNewThumbPos = mnMinRange; 1491 1492 if ( mnThumbPos != nNewThumbPos ) 1493 { 1494 mnThumbPos = nNewThumbPos; 1495 StateChanged( STATE_CHANGE_DATA ); 1496 } 1497 } 1498 1499 // ----------------------------------------------------------------------- 1500 1501 void ScrollBar::SetVisibleSize( long nNewSize ) 1502 { 1503 if ( mnVisibleSize != nNewSize ) 1504 { 1505 mnVisibleSize = nNewSize; 1506 1507 // Thumb einpassen 1508 if ( mnThumbPos > mnMaxRange-mnVisibleSize ) 1509 mnThumbPos = mnMaxRange-mnVisibleSize; 1510 if ( mnThumbPos < mnMinRange ) 1511 mnThumbPos = mnMinRange; 1512 StateChanged( STATE_CHANGE_DATA ); 1513 } 1514 } 1515 1516 // ======================================================================= 1517 1518 void ScrollBarBox::ImplInit( Window* pParent, WinBits nStyle ) 1519 { 1520 Window::ImplInit( pParent, nStyle, NULL ); 1521 1522 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 1523 long nScrollSize = rStyleSettings.GetScrollBarSize(); 1524 SetSizePixel( Size( nScrollSize, nScrollSize ) ); 1525 ImplInitSettings(); 1526 } 1527 1528 // ----------------------------------------------------------------------- 1529 1530 ScrollBarBox::ScrollBarBox( Window* pParent, WinBits nStyle ) : 1531 Window( WINDOW_SCROLLBARBOX ) 1532 { 1533 ImplInit( pParent, nStyle ); 1534 } 1535 1536 // ----------------------------------------------------------------------- 1537 1538 ScrollBarBox::ScrollBarBox( Window* pParent, const ResId& rResId ) : 1539 Window( WINDOW_SCROLLBARBOX ) 1540 { 1541 rResId.SetRT( RSC_SCROLLBAR ); 1542 ImplInit( pParent, ImplInitRes( rResId ) ); 1543 ImplLoadRes( rResId ); 1544 } 1545 1546 // ----------------------------------------------------------------------- 1547 1548 void ScrollBarBox::ImplInitSettings() 1549 { 1550 // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann 1551 // und noch nicht alles umgestellt ist 1552 if ( IsBackground() ) 1553 { 1554 Color aColor; 1555 if ( IsControlBackground() ) 1556 aColor = GetControlBackground(); 1557 else 1558 aColor = GetSettings().GetStyleSettings().GetFaceColor(); 1559 SetBackground( aColor ); 1560 } 1561 } 1562 1563 // ----------------------------------------------------------------------- 1564 1565 void ScrollBarBox::StateChanged( StateChangedType nType ) 1566 { 1567 Window::StateChanged( nType ); 1568 1569 if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 1570 { 1571 ImplInitSettings(); 1572 Invalidate(); 1573 } 1574 } 1575 1576 // ----------------------------------------------------------------------- 1577 1578 void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt ) 1579 { 1580 Window::DataChanged( rDCEvt ); 1581 1582 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && 1583 (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 1584 { 1585 ImplInitSettings(); 1586 Invalidate(); 1587 } 1588 } 1589