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