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 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::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
)
155 for (SCCOL nCol
= rRange
.aStart
.Col(); nCol
<= rRange
.aEnd
.Col(); ++nCol
)
158 for (SCROW nRow
= rRange
.aStart
.Row(); nRow
<= rRange
.aEnd
.Row(); ++nRow
)
161 pDoc
->Broadcast(aHint
);
166 pDoc
->BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED
));
169 void ScSimpleUndo::ShowTable( SCTAB nTab
)
171 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
173 pViewShell
->SetTabNo( nTab
);
176 void ScSimpleUndo::ShowTable( const ScRange
& rRange
)
178 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
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
),
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
)
214 EnableDrawAdjust( pDocShell
->GetDocument(), sal_True
);
215 DoSdrUndoAction( pDrawUndo
, pDocShell
->GetDocument() );
218 ScSimpleUndo::EndUndo();
221 void ScBlockUndo::EndRedo()
223 if (eMode
== SC_UNDO_AUTOHEIGHT
)
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
;
238 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
241 ScViewData
* pData
= pViewShell
->GetViewData();
242 nPPTX
= pData
->GetPPTX();
243 nPPTY
= pData
->GetPPTY();
244 aZoomX
= pData
->GetZoomX();
245 aZoomY
= pData
->GetZoomY();
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 );
259 pDocShell
->PostPaint( 0, aBlockRange
.aStart
.Row(), aBlockRange
.aStart
.Tab(),
260 MAXCOL
, MAXROW
, aBlockRange
.aEnd
.Tab(),
261 PAINT_GRID
| PAINT_LEFT
);
266 void ScBlockUndo::ShowBlock()
268 if ( IsPaintLocked() )
271 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
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
),
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
)
312 EnableDrawAdjust(pDocShell
->GetDocument(), true);
313 DoSdrUndoAction(mpDrawUndo
, pDocShell
->GetDocument());
316 ScSimpleUndo::EndUndo();
319 void ScMultiBlockUndo::EndRedo()
321 if (meMode
== SC_UNDO_AUTOHEIGHT
)
325 ScSimpleUndo::EndRedo();
328 void ScMultiBlockUndo::AdjustHeight()
330 ScDocument
* pDoc
= pDocShell
->GetDocument();
332 VirtualDevice aVirtDev
;
333 Fraction
aZoomX( 1, 1 );
334 Fraction aZoomY
= aZoomX
;
336 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
339 ScViewData
* pData
= pViewShell
->GetViewData();
340 nPPTX
= pData
->GetPPTX();
341 nPPTY
= pData
->GetPPTY();
342 aZoomX
= pData
->GetZoomX();
343 aZoomY
= pData
->GetZoomY();
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);
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() )
371 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
375 if (maBlockRanges
.empty())
378 // Move to the sheet of the first range.
379 ScRange aRange
= *maBlockRanges
.front();
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
),
404 ScDocument
* pDoc
= pDocShell
->GetDocument();
406 pRefUndoData
->DeleteUnchanged(pDoc
);
407 pDrawUndo
= GetSdrUndoAction( pDoc
);
410 ScMoveUndo::~ScMoveUndo()
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 );
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
)
439 void ScMoveUndo::EndUndo()
441 DoSdrUndoAction( pDrawUndo
, pDocShell
->GetDocument() ); // must also be called when pointer is null
443 if (pRefUndoDoc
&& eMode
== SC_UNDO_REFLAST
)
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
);
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();
483 ScDocument
* pDoc
= pDocShell
->GetDocument();
484 SCTAB nTab
= pDoc
->GetVisibleTab();
485 ScDBData
* pNoNameData
= pDoc
->GetAnonymousDBData(nTab
);
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
);
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());
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()
561 void ScUndoWrapper::ForgetWrappedUndo()
563 pWrappedUndo
= NULL
; // don't delete in dtor - pointer must be stored outside
566 OUString
ScUndoWrapper::GetComment() const
569 return pWrappedUndo
->GetComment();
573 OUString
ScUndoWrapper::GetRepeatComment(SfxRepeatTarget
& rTarget
) const
576 return pWrappedUndo
->GetRepeatComment(rTarget
);
580 sal_uInt16
ScUndoWrapper::GetId() const
583 return pWrappedUndo
->GetId();
588 void ScUndoWrapper::SetLinkToSfxLinkUndoAction(SfxLinkUndoAction
* pSfxLinkUndoAction
)
591 pWrappedUndo
->SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction
);
593 SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction
);
596 bool ScUndoWrapper::Merge( SfxUndoAction
* pNextAction
)
599 return pWrappedUndo
->Merge(pNextAction
);
604 void ScUndoWrapper::Undo()
607 pWrappedUndo
->Undo();
610 void ScUndoWrapper::Redo()
613 pWrappedUndo
->Redo();
616 void ScUndoWrapper::Repeat(SfxRepeatTarget
& rTarget
)
619 pWrappedUndo
->Repeat(rTarget
);
622 bool ScUndoWrapper::CanRepeat(SfxRepeatTarget
& rTarget
) const
625 return pWrappedUndo
->CanRepeat(rTarget
);
630 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */