GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / sc / source / ui / view / select.cxx
blob6f44a531248f395b2120828fc4b6ded51872b163
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/urlobj.hxx>
21 #include <vcl/svapp.hxx>
22 #include <sfx2/docfile.hxx>
24 #include "select.hxx"
25 #include "sc.hrc"
26 #include "tabvwsh.hxx"
27 #include "scmod.hxx"
28 #include "document.hxx"
29 #include "transobj.hxx"
30 #include "docsh.hxx"
31 #include "tabprotection.hxx"
32 #include "markdata.hxx"
34 #if defined WNT
35 #define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
36 #endif
38 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
40 using namespace com::sun::star;
42 // STATIC DATA -----------------------------------------------------------
44 static Point aSwitchPos; //! Member
45 static sal_Bool bDidSwitch = false;
47 // -----------------------------------------------------------------------
50 // View (Gridwin / keyboard)
53 ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) :
54 pViewData( pNewViewData ),
55 pEngine( NULL ),
56 bAnchor( false ),
57 bStarted( false )
59 OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
62 ScSplitPos ScViewFunctionSet::GetWhich()
64 if (pEngine)
65 return pEngine->GetWhich();
66 else
67 return pViewData->GetActivePart();
70 sal_uLong ScViewFunctionSet::CalcUpdateInterval( const Size& rWinSize, const Point& rEffPos,
71 bool bLeftScroll, bool bTopScroll, bool bRightScroll, bool bBottomScroll )
73 sal_uLong nUpdateInterval = SELENG_AUTOREPEAT_INTERVAL_MAX;
74 Window* pWin = pEngine->GetWindow();
75 Rectangle aScrRect = pWin->GetDesktopRectPixel();
76 Point aRootPos = pWin->OutputToAbsoluteScreenPixel(Point(0,0));
77 if (bRightScroll)
79 double nWinRight = rWinSize.getWidth() + aRootPos.getX();
80 double nMarginRight = aScrRect.GetWidth() - nWinRight;
81 double nHOffset = rEffPos.X() - rWinSize.Width();
82 double nHAccelRate = nHOffset / nMarginRight;
84 if (nHAccelRate > 1.0)
85 nHAccelRate = 1.0;
87 nUpdateInterval = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
90 if (bLeftScroll)
92 double nMarginLeft = aRootPos.getX();
93 double nHOffset = -rEffPos.X();
94 double nHAccelRate = nHOffset / nMarginLeft;
96 if (nHAccelRate > 1.0)
97 nHAccelRate = 1.0;
99 sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
100 if (nUpdateInterval > nTmp)
101 nUpdateInterval = nTmp;
104 if (bBottomScroll)
106 double nWinBottom = rWinSize.getHeight() + aRootPos.getY();
107 double nMarginBottom = aScrRect.GetHeight() - nWinBottom;
108 double nVOffset = rEffPos.Y() - rWinSize.Height();
109 double nVAccelRate = nVOffset / nMarginBottom;
111 if (nVAccelRate > 1.0)
112 nVAccelRate = 1.0;
114 sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
115 if (nUpdateInterval > nTmp)
116 nUpdateInterval = nTmp;
119 if (bTopScroll)
121 double nMarginTop = aRootPos.getY();
122 double nVOffset = -rEffPos.Y();
123 double nVAccelRate = nVOffset / nMarginTop;
125 if (nVAccelRate > 1.0)
126 nVAccelRate = 1.0;
128 sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
129 if (nUpdateInterval > nTmp)
130 nUpdateInterval = nTmp;
133 #ifdef WNT
134 ScTabViewShell* pViewShell = pViewData->GetViewShell();
135 bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
136 if (bRefMode && nUpdateInterval < SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN)
137 // Lower the update interval during ref mode, because re-draw can be
138 // expensive on Windows. Making this interval too small would queue up
139 // the scroll/paint requests which would cause semi-infinite
140 // scrolls even after the mouse cursor is released. We don't have
141 // this problem on Linux.
142 nUpdateInterval = SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN;
143 #endif
144 return nUpdateInterval;
147 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine )
149 pEngine = pSelEngine;
152 // Drag & Drop
154 void ScViewFunctionSet::BeginDrag()
156 SCTAB nTab = pViewData->GetTabNo();
158 SCsCOL nPosX;
159 SCsROW nPosY;
160 if (pEngine)
162 Point aMPos = pEngine->GetMousePosPixel();
163 pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
165 else
167 nPosX = pViewData->GetCurX();
168 nPosY = pViewData->GetCurY();
171 ScModule* pScMod = SC_MOD();
172 sal_Bool bRefMode = pScMod->IsFormulaMode();
173 if (!bRefMode)
175 pViewData->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp is swallowed
177 ScMarkData& rMark = pViewData->GetMarkData();
178 rMark.MarkToSimple();
179 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
181 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
182 // bApi = TRUE -> no error messages
183 sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, false, true );
184 if ( bCopied )
186 sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ?
187 ( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) :
188 ( DND_ACTION_COPY | DND_ACTION_LINK );
190 ScDocShell* pDocSh = pViewData->GetDocShell();
191 TransferableObjectDescriptor aObjDesc;
192 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
193 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
194 // maSize is set in ScTransferObj ctor
196 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
197 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
199 // set position of dragged cell within range
200 ScRange aMarkRange = pTransferObj->GetRange();
201 SCCOL nStartX = aMarkRange.aStart.Col();
202 SCROW nStartY = aMarkRange.aStart.Row();
203 SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0;
204 SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0;
205 pTransferObj->SetDragHandlePos( nHandleX, nHandleY );
206 pTransferObj->SetVisibleTab( nTab );
208 pTransferObj->SetDragSource( pDocSh, rMark );
210 Window* pWindow = pViewData->GetActiveWin();
211 if ( pWindow->IsTracking() )
212 pWindow->EndTracking( ENDTRACK_CANCEL ); // abort selecting
214 SC_MOD()->SetDragObject( pTransferObj, NULL ); // for internal D&D
215 pTransferObj->StartDrag( pWindow, nDragActions );
217 return; // dragging started
219 else
220 delete pClipDoc;
226 // Selection
228 void ScViewFunctionSet::CreateAnchor()
230 if (bAnchor) return;
232 sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
233 if (bRefMode)
234 SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() );
235 else
236 SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() );
239 void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY )
241 sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
242 ScTabView* pView = pViewData->GetView();
243 SCTAB nTab = pViewData->GetTabNo();
245 if (bRefMode)
247 pView->DoneRefMode( false );
248 aAnchorPos.Set( nPosX, nPosY, nTab );
249 pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(),
250 SC_REFTYPE_REF );
251 bStarted = sal_True;
253 else if (pViewData->IsAnyFillMode())
255 aAnchorPos.Set( nPosX, nPosY, nTab );
256 bStarted = sal_True;
258 else
260 // nicht weg und gleich wieder hin
261 if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
263 // nix
265 else
267 pView->DoneBlockMode( sal_True );
268 aAnchorPos.Set( nPosX, nPosY, nTab );
269 ScMarkData& rMark = pViewData->GetMarkData();
270 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
272 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
273 aAnchorPos.Tab(), sal_True );
274 bStarted = sal_True;
276 else
277 bStarted = false;
280 bAnchor = sal_True;
283 void ScViewFunctionSet::DestroyAnchor()
285 sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
286 if (bRefMode)
287 pViewData->GetView()->DoneRefMode( sal_True );
288 else
289 pViewData->GetView()->DoneBlockMode( sal_True );
291 bAnchor = false;
294 void ScViewFunctionSet::SetAnchorFlag( sal_Bool bSet )
296 bAnchor = bSet;
299 sal_Bool ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ )
301 if ( bDidSwitch )
303 if ( rPointPixel == aSwitchPos )
304 return false; // don't scroll in wrong window
305 else
306 bDidSwitch = false;
308 aSwitchPos = rPointPixel; // only important, if bDidSwitch
310 // treat position 0 as -1, so scrolling is always possible
311 // (with full screen and hidden headers, the top left border may be at 0)
312 // (moved from ScViewData::GetPosFromPixel)
314 Point aEffPos = rPointPixel;
315 if ( aEffPos.X() == 0 )
316 aEffPos.X() = -1;
317 if ( aEffPos.Y() == 0 )
318 aEffPos.Y() = -1;
320 // Scrolling
322 Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel();
323 bool bRightScroll = ( aEffPos.X() >= aWinSize.Width() );
324 bool bLeftScroll = ( aEffPos.X() < 0 );
325 bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() );
326 bool bTopScroll = ( aEffPos.Y() < 0 );
327 bool bScroll = bRightScroll || bBottomScroll || bLeftScroll || bTopScroll;
329 SCsCOL nPosX;
330 SCsROW nPosY;
331 pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
332 nPosX, nPosY, sal_True, sal_True ); // with Repair
334 // for Autofill switch in the center of cell
335 // thereby don't prevent scrolling to bottom/right
336 if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX )
338 sal_Bool bLeft, bTop;
339 pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
340 ScDocument* pDoc = pViewData->GetDocument();
341 SCTAB nTab = pViewData->GetTabNo();
342 if ( bLeft && !bRightScroll )
343 do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) );
344 if ( bTop && !bBottomScroll )
346 if (--nPosY >= 0)
348 nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
349 if (!ValidRow(nPosY))
350 nPosY = -1;
353 // negative value is allowed
356 // moved out of fix limit?
358 ScSplitPos eWhich = GetWhich();
359 if ( eWhich == pViewData->GetActivePart() )
361 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
362 if ( aEffPos.X() >= aWinSize.Width() )
364 if ( eWhich == SC_SPLIT_TOPLEFT )
365 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = false, bDidSwitch = sal_True;
366 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
367 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = false, bDidSwitch = sal_True;
370 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
371 if ( aEffPos.Y() >= aWinSize.Height() )
373 if ( eWhich == SC_SPLIT_TOPLEFT )
374 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = false, bDidSwitch = sal_True;
375 else if ( eWhich == SC_SPLIT_TOPRIGHT )
376 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = false, bDidSwitch = sal_True;
380 if (bScroll)
382 // Adjust update interval based on how far the mouse pointer is from the edge.
383 sal_uLong nUpdateInterval = CalcUpdateInterval(
384 aWinSize, aEffPos, bLeftScroll, bTopScroll, bRightScroll, bBottomScroll);
385 pEngine->SetUpdateInterval(nUpdateInterval);
387 else
389 // Don't forget to reset the interval when not scrolling!
390 pEngine->SetUpdateInterval(SELENG_AUTOREPEAT_INTERVAL);
393 pViewData->ResetOldCursor();
394 return SetCursorAtCell( nPosX, nPosY, bScroll );
397 sal_Bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, sal_Bool bScroll )
399 ScTabView* pView = pViewData->GetView();
400 SCTAB nTab = pViewData->GetTabNo();
401 ScDocument* pDoc = pViewData->GetDocument();
403 if ( pDoc->IsTabProtected(nTab) )
405 if (nPosX < 0 || nPosY < 0)
406 return false;
408 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
409 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
410 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
412 if ( bSkipProtected && bSkipUnprotected )
413 return false;
415 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
416 if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
417 // Don't select this cell!
418 return false;
421 ScModule* pScMod = SC_MOD();
422 ScTabViewShell* pViewShell = pViewData->GetViewShell();
423 bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false );
425 sal_Bool bHide = !bRefMode && !pViewData->IsAnyFillMode() &&
426 ( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() );
428 if (bHide)
429 pView->HideAllCursors();
431 if (bScroll)
433 if (bRefMode)
435 ScSplitPos eWhich = GetWhich();
436 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
438 else
439 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
442 if (bRefMode)
444 // if no input is possible from this doc, don't move the reference cursor around
445 if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) )
447 if (!bAnchor)
449 pView->DoneRefMode( sal_True );
450 pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF );
453 pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() );
456 else if (pViewData->IsFillMode() ||
457 (pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) ))
459 // If a matrix got touched, switch back to Autofill is possible with Ctrl
461 SCCOL nStartX, nEndX;
462 SCROW nStartY, nEndY; // Block
463 SCTAB nDummy;
464 pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
466 if (pViewData->GetRefType() != SC_REFTYPE_FILL)
468 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
469 CreateAnchor();
472 ScRange aDelRange;
473 sal_Bool bOldDelMark = pViewData->GetDelMark( aDelRange );
475 if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
476 nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
477 ( nPosX != nEndX || nPosY != nEndY ) ) // minimize?
479 // direction (left or top)
481 long nSizeX = 0;
482 for (SCCOL i=nPosX+1; i<=nEndX; i++)
483 nSizeX += pDoc->GetColWidth( i, nTab );
484 long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab );
486 SCCOL nDelStartX = nStartX;
487 SCROW nDelStartY = nStartY;
488 if ( nSizeX > nSizeY )
489 nDelStartX = nPosX + 1;
490 else
491 nDelStartY = nPosY + 1;
492 // there is no need to check for zero, because nPosX/Y is also negative
494 if ( nDelStartX < nStartX )
495 nDelStartX = nStartX;
496 if ( nDelStartY < nStartY )
497 nDelStartY = nStartY;
499 // set range
501 pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
502 nEndX,nEndY,nTab ) );
503 pViewData->GetView()->UpdateShrinkOverlay();
505 pViewData->GetView()->
506 PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS );
508 nPosX = nEndX; // keep red border around range
509 nPosY = nEndY;
511 // reference the right way up, if it's upside down below
512 if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() )
514 pViewData->GetView()->DoneRefMode();
515 pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
518 else
520 if ( bOldDelMark )
522 pViewData->ResetDelMark();
523 pViewData->GetView()->UpdateShrinkOverlay();
526 sal_Bool bNegX = ( nPosX < (SCsCOL) nStartX );
527 sal_Bool bNegY = ( nPosY < (SCsROW) nStartY );
529 long nSizeX = 0;
530 if ( bNegX )
532 // in SetCursorAtPoint hidden columns are skipped.
533 // They must be skipped here too, or the result will always be the first hidden column.
534 do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) );
535 for (SCCOL i=nPosX; i<nStartX; i++)
536 nSizeX += pDoc->GetColWidth( i, nTab );
538 else
539 for (SCCOL i=nEndX+1; i<=nPosX; i++)
540 nSizeX += pDoc->GetColWidth( i, nTab );
542 long nSizeY = 0;
543 if ( bNegY )
545 // in SetCursorAtPoint hidden rows are skipped.
546 // They must be skipped here too, or the result will always be the first hidden row.
547 if (++nPosY < nStartY)
549 nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab);
550 if (!ValidRow(nPosY))
551 nPosY = nStartY;
553 nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab );
555 else
556 nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab );
558 if ( nSizeX > nSizeY ) // Fill only ever in one direction
560 nPosY = nEndY;
561 bNegY = false;
563 else
565 nPosX = nEndX;
566 bNegX = false;
569 SCCOL nRefStX = bNegX ? nEndX : nStartX;
570 SCROW nRefStY = bNegY ? nEndY : nStartY;
571 if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() )
573 pViewData->GetView()->DoneRefMode();
574 pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
578 pView->UpdateRef( nPosX, nPosY, nTab );
580 else if (pViewData->IsAnyFillMode())
582 sal_uInt8 nMode = pViewData->GetFillMode();
583 if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
585 OSL_ENSURE( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
586 ScRange aRange;
587 pDoc->GetEmbedded( aRange);
588 ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB;
589 if (pViewData->GetRefType() != eRefMode)
591 if ( nMode == SC_FILL_EMBED_LT )
592 pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
593 else
594 pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
595 CreateAnchor();
598 pView->UpdateRef( nPosX, nPosY, nTab );
600 else if ( nMode == SC_FILL_MATRIX )
602 SCCOL nStartX, nEndX;
603 SCROW nStartY, nEndY; // Block
604 SCTAB nDummy;
605 pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
607 if (pViewData->GetRefType() != SC_REFTYPE_FILL)
609 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
610 CreateAnchor();
613 if ( nPosX < nStartX ) nPosX = nStartX;
614 if ( nPosY < nStartY ) nPosY = nStartY;
616 pView->UpdateRef( nPosX, nPosY, nTab );
618 // else new modes
620 else // regular selection
622 sal_Bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() ||
623 (SCROW)nPosY != pViewData->GetCurY() );
624 if (bHideCur)
625 pView->HideAllCursors(); // otherwise twice: Block and SetCursor
627 if (bAnchor)
629 if (!bStarted)
631 sal_Bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() ||
632 nPosY != (SCsROW) aAnchorPos.Row() );
633 if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) )
635 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
636 aAnchorPos.Tab(), sal_True );
637 bStarted = sal_True;
640 if (bStarted)
641 // If the selection is already started, don't set the cursor.
642 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, false, false, true );
643 else
644 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
646 else
648 ScMarkData& rMark = pViewData->GetMarkData();
649 if (rMark.IsMarked() || rMark.IsMultiMarked())
651 pView->DoneBlockMode(sal_True);
652 pView->InitBlockMode( nPosX, nPosY, nTab, sal_True );
653 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
655 aAnchorPos.Set( nPosX, nPosY, nTab );
656 bStarted = sal_True;
658 // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
659 // it highlights that new cell as well as the old cell where the cursor is
660 // positioned prior to the click. A selection mode via Shift-F8 should also
661 // follow the same behavior.
662 else if ( pViewData->IsSelCtrlMouseClick() )
664 SCCOL nOldX = pViewData->GetCurX();
665 SCROW nOldY = pViewData->GetCurY();
667 pView->InitBlockMode( nOldX, nOldY, nTab, sal_True );
668 pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab );
670 if ( nOldX != nPosX || nOldY != nPosY )
672 pView->DoneBlockMode( sal_True );
673 pView->InitBlockMode( nPosX, nPosY, nTab, sal_True );
674 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
675 aAnchorPos.Set( nPosX, nPosY, nTab );
678 bStarted = sal_True;
680 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
683 pViewData->SetRefStart( nPosX, nPosY, nTab );
684 if (bHideCur)
685 pView->ShowAllCursors();
688 if (bHide)
689 pView->ShowAllCursors();
691 return sal_True;
694 sal_Bool ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
696 sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
697 if (bRefMode)
698 return false;
700 if (pViewData->IsAnyFillMode())
701 return false;
703 ScMarkData& rMark = pViewData->GetMarkData();
704 if (bAnchor || !rMark.IsMultiMarked())
706 SCsCOL nPosX;
707 SCsROW nPosY;
708 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
709 return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY );
712 return false;
715 void ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
717 // doesn't exist
720 void ScViewFunctionSet::DeselectAll()
722 if (pViewData->IsAnyFillMode())
723 return;
725 sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
726 if (bRefMode)
728 pViewData->GetView()->DoneRefMode( false );
730 else
732 pViewData->GetView()->DoneBlockMode( false );
733 pViewData->GetViewShell()->UpdateInputHandler();
736 bAnchor = false;
739 //------------------------------------------------------------------------
741 ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView,
742 ScSplitPos eSplitPos ) :
743 SelectionEngine( pWindow, pView->GetFunctionSet() ),
744 eWhich( eSplitPos )
746 SetSelectionMode( MULTIPLE_SELECTION );
747 EnableDrag( sal_True );
751 //------------------------------------------------------------------------
754 // column and row headers
757 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) :
758 pViewData( pNewViewData ),
759 bColumn( false ),
760 eWhich( SC_SPLIT_TOPLEFT ),
761 bAnchor( false ),
762 nCursorPos( 0 )
764 OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
767 void ScHeaderFunctionSet::SetColumn( sal_Bool bSet )
769 bColumn = bSet;
772 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew )
774 eWhich = eNew;
777 void ScHeaderFunctionSet::BeginDrag()
779 // doesn't exist
782 void ScHeaderFunctionSet::CreateAnchor()
784 if (bAnchor)
785 return;
787 ScTabView* pView = pViewData->GetView();
788 pView->DoneBlockMode( sal_True );
789 if (bColumn)
791 pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), sal_True, sal_True, false );
792 pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() );
794 else
796 pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), sal_True, false, sal_True );
797 pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() );
799 bAnchor = sal_True;
802 void ScHeaderFunctionSet::DestroyAnchor()
804 pViewData->GetView()->DoneBlockMode( sal_True );
805 bAnchor = false;
808 sal_Bool ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ )
810 if ( bDidSwitch )
812 // next valid position has to be originated from another window
813 if ( rPointPixel == aSwitchPos )
814 return false; // don't scroll in the wrong window
815 else
816 bDidSwitch = false;
819 // Scrolling
821 Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel();
822 sal_Bool bScroll;
823 if (bColumn)
824 bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
825 else
826 bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
828 // moved out of fix limit?
830 sal_Bool bSwitched = false;
831 if ( bColumn )
833 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
835 if ( rPointPixel.X() > aWinSize.Width() )
837 if ( eWhich == SC_SPLIT_TOPLEFT )
838 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = sal_True;
839 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
840 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True;
844 else // column headers
846 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
848 if ( rPointPixel.Y() > aWinSize.Height() )
850 if ( eWhich == SC_SPLIT_TOPLEFT )
851 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = sal_True;
852 else if ( eWhich == SC_SPLIT_TOPRIGHT )
853 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True;
857 if (bSwitched)
859 aSwitchPos = rPointPixel;
860 bDidSwitch = sal_True;
861 return false; // do not crunch with wrong positions
864 SCsCOL nPosX;
865 SCsROW nPosY;
866 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
867 nPosX, nPosY, false );
868 if (bColumn)
870 nCursorPos = static_cast<SCCOLROW>(nPosX);
871 nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart()));
873 else
875 nCursorPos = static_cast<SCCOLROW>(nPosY);
876 nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart()));
879 ScTabView* pView = pViewData->GetView();
880 sal_Bool bHide = pViewData->GetCurX() != nPosX ||
881 pViewData->GetCurY() != nPosY;
882 if (bHide)
883 pView->HideAllCursors();
885 if (bScroll)
886 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
887 pView->SetCursor( nPosX, nPosY );
889 if ( !bAnchor || !pView->IsBlockMode() )
891 pView->DoneBlockMode( sal_True );
892 pViewData->GetMarkData().MarkToMulti(); //! who changes this?
893 pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), sal_True, bColumn, !bColumn );
895 bAnchor = sal_True;
898 pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
900 // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
901 pView->SelectionChanged();
903 if (bHide)
904 pView->ShowAllCursors();
906 return sal_True;
909 sal_Bool ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
911 SCsCOL nPosX;
912 SCsROW nPosY;
913 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
914 nPosX, nPosY, false );
916 ScMarkData& rMark = pViewData->GetMarkData();
917 if (bColumn)
918 return rMark.IsColumnMarked( nPosX );
919 else
920 return rMark.IsRowMarked( nPosY );
923 void ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
927 void ScHeaderFunctionSet::DeselectAll()
929 pViewData->GetView()->DoneBlockMode( false );
930 bAnchor = false;
933 //------------------------------------------------------------------------
935 ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) :
936 SelectionEngine( pWindow, pFuncSet )
938 SetSelectionMode( MULTIPLE_SELECTION );
939 EnableDrag( false );
942 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */