blob: 8685ccb3cafbd28398ccdd510a3bbc6eb3699922 [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 "scitems.hxx"
#include <vcl/virdev.hxx>
#include <vcl/waitobj.hxx>
#include <editeng/boxitem.hxx>
#include <sfx2/app.hxx>
#include "undoblk.hxx"
#include "undoutil.hxx"
#include "document.hxx"
#include "patattr.hxx"
#include "docsh.hxx"
#include "tabvwsh.hxx"
#include "rangenam.hxx"
#include "rangeutl.hxx"
#include "dbcolect.hxx"
#include "stlpool.hxx"
#include "stlsheet.hxx"
#include "globstr.hrc"
#include "global.hxx"
#include "target.hxx"
#include "docpool.hxx"
#include "docfunc.hxx"
#include "attrib.hxx"
#include "chgtrack.hxx"
#include "transobj.hxx"
#include "refundo.hxx"
#include "undoolk.hxx"
#include "clipparam.hxx"
#include "sc.hrc"
// STATIC DATA -----------------------------------------------------------
TYPEINIT1(ScUndoInsertCells, SfxUndoAction);
TYPEINIT1(ScUndoDeleteCells, SfxUndoAction);
TYPEINIT1(ScUndoDeleteMulti, SfxUndoAction);
TYPEINIT1(ScUndoCut, ScBlockUndo);
TYPEINIT1(ScUndoPaste, SfxUndoAction);
TYPEINIT1(ScUndoDragDrop, SfxUndoAction);
TYPEINIT1(ScUndoListNames, SfxUndoAction);
TYPEINIT1(ScUndoUseScenario, SfxUndoAction);
TYPEINIT1(ScUndoSelectionStyle, SfxUndoAction);
TYPEINIT1(ScUndoEnterMatrix, ScBlockUndo);
TYPEINIT1(ScUndoIndent, ScBlockUndo);
TYPEINIT1(ScUndoTransliterate, ScBlockUndo);
TYPEINIT1(ScUndoClearItems, ScBlockUndo);
TYPEINIT1(ScUndoRemoveBreaks, SfxUndoAction);
TYPEINIT1(ScUndoRemoveMerge, ScBlockUndo);
TYPEINIT1(ScUndoBorder, ScBlockUndo);
// To Do:
/*A*/ // SetOptimalHeight auf Dokument, wenn keine View
/*B*/ // gelinkte Tabellen
/*C*/ // ScArea
//? // spaeter mal pruefen
// -----------------------------------------------------------------------
//
// Zellen einfuegen
// Zeilen einfuegen
// einzeln oder Block
//
ScUndoInsertCells::ScUndoInsertCells( ScDocShell* pNewDocShell,
const ScRange& rRange, SCTAB nNewCount, SCTAB* pNewTabs, SCTAB* pNewScenarios,
InsCellCmd eNewCmd, ScDocument* pUndoDocument, ScRefUndoData* pRefData,
sal_Bool bNewPartOfPaste ) :
ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ),
aEffRange( rRange ),
nCount( nNewCount ),
pTabs( pNewTabs ),
pScenarios( pNewScenarios ),
eCmd( eNewCmd ),
bPartOfPaste( bNewPartOfPaste ),
pPasteUndo( NULL )
{
if (eCmd == INS_INSROWS) // ganze Zeilen?
{
aEffRange.aStart.SetCol(0);
aEffRange.aEnd.SetCol(MAXCOL);
}
if (eCmd == INS_INSCOLS) // ganze Spalten?
{
aEffRange.aStart.SetRow(0);
aEffRange.aEnd.SetRow(MAXROW);
}
SetChangeTrack();
}
__EXPORT ScUndoInsertCells::~ScUndoInsertCells()
{
delete pPasteUndo;
delete []pTabs;
delete []pScenarios;
}
String __EXPORT ScUndoInsertCells::GetComment() const
{
return ScGlobal::GetRscString( pPasteUndo ? STR_UNDO_PASTE : STR_UNDO_INSERTCELLS );
}
sal_Bool ScUndoInsertCells::Merge( SfxUndoAction* pNextAction )
{
// If a paste undo action has already been added, append (detective) action there.
if ( pPasteUndo )
return pPasteUndo->Merge( pNextAction );
if ( bPartOfPaste && pNextAction->ISA( ScUndoWrapper ) )
{
ScUndoWrapper* pWrapper = (ScUndoWrapper*)pNextAction;
SfxUndoAction* pWrappedAction = pWrapper->GetWrappedUndo();
if ( pWrappedAction && pWrappedAction->ISA( ScUndoPaste ) )
{
// Store paste action if this is part of paste with inserting cells.
// A list action isn't used because Repeat wouldn't work (insert wrong cells).
pPasteUndo = pWrappedAction;
pWrapper->ForgetWrappedUndo(); // pWrapper is deleted by UndoManager
return sal_True;
}
}
// Call base class for detective handling
return ScMoveUndo::Merge( pNextAction );
}
void ScUndoInsertCells::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
if ( pChangeTrack )
{
pChangeTrack->AppendInsert( aEffRange );
nEndChangeAction = pChangeTrack->GetActionMax();
}
else
nEndChangeAction = 0;
}
void ScUndoInsertCells::DoChange( const sal_Bool bUndo )
{
ScDocument* pDoc = pDocShell->GetDocument();
SCTAB i;
if ( bUndo )
{
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
}
else
SetChangeTrack();
// refresh of merged cells has to be after inserting/deleting
switch (eCmd)
{
case INS_INSROWS:
case INS_CELLSDOWN:
for( i=0; i<nCount; i++ )
{
if (bUndo)
pDoc->DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
else
pDoc->InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
}
break;
case INS_INSCOLS:
case INS_CELLSRIGHT:
for( i=0; i<nCount; i++ )
{
if (bUndo)
pDoc->DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
else
pDoc->InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
}
break;
default:
{
// added to avoid warnings
}
}
ScRange aWorkRange( aEffRange );
if ( eCmd == INS_CELLSRIGHT ) // only "shift right" requires refresh of the moved area
aWorkRange.aEnd.SetCol(MAXCOL);
for( i=0; i<nCount; i++ )
{
if ( pDoc->HasAttrib( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i], HASATTR_MERGED ) )
{
SCCOL nEndCol = aWorkRange.aEnd.Col();
SCROW nEndRow = aWorkRange.aEnd.Row();
pDoc->ExtendMerge( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), nEndCol, nEndRow, pTabs[i], sal_True );
}
}
//? Undo fuer herausgeschobene Attribute ?
sal_uInt16 nPaint = PAINT_GRID;
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
switch (eCmd)
{
case INS_INSROWS:
nPaint |= PAINT_LEFT;
aWorkRange.aEnd.SetRow(MAXROW);
break;
case INS_CELLSDOWN:
for( i=0; i<nCount; i++ )
{
aWorkRange.aEnd.SetRow(MAXROW);
if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ))
{
aWorkRange.aStart.SetCol(0);
aWorkRange.aEnd.SetCol(MAXCOL);
nPaint |= PAINT_LEFT;
}
}
break;
case INS_INSCOLS:
nPaint |= PAINT_TOP; // obere Leiste
case INS_CELLSRIGHT:
for( i=0; i<nCount; i++ )
{
aWorkRange.aEnd.SetCol(MAXCOL); // bis ganz nach rechts
if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i]) )
{ // AdjustDraw zeichnet PAINT_TOP nicht,
aWorkRange.aStart.SetCol(0); // daher so geloest
aWorkRange.aEnd.SetRow(MAXROW);
nPaint |= PAINT_LEFT;
}
}
break;
default:
{
// added to avoid warnings
}
}
for( i=0; i<nCount; i++ )
{
pDocShell->PostPaint( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i]+pScenarios[i], nPaint );
}
pDocShell->PostDataChanged();
if (pViewShell)
pViewShell->CellContentChanged();
}
void __EXPORT ScUndoInsertCells::Undo()
{
if ( pPasteUndo )
pPasteUndo->Undo(); // undo paste first
WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
BeginUndo();
DoChange( sal_True );
EndUndo();
}
void __EXPORT ScUndoInsertCells::Redo()
{
WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
BeginRedo();
DoChange( sal_False );
EndRedo();
if ( pPasteUndo )
pPasteUndo->Redo(); // redo paste last
}
void __EXPORT ScUndoInsertCells::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
if ( pPasteUndo )
{
// #94115# Repeat for paste with inserting cells is handled completely
// by the Paste undo action
pPasteUndo->Repeat( rTarget );
}
else
((ScTabViewTarget&)rTarget).GetViewShell()->InsertCells( eCmd, sal_True );
}
}
sal_Bool __EXPORT ScUndoInsertCells::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Zellen loeschen
// Zeilen loeschen
// einzeln oder Block
//
ScUndoDeleteCells::ScUndoDeleteCells( ScDocShell* pNewDocShell,
const ScRange& rRange, SCTAB nNewCount, SCTAB* pNewTabs, SCTAB* pNewScenarios,
DelCellCmd eNewCmd, ScDocument* pUndoDocument, ScRefUndoData* pRefData ) :
ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ),
aEffRange( rRange ),
nCount( nNewCount ),
pTabs( pNewTabs ),
pScenarios( pNewScenarios ),
eCmd( eNewCmd )
{
if (eCmd == DEL_DELROWS) // gaze Zeilen?
{
aEffRange.aStart.SetCol(0);
aEffRange.aEnd.SetCol(MAXCOL);
}
if (eCmd == DEL_DELCOLS) // ganze Spalten?
{
aEffRange.aStart.SetRow(0);
aEffRange.aEnd.SetRow(MAXROW);
}
SetChangeTrack();
}
__EXPORT ScUndoDeleteCells::~ScUndoDeleteCells()
{
delete []pTabs;
delete []pScenarios;
}
String __EXPORT ScUndoDeleteCells::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); // "Loeschen"
}
void ScUndoDeleteCells::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->AppendDeleteRange( aEffRange, pRefUndoDoc,
nStartChangeAction, nEndChangeAction );
else
nStartChangeAction = nEndChangeAction = 0;
}
void ScUndoDeleteCells::DoChange( const sal_Bool bUndo )
{
ScDocument* pDoc = pDocShell->GetDocument();
SCTAB i;
if ( bUndo )
{
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
}
else
SetChangeTrack();
// Ausfuehren
switch (eCmd)
{
case DEL_DELROWS:
case DEL_CELLSUP:
for( i=0; i<nCount; i++ )
{
if (bUndo)
pDoc->InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
else
pDoc->DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
}
break;
case DEL_DELCOLS:
case DEL_CELLSLEFT:
for( i=0; i<nCount; i++ )
{
if (bUndo)
pDoc->InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
else
pDoc->DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
}
break;
default:
{
// added to avoid warnings
}
}
// bei Undo Referenzen wiederherstellen
for( i=0; i<nCount && bUndo; i++ )
{
pRefUndoDoc->CopyToDocument( aEffRange.aStart.Col(), aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Col(), aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
IDF_ALL | IDF_NOCAPTIONS, sal_False, pDoc );
}
ScRange aWorkRange( aEffRange );
if ( eCmd == DEL_CELLSLEFT ) // only "shift left" requires refresh of the moved area
aWorkRange.aEnd.SetCol(MAXCOL);
for( i=0; i<nCount; i++ )
{
if ( pDoc->HasAttrib( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i], HASATTR_MERGED | HASATTR_OVERLAPPED ) )
{
// #i51445# old merge flag attributes must be deleted also for single cells,
// not only for whole columns/rows
if ( !bUndo )
{
if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
aWorkRange.aEnd.SetCol(MAXCOL);
if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
aWorkRange.aEnd.SetRow(MAXROW);
ScMarkData aMarkData;
aMarkData.SelectOneTable( aWorkRange.aStart.Tab() );
ScPatternAttr aPattern( pDoc->GetPool() );
aPattern.GetItemSet().Put( ScMergeFlagAttr() );
pDoc->ApplyPatternArea( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(),
aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(),
aMarkData, aPattern );
}
SCCOL nEndCol = aWorkRange.aEnd.Col();
SCROW nEndRow = aWorkRange.aEnd.Row();
pDoc->ExtendMerge( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), nEndCol, nEndRow, pTabs[i], sal_True );
}
}
// Zeichnen
sal_uInt16 nPaint = PAINT_GRID;
switch (eCmd)
{
case DEL_DELROWS:
nPaint |= PAINT_LEFT;
aWorkRange.aEnd.SetRow(MAXROW);
break;
case DEL_CELLSUP:
for( i=0; i<nCount; i++ )
{
aWorkRange.aEnd.SetRow(MAXROW);
if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ))
{
aWorkRange.aStart.SetCol(0);
aWorkRange.aEnd.SetCol(MAXCOL);
nPaint |= PAINT_LEFT;
}
}
break;
case DEL_DELCOLS:
nPaint |= PAINT_TOP; // obere Leiste
case DEL_CELLSLEFT:
for( i=0; i<nCount; i++ )
{
aWorkRange.aEnd.SetCol(MAXCOL); // bis ganz nach rechts
if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ) )
{
aWorkRange.aStart.SetCol(0);
aWorkRange.aEnd.SetRow(MAXROW);
nPaint |= PAINT_LEFT;
}
}
break;
default:
{
// added to avoid warnings
}
}
for( i=0; i<nCount; i++ )
{
pDocShell->PostPaint( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i]+pScenarios[i], nPaint, SC_PF_LINES );
}
// Markierung erst nach EndUndo
pDocShell->PostDataChanged();
// CellContentChanged kommt mit der Markierung
}
void __EXPORT ScUndoDeleteCells::Undo()
{
WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
BeginUndo();
DoChange( sal_True );
EndUndo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
// Markierung erst nach EndUndo
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
for( SCTAB i=0; i<nCount; i++ )
{
pViewShell->MarkRange( ScRange(aEffRange.aStart.Col(), aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Col(), aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i]) );
}
}
}
void __EXPORT ScUndoDeleteCells::Redo()
{
WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
BeginRedo();
DoChange( sal_False);
EndRedo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
pViewShell->DoneBlockMode(); // aktuelle weg
}
void __EXPORT ScUndoDeleteCells::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->DeleteCells( eCmd, sal_True );
}
sal_Bool __EXPORT ScUndoDeleteCells::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Zellen loeschen auf Mehrfachselektion
//
ScUndoDeleteMulti::ScUndoDeleteMulti( ScDocShell* pNewDocShell,
sal_Bool bNewRows, sal_Bool bNeedsRefresh, SCTAB nNewTab,
const SCCOLROW* pRng, SCCOLROW nRngCnt,
ScDocument* pUndoDocument, ScRefUndoData* pRefData ) :
ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ),
bRows( bNewRows ),
bRefresh( bNeedsRefresh ),
nTab( nNewTab ),
nRangeCnt( nRngCnt )
{
pRanges = new SCCOLROW[ 2 * nRangeCnt ];
memcpy(pRanges,pRng,nRangeCnt*2*sizeof(SCCOLROW));
SetChangeTrack();
}
__EXPORT ScUndoDeleteMulti::~ScUndoDeleteMulti()
{
delete [] pRanges;
}
String __EXPORT ScUndoDeleteMulti::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); // wie DeleteCells
}
void ScUndoDeleteMulti::DoChange() const
{
SCCOL nStartCol;
SCROW nStartRow;
sal_uInt16 nPaint;
if (bRows)
{
nStartCol = 0;
nStartRow = static_cast<SCROW>(pRanges[0]);
nPaint = PAINT_GRID | PAINT_LEFT;
}
else
{
nStartCol = static_cast<SCCOL>(pRanges[0]);
nStartRow = 0;
nPaint = PAINT_GRID | PAINT_TOP;
}
if ( bRefresh )
{
ScDocument* pDoc = pDocShell->GetDocument();
SCCOL nEndCol = MAXCOL;
SCROW nEndRow = MAXROW;
pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, sal_True );
}
pDocShell->PostPaint( nStartCol, nStartRow, nTab, MAXCOL, MAXROW, nTab, nPaint );
pDocShell->PostDataChanged();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
pViewShell->CellContentChanged();
ShowTable( nTab );
}
void ScUndoDeleteMulti::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
if ( pChangeTrack )
{
nStartChangeAction = pChangeTrack->GetActionMax() + 1;
ScRange aRange( 0, 0, nTab, 0, 0, nTab );
if ( bRows )
aRange.aEnd.SetCol( MAXCOL );
else
aRange.aEnd.SetRow( MAXROW );
// rueckwaerts loeschen
SCCOLROW* pOneRange = &pRanges[2*nRangeCnt];
for ( SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++ )
{
SCCOLROW nEnd = *(--pOneRange);
SCCOLROW nStart = *(--pOneRange);
if ( bRows )
{
aRange.aStart.SetRow( nStart );
aRange.aEnd.SetRow( nEnd );
}
else
{
aRange.aStart.SetCol( static_cast<SCCOL>(nStart) );
aRange.aEnd.SetCol( static_cast<SCCOL>(nEnd) );
}
sal_uLong nDummyStart;
pChangeTrack->AppendDeleteRange( aRange, pRefUndoDoc,
nDummyStart, nEndChangeAction );
}
}
else
nStartChangeAction = nEndChangeAction = 0;
}
void __EXPORT ScUndoDeleteMulti::Undo()
{
WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
SCCOLROW* pOneRange;
SCCOLROW nRangeNo;
// rueckwaerts geloescht -> vorwaerts einfuegen
pOneRange = pRanges;
for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
{
SCCOLROW nStart = *(pOneRange++);
SCCOLROW nEnd = *(pOneRange++);
if (bRows)
pDoc->InsertRow( 0,nTab, MAXCOL,nTab, nStart,static_cast<SCSIZE>(nEnd-nStart+1) );
else
pDoc->InsertCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
}
pOneRange = pRanges;
for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
{
SCCOLROW nStart = *(pOneRange++);
SCCOLROW nEnd = *(pOneRange++);
if (bRows)
pRefUndoDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pDoc );
else
pRefUndoDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
static_cast<SCCOL>(nEnd),MAXROW,nTab, IDF_ALL,sal_False,pDoc );
}
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
DoChange();
//! Markierung wieder einzeichnen
//! geht im Moment nicht, da keine Daten fuer Markierung vorhanden!
EndUndo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}
void __EXPORT ScUndoDeleteMulti::Redo()
{
WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
// rueckwaerts loeschen
SCCOLROW* pOneRange = &pRanges[2*nRangeCnt];
for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
{
SCCOLROW nEnd = *(--pOneRange);
SCCOLROW nStart = *(--pOneRange);
if (bRows)
pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart,static_cast<SCSIZE>(nEnd-nStart+1) );
else
pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
}
SetChangeTrack();
DoChange();
//! Markierung loeschen, derzeit unnoetig (s.o.)
//! ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
//! if (pViewShell)
//! DoneBlockMode();
EndRedo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}
void __EXPORT ScUndoDeleteMulti::Repeat(SfxRepeatTarget& rTarget)
{
// DeleteCells, falls einfache Selektion
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->DeleteCells( DEL_DELROWS, sal_True );
}
sal_Bool __EXPORT ScUndoDeleteMulti::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Ausschneiden (Cut)
//
ScUndoCut::ScUndoCut( ScDocShell* pNewDocShell,
ScRange aRange, ScAddress aOldEnd, const ScMarkData& rMark,
ScDocument* pNewUndoDoc ) :
ScBlockUndo( pNewDocShell, ScRange(aRange.aStart, aOldEnd), SC_UNDO_AUTOHEIGHT ),
aMarkData( rMark ),
pUndoDoc( pNewUndoDoc ),
aExtendedRange( aRange )
{
SetChangeTrack();
}
__EXPORT ScUndoCut::~ScUndoCut()
{
delete pUndoDoc;
}
String __EXPORT ScUndoCut::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_CUT ); // "Ausschneiden"
}
void ScUndoCut::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
nStartChangeAction, nEndChangeAction, SC_CACM_CUT );
else
nStartChangeAction = nEndChangeAction = 0;
}
void ScUndoCut::DoChange( const sal_Bool bUndo )
{
ScDocument* pDoc = pDocShell->GetDocument();
sal_uInt16 nExtFlags = 0;
// do not undo/redo objects and note captions, they are handled via drawing undo
sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
if (bUndo) // nur bei Undo
{
// all sheets - CopyToDocument skips those that don't exist in pUndoDoc
SCTAB nTabCount = pDoc->GetTableCount();
ScRange aCopyRange = aExtendedRange;
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
pUndoDoc->CopyToDocument( aCopyRange, nUndoFlags, sal_False, pDoc );
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
}
else // nur bei Redo
{
pDocShell->UpdatePaintExt( nExtFlags, aExtendedRange );
pDoc->DeleteArea( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), aMarkData, nUndoFlags );
SetChangeTrack();
}
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) )
/*A*/ pDocShell->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
if ( !bUndo ) // draw redo after updating row heights
RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo?
pDocShell->PostDataChanged();
if (pViewShell)
pViewShell->CellContentChanged();
}
void __EXPORT ScUndoCut::Undo()
{
BeginUndo();
DoChange( sal_True );
EndUndo();
}
void __EXPORT ScUndoCut::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
EnableDrawAdjust( pDoc, sal_False ); //! include in ScBlockUndo?
DoChange( sal_False );
EnableDrawAdjust( pDoc, sal_True ); //! include in ScBlockUndo?
EndRedo();
}
void __EXPORT ScUndoCut::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->CutToClip( NULL, sal_True );
}
sal_Bool __EXPORT ScUndoCut::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Einfuegen (Paste)
//
ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell,
SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
const ScMarkData& rMark,
ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
sal_uInt16 nNewFlags,
ScRefUndoData* pRefData,
void* /* pFill1 */, void* /* pFill2 */, void* /* pFill3 */,
sal_Bool bRedoIsFilled, const ScUndoPasteOptions* pOptions ) :
ScBlockUndo( pNewDocShell, ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), SC_UNDO_SIMPLE ),
aMarkData( rMark ),
pUndoDoc( pNewUndoDoc ),
pRedoDoc( pNewRedoDoc ),
nFlags( nNewFlags ),
pRefUndoData( pRefData ),
pRefRedoData( NULL ),
bRedoFilled( bRedoIsFilled )
{
// pFill1,pFill2,pFill3 are there so the ctor calls for simple paste (without cutting)
// don't have to be changed and branched for 641.
// They can be removed later.
if ( !aMarkData.IsMarked() ) // no cell marked:
aMarkData.SetMarkArea( aBlockRange ); // mark paste block
if ( pRefUndoData )
pRefUndoData->DeleteUnchanged( pDocShell->GetDocument() );
if ( pOptions )
aPasteOptions = *pOptions; // used only for Repeat
SetChangeTrack();
}
__EXPORT ScUndoPaste::~ScUndoPaste()
{
delete pUndoDoc;
delete pRedoDoc;
delete pRefUndoData;
delete pRefRedoData;
}
String __EXPORT ScUndoPaste::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_PASTE ); // "Einfuegen"
}
void ScUndoPaste::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
if ( pChangeTrack && (nFlags & IDF_CONTENTS) )
pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
nStartChangeAction, nEndChangeAction, SC_CACM_PASTE );
else
nStartChangeAction = nEndChangeAction = 0;
}
void ScUndoPaste::DoChange( const sal_Bool bUndo )
{
ScDocument* pDoc = pDocShell->GetDocument();
// RefUndoData for redo is created before first undo
// (with DeleteUnchanged after the DoUndo call)
sal_Bool bCreateRedoData = ( bUndo && pRefUndoData && !pRefRedoData );
if ( bCreateRedoData )
pRefRedoData = new ScRefUndoData( pDoc );
ScRefUndoData* pWorkRefData = bUndo ? pRefUndoData : pRefRedoData;
// fuer Undo immer alle oder keine Inhalte sichern
sal_uInt16 nUndoFlags = IDF_NONE;
if (nFlags & IDF_CONTENTS)
nUndoFlags |= IDF_CONTENTS;
if (nFlags & IDF_ATTRIB)
nUndoFlags |= IDF_ATTRIB;
// do not undo/redo objects and note captions, they are handled via drawing undo
(nUndoFlags &= ~IDF_OBJECTS) |= IDF_NOCAPTIONS;
sal_Bool bPaintAll = sal_False;
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
// marking is in ScBlockUndo...
ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockRange );
SCTAB nTabCount = pDoc->GetTableCount();
if ( bUndo && !bRedoFilled )
{
if (!pRedoDoc)
{
sal_Bool bColInfo = ( aBlockRange.aStart.Row()==0 && aBlockRange.aEnd.Row()==MAXROW );
sal_Bool bRowInfo = ( aBlockRange.aStart.Col()==0 && aBlockRange.aEnd.Col()==MAXCOL );
pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
pRedoDoc->InitUndoSelected( pDoc, aMarkData, bColInfo, bRowInfo );
}
// read "redo" data from the document in the first undo
// all sheets - CopyToDocument skips those that don't exist in pRedoDoc
ScRange aCopyRange = aBlockRange;
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
pDoc->CopyToDocument( aCopyRange, nUndoFlags, sal_False, pRedoDoc );
bRedoFilled = sal_True;
}
sal_uInt16 nExtFlags = 0;
pDocShell->UpdatePaintExt( nExtFlags, aBlockRange );
aMarkData.MarkToMulti();
pDoc->DeleteSelection( nUndoFlags, aMarkData );
aMarkData.MarkToSimple();
SCTAB nFirstSelected = aMarkData.GetFirstSelected();
ScRange aTabSelectRange = aBlockRange;
SCTAB nTab;
if ( !bUndo && pRedoDoc ) // Redo: UndoToDocument before handling RefData
{
aTabSelectRange.aStart.SetTab( nFirstSelected );
aTabSelectRange.aEnd.SetTab( nFirstSelected );
pRedoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
for (nTab=0; nTab<nTabCount; nTab++)
if (nTab != nFirstSelected && aMarkData.GetTableSelect(nTab))
{
aTabSelectRange.aStart.SetTab( nTab );
aTabSelectRange.aEnd.SetTab( nTab );
pRedoDoc->CopyToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
}
}
if (pWorkRefData)
{
pWorkRefData->DoUndo( pDoc, sal_True ); // sal_True = bSetChartRangeLists for SetChartListenerCollection
if ( pDoc->RefreshAutoFilter( 0,0, MAXCOL,MAXROW, aBlockRange.aStart.Tab() ) )
bPaintAll = sal_True;
}
if ( bCreateRedoData && pRefRedoData )
pRefRedoData->DeleteUnchanged( pDoc );
if (bUndo) // Undo: UndoToDocument after handling RefData
{
aTabSelectRange.aStart.SetTab( nFirstSelected );
aTabSelectRange.aEnd.SetTab( nFirstSelected );
pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
for (nTab=0; nTab<nTabCount; nTab++)
if (nTab != nFirstSelected && aMarkData.GetTableSelect(nTab))
{
aTabSelectRange.aStart.SetTab( nTab );
aTabSelectRange.aEnd.SetTab( nTab );
pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
}
}
if ( bUndo )
{
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
}
else
SetChangeTrack();
ScRange aDrawRange( aBlockRange );
pDoc->ExtendMerge( aDrawRange, sal_True ); // only needed for single sheet (text/rtf etc.)
sal_uInt16 nPaint = PAINT_GRID;
if (bPaintAll)
{
aDrawRange.aStart.SetCol(0);
aDrawRange.aStart.SetRow(0);
aDrawRange.aEnd.SetCol(MAXCOL);
aDrawRange.aEnd.SetRow(MAXROW);
nPaint |= PAINT_TOP | PAINT_LEFT;
/*A*/ if (pViewShell)
pViewShell->AdjustBlockHeight(sal_False);
}
else
{
if ( aBlockRange.aStart.Row() == 0 && aBlockRange.aEnd.Row() == MAXROW ) // ganze Spalte
{
nPaint |= PAINT_TOP;
aDrawRange.aEnd.SetCol(MAXCOL);
}
if ( aBlockRange.aStart.Col() == 0 && aBlockRange.aEnd.Col() == MAXCOL ) // ganze Zeile
{
nPaint |= PAINT_LEFT;
aDrawRange.aEnd.SetRow(MAXROW);
}
/*A*/ if ((pViewShell) && pViewShell->AdjustBlockHeight(sal_False))
{
aDrawRange.aStart.SetCol(0);
aDrawRange.aStart.SetRow(0);
aDrawRange.aEnd.SetCol(MAXCOL);
aDrawRange.aEnd.SetRow(MAXROW);
nPaint |= PAINT_LEFT;
}
pDocShell->UpdatePaintExt( nExtFlags, aDrawRange );
}
if ( !bUndo ) // draw redo after updating row heights
RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo?
pDocShell->PostPaint( aDrawRange, nPaint, nExtFlags );
pDocShell->PostDataChanged();
if (pViewShell)
pViewShell->CellContentChanged();
}
void __EXPORT ScUndoPaste::Undo()
{
BeginUndo();
DoChange( sal_True );
ShowTable( aBlockRange );
EndUndo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}
void __EXPORT ScUndoPaste::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
EnableDrawAdjust( pDoc, sal_False ); //! include in ScBlockUndo?
DoChange( sal_False );
EnableDrawAdjust( pDoc, sal_True ); //! include in ScBlockUndo?
EndRedo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}
void __EXPORT ScUndoPaste::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
ScTabViewShell* pViewSh = ((ScTabViewTarget&)rTarget).GetViewShell();
ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pViewSh->GetActiveWin() );
if (pOwnClip)
{
// #129384# keep a reference in case the clipboard is changed during PasteFromClip
com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> aOwnClipRef( pOwnClip );
pViewSh->PasteFromClip( nFlags, pOwnClip->GetDocument(),
aPasteOptions.nFunction, aPasteOptions.bSkipEmpty, aPasteOptions.bTranspose,
aPasteOptions.bAsLink, aPasteOptions.eMoveMode, IDF_NONE,
sal_True ); // allow warning dialog
}
}
}
sal_Bool __EXPORT ScUndoPaste::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Verschieben/Kopieren (Drag & Drop)
//
ScUndoDragDrop::ScUndoDragDrop( ScDocShell* pNewDocShell,
const ScRange& rRange, ScAddress aNewDestPos, sal_Bool bNewCut,
ScDocument* pUndoDocument, ScRefUndoData* pRefData, sal_Bool bScenario ) :
ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFFIRST ),
aSrcRange( rRange ),
bCut( bNewCut ),
bKeepScenarioFlags( bScenario )
{
ScAddress aDestEnd(aNewDestPos);
aDestEnd.IncRow(aSrcRange.aEnd.Row() - aSrcRange.aStart.Row());
aDestEnd.IncCol(aSrcRange.aEnd.Col() - aSrcRange.aStart.Col());
aDestEnd.IncTab(aSrcRange.aEnd.Tab() - aSrcRange.aStart.Tab());
sal_Bool bIncludeFiltered = bCut;
if ( !bIncludeFiltered )
{
// find number of non-filtered rows
SCROW nPastedCount = pDocShell->GetDocument()->CountNonFilteredRows(
aSrcRange.aStart.Row(), aSrcRange.aEnd.Row(), aSrcRange.aStart.Tab());
if ( nPastedCount == 0 )
nPastedCount = 1;
aDestEnd.SetRow( aNewDestPos.Row() + nPastedCount - 1 );
}
aDestRange.aStart = aNewDestPos;
aDestRange.aEnd = aDestEnd;
SetChangeTrack();
}
__EXPORT ScUndoDragDrop::~ScUndoDragDrop()
{
}
String __EXPORT ScUndoDragDrop::GetComment() const
{ // "Verschieben" : "Kopieren"
return bCut ?
ScGlobal::GetRscString( STR_UNDO_MOVE ) :
ScGlobal::GetRscString( STR_UNDO_COPY );
}
void ScUndoDragDrop::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
if ( pChangeTrack )
{
if ( bCut )
{
nStartChangeAction = pChangeTrack->GetActionMax() + 1;
pChangeTrack->AppendMove( aSrcRange, aDestRange, pRefUndoDoc );
nEndChangeAction = pChangeTrack->GetActionMax();
}
else
pChangeTrack->AppendContentRange( aDestRange, pRefUndoDoc,
nStartChangeAction, nEndChangeAction );
}
else
nStartChangeAction = nEndChangeAction = 0;
}
void ScUndoDragDrop::PaintArea( ScRange aRange, sal_uInt16 nExtFlags ) const
{
sal_uInt16 nPaint = PAINT_GRID;
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
ScDocument* pDoc = pDocShell->GetDocument();
if (pViewShell)
{
VirtualDevice aVirtDev;
ScViewData* pViewData = pViewShell->GetViewData();
if ( pDoc->SetOptimalHeight( aRange.aStart.Row(), aRange.aEnd.Row(),
aRange.aStart.Tab(), 0, &aVirtDev,
pViewData->GetPPTX(), pViewData->GetPPTY(),
pViewData->GetZoomX(), pViewData->GetZoomY(),
sal_False ) )
{
aRange.aStart.SetCol(0);
aRange.aEnd.SetCol(MAXCOL);
aRange.aEnd.SetRow(MAXROW);
nPaint |= PAINT_LEFT;
}
}
if ( bKeepScenarioFlags )
{
// Szenarien mitkopiert -> auch Szenario-Rahmen painten
aRange.aStart.SetCol(0);
aRange.aStart.SetRow(0);
aRange.aEnd.SetCol(MAXCOL);
aRange.aEnd.SetRow(MAXROW);
}
// column/row info (width/height) included if whole columns/rows were copied
if ( aSrcRange.aStart.Col() == 0 && aSrcRange.aEnd.Col() == MAXCOL )
{
nPaint |= PAINT_LEFT;
aRange.aEnd.SetRow(MAXROW);
}
if ( aSrcRange.aStart.Row() == 0 && aSrcRange.aEnd.Row() == MAXROW )
{
nPaint |= PAINT_TOP;
aRange.aEnd.SetCol(MAXCOL);
}
pDocShell->PostPaint( aRange, nPaint, nExtFlags );
}
void ScUndoDragDrop::DoUndo( ScRange aRange ) const
{
ScDocument* pDoc = pDocShell->GetDocument();
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
//? DB-Areas vor Daten, damit bei ExtendMerge die Autofilter-Knoepfe stimmen
ScRange aPaintRange = aRange;
pDoc->ExtendMerge( aPaintRange ); // before deleting
sal_uInt16 nExtFlags = 0;
pDocShell->UpdatePaintExt( nExtFlags, aPaintRange );
// do not undo objects and note captions, they are handled via drawing undo
sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
pDoc->DeleteAreaTab( aRange, nUndoFlags );
pRefUndoDoc->CopyToDocument( aRange, nUndoFlags, sal_False, pDoc );
if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) )
pDoc->ExtendMerge( aRange, sal_True );
aPaintRange.aEnd.SetCol( Max( aPaintRange.aEnd.Col(), aRange.aEnd.Col() ) );
aPaintRange.aEnd.SetRow( Max( aPaintRange.aEnd.Row(), aRange.aEnd.Row() ) );
pDocShell->UpdatePaintExt( nExtFlags, aPaintRange );
PaintArea( aPaintRange, nExtFlags );
}
void __EXPORT ScUndoDragDrop::Undo()
{
BeginUndo();
DoUndo(aDestRange);
if (bCut)
DoUndo(aSrcRange);
EndUndo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}
void __EXPORT ScUndoDragDrop::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
EnableDrawAdjust( pDoc, sal_False ); //! include in ScBlockUndo?
// do not undo/redo objects and note captions, they are handled via drawing undo
sal_uInt16 nRedoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
/* TODO: Redoing note captions is quite tricky due to the fact that a
helper clip document is used. While (re-)pasting the contents to the
destination area, the original pointers to the captions created while
dropping have to be restored. A simple CopyFromClip() would create new
caption objects that are not tracked by drawing undo, and the captions
restored by drawing redo would live without cell note objects pointing
to them. So, first, CopyToClip() and CopyFromClip() are called without
cloning the caption objects. This leads to cell notes pointing to the
wrong captions from source area that will be removed by drawing redo
later. Second, the pointers to the new captions have to be restored.
Sadly, currently these pointers are not stored anywhere but in the list
of drawing undo actions. */
SCTAB nTab;
ScMarkData aSourceMark;
for (nTab=aSrcRange.aStart.Tab(); nTab<=aSrcRange.aEnd.Tab(); nTab++)
aSourceMark.SelectTable( nTab, sal_True );
// do not clone objects and note captions into clipdoc (see above)
ScClipParam aClipParam(aSrcRange, bCut);
pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bKeepScenarioFlags, false, false);
if (bCut)
{
ScRange aSrcPaintRange = aSrcRange;
pDoc->ExtendMerge( aSrcPaintRange ); // before deleting
sal_uInt16 nExtFlags = 0;
pDocShell->UpdatePaintExt( nExtFlags, aSrcPaintRange );
pDoc->DeleteAreaTab( aSrcRange, nRedoFlags );
PaintArea( aSrcPaintRange, nExtFlags );
}
ScMarkData aDestMark;
for (nTab=aDestRange.aStart.Tab(); nTab<=aDestRange.aEnd.Tab(); nTab++)
aDestMark.SelectTable( nTab, sal_True );
sal_Bool bIncludeFiltered = bCut;
// TODO: restore old note captions instead of cloning new captions...
pDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL & ~IDF_OBJECTS, NULL, pClipDoc, sal_True, sal_False, bIncludeFiltered );
if (bCut)
for (nTab=aSrcRange.aStart.Tab(); nTab<=aSrcRange.aEnd.Tab(); nTab++)
pDoc->RefreshAutoFilter( aSrcRange.aStart.Col(), aSrcRange.aStart.Row(),
aSrcRange.aEnd.Col(), aSrcRange.aEnd.Row(), nTab );
// skipped rows and merged cells don't mix
if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
pDocShell->GetDocFunc().UnmergeCells( aDestRange, sal_False, sal_True );
for (nTab=aDestRange.aStart.Tab(); nTab<=aDestRange.aEnd.Tab(); nTab++)
{
SCCOL nEndCol = aDestRange.aEnd.Col();
SCROW nEndRow = aDestRange.aEnd.Row();
pDoc->ExtendMerge( aDestRange.aStart.Col(), aDestRange.aStart.Row(),
nEndCol, nEndRow, nTab, sal_True );
PaintArea( ScRange( aDestRange.aStart.Col(), aDestRange.aStart.Row(), nTab,
nEndCol, nEndRow, nTab ), 0 );
}
SetChangeTrack();
delete pClipDoc;
ShowTable( aDestRange.aStart.Tab() );
RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo?
EnableDrawAdjust( pDoc, sal_True ); //! include in ScBlockUndo?
EndRedo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}
void __EXPORT ScUndoDragDrop::Repeat(SfxRepeatTarget& /* rTarget */)
{
}
sal_Bool __EXPORT ScUndoDragDrop::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
return sal_False; // geht nicht
}
// -----------------------------------------------------------------------
//
// Liste der Bereichsnamen einfuegen
// (Einfuegen|Name|Einfuegen =>[Liste])
//
ScUndoListNames::ScUndoListNames( ScDocShell* pNewDocShell, const ScRange& rRange,
ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc ) :
ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ),
pUndoDoc( pNewUndoDoc ),
pRedoDoc( pNewRedoDoc )
{
}
__EXPORT ScUndoListNames::~ScUndoListNames()
{
delete pUndoDoc;
delete pRedoDoc;
}
String __EXPORT ScUndoListNames::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_LISTNAMES );
}
void ScUndoListNames::DoChange( ScDocument* pSrcDoc ) const
{
ScDocument* pDoc = pDocShell->GetDocument();
pDoc->DeleteAreaTab( aBlockRange, IDF_ALL );
pSrcDoc->CopyToDocument( aBlockRange, IDF_ALL, sal_False, pDoc );
pDocShell->PostPaint( aBlockRange, PAINT_GRID );
pDocShell->PostDataChanged();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
pViewShell->CellContentChanged();
}
void __EXPORT ScUndoListNames::Undo()
{
BeginUndo();
DoChange(pUndoDoc);
EndUndo();
}
void __EXPORT ScUndoListNames::Redo()
{
BeginRedo();
DoChange(pRedoDoc);
EndRedo();
}
void __EXPORT ScUndoListNames::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->InsertNameList();
}
sal_Bool __EXPORT ScUndoListNames::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Szenario anwenden
// (Extras|Szenarien)
//
ScUndoUseScenario::ScUndoUseScenario( ScDocShell* pNewDocShell,
const ScMarkData& rMark,
/*C*/ const ScArea& rDestArea,
ScDocument* pNewUndoDoc,
const String& rNewName ) :
ScSimpleUndo( pNewDocShell ),
pUndoDoc( pNewUndoDoc ),
aMarkData( rMark ),
aName( rNewName )
{
aRange.aStart.SetCol(rDestArea.nColStart);
aRange.aStart.SetRow(rDestArea.nRowStart);
aRange.aStart.SetTab(rDestArea.nTab);
aRange.aEnd.SetCol(rDestArea.nColEnd);
aRange.aEnd.SetRow(rDestArea.nRowEnd);
aRange.aEnd.SetTab(rDestArea.nTab);
}
__EXPORT ScUndoUseScenario::~ScUndoUseScenario()
{
delete pUndoDoc;
}
String __EXPORT ScUndoUseScenario::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_USESCENARIO );
}
void __EXPORT ScUndoUseScenario::Undo()
{
BeginUndo();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
pViewShell->DoneBlockMode();
pViewShell->InitOwnBlockMode();
}
ScDocument* pDoc = pDocShell->GetDocument();
pDoc->DeleteSelection( IDF_ALL, aMarkData );
pUndoDoc->CopyToDocument( aRange, IDF_ALL, sal_True, pDoc, &aMarkData );
// Szenario-Tabellen
sal_Bool bFrame = sal_False;
SCTAB nTab = aRange.aStart.Tab();
SCTAB nEndTab = nTab;
while ( pUndoDoc->HasTable(nEndTab+1) && pUndoDoc->IsScenario(nEndTab+1) )
++nEndTab;
for (SCTAB i = nTab+1; i<=nEndTab; i++)
{
// Flags immer
String aComment;
Color aColor;
sal_uInt16 nScenFlags;
pUndoDoc->GetScenarioData( i, aComment, aColor, nScenFlags );
pDoc->SetScenarioData( i, aComment, aColor, nScenFlags );
sal_Bool bActive = pUndoDoc->IsActiveScenario( i );
pDoc->SetActiveScenario( i, bActive );
// Bei Zurueckkopier-Szenarios auch Inhalte
if ( nScenFlags & SC_SCENARIO_TWOWAY )
{
pDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, i, IDF_ALL );
pUndoDoc->CopyToDocument( 0,0,i, MAXCOL,MAXROW,i, IDF_ALL,sal_False, pDoc );
}
if ( nScenFlags & SC_SCENARIO_SHOWFRAME )
bFrame = sal_True;
}
// Wenn sichtbare Rahmen, dann alles painten
if (bFrame)
pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_EXTRAS );
else
pDocShell->PostPaint( aRange, PAINT_GRID | PAINT_EXTRAS );
pDocShell->PostDataChanged();
if (pViewShell)
pViewShell->CellContentChanged();
ShowTable( aRange.aStart.Tab() );
EndUndo();
}
void __EXPORT ScUndoUseScenario::Redo()
{
SCTAB nTab = aRange.aStart.Tab();
BeginRedo();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
pViewShell->SetTabNo( nTab );
pViewShell->DoneBlockMode();
pViewShell->InitOwnBlockMode();
}
pDocShell->UseScenario( nTab, aName, sal_False );
EndRedo();
}
void __EXPORT ScUndoUseScenario::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
String aTemp = aName;
((ScTabViewTarget&)rTarget).GetViewShell()->UseScenario(aTemp);
}
}
sal_Bool __EXPORT ScUndoUseScenario::CanRepeat(SfxRepeatTarget& rTarget) const
{
if (rTarget.ISA(ScTabViewTarget))
{
ScViewData* pViewData = ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData();
return !pViewData->GetDocument()->IsScenario( pViewData->GetTabNo() );
}
return sal_False;
}
// -----------------------------------------------------------------------
//
// Vorlage anwenden
// (Format|Vorlagenkatalog)
//
ScUndoSelectionStyle::ScUndoSelectionStyle( ScDocShell* pNewDocShell,
const ScMarkData& rMark,
const ScRange& rRange,
const String& rName,
ScDocument* pNewUndoDoc ) :
ScSimpleUndo( pNewDocShell ),
aMarkData( rMark ),
pUndoDoc( pNewUndoDoc ),
aStyleName( rName ),
aRange( rRange )
{
aMarkData.MarkToMulti();
}
__EXPORT ScUndoSelectionStyle::~ScUndoSelectionStyle()
{
delete pUndoDoc;
}
String __EXPORT ScUndoSelectionStyle::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_APPLYCELLSTYLE );
}
void ScUndoSelectionStyle::DoChange( const sal_Bool bUndo )
{
ScDocument* pDoc = pDocShell->GetDocument();
SetViewMarkData( aMarkData );
ScRange aWorkRange( aRange );
if ( pDoc->HasAttrib( aWorkRange, HASATTR_MERGED ) ) // zusammengefasste Zellen?
pDoc->ExtendMerge( aWorkRange, sal_True );
sal_uInt16 nExtFlags = 0;
pDocShell->UpdatePaintExt( nExtFlags, aWorkRange );
if (bUndo) // bei Undo alte Daten wieder reinschubsen
{
SCTAB nTabCount = pDoc->GetTableCount();
ScRange aCopyRange = aWorkRange;
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
}
else // bei Redo Style wieder zuweisen
{
ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
ScStyleSheet* pStyleSheet =
(ScStyleSheet*) pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
if (!pStyleSheet)
{
DBG_ERROR("StyleSheet not found");
return;
}
pDoc->ApplySelectionStyle( *pStyleSheet, aMarkData );
}
pDocShell->UpdatePaintExt( nExtFlags, aWorkRange );
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) )
/*A*/ pDocShell->PostPaint( aWorkRange, PAINT_GRID | PAINT_EXTRAS, nExtFlags );
ShowTable( aWorkRange.aStart.Tab() );
}
void __EXPORT ScUndoSelectionStyle::Undo()
{
BeginUndo();
DoChange( sal_True );
EndUndo();
}
void __EXPORT ScUndoSelectionStyle::Redo()
{
BeginRedo();
DoChange( sal_False );
EndRedo();
}
void __EXPORT ScUndoSelectionStyle::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
ScDocument* pDoc = pDocShell->GetDocument();
ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
ScStyleSheet* pStyleSheet = (ScStyleSheet*) pStlPool->
Find( aStyleName, SFX_STYLE_FAMILY_PARA );
if (!pStyleSheet)
{
DBG_ERROR("StyleSheet not found");
return;
}
ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell();
rViewShell.SetStyleSheetToMarked( pStyleSheet, sal_True );
}
}
sal_Bool __EXPORT ScUndoSelectionStyle::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
sal_uInt16 __EXPORT ScUndoSelectionStyle::GetId() const
{
return STR_UNDO_APPLYCELLSTYLE;
}
// -----------------------------------------------------------------------
//
// Matrix-Formel eingeben
//
ScUndoEnterMatrix::ScUndoEnterMatrix( ScDocShell* pNewDocShell, const ScRange& rArea,
ScDocument* pNewUndoDoc, const String& rForm ) :
ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ),
pUndoDoc( pNewUndoDoc ),
aFormula( rForm )
{
SetChangeTrack();
}
__EXPORT ScUndoEnterMatrix::~ScUndoEnterMatrix()
{
delete pUndoDoc;
}
String __EXPORT ScUndoEnterMatrix::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_ENTERMATRIX );
}
void ScUndoEnterMatrix::SetChangeTrack()
{
ScDocument* pDoc = pDocShell->GetDocument();
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
nStartChangeAction, nEndChangeAction );
else
nStartChangeAction = nEndChangeAction = 0;
}
void __EXPORT ScUndoEnterMatrix::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
pDoc->DeleteAreaTab( aBlockRange, IDF_ALL & ~IDF_NOTE );
pUndoDoc->CopyToDocument( aBlockRange, IDF_ALL & ~IDF_NOTE, sal_False, pDoc );
pDocShell->PostPaint( aBlockRange, PAINT_GRID );
pDocShell->PostDataChanged();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
pViewShell->CellContentChanged();
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
EndUndo();
}
void __EXPORT ScUndoEnterMatrix::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
ScMarkData aDestMark;
aDestMark.SelectOneTable( aBlockRange.aStart.Tab() );
aDestMark.SetMarkArea( aBlockRange );
pDoc->InsertMatrixFormula( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(),
aDestMark, aFormula );
// pDocShell->PostPaint( aBlockRange, PAINT_GRID ); // nicht noetig ???
SetChangeTrack();
EndRedo();
}
void __EXPORT ScUndoEnterMatrix::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
String aTemp = aFormula;
((ScTabViewTarget&)rTarget).GetViewShell()->EnterMatrix(aTemp);
}
}
sal_Bool __EXPORT ScUndoEnterMatrix::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Einzug vermindern / erhoehen
//
ScRange lcl_GetMultiMarkRange( const ScMarkData& rMark )
{
DBG_ASSERT( rMark.IsMultiMarked(), "wrong mark type" );
ScRange aRange;
rMark.GetMultiMarkArea( aRange );
return aRange;
}
ScUndoIndent::ScUndoIndent( ScDocShell* pNewDocShell, const ScMarkData& rMark,
ScDocument* pNewUndoDoc, sal_Bool bIncrement ) :
ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ),
aMarkData( rMark ),
pUndoDoc( pNewUndoDoc ),
bIsIncrement( bIncrement )
{
}
__EXPORT ScUndoIndent::~ScUndoIndent()
{
delete pUndoDoc;
}
String __EXPORT ScUndoIndent::GetComment() const
{
sal_uInt16 nId = bIsIncrement ? STR_UNDO_INC_INDENT : STR_UNDO_DEC_INDENT;
return ScGlobal::GetRscString( nId );
}
void __EXPORT ScUndoIndent::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
SCTAB nTabCount = pDoc->GetTableCount();
ScRange aCopyRange = aBlockRange;
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndUndo();
}
void __EXPORT ScUndoIndent::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
pDoc->ChangeSelectionIndent( bIsIncrement, aMarkData );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndRedo();
}
void __EXPORT ScUndoIndent::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->ChangeIndent( bIsIncrement );
}
sal_Bool __EXPORT ScUndoIndent::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Transliteration for cells
//
ScUndoTransliterate::ScUndoTransliterate( ScDocShell* pNewDocShell, const ScMarkData& rMark,
ScDocument* pNewUndoDoc, sal_Int32 nType ) :
ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ),
aMarkData( rMark ),
pUndoDoc( pNewUndoDoc ),
nTransliterationType( nType )
{
}
__EXPORT ScUndoTransliterate::~ScUndoTransliterate()
{
delete pUndoDoc;
}
String __EXPORT ScUndoTransliterate::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_TRANSLITERATE );
}
void __EXPORT ScUndoTransliterate::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
SCTAB nTabCount = pDoc->GetTableCount();
ScRange aCopyRange = aBlockRange;
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
pUndoDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pDoc, &aMarkData );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndUndo();
}
void __EXPORT ScUndoTransliterate::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
pDoc->TransliterateText( aMarkData, nTransliterationType );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndRedo();
}
void __EXPORT ScUndoTransliterate::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->TransliterateText( nTransliterationType );
}
sal_Bool __EXPORT ScUndoTransliterate::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// einzelne Items per Which-IDs aus Bereich loeschen
//
ScUndoClearItems::ScUndoClearItems( ScDocShell* pNewDocShell, const ScMarkData& rMark,
ScDocument* pNewUndoDoc, const sal_uInt16* pW ) :
ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ),
aMarkData( rMark ),
pUndoDoc( pNewUndoDoc ),
pWhich( NULL )
{
DBG_ASSERT( pW, "ScUndoClearItems: Which-Pointer ist 0" );
sal_uInt16 nCount = 0;
while ( pW[nCount] )
++nCount;
pWhich = new sal_uInt16[nCount+1];
for (sal_uInt16 i=0; i<=nCount; i++)
pWhich[i] = pW[i];
}
__EXPORT ScUndoClearItems::~ScUndoClearItems()
{
delete pUndoDoc;
delete pWhich;
}
String __EXPORT ScUndoClearItems::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_DELETECONTENTS );
}
void __EXPORT ScUndoClearItems::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndUndo();
}
void __EXPORT ScUndoClearItems::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
pDoc->ClearSelectionItems( pWhich, aMarkData );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndRedo();
}
void __EXPORT ScUndoClearItems::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
ScViewData* pViewData = ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData();
ScDocFunc aFunc(*pViewData->GetDocShell());
aFunc.ClearItems( pViewData->GetMarkData(), pWhich, sal_False );
}
}
sal_Bool __EXPORT ScUndoClearItems::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Alle Umbrueche einer Tabelle loeschen
//
ScUndoRemoveBreaks::ScUndoRemoveBreaks( ScDocShell* pNewDocShell,
SCTAB nNewTab, ScDocument* pNewUndoDoc ) :
ScSimpleUndo( pNewDocShell ),
nTab( nNewTab ),
pUndoDoc( pNewUndoDoc )
{
}
__EXPORT ScUndoRemoveBreaks::~ScUndoRemoveBreaks()
{
delete pUndoDoc;
}
String __EXPORT ScUndoRemoveBreaks::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_REMOVEBREAKS );
}
void __EXPORT ScUndoRemoveBreaks::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
pUndoDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, sal_False, pDoc );
if (pViewShell)
pViewShell->UpdatePageBreakData( sal_True );
pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
EndUndo();
}
void __EXPORT ScUndoRemoveBreaks::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
pDoc->RemoveManualBreaks(nTab);
pDoc->UpdatePageBreaks(nTab);
if (pViewShell)
pViewShell->UpdatePageBreakData( sal_True );
pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
EndRedo();
}
void __EXPORT ScUndoRemoveBreaks::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
{
ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell();
rViewShell.RemoveManualBreaks();
}
}
sal_Bool __EXPORT ScUndoRemoveBreaks::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// Zusammenfassung aufheben (fuer einen ganzen Bereich)
//
ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell* pNewDocShell,
const ScRange& rArea, ScDocument* pNewUndoDoc ) :
ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ),
pUndoDoc( pNewUndoDoc )
{
}
__EXPORT ScUndoRemoveMerge::~ScUndoRemoveMerge()
{
delete pUndoDoc;
}
String __EXPORT ScUndoRemoveMerge::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_REMERGE ); // "Zusammenfassung aufheben"
}
void __EXPORT ScUndoRemoveMerge::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
ScRange aExtended = aBlockRange;
pUndoDoc->ExtendMerge( aExtended );
pDoc->DeleteAreaTab( aExtended, IDF_ATTRIB );
pUndoDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pDoc );
sal_Bool bDidPaint = sal_False;
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if ( pViewShell )
{
pViewShell->SetTabNo( aExtended.aStart.Tab() );
bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() );
}
if (!bDidPaint)
ScUndoUtil::PaintMore( pDocShell, aExtended );
EndUndo();
}
void __EXPORT ScUndoRemoveMerge::Redo()
{
BeginRedo();
SCTAB nTab = aBlockRange.aStart.Tab();
ScDocument* pDoc = pDocShell->GetDocument();
ScRange aExtended = aBlockRange;
pDoc->ExtendMerge( aExtended );
ScRange aRefresh = aExtended;
pDoc->ExtendOverlapped( aRefresh );
// ausfuehren
const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
ScPatternAttr aPattern( pDoc->GetPool() );
aPattern.GetItemSet().Put( rDefAttr );
pDoc->ApplyPatternAreaTab( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), nTab,
aPattern );
pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
SC_MF_HOR | SC_MF_VER );
pDoc->ExtendMerge( aRefresh, sal_True, sal_False );
// Paint
sal_Bool bDidPaint = sal_False;
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if ( pViewShell )
{
pViewShell->SetTabNo( aExtended.aStart.Tab() );
bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() );
}
if (!bDidPaint)
ScUndoUtil::PaintMore( pDocShell, aExtended );
EndRedo();
}
void __EXPORT ScUndoRemoveMerge::Repeat(SfxRepeatTarget& rTarget)
{
if (rTarget.ISA(ScTabViewTarget))
((ScTabViewTarget&)rTarget).GetViewShell()->RemoveMerge();
}
sal_Bool __EXPORT ScUndoRemoveMerge::CanRepeat(SfxRepeatTarget& rTarget) const
{
return (rTarget.ISA(ScTabViewTarget));
}
// -----------------------------------------------------------------------
//
// nur Umrandung setzen, per ScRangeList (StarOne)
//
ScRange lcl_TotalRange( const ScRangeList& rRanges )
{
ScRange aTotal;
sal_uLong nCount = rRanges.Count();
for (sal_uLong i=0; i<nCount; i++)
{
ScRange aRange = *rRanges.GetObject(i);
if (i==0)
aTotal = aRange;
else
{
if (aRange.aStart.Col() < aTotal.aStart.Col())
aTotal.aStart.SetCol(aRange.aStart.Col());
if (aRange.aStart.Row() < aTotal.aStart.Row())
aTotal.aStart.SetRow(aRange.aStart.Row());
if (aRange.aStart.Tab() < aTotal.aStart.Tab())
aTotal.aStart.SetTab(aRange.aStart.Tab());
if (aRange.aEnd.Col() > aTotal.aEnd.Col())
aTotal.aEnd.SetCol(aRange.aEnd.Col());
if (aRange.aEnd.Row() > aTotal.aEnd.Row())
aTotal.aEnd.SetRow(aRange.aEnd.Row());
if (aRange.aEnd.Tab() > aTotal.aEnd.Tab())
aTotal.aEnd.SetTab(aRange.aEnd.Tab());
}
}
return aTotal;
}
ScUndoBorder::ScUndoBorder( ScDocShell* pNewDocShell,
const ScRangeList& rRangeList, ScDocument* pNewUndoDoc,
const SvxBoxItem& rNewOuter, const SvxBoxInfoItem& rNewInner ) :
ScBlockUndo( pNewDocShell, lcl_TotalRange(rRangeList), SC_UNDO_SIMPLE ),
pUndoDoc( pNewUndoDoc )
{
pRanges = new ScRangeList(rRangeList);
pOuter = new SvxBoxItem(rNewOuter);
pInner = new SvxBoxInfoItem(rNewInner);
}
__EXPORT ScUndoBorder::~ScUndoBorder()
{
delete pUndoDoc;
delete pRanges;
delete pOuter;
delete pInner;
}
String __EXPORT ScUndoBorder::GetComment() const
{
return ScGlobal::GetRscString( STR_UNDO_SELATTRLINES ); //! eigener String?
}
void __EXPORT ScUndoBorder::Undo()
{
BeginUndo();
ScDocument* pDoc = pDocShell->GetDocument();
ScMarkData aMarkData;
aMarkData.MarkFromRangeList( *pRanges, sal_False );
pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndUndo();
}
void __EXPORT ScUndoBorder::Redo()
{
BeginRedo();
ScDocument* pDoc = pDocShell->GetDocument(); //! Funktion an docfunc aufrufen
sal_uLong nCount = pRanges->Count();
sal_uLong i;
for (i=0; i<nCount; i++)
{
ScRange aRange = *pRanges->GetObject(i);
SCTAB nTab = aRange.aStart.Tab();
ScMarkData aMark;
aMark.SetMarkArea( aRange );
aMark.SelectTable( nTab, sal_True );
pDoc->ApplySelectionFrame( aMark, pOuter, pInner );
}
for (i=0; i<nCount; i++)
pDocShell->PostPaint( *pRanges->GetObject(i), PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
EndRedo();
}
void __EXPORT ScUndoBorder::Repeat(SfxRepeatTarget& /* rTarget */)
{
//! spaeter (wenn die Funktion aus cellsuno nach docfunc gewandert ist)
}
sal_Bool __EXPORT ScUndoBorder::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
return sal_False; // s.o.
}