summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-17 17:37:07 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-18 08:31:57 -0500
commit6b4e767cf90e4f384a6b3dd43aa51c09b500b97b (patch)
treea9a06d522bab185c7df24a6958daf9e59dbefa6a
parent627bfb4e664a3fde23c06aa4dd0809de84ec97c5 (diff)
Use group-area listeners during copy & paste if we can.
This should reduce the number of area listeners generated esp. when replicating tons of formula cells down the column. Change-Id: I1ea8f51f667e6b0e1a646f84d79f5e8430b478d5
-rw-r--r--sc/inc/column.hxx3
-rw-r--r--sc/inc/table.hxx3
-rw-r--r--sc/source/core/data/column3.cxx22
-rw-r--r--sc/source/core/data/column4.cxx93
-rw-r--r--sc/source/core/data/document.cxx9
-rw-r--r--sc/source/core/data/formulacell.cxx6
-rw-r--r--sc/source/core/data/table2.cxx5
7 files changed, 113 insertions, 28 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index adcd17ae2284..6187d4e1d2e0 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -255,7 +255,8 @@ public:
void CopyFromClip(
sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn );
- void StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
+ void StartListeningInArea(
+ sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt, SCROW nRow1, SCROW nRow2 );
void RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index ea1e2a30ea26..b1e06e102f28 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -437,7 +437,8 @@ public:
SCsCOL nDx, SCsROW nDy, ScTable* pTable );
void StartListeningInArea(
- sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+ sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
void SetDirtyFromClip(
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans );
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 6f31cf5fe900..67c51be7e39e 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1535,28 +1535,6 @@ void ScColumn::StartNeededListeners()
namespace {
-class StartListeningInAreaHandler
-{
- sc::StartListeningContext& mrCxt;
-public:
- StartListeningInAreaHandler(sc::StartListeningContext& rCxt) : mrCxt(rCxt) {}
-
- void operator() (size_t /*nRow*/, ScFormulaCell* p)
- {
- p->StartListeningTo(mrCxt);
- }
-};
-
-}
-
-void ScColumn::StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
-{
- StartListeningInAreaHandler aFunc(rCxt);
- sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
-}
-
-namespace {
-
void applyTextNumFormat( ScColumn& rCol, SCROW nRow, SvNumberFormatter* pFormatter )
{
sal_uInt32 nFormat = pFormatter->GetStandardFormat(NUMBERFORMAT_TEXT);
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index f0d28eb82dd5..925bb4cabb56 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1135,4 +1135,97 @@ bool ScColumn::HasFormulaCell( SCROW nRow1, SCROW nRow2 ) const
return aRet.first != maCells.end();
}
+namespace {
+
+class StartListeningInAreaHandler
+{
+ sc::StartListeningContext& mrStartCxt;
+ sc::EndListeningContext& mrEndCxt;
+
+public:
+ StartListeningInAreaHandler( sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt ) :
+ mrStartCxt(rStartCxt), mrEndCxt(rEndCxt) {}
+
+ void operator() ( const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize )
+ {
+ if (node.type != sc::element_type_formula)
+ // We are only interested in formulas.
+ return;
+
+ ScFormulaCell** ppBeg = &sc::formula_block::at(*node.data, nOffset);
+ ScFormulaCell** ppEnd = ppBeg + nDataSize;
+
+ ScFormulaCell** pp = ppBeg;
+
+ // If the first formula cell belongs to a group and it's not the top
+ // cell, move up to the top cell of the group, and have all the extra
+ // formula cells stop listening.
+
+ ScFormulaCell* pFC = *pp;
+ if (pFC->IsShared() && !pFC->IsSharedTop())
+ {
+ SCROW nBackTrackSize = pFC->aPos.Row() - pFC->GetSharedTopRow();
+ if (nBackTrackSize > 0)
+ {
+ assert(static_cast<size_t>(nBackTrackSize) <= nOffset);
+ for (SCROW i = 0; i < nBackTrackSize; ++i)
+ --pp;
+ endListening(pp, ppBeg);
+ }
+ }
+
+ for (; pp != ppEnd; ++pp)
+ {
+ pFC = *pp;
+
+ if (!pFC->IsSharedTop())
+ {
+ pFC->StartListeningTo(mrStartCxt);
+ continue;
+ }
+
+ // If This is the last group in the range, see if the group
+ // extends beyond the range, in which case have the excess
+ // formula cells stop listening.
+ size_t nEndGroupPos = (pp - ppBeg) + pFC->GetSharedLength();
+ if (nEndGroupPos > nDataSize)
+ {
+ size_t nExcessSize = nEndGroupPos - nDataSize;
+ ScFormulaCell** ppGrpEnd = pp + pFC->GetSharedLength();
+ ScFormulaCell** ppGrp = ppGrpEnd - nExcessSize;
+ endListening(ppGrp, ppGrpEnd);
+
+ // Register formula cells as a group.
+ sc::SharedFormulaUtil::startListeningAsGroup(mrStartCxt, pp);
+ pp = ppEnd - 1; // Move to the one before the end position.
+ }
+ else
+ {
+ // Register formula cells as a group.
+ sc::SharedFormulaUtil::startListeningAsGroup(mrStartCxt, pp);
+ pp += pFC->GetSharedLength() - 1; // Move to the last one in the group.
+ }
+ }
+ }
+
+private:
+ void endListening( ScFormulaCell** pp, ScFormulaCell** ppEnd )
+ {
+ for (; pp != ppEnd; ++pp)
+ {
+ ScFormulaCell& rFC = **pp;
+ rFC.EndListeningTo(mrEndCxt);
+ }
+ }
+};
+
+}
+
+void ScColumn::StartListeningInArea(
+ sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt, SCROW nRow1, SCROW nRow2 )
+{
+ StartListeningInAreaHandler aFunc(rStartCxt, rEndCxt);
+ sc::ProcessBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 8440e2b303ae..8e3871f4c91d 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2420,12 +2420,17 @@ void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
{
if (nInsFlag & IDF_CONTENTS)
{
- sc::StartListeningContext aCxt(*this);
+ boost::shared_ptr<sc::ColumnBlockPositionSet> pSet(
+ new sc::ColumnBlockPositionSet(*this));
+
+ sc::StartListeningContext aStartCxt(*this, pSet);
+ sc::EndListeningContext aEndCxt(*this, pSet, NULL);
+
SCTAB nMax = static_cast<SCTAB>(maTabs.size());
ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
for (; itr != itrEnd && *itr < nMax; ++itr)
if (maTabs[*itr])
- maTabs[*itr]->StartListeningInArea(aCxt, nCol1, nRow1, nCol2, nRow2);
+ maTabs[*itr]->StartListeningInArea(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2);
}
}
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 6b3cbe46ba28..788cb73cf96d 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3947,6 +3947,9 @@ void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
if (pDoc->IsClipOrUndo() || IsInChangeTrack())
return;
+ if (!HasBroadcaster())
+ return;
+
pDoc->SetDetectiveDirty(true); // It has changed something
if ( GetCode()->IsRecalcModeAlways() )
@@ -3989,6 +3992,9 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt )
if (rCxt.getDoc().IsClipOrUndo() || IsInChangeTrack())
return;
+ if (!HasBroadcaster())
+ return;
+
ScDocument& rDoc = rCxt.getDoc();
rDoc.SetDetectiveDirty(true); // It has changed something
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 66db45d72794..8d7ecc6ff138 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1060,13 +1060,14 @@ void ScTable::SetDirtyFromClip(
}
void ScTable::StartListeningInArea(
- sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+ sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
{
if (nCol2 > MAXCOL) nCol2 = MAXCOL;
if (nRow2 > MAXROW) nRow2 = MAXROW;
if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
for (SCCOL i = nCol1; i <= nCol2; i++)
- aCol[i].StartListeningInArea(rCxt, nRow1, nRow2);
+ aCol[i].StartListeningInArea(rStartCxt, rEndCxt, nRow1, nRow2);
}
void ScTable::CopyToTable(