summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/undo/undocell.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/undo/undocell.cxx')
-rw-r--r--sc/source/ui/undo/undocell.cxx1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx
new file mode 100644
index 000000000..8323cd824
--- /dev/null
+++ b/sc/source/ui/undo/undocell.cxx
@@ -0,0 +1,1048 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <undocell.hxx>
+
+#include <scitems.hxx>
+#include <editeng/editobj.hxx>
+#include <sfx2/app.hxx>
+#include <comphelper/lok.hxx>
+#include <osl/diagnose.h>
+
+#include <document.hxx>
+#include <docpool.hxx>
+#include <patattr.hxx>
+#include <docsh.hxx>
+#include <tabvwsh.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <global.hxx>
+#include <formulacell.hxx>
+#include <target.hxx>
+#include <undoolk.hxx>
+#include <detdata.hxx>
+#include <stlpool.hxx>
+#include <printfun.hxx>
+#include <rangenam.hxx>
+#include <chgtrack.hxx>
+#include <stringutil.hxx>
+
+namespace HelperNotifyChanges
+{
+ static void NotifyIfChangesListeners(const ScDocShell& rDocShell, const ScAddress &rPos,
+ const ScUndoEnterData::ValuesType &rOldValues)
+ {
+ if (ScModelObj* pModelObj = getMustPropagateChangesModel(rDocShell))
+ {
+ ScRangeList aChangeRanges;
+
+ for (const auto & rOldValue : rOldValues)
+ {
+ aChangeRanges.push_back( ScRange(rPos.Col(), rPos.Row(), rOldValue.mnTab));
+ }
+
+ Notify(*pModelObj, aChangeRanges, "cell-change");
+ }
+ }
+}
+
+
+ScUndoCursorAttr::ScUndoCursorAttr( ScDocShell* pNewDocShell,
+ SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
+ const ScPatternAttr* pOldPat, const ScPatternAttr* pNewPat,
+ const ScPatternAttr* pApplyPat ) :
+ ScSimpleUndo( pNewDocShell ),
+ nCol( nNewCol ),
+ nRow( nNewRow ),
+ nTab( nNewTab ),
+ pOldEditData( static_cast<EditTextObject*>(nullptr) ),
+ pNewEditData( static_cast<EditTextObject*>(nullptr) )
+{
+ ScDocumentPool* pPool = pDocShell->GetDocument().GetPool();
+ pNewPattern = const_cast<ScPatternAttr*>( &pPool->Put( *pNewPat ) );
+ pOldPattern = const_cast<ScPatternAttr*>( &pPool->Put( *pOldPat ) );
+ pApplyPattern = const_cast<ScPatternAttr*>( &pPool->Put( *pApplyPat ) );
+}
+
+ScUndoCursorAttr::~ScUndoCursorAttr()
+{
+ ScDocumentPool* pPool = pDocShell->GetDocument().GetPool();
+ pPool->Remove(*pNewPattern);
+ pPool->Remove(*pOldPattern);
+ pPool->Remove(*pApplyPattern);
+}
+
+OUString ScUndoCursorAttr::GetComment() const
+{
+ //! own text for automatic attribution
+ return ScResId( STR_UNDO_CURSORATTR ); // "Attribute"
+}
+
+void ScUndoCursorAttr::SetEditData( std::unique_ptr<EditTextObject> pOld, std::unique_ptr<EditTextObject> pNew )
+{
+ pOldEditData = std::move(pOld);
+ pNewEditData = std::move(pNew);
+}
+
+void ScUndoCursorAttr::DoChange( const ScPatternAttr* pWhichPattern, const std::unique_ptr<EditTextObject>& pEditData ) const
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScAddress aPos(nCol, nRow, nTab);
+ rDoc.SetPattern( nCol, nRow, nTab, *pWhichPattern );
+
+ if (rDoc.GetCellType(aPos) == CELLTYPE_EDIT && pEditData)
+ rDoc.SetEditText(aPos, *pEditData, nullptr);
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+ {
+ pViewShell->SetTabNo( nTab );
+ pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
+ pViewShell->AdjustBlockHeight();
+ }
+
+ const SfxItemSet& rApplySet = pApplyPattern->GetItemSet();
+ bool bPaintExt = ( rApplySet.GetItemState( ATTR_SHADOW ) != SfxItemState::DEFAULT ||
+ rApplySet.GetItemState( ATTR_CONDITIONAL ) != SfxItemState::DEFAULT );
+ bool bPaintRows = ( rApplySet.GetItemState( ATTR_HOR_JUSTIFY ) != SfxItemState::DEFAULT );
+
+ sal_uInt16 nFlags = SC_PF_TESTMERGE;
+ if (bPaintExt)
+ nFlags |= SC_PF_LINES;
+ if (bPaintRows)
+ nFlags |= SC_PF_WHOLEROWS;
+ pDocShell->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PaintPartFlags::Grid, nFlags );
+}
+
+void ScUndoCursorAttr::Undo()
+{
+ BeginUndo();
+ DoChange(pOldPattern, pOldEditData);
+ EndUndo();
+}
+
+void ScUndoCursorAttr::Redo()
+{
+ BeginRedo();
+ DoChange(pNewPattern, pNewEditData);
+ EndRedo();
+}
+
+void ScUndoCursorAttr::Repeat(SfxRepeatTarget& rTarget)
+{
+ if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
+ pViewTarget->GetViewShell()->ApplySelectionPattern( *pApplyPattern );
+}
+
+bool ScUndoCursorAttr::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+ return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
+}
+
+ScUndoEnterData::Value::Value() : mnTab(-1), mbHasFormat(false), mnFormat(0) {}
+
+ScUndoEnterData::ScUndoEnterData(
+ ScDocShell* pNewDocShell, const ScAddress& rPos, ValuesType& rOldValues,
+ const OUString& rNewStr, std::unique_ptr<EditTextObject> pObj ) :
+ ScSimpleUndo( pNewDocShell ),
+ maNewString(rNewStr),
+ mpNewEditData(std::move(pObj)),
+ mnEndChangeAction(0),
+ maPos(rPos)
+{
+ maOldValues.swap(rOldValues);
+
+ SetChangeTrack();
+}
+
+OUString ScUndoEnterData::GetComment() const
+{
+ return ScResId( STR_UNDO_ENTERDATA ); // "Input"
+}
+
+void ScUndoEnterData::DoChange() const
+{
+ // only when needed (old or new Edit cell, or Attribute)?
+ bool bHeightChanged = false;
+ for (const auto & i : maOldValues)
+ {
+ if (pDocShell->AdjustRowHeight(maPos.Row(), maPos.Row(), i.mnTab))
+ bHeightChanged = true;
+ }
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+ {
+ if (comphelper::LibreOfficeKit::isActive() && bHeightChanged)
+ {
+ ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell, ROW_HEADER, maPos.Tab());
+ ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+ pViewShell, false /* bColumns */, true /* bRows */, true /* bSizes*/,
+ false /* bHidden */, false /* bFiltered */, false /* bGroups */, maPos.Tab());
+ }
+ pViewShell->SetTabNo(maPos.Tab());
+ pViewShell->MoveCursorAbs(maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false);
+ }
+
+ pDocShell->PostDataChanged();
+}
+
+void ScUndoEnterData::SetChangeTrack()
+{
+ ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
+ if ( pChangeTrack )
+ {
+ mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
+ ScAddress aPos(maPos);
+ for (const Value & rOldValue : maOldValues)
+ {
+ aPos.SetTab(rOldValue.mnTab);
+ sal_uLong nFormat = 0;
+ if (rOldValue.mbHasFormat)
+ nFormat = rOldValue.mnFormat;
+ pChangeTrack->AppendContent(aPos, rOldValue.maCell, nFormat);
+ }
+ if ( mnEndChangeAction > pChangeTrack->GetActionMax() )
+ mnEndChangeAction = 0; // nothing is appended
+ }
+ else
+ mnEndChangeAction = 0;
+}
+
+void ScUndoEnterData::Undo()
+{
+ BeginUndo();
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ for (const Value & rVal : maOldValues)
+ {
+ ScCellValue aNewCell;
+ aNewCell.assign(rVal.maCell, rDoc, ScCloneFlags::StartListening);
+ ScAddress aPos = maPos;
+ aPos.SetTab(rVal.mnTab);
+ aNewCell.release(rDoc, aPos);
+
+ if (rVal.mbHasFormat)
+ rDoc.ApplyAttr(maPos.Col(), maPos.Row(), rVal.mnTab,
+ SfxUInt32Item(ATTR_VALUE_FORMAT, rVal.mnFormat));
+ else
+ {
+ auto pPattern = std::make_unique<ScPatternAttr>(*rDoc.GetPattern(maPos.Col(), maPos.Row(), rVal.mnTab));
+ pPattern->GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
+ rDoc.SetPattern(maPos.Col(), maPos.Row(), rVal.mnTab, std::move(pPattern));
+ }
+ pDocShell->PostPaintCell(maPos.Col(), maPos.Row(), rVal.mnTab);
+ }
+
+ ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
+ size_t nCount = maOldValues.size();
+ if ( pChangeTrack && mnEndChangeAction >= sal::static_int_cast<sal_uLong>(nCount) )
+ pChangeTrack->Undo( mnEndChangeAction - nCount + 1, mnEndChangeAction );
+
+ DoChange();
+ EndUndo();
+
+ HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, maOldValues);
+}
+
+void ScUndoEnterData::Redo()
+{
+ BeginRedo();
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ for (const Value & rOldValue : maOldValues)
+ {
+ SCTAB nTab = rOldValue.mnTab;
+ if (mpNewEditData)
+ {
+ ScAddress aPos = maPos;
+ aPos.SetTab(nTab);
+ // edit text will be cloned.
+ rDoc.SetEditText(aPos, *mpNewEditData, nullptr);
+ }
+ else
+ rDoc.SetString(maPos.Col(), maPos.Row(), nTab, maNewString);
+
+ pDocShell->PostPaintCell(maPos.Col(), maPos.Row(), nTab);
+ }
+
+ SetChangeTrack();
+
+ DoChange();
+ EndRedo();
+
+ HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, maOldValues);
+}
+
+void ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget)
+{
+ if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
+ {
+ OUString aTemp = maNewString;
+ pViewTarget->GetViewShell()->EnterDataAtCursor( aTemp );
+ }
+}
+
+bool ScUndoEnterData::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+ return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
+}
+
+ScUndoEnterValue::ScUndoEnterValue(
+ ScDocShell* pNewDocShell, const ScAddress& rNewPos,
+ const ScCellValue& rUndoCell, double nVal ) :
+ ScSimpleUndo( pNewDocShell ),
+ aPos ( rNewPos ),
+ maOldCell(rUndoCell),
+ nValue ( nVal )
+{
+ SetChangeTrack();
+}
+
+ScUndoEnterValue::~ScUndoEnterValue()
+{
+}
+
+OUString ScUndoEnterValue::GetComment() const
+{
+ return ScResId( STR_UNDO_ENTERDATA ); // "Input"
+}
+
+void ScUndoEnterValue::SetChangeTrack()
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
+ if ( pChangeTrack )
+ {
+ nEndChangeAction = pChangeTrack->GetActionMax() + 1;
+ pChangeTrack->AppendContent(aPos, maOldCell);
+ if ( nEndChangeAction > pChangeTrack->GetActionMax() )
+ nEndChangeAction = 0; // nothing is appended
+ }
+ else
+ nEndChangeAction = 0;
+}
+
+void ScUndoEnterValue::Undo()
+{
+ BeginUndo();
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScCellValue aNewCell;
+ aNewCell.assign(maOldCell, rDoc, ScCloneFlags::StartListening);
+ aNewCell.release(rDoc, aPos);
+
+ pDocShell->PostPaintCell( aPos );
+
+ ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
+
+ EndUndo();
+}
+
+void ScUndoEnterValue::Redo()
+{
+ BeginRedo();
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.SetValue( aPos.Col(), aPos.Row(), aPos.Tab(), nValue );
+ pDocShell->PostPaintCell( aPos );
+
+ SetChangeTrack();
+
+ EndRedo();
+}
+
+void ScUndoEnterValue::Repeat(SfxRepeatTarget& /* rTarget */)
+{
+ // makes no sense
+}
+
+bool ScUndoEnterValue::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+{
+ return false;
+}
+
+ScUndoSetCell::ScUndoSetCell( ScDocShell* pDocSh, const ScAddress& rPos, const ScCellValue& rOldVal, const ScCellValue& rNewVal ) :
+ ScSimpleUndo(pDocSh), maPos(rPos), maOldValue(rOldVal), maNewValue(rNewVal), mnEndChangeAction(0)
+{
+ SetChangeTrack();
+}
+
+ScUndoSetCell::~ScUndoSetCell() {}
+
+void ScUndoSetCell::Undo()
+{
+ BeginUndo();
+ SetValue(maOldValue);
+ MoveCursorToCell();
+ pDocShell->PostPaintCell(maPos);
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
+ if (pChangeTrack)
+ pChangeTrack->Undo(mnEndChangeAction, mnEndChangeAction);
+
+ EndUndo();
+}
+
+void ScUndoSetCell::Redo()
+{
+ BeginRedo();
+ SetValue(maNewValue);
+ MoveCursorToCell();
+ pDocShell->PostPaintCell(maPos);
+ SetChangeTrack();
+ EndRedo();
+}
+
+void ScUndoSetCell::Repeat( SfxRepeatTarget& /*rTarget*/ )
+{
+ // Makes no sense.
+}
+
+bool ScUndoSetCell::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
+{
+ return false;
+}
+
+OUString ScUndoSetCell::GetComment() const
+{
+ return ScResId(STR_UNDO_ENTERDATA); // "Input"
+}
+
+void ScUndoSetCell::SetChangeTrack()
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
+ if (pChangeTrack)
+ {
+ mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
+
+ pChangeTrack->AppendContent(maPos, maOldValue);
+
+ if (mnEndChangeAction > pChangeTrack->GetActionMax())
+ mnEndChangeAction = 0; // Nothing is appended
+ }
+ else
+ mnEndChangeAction = 0;
+}
+
+void ScUndoSetCell::SetValue( const ScCellValue& rVal )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ switch (rVal.meType)
+ {
+ case CELLTYPE_NONE:
+ // empty cell
+ rDoc.SetEmptyCell(maPos);
+ break;
+ case CELLTYPE_VALUE:
+ rDoc.SetValue(maPos, rVal.mfValue);
+ break;
+ case CELLTYPE_STRING:
+ {
+ ScSetStringParam aParam;
+ aParam.setTextInput();
+ // Undo only cell content, without setting any number format.
+ aParam.meSetTextNumFormat = ScSetStringParam::Keep;
+ rDoc.SetString(maPos, rVal.mpString->getString(), &aParam);
+ }
+ break;
+ case CELLTYPE_EDIT:
+ rDoc.SetEditText(maPos, rVal.mpEditText->Clone());
+ break;
+ case CELLTYPE_FORMULA:
+ rDoc.SetFormulaCell(maPos, rVal.mpFormula->Clone());
+ break;
+ default:
+ ;
+ }
+}
+
+void ScUndoSetCell::MoveCursorToCell()
+{
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if ( pViewShell )
+ {
+ pViewShell->SetTabNo( maPos.Tab() );
+ pViewShell->MoveCursorAbs( maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false );
+ }
+}
+
+ScUndoPageBreak::ScUndoPageBreak( ScDocShell* pNewDocShell,
+ SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
+ bool bNewColumn, bool bNewInsert ) :
+ ScSimpleUndo( pNewDocShell ),
+ nCol( nNewCol ),
+ nRow( nNewRow ),
+ nTab( nNewTab ),
+ bColumn( bNewColumn ),
+ bInsert( bNewInsert )
+{
+}
+
+ScUndoPageBreak::~ScUndoPageBreak()
+{
+}
+
+OUString ScUndoPageBreak::GetComment() const
+{
+ //"Column break" | "Row break" "insert" | "delete"
+ return bColumn ?
+ ( bInsert ?
+ ScResId( STR_UNDO_INSCOLBREAK ) :
+ ScResId( STR_UNDO_DELCOLBREAK )
+ ) :
+ ( bInsert ?
+ ScResId( STR_UNDO_INSROWBREAK ) :
+ ScResId( STR_UNDO_DELROWBREAK )
+ );
+}
+
+void ScUndoPageBreak::DoChange( bool bInsertP ) const
+{
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
+ if (pViewShell)
+ {
+ pViewShell->SetTabNo( nTab );
+ pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
+
+ if (bInsertP)
+ pViewShell->InsertPageBreak(bColumn, false);
+ else
+ pViewShell->DeletePageBreak(bColumn, false);
+
+ pDocShell->GetDocument().InvalidatePageBreaks(nTab);
+ }
+}
+
+void ScUndoPageBreak::Undo()
+{
+ BeginUndo();
+ DoChange(!bInsert);
+ EndUndo();
+}
+
+void ScUndoPageBreak::Redo()
+{
+ BeginRedo();
+ DoChange(bInsert);
+ EndRedo();
+}
+
+void ScUndoPageBreak::Repeat(SfxRepeatTarget& rTarget)
+{
+ if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
+ {
+ ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
+
+ if (bInsert)
+ rViewShell.InsertPageBreak(bColumn);
+ else
+ rViewShell.DeletePageBreak(bColumn);
+ }
+}
+
+bool ScUndoPageBreak::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+ return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
+}
+
+ScUndoPrintZoom::ScUndoPrintZoom( ScDocShell* pNewDocShell,
+ SCTAB nT, sal_uInt16 nOS, sal_uInt16 nOP, sal_uInt16 nNS, sal_uInt16 nNP ) :
+ ScSimpleUndo( pNewDocShell ),
+ nTab( nT ),
+ nOldScale( nOS ),
+ nOldPages( nOP ),
+ nNewScale( nNS ),
+ nNewPages( nNP )
+{
+}
+
+ScUndoPrintZoom::~ScUndoPrintZoom()
+{
+}
+
+OUString ScUndoPrintZoom::GetComment() const
+{
+ return ScResId( STR_UNDO_PRINTSCALE );
+}
+
+void ScUndoPrintZoom::DoChange( bool bUndo )
+{
+ sal_uInt16 nScale = bUndo ? nOldScale : nNewScale;
+ sal_uInt16 nPages = bUndo ? nOldPages : nNewPages;
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ OUString aStyleName = rDoc.GetPageStyle( nTab );
+ ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
+ OSL_ENSURE( pStyleSheet, "PageStyle not found" );
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
+
+ ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ }
+}
+
+void ScUndoPrintZoom::Undo()
+{
+ BeginUndo();
+ DoChange(true);
+ EndUndo();
+}
+
+void ScUndoPrintZoom::Redo()
+{
+ BeginRedo();
+ DoChange(false);
+ EndRedo();
+}
+
+void ScUndoPrintZoom::Repeat(SfxRepeatTarget& rTarget)
+{
+ if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
+ {
+ ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
+ ScViewData& rViewData = rViewShell.GetViewData();
+ rViewData.GetDocShell()->SetPrintZoom( rViewData.GetTabNo(), nNewScale, nNewPages );
+ }
+}
+
+bool ScUndoPrintZoom::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+ return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
+}
+
+ScUndoThesaurus::ScUndoThesaurus(
+ ScDocShell* pNewDocShell, SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
+ const ScCellValue& rOldText, const ScCellValue& rNewText ) :
+ ScSimpleUndo( pNewDocShell ),
+ nCol( nNewCol ),
+ nRow( nNewRow ),
+ nTab( nNewTab ),
+ maOldText(rOldText),
+ maNewText(rNewText)
+{
+ SetChangeTrack(maOldText);
+}
+
+ScUndoThesaurus::~ScUndoThesaurus() {}
+
+OUString ScUndoThesaurus::GetComment() const
+{
+ return ScResId( STR_UNDO_THESAURUS ); // "Thesaurus"
+}
+
+void ScUndoThesaurus::SetChangeTrack( const ScCellValue& rOldCell )
+{
+ ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
+ if ( pChangeTrack )
+ {
+ nEndChangeAction = pChangeTrack->GetActionMax() + 1;
+ pChangeTrack->AppendContent(ScAddress(nCol, nRow, nTab), rOldCell);
+ if ( nEndChangeAction > pChangeTrack->GetActionMax() )
+ nEndChangeAction = 0; // nothing is appended
+ }
+ else
+ nEndChangeAction = 0;
+}
+
+void ScUndoThesaurus::DoChange( bool bUndo, const ScCellValue& rText )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+ {
+ pViewShell->SetTabNo( nTab );
+ pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
+ }
+
+ ScAddress aPos(nCol, nRow, nTab);
+ rText.commit(rDoc, aPos);
+ if (!bUndo)
+ SetChangeTrack(maOldText);
+
+ pDocShell->PostPaintCell( nCol, nRow, nTab );
+}
+
+void ScUndoThesaurus::Undo()
+{
+ BeginUndo();
+ DoChange(true, maOldText);
+ ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
+ EndUndo();
+}
+
+void ScUndoThesaurus::Redo()
+{
+ BeginRedo();
+ DoChange(false, maNewText);
+ EndRedo();
+}
+
+void ScUndoThesaurus::Repeat(SfxRepeatTarget& rTarget)
+{
+ if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
+ pViewTarget->GetViewShell()->DoThesaurus();
+}
+
+bool ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+ return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
+}
+
+
+ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
+ const ScNoteData& rNoteData, bool bInsert, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
+ ScSimpleUndo( &rDocShell ),
+ maPos( rPos ),
+ mpDrawUndo( std::move(pDrawUndo) )
+{
+ OSL_ENSURE( rNoteData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
+ if (bInsert)
+ {
+ maNewData = rNoteData;
+ maNewData.mxCaption.setNotOwner();
+ }
+ else
+ {
+ maOldData = rNoteData;
+ maOldData.mxCaption.setNotOwner();
+ }
+}
+
+ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
+ const ScNoteData& rOldData, const ScNoteData& rNewData, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
+ ScSimpleUndo( &rDocShell ),
+ maPos( rPos ),
+ maOldData( rOldData ),
+ maNewData( rNewData ),
+ mpDrawUndo( std::move(pDrawUndo) )
+{
+ OSL_ENSURE( maOldData.mxCaption || maNewData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
+ OSL_ENSURE( !maOldData.mxInitData && !maNewData.mxInitData, "ScUndoReplaceNote::ScUndoReplaceNote - unexpected uninitialized note" );
+ maOldData.mxCaption.setNotOwner();
+ maNewData.mxCaption.setNotOwner();
+}
+
+ScUndoReplaceNote::~ScUndoReplaceNote()
+{
+ mpDrawUndo.reset();
+}
+
+void ScUndoReplaceNote::Undo()
+{
+ BeginUndo();
+ DoSdrUndoAction( mpDrawUndo.get(), &pDocShell->GetDocument() );
+ /* Undo insert -> remove new note.
+ Undo remove -> insert old note.
+ Undo replace -> remove new note, insert old note. */
+ DoRemoveNote( maNewData );
+ DoInsertNote( maOldData );
+ pDocShell->PostPaintCell( maPos );
+ EndUndo();
+}
+
+void ScUndoReplaceNote::Redo()
+{
+ BeginRedo();
+ RedoSdrUndoAction( mpDrawUndo.get() );
+ /* Redo insert -> insert new note.
+ Redo remove -> remove old note.
+ Redo replace -> remove old note, insert new note. */
+ DoRemoveNote( maOldData );
+ DoInsertNote( maNewData );
+ pDocShell->PostPaintCell( maPos );
+ EndRedo();
+}
+
+void ScUndoReplaceNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
+{
+}
+
+bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
+{
+ return false;
+}
+
+OUString ScUndoReplaceNote::GetComment() const
+{
+ return ScResId( maNewData.mxCaption ?
+ (maOldData.mxCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
+}
+
+void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
+{
+ if( rNoteData.mxCaption )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ OSL_ENSURE( !rDoc.GetNote(maPos), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" );
+ ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false );
+ rDoc.SetNote( maPos, std::unique_ptr<ScPostIt>(pNote) );
+ ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Add, &rDoc, maPos, pNote);
+ }
+}
+
+void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData )
+{
+ if( !rNoteData.mxCaption )
+ return;
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ OSL_ENSURE( rDoc.GetNote(maPos), "ScUndoReplaceNote::DoRemoveNote - missing cell note" );
+ if( std::unique_ptr<ScPostIt> pNote = rDoc.ReleaseNote( maPos ) )
+ {
+ /* Forget pointer to caption object to suppress removing the
+ caption object from the drawing layer while deleting pNote
+ (removing the caption is done by a drawing undo action). */
+ pNote->ForgetCaption();
+ ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Remove, &rDoc, maPos, pNote.get());
+ }
+}
+
+ScUndoShowHideNote::ScUndoShowHideNote( ScDocShell& rDocShell, const ScAddress& rPos, bool bShow ) :
+ ScSimpleUndo( &rDocShell ),
+ maPos( rPos ),
+ mbShown( bShow )
+{
+}
+
+ScUndoShowHideNote::~ScUndoShowHideNote()
+{
+}
+
+void ScUndoShowHideNote::Undo()
+{
+ BeginUndo();
+ if( ScPostIt* pNote = pDocShell->GetDocument().GetNote(maPos) )
+ pNote->ShowCaption( maPos, !mbShown );
+ EndUndo();
+}
+
+void ScUndoShowHideNote::Redo()
+{
+ BeginRedo();
+ if( ScPostIt* pNote = pDocShell->GetDocument().GetNote(maPos) )
+ pNote->ShowCaption( maPos, mbShown );
+ EndRedo();
+}
+
+void ScUndoShowHideNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
+{
+}
+
+bool ScUndoShowHideNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
+{
+ return false;
+}
+
+OUString ScUndoShowHideNote::GetComment() const
+{
+ return ScResId( mbShown ? STR_UNDO_SHOWNOTE : STR_UNDO_HIDENOTE );
+}
+
+ScUndoDetective::ScUndoDetective( ScDocShell* pNewDocShell,
+ std::unique_ptr<SdrUndoAction> pDraw, const ScDetOpData* pOperation,
+ std::unique_ptr<ScDetOpList> pUndoList ) :
+ ScSimpleUndo( pNewDocShell ),
+ pOldList ( std::move(pUndoList) ),
+ nAction ( 0 ),
+ pDrawUndo ( std::move(pDraw) )
+{
+ bIsDelete = ( pOperation == nullptr );
+ if (!bIsDelete)
+ {
+ nAction = static_cast<sal_uInt16>(pOperation->GetOperation());
+ aPos = pOperation->GetPos();
+ }
+}
+
+ScUndoDetective::~ScUndoDetective()
+{
+ pDrawUndo.reset();
+ pOldList.reset();
+}
+
+OUString ScUndoDetective::GetComment() const
+{
+ TranslateId pId = STR_UNDO_DETDELALL;
+ if ( !bIsDelete )
+ switch ( static_cast<ScDetOpType>(nAction) )
+ {
+ case SCDETOP_ADDSUCC: pId = STR_UNDO_DETADDSUCC; break;
+ case SCDETOP_DELSUCC: pId = STR_UNDO_DETDELSUCC; break;
+ case SCDETOP_ADDPRED: pId = STR_UNDO_DETADDPRED; break;
+ case SCDETOP_DELPRED: pId = STR_UNDO_DETDELPRED; break;
+ case SCDETOP_ADDERROR: pId = STR_UNDO_DETADDERROR; break;
+ }
+
+ return ScResId(pId);
+}
+
+void ScUndoDetective::Undo()
+{
+ BeginUndo();
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ DoSdrUndoAction(pDrawUndo.get(), &rDoc);
+
+ if (bIsDelete)
+ {
+ if ( pOldList )
+ rDoc.SetDetOpList( std::unique_ptr<ScDetOpList>(new ScDetOpList(*pOldList)) );
+ }
+ else
+ {
+ // Remove entry from list
+
+ ScDetOpList* pList = rDoc.GetDetOpList();
+ if (pList && pList->Count())
+ {
+ ScDetOpDataVector& rVec = pList->GetDataVector();
+ ScDetOpDataVector::iterator it = rVec.begin() + rVec.size() - 1;
+ if ( it->GetOperation() == static_cast<ScDetOpType>(nAction) && it->GetPos() == aPos )
+ rVec.erase( it);
+ else
+ {
+ OSL_FAIL("Detective entry could not be found in list");
+ }
+ }
+ }
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+ pViewShell->RecalcPPT(); //! use broadcast instead?
+
+ EndUndo();
+}
+
+void ScUndoDetective::Redo()
+{
+ BeginRedo();
+
+ RedoSdrUndoAction(pDrawUndo.get());
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ if (bIsDelete)
+ rDoc.ClearDetectiveOperations();
+ else
+ rDoc.AddDetectiveOperation( ScDetOpData( aPos, static_cast<ScDetOpType>(nAction) ) );
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+ pViewShell->RecalcPPT(); //! use broadcast instead?
+
+ EndRedo();
+}
+
+void ScUndoDetective::Repeat(SfxRepeatTarget& /* rTarget */)
+{
+ // makes no sense
+}
+
+bool ScUndoDetective::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+{
+ return false;
+}
+
+ScUndoRangeNames::ScUndoRangeNames( ScDocShell* pNewDocShell,
+ std::unique_ptr<ScRangeName> pOld, std::unique_ptr<ScRangeName> pNew, SCTAB nTab ) :
+ ScSimpleUndo( pNewDocShell ),
+ pOldRanges ( std::move(pOld) ),
+ pNewRanges ( std::move(pNew) ),
+ mnTab ( nTab )
+{
+}
+
+ScUndoRangeNames::~ScUndoRangeNames()
+{
+ pOldRanges.reset();
+ pNewRanges.reset();
+}
+
+OUString ScUndoRangeNames::GetComment() const
+{
+ return ScResId( STR_UNDO_RANGENAMES );
+}
+
+void ScUndoRangeNames::DoChange( bool bUndo )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.PreprocessRangeNameUpdate();
+
+ if ( bUndo )
+ {
+ auto p = std::make_unique<ScRangeName>(*pOldRanges);
+ if (mnTab >= 0)
+ rDoc.SetRangeName( mnTab, std::move(p) );
+ else
+ rDoc.SetRangeName( std::move(p) );
+ }
+ else
+ {
+ auto p = std::make_unique<ScRangeName>(*pNewRanges);
+ if (mnTab >= 0)
+ rDoc.SetRangeName( mnTab, std::move(p) );
+ else
+ rDoc.SetRangeName( std::move(p) );
+ }
+
+ rDoc.CompileHybridFormula();
+
+ SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
+}
+
+void ScUndoRangeNames::Undo()
+{
+ BeginUndo();
+ DoChange( true );
+ EndUndo();
+}
+
+void ScUndoRangeNames::Redo()
+{
+ BeginRedo();
+ DoChange( false );
+ EndRedo();
+}
+
+void ScUndoRangeNames::Repeat(SfxRepeatTarget& /* rTarget */)
+{
+ // makes no sense
+}
+
+bool ScUndoRangeNames::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */