summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2014-12-01 23:56:44 +0100
committerEike Rathke <erack@redhat.com>2014-12-02 15:37:06 +0100
commit4c254a6d2532460351180c071fabf44129e8885d (patch)
treea483f2ac79657fc9e1f0050c13e7ebbd39f987df
parent0795fb9395d3245cbde679f9622d11020daf7ce4 (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.hxx18
-rw-r--r--sc/source/core/data/formulacell.cxx10
-rw-r--r--sc/source/core/data/table3.cxx145
-rw-r--r--sc/source/core/tool/refhint.cxx6
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: */