fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / undo / undobase.cxx
bloba383eed17f2fbd5545081a8c91d04069837da17e
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 "bcaslot.hxx"
33 #include "globstr.hrc"
34 #include <rowheightcontext.hxx>
35 #include <column.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 ) :
46 pDocShell( pDocSh ),
47 pDetectiveUndo( NULL )
51 ScSimpleUndo::~ScSimpleUndo()
53 delete pDetectiveUndo;
56 bool ScSimpleUndo::SetViewMarkData( const ScMarkData& rMarkData )
58 if ( IsPaintLocked() )
59 return false;
61 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
62 if ( !pViewShell )
63 return false;
65 pViewShell->SetMarkData( rMarkData );
66 return true;
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();
86 return true;
89 return false;
92 void ScSimpleUndo::BeginUndo()
94 pDocShell->SetInUndo( true );
96 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
97 if (pViewShell)
98 pViewShell->HideAllCursors(); // for example due to merged cells
100 // detective updates happened last, must be undone first
101 if (pDetectiveUndo)
102 pDetectiveUndo->Undo();
105 void ScSimpleUndo::EndUndo()
107 pDocShell->SetDocumentModified();
109 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
110 if (pViewShell)
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();
125 if (pViewShell)
126 pViewShell->HideAllCursors(); // for example due to merged cells
129 void ScSimpleUndo::EndRedo()
131 if (pDetectiveUndo)
132 pDetectiveUndo->Redo();
134 pDocShell->SetDocumentModified();
136 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
137 if (pViewShell)
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);
153 namespace {
155 class SpanBroadcaster : public sc::ColumnSpanSet::ColumnAction
157 ScDocument& mrDoc;
158 SCTAB mnCurTab;
159 SCCOL mnCurCol;
161 public:
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
172 if (!bVal)
173 return;
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();
198 if (pViewShell)
199 pViewShell->SetTabNo( nTab );
202 void ScSimpleUndo::ShowTable( const ScRange& rRange )
204 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
205 if (pViewShell)
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 ),
219 eMode( eBlockMode )
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)
238 AdjustHeight();
240 EnableDrawAdjust( &pDocShell->GetDocument(), true );
241 DoSdrUndoAction( pDrawUndo, &pDocShell->GetDocument() );
243 ShowBlock();
244 ScSimpleUndo::EndUndo();
247 void ScBlockUndo::EndRedo()
249 if (eMode == SC_UNDO_AUTOHEIGHT)
250 AdjustHeight();
252 ShowBlock();
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;
263 double nPPTX, nPPTY;
264 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
265 if (pViewShell)
267 ScViewData& rData = pViewShell->GetViewData();
268 nPPTX = rData.GetPPTX();
269 nPPTY = rData.GetPPTY();
270 aZoomX = rData.GetZoomX();
271 aZoomY = rData.GetZoomY();
273 else
275 // Leave zoom at 100
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());
284 if (bRet)
285 pDocShell->PostPaint( 0, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(),
286 MAXCOL, MAXROW, aBlockRange.aEnd.Tab(),
287 PAINT_GRID | PAINT_LEFT );
289 return bRet;
292 void ScBlockUndo::ShowBlock()
294 if ( IsPaintLocked() )
295 return;
297 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
298 if (pViewShell)
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),
317 meMode(eBlockMode)
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)
336 AdjustHeight();
338 EnableDrawAdjust(&pDocShell->GetDocument(), true);
339 DoSdrUndoAction(mpDrawUndo, &pDocShell->GetDocument());
341 ShowBlock();
342 ScSimpleUndo::EndUndo();
345 void ScMultiBlockUndo::EndRedo()
347 if (meMode == SC_UNDO_AUTOHEIGHT)
348 AdjustHeight();
350 ShowBlock();
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;
361 double nPPTX, nPPTY;
362 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
363 if (pViewShell)
365 ScViewData& rData = pViewShell->GetViewData();
366 nPPTX = rData.GetPPTX();
367 nPPTY = rData.GetPPTY();
368 aZoomX = rData.GetZoomX();
369 aZoomY = rData.GetZoomY();
371 else
373 // Leave zoom at 100
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());
384 if (bRet)
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() )
394 return;
396 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
397 if (!pViewShell)
398 return;
400 if (maBlockRanges.empty())
401 return;
403 // Move to the sheet of the first range.
404 ScRange aRange = *maBlockRanges.front();
405 ShowTable(aRange);
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 ),
427 eMode( eRefMode )
429 ScDocument& rDoc = pDocShell->GetDocument();
430 if (pRefUndoData)
431 pRefUndoData->DeleteUnchanged(&rDoc);
432 pDrawUndo = GetSdrUndoAction( &rDoc );
435 ScMoveUndo::~ScMoveUndo()
437 delete pRefUndoData;
438 delete pRefUndoDoc;
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 );
447 if (pRefUndoData)
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)
461 UndoRef();
464 void ScMoveUndo::EndUndo()
466 DoSdrUndoAction( pDrawUndo, &pDocShell->GetDocument() ); // must also be called when pointer is null
468 if (pRefUndoDoc && eMode == SC_UNDO_REFLAST)
469 UndoRef();
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 );
487 delete pAutoDBRange;
490 void ScDBFuncUndo::BeginUndo()
492 ScSimpleUndo::BeginUndo();
493 DoSdrUndoAction( mpDrawUndo, &pDocShell->GetDocument() );
496 void ScDBFuncUndo::EndUndo()
498 ScSimpleUndo::EndUndo();
500 if ( pAutoDBRange )
502 ScDocument& rDoc = pDocShell->GetDocument();
503 SCTAB nTab = rDoc.GetVisibleTab();
504 ScDBData* pNoNameData = rDoc.GetAnonymousDBData(nTab);
505 if (pNoNameData )
507 SCCOL nRangeX1;
508 SCROW nRangeY1;
509 SCCOL nRangeX2;
510 SCROW nRangeY2;
511 SCTAB nRangeTab;
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 );
531 if ( pAutoDBRange )
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());
537 if ( pNoNameData )
540 SCCOL nRangeX1;
541 SCROW nRangeY1;
542 SCCOL nRangeX2;
543 SCROW nRangeY2;
544 SCTAB nRangeTab;
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()
577 delete pWrappedUndo;
580 void ScUndoWrapper::ForgetWrappedUndo()
582 pWrappedUndo = NULL; // don't delete in dtor - pointer must be stored outside
585 OUString ScUndoWrapper::GetComment() const
587 if (pWrappedUndo)
588 return pWrappedUndo->GetComment();
589 return OUString();
592 OUString ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const
594 if (pWrappedUndo)
595 return pWrappedUndo->GetRepeatComment(rTarget);
596 return OUString();
599 sal_uInt16 ScUndoWrapper::GetId() const
601 if (pWrappedUndo)
602 return pWrappedUndo->GetId();
603 else
604 return 0;
607 void ScUndoWrapper::SetLinkToSfxLinkUndoAction(SfxLinkUndoAction* pSfxLinkUndoAction)
609 if (pWrappedUndo)
610 pWrappedUndo->SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction);
611 else
612 SetLinkToSfxLinkUndoAction(pSfxLinkUndoAction);
615 bool ScUndoWrapper::Merge( SfxUndoAction* pNextAction )
617 if (pWrappedUndo)
618 return pWrappedUndo->Merge(pNextAction);
619 else
620 return false;
623 void ScUndoWrapper::Undo()
625 if (pWrappedUndo)
626 pWrappedUndo->Undo();
629 void ScUndoWrapper::Redo()
631 if (pWrappedUndo)
632 pWrappedUndo->Redo();
635 void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget)
637 if (pWrappedUndo)
638 pWrappedUndo->Repeat(rTarget);
641 bool ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const
643 if (pWrappedUndo)
644 return pWrappedUndo->CanRepeat(rTarget);
645 else
646 return false;
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */