1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
25 #include "tabvwsh.hxx"
26 #include "undoolk.hxx"
27 #include "undodraw.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
) :
45 pDetectiveUndo( NULL
)
49 ScSimpleUndo::~ScSimpleUndo()
51 delete pDetectiveUndo
;
54 bool ScSimpleUndo::SetViewMarkData( const ScMarkData
& rMarkData
)
56 if ( IsPaintLocked() )
59 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
63 pViewShell
->SetMarkData( rMarkData
);
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();
90 void ScSimpleUndo::BeginUndo()
92 pDocShell
->SetInUndo( sal_True
);
94 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
96 pViewShell
->HideAllCursors(); // for example due to merged cells
98 // detective updates happened last, must be undone first
100 pDetectiveUndo
->Undo();
103 void ScSimpleUndo::EndUndo()
105 pDocShell
->SetDocumentModified();
107 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
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();
124 pViewShell
->HideAllCursors(); // for example due to merged cells
127 void ScSimpleUndo::EndRedo()
130 pDetectiveUndo
->Redo();
132 pDocShell
->SetDocumentModified();
134 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
137 pViewShell
->UpdateAutoFillMark();
138 pViewShell
->UpdateInputHandler();
139 pViewShell
->ShowAllCursors();
142 pDocShell
->SetInUndo( false );
145 void ScSimpleUndo::ShowTable( SCTAB nTab
)
147 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
149 pViewShell
->SetTabNo( nTab
);
152 void ScSimpleUndo::ShowTable( const ScRange
& rRange
)
154 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
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
),
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
)
190 EnableDrawAdjust( pDocShell
->GetDocument(), sal_True
);
191 DoSdrUndoAction( pDrawUndo
, pDocShell
->GetDocument() );
194 ScSimpleUndo::EndUndo();
197 void ScBlockUndo::EndRedo()
199 if (eMode
== SC_UNDO_AUTOHEIGHT
)
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
;
214 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
217 ScViewData
* pData
= pViewShell
->GetViewData();
218 nPPTX
= pData
->GetPPTX();
219 nPPTY
= pData
->GetPPTY();
220 aZoomX
= pData
->GetZoomX();
221 aZoomY
= pData
->GetZoomY();
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 );
235 pDocShell
->PostPaint( 0, aBlockRange
.aStart
.Row(), aBlockRange
.aStart
.Tab(),
236 MAXCOL
, MAXROW
, aBlockRange
.aEnd
.Tab(),
237 PAINT_GRID
| PAINT_LEFT
);
242 void ScBlockUndo::ShowBlock()
244 if ( IsPaintLocked() )
247 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
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
),
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
)
288 EnableDrawAdjust(pDocShell
->GetDocument(), true);
289 DoSdrUndoAction(mpDrawUndo
, pDocShell
->GetDocument());
292 ScSimpleUndo::EndUndo();
295 void ScMultiBlockUndo::EndRedo()
297 if (meMode
== SC_UNDO_AUTOHEIGHT
)
301 ScSimpleUndo::EndRedo();
304 void ScMultiBlockUndo::AdjustHeight()
306 ScDocument
* pDoc
= pDocShell
->GetDocument();
308 VirtualDevice aVirtDev
;
309 Fraction
aZoomX( 1, 1 );
310 Fraction aZoomY
= aZoomX
;
312 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
315 ScViewData
* pData
= pViewShell
->GetViewData();
316 nPPTX
= pData
->GetPPTX();
317 nPPTY
= pData
->GetPPTY();
318 aZoomX
= pData
->GetZoomX();
319 aZoomY
= pData
->GetZoomY();
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);
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() )
347 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
351 if (maBlockRanges
.empty())
354 // Move to the sheet of the first range.
355 ScRange aRange
= *maBlockRanges
.front();
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
),
380 ScDocument
* pDoc
= pDocShell
->GetDocument();
382 pRefUndoData
->DeleteUnchanged(pDoc
);
383 pDrawUndo
= GetSdrUndoAction( pDoc
);
386 ScMoveUndo::~ScMoveUndo()
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 );
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
)
415 void ScMoveUndo::EndUndo()
417 DoSdrUndoAction( pDrawUndo
, pDocShell
->GetDocument() ); // must also be called when pointer is null
419 if (pRefUndoDoc
&& eMode
== SC_UNDO_REFLAST
)
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
);
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();
459 ScDocument
* pDoc
= pDocShell
->GetDocument();
460 SCTAB nTab
= pDoc
->GetVisibleTab();
461 ScDBData
* pNoNameData
= pDoc
->GetAnonymousDBData(nTab
);
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
);
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());
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()
537 void ScUndoWrapper::ForgetWrappedUndo()
539 pWrappedUndo
= NULL
; // don't delete in dtor - pointer must be stored outside
542 OUString
ScUndoWrapper::GetComment() const
545 return pWrappedUndo
->GetComment();
549 OUString
ScUndoWrapper::GetRepeatComment(SfxRepeatTarget
& rTarget
) const
552 return pWrappedUndo
->GetRepeatComment(rTarget
);
556 sal_uInt16
ScUndoWrapper::GetId() const
559 return pWrappedUndo
->GetId();
564 sal_Bool
ScUndoWrapper::IsLinked()
567 return pWrappedUndo
->IsLinked();
572 void ScUndoWrapper::SetLinked( sal_Bool bIsLinked
)
575 pWrappedUndo
->SetLinked(bIsLinked
);
578 sal_Bool
ScUndoWrapper::Merge( SfxUndoAction
* pNextAction
)
581 return pWrappedUndo
->Merge(pNextAction
);
586 void ScUndoWrapper::Undo()
589 pWrappedUndo
->Undo();
592 void ScUndoWrapper::Redo()
595 pWrappedUndo
->Redo();
598 void ScUndoWrapper::Repeat(SfxRepeatTarget
& rTarget
)
601 pWrappedUndo
->Repeat(rTarget
);
604 sal_Bool
ScUndoWrapper::CanRepeat(SfxRepeatTarget
& rTarget
) const
607 return pWrappedUndo
->CanRepeat(rTarget
);
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */