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/svapp.hxx> 32 #include <vcl/timer.hxx> 33 #include <vcl/settings.hxx> 34 #include <vcl/window.hxx> 35 #include <vcl/cursor.hxx> 36 37 #include <window.h> 38 39 #include <tools/poly.hxx> 40 41 42 // ======================================================================= 43 44 struct ImplCursorData 45 { 46 AutoTimer maTimer; // Timer 47 Point maPixPos; // Pixel-Position 48 Point maPixRotOff; // Pixel-Offset-Position 49 Size maPixSize; // Pixel-Size 50 long mnPixSlant; // Pixel-Slant 51 short mnOrientation; // Pixel-Orientation 52 unsigned char mnDirection; // indicates writing direction 53 sal_uInt16 mnStyle; // Cursor-Style 54 sal_Bool mbCurVisible; // Ist Cursor aktuell sichtbar 55 Window* mpWindow; // Zugeordnetes Windows 56 }; 57 58 // ======================================================================= 59 60 static void ImplCursorInvert( ImplCursorData* pData ) 61 { 62 Window* pWindow = pData->mpWindow; 63 sal_Bool bMapMode = pWindow->IsMapModeEnabled(); 64 pWindow->EnableMapMode( sal_False ); 65 sal_uInt16 nInvertStyle; 66 if ( pData->mnStyle & CURSOR_SHADOW ) 67 nInvertStyle = INVERT_50; 68 else 69 nInvertStyle = 0; 70 71 Rectangle aRect( pData->maPixPos, pData->maPixSize ); 72 if ( pData->mnDirection || pData->mnOrientation || pData->mnPixSlant ) 73 { 74 Polygon aPoly( aRect ); 75 if( aPoly.GetSize() == 5 ) 76 { 77 aPoly[1].X() += 1; // include the right border 78 aPoly[2].X() += 1; 79 if ( pData->mnPixSlant ) 80 { 81 Point aPoint = aPoly.GetPoint( 0 ); 82 aPoint.X() += pData->mnPixSlant; 83 aPoly.SetPoint( aPoint, 0 ); 84 aPoly.SetPoint( aPoint, 4 ); 85 aPoint = aPoly.GetPoint( 1 ); 86 aPoint.X() += pData->mnPixSlant; 87 aPoly.SetPoint( aPoint, 1 ); 88 } 89 90 // apply direction flag after slant to use the correct shape 91 if ( pData->mnDirection ) 92 { 93 Point pAry[7]; 94 int delta = 3*aRect.getWidth()+1; 95 if( pData->mnDirection == CURSOR_DIRECTION_LTR ) 96 { 97 // left-to-right 98 pAry[0] = aPoly.GetPoint( 0 ); 99 pAry[1] = aPoly.GetPoint( 1 ); 100 pAry[2] = pAry[1]; 101 pAry[2].X() += delta; 102 pAry[3] = pAry[1]; 103 pAry[3].Y() += delta; 104 pAry[4] = aPoly.GetPoint( 2 ); 105 pAry[5] = aPoly.GetPoint( 3 ); 106 pAry[6] = aPoly.GetPoint( 4 ); 107 } 108 else if( pData->mnDirection == CURSOR_DIRECTION_RTL ) 109 { 110 // right-to-left 111 pAry[0] = aPoly.GetPoint( 0 ); 112 pAry[1] = aPoly.GetPoint( 1 ); 113 pAry[2] = aPoly.GetPoint( 2 ); 114 pAry[3] = aPoly.GetPoint( 3 ); 115 pAry[4] = pAry[0]; 116 pAry[4].Y() += delta; 117 pAry[5] = pAry[0]; 118 pAry[5].X() -= delta; 119 pAry[6] = aPoly.GetPoint( 4 ); 120 } 121 aPoly = Polygon( 7, pAry); 122 } 123 124 if ( pData->mnOrientation ) 125 aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation ); 126 pWindow->Invert( aPoly, nInvertStyle ); 127 } 128 } 129 else 130 pWindow->Invert( aRect, nInvertStyle ); 131 pWindow->EnableMapMode( bMapMode ); 132 } 133 134 // ----------------------------------------------------------------------- 135 136 void Cursor::ImplDraw() 137 { 138 if ( mpData && mpData->mpWindow && !mpData->mbCurVisible ) 139 { 140 Window* pWindow = mpData->mpWindow; 141 mpData->maPixPos = pWindow->LogicToPixel( maPos ); 142 mpData->maPixSize = pWindow->LogicToPixel( maSize ); 143 mpData->mnPixSlant = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width(); 144 mpData->mnOrientation = mnOrientation; 145 mpData->mnDirection = mnDirection; 146 long nOffsetY = pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height(); 147 148 // Position um den Offset korrigieren 149 mpData->maPixPos.Y() -= nOffsetY; 150 mpData->maPixRotOff = mpData->maPixPos; 151 mpData->maPixRotOff.Y() += nOffsetY; 152 153 // Wenn groesse 0 ist, nehmen wir die breite, die in den 154 // Settings eingestellt ist 155 if ( !mpData->maPixSize.Width() ) 156 mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize(); 157 158 // Ausgabeflaeche berechnen und ausgeben 159 ImplCursorInvert( mpData ); 160 mpData->mbCurVisible = sal_True; 161 } 162 } 163 164 // ----------------------------------------------------------------------- 165 166 void Cursor::ImplRestore() 167 { 168 if ( mpData && mpData->mbCurVisible ) 169 { 170 ImplCursorInvert( mpData ); 171 mpData->mbCurVisible = sal_False; 172 } 173 } 174 175 // ----------------------------------------------------------------------- 176 177 void Cursor::ImplShow( bool bDrawDirect, bool bRestore ) 178 { 179 if ( mbVisible ) 180 { 181 Window* pWindow; 182 if ( mpWindow ) 183 pWindow = mpWindow; 184 else 185 { 186 // Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster 187 // selektiert, dann zeige den Cursor an 188 pWindow = Application::GetFocusWindow(); 189 if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint 190 || !pWindow->mpWindowImpl->mpFrameData->mbHasFocus ) 191 pWindow = NULL; 192 } 193 194 if ( pWindow ) 195 { 196 if ( !mpData ) 197 { 198 mpData = new ImplCursorData; 199 mpData->mbCurVisible = sal_False; 200 mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) ); 201 } 202 203 mpData->mpWindow = pWindow; 204 mpData->mnStyle = mnStyle; 205 if ( bDrawDirect || bRestore ) 206 ImplDraw(); 207 208 if ( !mpWindow && ! ( ! bDrawDirect && mpData->maTimer.IsActive()) ) 209 { 210 mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() ); 211 if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME ) 212 mpData->maTimer.Start(); 213 else if ( !mpData->mbCurVisible ) 214 ImplDraw(); 215 } 216 } 217 } 218 } 219 220 // ----------------------------------------------------------------------- 221 222 bool Cursor::ImplHide( bool i_bStopTimer ) 223 { 224 bool bWasCurVisible = false; 225 if ( mpData && mpData->mpWindow ) 226 { 227 bWasCurVisible = mpData->mbCurVisible; 228 if ( mpData->mbCurVisible ) 229 ImplRestore(); 230 } 231 232 if( mpData && i_bStopTimer ) 233 { 234 mpData->maTimer.Stop(); 235 mpData->mpWindow = NULL; 236 } 237 238 return bWasCurVisible; 239 } 240 241 // ----------------------------------------------------------------------- 242 243 void Cursor::ImplNew() 244 { 245 if ( mbVisible && mpData && mpData->mpWindow ) 246 { 247 if ( mpData->mbCurVisible ) 248 ImplRestore(); 249 250 ImplDraw(); 251 if ( !mpWindow ) 252 { 253 if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME ) 254 mpData->maTimer.Start(); 255 } 256 } 257 } 258 259 // ----------------------------------------------------------------------- 260 261 IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG ) 262 { 263 if ( mpData->mbCurVisible ) 264 ImplRestore(); 265 else 266 ImplDraw(); 267 return 0; 268 } 269 270 // ======================================================================= 271 272 Cursor::Cursor() 273 { 274 mpData = NULL; 275 mpWindow = NULL; 276 mnSlant = 0; 277 mnOffsetY = 0; 278 mnOrientation = 0; 279 mnDirection = 0; 280 mnStyle = 0; 281 mbVisible = sal_False; 282 } 283 284 // ----------------------------------------------------------------------- 285 286 Cursor::Cursor( const Cursor& rCursor ) : 287 maSize( rCursor.maSize ), 288 maPos( rCursor.maPos ) 289 { 290 mpData = NULL; 291 mpWindow = NULL; 292 mnSlant = rCursor.mnSlant; 293 mnOrientation = rCursor.mnOrientation; 294 mnDirection = rCursor.mnDirection; 295 mnStyle = 0; 296 mbVisible = rCursor.mbVisible; 297 } 298 299 // ----------------------------------------------------------------------- 300 301 Cursor::~Cursor() 302 { 303 if ( mpData ) 304 { 305 if ( mpData->mbCurVisible ) 306 ImplRestore(); 307 308 delete mpData; 309 } 310 } 311 312 // ----------------------------------------------------------------------- 313 314 void Cursor::SetStyle( sal_uInt16 nStyle ) 315 { 316 if ( mnStyle != nStyle ) 317 { 318 mnStyle = nStyle; 319 ImplNew(); 320 } 321 } 322 323 // ----------------------------------------------------------------------- 324 325 void Cursor::Show() 326 { 327 if ( !mbVisible ) 328 { 329 mbVisible = sal_True; 330 ImplShow(); 331 } 332 } 333 334 // ----------------------------------------------------------------------- 335 336 void Cursor::Hide() 337 { 338 if ( mbVisible ) 339 { 340 mbVisible = sal_False; 341 ImplHide( true ); 342 } 343 } 344 345 // ----------------------------------------------------------------------- 346 347 void Cursor::SetWindow( Window* pWindow ) 348 { 349 if ( mpWindow != pWindow ) 350 { 351 mpWindow = pWindow; 352 ImplNew(); 353 } 354 } 355 356 // ----------------------------------------------------------------------- 357 358 void Cursor::SetPos( const Point& rPoint ) 359 { 360 if ( maPos != rPoint ) 361 { 362 maPos = rPoint; 363 ImplNew(); 364 } 365 } 366 367 // ----------------------------------------------------------------------- 368 369 void Cursor::SetOffsetY( long nNewOffsetY ) 370 { 371 if ( mnOffsetY != nNewOffsetY ) 372 { 373 mnOffsetY = nNewOffsetY; 374 ImplNew(); 375 } 376 } 377 378 // ----------------------------------------------------------------------- 379 380 void Cursor::SetSize( const Size& rSize ) 381 { 382 if ( maSize != rSize ) 383 { 384 maSize = rSize; 385 ImplNew(); 386 } 387 } 388 389 // ----------------------------------------------------------------------- 390 391 void Cursor::SetWidth( long nNewWidth ) 392 { 393 if ( maSize.Width() != nNewWidth ) 394 { 395 maSize.Width() = nNewWidth; 396 ImplNew(); 397 } 398 } 399 400 // ----------------------------------------------------------------------- 401 402 void Cursor::SetHeight( long nNewHeight ) 403 { 404 if ( maSize.Height() != nNewHeight ) 405 { 406 maSize.Height() = nNewHeight; 407 ImplNew(); 408 } 409 } 410 411 // ----------------------------------------------------------------------- 412 413 void Cursor::SetSlant( long nNewSlant ) 414 { 415 if ( mnSlant != nNewSlant ) 416 { 417 mnSlant = nNewSlant; 418 ImplNew(); 419 } 420 } 421 422 // ----------------------------------------------------------------------- 423 424 void Cursor::SetOrientation( short nNewOrientation ) 425 { 426 if ( mnOrientation != nNewOrientation ) 427 { 428 mnOrientation = nNewOrientation; 429 ImplNew(); 430 } 431 } 432 433 // ----------------------------------------------------------------------- 434 435 void Cursor::SetDirection( unsigned char nNewDirection ) 436 { 437 if ( mnDirection != nNewDirection ) 438 { 439 mnDirection = nNewDirection; 440 ImplNew(); 441 } 442 } 443 444 // ----------------------------------------------------------------------- 445 446 Cursor& Cursor::operator=( const Cursor& rCursor ) 447 { 448 maPos = rCursor.maPos; 449 maSize = rCursor.maSize; 450 mnSlant = rCursor.mnSlant; 451 mnOrientation = rCursor.mnOrientation; 452 mnDirection = rCursor.mnDirection; 453 mbVisible = rCursor.mbVisible; 454 ImplNew(); 455 456 return *this; 457 } 458 459 // ----------------------------------------------------------------------- 460 461 sal_Bool Cursor::operator==( const Cursor& rCursor ) const 462 { 463 if ( (maPos == rCursor.maPos) && 464 (maSize == rCursor.maSize) && 465 (mnSlant == rCursor.mnSlant) && 466 (mnOrientation == rCursor.mnOrientation) && 467 (mnDirection == rCursor.mnDirection) && 468 (mbVisible == rCursor.mbVisible) ) 469 return sal_True; 470 else 471 return sal_False; 472 } 473