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