summaryrefslogtreecommitdiff
path: root/sc/source/ui/undo
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-07-30 13:51:28 -0400
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-07-31 09:05:18 -0400
commit27182231acd3a0c9898a8dba78b76dc8a827b4c0 (patch)
tree02b853f50d4201799a28f85a40de1d171db73333 /sc/source/ui/undo
parent85f8f8f8589af3c404339c0f78021a7fe21cdfcd (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.cxx71
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];