diff options
author | Eike Rathke <erack@redhat.com> | 2014-12-01 23:56:44 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2014-12-02 15:37:06 +0100 |
commit | 4c254a6d2532460351180c071fabf44129e8885d (patch) | |
tree | a483f2ac79657fc9e1f0050c13e7ebbd39f987df | |
parent | 0795fb9395d3245cbde679f9622d11020daf7ce4 (diff) |
fdo#86762 re-establish listeners to move cell broadcasters
... for UpdateReferenceOnSort=false
Change-Id: Id90288660e317d6e47ee01ee3b5ff9058cfa18df
(cherry picked from commit 6c2111f17089eb667bf526561d7667d17825e822)
-rw-r--r-- | sc/inc/refhint.hxx | 18 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 10 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 145 | ||||
-rw-r--r-- | sc/source/core/tool/refhint.cxx | 6 |
4 files changed, 132 insertions, 47 deletions
diff --git a/sc/inc/refhint.hxx b/sc/inc/refhint.hxx index 0f65aaeae06b..558e160af9b2 100644 --- a/sc/inc/refhint.hxx +++ b/sc/inc/refhint.hxx @@ -23,7 +23,9 @@ public: enum Type { Moved, ColumnReordered, - RowReordered + RowReordered, + StartListening, + StopListening }; private: @@ -100,6 +102,20 @@ public: SCCOL getEndColumn() const; }; +class RefStartListeningHint : public RefHint +{ +public: + RefStartListeningHint(); + virtual ~RefStartListeningHint(); +}; + +class RefStopListeningHint : public RefHint +{ +public: + RefStopListeningHint(); + virtual ~RefStopListeningHint(); +}; + } #endif diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index e364a6e029ce..46f165599b47 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2044,6 +2044,16 @@ void ScFormulaCell::Notify( const SfxHint& rHint ) rRefRowReorder.getRowMap()); } break; + case sc::RefHint::StartListening: + { + StartListeningTo( pDocument); + } + break; + case sc::RefHint::StopListening: + { + EndListeningTo( pDocument); + } + break; default: ; } diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 227dfab8b5b9..2c7b30947037 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -661,6 +661,30 @@ public: typedef ReorderNotifier<sc::RefColReorderHint, sc::ColRowReorderMapType, SCCOL> ColReorderNotifier; typedef ReorderNotifier<sc::RefRowReorderHint, sc::ColRowReorderMapType, SCROW> RowReorderNotifier; +class StartListeningNotifier : std::unary_function<SvtListener*, void> +{ + sc::RefStartListeningHint maHint; +public: + StartListeningNotifier() {} + + void operator() ( SvtListener* p ) + { + p->Notify(maHint); + } +}; + +class StopListeningNotifier : std::unary_function<SvtListener*, void> +{ + sc::RefStopListeningHint maHint; +public: + StopListeningNotifier() {} + + void operator() ( SvtListener* p ) + { + p->Notify(maHint); + } +}; + class FormulaGroupPosCollector : std::unary_function<SvtListener*, void> { sc::RefQueryFormulaGroup& mrQuery; @@ -801,6 +825,9 @@ void ScTable::SortReorderByRow( ScSortInfoArray::RowsType* pRows = pArray->GetDataRows(); assert(pRows); // In sort-by-row mode we must have data rows already populated. + // Collect all listeners of cell broadcasters of sorted range. + std::vector<SvtListener*> aCellListeners; + if (!pArray->IsUpdateRefs()) { // When the update ref mode is disabled, we need to detach all formula @@ -808,6 +835,22 @@ void ScTable::SortReorderByRow( // afterward. sc::EndListeningContext aCxt(*pDocument); DetachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2); + + // Collect listeners of cell broadcasters. + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + aCol[nCol].CollectListeners(aCellListeners, nRow1, nRow2); + + // Remove any duplicate listener entries. We must ensure that we notify + // each unique listener only once. + std::sort(aCellListeners.begin(), aCellListeners.end()); + aCellListeners.erase(std::unique(aCellListeners.begin(), aCellListeners.end()), aCellListeners.end()); + + // Notify the cells' listeners to stop listening. + /* TODO: for performance this could be enhanced to stop and later + * restart only listening to within the reordered range and keep + * listening to everything outside untouched. */ + StopListeningNotifier aFunc; + std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc); } // Split formula groups at the sort range boundaries (if applicable). @@ -887,15 +930,18 @@ void ScTable::SortReorderByRow( else rAttrStore.push_back_empty(); - // At this point each broadcaster instance is managed by 2 - // containers. We will release those in the original storage - // below before transferring them to the document. - sc::BroadcasterStoreType& rBCStore = aSortedCols.at(j).maBroadcasters; - if (rCell.mpBroadcaster) - // A const pointer would be implicitly converted to a bool type. - rBCStore.push_back(const_cast<SvtBroadcaster*>(rCell.mpBroadcaster)); - else - rBCStore.push_back_empty(); + if (pArray->IsUpdateRefs()) + { + // At this point each broadcaster instance is managed by 2 + // containers. We will release those in the original storage + // below before transferring them to the document. + sc::BroadcasterStoreType& rBCStore = aSortedCols.at(j).maBroadcasters; + if (rCell.mpBroadcaster) + // A const pointer would be implicitly converted to a bool type. + rBCStore.push_back(const_cast<SvtBroadcaster*>(rCell.mpBroadcaster)); + else + rBCStore.push_back_empty(); + } // The same with cell note instances ... sc::CellNoteStoreType& rNoteStore = aSortedCols.at(j).maCellNotes; @@ -936,6 +982,7 @@ void ScTable::SortReorderByRow( rSrc.transfer(nRow1, nRow2, rDest, nRow1); } + if (pArray->IsUpdateRefs()) { sc::BroadcasterStoreType& rSrc = aSortedCols[i].maBroadcasters; sc::BroadcasterStoreType& rDest = aCol[nThisCol].maBroadcasters; @@ -1003,39 +1050,39 @@ void ScTable::SortReorderByRow( SetRowFiltered(it->mnRow1, it->mnRow2, true); } - // Set up row reorder map (for later broadcasting of reference updates). - sc::ColRowReorderMapType aRowMap; - const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices(); - for (size_t i = 0, n = rOldIndices.size(); i < n; ++i) - { - SCROW nNew = i + nRow1; - SCROW nOld = rOldIndices[i]; - aRowMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew)); - } - - // Collect all listeners within sorted range ahead of time. - std::vector<SvtListener*> aListeners; - - // Get all area listeners that listen on one row within the range and end - // their listening. - ScRange aMoveRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab); - std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners( - aMoveRange, sc::OneRowInsideArea); + if (pArray->IsUpdateRefs()) { - std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); - for (; it != itEnd; ++it) + // Set up row reorder map (for later broadcasting of reference updates). + sc::ColRowReorderMapType aRowMap; + const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices(); + for (size_t i = 0, n = rOldIndices.size(); i < n; ++i) { - pDocument->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener); - aListeners.push_back( it->mpListener); + SCROW nNew = i + nRow1; + SCROW nOld = rOldIndices[i]; + aRowMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew)); } - } - if (pArray->IsUpdateRefs()) - { + // Collect all listeners within sorted range ahead of time. + std::vector<SvtListener*> aListeners; + // Collect listeners of cell broadcasters. for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) aCol[nCol].CollectListeners(aListeners, nRow1, nRow2); + // Get all area listeners that listen on one row within the range and end + // their listening. + ScRange aMoveRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab); + std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners( + aMoveRange, sc::OneRowInsideArea); + { + std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); + for (; it != itEnd; ++it) + { + pDocument->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener); + aListeners.push_back( it->mpListener); + } + } + // Remove any duplicate listener entries. We must ensure that we notify // each unique listener only once. std::sort(aListeners.begin(), aListeners.end()); @@ -1061,7 +1108,7 @@ void ScTable::SortReorderByRow( } } - // Notify the listeners. + // Notify the listeners to update their references. RowReorderNotifier aFunc(aRowMap, nTab, nCol1, nCol2); std::for_each(aListeners.begin(), aListeners.end(), aFunc); @@ -1073,23 +1120,29 @@ void ScTable::SortReorderByRow( for (; itCol != itColEnd; ++itCol) pDocument->RegroupFormulaCells(itGroupTab->first, itCol->first); } - } - // Re-start area listeners on the reordered rows. - { - std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); - for (; it != itEnd; ++it) + // Re-start area listeners on the reordered rows. { - ScRange aNewRange = it->maArea; - sc::ColRowReorderMapType::const_iterator itRow = aRowMap.find( aNewRange.aStart.Row()); - if (itRow != aRowMap.end()) + std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); + for (; it != itEnd; ++it) { - aNewRange.aStart.SetRow( itRow->second); - aNewRange.aEnd.SetRow( itRow->second); + ScRange aNewRange = it->maArea; + sc::ColRowReorderMapType::const_iterator itRow = aRowMap.find( aNewRange.aStart.Row()); + if (itRow != aRowMap.end()) + { + aNewRange.aStart.SetRow( itRow->second); + aNewRange.aEnd.SetRow( itRow->second); + } + pDocument->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener); } - pDocument->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener); } } + else // !(pArray->IsUpdateRefs()) + { + // Notify the cells' listeners to (re-)start listening. + StartListeningNotifier aFunc; + std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc); + } // Re-group columns in the sorted range too. for (SCCOL i = nCol1; i <= nCol2; ++i) diff --git a/sc/source/core/tool/refhint.cxx b/sc/source/core/tool/refhint.cxx index f76489c90e77..c159e9695b18 100644 --- a/sc/source/core/tool/refhint.cxx +++ b/sc/source/core/tool/refhint.cxx @@ -89,6 +89,12 @@ SCCOL RefRowReorderHint::getEndColumn() const return mnCol2; } +RefStartListeningHint::RefStartListeningHint() : RefHint(StartListening) {} +RefStartListeningHint::~RefStartListeningHint() {} + +RefStopListeningHint::RefStopListeningHint() : RefHint(StopListening) {} +RefStopListeningHint::~RefStopListeningHint() {} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |