[Libreoffice-commits] core.git: 2 commits - include/svl sc/inc sc/Library_sc.mk sc/qa sc/source svl/source
Kohei Yoshida
kohei.yoshida at collabora.com
Fri Mar 14 21:16:30 PDT 2014
include/svl/listener.hxx | 2
sc/Library_sc.mk | 1
sc/inc/brdcst.hxx | 6 -
sc/inc/cellsuno.hxx | 2
sc/inc/chartlis.hxx | 2
sc/inc/column.hxx | 3
sc/inc/document.hxx | 2
sc/inc/formulacell.hxx | 2
sc/inc/lookupcache.hxx | 2
sc/inc/mtvcellfunc.hxx | 10 +++
sc/inc/refhint.hxx | 62 +++++++++++++++++++
sc/inc/simplehintids.hxx | 22 ++++++
sc/inc/table.hxx | 10 +++
sc/inc/tokenarray.hxx | 10 +++
sc/qa/unit/ucalc.hxx | 2
sc/qa/unit/ucalc_formula.cxx | 116 ++++++++++++++++++++++++++++++++++++
sc/source/core/data/bcaslot.cxx | 42 +++++++++++++
sc/source/core/data/colorscale.cxx | 4 -
sc/source/core/data/column.cxx | 92 ++++++++++++++++++++++++++++
sc/source/core/data/documen7.cxx | 54 ++++++++++++++++
sc/source/core/data/formulacell.cxx | 25 ++++++-
sc/source/core/data/table2.cxx | 20 ++++++
sc/source/core/inc/bcaslot.hxx | 4 +
sc/source/core/tool/chartlis.cxx | 2
sc/source/core/tool/lookupcache.cxx | 2
sc/source/core/tool/refhint.cxx | 36 +++++++++++
sc/source/core/tool/token.cxx | 39 ++++++++++++
sc/source/ui/docshell/servobj.cxx | 2
sc/source/ui/inc/servobj.hxx | 2
sc/source/ui/undo/undoblk.cxx | 10 +++
sc/source/ui/unoobj/cellsuno.cxx | 2
svl/source/notify/broadcast.cxx | 2
svl/source/notify/listener.cxx | 10 ---
33 files changed, 572 insertions(+), 30 deletions(-)
New commits:
commit 88955714d345d8584e86ae34bf5f5d1f3f4af9f7
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Fri Mar 14 23:15:32 2014 -0400
fdo#71491: Adjust reference during undo of drag-n-drop of cell range.
Also with this commit, the signature of SvtListener::Notify() changes,
by dropping the first argument which nobody uses. This change was necessary
in order to call it directly without needing to pass any broadcaster instance.
Change-Id: I6a1e97f0fb1e070d1d8f7db614690b04c9e8024e
diff --git a/include/svl/listener.hxx b/include/svl/listener.hxx
index c871023..1c98458 100644
--- a/include/svl/listener.hxx
+++ b/include/svl/listener.hxx
@@ -45,7 +45,7 @@ public:
bool HasBroadcaster() const;
- virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+ virtual void Notify( const SfxHint& rHint );
};
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index efc7d5e..9aebd45 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -258,6 +258,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/tool/recursionhelper \
sc/source/core/tool/refdata \
sc/source/core/tool/reffind \
+ sc/source/core/tool/refhint \
sc/source/core/tool/refreshtimer \
sc/source/core/tool/reftokenhelper \
sc/source/core/tool/refupdat \
diff --git a/sc/inc/brdcst.hxx b/sc/inc/brdcst.hxx
index beef774..b328bec 100644
--- a/sc/inc/brdcst.hxx
+++ b/sc/inc/brdcst.hxx
@@ -21,16 +21,12 @@
#include "global.hxx"
#include "address.hxx"
+#include <simplehintids.hxx>
#include <tools/rtti.hxx>
#include <svl/hint.hxx>
-#include <svl/smplhint.hxx>
class SvtBroadcaster;
-#define SC_HINT_DATACHANGED SFX_HINT_DATACHANGED
-#define SC_HINT_TABLEOPDIRTY SFX_HINT_USER00
-#define SC_HINT_CALCALL SFX_HINT_USER01
-
class ScHint : public SfxSimpleHint
{
ScAddress aAddress;
diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx
index 9ab5b27..09e112e 100644
--- a/sc/inc/cellsuno.hxx
+++ b/sc/inc/cellsuno.hxx
@@ -115,7 +115,7 @@ class ScLinkListener : public SvtListener
public:
ScLinkListener(const Link& rL) : aLink(rL) {}
virtual ~ScLinkListener();
- virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+ virtual void Notify( const SfxHint& rHint );
};
typedef ::com::sun::star::uno::Reference<
diff --git a/sc/inc/chartlis.hxx b/sc/inc/chartlis.hxx
index ea80fa7..d04a1ab 100644
--- a/sc/inc/chartlis.hxx
+++ b/sc/inc/chartlis.hxx
@@ -92,7 +92,7 @@ public:
bool IsUno() const { return (pUnoData != NULL); }
- virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+ virtual void Notify( const SfxHint& rHint );
void StartListeningTo();
void EndListeningTo();
void ChangeListening( const ScRangeListRef& rRangeListRef,
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index de28214..c9e9757 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -61,6 +61,7 @@ struct RowSpan;
class RowHeightContext;
class CompileFormulaContext;
struct SetFormulaDirtyContext;
+class RefMovedHint;
}
@@ -462,6 +463,8 @@ public:
void StartNeededListeners(); // only for cells where NeedsListening()==true
void SetDirtyIfPostponed();
void BroadcastRecalcOnRefMove();
+ void BroadcastRefMoved( const sc::RefMovedHint& rHint );
+ void TransferListeners( ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta );
void CompileDBFormula( sc::CompileFormulaContext& rCxt );
void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 2d39f5a..05afc1c 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -77,6 +77,7 @@ class DocumentLinkManager;
class CellValues;
class RowHeightContext;
struct SetFormulaDirtyContext;
+class RefMovedHint;
}
@@ -1829,6 +1830,7 @@ public:
void Broadcast( const ScHint& rHint );
void BroadcastCells( const ScRange& rRange, sal_uLong nHint );
+ void BroadcastRefMoved( const sc::RefMovedHint& rHint );
/// only area, no cell broadcast
void AreaBroadcast( const ScHint& rHint );
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 9b47046..81dd1fd 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -314,7 +314,7 @@ public:
void SetPreviousTrack( ScFormulaCell* pF );
void SetNextTrack( ScFormulaCell* pF );
- virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
+ virtual void Notify( const SfxHint& rHint );
void SetCompile( bool bVal );
ScDocument* GetDocument() const;
void SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
diff --git a/sc/inc/lookupcache.hxx b/sc/inc/lookupcache.hxx
index 0b6c53b..2f73930 100644
--- a/sc/inc/lookupcache.hxx
+++ b/sc/inc/lookupcache.hxx
@@ -120,7 +120,7 @@ public:
ScLookupCache( ScDocument * pDoc, const ScRange & rRange );
virtual ~ScLookupCache();
/// Remove from document structure and delete (!) cache on modify hint.
- virtual void Notify( SvtBroadcaster & rBC, const SfxHint & rHint );
+ virtual void Notify( const SfxHint& rHint );
/// @returns document address in o_rAddress if Result==FOUND
Result lookup( ScAddress & o_rResultAddress,
diff --git a/sc/inc/mtvcellfunc.hxx b/sc/inc/mtvcellfunc.hxx
index d5e7921..092dcf7 100644
--- a/sc/inc/mtvcellfunc.hxx
+++ b/sc/inc/mtvcellfunc.hxx
@@ -187,6 +187,16 @@ ProcessNote(
CellNoteStoreType, cellnote_block, _FuncElem, FuncElseNoOp<size_t> >(it, rStore, nRow1, nRow2, rFuncElem, aElse);
}
+template<typename _FuncElem>
+typename BroadcasterStoreType::iterator
+ProcessBroadcaster(
+ const BroadcasterStoreType::iterator& it, BroadcasterStoreType& rStore, SCROW nRow1, SCROW nRow2, _FuncElem& rFuncElem)
+{
+ FuncElseNoOp<size_t> aElse;
+ return ProcessElements1<
+ BroadcasterStoreType, broadcaster_block, _FuncElem, FuncElseNoOp<size_t> >(it, rStore, nRow1, nRow2, rFuncElem, aElse);
+}
+
}
#endif
diff --git a/sc/inc/refhint.hxx b/sc/inc/refhint.hxx
new file mode 100644
index 0000000..ec56735
--- /dev/null
+++ b/sc/inc/refhint.hxx
@@ -0,0 +1,62 @@
+/* -*- 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/.
+ */
+
+#ifndef SC_REFHINT_HXX
+#define SC_REFHINT_HXX
+
+#include <address.hxx>
+#include <simplehintids.hxx>
+
+namespace sc {
+
+class RefHint : public SfxSimpleHint
+{
+public:
+ enum Type { Moved };
+
+private:
+ Type meType;
+
+ RefHint(); // disabled
+
+protected:
+ RefHint( Type eType );
+
+public:
+ virtual ~RefHint() = 0;
+
+ Type getType() const;
+};
+
+class RefMovedHint : public RefHint
+{
+ ScRange maRange;
+ ScAddress maMoveDelta;
+
+public:
+
+ RefMovedHint( const ScRange& rRange, const ScAddress& rMove );
+ virtual ~RefMovedHint();
+
+ /**
+ * Get the source range from which the references have moved.
+ */
+ const ScRange& getRange() const;
+
+ /**
+ * Get the movement vector.
+ */
+ const ScAddress& getDelta() const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/simplehintids.hxx b/sc/inc/simplehintids.hxx
new file mode 100644
index 0000000..ecf2f93
--- /dev/null
+++ b/sc/inc/simplehintids.hxx
@@ -0,0 +1,22 @@
+/* -*- 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/.
+ */
+
+#ifndef SC_SIMPLEHINTIDS_HXX
+#define SC_SIMPLEHINTIDS_HXX
+
+#include <svl/smplhint.hxx>
+
+#define SC_HINT_DATACHANGED SFX_HINT_DATACHANGED
+#define SC_HINT_TABLEOPDIRTY SFX_HINT_USER00
+#define SC_HINT_CALCALL SFX_HINT_USER01
+#define SC_HINT_REFERENCE SFX_HINT_USER02
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 8cf0fb1..ce58c20 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -72,6 +72,7 @@ class CellValues;
class RowHeightContext;
class CompileFormulaContext;
struct SetFormulaDirtyContext;
+class RefMovedHint;
}
@@ -896,6 +897,15 @@ public:
*/
void BroadcastRecalcOnRefMove();
+ /**
+ * Broadcast all listeners of specified range that the range have moved.
+ */
+ void BroadcastRefMoved( const sc::RefMovedHint& rHint );
+
+ void TransferListeners(
+ ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+ SCCOL nColDelta, SCROW nRowDelta );
+
void TransferCellValuesTo( SCCOL nCol, SCROW nRow, size_t nLen, sc::CellValues& rDest );
void CopyCellValuesFrom( SCCOL nCol, SCROW nRow, const sc::CellValues& rSrc );
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 312e63a..eb68997 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -144,6 +144,16 @@ public:
const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos );
/**
+ * Move reference positions that are within specified moved range.
+ *
+ * @param rPos position of this formula cell
+ * @param rMovedRange range that has been moved.
+ * @param rDelta movement vector.
+ */
+ void MoveReference(
+ const ScAddress& rPos, const ScRange& rMovedRange, const ScAddress& rDelta );
+
+ /**
* Adjust all references in named expression. In named expression, we only
* update absolute positions, and leave relative positions intact.
*
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index 4578fd9..cccddb0 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -446,6 +446,23 @@ void ScBroadcastAreaSlot::EraseArea( ScBroadcastAreas::iterator& rIter )
}
}
+void ScBroadcastAreaSlot::GetAllListeners( const ScRange& rRange, std::vector<SvtListener*>& rListeners )
+{
+ for (ScBroadcastAreas::const_iterator aIter( aBroadcastAreaTbl.begin()),
+ aIterEnd( aBroadcastAreaTbl.end()); aIter != aIterEnd; ++aIter )
+ {
+ if (isMarkedErased( aIter))
+ continue;
+
+ ScBroadcastArea* pArea = (*aIter).mpArea;
+ const ScRange& rAreaRange = pArea->GetRange();
+ if (!rAreaRange.Intersects(rRange))
+ continue;
+
+ SvtBroadcaster::ListenersType& rLst = pArea->GetBroadcaster().GetAllListeners();
+ std::copy(rLst.begin(), rLst.end(), std::back_inserter(rListeners));
+ }
+}
void ScBroadcastAreaSlot::FinallyEraseAreas()
{
@@ -976,4 +993,29 @@ void ScBroadcastAreaSlotMachine::FinallyEraseAreas( ScBroadcastAreaSlot* pSlot )
maAreasToBeErased.swap( aCopy);
}
+std::vector<SvtListener*> ScBroadcastAreaSlotMachine::GetAllListeners( const ScRange& rRange )
+{
+ std::vector<SvtListener*> aRet;
+
+ SCTAB nEndTab = rRange.aEnd.Tab();
+ for (TableSlotsMap::const_iterator iTab( aTableSlotsMap.lower_bound( rRange.aStart.Tab()));
+ iTab != aTableSlotsMap.end() && (*iTab).first <= nEndTab; ++iTab)
+ {
+ ScBroadcastAreaSlot** ppSlots = (*iTab).second->getSlots();
+ SCSIZE nStart, nEnd, nRowBreak;
+ ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+ SCSIZE nOff = nStart;
+ SCSIZE nBreak = nOff + nRowBreak;
+ ScBroadcastAreaSlot** pp = ppSlots + nOff;
+ while ( nOff <= nEnd )
+ {
+ ScBroadcastAreaSlot* p = *pp;
+ p->GetAllListeners(rRange, aRet);
+ ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak);
+ }
+ }
+
+ return aRet;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx
index 5409c6b..b50ea9f 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -33,7 +33,7 @@ public:
ScFormulaListener(ScFormulaCell* pCell);
virtual ~ScFormulaListener();
- void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+ void Notify( const SfxHint& rHint );
bool NeedsRepaint() const;
};
@@ -129,7 +129,7 @@ ScFormulaListener::~ScFormulaListener()
std::for_each(maCells.begin(), maCells.end(), StopListeningCell(mpDoc, this));
}
-void ScFormulaListener::Notify(SvtBroadcaster&, const SfxHint&)
+void ScFormulaListener::Notify( const SfxHint& )
{
mbDirty = true;
}
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 2e9192d..8b6aa9d 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -42,6 +42,7 @@
#include "sharedformula.hxx"
#include "refupdatecontext.hxx"
#include <listenercontext.hxx>
+#include <refhint.hxx>
#include <svl/poolcach.hxx>
#include <svl/zforlist.hxx>
@@ -3446,6 +3447,97 @@ void ScColumn::BroadcastRecalcOnRefMove()
BroadcastCells(aFunc.getDirtyRows(), SC_HINT_DATACHANGED);
}
+namespace {
+
+class BroadcastRefMovedHandler
+{
+ const sc::RefMovedHint& mrHint;
+public:
+ BroadcastRefMovedHandler( const sc::RefMovedHint& rHint ) : mrHint(rHint) {}
+
+ void operator() ( size_t, SvtBroadcaster* p )
+ {
+ p->Broadcast(mrHint);
+ }
+};
+
+}
+
+void ScColumn::BroadcastRefMoved( const sc::RefMovedHint& rHint )
+{
+ const ScRange& rRange = rHint.getRange();
+ SCROW nRow1 = rRange.aStart.Row();
+ SCROW nRow2 = rRange.aEnd.Row();
+
+ // Notify all listeners within specified rows.
+ BroadcastRefMovedHandler aFunc(rHint);
+ sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
+}
+
+namespace {
+
+class TransferListenersHandler
+{
+ sc::BroadcasterStoreType& mrDestBroadcasters;
+ sc::BroadcasterStoreType::iterator miDestPos;
+ SCROW mnRowDelta; /// Add this to the source row to get the destination row.
+
+public:
+ TransferListenersHandler( sc::BroadcasterStoreType& rDestBrd, SCROW nRowDelta ) :
+ mrDestBroadcasters(rDestBrd), miDestPos(rDestBrd.begin()), mnRowDelta(nRowDelta) {}
+
+ void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
+ {
+ assert(pBroadcaster);
+
+ SvtBroadcaster::ListenersType& rLis = pBroadcaster->GetAllListeners();
+ if (rLis.empty())
+ // No listeners to transfer.
+ return;
+
+ SCROW nDestRow = nRow + mnRowDelta;
+
+ sc::BroadcasterStoreType::position_type aPos = mrDestBroadcasters.position(miDestPos, nDestRow);
+ miDestPos = aPos.first;
+ SvtBroadcaster* pDestBrd = NULL;
+ if (aPos.first->type == sc::element_type_broadcaster)
+ {
+ // Existing broadcaster.
+ pDestBrd = sc::broadcaster_block::at(*aPos.first->data, aPos.second);
+ }
+ else
+ {
+ // No existing broadcaster. Create a new one.
+ assert(aPos.first->type == sc::element_type_empty);
+ pDestBrd = new SvtBroadcaster;
+ miDestPos = mrDestBroadcasters.set(miDestPos, nDestRow, pDestBrd);
+ }
+
+ // Transfer all listeners from the source to the destination.
+ SvtBroadcaster::ListenersType::iterator it = rLis.begin(), itEnd = rLis.end();
+ for (; it != itEnd; ++it)
+ {
+ SvtListener* pLis = *it;
+ pLis->EndListening(*pBroadcaster);
+ pLis->StartListening(*pDestBrd);
+ }
+
+ // At this point, the source broadcaster should have no more listeners.
+ assert(!pBroadcaster->HasListeners());
+ }
+};
+
+}
+
+void ScColumn::TransferListeners(
+ ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta )
+{
+ TransferListenersHandler aFunc(rDestCol.maBroadcasters, nRowDelta);
+ sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
+
+ maBroadcasters.set_empty(nRow1, nRow2); // Remove all source broadcaster.
+}
+
void ScColumn::CalcAll()
{
CalcAllHandler aFunc;
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index 0faa829..d48acbf 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -37,6 +37,7 @@
#include "tokenarray.hxx"
#include "listenercontext.hxx"
#include "formulagroup.hxx"
+#include <refhint.hxx>
#include <tools/shl.hxx>
@@ -129,6 +130,59 @@ void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
}
+void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint )
+{
+ if (!pBASM)
+ // clipboard or undo document.
+ return;
+
+ const ScRange& rSrcRange = rHint.getRange(); // old range
+ const ScAddress& rDelta = rHint.getDelta();
+
+ // Get all area listeners that listens on the old range, and end their listening.
+ std::vector<SvtListener*> aAreaListeners = pBASM->GetAllListeners(rSrcRange);
+ {
+ std::vector<SvtListener*>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+ for (; it != itEnd; ++it)
+ {
+ SvtListener* p = *it;
+ pBASM->EndListeningArea(rSrcRange, p);
+ p->Notify(rHint); // Adjust the references.
+ }
+ }
+
+ for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ SCTAB nDestTab = nTab + rDelta.Tab();
+ ScTable* pDestTab = FetchTable(nDestTab);
+ if (!pDestTab)
+ continue;
+
+ // Adjust the references.
+ pTab->BroadcastRefMoved(rHint);
+ // Move the listeners from the old location to the new.
+ pTab->TransferListeners(
+ *pDestTab, rSrcRange.aStart.Col(), rSrcRange.aStart.Row(),
+ rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), rDelta.Col(), rDelta.Row());
+ }
+
+ // Re-start area listeners on the new range.
+ ScRange aNewRange = rSrcRange;
+ aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+ {
+ std::vector<SvtListener*>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+ for (; it != itEnd; ++it)
+ {
+ SvtListener* p = *it;
+ pBASM->StartListeningArea(aNewRange, p);
+ }
+ }
+}
+
void ScDocument::AreaBroadcast( const ScHint& rHint )
{
if ( !pBASM )
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 957d8b2..2eedc52 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -55,6 +55,7 @@
#include "scopetools.hxx"
#include "refupdatecontext.hxx"
#include <tokenstringcontext.hxx>
+#include <refhint.hxx>
#include <boost/scoped_ptr.hpp>
@@ -1867,12 +1868,30 @@ bool ScFormulaCell::IsInChangeTrack() const
return bInChangeTrack;
}
-void ScFormulaCell::Notify( SvtBroadcaster&, const SfxHint& rHint)
+void ScFormulaCell::Notify( const SfxHint& rHint )
{
+ const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
+ if (!pSimpleHint)
+ return;
+
+ sal_uLong nHint = pSimpleHint->GetId();
+ if (nHint == SC_HINT_REFERENCE)
+ {
+ const sc::RefHint& rRefHint = static_cast<const sc::RefHint&>(rHint);
+
+ if (rRefHint.getType() == sc::RefHint::Moved)
+ {
+ // One of the references has moved.
+
+ const sc::RefMovedHint& rRefMoved = static_cast<const sc::RefMovedHint&>(rRefHint);
+ pCode->MoveReference(aPos, rRefMoved.getRange(), rRefMoved.getDelta());
+ }
+
+ return;
+ }
+
if ( !pDocument->IsInDtorClear() && !pDocument->GetHardRecalcState() )
{
- const ScHint* p = PTR_CAST( ScHint, &rHint );
- sal_uLong nHint = (p ? p->GetId() : 0);
if (nHint & (SC_HINT_DATACHANGED | SC_HINT_TABLEOPDIRTY))
{
bool bForceTrack = false;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index a1e9bf1..3eb4962 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -50,6 +50,7 @@
#include "refupdatecontext.hxx"
#include "scopetools.hxx"
#include <rowheightcontext.hxx>
+#include <refhint.hxx>
#include "scitems.hxx"
#include <editeng/boxitem.hxx>
@@ -1716,6 +1717,25 @@ void ScTable::BroadcastRecalcOnRefMove()
aCol[i].BroadcastRecalcOnRefMove();
}
+void ScTable::BroadcastRefMoved( const sc::RefMovedHint& rHint )
+{
+ const ScRange& rRange = rHint.getRange();
+ for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ aCol[nCol].BroadcastRefMoved(rHint);
+}
+
+void ScTable::TransferListeners(
+ ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+ SCCOL nColDelta, SCROW nRowDelta )
+{
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ ScColumn& rSrcCol = aCol[nCol];
+ ScColumn& rDestCol = rDestTab.aCol[nCol+nColDelta];
+ rSrcCol.TransferListeners(rDestCol, nRow1, nRow2, nRowDelta);
+ }
+}
+
void ScTable::SetLoadingMedium(bool bLoading)
{
mpRowHeights->enableTreeSearch(!bLoading);
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx
index 6974acf..9bd416c 100644
--- a/sc/source/core/inc/bcaslot.hxx
+++ b/sc/source/core/inc/bcaslot.hxx
@@ -210,6 +210,8 @@ public:
Meant to be used internally and from ScBroadcastAreaSlotMachine only.
*/
void EraseArea( ScBroadcastAreas::iterator& rIter );
+
+ void GetAllListeners( const ScRange& rRange, std::vector<SvtListener*>& rListeners );
};
@@ -304,6 +306,8 @@ public:
ScBroadcastAreas::iterator& rIter );
// only for ScBroadcastAreaSlot
void FinallyEraseAreas( ScBroadcastAreaSlot* pSlot );
+
+ std::vector<SvtListener*> GetAllListeners( const ScRange& rRange );
};
diff --git a/sc/source/core/tool/chartlis.cxx b/sc/source/core/tool/chartlis.cxx
index 3cc5b8f..db5c6cf 100644
--- a/sc/source/core/tool/chartlis.cxx
+++ b/sc/source/core/tool/chartlis.cxx
@@ -202,7 +202,7 @@ uno::Reference< chart::XChartData > ScChartListener::GetUnoSource() const
return uno::Reference< chart::XChartData >();
}
-void ScChartListener::Notify( SvtBroadcaster&, const SfxHint& rHint )
+void ScChartListener::Notify( const SfxHint& rHint )
{
const ScHint* p = dynamic_cast<const ScHint*>(&rHint);
if (p && (p->GetId() & SC_HINT_DATACHANGED))
diff --git a/sc/source/core/tool/lookupcache.cxx b/sc/source/core/tool/lookupcache.cxx
index 914b188..ac92fe6 100644
--- a/sc/source/core/tool/lookupcache.cxx
+++ b/sc/source/core/tool/lookupcache.cxx
@@ -110,7 +110,7 @@ bool ScLookupCache::insert( const ScAddress & rResultAddress,
}
-void ScLookupCache::Notify( SvtBroadcaster & /* rBC */ , const SfxHint & rHint )
+void ScLookupCache::Notify( const SfxHint& rHint )
{
if (!mpDoc->IsInDtorClear())
{
diff --git a/sc/source/core/tool/refhint.cxx b/sc/source/core/tool/refhint.cxx
new file mode 100644
index 0000000..eb07b4fe
--- /dev/null
+++ b/sc/source/core/tool/refhint.cxx
@@ -0,0 +1,36 @@
+/* -*- 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/.
+ */
+
+#include <refhint.hxx>
+
+namespace sc {
+
+RefHint::RefHint( Type eType ) : SfxSimpleHint(SC_HINT_REFERENCE), meType(eType) {}
+RefHint::~RefHint() {}
+
+RefHint::Type RefHint::getType() const { return meType; }
+
+RefMovedHint::RefMovedHint( const ScRange& rRange, const ScAddress& rMove ) :
+ RefHint(Moved), maRange(rRange), maMoveDelta(rMove) {}
+
+RefMovedHint::~RefMovedHint() {}
+
+const ScRange& RefMovedHint::getRange() const
+{
+ return maRange;
+}
+
+const ScAddress& RefMovedHint::getDelta() const
+{
+ return maMoveDelta;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 3856bac..75f8bc0 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2845,6 +2845,45 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
return aRes;
}
+void ScTokenArray::MoveReference(
+ const ScAddress& rPos, const ScRange& rMovedRange, const ScAddress& rDelta )
+{
+ FormulaToken** p = pCode;
+ FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+ for (; p != pEnd; ++p)
+ {
+ switch ((*p)->GetType())
+ {
+ case svSingleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScSingleRefData& rRef = pToken->GetSingleRef();
+ ScAddress aAbs = rRef.toAbs(rPos);
+ if (rMovedRange.In(aAbs))
+ {
+ aAbs.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+ rRef.SetAddress(aAbs, rPos);
+ }
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScComplexRefData& rRef = pToken->GetDoubleRef();
+ ScRange aAbs = rRef.toAbs(rPos);
+ if (rMovedRange.In(aAbs))
+ {
+ aAbs.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+ rRef.SetRange(aAbs, rPos);
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
namespace {
bool adjustSingleRefInName(
diff --git a/sc/source/ui/docshell/servobj.cxx b/sc/source/ui/docshell/servobj.cxx
index 9cedad4..071d2ba 100644
--- a/sc/source/ui/docshell/servobj.cxx
+++ b/sc/source/ui/docshell/servobj.cxx
@@ -61,7 +61,7 @@ ScServerObjectSvtListenerForwarder::~ScServerObjectSvtListenerForwarder()
//! do NOT access pObj
}
-void ScServerObjectSvtListenerForwarder::Notify( SvtBroadcaster& /* rBC */, const SfxHint& rHint)
+void ScServerObjectSvtListenerForwarder::Notify( const SfxHint& rHint )
{
pObj->Notify( aBroadcaster, rHint);
}
diff --git a/sc/source/ui/inc/servobj.hxx b/sc/source/ui/inc/servobj.hxx
index 376984d..a35bcaf 100644
--- a/sc/source/ui/inc/servobj.hxx
+++ b/sc/source/ui/inc/servobj.hxx
@@ -36,7 +36,7 @@ class ScServerObjectSvtListenerForwarder : public SvtListener
public:
ScServerObjectSvtListenerForwarder( ScServerObject* pObjP);
virtual ~ScServerObjectSvtListenerForwarder();
- virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
+ virtual void Notify( const SfxHint& rHint );
};
class ScServerObject : public ::sfx2::SvLinkSource, public SfxListener
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 17b3520..68bdbe7 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -48,6 +48,7 @@
#include "clipparam.hxx"
#include "sc.hrc"
#include <rowheightcontext.hxx>
+#include <refhint.hxx>
#include <set>
@@ -1251,6 +1252,15 @@ void ScUndoDragDrop::Undo()
maPaintRanges.RemoveAll();
BeginUndo();
+
+ // Notify all listeners of the destination range, and have them update their references.
+ ScDocument* pDoc = 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));
+ pDoc->BroadcastRefMoved(aHint);
+
DoUndo(aDestRange);
if (bCut)
DoUndo(aSrcRange);
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 9c84753..5bb1309 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -891,7 +891,7 @@ ScLinkListener::~ScLinkListener()
{
}
-void ScLinkListener::Notify( SvtBroadcaster&, const SfxHint& rHint )
+void ScLinkListener::Notify( const SfxHint& rHint )
{
aLink.Call( (SfxHint*)&rHint );
}
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 19abe38..753cbc8 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -132,7 +132,7 @@ void SvtBroadcaster::Broadcast( const SfxHint &rHint )
++dest;
if (dest == maDestructedListeners.end() || *dest != *it)
- (*it)->Notify(*this, rHint);
+ (*it)->Notify(rHint);
}
}
diff --git a/svl/source/notify/listener.cxx b/svl/source/notify/listener.cxx
index 59d3ef9..66207bf 100644
--- a/svl/source/notify/listener.cxx
+++ b/svl/source/notify/listener.cxx
@@ -80,15 +80,7 @@ bool SvtListener::HasBroadcaster() const
return !maBroadcasters.empty();
}
-void SvtListener::Notify( SvtBroadcaster&
-#ifdef DBG_UTIL
-rBC
-#endif
-, const SfxHint& )
-{
- DBG_ASSERT( IsListening( rBC ),
- "notification from unregistered broadcaster" );
-}
+void SvtListener::Notify( const SfxHint& ) {}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 980898058f1411d234c009caaae58b29eb3420c8
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Fri Mar 14 09:47:25 2014 -0400
fdo#71491: Write test for this.
Change-Id: I20de3d5c3c254b2ce96678553d91492dc95e2c39
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 8c3ec8f..81e915f 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -119,6 +119,7 @@ public:
void testFormulaRefUpdateRange();
void testFormulaRefUpdateSheets();
void testFormulaRefUpdateMove();
+ void testFormulaRefUpdateMoveUndo();
void testFormulaRefUpdateNamedExpression();
void testMultipleOperations();
void testFuncCOLUMN();
@@ -362,6 +363,7 @@ public:
CPPUNIT_TEST(testFormulaRefUpdateRange);
CPPUNIT_TEST(testFormulaRefUpdateSheets);
CPPUNIT_TEST(testFormulaRefUpdateMove);
+ CPPUNIT_TEST(testFormulaRefUpdateMoveUndo);
CPPUNIT_TEST(testFormulaRefUpdateNamedExpression);
CPPUNIT_TEST(testMultipleOperations);
CPPUNIT_TEST(testFuncCOLUMN);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 4dd1acd..f939698 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1571,6 +1571,122 @@ void Test::testFormulaRefUpdateMove()
m_pDoc->DeleteTab(0);
}
+void Test::testFormulaRefUpdateMoveUndo()
+{
+ m_pDoc->InsertTab(0, "Test");
+
+ sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+ // Set values in A1:A4.
+ m_pDoc->SetValue(ScAddress(0,0,0), 1.0);
+ m_pDoc->SetValue(ScAddress(0,1,0), 2.0);
+ m_pDoc->SetValue(ScAddress(0,2,0), 3.0);
+ m_pDoc->SetValue(ScAddress(0,3,0), 4.0);
+
+ // Set formulas with single cell references in A6:A8.
+ m_pDoc->SetString(ScAddress(0,5,0), "=A1");
+ CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "A1"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ m_pDoc->SetString(ScAddress(0,6,0), "=A1+A2+A3");
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "A1+A2+A3"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ m_pDoc->SetString(ScAddress(0,7,0), "=A1+A3+A4");
+ CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "A1+A3+A4"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ // Set formulas with range references in A10:A12.
+ m_pDoc->SetString(ScAddress(0,9,0), "=SUM(A1:A2)");
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM(A1:A2)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ m_pDoc->SetString(ScAddress(0,10,0), "=SUM(A1:A3)");
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "SUM(A1:A3)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ m_pDoc->SetString(ScAddress(0,11,0), "=SUM(A1:A4)");
+ CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "SUM(A1:A4)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ // Move A1:A3 to C1:C3. Note that A4 remains.
+ ScDocFunc& rFunc = getDocShell().GetDocFunc();
+ bool bMoved = rFunc.MoveBlock(ScRange(0,0,0,0,2,0), ScAddress(2,0,0), true, true, false, true);
+ CPPUNIT_ASSERT(bMoved);
+
+ CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "C1"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "C1+C2+C3"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "C1+C3+A4"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM(C1:C2)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "SUM(C1:C3)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "SUM(A1:A4)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ // Undo the move.
+ SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
+ CPPUNIT_ASSERT(pUndoMgr);
+ pUndoMgr->Undo();
+
+ CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "A1"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "A1+A2+A3"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "A1+A3+A4"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM(A1:A2)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "SUM(A1:A3)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+ if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "SUM(A1:A4)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ // Make sure the broadcasters are still valid by changing the value of A1.
+ m_pDoc->SetValue(ScAddress(0,0,0), 20);
+
+ CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0,5,0)));
+ CPPUNIT_ASSERT_EQUAL( 6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+ CPPUNIT_ASSERT_EQUAL(27.0, m_pDoc->GetValue(ScAddress(0,7,0)));
+
+ CPPUNIT_ASSERT_EQUAL(22.0, m_pDoc->GetValue(ScAddress(0,9,0)));
+ CPPUNIT_ASSERT_EQUAL(25.0, m_pDoc->GetValue(ScAddress(0,10,0)));
+ CPPUNIT_ASSERT_EQUAL(29.0, m_pDoc->GetValue(ScAddress(0,11,0)));
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testFormulaRefUpdateNamedExpression()
{
m_pDoc->InsertTab(0, "Formula");
More information about the Libreoffice-commits
mailing list