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 "bcaslot.hxx"
33 #include "globstr.hrc"
34 #include <rowheightcontext.hxx>
36 #include <sortparam.hxx>
38 TYPEINIT1(ScSimpleUndo
, SfxUndoAction
);
39 TYPEINIT1(ScBlockUndo
, ScSimpleUndo
);
40 TYPEINIT1(ScMultiBlockUndo
, ScSimpleUndo
);
41 TYPEINIT1(ScMoveUndo
, ScSimpleUndo
);
42 TYPEINIT1(ScDBFuncUndo
, ScSimpleUndo
);
43 TYPEINIT1(ScUndoWrapper
, SfxUndoAction
);
45 ScSimpleUndo::ScSimpleUndo( ScDocShell
* pDocSh
) :
47 pDetectiveUndo( NULL
)
51 ScSimpleUndo::~ScSimpleUndo()
53 delete pDetectiveUndo
;
56 bool ScSimpleUndo::SetViewMarkData( const ScMarkData
& rMarkData
)
58 if ( IsPaintLocked() )
61 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
65 pViewShell
->SetMarkData( rMarkData
);
69 bool ScSimpleUndo::Merge( SfxUndoAction
*pNextAction
)
71 // A SdrUndoGroup for updating detective arrows can belong
72 // to each Undo-Action.
73 // DetectiveRefresh is always called next,
74 // the SdrUndoGroup is encapsulated in a ScUndoDraw action.
75 // AddUndoAction is only called with bTryMerg=sal_True
76 // for automatic update.
78 if ( !pDetectiveUndo
&& pNextAction
->ISA(ScUndoDraw
) )
80 // Take SdrUndoAction from ScUndoDraw Action,
81 // ScUndoDraw is later deleted by the UndoManager
83 ScUndoDraw
* pCalcUndo
= static_cast<ScUndoDraw
*>(pNextAction
);
84 pDetectiveUndo
= pCalcUndo
->GetDrawUndo();
85 pCalcUndo
->ForgetDrawUndo();
92 void ScSimpleUndo::BeginUndo()
94 pDocShell
->SetInUndo( true );
96 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
98 pViewShell
->HideAllCursors(); // for example due to merged cells
100 // detective updates happened last, must be undone first
102 pDetectiveUndo
->Undo();
105 void ScSimpleUndo::EndUndo()
107 pDocShell
->SetDocumentModified();
109 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
112 pViewShell
->UpdateAutoFillMark();
113 pViewShell
->UpdateInputHandler();
114 pViewShell
->ShowAllCursors();
117 pDocShell
->SetInUndo( false );
120 void ScSimpleUndo::BeginRedo()
122 pDocShell
->SetInUndo( true ); //! own Flag for Redo?
124 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
126 pViewShell
->HideAllCursors(); // for example due to merged cells
129 void ScSimpleUndo::EndRedo()
132 pDetectiveUndo
->Redo();
134 pDocShell
->SetDocumentModified();
136 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
139 pViewShell
->UpdateAutoFillMark();
140 pViewShell
->UpdateInputHandler();
141 pViewShell
->ShowAllCursors();
144 pDocShell
->SetInUndo( false );
147 void ScSimpleUndo::BroadcastChanges( const ScRange
& rRange
)
149 ScDocument
& rDoc
= pDocShell
->GetDocument();
150 rDoc
.BroadcastCells(rRange
, SC_HINT_DATACHANGED
);
155 class SpanBroadcaster
: public sc::ColumnSpanSet::ColumnAction
162 SpanBroadcaster( ScDocument
& rDoc
) : mrDoc(rDoc
), mnCurTab(-1), mnCurCol(-1) {}
164 virtual void startColumn( ScColumn
* pCol
) SAL_OVERRIDE
166 mnCurTab
= pCol
->GetTab();
167 mnCurCol
= pCol
->GetCol();
170 virtual void execute( SCROW nRow1
, SCROW nRow2
, bool bVal
) SAL_OVERRIDE
175 ScRange
aRange(mnCurCol
, nRow1
, mnCurTab
, mnCurCol
, nRow2
, mnCurTab
);
176 mrDoc
.BroadcastCells(aRange
, SC_HINT_DATACHANGED
);
182 void ScSimpleUndo::BroadcastChanges( const DataSpansType
& rSpans
)
184 ScDocument
& rDoc
= pDocShell
->GetDocument();
185 SpanBroadcaster
aBroadcaster(rDoc
);
187 DataSpansType::const_iterator it
= rSpans
.begin(), itEnd
= rSpans
.end();
188 for (; it
!= itEnd
; ++it
)
190 const sc::ColumnSpanSet
& rSet
= *it
->second
;
191 rSet
.executeColumnAction(rDoc
, aBroadcaster
);
195 void ScSimpleUndo::ShowTable( SCTAB nTab
)
197 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
199 pViewShell
->SetTabNo( nTab
);
202 void ScSimpleUndo::ShowTable( const ScRange
& rRange
)
204 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
207 SCTAB nStart
= rRange
.aStart
.Tab();
208 SCTAB nEnd
= rRange
.aEnd
.Tab();
209 SCTAB nTab
= pViewShell
->GetViewData().GetTabNo();
210 if ( nTab
< nStart
|| nTab
> nEnd
) // if not in range:
211 pViewShell
->SetTabNo( nStart
); // at beginning of the range
215 ScBlockUndo::ScBlockUndo( ScDocShell
* pDocSh
, const ScRange
& rRange
,
216 ScBlockUndoMode eBlockMode
) :
217 ScSimpleUndo( pDocSh
),
218 aBlockRange( rRange
),
221 pDrawUndo
= GetSdrUndoAction( &pDocShell
->GetDocument() );
224 ScBlockUndo::~ScBlockUndo()
226 DeleteSdrUndoAction( pDrawUndo
);
229 void ScBlockUndo::BeginUndo()
231 ScSimpleUndo::BeginUndo();
232 EnableDrawAdjust( &pDocShell
->GetDocument(), false );
235 void ScBlockUndo::EndUndo()
237 if (eMode
== SC_UNDO_AUTOHEIGHT
)
240 EnableDrawAdjust( &pDocShell
->GetDocument(), true );
241 DoSdrUndoAction( pDrawUndo
, &pDocShell
->GetDocument() );
244 ScSimpleUndo::EndUndo();
247 void ScBlockUndo::EndRedo()
249 if (eMode
== SC_UNDO_AUTOHEIGHT
)
253 ScSimpleUndo::EndRedo();
256 bool ScBlockUndo::AdjustHeight()
258 ScDocument
& rDoc
= pDocShell
->GetDocument();
260 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
261 Fraction
aZoomX( 1, 1 );
262 Fraction aZoomY
= aZoomX
;
264 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
267 ScViewData
& rData
= pViewShell
->GetViewData();
268 nPPTX
= rData
.GetPPTX();
269 nPPTY
= rData
.GetPPTY();
270 aZoomX
= rData
.GetZoomX();
271 aZoomY
= rData
.GetZoomY();
276 nPPTX
= ScGlobal::nScreenPPTX
;
277 nPPTY
= ScGlobal::nScreenPPTY
;
280 sc::RowHeightContext
aCxt(nPPTX
, nPPTY
, aZoomX
, aZoomY
, pVirtDev
);
281 bool bRet
= rDoc
.SetOptimalHeight(
282 aCxt
, aBlockRange
.aStart
.Row(), aBlockRange
.aEnd
.Row(), aBlockRange
.aStart
.Tab());
285 pDocShell
->PostPaint( 0, aBlockRange
.aStart
.Row(), aBlockRange
.aStart
.Tab(),
286 MAXCOL
, MAXROW
, aBlockRange
.aEnd
.Tab(),
287 PAINT_GRID
| PAINT_LEFT
);
292 void ScBlockUndo::ShowBlock()
294 if ( IsPaintLocked() )
297 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
300 ShowTable( aBlockRange
); // with multiple sheets in range each of them is good
301 pViewShell
->MoveCursorAbs( aBlockRange
.aStart
.Col(), aBlockRange
.aStart
.Row(),
302 SC_FOLLOW_JUMP
, false, false );
303 SCTAB nTab
= pViewShell
->GetViewData().GetTabNo();
304 ScRange aRange
= aBlockRange
;
305 aRange
.aStart
.SetTab( nTab
);
306 aRange
.aEnd
.SetTab( nTab
);
307 pViewShell
->MarkRange( aRange
);
309 // not through SetMarkArea to MarkData, due to possibly lacking paint
313 ScMultiBlockUndo::ScMultiBlockUndo(
314 ScDocShell
* pDocSh
, const ScRangeList
& rRanges
, ScBlockUndoMode eBlockMode
) :
315 ScSimpleUndo(pDocSh
),
316 maBlockRanges(rRanges
),
319 mpDrawUndo
= GetSdrUndoAction( &pDocShell
->GetDocument() );
322 ScMultiBlockUndo::~ScMultiBlockUndo()
324 DeleteSdrUndoAction( mpDrawUndo
);
327 void ScMultiBlockUndo::BeginUndo()
329 ScSimpleUndo::BeginUndo();
330 EnableDrawAdjust(&pDocShell
->GetDocument(), false);
333 void ScMultiBlockUndo::EndUndo()
335 if (meMode
== SC_UNDO_AUTOHEIGHT
)
338 EnableDrawAdjust(&pDocShell
->GetDocument(), true);
339 DoSdrUndoAction(mpDrawUndo
, &pDocShell
->GetDocument());
342 ScSimpleUndo::EndUndo();
345 void ScMultiBlockUndo::EndRedo()
347 if (meMode
== SC_UNDO_AUTOHEIGHT
)
351 ScSimpleUndo::EndRedo();
354 void ScMultiBlockUndo::AdjustHeight()
356 ScDocument
& rDoc
= pDocShell
->GetDocument();
358 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
359 Fraction
aZoomX( 1, 1 );
360 Fraction aZoomY
= aZoomX
;
362 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
365 ScViewData
& rData
= pViewShell
->GetViewData();
366 nPPTX
= rData
.GetPPTX();
367 nPPTY
= rData
.GetPPTY();
368 aZoomX
= rData
.GetZoomX();
369 aZoomY
= rData
.GetZoomY();
374 nPPTX
= ScGlobal::nScreenPPTX
;
375 nPPTY
= ScGlobal::nScreenPPTY
;
378 sc::RowHeightContext
aCxt(nPPTX
, nPPTY
, aZoomX
, aZoomY
, pVirtDev
);
379 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
381 const ScRange
& r
= *maBlockRanges
[i
];
382 bool bRet
= rDoc
.SetOptimalHeight(aCxt
, r
.aStart
.Row(), r
.aEnd
.Row(), r
.aStart
.Tab());
385 pDocShell
->PostPaint(
386 0, r
.aStart
.Row(), r
.aStart
.Tab(), MAXCOL
, MAXROW
, r
.aEnd
.Tab(),
387 PAINT_GRID
| PAINT_LEFT
);
391 void ScMultiBlockUndo::ShowBlock()
393 if ( IsPaintLocked() )
396 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
400 if (maBlockRanges
.empty())
403 // Move to the sheet of the first range.
404 ScRange aRange
= *maBlockRanges
.front();
406 pViewShell
->MoveCursorAbs(
407 aRange
.aStart
.Col(), aRange
.aStart
.Row(), SC_FOLLOW_JUMP
, false, false);
408 SCTAB nTab
= pViewShell
->GetViewData().GetTabNo();
409 aRange
.aStart
.SetTab(nTab
);
410 aRange
.aEnd
.SetTab(nTab
);
411 pViewShell
->MarkRange(aRange
, false, false);
413 for (size_t i
= 1, n
= maBlockRanges
.size(); i
< n
; ++i
)
415 aRange
= *maBlockRanges
[i
];
416 aRange
.aStart
.SetTab(nTab
);
417 aRange
.aEnd
.SetTab(nTab
);
418 pViewShell
->MarkRange(aRange
, false, true);
422 ScMoveUndo::ScMoveUndo( ScDocShell
* pDocSh
, ScDocument
* pRefDoc
, ScRefUndoData
* pRefData
,
423 ScMoveUndoMode eRefMode
) :
424 ScSimpleUndo( pDocSh
),
425 pRefUndoDoc( pRefDoc
),
426 pRefUndoData( pRefData
),
429 ScDocument
& rDoc
= pDocShell
->GetDocument();
431 pRefUndoData
->DeleteUnchanged(&rDoc
);
432 pDrawUndo
= GetSdrUndoAction( &rDoc
);
435 ScMoveUndo::~ScMoveUndo()
439 DeleteSdrUndoAction( pDrawUndo
);
442 void ScMoveUndo::UndoRef()
444 ScDocument
& rDoc
= pDocShell
->GetDocument();
445 ScRange
aRange(0,0,0, MAXCOL
,MAXROW
,pRefUndoDoc
->GetTableCount()-1);
446 pRefUndoDoc
->CopyToDocument( aRange
, IDF_FORMULA
, false, &rDoc
, NULL
, false );
448 pRefUndoData
->DoUndo( &rDoc
, (eMode
== SC_UNDO_REFFIRST
) );
449 // HACK: ScDragDropUndo is the only one with REFFIRST.
450 // If not, results possibly in a too frequent adjustment
451 // of ChartRefs. Not that pretty, but not too bad either..
454 void ScMoveUndo::BeginUndo()
456 ScSimpleUndo::BeginUndo();
458 EnableDrawAdjust( &pDocShell
->GetDocument(), false );
460 if (pRefUndoDoc
&& eMode
== SC_UNDO_REFFIRST
)
464 void ScMoveUndo::EndUndo()
466 DoSdrUndoAction( pDrawUndo
, &pDocShell
->GetDocument() ); // must also be called when pointer is null
468 if (pRefUndoDoc
&& eMode
== SC_UNDO_REFLAST
)
471 EnableDrawAdjust( &pDocShell
->GetDocument(), true );
473 ScSimpleUndo::EndUndo();
476 ScDBFuncUndo::ScDBFuncUndo( ScDocShell
* pDocSh
, const ScRange
& rOriginal
, SdrUndoAction
* pDrawUndo
) :
477 ScSimpleUndo( pDocSh
),
478 aOriginalRange( rOriginal
),
479 mpDrawUndo( pDrawUndo
)
481 pAutoDBRange
= pDocSh
->GetOldAutoDBRange();
484 ScDBFuncUndo::~ScDBFuncUndo()
486 DeleteSdrUndoAction( mpDrawUndo
);
490 void ScDBFuncUndo::BeginUndo()
492 ScSimpleUndo::BeginUndo();
493 DoSdrUndoAction( mpDrawUndo
, &pDocShell
->GetDocument() );
496 void ScDBFuncUndo::EndUndo()
498 ScSimpleUndo::EndUndo();
502 ScDocument
& rDoc
= pDocShell
->GetDocument();
503 SCTAB nTab
= rDoc
.GetVisibleTab();
504 ScDBData
* pNoNameData
= rDoc
.GetAnonymousDBData(nTab
);
512 pNoNameData
->GetArea( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
513 pDocShell
->DBAreaDeleted( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
515 *pNoNameData
= *pAutoDBRange
;
517 if ( pAutoDBRange
->HasAutoFilter() )
519 // restore AutoFilter buttons
520 pAutoDBRange
->GetArea( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
521 rDoc
.ApplyFlagsTab( nRangeX1
, nRangeY1
, nRangeX2
, nRangeY1
, nRangeTab
, SC_MF_AUTO
);
522 pDocShell
->PostPaint( nRangeX1
, nRangeY1
, nRangeTab
, nRangeX2
, nRangeY1
, nRangeTab
, PAINT_GRID
);
528 void ScDBFuncUndo::BeginRedo()
530 RedoSdrUndoAction( mpDrawUndo
);
533 // move the database range to this function's position again (see ScDocShell::GetDBData)
535 ScDocument
& rDoc
= pDocShell
->GetDocument();
536 ScDBData
* pNoNameData
= rDoc
.GetAnonymousDBData(aOriginalRange
.aStart
.Tab());
545 pNoNameData
->GetArea( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
546 pDocShell
->DBAreaDeleted( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
548 pNoNameData
->SetSortParam( ScSortParam() );
549 pNoNameData
->SetQueryParam( ScQueryParam() );
550 pNoNameData
->SetSubTotalParam( ScSubTotalParam() );
552 pNoNameData
->SetArea( aOriginalRange
.aStart
.Tab(),
553 aOriginalRange
.aStart
.Col(), aOriginalRange
.aStart
.Row(),
554 aOriginalRange
.aEnd
.Col(), aOriginalRange
.aEnd
.Row() );
556 pNoNameData
->SetByRow( true );
557 pNoNameData
->SetAutoFilter( false );
558 // header is always set with the operation in redo
562 ScSimpleUndo::BeginRedo();
565 void ScDBFuncUndo::EndRedo()
567 ScSimpleUndo::EndRedo();
570 ScUndoWrapper::ScUndoWrapper( SfxUndoAction
* pUndo
) :
571 pWrappedUndo( pUndo
)
575 ScUndoWrapper::~ScUndoWrapper()
580 void ScUndoWrapper::ForgetWrappedUndo()
582 pWrappedUndo
= NULL
; // don't delete in dtor - pointer must be stored outside
585 OUString
ScUndoWrapper::GetComment() const
588 return pWrappedUndo
->GetComment();
592 OUString
ScUndoWrapper::GetRepeatComment(SfxRepeatTarget
& rTarget
) const
595 return pWrappedUndo
->GetRepeatComment(rTarget
);
599 sal_uInt16
ScUndoWrapper::GetId() const
602 return pWrappedUndo
->GetId();
607 void ScUndoWrapper::SetLinkToSfxLinkUndoAction(SfxLinkUndoAction
* pSfxLinkUndoAction
)
610 pWrappedUndo
->SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction
);
612 SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction
);
615 bool ScUndoWrapper::Merge( SfxUndoAction
* pNextAction
)
618 return pWrappedUndo
->Merge(pNextAction
);
623 void ScUndoWrapper::Undo()
626 pWrappedUndo
->Undo();
629 void ScUndoWrapper::Redo()
632 pWrappedUndo
->Redo();
635 void ScUndoWrapper::Repeat(SfxRepeatTarget
& rTarget
)
638 pWrappedUndo
->Repeat(rTarget
);
641 bool ScUndoWrapper::CanRepeat(SfxRepeatTarget
& rTarget
) const
644 return pWrappedUndo
->CanRepeat(rTarget
);
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */