merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / view / select.cxx
blob1451916262b5eb814b7ce77a5ba02d96a80e78b7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: select.cxx,v $
10 * $Revision: 1.20 $
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>
43 #include "select.hxx"
44 #include "sc.hrc"
45 #include "tabvwsh.hxx"
46 #include "scmod.hxx"
47 #include "document.hxx"
48 //#include "dataobj.hxx"
49 #include "transobj.hxx"
50 #include "docsh.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 ),
72 pEngine( NULL ),
73 bAnchor( FALSE ),
74 bStarted( FALSE )
76 DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet");
79 ScSplitPos ScViewFunctionSet::GetWhich()
81 if (pEngine)
82 return pEngine->GetWhich();
83 else
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));
94 if (bRightScroll)
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)
102 nHAccelRate = 1.0;
104 nUpdateInterval = static_cast<ULONG>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
107 if (bLeftScroll)
109 double nMarginLeft = aRootPos.getX();
110 double nHOffset = -rEffPos.X();
111 double nHAccelRate = nHOffset / nMarginLeft;
113 if (nHAccelRate > 1.0)
114 nHAccelRate = 1.0;
116 ULONG nTmp = static_cast<ULONG>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
117 if (nUpdateInterval > nTmp)
118 nUpdateInterval = nTmp;
121 if (bBottomScroll)
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)
129 nVAccelRate = 1.0;
131 ULONG nTmp = static_cast<ULONG>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
132 if (nUpdateInterval > nTmp)
133 nUpdateInterval = nTmp;
136 if (bTopScroll)
138 double nMarginTop = aRootPos.getY();
139 double nVOffset = -rEffPos.Y();
140 double nVAccelRate = nVOffset / nMarginTop;
142 if (nVAccelRate > 1.0)
143 nVAccelRate = 1.0;
145 ULONG nTmp = static_cast<ULONG>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
146 if (nUpdateInterval > nTmp)
147 nUpdateInterval = nTmp;
150 #ifdef WNT
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;
160 #endif
161 return nUpdateInterval;
164 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine )
166 pEngine = pSelEngine;
169 // Drag & Drop
171 void __EXPORT ScViewFunctionSet::BeginDrag()
173 SCTAB nTab = pViewData->GetTabNo();
175 SCsCOL nPosX;
176 SCsROW nPosY;
177 if (pEngine)
179 Point aMPos = pEngine->GetMousePosPixel();
180 pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
182 else
184 nPosX = pViewData->GetCurX();
185 nPosY = pViewData->GetCurY();
188 ScModule* pScMod = SC_MOD();
189 BOOL bRefMode = pScMod->IsFormulaMode();
190 if (!bRefMode)
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 );
202 if ( bCopied )
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
237 else
238 delete pClipDoc;
242 Sound::Beep(); // can't drag
245 // Selektion
247 void __EXPORT ScViewFunctionSet::CreateAnchor()
249 if (bAnchor) return;
251 BOOL bRefMode = SC_MOD()->IsFormulaMode();
252 if (bRefMode)
253 SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() );
254 else
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();
264 if (bRefMode)
266 pView->DoneRefMode( FALSE );
267 aAnchorPos.Set( nPosX, nPosY, nTab );
268 pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(),
269 SC_REFTYPE_REF );
270 bStarted = TRUE;
272 else if (pViewData->IsAnyFillMode())
274 aAnchorPos.Set( nPosX, nPosY, nTab );
275 bStarted = TRUE;
277 else
279 // nicht weg und gleich wieder hin
280 if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
282 // nix
284 else
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 );
293 bStarted = TRUE;
295 else
296 bStarted = FALSE;
299 bAnchor = TRUE;
302 void __EXPORT ScViewFunctionSet::DestroyAnchor()
304 BOOL bRefMode = SC_MOD()->IsFormulaMode();
305 if (bRefMode)
306 pViewData->GetView()->DoneRefMode( TRUE );
307 else
308 pViewData->GetView()->DoneBlockMode( TRUE );
310 bAnchor = FALSE;
313 void ScViewFunctionSet::SetAnchorFlag( BOOL bSet )
315 bAnchor = bSet;
318 BOOL __EXPORT ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, BOOL /* bDontSelectAtCursor */ )
320 if ( bDidSwitch )
322 if ( rPointPixel == aSwitchPos )
323 return FALSE; // nicht auf falschem Fenster scrollen
324 else
325 bDidSwitch = FALSE;
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 )
335 aEffPos.X() = -1;
336 if ( aEffPos.Y() == 0 )
337 aEffPos.Y() = -1;
339 // Scrolling
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;
348 SCsCOL nPosX;
349 SCsROW nPosY;
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 )
357 BOOL bLeft, bTop;
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 )
365 if (--nPosY >= 0)
367 nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
368 if (!ValidRow(nPosY))
369 nPosY = -1;
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;
399 if (bScroll)
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);
406 else
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)
425 return false;
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 )
432 return FALSE;
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!
437 return FALSE;
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() );
447 if (bHide)
448 pView->HideAllCursors();
450 if (bScroll)
452 if (bRefMode)
454 ScSplitPos eWhich = GetWhich();
455 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
457 else
458 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
461 if (bRefMode)
463 // #90910# if no input is possible from this doc, don't move the reference cursor around
464 if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) )
466 if (!bAnchor)
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
482 SCTAB nDummy;
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 );
488 CreateAnchor();
491 ScRange aDelRange;
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)
500 long nSizeX = 0;
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;
509 else
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;
518 // Bereich setzen
520 pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
521 nEndX,nEndY,nTab ) );
522 pViewData->GetView()->UpdateShrinkOverlay();
524 #if 0
525 if ( bOldDelMark )
527 ScUpdateRect aRect( aDelRange.aStart.Col(), aDelRange.aStart.Row(),
528 aDelRange.aEnd.Col(), aDelRange.aEnd.Row() );
529 aRect.SetNew( nDelStartX,nDelStartY, nEndX,nEndY );
530 SCCOL nPaintStartX;
531 SCROW nPaintStartY;
532 SCCOL nPaintEndX;
533 SCROW nPaintEndY;
534 if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY ))
535 pViewData->GetView()->
536 PaintArea( nPaintStartX, nPaintStartY,
537 nPaintEndX, nPaintEndY, SC_UPDATE_MARKS );
539 else
540 #endif
541 pViewData->GetView()->
542 PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS );
544 nPosX = nEndX; // roten Rahmen um ganzen Bereich lassen
545 nPosY = nEndY;
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 );
554 else
556 if ( bOldDelMark )
558 pViewData->ResetDelMark();
559 pViewData->GetView()->UpdateShrinkOverlay();
561 #if 0
562 pViewData->GetView()->
563 PaintArea( aDelRange.aStart.Col(), aDelRange.aStart.Row(),
564 aDelRange.aEnd.Col(), aDelRange.aEnd.Row(), SC_UPDATE_MARKS );
565 #endif
568 BOOL bNegX = ( nPosX < (SCsCOL) nStartX );
569 BOOL bNegY = ( nPosY < (SCsROW) nStartY );
571 long nSizeX = 0;
572 if ( bNegX )
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 );
580 else
581 for (SCCOL i=nEndX+1; i<=nPosX; i++)
582 nSizeX += pDoc->GetColWidth( i, nTab );
584 long nSizeY = 0;
585 if ( bNegY )
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))
593 nPosY = nStartY;
595 nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab );
597 else
598 nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab );
600 if ( nSizeX > nSizeY ) // Fill immer nur in einer Richtung
602 nPosY = nEndY;
603 bNegY = FALSE;
605 else
607 nPosX = nEndX;
608 bNegX = FALSE;
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()" );
628 ScRange aRange;
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 );
635 else
636 pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
637 CreateAnchor();
640 pView->UpdateRef( nPosX, nPosY, nTab );
642 else if ( nMode == SC_FILL_MATRIX )
644 SCCOL nStartX, nEndX;
645 SCROW nStartY, nEndY; // Block
646 SCTAB nDummy;
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 );
652 CreateAnchor();
655 if ( nPosX < nStartX ) nPosX = nStartX;
656 if ( nPosY < nStartY ) nPosY = nStartY;
658 pView->UpdateRef( nPosX, nPosY, nTab );
660 // else neue Modi
662 else // normales Markieren
664 BOOL bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() ||
665 (SCROW)nPosY != pViewData->GetCurY() );
666 if (bHideCur)
667 pView->HideAllCursors(); // sonst zweimal: Block und SetCursor
669 if (bAnchor)
671 if (!bStarted)
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 );
679 bStarted = TRUE;
682 if (bStarted)
683 // If the selection is already started, don't set the cursor.
684 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, FALSE, FALSE, TRUE );
685 else
686 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
688 else
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 );
698 bStarted = TRUE;
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 );
720 bStarted = TRUE;
722 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
725 pViewData->SetRefStart( nPosX, nPosY, nTab );
726 if (bHideCur)
727 pView->ShowAllCursors();
730 if (bHide)
731 pView->ShowAllCursors();
733 return TRUE;
736 BOOL __EXPORT ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
738 BOOL bRefMode = SC_MOD()->IsFormulaMode();
739 if (bRefMode)
740 return FALSE;
742 if (pViewData->IsAnyFillMode())
743 return FALSE;
745 ScMarkData& rMark = pViewData->GetMarkData();
746 if (bAnchor || !rMark.IsMultiMarked())
748 SCsCOL nPosX;
749 SCsROW nPosY;
750 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
751 return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY );
754 return FALSE;
757 void __EXPORT ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
759 // gibt's nicht
762 void __EXPORT ScViewFunctionSet::DeselectAll()
764 if (pViewData->IsAnyFillMode())
765 return;
767 BOOL bRefMode = SC_MOD()->IsFormulaMode();
768 if (bRefMode)
770 pViewData->GetView()->DoneRefMode( FALSE );
772 else
774 pViewData->GetView()->DoneBlockMode( FALSE );
775 pViewData->GetViewShell()->UpdateInputHandler();
778 bAnchor = FALSE;
781 //------------------------------------------------------------------------
783 ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView,
784 ScSplitPos eSplitPos ) :
785 SelectionEngine( pWindow, pView->GetFunctionSet() ),
786 eWhich( eSplitPos )
788 // Parameter einstellen
789 SetSelectionMode( MULTIPLE_SELECTION );
790 EnableDrag( TRUE );
794 //------------------------------------------------------------------------
797 // Spalten- / Zeilenheader
800 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) :
801 pViewData( pNewViewData ),
802 bColumn( FALSE ),
803 eWhich( SC_SPLIT_TOPLEFT ),
804 bAnchor( FALSE ),
805 nCursorPos( 0 )
807 DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet");
810 void ScHeaderFunctionSet::SetColumn( BOOL bSet )
812 bColumn = bSet;
815 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew )
817 eWhich = eNew;
820 void __EXPORT ScHeaderFunctionSet::BeginDrag()
822 // gippsnich
825 void __EXPORT ScHeaderFunctionSet::CreateAnchor()
827 if (bAnchor)
828 return;
830 ScTabView* pView = pViewData->GetView();
831 pView->DoneBlockMode( TRUE );
832 if (bColumn)
834 pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), TRUE, TRUE, FALSE );
835 pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() );
837 else
839 pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), TRUE, FALSE, TRUE );
840 pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() );
842 bAnchor = TRUE;
845 void __EXPORT ScHeaderFunctionSet::DestroyAnchor()
847 pViewData->GetView()->DoneBlockMode( TRUE );
848 bAnchor = FALSE;
851 BOOL __EXPORT ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, BOOL /* bDontSelectAtCursor */ )
853 if ( bDidSwitch )
855 // die naechste gueltige Position muss vom anderen Fenster kommen
856 if ( rPointPixel == aSwitchPos )
857 return FALSE; // nicht auf falschem Fenster scrollen
858 else
859 bDidSwitch = FALSE;
862 // Scrolling
864 Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel();
865 BOOL bScroll;
866 if (bColumn)
867 bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
868 else
869 bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
871 // ueber Fixier-Grenze bewegt?
873 BOOL bSwitched = FALSE;
874 if ( bColumn )
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;
887 else // Zeilenkoepfe
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;
900 if (bSwitched)
902 aSwitchPos = rPointPixel;
903 bDidSwitch = TRUE;
904 return FALSE; // nicht mit falschen Positionen rechnen
909 SCsCOL nPosX;
910 SCsROW nPosY;
911 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
912 nPosX, nPosY, FALSE );
913 if (bColumn)
915 nCursorPos = static_cast<SCCOLROW>(nPosX);
916 nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart()));
918 else
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;
927 if (bHide)
928 pView->HideAllCursors();
930 if (bScroll)
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 );
940 bAnchor = TRUE;
943 pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
945 // SelectionChanged innerhalb von HideCursor wegen UpdateAutoFillMark
946 pView->SelectionChanged();
948 if (bHide)
949 pView->ShowAllCursors();
951 return TRUE;
954 BOOL __EXPORT ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
956 SCsCOL nPosX;
957 SCsROW nPosY;
958 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
959 nPosX, nPosY, FALSE );
961 ScMarkData& rMark = pViewData->GetMarkData();
962 if (bColumn)
963 return rMark.IsColumnMarked( nPosX );
964 else
965 return rMark.IsRowMarked( nPosY );
968 void __EXPORT ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
972 void __EXPORT ScHeaderFunctionSet::DeselectAll()
974 pViewData->GetView()->DoneBlockMode( FALSE );
975 bAnchor = FALSE;
978 //------------------------------------------------------------------------
980 ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) :
981 SelectionEngine( pWindow, pFuncSet )
983 // Parameter einstellen
984 SetSelectionMode( MULTIPLE_SELECTION );
985 EnableDrag( FALSE );