Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / undo / undobase.cxx
blob178ec573bb7d702056b215a46677232230fef6cd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/virdev.hxx>
22 #include "undobase.hxx"
23 #include "refundo.hxx"
24 #include "docsh.hxx"
25 #include "tabvwsh.hxx"
26 #include "undoolk.hxx"
27 #include "undodraw.hxx"
28 #include "dbdata.hxx"
29 #include "attrib.hxx"
30 #include "queryparam.hxx"
31 #include "subtotalparam.hxx"
32 #include "globstr.hrc"
34 // STATIC DATA -----------------------------------------------------------
36 TYPEINIT1(ScSimpleUndo, SfxUndoAction);
37 TYPEINIT1(ScBlockUndo, ScSimpleUndo);
38 TYPEINIT1(ScMultiBlockUndo, ScSimpleUndo);
39 TYPEINIT1(ScMoveUndo, ScSimpleUndo);
40 TYPEINIT1(ScDBFuncUndo, ScSimpleUndo);
41 TYPEINIT1(ScUndoWrapper, SfxUndoAction);
43 ScSimpleUndo::ScSimpleUndo( ScDocShell* pDocSh ) :
44 pDocShell( pDocSh ),
45 pDetectiveUndo( NULL )
49 ScSimpleUndo::~ScSimpleUndo()
51 delete pDetectiveUndo;
54 bool ScSimpleUndo::SetViewMarkData( const ScMarkData& rMarkData )
56 if ( IsPaintLocked() )
57 return false;
59 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
60 if ( !pViewShell )
61 return false;
63 pViewShell->SetMarkData( rMarkData );
64 return true;
67 bool ScSimpleUndo::Merge( SfxUndoAction *pNextAction )
69 // A SdrUndoGroup for updating detective arrows can belong
70 // to each Undo-Action.
71 // DetectiveRefresh is always called next,
72 // the SdrUndoGroup is encapsulated in a ScUndoDraw action.
73 // AddUndoAction is only called with bTryMerg=sal_True
74 // for automatic update.
76 if ( !pDetectiveUndo && pNextAction->ISA(ScUndoDraw) )
78 // Take SdrUndoAction from ScUndoDraw Action,
79 // ScUndoDraw is later deleted by the UndoManager
81 ScUndoDraw* pCalcUndo = (ScUndoDraw*)pNextAction;
82 pDetectiveUndo = pCalcUndo->GetDrawUndo();
83 pCalcUndo->ForgetDrawUndo();
84 return sal_True;
87 return false;
90 void ScSimpleUndo::BeginUndo()
92 pDocShell->SetInUndo( sal_True );
94 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
95 if (pViewShell)
96 pViewShell->HideAllCursors(); // for example due to merged cells
98 // detective updates happened last, must be undone first
99 if (pDetectiveUndo)
100 pDetectiveUndo->Undo();
103 void ScSimpleUndo::EndUndo()
105 pDocShell->SetDocumentModified();
107 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
108 if (pViewShell)
110 pViewShell->UpdateAutoFillMark();
111 pViewShell->UpdateInputHandler();
112 pViewShell->ShowAllCursors();
115 pDocShell->SetInUndo( false );
118 void ScSimpleUndo::BeginRedo()
120 pDocShell->SetInUndo( sal_True ); //! own Flag for Redo?
122 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
123 if (pViewShell)
124 pViewShell->HideAllCursors(); // for example due to merged cells
127 void ScSimpleUndo::EndRedo()
129 if (pDetectiveUndo)
130 pDetectiveUndo->Redo();
132 pDocShell->SetDocumentModified();
134 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
135 if (pViewShell)
137 pViewShell->UpdateAutoFillMark();
138 pViewShell->UpdateInputHandler();
139 pViewShell->ShowAllCursors();
142 pDocShell->SetInUndo( false );
145 void ScSimpleUndo::BroadcastChanges( const ScRange& rRange )
147 ScDocument* pDoc = pDocShell->GetDocument();
148 pDoc->CellContentModified();
150 ScHint aHint(SC_HINT_DATACHANGED, ScAddress());
151 ScAddress& rPos = aHint.GetAddress();
152 for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
154 rPos.SetTab(nTab);
155 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
157 rPos.SetCol(nCol);
158 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
160 rPos.SetRow(nRow);
161 pDoc->Broadcast(aHint);
166 pDoc->BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
169 void ScSimpleUndo::ShowTable( SCTAB nTab )
171 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
172 if (pViewShell)
173 pViewShell->SetTabNo( nTab );
176 void ScSimpleUndo::ShowTable( const ScRange& rRange )
178 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
179 if (pViewShell)
181 SCTAB nStart = rRange.aStart.Tab();
182 SCTAB nEnd = rRange.aEnd.Tab();
183 SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
184 if ( nTab < nStart || nTab > nEnd ) // if not in range:
185 pViewShell->SetTabNo( nStart ); // at beginning of the range
189 ScBlockUndo::ScBlockUndo( ScDocShell* pDocSh, const ScRange& rRange,
190 ScBlockUndoMode eBlockMode ) :
191 ScSimpleUndo( pDocSh ),
192 aBlockRange( rRange ),
193 eMode( eBlockMode )
195 pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
198 ScBlockUndo::~ScBlockUndo()
200 DeleteSdrUndoAction( pDrawUndo );
203 void ScBlockUndo::BeginUndo()
205 ScSimpleUndo::BeginUndo();
206 EnableDrawAdjust( pDocShell->GetDocument(), false );
209 void ScBlockUndo::EndUndo()
211 if (eMode == SC_UNDO_AUTOHEIGHT)
212 AdjustHeight();
214 EnableDrawAdjust( pDocShell->GetDocument(), sal_True );
215 DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() );
217 ShowBlock();
218 ScSimpleUndo::EndUndo();
221 void ScBlockUndo::EndRedo()
223 if (eMode == SC_UNDO_AUTOHEIGHT)
224 AdjustHeight();
226 ShowBlock();
227 ScSimpleUndo::EndRedo();
230 sal_Bool ScBlockUndo::AdjustHeight()
232 ScDocument* pDoc = pDocShell->GetDocument();
234 VirtualDevice aVirtDev;
235 Fraction aZoomX( 1, 1 );
236 Fraction aZoomY = aZoomX;
237 double nPPTX, nPPTY;
238 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
239 if (pViewShell)
241 ScViewData* pData = pViewShell->GetViewData();
242 nPPTX = pData->GetPPTX();
243 nPPTY = pData->GetPPTY();
244 aZoomX = pData->GetZoomX();
245 aZoomY = pData->GetZoomY();
247 else
249 // Leave zoom at 100
250 nPPTX = ScGlobal::nScreenPPTX;
251 nPPTY = ScGlobal::nScreenPPTY;
254 sal_Bool bRet = pDoc->SetOptimalHeight( aBlockRange.aStart.Row(), aBlockRange.aEnd.Row(),
255 /*!*/ aBlockRange.aStart.Tab(), 0, &aVirtDev,
256 nPPTX, nPPTY, aZoomX, aZoomY, false );
258 if (bRet)
259 pDocShell->PostPaint( 0, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(),
260 MAXCOL, MAXROW, aBlockRange.aEnd.Tab(),
261 PAINT_GRID | PAINT_LEFT );
263 return bRet;
266 void ScBlockUndo::ShowBlock()
268 if ( IsPaintLocked() )
269 return;
271 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
272 if (pViewShell)
274 ShowTable( aBlockRange ); // with multiple sheets in range each of them is good
275 pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
276 SC_FOLLOW_JUMP, false, false );
277 SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
278 ScRange aRange = aBlockRange;
279 aRange.aStart.SetTab( nTab );
280 aRange.aEnd.SetTab( nTab );
281 pViewShell->MarkRange( aRange );
283 // not through SetMarkArea to MarkData, due to possibly lacking paint
287 ScMultiBlockUndo::ScMultiBlockUndo(
288 ScDocShell* pDocSh, const ScRangeList& rRanges, ScBlockUndoMode eBlockMode) :
289 ScSimpleUndo(pDocSh),
290 maBlockRanges(rRanges),
291 meMode(eBlockMode)
293 mpDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
296 ScMultiBlockUndo::~ScMultiBlockUndo()
298 DeleteSdrUndoAction( mpDrawUndo );
301 void ScMultiBlockUndo::BeginUndo()
303 ScSimpleUndo::BeginUndo();
304 EnableDrawAdjust(pDocShell->GetDocument(), false);
307 void ScMultiBlockUndo::EndUndo()
309 if (meMode == SC_UNDO_AUTOHEIGHT)
310 AdjustHeight();
312 EnableDrawAdjust(pDocShell->GetDocument(), true);
313 DoSdrUndoAction(mpDrawUndo, pDocShell->GetDocument());
315 ShowBlock();
316 ScSimpleUndo::EndUndo();
319 void ScMultiBlockUndo::EndRedo()
321 if (meMode == SC_UNDO_AUTOHEIGHT)
322 AdjustHeight();
324 ShowBlock();
325 ScSimpleUndo::EndRedo();
328 void ScMultiBlockUndo::AdjustHeight()
330 ScDocument* pDoc = pDocShell->GetDocument();
332 VirtualDevice aVirtDev;
333 Fraction aZoomX( 1, 1 );
334 Fraction aZoomY = aZoomX;
335 double nPPTX, nPPTY;
336 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
337 if (pViewShell)
339 ScViewData* pData = pViewShell->GetViewData();
340 nPPTX = pData->GetPPTX();
341 nPPTY = pData->GetPPTY();
342 aZoomX = pData->GetZoomX();
343 aZoomY = pData->GetZoomY();
345 else
347 // Leave zoom at 100
348 nPPTX = ScGlobal::nScreenPPTX;
349 nPPTY = ScGlobal::nScreenPPTY;
352 for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
354 const ScRange& r = *maBlockRanges[i];
355 bool bRet = pDoc->SetOptimalHeight(
356 r.aStart.Row(), r.aEnd.Row(), r.aStart.Tab(), 0, &aVirtDev,
357 nPPTX, nPPTY, aZoomX, aZoomY, false);
359 if (bRet)
360 pDocShell->PostPaint(
361 0, r.aStart.Row(), r.aStart.Tab(), MAXCOL, MAXROW, r.aEnd.Tab(),
362 PAINT_GRID | PAINT_LEFT);
366 void ScMultiBlockUndo::ShowBlock()
368 if ( IsPaintLocked() )
369 return;
371 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
372 if (!pViewShell)
373 return;
375 if (maBlockRanges.empty())
376 return;
378 // Move to the sheet of the first range.
379 ScRange aRange = *maBlockRanges.front();
380 ShowTable(aRange);
381 pViewShell->MoveCursorAbs(
382 aRange.aStart.Col(), aRange.aStart.Row(), SC_FOLLOW_JUMP, false, false);
383 SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
384 aRange.aStart.SetTab(nTab);
385 aRange.aEnd.SetTab(nTab);
386 pViewShell->MarkRange(aRange, false, false);
388 for (size_t i = 1, n = maBlockRanges.size(); i < n; ++i)
390 aRange = *maBlockRanges[i];
391 aRange.aStart.SetTab(nTab);
392 aRange.aEnd.SetTab(nTab);
393 pViewShell->MarkRange(aRange, false, true);
397 ScMoveUndo::ScMoveUndo( ScDocShell* pDocSh, ScDocument* pRefDoc, ScRefUndoData* pRefData,
398 ScMoveUndoMode eRefMode ) :
399 ScSimpleUndo( pDocSh ),
400 pRefUndoDoc( pRefDoc ),
401 pRefUndoData( pRefData ),
402 eMode( eRefMode )
404 ScDocument* pDoc = pDocShell->GetDocument();
405 if (pRefUndoData)
406 pRefUndoData->DeleteUnchanged(pDoc);
407 pDrawUndo = GetSdrUndoAction( pDoc );
410 ScMoveUndo::~ScMoveUndo()
412 delete pRefUndoData;
413 delete pRefUndoDoc;
414 DeleteSdrUndoAction( pDrawUndo );
417 void ScMoveUndo::UndoRef()
419 ScDocument* pDoc = pDocShell->GetDocument();
420 ScRange aRange(0,0,0, MAXCOL,MAXROW,pRefUndoDoc->GetTableCount()-1);
421 pRefUndoDoc->CopyToDocument( aRange, IDF_FORMULA, false, pDoc, NULL, false );
422 if (pRefUndoData)
423 pRefUndoData->DoUndo( pDoc, (eMode == SC_UNDO_REFFIRST) );
424 // HACK: ScDragDropUndo is the only one with REFFIRST.
425 // If not, results possibly in a too frequent adjustment
426 // of ChartRefs. Not that pretty, but not too bad either..
429 void ScMoveUndo::BeginUndo()
431 ScSimpleUndo::BeginUndo();
433 EnableDrawAdjust( pDocShell->GetDocument(), false );
435 if (pRefUndoDoc && eMode == SC_UNDO_REFFIRST)
436 UndoRef();
439 void ScMoveUndo::EndUndo()
441 DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); // must also be called when pointer is null
443 if (pRefUndoDoc && eMode == SC_UNDO_REFLAST)
444 UndoRef();
446 EnableDrawAdjust( pDocShell->GetDocument(), sal_True );
448 ScSimpleUndo::EndUndo();
451 ScDBFuncUndo::ScDBFuncUndo( ScDocShell* pDocSh, const ScRange& rOriginal, SdrUndoAction* pDrawUndo ) :
452 ScSimpleUndo( pDocSh ),
453 aOriginalRange( rOriginal ),
454 mpDrawUndo( pDrawUndo )
456 pAutoDBRange = pDocSh->GetOldAutoDBRange();
459 ScDBFuncUndo::~ScDBFuncUndo()
461 DeleteSdrUndoAction( mpDrawUndo );
462 delete pAutoDBRange;
465 void ScDBFuncUndo::SetDrawUndoAction( SdrUndoAction* pDrawUndo )
467 DeleteSdrUndoAction( mpDrawUndo );
468 mpDrawUndo = pDrawUndo;
471 void ScDBFuncUndo::BeginUndo()
473 ScSimpleUndo::BeginUndo();
474 DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() );
477 void ScDBFuncUndo::EndUndo()
479 ScSimpleUndo::EndUndo();
481 if ( pAutoDBRange )
483 ScDocument* pDoc = pDocShell->GetDocument();
484 SCTAB nTab = pDoc->GetVisibleTab();
485 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
486 if (pNoNameData )
488 SCCOL nRangeX1;
489 SCROW nRangeY1;
490 SCCOL nRangeX2;
491 SCROW nRangeY2;
492 SCTAB nRangeTab;
493 pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
494 pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
496 *pNoNameData = *pAutoDBRange;
498 if ( pAutoDBRange->HasAutoFilter() )
500 // restore AutoFilter buttons
501 pAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
502 pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO );
503 pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID );
509 void ScDBFuncUndo::BeginRedo()
511 RedoSdrUndoAction( mpDrawUndo );
512 if ( pAutoDBRange )
514 // move the database range to this function's position again (see ScDocShell::GetDBData)
516 ScDocument* pDoc = pDocShell->GetDocument();
517 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(aOriginalRange.aStart.Tab());
518 if ( pNoNameData )
521 SCCOL nRangeX1;
522 SCROW nRangeY1;
523 SCCOL nRangeX2;
524 SCROW nRangeY2;
525 SCTAB nRangeTab;
526 pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
527 pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
529 pNoNameData->SetSortParam( ScSortParam() );
530 pNoNameData->SetQueryParam( ScQueryParam() );
531 pNoNameData->SetSubTotalParam( ScSubTotalParam() );
533 pNoNameData->SetArea( aOriginalRange.aStart.Tab(),
534 aOriginalRange.aStart.Col(), aOriginalRange.aStart.Row(),
535 aOriginalRange.aEnd.Col(), aOriginalRange.aEnd.Row() );
537 pNoNameData->SetByRow( sal_True );
538 pNoNameData->SetAutoFilter( false );
539 // header is always set with the operation in redo
543 ScSimpleUndo::BeginRedo();
546 void ScDBFuncUndo::EndRedo()
548 ScSimpleUndo::EndRedo();
551 ScUndoWrapper::ScUndoWrapper( SfxUndoAction* pUndo ) :
552 pWrappedUndo( pUndo )
556 ScUndoWrapper::~ScUndoWrapper()
558 delete pWrappedUndo;
561 void ScUndoWrapper::ForgetWrappedUndo()
563 pWrappedUndo = NULL; // don't delete in dtor - pointer must be stored outside
566 OUString ScUndoWrapper::GetComment() const
568 if (pWrappedUndo)
569 return pWrappedUndo->GetComment();
570 return OUString();
573 OUString ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const
575 if (pWrappedUndo)
576 return pWrappedUndo->GetRepeatComment(rTarget);
577 return OUString();
580 sal_uInt16 ScUndoWrapper::GetId() const
582 if (pWrappedUndo)
583 return pWrappedUndo->GetId();
584 else
585 return 0;
588 void ScUndoWrapper::SetLinkToSfxLinkUndoAction(SfxLinkUndoAction* pSfxLinkUndoAction)
590 if (pWrappedUndo)
591 pWrappedUndo->SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction);
592 else
593 SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction);
596 bool ScUndoWrapper::Merge( SfxUndoAction* pNextAction )
598 if (pWrappedUndo)
599 return pWrappedUndo->Merge(pNextAction);
600 else
601 return false;
604 void ScUndoWrapper::Undo()
606 if (pWrappedUndo)
607 pWrappedUndo->Undo();
610 void ScUndoWrapper::Redo()
612 if (pWrappedUndo)
613 pWrappedUndo->Redo();
616 void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget)
618 if (pWrappedUndo)
619 pWrappedUndo->Repeat(rTarget);
622 bool ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const
624 if (pWrappedUndo)
625 return pWrappedUndo->CanRepeat(rTarget);
626 else
627 return false;
630 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */