bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / undo / undobase.cxx
blob299d1a7c9ddc9b810a740e26145ccf2133f415be
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 sal_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::ShowTable( SCTAB nTab )
147 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
148 if (pViewShell)
149 pViewShell->SetTabNo( nTab );
152 void ScSimpleUndo::ShowTable( const ScRange& rRange )
154 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
155 if (pViewShell)
157 SCTAB nStart = rRange.aStart.Tab();
158 SCTAB nEnd = rRange.aEnd.Tab();
159 SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
160 if ( nTab < nStart || nTab > nEnd ) // if not in range:
161 pViewShell->SetTabNo( nStart ); // at beginning of the range
165 ScBlockUndo::ScBlockUndo( ScDocShell* pDocSh, const ScRange& rRange,
166 ScBlockUndoMode eBlockMode ) :
167 ScSimpleUndo( pDocSh ),
168 aBlockRange( rRange ),
169 eMode( eBlockMode )
171 pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
174 ScBlockUndo::~ScBlockUndo()
176 DeleteSdrUndoAction( pDrawUndo );
179 void ScBlockUndo::BeginUndo()
181 ScSimpleUndo::BeginUndo();
182 EnableDrawAdjust( pDocShell->GetDocument(), false );
185 void ScBlockUndo::EndUndo()
187 if (eMode == SC_UNDO_AUTOHEIGHT)
188 AdjustHeight();
190 EnableDrawAdjust( pDocShell->GetDocument(), sal_True );
191 DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() );
193 ShowBlock();
194 ScSimpleUndo::EndUndo();
197 void ScBlockUndo::EndRedo()
199 if (eMode == SC_UNDO_AUTOHEIGHT)
200 AdjustHeight();
202 ShowBlock();
203 ScSimpleUndo::EndRedo();
206 sal_Bool ScBlockUndo::AdjustHeight()
208 ScDocument* pDoc = pDocShell->GetDocument();
210 VirtualDevice aVirtDev;
211 Fraction aZoomX( 1, 1 );
212 Fraction aZoomY = aZoomX;
213 double nPPTX, nPPTY;
214 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
215 if (pViewShell)
217 ScViewData* pData = pViewShell->GetViewData();
218 nPPTX = pData->GetPPTX();
219 nPPTY = pData->GetPPTY();
220 aZoomX = pData->GetZoomX();
221 aZoomY = pData->GetZoomY();
223 else
225 // Leave zoom at 100
226 nPPTX = ScGlobal::nScreenPPTX;
227 nPPTY = ScGlobal::nScreenPPTY;
230 sal_Bool bRet = pDoc->SetOptimalHeight( aBlockRange.aStart.Row(), aBlockRange.aEnd.Row(),
231 /*!*/ aBlockRange.aStart.Tab(), 0, &aVirtDev,
232 nPPTX, nPPTY, aZoomX, aZoomY, false );
234 if (bRet)
235 pDocShell->PostPaint( 0, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(),
236 MAXCOL, MAXROW, aBlockRange.aEnd.Tab(),
237 PAINT_GRID | PAINT_LEFT );
239 return bRet;
242 void ScBlockUndo::ShowBlock()
244 if ( IsPaintLocked() )
245 return;
247 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
248 if (pViewShell)
250 ShowTable( aBlockRange ); // with multiple sheets in range each of them is good
251 pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
252 SC_FOLLOW_JUMP, false, false );
253 SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
254 ScRange aRange = aBlockRange;
255 aRange.aStart.SetTab( nTab );
256 aRange.aEnd.SetTab( nTab );
257 pViewShell->MarkRange( aRange );
259 // not through SetMarkArea to MarkData, due to possibly lacking paint
263 ScMultiBlockUndo::ScMultiBlockUndo(
264 ScDocShell* pDocSh, const ScRangeList& rRanges, ScBlockUndoMode eBlockMode) :
265 ScSimpleUndo(pDocSh),
266 maBlockRanges(rRanges),
267 meMode(eBlockMode)
269 mpDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
272 ScMultiBlockUndo::~ScMultiBlockUndo()
274 DeleteSdrUndoAction( mpDrawUndo );
277 void ScMultiBlockUndo::BeginUndo()
279 ScSimpleUndo::BeginUndo();
280 EnableDrawAdjust(pDocShell->GetDocument(), false);
283 void ScMultiBlockUndo::EndUndo()
285 if (meMode == SC_UNDO_AUTOHEIGHT)
286 AdjustHeight();
288 EnableDrawAdjust(pDocShell->GetDocument(), true);
289 DoSdrUndoAction(mpDrawUndo, pDocShell->GetDocument());
291 ShowBlock();
292 ScSimpleUndo::EndUndo();
295 void ScMultiBlockUndo::EndRedo()
297 if (meMode == SC_UNDO_AUTOHEIGHT)
298 AdjustHeight();
300 ShowBlock();
301 ScSimpleUndo::EndRedo();
304 void ScMultiBlockUndo::AdjustHeight()
306 ScDocument* pDoc = pDocShell->GetDocument();
308 VirtualDevice aVirtDev;
309 Fraction aZoomX( 1, 1 );
310 Fraction aZoomY = aZoomX;
311 double nPPTX, nPPTY;
312 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
313 if (pViewShell)
315 ScViewData* pData = pViewShell->GetViewData();
316 nPPTX = pData->GetPPTX();
317 nPPTY = pData->GetPPTY();
318 aZoomX = pData->GetZoomX();
319 aZoomY = pData->GetZoomY();
321 else
323 // Leave zoom at 100
324 nPPTX = ScGlobal::nScreenPPTX;
325 nPPTY = ScGlobal::nScreenPPTY;
328 for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
330 const ScRange& r = *maBlockRanges[i];
331 bool bRet = pDoc->SetOptimalHeight(
332 r.aStart.Row(), r.aEnd.Row(), r.aStart.Tab(), 0, &aVirtDev,
333 nPPTX, nPPTY, aZoomX, aZoomY, false);
335 if (bRet)
336 pDocShell->PostPaint(
337 0, r.aStart.Row(), r.aStart.Tab(), MAXCOL, MAXROW, r.aEnd.Tab(),
338 PAINT_GRID | PAINT_LEFT);
342 void ScMultiBlockUndo::ShowBlock()
344 if ( IsPaintLocked() )
345 return;
347 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
348 if (!pViewShell)
349 return;
351 if (maBlockRanges.empty())
352 return;
354 // Move to the sheet of the first range.
355 ScRange aRange = *maBlockRanges.front();
356 ShowTable(aRange);
357 pViewShell->MoveCursorAbs(
358 aRange.aStart.Col(), aRange.aStart.Row(), SC_FOLLOW_JUMP, false, false);
359 SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
360 aRange.aStart.SetTab(nTab);
361 aRange.aEnd.SetTab(nTab);
362 pViewShell->MarkRange(aRange, false, false);
364 for (size_t i = 1, n = maBlockRanges.size(); i < n; ++i)
366 aRange = *maBlockRanges[i];
367 aRange.aStart.SetTab(nTab);
368 aRange.aEnd.SetTab(nTab);
369 pViewShell->MarkRange(aRange, false, true);
373 ScMoveUndo::ScMoveUndo( ScDocShell* pDocSh, ScDocument* pRefDoc, ScRefUndoData* pRefData,
374 ScMoveUndoMode eRefMode ) :
375 ScSimpleUndo( pDocSh ),
376 pRefUndoDoc( pRefDoc ),
377 pRefUndoData( pRefData ),
378 eMode( eRefMode )
380 ScDocument* pDoc = pDocShell->GetDocument();
381 if (pRefUndoData)
382 pRefUndoData->DeleteUnchanged(pDoc);
383 pDrawUndo = GetSdrUndoAction( pDoc );
386 ScMoveUndo::~ScMoveUndo()
388 delete pRefUndoData;
389 delete pRefUndoDoc;
390 DeleteSdrUndoAction( pDrawUndo );
393 void ScMoveUndo::UndoRef()
395 ScDocument* pDoc = pDocShell->GetDocument();
396 ScRange aRange(0,0,0, MAXCOL,MAXROW,pRefUndoDoc->GetTableCount()-1);
397 pRefUndoDoc->CopyToDocument( aRange, IDF_FORMULA, false, pDoc, NULL, false );
398 if (pRefUndoData)
399 pRefUndoData->DoUndo( pDoc, (eMode == SC_UNDO_REFFIRST) );
400 // HACK: ScDragDropUndo is the only one with REFFIRST.
401 // If not, results possibly in a too frequent adjustment
402 // of ChartRefs. Not that pretty, but not too bad either..
405 void ScMoveUndo::BeginUndo()
407 ScSimpleUndo::BeginUndo();
409 EnableDrawAdjust( pDocShell->GetDocument(), false );
411 if (pRefUndoDoc && eMode == SC_UNDO_REFFIRST)
412 UndoRef();
415 void ScMoveUndo::EndUndo()
417 DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); // must also be called when pointer is null
419 if (pRefUndoDoc && eMode == SC_UNDO_REFLAST)
420 UndoRef();
422 EnableDrawAdjust( pDocShell->GetDocument(), sal_True );
424 ScSimpleUndo::EndUndo();
427 ScDBFuncUndo::ScDBFuncUndo( ScDocShell* pDocSh, const ScRange& rOriginal, SdrUndoAction* pDrawUndo ) :
428 ScSimpleUndo( pDocSh ),
429 aOriginalRange( rOriginal ),
430 mpDrawUndo( pDrawUndo )
432 pAutoDBRange = pDocSh->GetOldAutoDBRange();
435 ScDBFuncUndo::~ScDBFuncUndo()
437 DeleteSdrUndoAction( mpDrawUndo );
438 delete pAutoDBRange;
441 void ScDBFuncUndo::SetDrawUndoAction( SdrUndoAction* pDrawUndo )
443 DeleteSdrUndoAction( mpDrawUndo );
444 mpDrawUndo = pDrawUndo;
447 void ScDBFuncUndo::BeginUndo()
449 ScSimpleUndo::BeginUndo();
450 DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() );
453 void ScDBFuncUndo::EndUndo()
455 ScSimpleUndo::EndUndo();
457 if ( pAutoDBRange )
459 ScDocument* pDoc = pDocShell->GetDocument();
460 SCTAB nTab = pDoc->GetVisibleTab();
461 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
462 if (pNoNameData )
464 SCCOL nRangeX1;
465 SCROW nRangeY1;
466 SCCOL nRangeX2;
467 SCROW nRangeY2;
468 SCTAB nRangeTab;
469 pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
470 pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
472 *pNoNameData = *pAutoDBRange;
474 if ( pAutoDBRange->HasAutoFilter() )
476 // restore AutoFilter buttons
477 pAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
478 pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO );
479 pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID );
485 void ScDBFuncUndo::BeginRedo()
487 RedoSdrUndoAction( mpDrawUndo );
488 if ( pAutoDBRange )
490 // move the database range to this function's position again (see ScDocShell::GetDBData)
492 ScDocument* pDoc = pDocShell->GetDocument();
493 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(aOriginalRange.aStart.Tab());
494 if ( pNoNameData )
497 SCCOL nRangeX1;
498 SCROW nRangeY1;
499 SCCOL nRangeX2;
500 SCROW nRangeY2;
501 SCTAB nRangeTab;
502 pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
503 pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
505 pNoNameData->SetSortParam( ScSortParam() );
506 pNoNameData->SetQueryParam( ScQueryParam() );
507 pNoNameData->SetSubTotalParam( ScSubTotalParam() );
509 pNoNameData->SetArea( aOriginalRange.aStart.Tab(),
510 aOriginalRange.aStart.Col(), aOriginalRange.aStart.Row(),
511 aOriginalRange.aEnd.Col(), aOriginalRange.aEnd.Row() );
513 pNoNameData->SetByRow( sal_True );
514 pNoNameData->SetAutoFilter( false );
515 // header is always set with the operation in redo
519 ScSimpleUndo::BeginRedo();
522 void ScDBFuncUndo::EndRedo()
524 ScSimpleUndo::EndRedo();
527 ScUndoWrapper::ScUndoWrapper( SfxUndoAction* pUndo ) :
528 pWrappedUndo( pUndo )
532 ScUndoWrapper::~ScUndoWrapper()
534 delete pWrappedUndo;
537 void ScUndoWrapper::ForgetWrappedUndo()
539 pWrappedUndo = NULL; // don't delete in dtor - pointer must be stored outside
542 OUString ScUndoWrapper::GetComment() const
544 if (pWrappedUndo)
545 return pWrappedUndo->GetComment();
546 return OUString();
549 OUString ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const
551 if (pWrappedUndo)
552 return pWrappedUndo->GetRepeatComment(rTarget);
553 return OUString();
556 sal_uInt16 ScUndoWrapper::GetId() const
558 if (pWrappedUndo)
559 return pWrappedUndo->GetId();
560 else
561 return 0;
564 sal_Bool ScUndoWrapper::IsLinked()
566 if (pWrappedUndo)
567 return pWrappedUndo->IsLinked();
568 else
569 return false;
572 void ScUndoWrapper::SetLinked( sal_Bool bIsLinked )
574 if (pWrappedUndo)
575 pWrappedUndo->SetLinked(bIsLinked);
578 sal_Bool ScUndoWrapper::Merge( SfxUndoAction* pNextAction )
580 if (pWrappedUndo)
581 return pWrappedUndo->Merge(pNextAction);
582 else
583 return false;
586 void ScUndoWrapper::Undo()
588 if (pWrappedUndo)
589 pWrappedUndo->Undo();
592 void ScUndoWrapper::Redo()
594 if (pWrappedUndo)
595 pWrappedUndo->Redo();
598 void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget)
600 if (pWrappedUndo)
601 pWrappedUndo->Repeat(rTarget);
604 sal_Bool ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const
606 if (pWrappedUndo)
607 return pWrappedUndo->CanRepeat(rTarget);
608 else
609 return false;
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */