diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-17 17:37:07 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-18 08:31:57 -0500 |
commit | 6b4e767cf90e4f384a6b3dd43aa51c09b500b97b (patch) | |
tree | a9a06d522bab185c7df24a6958daf9e59dbefa6a | |
parent | 627bfb4e664a3fde23c06aa4dd0809de84ec97c5 (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.hxx | 3 | ||||
-rw-r--r-- | sc/inc/table.hxx | 3 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 22 | ||||
-rw-r--r-- | sc/source/core/data/column4.cxx | 93 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 9 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 5 |
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( |