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