sc/inc/listenercontext.hxx | 12 ++ sc/qa/unit/ucalc_formula.cxx | 2 sc/source/core/data/column.cxx | 134 +++++++++++++++++++++++++------- sc/source/core/data/listenercontext.cxx | 44 ++++------ 4 files changed, 135 insertions(+), 57 deletions(-)
New commits: commit 8b368d808e90561a9b34658e6b811a8fad83088f Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Sat Mar 15 11:14:24 2014 -0400 Unregister all listeners first then re-register them. It's safe this way in case we are transferring them within the same column. Any empty broadcasters are checked and purged at the end. Change-Id: Ib2d46e616cde4923720ad21cb101d3a97dc8c5d9 diff --git a/sc/inc/listenercontext.hxx b/sc/inc/listenercontext.hxx index c0260ef..501f1d2 100644 --- a/sc/inc/listenercontext.hxx +++ b/sc/inc/listenercontext.hxx @@ -58,6 +58,18 @@ public: void purgeEmptyBroadcasters(); }; +class PurgeListenerAction : public ColumnSpanSet::Action, boost::noncopyable +{ + ScDocument& mrDoc; + boost::scoped_ptr<ColumnBlockPosition> mpBlockPos; + +public: + PurgeListenerAction( ScDocument& rDoc ); + + virtual void startColumn( SCTAB nTab, SCCOL nCol ); + virtual void execute( const ScAddress& rPos, SCROW nLength, bool bVal ); +}; + } #endif diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 8b6aa9d..9694790 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -3478,27 +3478,113 @@ 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) {} + typedef std::vector<SvtListener*> ListenersType; + struct Entry + { + size_t mnRow; + ListenersType maListeners; + }; + typedef std::vector<Entry> ListenerListType; + + void swapListeners( std::vector<Entry>& rListenerList ) + { + maListenerList.swap(rListenerList); + } void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster ) { assert(pBroadcaster); - SvtBroadcaster::ListenersType& rLis = pBroadcaster->GetAllListeners(); - if (rLis.empty()) + // It's important to make a copy here. + SvtBroadcaster::ListenersType aLis = pBroadcaster->GetAllListeners(); + if (aLis.empty()) // No listeners to transfer. return; - SCROW nDestRow = nRow + mnRowDelta; + Entry aEntry; + aEntry.mnRow = nRow; + + SvtBroadcaster::ListenersType::iterator it = aLis.begin(), itEnd = aLis.end(); + for (; it != itEnd; ++it) + { + SvtListener* pLis = *it; + pLis->EndListening(*pBroadcaster); + aEntry.maListeners.push_back(pLis); + } + + maListenerList.push_back(aEntry); + + // At this point, the source broadcaster should have no more listeners. + assert(!pBroadcaster->HasListeners()); + } + +private: + ListenerListType maListenerList; +}; + +class RemoveEmptyBroadcasterHandler +{ + sc::ColumnSpanSet maSet; + ScDocument& mrDoc; + SCCOL mnCol; + SCTAB mnTab; + +public: + RemoveEmptyBroadcasterHandler( ScDocument& rDoc, SCCOL nCol, SCTAB nTab ) : + maSet(false), mrDoc(rDoc), mnCol(nCol), mnTab(nTab) {} + + void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster ) + { + if (!pBroadcaster->HasListeners()) + maSet.set(mnTab, mnCol, nRow, true); + } + + void purge() + { + sc::PurgeListenerAction aAction(mrDoc); + maSet.executeAction(aAction); + } +}; + +} + +void ScColumn::TransferListeners( + ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta ) +{ + if (nRow2 < nRow1) + return; + + if (!ValidRow(nRow1) || !ValidRow(nRow2)) + return; - sc::BroadcasterStoreType::position_type aPos = mrDestBroadcasters.position(miDestPos, nDestRow); - miDestPos = aPos.first; + if (nRowDelta <= 0 && !ValidRow(nRow1+nRowDelta)) + return; + + if (nRowDelta >= 0 && !ValidRow(nRow2+nRowDelta)) + return; + + // Collect all listeners from the source broadcasters. The listeners will + // be removed from their broadcasters as they are collected. + TransferListenersHandler aFunc; + sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc); + + TransferListenersHandler::ListenerListType aListenerList; + aFunc.swapListeners(aListenerList); + + // Re-register listeners with their destination broadcasters. + sc::BroadcasterStoreType::iterator itDestPos = rDestCol.maBroadcasters.begin(); + TransferListenersHandler::ListenerListType::iterator it = aListenerList.begin(), itEnd = aListenerList.end(); + for (; it != itEnd; ++it) + { + TransferListenersHandler::Entry& rEntry = *it; + + SCROW nDestRow = rEntry.mnRow + nRowDelta; + + sc::BroadcasterStoreType::position_type aPos = + rDestCol.maBroadcasters.position(itDestPos, nDestRow); + + itDestPos = aPos.first; SvtBroadcaster* pDestBrd = NULL; if (aPos.first->type == sc::element_type_broadcaster) { @@ -3510,32 +3596,22 @@ public: // No existing broadcaster. Create a new one. assert(aPos.first->type == sc::element_type_empty); pDestBrd = new SvtBroadcaster; - miDestPos = mrDestBroadcasters.set(miDestPos, nDestRow, pDestBrd); + itDestPos = rDestCol.maBroadcasters.set(itDestPos, nDestRow, pDestBrd); } // Transfer all listeners from the source to the destination. - SvtBroadcaster::ListenersType::iterator it = rLis.begin(), itEnd = rLis.end(); - for (; it != itEnd; ++it) + SvtBroadcaster::ListenersType::iterator it2 = rEntry.maListeners.begin(), it2End = rEntry.maListeners.end(); + for (; it2 != it2End; ++it2) { - SvtListener* pLis = *it; - pLis->EndListening(*pBroadcaster); + SvtListener* pLis = *it2; 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. + // Remove any broadcasters that have no listeners. + RemoveEmptyBroadcasterHandler aFuncRemoveEmpty(*pDocument, nCol, nTab); + sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFuncRemoveEmpty); + aFuncRemoveEmpty.purge(); } void ScColumn::CalcAll() diff --git a/sc/source/core/data/listenercontext.cxx b/sc/source/core/data/listenercontext.cxx index 3dfe5ed..add75a2 100644 --- a/sc/source/core/data/listenercontext.cxx +++ b/sc/source/core/data/listenercontext.cxx @@ -13,32 +13,6 @@ namespace sc { -namespace { - -class PurgeAction : public ColumnSpanSet::Action -{ - ScDocument& mrDoc; - sc::ColumnBlockPosition maBlockPos; - -public: - PurgeAction(ScDocument& rDoc) : mrDoc(rDoc) {} - - virtual void startColumn(SCTAB nTab, SCCOL nCol) - { - mrDoc.InitColumnBlockPosition(maBlockPos, nTab, nCol); - } - - virtual void execute(const ScAddress& rPos, SCROW nLength, bool bVal) - { - if (bVal) - { - mrDoc.DeleteBroadcasters(maBlockPos, rPos, nLength); - } - }; -}; - -} - StartListeningContext::StartListeningContext(ScDocument& rDoc) : mrDoc(rDoc), mpSet(new ColumnBlockPositionSet(rDoc)) {} @@ -92,10 +66,26 @@ void EndListeningContext::addEmptyBroadcasterPosition(SCTAB nTab, SCCOL nCol, SC void EndListeningContext::purgeEmptyBroadcasters() { - PurgeAction aAction(mrDoc); + PurgeListenerAction aAction(mrDoc); maSet.executeAction(aAction); } +PurgeListenerAction::PurgeListenerAction(ScDocument& rDoc) : + mrDoc(rDoc), mpBlockPos(new ColumnBlockPosition) {} + +void PurgeListenerAction::startColumn( SCTAB nTab, SCCOL nCol ) +{ + mrDoc.InitColumnBlockPosition(*mpBlockPos, nTab, nCol); +} + +void PurgeListenerAction::execute( const ScAddress& rPos, SCROW nLength, bool bVal ) +{ + if (bVal) + { + mrDoc.DeleteBroadcasters(*mpBlockPos, rPos, nLength); + } +}; + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 3ced80133a171bc528ed4600f1d00daadfdbb21b Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Sat Mar 15 11:14:02 2014 -0400 The test is incorrect. Change-Id: I4e4b788f34e01f926d60d97515de4191d7346d5e diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index f939698..a03ba89 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -1677,7 +1677,7 @@ void Test::testFormulaRefUpdateMoveUndo() 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(25.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))); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits