update dev300-m58
[ooovba.git] / vcl / source / window / seleng.cxx
blob0a8f57cfa1ef336be53c1e7b1b23260a06652db9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: seleng.cxx,v $
10 * $Revision: 1.7 $
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 ) :
63 pWin( pWindow ),
64 nUpdateInterval( nAutoRepeatInterval )
66 eSelMode = SINGLE_SELECTION;
67 pFunctionSet = pFuncSet;
68 nFlags = SELENG_EXPANDONMOVE;
69 nLockedMods = 0;
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()
87 aWTimer.Stop();
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 );
104 return 0;
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 )
119 eSelMode = 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 )
149 if ( !pFunctionSet )
150 return;
152 if ( bShift && eSelMode != SINGLE_SELECTION )
154 if ( IsAddMode() )
156 if ( !(nFlags & SELENG_HAS_ANCH) )
158 pFunctionSet->CreateAnchor();
159 nFlags |= SELENG_HAS_ANCH;
162 else
164 if ( !(nFlags & SELENG_HAS_ANCH) )
166 if( ShouldDeselect( bMod1 ) )
167 pFunctionSet->DeselectAll();
168 pFunctionSet->CreateAnchor();
169 nFlags |= SELENG_HAS_ANCH;
173 else
175 if ( IsAddMode() )
177 if ( nFlags & SELENG_HAS_ANCH )
179 // pFunctionSet->CreateCursor();
180 pFunctionSet->DestroyAnchor();
181 nFlags &= (~SELENG_HAS_ANCH);
184 else
186 if( ShouldDeselect( bMod1 ) )
187 pFunctionSet->DeselectAll();
188 else
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() )
209 return FALSE;
211 USHORT nModifier = rMEvt.GetModifier() | nLockedMods;
212 if ( nModifier & KEY_MOD2 )
213 return FALSE;
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 )
217 nModifier = 0;
219 Point aPos = rMEvt.GetPosPixel();
220 aLastMove = rMEvt;
222 pWin->CaptureMouse();
223 nFlags |= SELENG_IN_SEL;
225 switch ( nModifier )
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 )
240 if( !IsAddMode() )
241 pFunctionSet->DeselectAll();
242 else
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;
251 return TRUE;
254 case KEY_SHIFT:
255 if ( eSelMode == SINGLE_SELECTION )
257 pWin->ReleaseMouse();
258 nFlags &= (~SELENG_IN_SEL);
259 return FALSE;
261 if ( nFlags & SELENG_ADD_ALW )
262 nFlags |= SELENG_IN_ADD;
263 else
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 );
274 return TRUE;
276 case KEY_MOD1:
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 );
295 else
297 pFunctionSet->SetCursorAtPoint( aPos );
299 return TRUE;
301 case KEY_SHIFT + KEY_MOD1:
302 if ( eSelMode != MULTIPLE_SELECTION )
304 pWin->ReleaseMouse();
305 nFlags &= (~SELENG_IN_SEL);
306 return FALSE;
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 );
315 return TRUE;
318 return FALSE;
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 */ )
333 aWTimer.Stop();
334 //DbgOut("Up");
335 if( !pFunctionSet || !pWin )
337 nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL);
338 return FALSE;
340 pWin->ReleaseMouse();
342 if( (nFlags & SELENG_WAIT_UPEVT) && !(nFlags & SELENG_CMDEVT) &&
343 eSelMode != SINGLE_SELECTION)
345 // MouseButtonDown in Sel aber kein CommandEvent eingetrudelt
346 // ==> deselektieren
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 );
359 else
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);
368 return TRUE;
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)) )
386 return FALSE;
388 if( !(nFlags & SELENG_EXPANDONMOVE) )
389 return FALSE; // auf DragEvent warten!
391 aLastMove = rMEvt;
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() ))
395 return TRUE;
397 aWTimer.SetTimeout( nUpdateInterval );
398 aWTimer.Start();
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() );
412 return TRUE;
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();
431 pWin = pNewWin;
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()
449 aWTimer.Stop();
450 if ( nFlags & SELENG_IN_SEL )
451 pWin->ReleaseMouse();
452 nFlags &= ~(SELENG_HAS_ANCH | SELENG_IN_SEL);
453 nLockedMods = 0;
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() )
470 return;
471 aWTimer.Stop();
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);
486 else
487 nFlags &= ~SELENG_CMDEVT;
489 else
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)
502 // no update needed.
503 return;
505 if (aWTimer.IsActive())
507 // reset the timer right away on interval change.
508 aWTimer.Stop();
509 aWTimer.SetTimeout(nInterval);
510 aWTimer.Start();
512 else
513 aWTimer.SetTimeout(nInterval);
515 nUpdateInterval = nInterval;