1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: seleng.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <tools/ref.hxx>
35 #include <vcl/window.hxx>
36 #include <vcl/seleng.hxx>
37 #include <tools/debug.hxx>
42 inline BOOL
SelectionEngine::ShouldDeselect( BOOL bModifierKey1
) const
44 // return !( eSelMode == MULTIPLE_SELECTION && bModifierKey1 );
45 return eSelMode
!= MULTIPLE_SELECTION
|| !bModifierKey1
;
49 // TODO: FunctionSet::SelectAtPoint raus
51 /*************************************************************************
53 |* SelectionEngine::SelectionEngine()
55 |* Beschreibung SELENG.SDW
56 |* Ersterstellung OV 10.10.94
57 |* Letzte Aenderung OV 10.10.94
59 *************************************************************************/
61 SelectionEngine::SelectionEngine( Window
* pWindow
, FunctionSet
* pFuncSet
,
62 ULONG nAutoRepeatInterval
) :
64 nUpdateInterval( nAutoRepeatInterval
)
66 eSelMode
= SINGLE_SELECTION
;
67 pFunctionSet
= pFuncSet
;
68 nFlags
= SELENG_EXPANDONMOVE
;
71 aWTimer
.SetTimeoutHdl( LINK( this, SelectionEngine
, ImpWatchDog
) );
72 aWTimer
.SetTimeout( nUpdateInterval
);
75 /*************************************************************************
77 |* SelectionEngine::~SelectionEngine()
79 |* Beschreibung SELENG.SDW
80 |* Ersterstellung OV 10.10.94
81 |* Letzte Aenderung OV 10.10.94
83 *************************************************************************/
85 SelectionEngine::~SelectionEngine()
90 /*************************************************************************
92 |* SelectionEngine::ImpWatchDog()
94 |* Beschreibung SELENG.SDW
95 |* Ersterstellung OV 10.10.94
96 |* Letzte Aenderung OV 10.10.94
98 *************************************************************************/
100 IMPL_LINK( SelectionEngine
, ImpWatchDog
, Timer
*, EMPTYARG
)
102 if ( !aArea
.IsInside( aLastMove
.GetPosPixel() ) )
103 SelMouseMove( aLastMove
);
107 /*************************************************************************
109 |* SelectionEngine::SetSelectionMode()
111 |* Beschreibung SELENG.SDW
112 |* Ersterstellung OV 10.10.94
113 |* Letzte Aenderung OV 10.10.94
115 *************************************************************************/
117 void SelectionEngine::SetSelectionMode( SelectionMode eMode
)
122 /*************************************************************************
124 |* SelectionEngine::ActivateDragMode()
126 |* Beschreibung SELENG.SDW
127 |* Ersterstellung OV 10.10.94
128 |* Letzte Aenderung OV 10.10.94
130 *************************************************************************/
132 void SelectionEngine::ActivateDragMode()
134 DBG_ERRORFILE( "SelectionEngine::ActivateDragMode not implemented" );
137 /*************************************************************************
139 |* SelectionEngine::CursorPosChanging()
141 |* Beschreibung SELENG.SDW
142 |* Ersterstellung OV 10.10.94
143 |* Letzte Aenderung GT 2002-04-04
145 *************************************************************************/
147 void SelectionEngine::CursorPosChanging( BOOL bShift
, BOOL bMod1
)
152 if ( bShift
&& eSelMode
!= SINGLE_SELECTION
)
156 if ( !(nFlags
& SELENG_HAS_ANCH
) )
158 pFunctionSet
->CreateAnchor();
159 nFlags
|= SELENG_HAS_ANCH
;
164 if ( !(nFlags
& SELENG_HAS_ANCH
) )
166 if( ShouldDeselect( bMod1
) )
167 pFunctionSet
->DeselectAll();
168 pFunctionSet
->CreateAnchor();
169 nFlags
|= SELENG_HAS_ANCH
;
177 if ( nFlags
& SELENG_HAS_ANCH
)
179 // pFunctionSet->CreateCursor();
180 pFunctionSet
->DestroyAnchor();
181 nFlags
&= (~SELENG_HAS_ANCH
);
186 if( ShouldDeselect( bMod1
) )
187 pFunctionSet
->DeselectAll();
189 pFunctionSet
->DestroyAnchor();
190 nFlags
&= (~SELENG_HAS_ANCH
);
195 /*************************************************************************
197 |* SelectionEngine::SelMouseButtonDown()
199 |* Beschreibung SELENG.SDW
200 |* Ersterstellung OV 10.10.94
201 |* Letzte Aenderung OV 07.06.95
203 *************************************************************************/
205 BOOL
SelectionEngine::SelMouseButtonDown( const MouseEvent
& rMEvt
)
207 nFlags
&= (~SELENG_CMDEVT
);
208 if ( !pFunctionSet
|| !pWin
|| rMEvt
.GetClicks() > 1 || rMEvt
.IsRight() )
211 USHORT nModifier
= rMEvt
.GetModifier() | nLockedMods
;
212 if ( nModifier
& KEY_MOD2
)
214 // in SingleSelection: Control-Taste filtern (damit auch
215 // mit Ctrl-Click ein D&D gestartet werden kann)
216 if ( nModifier
== KEY_MOD1
&& eSelMode
== SINGLE_SELECTION
)
219 Point aPos
= rMEvt
.GetPosPixel();
222 pWin
->CaptureMouse();
223 nFlags
|= SELENG_IN_SEL
;
227 case 0: // KEY_NO_KEY
229 BOOL bSelAtPoint
= pFunctionSet
->IsSelectionAtPoint( aPos
);
230 nFlags
&= (~SELENG_IN_ADD
);
231 if ( (nFlags
& SELENG_DRG_ENAB
) && bSelAtPoint
)
233 nFlags
|= SELENG_WAIT_UPEVT
;
234 nFlags
&= ~(SELENG_IN_SEL
);
235 pWin
->ReleaseMouse();
236 return TRUE
; //auf STARTDRAG-Command-Event warten
238 if ( eSelMode
!= SINGLE_SELECTION
)
241 pFunctionSet
->DeselectAll();
243 pFunctionSet
->DestroyAnchor();
244 nFlags
&= (~SELENG_HAS_ANCH
); // bHasAnchor = FALSE;
246 pFunctionSet
->SetCursorAtPoint( aPos
);
247 // Sonderbehandlung Single-Selection, damit Select+Drag
248 // in einem Zug moeglich ist
249 if (eSelMode
== SINGLE_SELECTION
&& (nFlags
& SELENG_DRG_ENAB
))
250 nFlags
|= SELENG_WAIT_UPEVT
;
255 if ( eSelMode
== SINGLE_SELECTION
)
257 pWin
->ReleaseMouse();
258 nFlags
&= (~SELENG_IN_SEL
);
261 if ( nFlags
& SELENG_ADD_ALW
)
262 nFlags
|= SELENG_IN_ADD
;
264 nFlags
&= (~SELENG_IN_ADD
);
266 if( !(nFlags
& SELENG_HAS_ANCH
) )
268 if ( !(nFlags
& SELENG_IN_ADD
) )
269 pFunctionSet
->DeselectAll();
270 pFunctionSet
->CreateAnchor();
271 nFlags
|= SELENG_HAS_ANCH
;
273 pFunctionSet
->SetCursorAtPoint( aPos
);
277 // Control nur bei Mehrfachselektion erlaubt
278 if ( eSelMode
!= MULTIPLE_SELECTION
)
280 nFlags
&= (~SELENG_IN_SEL
);
281 pWin
->ReleaseMouse();
282 return TRUE
; // Mausclick verschlucken
284 if ( nFlags
& SELENG_HAS_ANCH
)
286 // pFunctionSet->CreateCursor();
287 pFunctionSet
->DestroyAnchor();
288 nFlags
&= (~SELENG_HAS_ANCH
);
290 if ( pFunctionSet
->IsSelectionAtPoint( aPos
) )
292 pFunctionSet
->DeselectAtPoint( aPos
);
293 pFunctionSet
->SetCursorAtPoint( aPos
, TRUE
);
297 pFunctionSet
->SetCursorAtPoint( aPos
);
301 case KEY_SHIFT
+ KEY_MOD1
:
302 if ( eSelMode
!= MULTIPLE_SELECTION
)
304 pWin
->ReleaseMouse();
305 nFlags
&= (~SELENG_IN_SEL
);
308 nFlags
|= SELENG_IN_ADD
; //bIsInAddMode = TRUE;
309 if ( !(nFlags
& SELENG_HAS_ANCH
) )
311 pFunctionSet
->CreateAnchor();
312 nFlags
|= SELENG_HAS_ANCH
;
314 pFunctionSet
->SetCursorAtPoint( aPos
);
321 /*************************************************************************
323 |* SelectionEngine::SelMouseButtonUp()
325 |* Beschreibung SELENG.SDW
326 |* Ersterstellung OV 10.10.94
327 |* Letzte Aenderung OV 10.10.94
329 *************************************************************************/
331 BOOL
SelectionEngine::SelMouseButtonUp( const MouseEvent
& /* rMEvt */ )
335 if( !pFunctionSet
|| !pWin
)
337 nFlags
&= ~(SELENG_CMDEVT
| SELENG_WAIT_UPEVT
| SELENG_IN_SEL
);
340 pWin
->ReleaseMouse();
342 if( (nFlags
& SELENG_WAIT_UPEVT
) && !(nFlags
& SELENG_CMDEVT
) &&
343 eSelMode
!= SINGLE_SELECTION
)
345 // MouseButtonDown in Sel aber kein CommandEvent eingetrudelt
347 USHORT nModifier
= aLastMove
.GetModifier() | nLockedMods
;
348 if( nModifier
== KEY_MOD1
|| IsAlwaysAdding() )
350 if( !(nModifier
& KEY_SHIFT
) )
352 pFunctionSet
->DestroyAnchor();
353 nFlags
&= (~SELENG_HAS_ANCH
); // nix Anker
355 pFunctionSet
->DeselectAtPoint( aLastMove
.GetPosPixel() );
356 nFlags
&= (~SELENG_HAS_ANCH
); // nix Anker
357 pFunctionSet
->SetCursorAtPoint( aLastMove
.GetPosPixel(), TRUE
);
361 pFunctionSet
->DeselectAll();
362 nFlags
&= (~SELENG_HAS_ANCH
); // nix Anker
363 pFunctionSet
->SetCursorAtPoint( aLastMove
.GetPosPixel() );
367 nFlags
&= ~(SELENG_CMDEVT
| SELENG_WAIT_UPEVT
| SELENG_IN_SEL
);
371 /*************************************************************************
373 |* SelectionEngine::SelMouseMove()
375 |* Beschreibung SELENG.SDW
376 |* Ersterstellung OV 10.10.94
377 |* Letzte Aenderung OV 10.10.94
379 *************************************************************************/
381 BOOL
SelectionEngine::SelMouseMove( const MouseEvent
& rMEvt
)
384 if ( !pFunctionSet
|| !(nFlags
& SELENG_IN_SEL
) ||
385 (nFlags
& (SELENG_CMDEVT
| SELENG_WAIT_UPEVT
)) )
388 if( !(nFlags
& SELENG_EXPANDONMOVE
) )
389 return FALSE
; // auf DragEvent warten!
392 // wenn die Maus ausserhalb der Area steht, dann wird die
393 // Frequenz des SetCursorAtPoint() nur durch den Timer bestimmt
394 if( aWTimer
.IsActive() && !aArea
.IsInside( rMEvt
.GetPosPixel() ))
397 aWTimer
.SetTimeout( nUpdateInterval
);
399 if ( eSelMode
!= SINGLE_SELECTION
)
401 if ( !(nFlags
& SELENG_HAS_ANCH
) )
403 pFunctionSet
->CreateAnchor();
404 //DbgOut("Move:Creating anchor");
405 nFlags
|= SELENG_HAS_ANCH
;
409 //DbgOut("Move:SetCursor");
410 pFunctionSet
->SetCursorAtPoint( rMEvt
.GetPosPixel() );
415 /*************************************************************************
417 |* SelectionEngine::SetWindow()
419 |* Beschreibung SELENG.SDW
420 |* Ersterstellung OV 10.10.94
421 |* Letzte Aenderung OV 10.10.94
423 *************************************************************************/
425 void SelectionEngine::SetWindow( Window
* pNewWin
)
427 if( pNewWin
!= pWin
)
429 if ( pWin
&& (nFlags
& SELENG_IN_SEL
) )
430 pWin
->ReleaseMouse();
432 if ( pWin
&& ( nFlags
& SELENG_IN_SEL
) )
433 pWin
->CaptureMouse();
437 /*************************************************************************
439 |* SelectionEngine::Reset()
441 |* Beschreibung SELENG.SDW
442 |* Ersterstellung OV 07.07.95
443 |* Letzte Aenderung OV 07.07.95
445 *************************************************************************/
447 void SelectionEngine::Reset()
450 if ( nFlags
& SELENG_IN_SEL
)
451 pWin
->ReleaseMouse();
452 nFlags
&= ~(SELENG_HAS_ANCH
| SELENG_IN_SEL
);
456 /*************************************************************************
458 |* SelectionEngine::Command()
460 |* Beschreibung SELENG.SDW
461 |* Ersterstellung OV 07.07.95
462 |* Letzte Aenderung OV 07.07.95
464 *************************************************************************/
466 void SelectionEngine::Command( const CommandEvent
& rCEvt
)
468 // Timer aWTimer ist beim Aufspannen einer Selektion aktiv
469 if ( !pFunctionSet
|| !pWin
|| aWTimer
.IsActive() )
472 nFlags
|= SELENG_CMDEVT
;
473 if ( rCEvt
.GetCommand() == COMMAND_STARTDRAG
)
475 if ( nFlags
& SELENG_DRG_ENAB
)
477 DBG_ASSERT( rCEvt
.IsMouseEvent(), "STARTDRAG: Not a MouseEvent" );
478 if ( pFunctionSet
->IsSelectionAtPoint( rCEvt
.GetMousePosPixel() ) )
480 aLastMove
= MouseEvent( rCEvt
.GetMousePosPixel(),
481 aLastMove
.GetClicks(), aLastMove
.GetMode(),
482 aLastMove
.GetButtons(), aLastMove
.GetModifier() );
483 pFunctionSet
->BeginDrag();
484 nFlags
&= ~(SELENG_CMDEVT
|SELENG_WAIT_UPEVT
|SELENG_IN_SEL
);
487 nFlags
&= ~SELENG_CMDEVT
;
490 nFlags
&= ~SELENG_CMDEVT
;
494 void SelectionEngine::SetUpdateInterval( ULONG nInterval
)
496 if (nInterval
< SELENG_AUTOREPEAT_INTERVAL_MIN
)
497 // Set a lower threshold. On Windows, setting this value too low
498 // would cause selection to get updated indefinitely.
499 nInterval
= SELENG_AUTOREPEAT_INTERVAL_MIN
;
501 if (nUpdateInterval
== nInterval
)
505 if (aWTimer
.IsActive())
507 // reset the timer right away on interval change.
509 aWTimer
.SetTimeout(nInterval
);
513 aWTimer
.SetTimeout(nInterval
);
515 nUpdateInterval
= nInterval
;