diff options
Diffstat (limited to 'sc/source/ui/undo/undobase.cxx')
-rw-r--r-- | sc/source/ui/undo/undobase.cxx | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx new file mode 100644 index 000000000000..fffb76ebd061 --- /dev/null +++ b/sc/source/ui/undo/undobase.cxx @@ -0,0 +1,539 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <vcl/virdev.hxx> + +#include "undobase.hxx" +#include "refundo.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "undoolk.hxx" +#include "undodraw.hxx" +#include "dbcolect.hxx" +#include "attrib.hxx" +#include "queryparam.hxx" +#include "globstr.hrc" + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScSimpleUndo, SfxUndoAction); +TYPEINIT1(ScBlockUndo, ScSimpleUndo); +TYPEINIT1(ScMoveUndo, ScSimpleUndo); +TYPEINIT1(ScDBFuncUndo, ScSimpleUndo); +TYPEINIT1(ScUndoWrapper, SfxUndoAction); + +// ----------------------------------------------------------------------- + +ScSimpleUndo::ScSimpleUndo( ScDocShell* pDocSh ) : + pDocShell( pDocSh ), + pDetectiveUndo( NULL ) +{ +} + +__EXPORT ScSimpleUndo::~ScSimpleUndo() +{ + delete pDetectiveUndo; +} + +BOOL __EXPORT ScSimpleUndo::Merge( SfxUndoAction *pNextAction ) +{ + // Zu jeder Undo-Action kann eine SdrUndoGroup fuer das Aktualisieren + // der Detektiv-Pfeile gehoeren. + // DetectiveRefresh kommt immer hinterher, die SdrUndoGroup ist in + // eine ScUndoDraw Action verpackt. + // Nur beim automatischen Aktualisieren wird AddUndoAction mit + // bTryMerg=TRUE gerufen. + + if ( !pDetectiveUndo && pNextAction->ISA(ScUndoDraw) ) + { + // SdrUndoAction aus der ScUndoDraw Action uebernehmen, + // ScUndoDraw wird dann vom UndoManager geloescht + + ScUndoDraw* pCalcUndo = (ScUndoDraw*)pNextAction; + pDetectiveUndo = pCalcUndo->GetDrawUndo(); + pCalcUndo->ForgetDrawUndo(); + return TRUE; + } + + return FALSE; +} + +void ScSimpleUndo::BeginUndo() +{ + pDocShell->SetInUndo( TRUE ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->HideAllCursors(); // z.B. wegen zusammengefassten Zellen + + // detective updates happened last, must be undone first + if (pDetectiveUndo) + pDetectiveUndo->Undo(); +} + +void ScSimpleUndo::EndUndo() +{ + pDocShell->SetDocumentModified(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateAutoFillMark(); + pViewShell->UpdateInputHandler(); + pViewShell->ShowAllCursors(); + } + + pDocShell->SetInUndo( FALSE ); +} + +void ScSimpleUndo::BeginRedo() +{ + pDocShell->SetInUndo( TRUE ); //! eigenes Flag fuer Redo? + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->HideAllCursors(); // z.B. wegen zusammengefassten Zellen +} + +void ScSimpleUndo::EndRedo() +{ + if (pDetectiveUndo) + pDetectiveUndo->Redo(); + + pDocShell->SetDocumentModified(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateAutoFillMark(); + pViewShell->UpdateInputHandler(); + pViewShell->ShowAllCursors(); + } + + pDocShell->SetInUndo( FALSE ); +} + +void ScSimpleUndo::ShowTable( SCTAB nTab ) // static +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo( nTab ); +} + +void ScSimpleUndo::ShowTable( const ScRange& rRange ) // static +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nStart = rRange.aStart.Tab(); + SCTAB nEnd = rRange.aEnd.Tab(); + SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); + if ( nTab < nStart || nTab > nEnd ) // wenn nicht im Bereich: + pViewShell->SetTabNo( nStart ); // auf erste des Bereiches + } +} + + +// ----------------------------------------------------------------------- + +ScBlockUndo::ScBlockUndo( ScDocShell* pDocSh, const ScRange& rRange, + ScBlockUndoMode eBlockMode ) : + ScSimpleUndo( pDocSh ), + aBlockRange( rRange ), + eMode( eBlockMode ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); +} + +__EXPORT ScBlockUndo::~ScBlockUndo() +{ + DeleteSdrUndoAction( pDrawUndo ); +} + +void ScBlockUndo::BeginUndo() +{ + ScSimpleUndo::BeginUndo(); + EnableDrawAdjust( pDocShell->GetDocument(), FALSE ); +} + +void ScBlockUndo::EndUndo() +{ + if (eMode == SC_UNDO_AUTOHEIGHT) + AdjustHeight(); + + EnableDrawAdjust( pDocShell->GetDocument(), TRUE ); + DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); + + ShowBlock(); + ScSimpleUndo::EndUndo(); +} + +/* +void ScBlockUndo::BeginRedo() +{ + ScSimpleUndo::BeginRedo(); +} +*/ + +void ScBlockUndo::EndRedo() +{ + if (eMode == SC_UNDO_AUTOHEIGHT) + AdjustHeight(); + + ShowBlock(); + ScSimpleUndo::EndRedo(); +} + +BOOL ScBlockUndo::AdjustHeight() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + VirtualDevice aVirtDev; + Fraction aZoomX( 1, 1 ); + Fraction aZoomY = aZoomX; + double nPPTX, nPPTY; + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + ScViewData* pData = pViewShell->GetViewData(); + nPPTX = pData->GetPPTX(); + nPPTY = pData->GetPPTY(); + aZoomX = pData->GetZoomX(); + aZoomY = pData->GetZoomY(); + } + else + { + // Zoom auf 100 lassen + nPPTX = ScGlobal::nScreenPPTX; + nPPTY = ScGlobal::nScreenPPTY; + } + + BOOL bRet = pDoc->SetOptimalHeight( aBlockRange.aStart.Row(), aBlockRange.aEnd.Row(), +/*!*/ aBlockRange.aStart.Tab(), 0, &aVirtDev, + nPPTX, nPPTY, aZoomX, aZoomY, FALSE ); + + if (bRet) + pDocShell->PostPaint( 0, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(), + MAXCOL, MAXROW, aBlockRange.aEnd.Tab(), + PAINT_GRID | PAINT_LEFT ); + + return bRet; +} + +void ScBlockUndo::ShowBlock() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + ShowTable( aBlockRange ); // bei mehreren Tabs im Range ist jede davon gut + pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), + SC_FOLLOW_JUMP, FALSE, FALSE ); + SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); + ScRange aRange = aBlockRange; + aRange.aStart.SetTab( nTab ); + aRange.aEnd.SetTab( nTab ); + pViewShell->MarkRange( aRange ); + + // nicht per SetMarkArea an MarkData, wegen evtl. fehlendem Paint + } +} + + +// ----------------------------------------------------------------------- + +ScMoveUndo::ScMoveUndo( ScDocShell* pDocSh, ScDocument* pRefDoc, ScRefUndoData* pRefData, + ScMoveUndoMode eRefMode ) : + ScSimpleUndo( pDocSh ), + pRefUndoDoc( pRefDoc ), + pRefUndoData( pRefData ), + eMode( eRefMode ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + if (pRefUndoData) + pRefUndoData->DeleteUnchanged(pDoc); + pDrawUndo = GetSdrUndoAction( pDoc ); +} + +__EXPORT ScMoveUndo::~ScMoveUndo() +{ + delete pRefUndoData; + delete pRefUndoDoc; + DeleteSdrUndoAction( pDrawUndo ); +} + +void ScMoveUndo::UndoRef() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScRange aRange(0,0,0, MAXCOL,MAXROW,pRefUndoDoc->GetTableCount()-1); + pRefUndoDoc->CopyToDocument( aRange, IDF_FORMULA, FALSE, pDoc, NULL, FALSE ); + if (pRefUndoData) + pRefUndoData->DoUndo( pDoc, (eMode == SC_UNDO_REFFIRST) ); + // #65055# HACK: ScDragDropUndo ist der einzige mit REFFIRST. + // Falls nicht, resultiert daraus evtl. ein zu haeufiges Anpassen + // der ChartRefs, nicht schoen, aber auch nicht schlecht.. +} + +void ScMoveUndo::BeginUndo() +{ + ScSimpleUndo::BeginUndo(); + + EnableDrawAdjust( pDocShell->GetDocument(), FALSE ); + + if (pRefUndoDoc && eMode == SC_UNDO_REFFIRST) + UndoRef(); +} + +void ScMoveUndo::EndUndo() +{ + //@17.12.97 Reihenfolge der Fkt.s geaendert + DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); // #125875# must also be called when pointer is null + + if (pRefUndoDoc && eMode == SC_UNDO_REFLAST) + UndoRef(); + + EnableDrawAdjust( pDocShell->GetDocument(), TRUE ); + + ScSimpleUndo::EndUndo(); +} + +/* +void ScMoveUndo::BeginRedo() +{ + ScSimpleUndo::BeginRedo(); +} +*/ + +/* +void ScMoveUndo::EndRedo() +{ + ScSimpleUndo::EndRedo(); +} +*/ + +// ----------------------------------------------------------------------- + +ScDBFuncUndo::ScDBFuncUndo( ScDocShell* pDocSh, const ScRange& rOriginal, SdrUndoAction* pDrawUndo ) : + ScSimpleUndo( pDocSh ), + aOriginalRange( rOriginal ), + mpDrawUndo( pDrawUndo ) +{ + pAutoDBRange = pDocSh->GetOldAutoDBRange(); +} + +ScDBFuncUndo::~ScDBFuncUndo() +{ + DeleteSdrUndoAction( mpDrawUndo ); + delete pAutoDBRange; +} + +void ScDBFuncUndo::SetDrawUndoAction( SdrUndoAction* pDrawUndo ) +{ + DeleteSdrUndoAction( mpDrawUndo ); + mpDrawUndo = pDrawUndo; +} + +void ScDBFuncUndo::BeginUndo() +{ + ScSimpleUndo::BeginUndo(); + DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() ); +} + +void ScDBFuncUndo::EndUndo() +{ + ScSimpleUndo::EndUndo(); + + if ( pAutoDBRange ) + { + USHORT nNoNameIndex; + ScDocument* pDoc = pDocShell->GetDocument(); + ScDBCollection* pColl = pDoc->GetDBCollection(); + if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) ) + { + ScDBData* pNoNameData = (*pColl)[nNoNameIndex]; + + SCCOL nRangeX1; + SCROW nRangeY1; + SCCOL nRangeX2; + SCROW nRangeY2; + SCTAB nRangeTab; + pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + + *pNoNameData = *pAutoDBRange; + + if ( pAutoDBRange->HasAutoFilter() ) + { + // restore AutoFilter buttons + pAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO ); + pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID ); + } + } + } +} + +void ScDBFuncUndo::BeginRedo() +{ + RedoSdrUndoAction( mpDrawUndo ); + if ( pAutoDBRange ) + { + // move the database range to this function's position again (see ScDocShell::GetDBData) + + USHORT nNoNameIndex; + ScDocument* pDoc = pDocShell->GetDocument(); + ScDBCollection* pColl = pDoc->GetDBCollection(); + if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) ) + { + ScDBData* pNoNameData = (*pColl)[nNoNameIndex]; + + SCCOL nRangeX1; + SCROW nRangeY1; + SCCOL nRangeX2; + SCROW nRangeY2; + SCTAB nRangeTab; + pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + + pNoNameData->SetSortParam( ScSortParam() ); + pNoNameData->SetQueryParam( ScQueryParam() ); + pNoNameData->SetSubTotalParam( ScSubTotalParam() ); + + pNoNameData->SetArea( aOriginalRange.aStart.Tab(), + aOriginalRange.aStart.Col(), aOriginalRange.aStart.Row(), + aOriginalRange.aEnd.Col(), aOriginalRange.aEnd.Row() ); + + pNoNameData->SetByRow( TRUE ); + pNoNameData->SetAutoFilter( FALSE ); + // header is always set with the operation in redo + } + } + + ScSimpleUndo::BeginRedo(); +} + +void ScDBFuncUndo::EndRedo() +{ + ScSimpleUndo::EndRedo(); +} + +// ----------------------------------------------------------------------- + +ScUndoWrapper::ScUndoWrapper( SfxUndoAction* pUndo ) : + pWrappedUndo( pUndo ) +{ +} + +ScUndoWrapper::~ScUndoWrapper() +{ + delete pWrappedUndo; +} + +void ScUndoWrapper::ForgetWrappedUndo() +{ + pWrappedUndo = NULL; // don't delete in dtor - pointer must be stored outside +} + +String ScUndoWrapper::GetComment() const +{ + if (pWrappedUndo) + return pWrappedUndo->GetComment(); + else + return String(); +} + +String ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const +{ + if (pWrappedUndo) + return pWrappedUndo->GetRepeatComment(rTarget); + else + return String(); +} + +USHORT ScUndoWrapper::GetId() const +{ + if (pWrappedUndo) + return pWrappedUndo->GetId(); + else + return 0; +} + +BOOL ScUndoWrapper::IsLinked() +{ + if (pWrappedUndo) + return pWrappedUndo->IsLinked(); + else + return FALSE; +} + +void ScUndoWrapper::SetLinked( BOOL bIsLinked ) +{ + if (pWrappedUndo) + pWrappedUndo->SetLinked(bIsLinked); +} + +BOOL ScUndoWrapper::Merge( SfxUndoAction* pNextAction ) +{ + if (pWrappedUndo) + return pWrappedUndo->Merge(pNextAction); + else + return FALSE; +} + +void ScUndoWrapper::Undo() +{ + if (pWrappedUndo) + pWrappedUndo->Undo(); +} + +void ScUndoWrapper::Redo() +{ + if (pWrappedUndo) + pWrappedUndo->Redo(); +} + +void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget) +{ + if (pWrappedUndo) + pWrappedUndo->Repeat(rTarget); +} + +BOOL ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const +{ + if (pWrappedUndo) + return pWrappedUndo->CanRepeat(rTarget); + else + return FALSE; +} + + |