diff options
31 files changed, 454 insertions, 30 deletions
diff --git a/include/svl/listener.hxx b/include/svl/listener.hxx index c8710230c9a7..1c9845843bd1 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 efc7d5ecc205..9aebd4521d7c 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 beef7749b440..b328becc244a 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 9ab5b27d71f0..09e112e6497d 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 ea80fa76679e..d04a1ab9b857 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 de2821451499..c9e97572de65 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 2d39f5ac175f..05afc1c87a5d 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 9b47046c36e7..81dd1fdfdf2e 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 0b6c53baec4f..2f73930e2e64 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 d5e79218a350..092dcf7a54c1 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 000000000000..ec56735faaf3 --- /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 000000000000..ecf2f9357c2d --- /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 8cf0fb1d6815..ce58c206558c 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 312e63a5584a..eb68997b8cad 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 4578fd9e55cd..cccddb0d16fa 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 5409c6bc3bd8..b50ea9f991d4 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 2e9192df31a5..8b6aa9d0d8e4 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 0faa829969d4..d48acbf583b1 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 957d8b2439f3..2eedc520386a 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 a1e9bf1966af..3eb49629ee17 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 6974acf99197..9bd416c46111 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 3cc5b8fe753a..db5c6cf34b0e 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 914b188a851d..ac92fe627309 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 000000000000..eb07b4fe3565 --- /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 3856bac3e97d..75f8bc0d9587 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 9cedad40c772..071d2ba6604d 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 376984dd7120..a35bcaf08775 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 17b3520dd289..68bdbe731725 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 9c8475323fbe..5bb1309831f3 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 19abe3878684..753cbc8a14ef 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 59d3ef9f3352..66207bf4c0bc 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: */ |