diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-07-30 13:51:28 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-07-31 09:05:18 -0400 |
commit | 27182231acd3a0c9898a8dba78b76dc8a827b4c0 (patch) | |
tree | 02b853f50d4201799a28f85a40de1d171db73333 /sc/source/ui/undo | |
parent | 85f8f8f8589af3c404339c0f78021a7fe21cdfcd (diff) |
fdo#78555: Retain formula results when moving a range of cells.
* No need to re-compile RPN token array on reference change alone. We do that
when the formula contains one or more names that have been updated.
* Adjust undo code to get it to work without relying on ref undo document,
which would cause the token arrays to be unnecessarily recompiled.
* Whatever else need to be changed in order to pass all unit tests.
Change-Id: I99e86d23320aca8900fef011da23a9d34e42751e
Diffstat (limited to 'sc/source/ui/undo')
-rw-r--r-- | sc/source/ui/undo/undoblk.cxx | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index 982925d8c3ab..be6895fc3e6c 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -52,6 +52,7 @@ #include <refupdatecontext.hxx> #include <validat.hxx> #include <gridwin.hxx> +#include <svl/listener.hxx> #include <set> #include <boost/scoped_ptr.hpp> @@ -1249,6 +1250,22 @@ void ScUndoDragDrop::DoUndo( ScRange aRange ) maPaintRanges.Join(aPaintRange); } +namespace { + +class DataChangeNotifier : std::unary_function<SvtListener*, void> +{ + ScHint maHint; +public: + DataChangeNotifier() : maHint(SC_HINT_DATACHANGED, ScAddress()) {} + + void operator() ( SvtListener* p ) + { + p->Notify(maHint); + } +}; + +} + void ScUndoDragDrop::Undo() { mnPaintExtFlags = 0; @@ -1258,32 +1275,64 @@ void ScUndoDragDrop::Undo() if (bCut) { - // Notify all listeners of the destination range, and have them update their references. + // During undo, we move cells from aDestRange to aSrcRange. + ScDocument& rDoc = pDocShell->GetDocument(); + SCCOL nColDelta = aSrcRange.aStart.Col() - aDestRange.aStart.Col(); SCROW nRowDelta = aSrcRange.aStart.Row() - aDestRange.aStart.Row(); SCTAB nTabDelta = aSrcRange.aStart.Tab() - aDestRange.aStart.Tab(); - sc::RefMovedHint aHint(aDestRange, ScAddress(nColDelta, nRowDelta, nTabDelta)); + + sc::RefUpdateContext aCxt(rDoc); + aCxt.meMode = URM_MOVE; + aCxt.maRange = aSrcRange; + aCxt.mnColDelta = nColDelta; + aCxt.mnRowDelta = nRowDelta; + aCxt.mnTabDelta = nTabDelta; + + // Global range names. + ScRangeName* pName = rDoc.GetRangeName(); + if (pName) + pName->UpdateReference(aCxt); + + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; ++nTab) + { + // Sheet-local range names. + pName = rDoc.GetRangeName(nTab); + if (pName) + pName->UpdateReference(aCxt, nTab); + } + + // Notify all listeners of the destination range, and have them update their references. + sc::RefMovedHint aHint(aDestRange, ScAddress(nColDelta, nRowDelta, nTabDelta), aCxt); rDoc.BroadcastRefMoved(aHint); ScValidationDataList* pValidList = rDoc.GetValidationList(); if (pValidList) { // Update the references of validation entries. - sc::RefUpdateContext aCxt(rDoc); - aCxt.meMode = URM_MOVE; - aCxt.maRange = aSrcRange; - aCxt.mnColDelta = nColDelta; - aCxt.mnRowDelta = nRowDelta; - aCxt.mnTabDelta = nTabDelta; pValidList->UpdateReference(aCxt); } - } - DoUndo(aDestRange); - if (bCut) + DoUndo(aDestRange); DoUndo(aSrcRange); + // Notify all area listeners whose listened areas are partially moved, to + // recalculate. + std::vector<SvtListener*> aListeners; + rDoc.CollectAllAreaListeners(aListeners, aSrcRange, sc::AreaPartialOverlap); + + // Remove any duplicate listener entries. We must ensure that we notify + // each unique listener only once. + std::sort(aListeners.begin(), aListeners.end()); + aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end()); + + std::for_each(aListeners.begin(), aListeners.end(), DataChangeNotifier()); + } + else + DoUndo(aDestRange); + for (size_t i = 0; i < maPaintRanges.size(); ++i) { const ScRange* p = maPaintRanges[i]; |