1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
26 #include "tabvwsh.hxx"
28 #include "document.hxx"
29 #include "transobj.hxx"
31 #include "tabprotection.hxx"
32 #include "markdata.hxx"
35 #define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
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
),
59 OSL_ENSURE(pViewData
, "ViewData==0 at FunctionSet");
62 ScSplitPos
ScViewFunctionSet::GetWhich()
65 return pEngine
->GetWhich();
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));
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)
87 nUpdateInterval
= static_cast<sal_uLong
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nHAccelRate
));
92 double nMarginLeft
= aRootPos
.getX();
93 double nHOffset
= -rEffPos
.X();
94 double nHAccelRate
= nHOffset
/ nMarginLeft
;
96 if (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
;
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)
114 sal_uLong nTmp
= static_cast<sal_uLong
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nVAccelRate
));
115 if (nUpdateInterval
> nTmp
)
116 nUpdateInterval
= nTmp
;
121 double nMarginTop
= aRootPos
.getY();
122 double nVOffset
= -rEffPos
.Y();
123 double nVAccelRate
= nVOffset
/ nMarginTop
;
125 if (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
;
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
;
144 return nUpdateInterval
;
147 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine
* pSelEngine
)
149 pEngine
= pSelEngine
;
154 void ScViewFunctionSet::BeginDrag()
156 SCTAB nTab
= pViewData
->GetTabNo();
162 Point aMPos
= pEngine
->GetMousePosPixel();
163 pViewData
->GetPosFromPixel( aMPos
.X(), aMPos
.Y(), GetWhich(), nPosX
, nPosY
);
167 nPosX
= pViewData
->GetCurX();
168 nPosY
= pViewData
->GetCurY();
171 ScModule
* pScMod
= SC_MOD();
172 sal_Bool bRefMode
= pScMod
->IsFormulaMode();
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 );
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
228 void ScViewFunctionSet::CreateAnchor()
232 sal_Bool bRefMode
= SC_MOD()->IsFormulaMode();
234 SetAnchor( pViewData
->GetRefStartX(), pViewData
->GetRefStartY() );
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();
247 pView
->DoneRefMode( false );
248 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
249 pView
->InitRefMode( aAnchorPos
.Col(), aAnchorPos
.Row(), aAnchorPos
.Tab(),
253 else if (pViewData
->IsAnyFillMode())
255 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
260 // nicht weg und gleich wieder hin
261 if ( bStarted
&& pView
->IsMarking( nPosX
, nPosY
, nTab
) )
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
);
283 void ScViewFunctionSet::DestroyAnchor()
285 sal_Bool bRefMode
= SC_MOD()->IsFormulaMode();
287 pViewData
->GetView()->DoneRefMode( sal_True
);
289 pViewData
->GetView()->DoneBlockMode( sal_True
);
294 void ScViewFunctionSet::SetAnchorFlag( sal_Bool bSet
)
299 sal_Bool
ScViewFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, sal_Bool
/* bDontSelectAtCursor */ )
303 if ( rPointPixel
== aSwitchPos
)
304 return false; // don't scroll in wrong window
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 )
317 if ( aEffPos
.Y() == 0 )
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
;
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
)
348 nPosY
= pDoc
->LastVisibleRow(0, nPosY
, nTab
);
349 if (!ValidRow(nPosY
))
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
;
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
);
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)
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
)
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!
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() );
429 pView
->HideAllCursors();
435 ScSplitPos eWhich
= GetWhich();
436 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
, &eWhich
);
439 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
);
444 // if no input is possible from this doc, don't move the reference cursor around
445 if ( !pScMod
->IsModalMode(pViewData
->GetSfxDocShell()) )
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
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
);
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)
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;
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
;
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
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
);
522 pViewData
->ResetDelMark();
523 pViewData
->GetView()->UpdateShrinkOverlay();
526 sal_Bool bNegX
= ( nPosX
< (SCsCOL
) nStartX
);
527 sal_Bool bNegY
= ( nPosY
< (SCsROW
) nStartY
);
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
);
539 for (SCCOL i
=nEndX
+1; i
<=nPosX
; i
++)
540 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
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
))
553 nSizeY
+= pDoc
->GetRowHeight( nPosY
, nStartY
-1, nTab
);
556 nSizeY
+= pDoc
->GetRowHeight( nEndY
+1, nPosY
, nTab
);
558 if ( nSizeX
> nSizeY
) // Fill only ever in one direction
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()" );
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
);
594 pView
->InitRefMode( aRange
.aStart
.Col(), aRange
.aStart
.Row(), nTab
, eRefMode
);
598 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
600 else if ( nMode
== SC_FILL_MATRIX
)
602 SCCOL nStartX
, nEndX
;
603 SCROW nStartY
, nEndY
; // Block
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
);
613 if ( nPosX
< nStartX
) nPosX
= nStartX
;
614 if ( nPosY
< nStartY
) nPosY
= nStartY
;
616 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
620 else // regular selection
622 sal_Bool bHideCur
= bAnchor
&& ( (SCCOL
)nPosX
!= pViewData
->GetCurX() ||
623 (SCROW
)nPosY
!= pViewData
->GetCurY() );
625 pView
->HideAllCursors(); // otherwise twice: Block and SetCursor
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
);
641 // If the selection is already started, don't set the cursor.
642 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
, false, false, true );
644 pView
->SetCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
);
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
);
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
);
680 pView
->SetCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
);
683 pViewData
->SetRefStart( nPosX
, nPosY
, nTab
);
685 pView
->ShowAllCursors();
689 pView
->ShowAllCursors();
694 sal_Bool
ScViewFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
696 sal_Bool bRefMode
= SC_MOD()->IsFormulaMode();
700 if (pViewData
->IsAnyFillMode())
703 ScMarkData
& rMark
= pViewData
->GetMarkData();
704 if (bAnchor
|| !rMark
.IsMultiMarked())
708 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), GetWhich(), nPosX
, nPosY
);
709 return pViewData
->GetMarkData().IsCellMarked( (SCCOL
) nPosX
, (SCROW
) nPosY
);
715 void ScViewFunctionSet::DeselectAtPoint( const Point
& /* rPointPixel */ )
720 void ScViewFunctionSet::DeselectAll()
722 if (pViewData
->IsAnyFillMode())
725 sal_Bool bRefMode
= SC_MOD()->IsFormulaMode();
728 pViewData
->GetView()->DoneRefMode( false );
732 pViewData
->GetView()->DoneBlockMode( false );
733 pViewData
->GetViewShell()->UpdateInputHandler();
739 //------------------------------------------------------------------------
741 ScViewSelectionEngine::ScViewSelectionEngine( Window
* pWindow
, ScTabView
* pView
,
742 ScSplitPos eSplitPos
) :
743 SelectionEngine( pWindow
, pView
->GetFunctionSet() ),
746 SetSelectionMode( MULTIPLE_SELECTION
);
747 EnableDrag( sal_True
);
751 //------------------------------------------------------------------------
754 // column and row headers
757 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData
* pNewViewData
) :
758 pViewData( pNewViewData
),
760 eWhich( SC_SPLIT_TOPLEFT
),
764 OSL_ENSURE(pViewData
, "ViewData==0 at FunctionSet");
767 void ScHeaderFunctionSet::SetColumn( sal_Bool bSet
)
772 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew
)
777 void ScHeaderFunctionSet::BeginDrag()
782 void ScHeaderFunctionSet::CreateAnchor()
787 ScTabView
* pView
= pViewData
->GetView();
788 pView
->DoneBlockMode( sal_True
);
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() );
796 pView
->InitBlockMode( 0, nCursorPos
, pViewData
->GetTabNo(), sal_True
, false, sal_True
);
797 pView
->MarkCursor( MAXCOL
, nCursorPos
, pViewData
->GetTabNo() );
802 void ScHeaderFunctionSet::DestroyAnchor()
804 pViewData
->GetView()->DoneBlockMode( sal_True
);
808 sal_Bool
ScHeaderFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, sal_Bool
/* bDontSelectAtCursor */ )
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
821 Size aWinSize
= pViewData
->GetActiveWin()->GetOutputSizePixel();
824 bScroll
= ( rPointPixel
.X() < 0 || rPointPixel
.X() >= aWinSize
.Width() );
826 bScroll
= ( rPointPixel
.Y() < 0 || rPointPixel
.Y() >= aWinSize
.Height() );
828 // moved out of fix limit?
830 sal_Bool bSwitched
= false;
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
;
859 aSwitchPos
= rPointPixel
;
860 bDidSwitch
= sal_True
;
861 return false; // do not crunch with wrong positions
866 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), pViewData
->GetActivePart(),
867 nPosX
, nPosY
, false );
870 nCursorPos
= static_cast<SCCOLROW
>(nPosX
);
871 nPosY
= pViewData
->GetPosY(WhichV(pViewData
->GetActivePart()));
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
;
883 pView
->HideAllCursors();
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
);
898 pView
->MarkCursor( nPosX
, nPosY
, pViewData
->GetTabNo(), bColumn
, !bColumn
);
900 // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
901 pView
->SelectionChanged();
904 pView
->ShowAllCursors();
909 sal_Bool
ScHeaderFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
913 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), pViewData
->GetActivePart(),
914 nPosX
, nPosY
, false );
916 ScMarkData
& rMark
= pViewData
->GetMarkData();
918 return rMark
.IsColumnMarked( nPosX
);
920 return rMark
.IsRowMarked( nPosY
);
923 void ScHeaderFunctionSet::DeselectAtPoint( const Point
& /* rPointPixel */ )
927 void ScHeaderFunctionSet::DeselectAll()
929 pViewData
->GetView()->DoneBlockMode( false );
933 //------------------------------------------------------------------------
935 ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window
* pWindow
, ScHeaderFunctionSet
* pFuncSet
) :
936 SelectionEngine( pWindow
, pFuncSet
)
938 SetSelectionMode( MULTIPLE_SELECTION
);
942 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */