summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-13 20:14:27 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-18 08:31:55 -0500
commit192f6a41444b62feae03185975c120f770e2938f (patch)
treeb85e6c19a1465f0da8ab329dd6839978519cbec4 /sc/source/core
parente969c131a2d8ca21d32e5caaa302ee904021a1e5 (diff)
Reduce duplicate broadcasting done when pasting a range of cells from clip.
We do pasting from clip in 2 steps: 1) delete the destination range, then 2) paste the content onto the destination range. The old code would broadcast both during 1) and 2). This change consolidates them and do broadcasting only once at the end, and also avoids broadcasting the same cell twice, which the old code sometimes did. Change-Id: Ic524c2b70888ce158619d99cbfb55dea85870497
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/column.cxx23
-rw-r--r--sc/source/core/data/column3.cxx17
-rw-r--r--sc/source/core/data/document.cxx77
-rw-r--r--sc/source/core/data/table2.cxx12
4 files changed, 102 insertions, 27 deletions
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 123ff9911861..86faef861db9 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2634,6 +2634,18 @@ public:
maValueRanges.getRows(aRows);
mrColumn.BroadcastCells(aRows, SC_HINT_DATACHANGED);
}
+
+ void fillBroadcastSpans( sc::ColumnSpanSet& rBroadcastSpans ) const
+ {
+ SCCOL nCol = mrColumn.GetCol();
+ SCTAB nTab = mrColumn.GetTab();
+ sc::SingleColumnSpanSet::SpansType aSpans;
+ maValueRanges.getSpans(aSpans);
+
+ sc::SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
+ for (; it != itEnd; ++it)
+ rBroadcastSpans.set(nTab, nCol, it->mnRow1, it->mnRow2, true);
+ }
};
class SetTableOpDirtyOnRangeHandler
@@ -3006,6 +3018,17 @@ void ScColumn::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
sc::ProcessFormula(maCells, aFunc);
}
+void ScColumn::BroadcastInArea( SCROW nRow1, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
+{
+ // Set all formula cells in the range dirty, and pick up all non-formula
+ // cells for later broadcasting. We don't broadcast here.
+ sc::AutoCalcSwitch aSwitch(*pDocument, false);
+
+ SetDirtyOnRangeHandler aHdl(*this);
+ sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
+ aHdl.fillBroadcastSpans(rBroadcastSpans);
+}
+
void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2 )
{
// broadcasts everything within the range, with FormulaTracking
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index d37120c7b8ce..6f31cf5fe900 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -559,6 +559,7 @@ class EmptyCells
{
ScColumn& mrColumn;
sc::ColumnBlockPosition& mrPos;
+ sc::ColumnSpanSet* mpCellSpans;
void splitFormulaGrouping(const sc::CellStoreType::position_type& rPos)
{
@@ -570,8 +571,8 @@ class EmptyCells
}
public:
- EmptyCells(sc::ColumnBlockPosition& rPos, ScColumn& rColumn) :
- mrColumn(rColumn), mrPos(rPos) {}
+ EmptyCells( sc::ColumnBlockPosition& rPos, ScColumn& rColumn, sc::ColumnSpanSet* pCellSpans ) :
+ mrColumn(rColumn), mrPos(rPos), mpCellSpans(pCellSpans) {}
void operator() (const sc::RowSpan& rSpan)
{
@@ -586,6 +587,9 @@ public:
mrPos.miCellPos = rCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
mrPos.miCellTextAttrPos = mrColumn.GetCellAttrStore().set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
+
+ if (mpCellSpans)
+ mpCellSpans->set(mrColumn.GetTab(), mrColumn.GetCol(), rSpan.mnRow1, rSpan.mnRow2, true);
}
};
@@ -593,7 +597,7 @@ public:
void ScColumn::DeleteCells(
sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nDelFlag,
- std::vector<SCROW>& rDeleted )
+ std::vector<SCROW>& rDeleted, sc::ColumnSpanSet* pDeletedSpans )
{
// Determine which cells to delete based on the deletion flags.
DeleteAreaHandler aFunc(*pDocument, nDelFlag);
@@ -610,12 +614,13 @@ void ScColumn::DeleteCells(
aFunc.getSpans().getSpans(aSpans);
// Delete the cells for real.
- std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(rBlockPos, *this));
+ std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(rBlockPos, *this, pDeletedSpans));
CellStorageModified();
}
void ScColumn::DeleteArea(
- SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast )
+ SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast,
+ sc::ColumnSpanSet* pBroadcastSpans )
{
InsertDeleteFlags nContMask = IDF_CONTENTS;
// IDF_NOCAPTIONS needs to be passed too, if IDF_NOTE is set
@@ -629,7 +634,7 @@ void ScColumn::DeleteArea(
InitBlockPosition(aBlockPos);
if (!IsEmptyData() && nContFlag)
- DeleteCells(aBlockPos, nStartRow, nEndRow, nDelFlag, aDeletedRows);
+ DeleteCells(aBlockPos, nStartRow, nEndRow, nDelFlag, aDeletedRows, pBroadcastSpans);
if (nDelFlag & IDF_NOTE)
DeleteCellNotes(aBlockPos, nStartRow, nEndRow);
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index c9afcf08387c..2b6219284d4f 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1761,19 +1761,19 @@ void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, bool bClear
}
}
-void ScDocument::DeleteArea(SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2,
- const ScMarkData& rMark, InsertDeleteFlags nDelFlag)
+void ScDocument::DeleteArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ InsertDeleteFlags nDelFlag, bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans )
{
+ sc::AutoCalcSwitch aACSwitch(*this, false);
+
PutInOrder( nCol1, nCol2 );
PutInOrder( nRow1, nRow2 );
- bool bOldAutoCalc = GetAutoCalc();
- SetAutoCalc( false ); // avoid multiple calculations
for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
if (maTabs[i])
if ( rMark.GetTableSelect(i) || bIsUndo )
- maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
- SetAutoCalc( bOldAutoCalc );
+ maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag, bBroadcast, pBroadcastSpans);
+
}
void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1,
@@ -2429,9 +2429,9 @@ void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
}
}
-void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2,
- const ScMarkData& rMark, InsertDeleteFlags nInsFlag )
+void ScDocument::BroadcastFromClip(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ InsertDeleteFlags nInsFlag, sc::ColumnSpanSet& rBroadcastSpans )
{
if (nInsFlag & IDF_CONTENTS)
{
@@ -2440,7 +2440,7 @@ void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
for (; itr != itrEnd && *itr < nMax; ++itr)
if (maTabs[*itr])
- maTabs[*itr]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 );
+ maTabs[*itr]->BroadcastInArea(nCol1, nRow1, nCol2, nRow2, rBroadcastSpans);
}
}
@@ -2584,6 +2584,39 @@ void ScDocument::CopyNonFilteredFromClip(
rClipStartRow = nSourceRow;
}
+namespace {
+
+class BroadcastAction : public sc::ColumnSpanSet::ColumnAction
+{
+ ScDocument& mrDoc;
+ ScColumn* mpCol;
+ std::vector<SCROW> maRows;
+
+public:
+ BroadcastAction( ScDocument& rDoc ) : mrDoc(rDoc), mpCol(NULL) {}
+
+ virtual void startColumn( ScColumn* pCol ) SAL_OVERRIDE
+ {
+ mpCol = pCol;
+ }
+
+ virtual void execute( SCROW nRow1, SCROW nRow2, bool bVal ) SAL_OVERRIDE
+ {
+ if (!bVal)
+ 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);
+ };
+};
+
+}
+
void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
InsertDeleteFlags nInsFlag,
ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut,
@@ -2667,6 +2700,8 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
bInsertingFromOtherDoc = true; // kein Broadcast/Listener aufbauen bei Insert
+ sc::ColumnSpanSet aBroadcastSpans(false);
+
SCCOL nClipStartCol = aClipRange.aStart.Col();
SCROW nClipStartRow = aClipRange.aStart.Row();
SCROW nClipEndRow = aClipRange.aEnd.Row();
@@ -2685,7 +2720,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
DeleteBeforeCopyFromClip(aCxt, rMark);
}
else
- DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
+ DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag, false, &aBroadcastSpans);
if (CopyOneCellFromClip(aCxt, nCol1, nRow1, nCol2, nRow2))
continue;
@@ -2785,7 +2820,14 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
// Listener aufbauen nachdem alles inserted wurde
StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
// nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
- BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
+ BroadcastFromClip(nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag, aBroadcastSpans);
+
+ {
+ ScBulkBroadcast aBulkBroadcast( GetBASM());
+ BroadcastAction aAction(*this);
+ aBroadcastSpans.executeColumnAction(*this, aAction);
+ }
+
if (bResetCut)
pClipDoc->GetClipParam().mbCutMode = false;
}
@@ -2815,6 +2857,8 @@ void ScDocument::CopyMultiRangeFromClip(
SCROW nRow1 = rDestPos.Row();
ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ sc::ColumnSpanSet aBroadcastSpans(false);
+
if (!bSkipAttrForEmpty)
{
// Do the deletion first.
@@ -2822,7 +2866,7 @@ void ScDocument::CopyMultiRangeFromClip(
SCCOL nColSize = rClipParam.getPasteColSize();
SCROW nRowSize = rClipParam.getPasteRowSize();
- DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag);
+ DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag, false, &aBroadcastSpans);
}
sc::CopyFromClipContext aCxt(*this, NULL, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
@@ -2861,8 +2905,9 @@ void ScDocument::CopyMultiRangeFromClip(
StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
// nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
- BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
- aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
+ BroadcastFromClip(
+ aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aEnd.Col(), aDestRange.aEnd.Row(),
+ rMark, nInsFlag, aBroadcastSpans);
if (bResetCut)
pClipDoc->GetClipParam().mbCutMode = false;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index fd3c045b9f4e..c46977e39f0d 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -410,7 +410,9 @@ void ScTable::DeleteCol(
SetStreamValid(false);
}
-void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag)
+void ScTable::DeleteArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag,
+ bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans )
{
if (nCol2 > MAXCOL) nCol2 = MAXCOL;
if (nRow2 > MAXROW) nRow2 = MAXROW;
@@ -419,7 +421,7 @@ void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, Ins
{ // scope for bulk broadcast
ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
for (SCCOL i = nCol1; i <= nCol2; i++)
- aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
+ aCol[i].DeleteArea(nRow1, nRow2, nDelFlag, bBroadcast, pBroadcastSpans);
}
// Zellschutz auf geschuetzter Tabelle nicht setzen
@@ -1047,14 +1049,14 @@ void ScTable::StartNeededListeners()
aCol[i].StartNeededListeners();
}
-void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2 )
+void ScTable::BroadcastInArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
{
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].SetDirty(nRow1, nRow2);
+ aCol[i].BroadcastInArea(nRow1, nRow2, rBroadcastSpans);
}
void ScTable::StartListeningInArea(