summaryrefslogtreecommitdiff
path: root/sc/source/core/data
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-14 21:51:39 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-18 08:31:56 -0500
commit34c8c0bb878be82a25cdaf1d7e623843f00fed6c (patch)
treee1f86eac1ee8147a452127c43b37ab2964f9e5e7 /sc/source/core/data
parentc55a5b242585824d3c6c217f813dc9acfc3228b2 (diff)
Send broadcast range to the area broadcast slot machine.
Rather than iterating through cells in the range and broadcasting by cells individually. This way we can take advantage of the new group based area listeners and it's much faster this way. Change-Id: I8a4b49bce69d89b5b4698790befe4390871c755d
Diffstat (limited to 'sc/source/core/data')
-rw-r--r--sc/source/core/data/bcaslot.cxx100
-rw-r--r--sc/source/core/data/documen7.cxx62
-rw-r--r--sc/source/core/data/document.cxx10
3 files changed, 158 insertions, 14 deletions
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index 9af7c19e2304..ee6f17ae7cfd 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -258,6 +258,83 @@ ScBroadcastAreas::const_iterator ScBroadcastAreaSlot::FindBroadcastArea(
return aBroadcastAreaTbl.find( &aTmpSeekBroadcastArea);
}
+namespace {
+
+void broadcastRangeByCell( SvtBroadcaster& rBC, const ScRange& rRange, sal_uLong nHint )
+{
+ ScHint aHint(nHint, ScAddress());
+ ScAddress& rPos = aHint.GetAddress();
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ rPos.SetTab(nTab);
+ for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ {
+ rPos.SetCol(nCol);
+ for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
+ {
+ rPos.SetRow(nRow);
+ rBC.Broadcast(aHint);
+ }
+ }
+ }
+}
+
+}
+
+bool ScBroadcastAreaSlot::AreaBroadcast( const ScRange& rRange, sal_uLong nHint )
+{
+ if (aBroadcastAreaTbl.empty())
+ return false;
+
+ bool bInBroadcast = mbInBroadcastIteration;
+ mbInBroadcastIteration = true;
+ bool bIsBroadcasted = false;
+
+ mbHasErasedArea = false;
+
+ for (ScBroadcastAreas::const_iterator aIter( aBroadcastAreaTbl.begin()),
+ aIterEnd( aBroadcastAreaTbl.end()); aIter != aIterEnd; ++aIter )
+ {
+ if (mbHasErasedArea && isMarkedErased( aIter))
+ continue;
+
+ ScBroadcastArea* pArea = (*aIter).mpArea;
+ const ScRange& rAreaRange = pArea->GetRange();
+
+ // Take the union of the area range and the broadcast range.
+ ScRange aUnion = rAreaRange.Union(rRange);
+ if (!aUnion.IsValid())
+ continue;
+
+ if (pArea->IsGroupListening())
+ {
+ if (pBASM->IsInBulkBroadcast())
+ {
+ pBASM->InsertBulkGroupArea(pArea, aUnion);
+ }
+ else
+ {
+ broadcastRangeByCell(pArea->GetBroadcaster(), aUnion, nHint);
+ bIsBroadcasted = true;
+ }
+ }
+ else if (!pBASM->IsInBulkBroadcast() || pBASM->InsertBulkArea( pArea))
+ {
+ broadcastRangeByCell(pArea->GetBroadcaster(), aUnion, nHint);
+ bIsBroadcasted = true;
+ }
+ }
+
+ mbInBroadcastIteration = bInBroadcast;
+
+ // A Notify() during broadcast may call EndListeningArea() and thus dispose
+ // an area if it was the last listener, which would invalidate an iterator
+ // pointing to it, hence the real erase is done afterwards.
+ FinallyEraseAreas();
+
+ return bIsBroadcasted;
+}
+
bool ScBroadcastAreaSlot::AreaBroadcast( const ScHint& rHint)
{
if (aBroadcastAreaTbl.empty())
@@ -758,6 +835,29 @@ void ScBroadcastAreaSlotMachine::EndListeningArea(
}
}
+bool ScBroadcastAreaSlotMachine::AreaBroadcast( const ScRange& rRange, sal_uLong nHint )
+{
+ bool bBroadcasted = false;
+ SCTAB nEndTab = rRange.aEnd.Tab();
+ for (TableSlotsMap::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 )
+ {
+ if ( *pp )
+ bBroadcasted |= (*pp)->AreaBroadcast( rRange, nHint );
+ ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak);
+ }
+ }
+ return bBroadcasted;
+}
+
bool ScBroadcastAreaSlotMachine::AreaBroadcast( const ScHint& rHint ) const
{
const ScAddress& rAddress = rHint.GetAddress();
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index 5ea4ce59f338..b7bdf3070a48 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -100,24 +100,72 @@ void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
{
ClearFormulaContext();
- ScBulkBroadcast aBulkBroadcast(pBASM);
+ if (!pBASM)
+ return; // Clipboard or Undo
+
+ SCTAB nTab1 = rRange.aStart.Tab();
+ SCTAB nTab2 = rRange.aEnd.Tab();
+ SCROW nRow1 = rRange.aStart.Row();
+ SCROW nRow2 = rRange.aEnd.Row();
+ SCCOL nCol1 = rRange.aStart.Col();
+ SCCOL nCol2 = rRange.aEnd.Col();
ScHint aHint(nHint, ScAddress());
ScAddress& rPos = aHint.GetAddress();
- for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+
+ if (!bHardRecalcState)
{
- rPos.SetTab(nTab);
- for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ ScBulkBroadcast aBulkBroadcast( pBASM); // scoped bulk broadcast
+ bool bIsBroadcasted = false;
+
+ for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
{
- rPos.SetCol(nCol);
- for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
+ rPos.SetTab(nTab);
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
{
rPos.SetRow(nRow);
- Broadcast(aHint);
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ rPos.SetCol(nCol);
+ SvtBroadcaster* pBC = GetBroadcaster(rPos);
+ if (pBC)
+ {
+ pBC->Broadcast(aHint);
+ bIsBroadcasted = true;
+ }
+ }
+ }
+ }
+
+ if (pBASM->AreaBroadcast(rRange, nHint) || bIsBroadcasted)
+ TrackFormulas(nHint);
+ }
+
+ // Repaint fuer bedingte Formate mit relativen Referenzen:
+ for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
+ if (pCondFormList)
+ {
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ pCondFormList->SourceChanged(ScAddress(nCol,nRow,nTab));
}
}
}
+ for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (pTab)
+ pTab->SetStreamValid(false);
+ }
+
BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
}
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 2b6219284d4f..8b5821719008 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2590,7 +2590,6 @@ class BroadcastAction : public sc::ColumnSpanSet::ColumnAction
{
ScDocument& mrDoc;
ScColumn* mpCol;
- std::vector<SCROW> maRows;
public:
BroadcastAction( ScDocument& rDoc ) : mrDoc(rDoc), mpCol(NULL) {}
@@ -2606,12 +2605,9 @@ public:
return;
assert(mpCol);
- maRows.clear();
- maRows.reserve(nRow2-nRow1+1);
- for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
- maRows.push_back(nRow);
-
- mpCol->BroadcastCells(maRows, SC_HINT_DATACHANGED);
+ ScRange aRange(mpCol->GetCol(), nRow1, mpCol->GetTab());
+ aRange.aEnd.SetRow(nRow2);
+ mrDoc.BroadcastCells(aRange, SC_HINT_DATACHANGED);
};
};