blob: 4746c268123d44c99570c1963acb8728087408d3 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// INCLUDE ---------------------------------------------------------------
#include <tools/urlobj.hxx>
#include <vcl/sound.hxx>
#include <sfx2/docfile.hxx>
#include "select.hxx"
#include "sc.hrc"
#include "tabvwsh.hxx"
#include "scmod.hxx"
#include "document.hxx"
//#include "dataobj.hxx"
#include "transobj.hxx"
#include "docsh.hxx"
#include "tabprotection.hxx"
extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
using namespace com::sun::star;
// STATIC DATA -----------------------------------------------------------
static Point aSwitchPos; //! Member
static sal_Bool bDidSwitch = sal_False;
// -----------------------------------------------------------------------
//
// View (Gridwin / Tastatur)
//
ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) :
pViewData( pNewViewData ),
pEngine( NULL ),
bAnchor( sal_False ),
bStarted( sal_False )
{
DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet");
}
ScSplitPos ScViewFunctionSet::GetWhich()
{
if (pEngine)
return pEngine->GetWhich();
else
return pViewData->GetActivePart();
}
void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine )
{
pEngine = pSelEngine;
}
// Drag & Drop
void __EXPORT ScViewFunctionSet::BeginDrag()
{
SCTAB nTab = pViewData->GetTabNo();
SCsCOL nPosX;
SCsROW nPosY;
if (pEngine)
{
Point aMPos = pEngine->GetMousePosPixel();
pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
}
else
{
nPosX = pViewData->GetCurX();
nPosY = pViewData->GetCurY();
}
ScModule* pScMod = SC_MOD();
sal_Bool bRefMode = pScMod->IsFormulaMode();
if (!bRefMode)
{
pViewData->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp wird verschluckt
ScMarkData& rMark = pViewData->GetMarkData();
// rMark.SetMarking(sal_False); // es fehlt ein ButtonUp
rMark.MarkToSimple();
if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
{
ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
// bApi = sal_True -> no error mesages
sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, sal_False, sal_True );
if ( bCopied )
{
sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ?
( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) :
( DND_ACTION_COPY | DND_ACTION_LINK );
ScDocShell* pDocSh = pViewData->GetDocShell();
TransferableObjectDescriptor aObjDesc;
pDocSh->FillTransferableObjectDescriptor( aObjDesc );
aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
// maSize is set in ScTransferObj ctor
ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
// set position of dragged cell within range
ScRange aMarkRange = pTransferObj->GetRange();
SCCOL nStartX = aMarkRange.aStart.Col();
SCROW nStartY = aMarkRange.aStart.Row();
SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0;
SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0;
pTransferObj->SetDragHandlePos( nHandleX, nHandleY );
pTransferObj->SetVisibleTab( nTab );
pTransferObj->SetDragSource( pDocSh, rMark );
Window* pWindow = pViewData->GetActiveWin();
if ( pWindow->IsTracking() )
pWindow->EndTracking( ENDTRACK_CANCEL ); // abort selecting
SC_MOD()->SetDragObject( pTransferObj, NULL ); // for internal D&D
pTransferObj->StartDrag( pWindow, nDragActions );
return; // dragging started
}
else
delete pClipDoc;
}
}
Sound::Beep(); // can't drag
}
// Selektion
void __EXPORT ScViewFunctionSet::CreateAnchor()
{
if (bAnchor) return;
sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
if (bRefMode)
SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() );
else
SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() );
}
void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY )
{
sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
ScTabView* pView = pViewData->GetView();
SCTAB nTab = pViewData->GetTabNo();
if (bRefMode)
{
pView->DoneRefMode( sal_False );
aAnchorPos.Set( nPosX, nPosY, nTab );
pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(),
SC_REFTYPE_REF );
bStarted = sal_True;
}
else if (pViewData->IsAnyFillMode())
{
aAnchorPos.Set( nPosX, nPosY, nTab );
bStarted = sal_True;
}
else
{
// nicht weg und gleich wieder hin
if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
{
// nix
}
else
{
pView->DoneBlockMode( sal_True );
aAnchorPos.Set( nPosX, nPosY, nTab );
ScMarkData& rMark = pViewData->GetMarkData();
if ( rMark.IsMarked() || rMark.IsMultiMarked() )
{
pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
aAnchorPos.Tab(), sal_True );
bStarted = sal_True;
}
else
bStarted = sal_False;
}
}
bAnchor = sal_True;
}
void __EXPORT ScViewFunctionSet::DestroyAnchor()
{
sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
if (bRefMode)
pViewData->GetView()->DoneRefMode( sal_True );
else
pViewData->GetView()->DoneBlockMode( sal_True );
bAnchor = sal_False;
}
void ScViewFunctionSet::SetAnchorFlag( sal_Bool bSet )
{
bAnchor = bSet;
}
sal_Bool __EXPORT ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ )
{
if ( bDidSwitch )
{
if ( rPointPixel == aSwitchPos )
return sal_False; // nicht auf falschem Fenster scrollen
else
bDidSwitch = sal_False;
}
aSwitchPos = rPointPixel; // nur wichtig, wenn bDidSwitch
// treat position 0 as -1, so scrolling is always possible
// (with full screen and hidden headers, the top left border may be at 0)
// (moved from ScViewData::GetPosFromPixel)
Point aEffPos = rPointPixel;
if ( aEffPos.X() == 0 )
aEffPos.X() = -1;
if ( aEffPos.Y() == 0 )
aEffPos.Y() = -1;
// Scrolling
Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel();
sal_Bool bRightScroll = ( aEffPos.X() >= aWinSize.Width() );
sal_Bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() );
sal_Bool bNegScroll = ( aEffPos.X() < 0 || aEffPos.Y() < 0 );
sal_Bool bScroll = bRightScroll || bBottomScroll || bNegScroll;
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
nPosX, nPosY, sal_True, sal_True ); // mit Repair
// fuer AutoFill in der Mitte der Zelle umschalten
// dabei aber nicht das Scrolling nach rechts/unten verhindern
if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX )
{
sal_Bool bLeft, bTop;
pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
if ( bLeft && !bRightScroll )
do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) );
if ( bTop && !bBottomScroll )
{
if (--nPosY >= 0)
{
nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
if (!ValidRow(nPosY))
nPosY = -1;
}
}
// negativ ist erlaubt
}
// ueber Fixier-Grenze bewegt?
ScSplitPos eWhich = GetWhich();
if ( eWhich == pViewData->GetActivePart() )
{
if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
if ( aEffPos.X() >= aWinSize.Width() )
{
if ( eWhich == SC_SPLIT_TOPLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = sal_False, bDidSwitch = sal_True;
else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True;
}
if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
if ( aEffPos.Y() >= aWinSize.Height() )
{
if ( eWhich == SC_SPLIT_TOPLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = sal_False, bDidSwitch = sal_True;
else if ( eWhich == SC_SPLIT_TOPRIGHT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True;
}
}
pViewData->ResetOldCursor();
return SetCursorAtCell( nPosX, nPosY, bScroll );
}
sal_Bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, sal_Bool bScroll )
{
ScTabView* pView = pViewData->GetView();
SCTAB nTab = pViewData->GetTabNo();
ScDocument* pDoc = pViewData->GetDocument();
if ( pDoc->IsTabProtected(nTab) )
{
if (nPosX < 0 || nPosY < 0)
return false;
ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
if ( bSkipProtected && bSkipUnprotected )
return sal_False;
bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
// Don't select this cell!
return sal_False;
}
ScModule* pScMod = SC_MOD();
ScTabViewShell* pViewShell = pViewData->GetViewShell();
bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false );
sal_Bool bHide = !bRefMode && !pViewData->IsAnyFillMode() &&
( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() );
if (bHide)
pView->HideAllCursors();
if (bScroll)
{
if (bRefMode)
{
ScSplitPos eWhich = GetWhich();
pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
}
else
pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
}
if (bRefMode)
{
// #90910# if no input is possible from this doc, don't move the reference cursor around
if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) )
{
if (!bAnchor)
{
pView->DoneRefMode( sal_True );
pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF );
}
pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() );
pView->SelectionChanged();
}
}
else if (pViewData->IsFillMode() ||
(pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) ))
{
// Wenn eine Matrix angefasst wurde, kann mit Ctrl auf AutoFill zurueckgeschaltet werden
SCCOL nStartX, nEndX;
SCROW nStartY, nEndY; // Block
SCTAB nDummy;
pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
if (pViewData->GetRefType() != SC_REFTYPE_FILL)
{
pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
CreateAnchor();
}
ScRange aDelRange;
sal_Bool bOldDelMark = pViewData->GetDelMark( aDelRange );
if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
( nPosX != nEndX || nPosY != nEndY ) ) // verkleinern ?
{
// Richtung (links oder oben)
long nSizeX = 0;
for (SCCOL i=nPosX+1; i<=nEndX; i++)
nSizeX += pDoc->GetColWidth( i, nTab );
long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab );
SCCOL nDelStartX = nStartX;
SCROW nDelStartY = nStartY;
if ( nSizeX > nSizeY )
nDelStartX = nPosX + 1;
else
nDelStartY = nPosY + 1;
// 0 braucht nicht mehr getrennt abgefragt zu werden, weil nPosX/Y auch negativ wird
if ( nDelStartX < nStartX )
nDelStartX = nStartX;
if ( nDelStartY < nStartY )
nDelStartY = nStartY;
// Bereich setzen
pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
nEndX,nEndY,nTab ) );
pViewData->GetView()->UpdateShrinkOverlay();
#if 0
if ( bOldDelMark )
{
ScUpdateRect aRect( aDelRange.aStart.Col(), aDelRange.aStart.Row(),
aDelRange.aEnd.Col(), aDelRange.aEnd.Row() );
aRect.SetNew( nDelStartX,nDelStartY, nEndX,nEndY );
SCCOL nPaintStartX;
SCROW nPaintStartY;
SCCOL nPaintEndX;
SCROW nPaintEndY;
if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY ))
pViewData->GetView()->
PaintArea( nPaintStartX, nPaintStartY,
nPaintEndX, nPaintEndY, SC_UPDATE_MARKS );
}
else
#endif
pViewData->GetView()->
PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS );
nPosX = nEndX; // roten Rahmen um ganzen Bereich lassen
nPosY = nEndY;
// Referenz wieder richtigherum, falls unten umgedreht
if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() )
{
pViewData->GetView()->DoneRefMode();
pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
}
}
else
{
if ( bOldDelMark )
{
pViewData->ResetDelMark();
pViewData->GetView()->UpdateShrinkOverlay();
#if 0
pViewData->GetView()->
PaintArea( aDelRange.aStart.Col(), aDelRange.aStart.Row(),
aDelRange.aEnd.Col(), aDelRange.aEnd.Row(), SC_UPDATE_MARKS );
#endif
}
sal_Bool bNegX = ( nPosX < (SCsCOL) nStartX );
sal_Bool bNegY = ( nPosY < (SCsROW) nStartY );
long nSizeX = 0;
if ( bNegX )
{
// #94321# in SetCursorAtPoint hidden columns are skipped.
// They must be skipped here too, or the result will always be the first hidden column.
do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) );
for (SCCOL i=nPosX; i<nStartX; i++)
nSizeX += pDoc->GetColWidth( i, nTab );
}
else
for (SCCOL i=nEndX+1; i<=nPosX; i++)
nSizeX += pDoc->GetColWidth( i, nTab );
long nSizeY = 0;
if ( bNegY )
{
// #94321# in SetCursorAtPoint hidden rows are skipped.
// They must be skipped here too, or the result will always be the first hidden row.
if (++nPosY < nStartY)
{
nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab);
if (!ValidRow(nPosY))
nPosY = nStartY;
}
nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab );
}
else
nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab );
if ( nSizeX > nSizeY ) // Fill immer nur in einer Richtung
{
nPosY = nEndY;
bNegY = sal_False;
}
else
{
nPosX = nEndX;
bNegX = sal_False;
}
SCCOL nRefStX = bNegX ? nEndX : nStartX;
SCROW nRefStY = bNegY ? nEndY : nStartY;
if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() )
{
pViewData->GetView()->DoneRefMode();
pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
}
}
pView->UpdateRef( nPosX, nPosY, nTab );
}
else if (pViewData->IsAnyFillMode())
{
sal_uInt8 nMode = pViewData->GetFillMode();
if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
{
DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
ScRange aRange;
pDoc->GetEmbedded( aRange);
ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB;
if (pViewData->GetRefType() != eRefMode)
{
if ( nMode == SC_FILL_EMBED_LT )
pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
else
pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
CreateAnchor();
}
pView->UpdateRef( nPosX, nPosY, nTab );
}
else if ( nMode == SC_FILL_MATRIX )
{
SCCOL nStartX, nEndX;
SCROW nStartY, nEndY; // Block
SCTAB nDummy;
pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
if (pViewData->GetRefType() != SC_REFTYPE_FILL)
{
pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
CreateAnchor();
}
if ( nPosX < nStartX ) nPosX = nStartX;
if ( nPosY < nStartY ) nPosY = nStartY;
pView->UpdateRef( nPosX, nPosY, nTab );
}
// else neue Modi
}
else // normales Markieren
{
sal_Bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() ||
(SCROW)nPosY != pViewData->GetCurY() );
if (bHideCur)
pView->HideAllCursors(); // sonst zweimal: Block und SetCursor
if (bAnchor)
{
if (!bStarted)
{
sal_Bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() ||
nPosY != (SCsROW) aAnchorPos.Row() );
if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) )
{
pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
aAnchorPos.Tab(), sal_True );
bStarted = sal_True;
}
}
if (bStarted)
pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, sal_False, sal_False, sal_True );
}
else
{
ScMarkData& rMark = pViewData->GetMarkData();
if (rMark.IsMarked() || rMark.IsMultiMarked())
{
pView->DoneBlockMode(sal_True);
pView->InitBlockMode( nPosX, nPosY, nTab, sal_True );
pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
aAnchorPos.Set( nPosX, nPosY, nTab );
bStarted = sal_True;
}
// #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
// it highlights that new cell as well as the old cell where the cursor is
// positioned prior to the click. A selection mode via Shift-F8 should also
// follow the same behavior.
else if ( pViewData->IsSelCtrlMouseClick() )
{
SCCOL nOldX = pViewData->GetCurX();
SCROW nOldY = pViewData->GetCurY();
pView->InitBlockMode( nOldX, nOldY, nTab, sal_True );
pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab );
if ( nOldX != nPosX || nOldY != nPosY )
{
pView->DoneBlockMode( sal_True );
pView->InitBlockMode( nPosX, nPosY, nTab, sal_True );
pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
aAnchorPos.Set( nPosX, nPosY, nTab );
}
bStarted = sal_True;
}
}
pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
pViewData->SetRefStart( nPosX, nPosY, nTab );
if (bHideCur)
pView->ShowAllCursors();
}
if (bHide)
pView->ShowAllCursors();
return sal_True;
}
sal_Bool __EXPORT ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
{
sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
if (bRefMode)
return sal_False;
if (pViewData->IsAnyFillMode())
return sal_False;
ScMarkData& rMark = pViewData->GetMarkData();
if (bAnchor || !rMark.IsMultiMarked())
{
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY );
}
return sal_False;
}
void __EXPORT ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
{
// gibt's nicht
}
void __EXPORT ScViewFunctionSet::DeselectAll()
{
if (pViewData->IsAnyFillMode())
return;
sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
if (bRefMode)
{
pViewData->GetView()->DoneRefMode( sal_False );
}
else
{
pViewData->GetView()->DoneBlockMode( sal_False );
pViewData->GetViewShell()->UpdateInputHandler();
}
bAnchor = sal_False;
}
//------------------------------------------------------------------------
ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView,
ScSplitPos eSplitPos ) :
SelectionEngine( pWindow, pView->GetFunctionSet() ),
eWhich( eSplitPos )
{
// Parameter einstellen
SetSelectionMode( MULTIPLE_SELECTION );
EnableDrag( sal_True );
}
//------------------------------------------------------------------------
//
// Spalten- / Zeilenheader
//
ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) :
pViewData( pNewViewData ),
bColumn( sal_False ),
eWhich( SC_SPLIT_TOPLEFT ),
bAnchor( sal_False ),
nCursorPos( 0 )
{
DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet");
}
void ScHeaderFunctionSet::SetColumn( sal_Bool bSet )
{
bColumn = bSet;
}
void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew )
{
eWhich = eNew;
}
void __EXPORT ScHeaderFunctionSet::BeginDrag()
{
// gippsnich
}
void __EXPORT ScHeaderFunctionSet::CreateAnchor()
{
if (bAnchor)
return;
ScTabView* pView = pViewData->GetView();
pView->DoneBlockMode( sal_True );
if (bColumn)
{
pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), sal_True, sal_True, sal_False );
pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() );
}
else
{
pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), sal_True, sal_False, sal_True );
pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() );
}
bAnchor = sal_True;
}
void __EXPORT ScHeaderFunctionSet::DestroyAnchor()
{
pViewData->GetView()->DoneBlockMode( sal_True );
bAnchor = sal_False;
}
sal_Bool __EXPORT ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ )
{
if ( bDidSwitch )
{
// die naechste gueltige Position muss vom anderen Fenster kommen
if ( rPointPixel == aSwitchPos )
return sal_False; // nicht auf falschem Fenster scrollen
else
bDidSwitch = sal_False;
}
// Scrolling
Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel();
sal_Bool bScroll;
if (bColumn)
bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
else
bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
// ueber Fixier-Grenze bewegt?
sal_Bool bSwitched = sal_False;
if ( bColumn )
{
if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
{
if ( rPointPixel.X() > aWinSize.Width() )
{
if ( eWhich == SC_SPLIT_TOPLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = sal_True;
else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True;
}
}
}
else // Zeilenkoepfe
{
if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
{
if ( rPointPixel.Y() > aWinSize.Height() )
{
if ( eWhich == SC_SPLIT_TOPLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = sal_True;
else if ( eWhich == SC_SPLIT_TOPRIGHT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True;
}
}
}
if (bSwitched)
{
aSwitchPos = rPointPixel;
bDidSwitch = sal_True;
return sal_False; // nicht mit falschen Positionen rechnen
}
//
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
nPosX, nPosY, sal_False );
if (bColumn)
{
nCursorPos = static_cast<SCCOLROW>(nPosX);
nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart()));
}
else
{
nCursorPos = static_cast<SCCOLROW>(nPosY);
nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart()));
}
ScTabView* pView = pViewData->GetView();
sal_Bool bHide = pViewData->GetCurX() != nPosX ||
pViewData->GetCurY() != nPosY;
if (bHide)
pView->HideAllCursors();
if (bScroll)
pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
pView->SetCursor( nPosX, nPosY );
if ( !bAnchor || !pView->IsBlockMode() )
{
pView->DoneBlockMode( sal_True );
pViewData->GetMarkData().MarkToMulti(); //! wer verstellt das ???
pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), sal_True, bColumn, !bColumn );
bAnchor = sal_True;
}
pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
// SelectionChanged innerhalb von HideCursor wegen UpdateAutoFillMark
pView->SelectionChanged();
if (bHide)
pView->ShowAllCursors();
return sal_True;
}
sal_Bool __EXPORT ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
{
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
nPosX, nPosY, sal_False );
ScMarkData& rMark = pViewData->GetMarkData();
if (bColumn)
return rMark.IsColumnMarked( nPosX );
else
return rMark.IsRowMarked( nPosY );
}
void __EXPORT ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
{
}
void __EXPORT ScHeaderFunctionSet::DeselectAll()
{
pViewData->GetView()->DoneBlockMode( sal_False );
bAnchor = sal_False;
}
//------------------------------------------------------------------------
ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) :
SelectionEngine( pWindow, pFuncSet )
{
// Parameter einstellen
SetSelectionMode( MULTIPLE_SELECTION );
EnableDrag( sal_False );
}