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: select.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_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <tools/urlobj.hxx>
39 #include <vcl/sound.hxx>
40 #include <vcl/svapp.hxx>
41 #include <sfx2/docfile.hxx>
45 #include "tabvwsh.hxx"
47 #include "document.hxx"
48 //#include "dataobj.hxx"
49 #include "transobj.hxx"
51 #include "tabprotection.hxx"
53 #define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
55 extern USHORT nScFillModeMouseModifier
; // global.cxx
57 using namespace com::sun::star
;
59 // STATIC DATA -----------------------------------------------------------
61 static Point aSwitchPos
; //! Member
62 static BOOL bDidSwitch
= FALSE
;
64 // -----------------------------------------------------------------------
67 // View (Gridwin / Tastatur)
70 ScViewFunctionSet::ScViewFunctionSet( ScViewData
* pNewViewData
) :
71 pViewData( pNewViewData
),
76 DBG_ASSERT(pViewData
, "ViewData==0 bei FunctionSet");
79 ScSplitPos
ScViewFunctionSet::GetWhich()
82 return pEngine
->GetWhich();
84 return pViewData
->GetActivePart();
87 ULONG
ScViewFunctionSet::CalcUpdateInterval( const Size
& rWinSize
, const Point
& rEffPos
,
88 bool bLeftScroll
, bool bTopScroll
, bool bRightScroll
, bool bBottomScroll
)
90 ULONG nUpdateInterval
= SELENG_AUTOREPEAT_INTERVAL_MAX
;
91 Window
* pWin
= pEngine
->GetWindow();
92 Rectangle aScrRect
= pWin
->GetDesktopRectPixel();
93 Point aRootPos
= pWin
->OutputToAbsoluteScreenPixel(Point(0,0));
96 double nWinRight
= rWinSize
.getWidth() + aRootPos
.getX();
97 double nMarginRight
= aScrRect
.GetWidth() - nWinRight
;
98 double nHOffset
= rEffPos
.X() - rWinSize
.Width();
99 double nHAccelRate
= nHOffset
/ nMarginRight
;
101 if (nHAccelRate
> 1.0)
104 nUpdateInterval
= static_cast<ULONG
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nHAccelRate
));
109 double nMarginLeft
= aRootPos
.getX();
110 double nHOffset
= -rEffPos
.X();
111 double nHAccelRate
= nHOffset
/ nMarginLeft
;
113 if (nHAccelRate
> 1.0)
116 ULONG nTmp
= static_cast<ULONG
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nHAccelRate
));
117 if (nUpdateInterval
> nTmp
)
118 nUpdateInterval
= nTmp
;
123 double nWinBottom
= rWinSize
.getHeight() + aRootPos
.getY();
124 double nMarginBottom
= aScrRect
.GetHeight() - nWinBottom
;
125 double nVOffset
= rEffPos
.Y() - rWinSize
.Height();
126 double nVAccelRate
= nVOffset
/ nMarginBottom
;
128 if (nVAccelRate
> 1.0)
131 ULONG nTmp
= static_cast<ULONG
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nVAccelRate
));
132 if (nUpdateInterval
> nTmp
)
133 nUpdateInterval
= nTmp
;
138 double nMarginTop
= aRootPos
.getY();
139 double nVOffset
= -rEffPos
.Y();
140 double nVAccelRate
= nVOffset
/ nMarginTop
;
142 if (nVAccelRate
> 1.0)
145 ULONG nTmp
= static_cast<ULONG
>(SELENG_AUTOREPEAT_INTERVAL_MAX
*(1.0 - nVAccelRate
));
146 if (nUpdateInterval
> nTmp
)
147 nUpdateInterval
= nTmp
;
151 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
152 bool bRefMode
= pViewShell
&& pViewShell
->IsRefInputMode();
153 if (bRefMode
&& nUpdateInterval
< SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN
)
154 // Lower the update interval during ref mode, because re-draw can be
155 // expensive on Windows. Making this interval too small would queue up
156 // the scroll/paint requests which would cause semi-infinite
157 // scrolls even after the mouse cursor is released. We don't have
158 // this problem on Linux.
159 nUpdateInterval
= SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN
;
161 return nUpdateInterval
;
164 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine
* pSelEngine
)
166 pEngine
= pSelEngine
;
171 void __EXPORT
ScViewFunctionSet::BeginDrag()
173 SCTAB nTab
= pViewData
->GetTabNo();
179 Point aMPos
= pEngine
->GetMousePosPixel();
180 pViewData
->GetPosFromPixel( aMPos
.X(), aMPos
.Y(), GetWhich(), nPosX
, nPosY
);
184 nPosX
= pViewData
->GetCurX();
185 nPosY
= pViewData
->GetCurY();
188 ScModule
* pScMod
= SC_MOD();
189 BOOL bRefMode
= pScMod
->IsFormulaMode();
192 pViewData
->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp wird verschluckt
194 ScMarkData
& rMark
= pViewData
->GetMarkData();
195 // rMark.SetMarking(FALSE); // es fehlt ein ButtonUp
196 rMark
.MarkToSimple();
197 if ( rMark
.IsMarked() && !rMark
.IsMultiMarked() )
199 ScDocument
* pClipDoc
= new ScDocument( SCDOCMODE_CLIP
);
200 // bApi = TRUE -> no error mesages
201 BOOL bCopied
= pViewData
->GetView()->CopyToClip( pClipDoc
, FALSE
, TRUE
);
204 sal_Int8 nDragActions
= pViewData
->GetView()->SelectionEditable() ?
205 ( DND_ACTION_COPYMOVE
| DND_ACTION_LINK
) :
206 ( DND_ACTION_COPY
| DND_ACTION_LINK
);
208 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
209 TransferableObjectDescriptor aObjDesc
;
210 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
211 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
212 // maSize is set in ScTransferObj ctor
214 ScTransferObj
* pTransferObj
= new ScTransferObj( pClipDoc
, aObjDesc
);
215 uno::Reference
<datatransfer::XTransferable
> xTransferable( pTransferObj
);
217 // set position of dragged cell within range
218 ScRange aMarkRange
= pTransferObj
->GetRange();
219 SCCOL nStartX
= aMarkRange
.aStart
.Col();
220 SCROW nStartY
= aMarkRange
.aStart
.Row();
221 SCCOL nHandleX
= (nPosX
>= (SCsCOL
) nStartX
) ? nPosX
- nStartX
: 0;
222 SCROW nHandleY
= (nPosY
>= (SCsROW
) nStartY
) ? nPosY
- nStartY
: 0;
223 pTransferObj
->SetDragHandlePos( nHandleX
, nHandleY
);
224 pTransferObj
->SetVisibleTab( nTab
);
226 pTransferObj
->SetDragSource( pDocSh
, rMark
);
228 Window
* pWindow
= pViewData
->GetActiveWin();
229 if ( pWindow
->IsTracking() )
230 pWindow
->EndTracking( ENDTRACK_CANCEL
); // abort selecting
232 SC_MOD()->SetDragObject( pTransferObj
, NULL
); // for internal D&D
233 pTransferObj
->StartDrag( pWindow
, nDragActions
);
235 return; // dragging started
242 Sound::Beep(); // can't drag
247 void __EXPORT
ScViewFunctionSet::CreateAnchor()
251 BOOL bRefMode
= SC_MOD()->IsFormulaMode();
253 SetAnchor( pViewData
->GetRefStartX(), pViewData
->GetRefStartY() );
255 SetAnchor( pViewData
->GetCurX(), pViewData
->GetCurY() );
258 void ScViewFunctionSet::SetAnchor( SCCOL nPosX
, SCROW nPosY
)
260 BOOL bRefMode
= SC_MOD()->IsFormulaMode();
261 ScTabView
* pView
= pViewData
->GetView();
262 SCTAB nTab
= pViewData
->GetTabNo();
266 pView
->DoneRefMode( FALSE
);
267 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
268 pView
->InitRefMode( aAnchorPos
.Col(), aAnchorPos
.Row(), aAnchorPos
.Tab(),
272 else if (pViewData
->IsAnyFillMode())
274 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
279 // nicht weg und gleich wieder hin
280 if ( bStarted
&& pView
->IsMarking( nPosX
, nPosY
, nTab
) )
286 pView
->DoneBlockMode( TRUE
);
287 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
288 ScMarkData
& rMark
= pViewData
->GetMarkData();
289 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
291 pView
->InitBlockMode( aAnchorPos
.Col(), aAnchorPos
.Row(),
292 aAnchorPos
.Tab(), TRUE
);
302 void __EXPORT
ScViewFunctionSet::DestroyAnchor()
304 BOOL bRefMode
= SC_MOD()->IsFormulaMode();
306 pViewData
->GetView()->DoneRefMode( TRUE
);
308 pViewData
->GetView()->DoneBlockMode( TRUE
);
313 void ScViewFunctionSet::SetAnchorFlag( BOOL bSet
)
318 BOOL __EXPORT
ScViewFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, BOOL
/* bDontSelectAtCursor */ )
322 if ( rPointPixel
== aSwitchPos
)
323 return FALSE
; // nicht auf falschem Fenster scrollen
327 aSwitchPos
= rPointPixel
; // nur wichtig, wenn bDidSwitch
329 // treat position 0 as -1, so scrolling is always possible
330 // (with full screen and hidden headers, the top left border may be at 0)
331 // (moved from ScViewData::GetPosFromPixel)
333 Point aEffPos
= rPointPixel
;
334 if ( aEffPos
.X() == 0 )
336 if ( aEffPos
.Y() == 0 )
341 Size aWinSize
= pEngine
->GetWindow()->GetOutputSizePixel();
342 bool bRightScroll
= ( aEffPos
.X() >= aWinSize
.Width() );
343 bool bLeftScroll
= ( aEffPos
.X() < 0 );
344 bool bBottomScroll
= ( aEffPos
.Y() >= aWinSize
.Height() );
345 bool bTopScroll
= ( aEffPos
.Y() < 0 );
346 bool bScroll
= bRightScroll
|| bBottomScroll
|| bLeftScroll
|| bTopScroll
;
350 pViewData
->GetPosFromPixel( aEffPos
.X(), aEffPos
.Y(), GetWhich(),
351 nPosX
, nPosY
, TRUE
, TRUE
); // mit Repair
353 // fuer AutoFill in der Mitte der Zelle umschalten
354 // dabei aber nicht das Scrolling nach rechts/unten verhindern
355 if ( pViewData
->IsFillMode() || pViewData
->GetFillMode() == SC_FILL_MATRIX
)
358 pViewData
->GetMouseQuadrant( aEffPos
, GetWhich(), nPosX
, nPosY
, bLeft
, bTop
);
359 ScDocument
* pDoc
= pViewData
->GetDocument();
360 SCTAB nTab
= pViewData
->GetTabNo();
361 if ( bLeft
&& !bRightScroll
)
362 do --nPosX
; while ( nPosX
>=0 && pDoc
->ColHidden( nPosX
, nTab
) );
363 if ( bTop
&& !bBottomScroll
)
367 nPosY
= pDoc
->LastVisibleRow(0, nPosY
, nTab
);
368 if (!ValidRow(nPosY
))
372 // negativ ist erlaubt
375 // ueber Fixier-Grenze bewegt?
377 ScSplitPos eWhich
= GetWhich();
378 if ( eWhich
== pViewData
->GetActivePart() )
380 if ( pViewData
->GetHSplitMode() == SC_SPLIT_FIX
)
381 if ( aEffPos
.X() >= aWinSize
.Width() )
383 if ( eWhich
== SC_SPLIT_TOPLEFT
)
384 pViewData
->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
), bScroll
= FALSE
, bDidSwitch
= TRUE
;
385 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
386 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bScroll
= FALSE
, bDidSwitch
= TRUE
;
389 if ( pViewData
->GetVSplitMode() == SC_SPLIT_FIX
)
390 if ( aEffPos
.Y() >= aWinSize
.Height() )
392 if ( eWhich
== SC_SPLIT_TOPLEFT
)
393 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
), bScroll
= FALSE
, bDidSwitch
= TRUE
;
394 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
395 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bScroll
= FALSE
, bDidSwitch
= TRUE
;
401 // Adjust update interval based on how far the mouse pointer is from the edge.
402 ULONG nUpdateInterval
= CalcUpdateInterval(
403 aWinSize
, aEffPos
, bLeftScroll
, bTopScroll
, bRightScroll
, bBottomScroll
);
404 pEngine
->SetUpdateInterval(nUpdateInterval
);
408 // Don't forget to reset the interval when not scrolling!
409 pEngine
->SetUpdateInterval(SELENG_AUTOREPEAT_INTERVAL
);
412 pViewData
->ResetOldCursor();
413 return SetCursorAtCell( nPosX
, nPosY
, bScroll
);
416 BOOL
ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX
, SCsROW nPosY
, BOOL bScroll
)
418 ScTabView
* pView
= pViewData
->GetView();
419 SCTAB nTab
= pViewData
->GetTabNo();
420 ScDocument
* pDoc
= pViewData
->GetDocument();
422 if ( pDoc
->IsTabProtected(nTab
) )
424 if (nPosX
< 0 || nPosY
< 0)
427 ScTableProtection
* pProtect
= pDoc
->GetTabProtection(nTab
);
428 bool bSkipProtected
= !pProtect
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
429 bool bSkipUnprotected
= !pProtect
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
431 if ( bSkipProtected
&& bSkipUnprotected
)
434 bool bCellProtected
= pDoc
->HasAttrib(nPosX
, nPosY
, nTab
, nPosX
, nPosY
, nTab
, HASATTR_PROTECTED
);
435 if ( (bCellProtected
&& bSkipProtected
) || (!bCellProtected
&& bSkipUnprotected
) )
436 // Don't select this cell!
440 ScModule
* pScMod
= SC_MOD();
441 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
442 bool bRefMode
= ( pViewShell
? pViewShell
->IsRefInputMode() : false );
444 BOOL bHide
= !bRefMode
&& !pViewData
->IsAnyFillMode() &&
445 ( nPosX
!= (SCsCOL
) pViewData
->GetCurX() || nPosY
!= (SCsROW
) pViewData
->GetCurY() );
448 pView
->HideAllCursors();
454 ScSplitPos eWhich
= GetWhich();
455 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
, &eWhich
);
458 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
);
463 // #90910# if no input is possible from this doc, don't move the reference cursor around
464 if ( !pScMod
->IsModalMode(pViewData
->GetSfxDocShell()) )
468 pView
->DoneRefMode( TRUE
);
469 pView
->InitRefMode( nPosX
, nPosY
, pViewData
->GetTabNo(), SC_REFTYPE_REF
);
472 pView
->UpdateRef( nPosX
, nPosY
, pViewData
->GetTabNo() );
475 else if (pViewData
->IsFillMode() ||
476 (pViewData
->GetFillMode() == SC_FILL_MATRIX
&& (nScFillModeMouseModifier
& KEY_MOD1
) ))
478 // Wenn eine Matrix angefasst wurde, kann mit Ctrl auf AutoFill zurueckgeschaltet werden
480 SCCOL nStartX
, nEndX
;
481 SCROW nStartY
, nEndY
; // Block
483 pViewData
->GetSimpleArea( nStartX
, nStartY
, nDummy
, nEndX
, nEndY
, nDummy
);
485 if (pViewData
->GetRefType() != SC_REFTYPE_FILL
)
487 pView
->InitRefMode( nStartX
, nStartY
, nTab
, SC_REFTYPE_FILL
);
492 BOOL bOldDelMark
= pViewData
->GetDelMark( aDelRange
);
494 if ( nPosX
+1 >= (SCsCOL
) nStartX
&& nPosX
<= (SCsCOL
) nEndX
&&
495 nPosY
+1 >= (SCsROW
) nStartY
&& nPosY
<= (SCsROW
) nEndY
&&
496 ( nPosX
!= nEndX
|| nPosY
!= nEndY
) ) // verkleinern ?
498 // Richtung (links oder oben)
501 for (SCCOL i
=nPosX
+1; i
<=nEndX
; i
++)
502 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
503 long nSizeY
= (long) pDoc
->GetRowHeight( nPosY
+1, nEndY
, nTab
);
505 SCCOL nDelStartX
= nStartX
;
506 SCROW nDelStartY
= nStartY
;
507 if ( nSizeX
> nSizeY
)
508 nDelStartX
= nPosX
+ 1;
510 nDelStartY
= nPosY
+ 1;
511 // 0 braucht nicht mehr getrennt abgefragt zu werden, weil nPosX/Y auch negativ wird
513 if ( nDelStartX
< nStartX
)
514 nDelStartX
= nStartX
;
515 if ( nDelStartY
< nStartY
)
516 nDelStartY
= nStartY
;
520 pViewData
->SetDelMark( ScRange( nDelStartX
,nDelStartY
,nTab
,
521 nEndX
,nEndY
,nTab
) );
522 pViewData
->GetView()->UpdateShrinkOverlay();
527 ScUpdateRect
aRect( aDelRange
.aStart
.Col(), aDelRange
.aStart
.Row(),
528 aDelRange
.aEnd
.Col(), aDelRange
.aEnd
.Row() );
529 aRect
.SetNew( nDelStartX
,nDelStartY
, nEndX
,nEndY
);
534 if (aRect
.GetDiff( nPaintStartX
, nPaintStartY
, nPaintEndX
, nPaintEndY
))
535 pViewData
->GetView()->
536 PaintArea( nPaintStartX
, nPaintStartY
,
537 nPaintEndX
, nPaintEndY
, SC_UPDATE_MARKS
);
541 pViewData
->GetView()->
542 PaintArea( nStartX
,nDelStartY
, nEndX
,nEndY
, SC_UPDATE_MARKS
);
544 nPosX
= nEndX
; // roten Rahmen um ganzen Bereich lassen
547 // Referenz wieder richtigherum, falls unten umgedreht
548 if ( nStartX
!= pViewData
->GetRefStartX() || nStartY
!= pViewData
->GetRefStartY() )
550 pViewData
->GetView()->DoneRefMode();
551 pViewData
->GetView()->InitRefMode( nStartX
, nStartY
, nTab
, SC_REFTYPE_FILL
);
558 pViewData
->ResetDelMark();
559 pViewData
->GetView()->UpdateShrinkOverlay();
562 pViewData
->GetView()->
563 PaintArea( aDelRange
.aStart
.Col(), aDelRange
.aStart
.Row(),
564 aDelRange
.aEnd
.Col(), aDelRange
.aEnd
.Row(), SC_UPDATE_MARKS
);
568 BOOL bNegX
= ( nPosX
< (SCsCOL
) nStartX
);
569 BOOL bNegY
= ( nPosY
< (SCsROW
) nStartY
);
574 // #94321# in SetCursorAtPoint hidden columns are skipped.
575 // They must be skipped here too, or the result will always be the first hidden column.
576 do ++nPosX
; while ( nPosX
<nStartX
&& pDoc
->ColHidden(nPosX
, nTab
) );
577 for (SCCOL i
=nPosX
; i
<nStartX
; i
++)
578 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
581 for (SCCOL i
=nEndX
+1; i
<=nPosX
; i
++)
582 nSizeX
+= pDoc
->GetColWidth( i
, nTab
);
587 // #94321# in SetCursorAtPoint hidden rows are skipped.
588 // They must be skipped here too, or the result will always be the first hidden row.
589 if (++nPosY
< nStartY
)
591 nPosY
= pDoc
->FirstVisibleRow(nPosY
, nStartY
-1, nTab
);
592 if (!ValidRow(nPosY
))
595 nSizeY
+= pDoc
->GetRowHeight( nPosY
, nStartY
-1, nTab
);
598 nSizeY
+= pDoc
->GetRowHeight( nEndY
+1, nPosY
, nTab
);
600 if ( nSizeX
> nSizeY
) // Fill immer nur in einer Richtung
611 SCCOL nRefStX
= bNegX
? nEndX
: nStartX
;
612 SCROW nRefStY
= bNegY
? nEndY
: nStartY
;
613 if ( nRefStX
!= pViewData
->GetRefStartX() || nRefStY
!= pViewData
->GetRefStartY() )
615 pViewData
->GetView()->DoneRefMode();
616 pViewData
->GetView()->InitRefMode( nRefStX
, nRefStY
, nTab
, SC_REFTYPE_FILL
);
620 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
622 else if (pViewData
->IsAnyFillMode())
624 BYTE nMode
= pViewData
->GetFillMode();
625 if ( nMode
== SC_FILL_EMBED_LT
|| nMode
== SC_FILL_EMBED_RB
)
627 DBG_ASSERT( pDoc
->IsEmbedded(), "!pDoc->IsEmbedded()" );
629 pDoc
->GetEmbedded( aRange
);
630 ScRefType eRefMode
= (nMode
== SC_FILL_EMBED_LT
) ? SC_REFTYPE_EMBED_LT
: SC_REFTYPE_EMBED_RB
;
631 if (pViewData
->GetRefType() != eRefMode
)
633 if ( nMode
== SC_FILL_EMBED_LT
)
634 pView
->InitRefMode( aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), nTab
, eRefMode
);
636 pView
->InitRefMode( aRange
.aStart
.Col(), aRange
.aStart
.Row(), nTab
, eRefMode
);
640 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
642 else if ( nMode
== SC_FILL_MATRIX
)
644 SCCOL nStartX
, nEndX
;
645 SCROW nStartY
, nEndY
; // Block
647 pViewData
->GetSimpleArea( nStartX
, nStartY
, nDummy
, nEndX
, nEndY
, nDummy
);
649 if (pViewData
->GetRefType() != SC_REFTYPE_FILL
)
651 pView
->InitRefMode( nStartX
, nStartY
, nTab
, SC_REFTYPE_FILL
);
655 if ( nPosX
< nStartX
) nPosX
= nStartX
;
656 if ( nPosY
< nStartY
) nPosY
= nStartY
;
658 pView
->UpdateRef( nPosX
, nPosY
, nTab
);
662 else // normales Markieren
664 BOOL bHideCur
= bAnchor
&& ( (SCCOL
)nPosX
!= pViewData
->GetCurX() ||
665 (SCROW
)nPosY
!= pViewData
->GetCurY() );
667 pView
->HideAllCursors(); // sonst zweimal: Block und SetCursor
673 BOOL bMove
= ( nPosX
!= (SCsCOL
) aAnchorPos
.Col() ||
674 nPosY
!= (SCsROW
) aAnchorPos
.Row() );
675 if ( bMove
|| ( pEngine
&& pEngine
->GetMouseEvent().IsShift() ) )
677 pView
->InitBlockMode( aAnchorPos
.Col(), aAnchorPos
.Row(),
678 aAnchorPos
.Tab(), TRUE
);
683 // If the selection is already started, don't set the cursor.
684 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
, FALSE
, FALSE
, TRUE
);
686 pView
->SetCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
);
690 ScMarkData
& rMark
= pViewData
->GetMarkData();
691 if (rMark
.IsMarked() || rMark
.IsMultiMarked())
693 pView
->DoneBlockMode(TRUE
);
694 pView
->InitBlockMode( nPosX
, nPosY
, nTab
, TRUE
);
695 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
);
697 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
700 // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
701 // it highlights that new cell as well as the old cell where the cursor is
702 // positioned prior to the click. A selection mode via Shift-F8 should also
703 // follow the same behavior.
704 else if ( pViewData
->IsSelCtrlMouseClick() )
706 SCCOL nOldX
= pViewData
->GetCurX();
707 SCROW nOldY
= pViewData
->GetCurY();
709 pView
->InitBlockMode( nOldX
, nOldY
, nTab
, TRUE
);
710 pView
->MarkCursor( (SCCOL
) nOldX
, (SCROW
) nOldY
, nTab
);
712 if ( nOldX
!= nPosX
|| nOldY
!= nPosY
)
714 pView
->DoneBlockMode( TRUE
);
715 pView
->InitBlockMode( nPosX
, nPosY
, nTab
, TRUE
);
716 pView
->MarkCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
, nTab
);
717 aAnchorPos
.Set( nPosX
, nPosY
, nTab
);
722 pView
->SetCursor( (SCCOL
) nPosX
, (SCROW
) nPosY
);
725 pViewData
->SetRefStart( nPosX
, nPosY
, nTab
);
727 pView
->ShowAllCursors();
731 pView
->ShowAllCursors();
736 BOOL __EXPORT
ScViewFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
738 BOOL bRefMode
= SC_MOD()->IsFormulaMode();
742 if (pViewData
->IsAnyFillMode())
745 ScMarkData
& rMark
= pViewData
->GetMarkData();
746 if (bAnchor
|| !rMark
.IsMultiMarked())
750 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), GetWhich(), nPosX
, nPosY
);
751 return pViewData
->GetMarkData().IsCellMarked( (SCCOL
) nPosX
, (SCROW
) nPosY
);
757 void __EXPORT
ScViewFunctionSet::DeselectAtPoint( const Point
& /* rPointPixel */ )
762 void __EXPORT
ScViewFunctionSet::DeselectAll()
764 if (pViewData
->IsAnyFillMode())
767 BOOL bRefMode
= SC_MOD()->IsFormulaMode();
770 pViewData
->GetView()->DoneRefMode( FALSE
);
774 pViewData
->GetView()->DoneBlockMode( FALSE
);
775 pViewData
->GetViewShell()->UpdateInputHandler();
781 //------------------------------------------------------------------------
783 ScViewSelectionEngine::ScViewSelectionEngine( Window
* pWindow
, ScTabView
* pView
,
784 ScSplitPos eSplitPos
) :
785 SelectionEngine( pWindow
, pView
->GetFunctionSet() ),
788 // Parameter einstellen
789 SetSelectionMode( MULTIPLE_SELECTION
);
794 //------------------------------------------------------------------------
797 // Spalten- / Zeilenheader
800 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData
* pNewViewData
) :
801 pViewData( pNewViewData
),
803 eWhich( SC_SPLIT_TOPLEFT
),
807 DBG_ASSERT(pViewData
, "ViewData==0 bei FunctionSet");
810 void ScHeaderFunctionSet::SetColumn( BOOL bSet
)
815 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew
)
820 void __EXPORT
ScHeaderFunctionSet::BeginDrag()
825 void __EXPORT
ScHeaderFunctionSet::CreateAnchor()
830 ScTabView
* pView
= pViewData
->GetView();
831 pView
->DoneBlockMode( TRUE
);
834 pView
->InitBlockMode( static_cast<SCCOL
>(nCursorPos
), 0, pViewData
->GetTabNo(), TRUE
, TRUE
, FALSE
);
835 pView
->MarkCursor( static_cast<SCCOL
>(nCursorPos
), MAXROW
, pViewData
->GetTabNo() );
839 pView
->InitBlockMode( 0, nCursorPos
, pViewData
->GetTabNo(), TRUE
, FALSE
, TRUE
);
840 pView
->MarkCursor( MAXCOL
, nCursorPos
, pViewData
->GetTabNo() );
845 void __EXPORT
ScHeaderFunctionSet::DestroyAnchor()
847 pViewData
->GetView()->DoneBlockMode( TRUE
);
851 BOOL __EXPORT
ScHeaderFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, BOOL
/* bDontSelectAtCursor */ )
855 // die naechste gueltige Position muss vom anderen Fenster kommen
856 if ( rPointPixel
== aSwitchPos
)
857 return FALSE
; // nicht auf falschem Fenster scrollen
864 Size aWinSize
= pViewData
->GetActiveWin()->GetOutputSizePixel();
867 bScroll
= ( rPointPixel
.X() < 0 || rPointPixel
.X() >= aWinSize
.Width() );
869 bScroll
= ( rPointPixel
.Y() < 0 || rPointPixel
.Y() >= aWinSize
.Height() );
871 // ueber Fixier-Grenze bewegt?
873 BOOL bSwitched
= FALSE
;
876 if ( pViewData
->GetHSplitMode() == SC_SPLIT_FIX
)
878 if ( rPointPixel
.X() > aWinSize
.Width() )
880 if ( eWhich
== SC_SPLIT_TOPLEFT
)
881 pViewData
->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
), bSwitched
= TRUE
;
882 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
883 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bSwitched
= TRUE
;
889 if ( pViewData
->GetVSplitMode() == SC_SPLIT_FIX
)
891 if ( rPointPixel
.Y() > aWinSize
.Height() )
893 if ( eWhich
== SC_SPLIT_TOPLEFT
)
894 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
), bSwitched
= TRUE
;
895 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
896 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
), bSwitched
= TRUE
;
902 aSwitchPos
= rPointPixel
;
904 return FALSE
; // nicht mit falschen Positionen rechnen
911 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), pViewData
->GetActivePart(),
912 nPosX
, nPosY
, FALSE
);
915 nCursorPos
= static_cast<SCCOLROW
>(nPosX
);
916 nPosY
= pViewData
->GetPosY(WhichV(pViewData
->GetActivePart()));
920 nCursorPos
= static_cast<SCCOLROW
>(nPosY
);
921 nPosX
= pViewData
->GetPosX(WhichH(pViewData
->GetActivePart()));
924 ScTabView
* pView
= pViewData
->GetView();
925 BOOL bHide
= pViewData
->GetCurX() != nPosX
||
926 pViewData
->GetCurY() != nPosY
;
928 pView
->HideAllCursors();
931 pView
->AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_LINE
);
932 pView
->SetCursor( nPosX
, nPosY
);
934 if ( !bAnchor
|| !pView
->IsBlockMode() )
936 pView
->DoneBlockMode( TRUE
);
937 pViewData
->GetMarkData().MarkToMulti(); //! wer verstellt das ???
938 pView
->InitBlockMode( nPosX
, nPosY
, pViewData
->GetTabNo(), TRUE
, bColumn
, !bColumn
);
943 pView
->MarkCursor( nPosX
, nPosY
, pViewData
->GetTabNo(), bColumn
, !bColumn
);
945 // SelectionChanged innerhalb von HideCursor wegen UpdateAutoFillMark
946 pView
->SelectionChanged();
949 pView
->ShowAllCursors();
954 BOOL __EXPORT
ScHeaderFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
958 pViewData
->GetPosFromPixel( rPointPixel
.X(), rPointPixel
.Y(), pViewData
->GetActivePart(),
959 nPosX
, nPosY
, FALSE
);
961 ScMarkData
& rMark
= pViewData
->GetMarkData();
963 return rMark
.IsColumnMarked( nPosX
);
965 return rMark
.IsRowMarked( nPosY
);
968 void __EXPORT
ScHeaderFunctionSet::DeselectAtPoint( const Point
& /* rPointPixel */ )
972 void __EXPORT
ScHeaderFunctionSet::DeselectAll()
974 pViewData
->GetView()->DoneBlockMode( FALSE
);
978 //------------------------------------------------------------------------
980 ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window
* pWindow
, ScHeaderFunctionSet
* pFuncSet
) :
981 SelectionEngine( pWindow
, pFuncSet
)
983 // Parameter einstellen
984 SetSelectionMode( MULTIPLE_SELECTION
);