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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_vcl.hxx" 24 #include <tools/rcid.h> 25 #include <vcl/spin.h> 26 #include <vcl/event.hxx> 27 #include <vcl/spin.hxx> 28 29 // ======================================================================= 30 31 void SpinButton::ImplInit( Window* pParent, WinBits nStyle ) 32 { 33 mbUpperIn = sal_False; 34 mbLowerIn = sal_False; 35 mbInitialUp = sal_False; 36 mbInitialDown = sal_False; 37 38 mnMinRange = 0; 39 mnMaxRange = 100; 40 mnValue = 0; 41 mnValueStep = 1; 42 43 maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() ); 44 maRepeatTimer.SetTimeoutHdl( LINK( this, SpinButton, ImplTimeout ) ); 45 46 mbRepeat = 0 != ( nStyle & WB_REPEAT ); 47 48 if ( nStyle & WB_HSCROLL ) 49 mbHorz = sal_True; 50 else 51 mbHorz = sal_False; 52 53 Control::ImplInit( pParent, nStyle, NULL ); 54 } 55 56 // ----------------------------------------------------------------------- 57 58 SpinButton::SpinButton( Window* pParent, WinBits nStyle ) 59 :Control( WINDOW_SPINBUTTON ) 60 ,mbUpperIsFocused( sal_False ) 61 { 62 ImplInit( pParent, nStyle ); 63 } 64 65 // ----------------------------------------------------------------------- 66 67 SpinButton::SpinButton( Window* pParent, const ResId& rResId ) 68 :Control( WINDOW_SPINBUTTON ) 69 ,mbUpperIsFocused( sal_False ) 70 { 71 rResId.SetRT( RSC_SPINBUTTON ); 72 ImplInit( pParent, ImplInitRes( rResId ) ); 73 ImplLoadRes( rResId ); 74 Resize(); 75 } 76 77 // ----------------------------------------------------------------------- 78 79 SpinButton::~SpinButton() 80 { 81 } 82 83 // ----------------------------------------------------------------------- 84 85 IMPL_LINK( SpinButton, ImplTimeout, Timer*, pTimer ) 86 { 87 if ( pTimer->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() ) 88 { 89 pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() ); 90 pTimer->Start(); 91 } 92 else 93 { 94 if ( mbInitialUp ) 95 Up(); 96 else 97 Down(); 98 } 99 100 return 0; 101 } 102 103 // ----------------------------------------------------------------------- 104 105 void SpinButton::Up() 106 { 107 if ( ImplIsUpperEnabled() ) 108 { 109 mnValue += mnValueStep; 110 StateChanged( STATE_CHANGE_DATA ); 111 112 ImplMoveFocus( sal_True ); 113 } 114 115 ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_UP, maUpHdlLink, this ); 116 } 117 118 // ----------------------------------------------------------------------- 119 120 void SpinButton::Down() 121 { 122 if ( ImplIsLowerEnabled() ) 123 { 124 mnValue -= mnValueStep; 125 StateChanged( STATE_CHANGE_DATA ); 126 127 ImplMoveFocus( sal_False ); 128 } 129 130 ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_DOWN, maDownHdlLink, this ); 131 } 132 133 // ----------------------------------------------------------------------- 134 135 void SpinButton::Resize() 136 { 137 Control::Resize(); 138 139 Size aSize( GetOutputSizePixel() ); 140 Point aTmpPoint; 141 Rectangle aRect( aTmpPoint, aSize ); 142 if ( mbHorz ) 143 { 144 maLowerRect = Rectangle( 0, 0, aSize.Width() / 2, aSize.Height() - 1 ); 145 maUpperRect = Rectangle( maLowerRect.TopRight(), aRect.BottomRight() ); 146 } 147 else 148 { 149 maUpperRect = Rectangle( 0, 0, aSize.Width() - 1, aSize.Height() / 2 ); 150 maLowerRect = Rectangle( maUpperRect.BottomLeft(), aRect.BottomRight() ); 151 } 152 153 ImplCalcFocusRect( ImplIsUpperEnabled() || !ImplIsLowerEnabled() ); 154 155 Invalidate(); 156 } 157 158 // ----------------------------------------------------------------------- 159 160 void SpinButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) 161 { 162 Point aPos = pDev->LogicToPixel( rPos ); 163 Size aSize = pDev->LogicToPixel( rSize ); 164 165 pDev->Push(); 166 pDev->SetMapMode(); 167 if ( !(nFlags & WINDOW_DRAW_MONO) ) 168 { 169 // DecoView uses the FaceColor... 170 AllSettings aSettings = pDev->GetSettings(); 171 StyleSettings aStyleSettings = aSettings.GetStyleSettings(); 172 if ( IsControlBackground() ) 173 aStyleSettings.SetFaceColor( GetControlBackground() ); 174 else 175 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() ); 176 177 aSettings.SetStyleSettings( aStyleSettings ); 178 pDev->SetSettings( aSettings ); 179 } 180 181 Rectangle aRect( Point( 0, 0 ), aSize ); 182 Rectangle aLowerRect, aUpperRect; 183 if ( mbHorz ) 184 { 185 aLowerRect = Rectangle( 0, 0, aSize.Width() / 2, aSize.Height() - 1 ); 186 aUpperRect = Rectangle( aLowerRect.TopRight(), aRect.BottomRight() ); 187 } 188 else 189 { 190 aUpperRect = Rectangle( 0, 0, aSize.Width() - 1, aSize.Height() / 2 ); 191 aLowerRect = Rectangle( aUpperRect.BottomLeft(), aRect.BottomRight() ); 192 } 193 194 aUpperRect += aPos; 195 aLowerRect += aPos; 196 197 ImplDrawSpinButton( pDev, aUpperRect, aLowerRect, sal_False, sal_False, 198 IsEnabled() && ImplIsUpperEnabled(), 199 IsEnabled() && ImplIsLowerEnabled(), mbHorz, sal_True ); 200 pDev->Pop(); 201 } 202 203 204 void SpinButton::Paint( const Rectangle& ) 205 { 206 HideFocus(); 207 208 sal_Bool bEnable = IsEnabled(); 209 ImplDrawSpinButton( this, maUpperRect, maLowerRect, mbUpperIn, mbLowerIn, 210 bEnable && ImplIsUpperEnabled(), 211 bEnable && ImplIsLowerEnabled(), mbHorz, sal_True ); 212 213 if ( HasFocus() ) 214 ShowFocus( maFocusRect ); 215 } 216 217 // ----------------------------------------------------------------------- 218 219 void SpinButton::MouseButtonDown( const MouseEvent& rMEvt ) 220 { 221 if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsUpperEnabled() ) ) 222 { 223 mbUpperIn = sal_True; 224 mbInitialUp = sal_True; 225 Invalidate( maUpperRect ); 226 } 227 else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsLowerEnabled() ) ) 228 { 229 mbLowerIn = sal_True; 230 mbInitialDown = sal_True; 231 Invalidate( maLowerRect ); 232 } 233 234 if ( mbUpperIn || mbLowerIn ) 235 { 236 Update(); 237 CaptureMouse(); 238 if ( mbRepeat ) 239 maRepeatTimer.Start(); 240 } 241 } 242 243 // ----------------------------------------------------------------------- 244 245 void SpinButton::MouseButtonUp( const MouseEvent& ) 246 { 247 ReleaseMouse(); 248 if ( mbRepeat ) 249 { 250 maRepeatTimer.Stop(); 251 maRepeatTimer.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() ); 252 } 253 254 if ( mbUpperIn ) 255 { 256 mbUpperIn = sal_False; 257 Invalidate( maUpperRect ); 258 Update(); 259 Up(); 260 } 261 else if ( mbLowerIn ) 262 { 263 mbLowerIn = sal_False; 264 Invalidate( maLowerRect ); 265 Update(); 266 Down(); 267 } 268 269 mbInitialUp = mbInitialDown = sal_False; 270 } 271 272 // ----------------------------------------------------------------------- 273 274 void SpinButton::MouseMove( const MouseEvent& rMEvt ) 275 { 276 if ( !rMEvt.IsLeft() || (!mbInitialUp && !mbInitialDown) ) 277 return; 278 279 if ( !maUpperRect.IsInside( rMEvt.GetPosPixel() ) && 280 mbUpperIn && mbInitialUp ) 281 { 282 mbUpperIn = sal_False; 283 maRepeatTimer.Stop(); 284 Invalidate( maUpperRect ); 285 Update(); 286 } 287 else if ( !maLowerRect.IsInside( rMEvt.GetPosPixel() ) && 288 mbLowerIn & mbInitialDown ) 289 { 290 mbLowerIn = sal_False; 291 maRepeatTimer.Stop(); 292 Invalidate( maLowerRect ); 293 Update(); 294 } 295 else if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) && 296 !mbUpperIn && mbInitialUp ) 297 { 298 mbUpperIn = sal_True; 299 if ( mbRepeat ) 300 maRepeatTimer.Start(); 301 Invalidate( maUpperRect ); 302 Update(); 303 } 304 else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) && 305 !mbLowerIn && mbInitialDown ) 306 { 307 mbLowerIn = sal_True; 308 if ( mbRepeat ) 309 maRepeatTimer.Start(); 310 Invalidate( maLowerRect ); 311 Update(); 312 } 313 } 314 315 // ----------------------------------------------------------------------- 316 317 void SpinButton::KeyInput( const KeyEvent& rKEvt ) 318 { 319 KeyCode aCode = rKEvt.GetKeyCode(); 320 321 if ( !rKEvt.GetKeyCode().GetModifier() ) 322 { 323 switch ( rKEvt.GetKeyCode().GetCode() ) 324 { 325 case KEY_LEFT: 326 case KEY_RIGHT: 327 { 328 sal_Bool bUp = KEY_RIGHT == rKEvt.GetKeyCode().GetCode(); 329 if ( mbHorz && !ImplMoveFocus( bUp ) ) 330 bUp ? Up() : Down(); 331 } 332 break; 333 334 case KEY_UP: 335 case KEY_DOWN: 336 { 337 sal_Bool bUp = KEY_UP == rKEvt.GetKeyCode().GetCode(); 338 if ( !mbHorz && !ImplMoveFocus( KEY_UP == rKEvt.GetKeyCode().GetCode() ) ) 339 bUp ? Up() : Down(); 340 } 341 break; 342 343 case KEY_SPACE: 344 mbUpperIsFocused ? Up() : Down(); 345 break; 346 347 default: 348 Control::KeyInput( rKEvt ); 349 break; 350 } 351 } 352 else 353 Control::KeyInput( rKEvt ); 354 } 355 356 // ----------------------------------------------------------------------- 357 358 void SpinButton::StateChanged( StateChangedType nType ) 359 { 360 switch ( nType ) 361 { 362 case STATE_CHANGE_DATA: 363 case STATE_CHANGE_ENABLE: 364 Invalidate(); 365 break; 366 367 case STATE_CHANGE_STYLE: 368 { 369 sal_Bool bNewRepeat = 0 != ( GetStyle() & WB_REPEAT ); 370 if ( bNewRepeat != mbRepeat ) 371 { 372 if ( maRepeatTimer.IsActive() ) 373 { 374 maRepeatTimer.Stop(); 375 maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() ); 376 } 377 mbRepeat = bNewRepeat; 378 } 379 380 sal_Bool bNewHorz = 0 != ( GetStyle() & WB_HSCROLL ); 381 if ( bNewHorz != mbHorz ) 382 { 383 mbHorz = bNewHorz; 384 Resize(); 385 } 386 } 387 break; 388 } 389 390 Control::StateChanged( nType ); 391 } 392 393 // ----------------------------------------------------------------------- 394 395 void SpinButton::SetRangeMin( long nNewRange ) 396 { 397 SetRange( Range( nNewRange, GetRangeMax() ) ); 398 } 399 400 // ----------------------------------------------------------------------- 401 402 void SpinButton::SetRangeMax( long nNewRange ) 403 { 404 SetRange( Range( GetRangeMin(), nNewRange ) ); 405 } 406 407 // ----------------------------------------------------------------------- 408 409 void SpinButton::SetRange( const Range& rRange ) 410 { 411 // adjust range 412 Range aRange = rRange; 413 aRange.Justify(); 414 long nNewMinRange = aRange.Min(); 415 long nNewMaxRange = aRange.Max(); 416 417 // do something only if old and new range differ 418 if ( (mnMinRange != nNewMinRange) || 419 (mnMaxRange != nNewMaxRange) ) 420 { 421 mnMinRange = nNewMinRange; 422 mnMaxRange = nNewMaxRange; 423 424 // adjust value to new range, if necessary 425 if ( mnValue > mnMaxRange ) 426 mnValue = mnMaxRange; 427 if ( mnValue < mnMinRange ) 428 mnValue = mnMinRange; 429 430 StateChanged( STATE_CHANGE_DATA ); 431 } 432 } 433 434 // ----------------------------------------------------------------------- 435 436 void SpinButton::SetValue( long nValue ) 437 { 438 // adjust, if necessary 439 if ( nValue > mnMaxRange ) 440 nValue = mnMaxRange; 441 if ( nValue < mnMinRange ) 442 nValue = mnMinRange; 443 444 if ( mnValue != nValue ) 445 { 446 mnValue = nValue; 447 StateChanged( STATE_CHANGE_DATA ); 448 } 449 } 450 451 // ----------------------------------------------------------------------- 452 453 void SpinButton::GetFocus() 454 { 455 ShowFocus( maFocusRect ); 456 Control::GetFocus(); 457 } 458 459 // ----------------------------------------------------------------------- 460 461 void SpinButton::LoseFocus() 462 { 463 HideFocus(); 464 Control::LoseFocus(); 465 } 466 467 // ----------------------------------------------------------------------- 468 469 sal_Bool SpinButton::ImplMoveFocus( sal_Bool _bUpper ) 470 { 471 if ( _bUpper == mbUpperIsFocused ) 472 return sal_False; 473 474 HideFocus(); 475 ImplCalcFocusRect( _bUpper ); 476 if ( HasFocus() ) 477 ShowFocus( maFocusRect ); 478 return sal_True; 479 } 480 481 // ----------------------------------------------------------------------- 482 483 void SpinButton::ImplCalcFocusRect( sal_Bool _bUpper ) 484 { 485 maFocusRect = _bUpper ? maUpperRect : maLowerRect; 486 // inflate by some pixels 487 maFocusRect.Left() += 2; 488 maFocusRect.Top() += 2; 489 maFocusRect.Right() -= 2; 490 maFocusRect.Bottom() -= 2; 491 mbUpperIsFocused = _bUpper; 492 } 493 494 // ----------------------------------------------------------------------- 495 496 Rectangle* SpinButton::ImplFindPartRect( const Point& rPt ) 497 { 498 if( maUpperRect.IsInside( rPt ) ) 499 return &maUpperRect; 500 else if( maLowerRect.IsInside( rPt ) ) 501 return &maLowerRect; 502 else 503 return NULL; 504 } 505 506 long SpinButton::PreNotify( NotifyEvent& rNEvt ) 507 { 508 long nDone = 0; 509 const MouseEvent* pMouseEvt = NULL; 510 511 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) 512 { 513 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() ) 514 { 515 // trigger redraw if mouse over state has changed 516 if( IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) || 517 IsNativeControlSupported(CTRL_SPINBOX, PART_ALL_BUTTONS) ) 518 { 519 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 520 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); 521 if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) 522 { 523 Region aRgn( GetActiveClipRegion() ); 524 if( pLastRect ) 525 { 526 SetClipRegion( *pLastRect ); 527 Paint( *pLastRect ); 528 SetClipRegion( aRgn ); 529 } 530 if( pRect ) 531 { 532 SetClipRegion( *pRect ); 533 Paint( *pRect ); 534 SetClipRegion( aRgn ); 535 } 536 } 537 } 538 } 539 } 540 541 return nDone ? nDone : Control::PreNotify(rNEvt); 542 } 543 544 /* vim: set noet sw=4 ts=4: */ 545