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"
33 #include <gridwin.hxx>
36 #define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
39 extern sal_uInt16 nScFillModeMouseModifier
; // global.cxx
41 using namespace com::sun::star
;
43 // STATIC DATA -----------------------------------------------------------
45 static Point aSwitchPos
; //! Member
46 static bool bDidSwitch
= false;
48 // View (Gridwin / keyboard)
49 ScViewFunctionSet::ScViewFunctionSet( ScViewData
* pNewViewData
) :
50 pViewData( pNewViewData
),
55 OSL_ENSURE(pViewData
, "ViewData==0 at FunctionSet");
58 ScSplitPos
ScViewFunctionSet::GetWhich()
61 return pEngine
->GetWhich();
63 return pViewData
->GetActivePart();
66 sal_uLong
ScViewFunctionSet::CalcUpdateInterval( const Size
& rWinSize
, const Point
& rEffPos
,
67 bool bLeftScroll
, bool bTopScroll
, bool bRightScroll
, bool bBottomScroll
)
69 sal_uLong nUpdateInterval
= SELENG_AUTOREPEAT_INTERVAL_MAX
;
70 vcl::Window
* pWin
= pEngine
->GetWindow();
71 Rectangle aScrRect
= pWin
->GetDesktopRectPixel();
72 Point aRootPos
= pWin
->OutputToAbsoluteScreenPixel(Point(0,0));
75 double nWinRight
= rWinSize
.getWidth() + aRootPos
.getX();
76 double nMarginRight
= aScrRect
.GetWidth() - nWinRight
;
77 double nHOffset
= rEffPos
.X() - rWinSize
.Width();
78 double nHAccelRate
= nHOffset
/ nMarginRight
;
80 if (nHAccelRate
> 1.0)
83 nUpdateInterval
= static_cast<sal_uLong
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nHAccelRate
));
88 double nMarginLeft
= aRootPos
.getX();
89 double nHOffset
= -rEffPos
.X();
90 double nHAccelRate
= nHOffset
/ nMarginLeft
;
92 if (nHAccelRate
> 1.0)
95 sal_uLong nTmp
= static_cast<sal_uLong
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nHAccelRate
));
96 if (nUpdateInterval
> nTmp
)
97 nUpdateInterval
= nTmp
;
102 double nWinBottom
= rWinSize
.getHeight() + aRootPos
.getY();
103 double nMarginBottom
= aScrRect
.GetHeight() - nWinBottom
;
104 double nVOffset
= rEffPos
.Y() - rWinSize
.Height();
105 double nVAccelRate
= nVOffset
/ nMarginBottom
;
107 if (nVAccelRate
> 1.0)
110 sal_uLong nTmp
= static_cast<sal_uLong
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nVAccelRate
));
111 if (nUpdateInterval
> nTmp
)
112 nUpdateInterval
= nTmp
;
117 double nMarginTop
= aRootPos
.getY();
118 double nVOffset
= -rEffPos
.Y();
119 double nVAccelRate
= nVOffset
/ nMarginTop
;
121 if (nVAccelRate
> 1.0)
124 sal_uLong nTmp
= static_cast<sal_uLong
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nVAccelRate
));
125 if (nUpdateInterval
> nTmp
)
126 nUpdateInterval
= nTmp
;
130 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
131 bool bRefMode
= pViewShell
&& pViewShell
->IsRefInputMode();
132 if (bRefMode
&& nUpdateInterval
< SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN
)
133 // Lower the update interval during ref mode, because re-draw can be
134 // expensive on Windows. Making this interval too small would queue up
135 // the scroll/paint requests which would cause semi-infinite
136 // scrolls even after the mouse cursor is released. We don't have
137 // this problem on Linux.
138 nUpdateInterval
= SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN
;
140 return nUpdateInterval
;
143 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine
* pSelEngine
)
145 pEngine
= pSelEngine
;
149 void ScViewFunctionSet::BeginDrag()
151 SCTAB nTab
= pViewData
->GetTabNo();
157 Point aMPos
= pEngine
->GetMousePosPixel();
158 pViewData
->GetPosFromPixel( aMPos
.X(), aMPos
.Y(), GetWhich(), nPosX
, nPosY
);
162 nPosX
= pViewData
->GetCurX();
163 nPosY
= pViewData
->GetCurY();
166 ScModule
* pScMod
= SC_MOD();
167 bool bRefMode
= pScMod
->IsFormulaMode();
170 pViewData
->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp is swallowed
172 ScMarkData
& rMark
= pViewData
->GetMarkData();
173 rMark
.MarkToSimple();
174 if ( rMark
.IsMarked() && !rMark
.IsMultiMarked() )
176 ScDocument
* pClipDoc
= new ScDocument( SCDOCMODE_CLIP
);
177 // bApi = TRUE -> no error messages
178 bool bCopied
= pViewData
->GetView()->CopyToClip( pClipDoc
, false, true );
181 sal_Int8 nDragActions
= pViewData
->GetView()->SelectionEditable() ?
182 ( DND_ACTION_COPYMOVE
| DND_ACTION_LINK
) :
183 ( DND_ACTION_COPY
| DND_ACTION_LINK
);
185 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
186 TransferableObjectDescriptor aObjDesc
;
187 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
188 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
189 // maSize is set in ScTransferObj ctor
191 ScTransferObj
* pTransferObj
= new ScTransferObj( pClipDoc
, aObjDesc
);
192 uno::Reference
<datatransfer::XTransferable
> xTransferable( pTransferObj
);
194 // set position of dragged cell within range
195 ScRange aMarkRange
= pTransferObj
->GetRange();
196 SCCOL nStartX
= aMarkRange
.aStart
.Col();
197 SCROW nStartY
= aMarkRange
.aStart
.Row();
198 SCCOL nHandleX
= (nPosX
>= (SCsCOL
) nStartX
) ? nPosX
- nStartX
: 0;
199 SCROW nHandleY
= (nPosY
>= (SCsROW
) nStartY
) ? nPosY
- nStartY
: 0;
200 pTransferObj
->SetDragHandlePos( nHandleX
, nHandleY
);
201 pTransferObj
->SetVisibleTab( nTab
);
203 pTransferObj
->SetDragSource( pDocSh
, rMark
);
205 vcl::Window
* pWindow
= pViewData
->GetActiveWin();
206 if ( pWindow
->IsTracking() )
207 pWindow
->EndTracking( TrackingEventFlags::Cancel
); // abort selecting
209 SC_MOD()->SetDragObject( pTransferObj
, NULL
); // for internal D&D
210 pTransferObj
->StartDrag( pWindow
, nDragActions
);
212 return; // dragging started
222 void ScViewFunctionSet::CreateAnchor()
226 bool bRefMode
= SC_MOD()->IsFormulaMode();
228 SetAnchor( pViewData
->GetRefStartX(), pViewData
->GetRefStartY() );
230 SetAnchor( pViewData
->GetCurX(), pViewData
->GetCurY() );
233 void ScViewFunctionSet::SetAnchor( SCCOL nPosX
, SCROW nPosY
)
235 bool bRefMode
= SC_MOD()->IsFormulaMode();
236 ScTabView
* pView
= pViewData
->GetView();
237 SCTAB nTab
= pViewData
->GetTabNo();
241 pView
->DoneRefMode( false );
242 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
243 pView
->InitRefMode( aAnchorPos
.Col(), aAnchorPos
.Row(), aAnchorPos
.Tab(),
247 else if (pViewData
->IsAnyFillMode())
249 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
254 // don't go there and back again
255 if ( bStarted
&& pView
->IsMarking( nPosX
, nPosY
, nTab
) )
261 pView
->DoneBlockMode( true );
262 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
263 ScMarkData
& rMark
= pViewData
->GetMarkData();
264 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
266 pView
->InitBlockMode( aAnchorPos
.Col(), aAnchorPos
.Row(),
267 aAnchorPos
.Tab(), true );
277 void ScViewFunctionSet::DestroyAnchor()
279 bool bRefMode
= SC_MOD()->IsFormulaMode();
281 pViewData
->GetView()->DoneRefMode( true );
283 pViewData
->GetView()->DoneBlockMode( true );
288 void ScViewFunctionSet::SetAnchorFlag( bool bSet
)
293 bool ScViewFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, bool /* bDontSelectAtCursor */ )
297 if ( rPointPixel
== aSwitchPos
)
298 return false; // don't scroll in wrong window
302 aSwitchPos
= rPointPixel
; // only important, if bDidSwitch
304 // treat position 0 as -1, so scrolling is always possible
305 // (with full screen and hidden headers, the top left border may be at 0)
306 // (moved from ScViewData::GetPosFromPixel)
308 Point aEffPos
= rPointPixel
;
309 if ( aEffPos
.X() == 0 )
311 if ( aEffPos
.Y() == 0 )
315 Size aWinSize
= pEngine
->GetWindow()->GetOutputSizePixel();
316 bool bRightScroll
= ( aEffPos
.X() >= aWinSize
.Width() );
317 bool bLeftScroll
= ( aEffPos
.X() < 0 );
318 bool bBottomScroll
= ( aEffPos
.Y() >= aWinSize
.Height() );
319 bool bTopScroll
= ( aEffPos
.Y() < 0 );
320 bool bScroll
= bRightScroll
|| bBottomScroll
|| bLeftScroll
|| bTopScroll
;
324 pViewData
->GetPosFromPixel( aEffPos
.X(), aEffPos
.Y(), GetWhich(),
325 nPosX
, nPosY
, true, true ); // with Repair
327 // for Autofill switch in the center of cell
328 // thereby don't prevent scrolling to bottom/right
329 if ( pViewData
->IsFillMode() || pViewData
->GetFillMode() == SC_FILL_MATRIX
)
332 pViewData
->GetMouseQuadrant( aEffPos
, GetWhich(), nPosX
, nPosY
, bLeft
, bTop
);
333 ScDocument
* pDoc
= pViewData
->GetDocument();
334 SCTAB nTab
= pViewData
->GetTabNo();
335 if ( bLeft
&& !bRightScroll
)
336 do --nPosX
; while ( nPosX
>=0 && pDoc
->ColHidden( nPosX
, nTab
) );
337 if ( bTop
&& !bBottomScroll
)
341 nPosY
= pDoc
->LastVisibleRow(0, nPosY
, nTab
);
342 if (!ValidRow(nPosY
))
346 // negative value is allowed
349 // moved out of fix limit?
350 ScSplitPos eWhich
= GetWhich();
351 if ( eWhich
== pViewData
->GetActivePart() )
353 if ( pViewData
->GetHSplitMode() == SC_SPLIT_FIX
)
354 if ( aEffPos
.X() >= aWinSize
.Width() )
356 if ( eWhich
== SC_SPLIT_TOPLEFT
)
357 pViewData
->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
), bScroll
= false, bDidSwitch
= true;
358 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
359 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bScroll
= false, bDidSwitch
= true;
362 if ( pViewData
->GetVSplitMode() == SC_SPLIT_FIX
)
363 if ( aEffPos
.Y() >= aWinSize
.Height() )
365 if ( eWhich
== SC_SPLIT_TOPLEFT
)
366 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
), bScroll
= false, bDidSwitch
= true;
367 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
368 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bScroll
= false, bDidSwitch
= true;
374 // Adjust update interval based on how far the mouse pointer is from the edge.
375 sal_uLong nUpdateInterval
= CalcUpdateInterval(
376 aWinSize
, aEffPos
, bLeftScroll
, bTopScroll
, bRightScroll
, bBottomScroll
);
377 pEngine
->SetUpdateInterval(nUpdateInterval
);
381 // Don't forget to reset the interval when not scrolling!
382 pEngine
->SetUpdateInterval(SELENG_AUTOREPEAT_INTERVAL
);
385 pViewData
->ResetOldCursor();
386 return SetCursorAtCell( nPosX
, nPosY
, bScroll
);
389 bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX
, SCsROW nPosY
, bool bScroll
)
391 ScTabView
* pView
= pViewData
->GetView();
392 SCTAB nTab
= pViewData
->GetTabNo();
393 ScDocument
* pDoc
= pViewData
->GetDocument();
395 if ( pDoc
->IsTabProtected(nTab
) )
397 if (nPosX
< 0 || nPosY
< 0)
400 ScTableProtection
* pProtect
= pDoc
->GetTabProtection(nTab
);
404 bool bSkipProtected
= !pProtect
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
405 bool bSkipUnprotected
= !pProtect
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
407 if ( bSkipProtected
&& bSkipUnprotected
)
410 bool bCellProtected
= pDoc
->HasAttrib(nPosX
, nPosY
, nTab
, nPosX
, nPosY
, nTab
, HASATTR_PROTECTED
);
411 if ( (bCellProtected
&& bSkipProtected
) || (!bCellProtected
&& bSkipUnprotected
) )
412 // Don't select this cell!
416 ScModule
* pScMod
= SC_MOD();
417 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
418 bool bRefMode
= pViewShell
&& pViewShell
->IsRefInputMode();
420 bool bHide
= !bRefMode
&& !pViewData
->IsAnyFillMode() &&
421 ( nPosX
!= (SCsCOL
) pViewData
->GetCurX() || nPosY
!= (SCsROW
) pViewData
->GetCurY() );
424 pView
->HideAllCursors();
430 ScSplitPos eWhich
= GetWhich();
431 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
, &eWhich
);
434 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
);
439 // if no input is possible from this doc, don't move the reference cursor around
440 if ( !pScMod
->IsModalMode(pViewData
->GetSfxDocShell()) )
444 pView
->DoneRefMode( true );
445 pView
->InitRefMode( nPosX
, nPosY
, pViewData
->GetTabNo(), SC_REFTYPE_REF
);
448 pView
->UpdateRef( nPosX
, nPosY
, pViewData
->GetTabNo() );
449 pView
->SelectionChanged();
452 else if (pViewData
->IsFillMode() ||
453 (pViewData
->GetFillMode() == SC_FILL_MATRIX
&& (nScFillModeMouseModifier
& KEY_MOD1
) ))
455 // If a matrix got touched, switch back to Autofill is possible with Ctrl
457 SCCOL nStartX
, nEndX
;
458 SCROW nStartY
, nEndY
; // Block
460 pViewData
->GetSimpleArea( nStartX
, nStartY
, nDummy
, nEndX
, nEndY
, nDummy
);
462 if (pViewData
->GetRefType() != SC_REFTYPE_FILL
)
464 pView
->InitRefMode( nStartX
, nStartY
, nTab
, SC_REFTYPE_FILL
);
469 bool bOldDelMark
= pViewData
->GetDelMark( aDelRange
);
471 if ( nPosX
+1 >= (SCsCOL
) nStartX
&& nPosX
<= (SCsCOL
) nEndX
&&
472 nPosY
+1 >= (SCsROW
) nStartY
&& nPosY
<= (SCsROW
) nEndY
&&
473 ( nPosX
!= nEndX
|| nPosY
!= nEndY
) ) // minimize?
475 // direction (left or top)
478 for (SCCOL i
=nPosX
+1; i
<=nEndX
; i
++)
479 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
480 long nSizeY
= (long) pDoc
->GetRowHeight( nPosY
+1, nEndY
, nTab
);
482 SCCOL nDelStartX
= nStartX
;
483 SCROW nDelStartY
= nStartY
;
484 if ( nSizeX
> nSizeY
)
485 nDelStartX
= nPosX
+ 1;
487 nDelStartY
= nPosY
+ 1;
488 // there is no need to check for zero, because nPosX/Y is also negative
490 if ( nDelStartX
< nStartX
)
491 nDelStartX
= nStartX
;
492 if ( nDelStartY
< nStartY
)
493 nDelStartY
= nStartY
;
497 pViewData
->SetDelMark( ScRange( nDelStartX
,nDelStartY
,nTab
,
498 nEndX
,nEndY
,nTab
) );
499 pViewData
->GetView()->UpdateShrinkOverlay();
501 pViewData
->GetView()->
502 PaintArea( nStartX
,nDelStartY
, nEndX
,nEndY
, SC_UPDATE_MARKS
);
504 nPosX
= nEndX
; // keep red border around range
507 // reference the right way up, if it's upside down below
508 if ( nStartX
!= pViewData
->GetRefStartX() || nStartY
!= pViewData
->GetRefStartY() )
510 pViewData
->GetView()->DoneRefMode();
511 pViewData
->GetView()->InitRefMode( nStartX
, nStartY
, nTab
, SC_REFTYPE_FILL
);
518 pViewData
->ResetDelMark();
519 pViewData
->GetView()->UpdateShrinkOverlay();
522 bool bNegX
= ( nPosX
< (SCsCOL
) nStartX
);
523 bool bNegY
= ( nPosY
< (SCsROW
) nStartY
);
528 // in SetCursorAtPoint hidden columns are skipped.
529 // They must be skipped here too, or the result will always be the first hidden column.
530 do ++nPosX
; while ( nPosX
<nStartX
&& pDoc
->ColHidden(nPosX
, nTab
) );
531 for (SCCOL i
=nPosX
; i
<nStartX
; i
++)
532 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
535 for (SCCOL i
=nEndX
+1; i
<=nPosX
; i
++)
536 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
541 // in SetCursorAtPoint hidden rows are skipped.
542 // They must be skipped here too, or the result will always be the first hidden row.
543 if (++nPosY
< nStartY
)
545 nPosY
= pDoc
->FirstVisibleRow(nPosY
, nStartY
-1, nTab
);
546 if (!ValidRow(nPosY
))
549 nSizeY
+= pDoc
->GetRowHeight( nPosY
, nStartY
-1, nTab
);
552 nSizeY
+= pDoc
->GetRowHeight( nEndY
+1, nPosY
, nTab
);
554 if ( nSizeX
> nSizeY
) // Fill only ever in one direction
565 SCCOL nRefStX
= bNegX
? nEndX
: nStartX
;
566 SCROW nRefStY
= bNegY
? nEndY
: nStartY
;
567 if ( nRefStX
!= pViewData
->GetRefStartX() || nRefStY
!= pViewData
->GetRefStartY() )
569 pViewData
->GetView()->DoneRefMode();
570 pViewData
->GetView()->InitRefMode( nRefStX
, nRefStY
, nTab
, SC_REFTYPE_FILL
);
574 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
576 else if (pViewData
->IsAnyFillMode())
578 sal_uInt8 nMode
= pViewData
->GetFillMode();
579 if ( nMode
== SC_FILL_EMBED_LT
|| nMode
== SC_FILL_EMBED_RB
)
581 OSL_ENSURE( pDoc
->IsEmbedded(), "!pDoc->IsEmbedded()" );
583 pDoc
->GetEmbedded( aRange
);
584 ScRefType eRefMode
= (nMode
== SC_FILL_EMBED_LT
) ? SC_REFTYPE_EMBED_LT
: SC_REFTYPE_EMBED_RB
;
585 if (pViewData
->GetRefType() != eRefMode
)
587 if ( nMode
== SC_FILL_EMBED_LT
)
588 pView
->InitRefMode( aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), nTab
, eRefMode
);
590 pView
->InitRefMode( aRange
.aStart
.Col(), aRange
.aStart
.Row(), nTab
, eRefMode
);
594 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
596 else if ( nMode
== SC_FILL_MATRIX
)
598 SCCOL nStartX
, nEndX
;
599 SCROW nStartY
, nEndY
; // Block
601 pViewData
->GetSimpleArea( nStartX
, nStartY
, nDummy
, nEndX
, nEndY
, nDummy
);
603 if (pViewData
->GetRefType() != SC_REFTYPE_FILL
)
605 pView
->InitRefMode( nStartX
, nStartY
, nTab
, SC_REFTYPE_FILL
);
609 if ( nPosX
< nStartX
) nPosX
= nStartX
;
610 if ( nPosY
< nStartY
) nPosY
= nStartY
;
612 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
616 else // regular selection
618 bool bHideCur
= bAnchor
&& ( (SCCOL
)nPosX
!= pViewData
->GetCurX() ||
619 (SCROW
)nPosY
!= pViewData
->GetCurY() );
621 pView
->HideAllCursors(); // otherwise twice: Block and SetCursor
627 bool bMove
= ( nPosX
!= (SCsCOL
) aAnchorPos
.Col() ||
628 nPosY
!= (SCsROW
) aAnchorPos
.Row() );
629 if ( bMove
|| ( pEngine
&& pEngine
->GetMouseEvent().IsShift() ) )
631 pView
->InitBlockMode( aAnchorPos
.Col(), aAnchorPos
.Row(),
632 aAnchorPos
.Tab(), true );
637 // If the selection is already started, don't set the cursor.
638 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
, false, false, true );
640 pView
->SetCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
);
644 ScMarkData
& rMark
= pViewData
->GetMarkData();
645 if (rMark
.IsMarked() || rMark
.IsMultiMarked())
647 pView
->DoneBlockMode(true);
648 pView
->InitBlockMode( nPosX
, nPosY
, nTab
, true );
649 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
);
651 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
654 // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
655 // it highlights that new cell as well as the old cell where the cursor is
656 // positioned prior to the click. A selection mode via Shift-F8 should also
657 // follow the same behavior.
658 else if ( pViewData
->IsSelCtrlMouseClick() )
660 SCCOL nOldX
= pViewData
->GetCurX();
661 SCROW nOldY
= pViewData
->GetCurY();
663 pView
->InitBlockMode( nOldX
, nOldY
, nTab
, true );
664 pView
->MarkCursor( (SCCOL
) nOldX
, (SCROW
) nOldY
, nTab
);
666 if ( nOldX
!= nPosX
|| nOldY
!= nPosY
)
668 pView
->DoneBlockMode( true );
669 pView
->InitBlockMode( nPosX
, nPosY
, nTab
, true );
670 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
);
671 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
676 pView
->SetCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
);
679 pViewData
->SetRefStart( nPosX
, nPosY
, nTab
);
681 pView
->ShowAllCursors();
685 pView
->ShowAllCursors();
690 bool ScViewFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
692 bool bRefMode
= SC_MOD()->IsFormulaMode();
696 if (pViewData
->IsAnyFillMode())
699 ScMarkData
& rMark
= pViewData
->GetMarkData();
700 if (bAnchor
|| !rMark
.IsMultiMarked())
704 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), GetWhich(), nPosX
, nPosY
);
705 return pViewData
->GetMarkData().IsCellMarked( (SCCOL
) nPosX
, (SCROW
) nPosY
);
711 void ScViewFunctionSet::DeselectAtPoint( const Point
& /* rPointPixel */ )
716 void ScViewFunctionSet::DeselectAll()
718 if (pViewData
->IsAnyFillMode())
721 bool bRefMode
= SC_MOD()->IsFormulaMode();
724 pViewData
->GetView()->DoneRefMode( false );
728 pViewData
->GetView()->DoneBlockMode( false );
729 pViewData
->GetViewShell()->UpdateInputHandler();
735 ScViewSelectionEngine::ScViewSelectionEngine( vcl::Window
* pWindow
, ScTabView
* pView
,
736 ScSplitPos eSplitPos
) :
737 SelectionEngine( pWindow
, &pView
->GetFunctionSet() ),
740 SetSelectionMode( MULTIPLE_SELECTION
);
744 // column and row headers
745 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData
* pNewViewData
) :
746 pViewData( pNewViewData
),
748 eWhich( SC_SPLIT_TOPLEFT
),
752 OSL_ENSURE(pViewData
, "ViewData==0 at FunctionSet");
755 void ScHeaderFunctionSet::SetColumn( bool bSet
)
760 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew
)
765 void ScHeaderFunctionSet::BeginDrag()
770 void ScHeaderFunctionSet::CreateAnchor()
775 ScTabView
* pView
= pViewData
->GetView();
776 pView
->DoneBlockMode( true );
779 pView
->InitBlockMode( static_cast<SCCOL
>(nCursorPos
), 0, pViewData
->GetTabNo(), true, true, false );
780 pView
->MarkCursor( static_cast<SCCOL
>(nCursorPos
), MAXROW
, pViewData
->GetTabNo() );
784 pView
->InitBlockMode( 0, nCursorPos
, pViewData
->GetTabNo(), true, false, true );
785 pView
->MarkCursor( MAXCOL
, nCursorPos
, pViewData
->GetTabNo() );
790 void ScHeaderFunctionSet::DestroyAnchor()
792 pViewData
->GetView()->DoneBlockMode( true );
796 bool ScHeaderFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, bool /* bDontSelectAtCursor */ )
800 // next valid position has to be originated from another window
801 if ( rPointPixel
== aSwitchPos
)
802 return false; // don't scroll in the wrong window
808 Size aWinSize
= pViewData
->GetActiveWin()->GetOutputSizePixel();
811 bScroll
= ( rPointPixel
.X() < 0 || rPointPixel
.X() >= aWinSize
.Width() );
813 bScroll
= ( rPointPixel
.Y() < 0 || rPointPixel
.Y() >= aWinSize
.Height() );
815 // moved out of fix limit?
816 bool bSwitched
= false;
819 if ( pViewData
->GetHSplitMode() == SC_SPLIT_FIX
)
821 if ( rPointPixel
.X() > aWinSize
.Width() )
823 if ( eWhich
== SC_SPLIT_TOPLEFT
)
824 pViewData
->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
), bSwitched
= true;
825 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
826 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bSwitched
= true;
830 else // column headers
832 if ( pViewData
->GetVSplitMode() == SC_SPLIT_FIX
)
834 if ( rPointPixel
.Y() > aWinSize
.Height() )
836 if ( eWhich
== SC_SPLIT_TOPLEFT
)
837 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
), bSwitched
= true;
838 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
839 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bSwitched
= true;
845 aSwitchPos
= rPointPixel
;
847 return false; // do not crunch with wrong positions
852 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), pViewData
->GetActivePart(),
853 nPosX
, nPosY
, false );
856 nCursorPos
= static_cast<SCCOLROW
>(nPosX
);
857 nPosY
= pViewData
->GetPosY(WhichV(pViewData
->GetActivePart()));
861 nCursorPos
= static_cast<SCCOLROW
>(nPosY
);
862 nPosX
= pViewData
->GetPosX(WhichH(pViewData
->GetActivePart()));
865 ScTabView
* pView
= pViewData
->GetView();
866 bool bHide
= pViewData
->GetCurX() != nPosX
||
867 pViewData
->GetCurY() != nPosY
;
869 pView
->HideAllCursors();
872 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
);
873 pView
->SetCursor( nPosX
, nPosY
);
875 if ( !bAnchor
|| !pView
->IsBlockMode() )
877 pView
->DoneBlockMode( true );
878 pViewData
->GetMarkData().MarkToMulti(); //! who changes this?
879 pView
->InitBlockMode( nPosX
, nPosY
, pViewData
->GetTabNo(), true, bColumn
, !bColumn
);
884 pView
->MarkCursor( nPosX
, nPosY
, pViewData
->GetTabNo(), bColumn
, !bColumn
);
886 // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
887 pView
->SelectionChanged();
890 pView
->ShowAllCursors();
895 bool ScHeaderFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
899 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), pViewData
->GetActivePart(),
900 nPosX
, nPosY
, false );
902 ScMarkData
& rMark
= pViewData
->GetMarkData();
904 return rMark
.IsColumnMarked( nPosX
);
906 return rMark
.IsRowMarked( nPosY
);
909 void ScHeaderFunctionSet::DeselectAtPoint( const Point
& /* rPointPixel */ )
913 void ScHeaderFunctionSet::DeselectAll()
915 pViewData
->GetView()->DoneBlockMode( false );
919 ScHeaderSelectionEngine::ScHeaderSelectionEngine( vcl::Window
* pWindow
, ScHeaderFunctionSet
* pFuncSet
) :
920 SelectionEngine( pWindow
, pFuncSet
)
922 SetSelectionMode( MULTIPLE_SELECTION
);
926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */