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 <tools/ref.hxx> 32 #include <vcl/window.hxx> 33 #include <vcl/seleng.hxx> 34 #include <tools/debug.hxx> 35 36 37 38 39 inline sal_Bool SelectionEngine::ShouldDeselect( sal_Bool bModifierKey1 ) const 40 { 41 // return !( eSelMode == MULTIPLE_SELECTION && bModifierKey1 ); 42 return eSelMode != MULTIPLE_SELECTION || !bModifierKey1; 43 } 44 45 46 // TODO: FunctionSet::SelectAtPoint raus 47 48 /************************************************************************* 49 |* 50 |* SelectionEngine::SelectionEngine() 51 |* 52 |* Beschreibung SELENG.SDW 53 |* Ersterstellung OV 10.10.94 54 |* Letzte Aenderung OV 10.10.94 55 |* 56 *************************************************************************/ 57 58 SelectionEngine::SelectionEngine( Window* pWindow, FunctionSet* pFuncSet ) : 59 pWin( pWindow ) 60 { 61 eSelMode = SINGLE_SELECTION; 62 pFunctionSet = pFuncSet; 63 nFlags = SELENG_EXPANDONMOVE; 64 nLockedMods = 0; 65 66 aWTimer.SetTimeoutHdl( LINK( this, SelectionEngine, ImpWatchDog ) ); 67 aWTimer.SetTimeout( SELENG_AUTOREPEAT_INTERVAL ); 68 } 69 70 /************************************************************************* 71 |* 72 |* SelectionEngine::~SelectionEngine() 73 |* 74 |* Beschreibung SELENG.SDW 75 |* Ersterstellung OV 10.10.94 76 |* Letzte Aenderung OV 10.10.94 77 |* 78 *************************************************************************/ 79 80 SelectionEngine::~SelectionEngine() 81 { 82 aWTimer.Stop(); 83 } 84 85 /************************************************************************* 86 |* 87 |* SelectionEngine::ImpWatchDog() 88 |* 89 |* Beschreibung SELENG.SDW 90 |* Ersterstellung OV 10.10.94 91 |* Letzte Aenderung OV 10.10.94 92 |* 93 *************************************************************************/ 94 95 IMPL_LINK( SelectionEngine, ImpWatchDog, Timer*, EMPTYARG ) 96 { 97 if ( !aArea.IsInside( aLastMove.GetPosPixel() ) ) 98 SelMouseMove( aLastMove ); 99 return 0; 100 } 101 102 /************************************************************************* 103 |* 104 |* SelectionEngine::SetSelectionMode() 105 |* 106 |* Beschreibung SELENG.SDW 107 |* Ersterstellung OV 10.10.94 108 |* Letzte Aenderung OV 10.10.94 109 |* 110 *************************************************************************/ 111 112 void SelectionEngine::SetSelectionMode( SelectionMode eMode ) 113 { 114 eSelMode = eMode; 115 } 116 117 /************************************************************************* 118 |* 119 |* SelectionEngine::ActivateDragMode() 120 |* 121 |* Beschreibung SELENG.SDW 122 |* Ersterstellung OV 10.10.94 123 |* Letzte Aenderung OV 10.10.94 124 |* 125 *************************************************************************/ 126 127 void SelectionEngine::ActivateDragMode() 128 { 129 DBG_ERRORFILE( "SelectionEngine::ActivateDragMode not implemented" ); 130 } 131 132 /************************************************************************* 133 |* 134 |* SelectionEngine::CursorPosChanging() 135 |* 136 |* Beschreibung SELENG.SDW 137 |* Ersterstellung OV 10.10.94 138 |* Letzte Aenderung GT 2002-04-04 139 |* 140 *************************************************************************/ 141 142 void SelectionEngine::CursorPosChanging( sal_Bool bShift, sal_Bool bMod1 ) 143 { 144 if ( !pFunctionSet ) 145 return; 146 147 if ( bShift && eSelMode != SINGLE_SELECTION ) 148 { 149 if ( IsAddMode() ) 150 { 151 if ( !(nFlags & SELENG_HAS_ANCH) ) 152 { 153 pFunctionSet->CreateAnchor(); 154 nFlags |= SELENG_HAS_ANCH; 155 } 156 } 157 else 158 { 159 if ( !(nFlags & SELENG_HAS_ANCH) ) 160 { 161 if( ShouldDeselect( bMod1 ) ) 162 pFunctionSet->DeselectAll(); 163 pFunctionSet->CreateAnchor(); 164 nFlags |= SELENG_HAS_ANCH; 165 } 166 } 167 } 168 else 169 { 170 if ( IsAddMode() ) 171 { 172 if ( nFlags & SELENG_HAS_ANCH ) 173 { 174 // pFunctionSet->CreateCursor(); 175 pFunctionSet->DestroyAnchor(); 176 nFlags &= (~SELENG_HAS_ANCH); 177 } 178 } 179 else 180 { 181 if( ShouldDeselect( bMod1 ) ) 182 pFunctionSet->DeselectAll(); 183 else 184 pFunctionSet->DestroyAnchor(); 185 nFlags &= (~SELENG_HAS_ANCH); 186 } 187 } 188 } 189 190 /************************************************************************* 191 |* 192 |* SelectionEngine::SelMouseButtonDown() 193 |* 194 |* Beschreibung SELENG.SDW 195 |* Ersterstellung OV 10.10.94 196 |* Letzte Aenderung OV 07.06.95 197 |* 198 *************************************************************************/ 199 200 sal_Bool SelectionEngine::SelMouseButtonDown( const MouseEvent& rMEvt ) 201 { 202 nFlags &= (~SELENG_CMDEVT); 203 if ( !pFunctionSet || !pWin || rMEvt.GetClicks() > 1 || rMEvt.IsRight() ) 204 return sal_False; 205 206 sal_uInt16 nModifier = rMEvt.GetModifier() | nLockedMods; 207 if ( nModifier & KEY_MOD2 ) 208 return sal_False; 209 // in SingleSelection: Control-Taste filtern (damit auch 210 // mit Ctrl-Click ein D&D gestartet werden kann) 211 if ( nModifier == KEY_MOD1 && eSelMode == SINGLE_SELECTION ) 212 nModifier = 0; 213 214 Point aPos = rMEvt.GetPosPixel(); 215 aLastMove = rMEvt; 216 217 if( !rMEvt.IsRight() ) 218 { 219 pWin->CaptureMouse(); 220 nFlags |= SELENG_IN_SEL; 221 } 222 else 223 { 224 nModifier = 0; 225 } 226 227 switch ( nModifier ) 228 { 229 case 0: // KEY_NO_KEY 230 { 231 sal_Bool bSelAtPoint = pFunctionSet->IsSelectionAtPoint( aPos ); 232 nFlags &= (~SELENG_IN_ADD); 233 if ( (nFlags & SELENG_DRG_ENAB) && bSelAtPoint ) 234 { 235 nFlags |= SELENG_WAIT_UPEVT; 236 nFlags &= ~(SELENG_IN_SEL); 237 pWin->ReleaseMouse(); 238 return sal_True; //auf STARTDRAG-Command-Event warten 239 } 240 if ( eSelMode != SINGLE_SELECTION ) 241 { 242 if( !IsAddMode() ) 243 pFunctionSet->DeselectAll(); 244 else 245 pFunctionSet->DestroyAnchor(); 246 nFlags &= (~SELENG_HAS_ANCH); // bHasAnchor = sal_False; 247 } 248 pFunctionSet->SetCursorAtPoint( aPos ); 249 // Sonderbehandlung Single-Selection, damit Select+Drag 250 // in einem Zug moeglich ist 251 if (eSelMode == SINGLE_SELECTION && (nFlags & SELENG_DRG_ENAB)) 252 nFlags |= SELENG_WAIT_UPEVT; 253 return sal_True; 254 } 255 256 case KEY_SHIFT: 257 if ( eSelMode == SINGLE_SELECTION ) 258 { 259 pWin->ReleaseMouse(); 260 nFlags &= (~SELENG_IN_SEL); 261 return sal_False; 262 } 263 if ( nFlags & SELENG_ADD_ALW ) 264 nFlags |= SELENG_IN_ADD; 265 else 266 nFlags &= (~SELENG_IN_ADD); 267 268 if( !(nFlags & SELENG_HAS_ANCH) ) 269 { 270 if ( !(nFlags & SELENG_IN_ADD) ) 271 pFunctionSet->DeselectAll(); 272 pFunctionSet->CreateAnchor(); 273 nFlags |= SELENG_HAS_ANCH; 274 } 275 pFunctionSet->SetCursorAtPoint( aPos ); 276 return sal_True; 277 278 case KEY_MOD1: 279 // Control nur bei Mehrfachselektion erlaubt 280 if ( eSelMode != MULTIPLE_SELECTION ) 281 { 282 nFlags &= (~SELENG_IN_SEL); 283 pWin->ReleaseMouse(); 284 return sal_True; // Mausclick verschlucken 285 } 286 if ( nFlags & SELENG_HAS_ANCH ) 287 { 288 // pFunctionSet->CreateCursor(); 289 pFunctionSet->DestroyAnchor(); 290 nFlags &= (~SELENG_HAS_ANCH); 291 } 292 if ( pFunctionSet->IsSelectionAtPoint( aPos ) ) 293 { 294 pFunctionSet->DeselectAtPoint( aPos ); 295 pFunctionSet->SetCursorAtPoint( aPos, sal_True ); 296 } 297 else 298 { 299 pFunctionSet->SetCursorAtPoint( aPos ); 300 } 301 return sal_True; 302 303 case KEY_SHIFT + KEY_MOD1: 304 if ( eSelMode != MULTIPLE_SELECTION ) 305 { 306 pWin->ReleaseMouse(); 307 nFlags &= (~SELENG_IN_SEL); 308 return sal_False; 309 } 310 nFlags |= SELENG_IN_ADD; //bIsInAddMode = sal_True; 311 if ( !(nFlags & SELENG_HAS_ANCH) ) 312 { 313 pFunctionSet->CreateAnchor(); 314 nFlags |= SELENG_HAS_ANCH; 315 } 316 pFunctionSet->SetCursorAtPoint( aPos ); 317 return sal_True; 318 } 319 320 return sal_False; 321 } 322 323 /************************************************************************* 324 |* 325 |* SelectionEngine::SelMouseButtonUp() 326 |* 327 |* Beschreibung SELENG.SDW 328 |* Ersterstellung OV 10.10.94 329 |* Letzte Aenderung OV 10.10.94 330 |* 331 *************************************************************************/ 332 333 sal_Bool SelectionEngine::SelMouseButtonUp( const MouseEvent& rMEvt ) 334 { 335 aWTimer.Stop(); 336 //DbgOut("Up"); 337 if( !pFunctionSet || !pWin ) 338 { 339 nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL); 340 return sal_False; 341 } 342 343 if( !rMEvt.IsRight() ) 344 { 345 pWin->ReleaseMouse(); 346 } 347 348 if( (nFlags & SELENG_WAIT_UPEVT) && !(nFlags & SELENG_CMDEVT) && 349 eSelMode != SINGLE_SELECTION) 350 { 351 // MouseButtonDown in Sel aber kein CommandEvent eingetrudelt 352 // ==> deselektieren 353 sal_uInt16 nModifier = aLastMove.GetModifier() | nLockedMods; 354 if( nModifier == KEY_MOD1 || IsAlwaysAdding() ) 355 { 356 if( !(nModifier & KEY_SHIFT) ) 357 { 358 pFunctionSet->DestroyAnchor(); 359 nFlags &= (~SELENG_HAS_ANCH); // nix Anker 360 } 361 pFunctionSet->DeselectAtPoint( aLastMove.GetPosPixel() ); 362 nFlags &= (~SELENG_HAS_ANCH); // nix Anker 363 pFunctionSet->SetCursorAtPoint( aLastMove.GetPosPixel(), sal_True ); 364 } 365 else 366 { 367 pFunctionSet->DeselectAll(); 368 nFlags &= (~SELENG_HAS_ANCH); // nix Anker 369 pFunctionSet->SetCursorAtPoint( aLastMove.GetPosPixel() ); 370 } 371 } 372 373 nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL); 374 return sal_True; 375 } 376 377 /************************************************************************* 378 |* 379 |* SelectionEngine::SelMouseMove() 380 |* 381 |* Beschreibung SELENG.SDW 382 |* Ersterstellung OV 10.10.94 383 |* Letzte Aenderung OV 10.10.94 384 |* 385 *************************************************************************/ 386 387 sal_Bool SelectionEngine::SelMouseMove( const MouseEvent& rMEvt ) 388 { 389 390 if ( !pFunctionSet || !(nFlags & SELENG_IN_SEL) || 391 (nFlags & (SELENG_CMDEVT | SELENG_WAIT_UPEVT)) ) 392 return sal_False; 393 394 if( !(nFlags & SELENG_EXPANDONMOVE) ) 395 return sal_False; // auf DragEvent warten! 396 397 aLastMove = rMEvt; 398 // wenn die Maus ausserhalb der Area steht, dann wird die 399 // Frequenz des SetCursorAtPoint() nur durch den Timer bestimmt 400 if( aWTimer.IsActive() && !aArea.IsInside( rMEvt.GetPosPixel() )) 401 return sal_True; 402 403 404 aWTimer.Start(); 405 if ( eSelMode != SINGLE_SELECTION ) 406 { 407 if ( !(nFlags & SELENG_HAS_ANCH) ) 408 { 409 pFunctionSet->CreateAnchor(); 410 //DbgOut("Move:Creating anchor"); 411 nFlags |= SELENG_HAS_ANCH; 412 } 413 } 414 415 //DbgOut("Move:SetCursor"); 416 pFunctionSet->SetCursorAtPoint( rMEvt.GetPosPixel() ); 417 418 return sal_True; 419 } 420 421 /************************************************************************* 422 |* 423 |* SelectionEngine::SetWindow() 424 |* 425 |* Beschreibung SELENG.SDW 426 |* Ersterstellung OV 10.10.94 427 |* Letzte Aenderung OV 10.10.94 428 |* 429 *************************************************************************/ 430 431 void SelectionEngine::SetWindow( Window* pNewWin ) 432 { 433 if( pNewWin != pWin ) 434 { 435 if ( pWin && (nFlags & SELENG_IN_SEL) ) 436 pWin->ReleaseMouse(); 437 pWin = pNewWin; 438 if ( pWin && ( nFlags & SELENG_IN_SEL ) ) 439 pWin->CaptureMouse(); 440 } 441 } 442 443 /************************************************************************* 444 |* 445 |* SelectionEngine::Reset() 446 |* 447 |* Beschreibung SELENG.SDW 448 |* Ersterstellung OV 07.07.95 449 |* Letzte Aenderung OV 07.07.95 450 |* 451 *************************************************************************/ 452 453 void SelectionEngine::Reset() 454 { 455 aWTimer.Stop(); 456 if ( nFlags & SELENG_IN_SEL ) 457 pWin->ReleaseMouse(); 458 nFlags &= ~(SELENG_HAS_ANCH | SELENG_IN_SEL); 459 nLockedMods = 0; 460 } 461 462 /************************************************************************* 463 |* 464 |* SelectionEngine::Command() 465 |* 466 |* Beschreibung SELENG.SDW 467 |* Ersterstellung OV 07.07.95 468 |* Letzte Aenderung OV 07.07.95 469 |* 470 *************************************************************************/ 471 472 void SelectionEngine::Command( const CommandEvent& rCEvt ) 473 { 474 // Timer aWTimer ist beim Aufspannen einer Selektion aktiv 475 if ( !pFunctionSet || !pWin || aWTimer.IsActive() ) 476 return; 477 aWTimer.Stop(); 478 nFlags |= SELENG_CMDEVT; 479 if ( rCEvt.GetCommand() == COMMAND_STARTDRAG ) 480 { 481 if ( nFlags & SELENG_DRG_ENAB ) 482 { 483 DBG_ASSERT( rCEvt.IsMouseEvent(), "STARTDRAG: Not a MouseEvent" ); 484 if ( pFunctionSet->IsSelectionAtPoint( rCEvt.GetMousePosPixel() ) ) 485 { 486 aLastMove = MouseEvent( rCEvt.GetMousePosPixel(), 487 aLastMove.GetClicks(), aLastMove.GetMode(), 488 aLastMove.GetButtons(), aLastMove.GetModifier() ); 489 pFunctionSet->BeginDrag(); 490 nFlags &= ~(SELENG_CMDEVT|SELENG_WAIT_UPEVT|SELENG_IN_SEL); 491 } 492 else 493 nFlags &= ~SELENG_CMDEVT; 494 } 495 else 496 nFlags &= ~SELENG_CMDEVT; 497 } 498 } 499