summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-21 20:50:59 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-21 20:50:59 -0500
commitc488dbfb60f057fd752e01c8a4ceabffcb22da40 (patch)
treef69d3bd417a39764739593328c1cc3bd0b2803d0
parent15bf6a424836cc1acb927371047ec65807e59039 (diff)
Use group area listeners when deleting rows.
Change-Id: I9ceb1cabf448349e087e4d5c4c2b1a75af91dd75
-rw-r--r--sc/inc/column.hxx12
-rw-r--r--sc/inc/document.hxx1
-rw-r--r--sc/inc/sharedformula.hxx12
-rw-r--r--sc/inc/table.hxx4
-rw-r--r--sc/source/core/data/bcaslot.cxx1
-rw-r--r--sc/source/core/data/column3.cxx16
-rw-r--r--sc/source/core/data/column4.cxx29
-rw-r--r--sc/source/core/data/document.cxx17
-rw-r--r--sc/source/core/data/document10.cxx17
-rw-r--r--sc/source/core/data/table2.cxx18
-rw-r--r--sc/source/core/data/table7.cxx8
-rw-r--r--sc/source/core/tool/sharedformula.cxx17
12 files changed, 124 insertions, 28 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index e07c5ff9f04f..86fe906c7335 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -229,7 +229,14 @@ public:
bool TestInsertCol( SCROW nStartRow, SCROW nEndRow) const;
bool TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const;
void InsertRow( SCROW nStartRow, SCSIZE nSize );
- void DeleteRow( SCROW nStartRow, SCSIZE nSize );
+
+ /**
+ * @param nStartRow top row position
+ * @param nSize size of the segment to delete.
+ * @param pGroupPos when non-NULL, stores the top position of formula
+ * group that's been merged as a result of row deletion.
+ */
+ void DeleteRow( SCROW nStartRow, SCSIZE nSize, std::vector<ScAddress>* pGroupPos = NULL );
void DeleteArea(
SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag,
@@ -594,7 +601,7 @@ public:
/**
* Regroup formula cells for the entire column.
*/
- void RegroupFormulaCells();
+ void RegroupFormulaCells( std::vector<ScAddress>* pGroupPos = NULL );
/**
* Reset column position of formula cells within specified row range.
@@ -669,6 +676,7 @@ private:
void EndListeningIntersectedGroups(
sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2, std::vector<ScAddress>* pGroupPos = NULL );
+ void EndListeningGroup( sc::EndListeningContext& rCxt, SCROW nRow );
void SetNeedsListeningGroup( SCROW nRow );
};
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index acf0f67241cd..f9f0310ff11c 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -2182,6 +2182,7 @@ private:
void EndListeningIntersectedGroups(
sc::EndListeningContext& rCxt, const ScRange& rRange, std::vector<ScAddress>* pGroupPos = NULL );
+ void EndListeningGroups( const std::vector<ScAddress>& rPosArray );
void SetNeedsListeningGroups( const std::vector<ScAddress>& rPosArray );
};
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index e1799bf70e0b..d94d8fe39e08 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -82,17 +82,23 @@ public:
* @param rPos position object of the first cell
* @param rCell1 first cell
* @param rCell2 second cell located immediately below the first cell.
+ *
+ * @return true if the cells are merged, false otherwise. If the two
+ * cells already belong to the same group, it returns false.
*/
- static void joinFormulaCells(
- const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2);
+ static bool joinFormulaCells(
+ const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2 );
/**
* Merge with an existing formula group (if any) located immediately above
* if the cell at specified position is a formula cell, and its formula
* tokens are identical to that of the above formula group.
*
* @param aPos position of cell to examine.
+ *
+ * @return true if the cells are merged, false otherwise. If the two
+ * cells already belong to the same group, it returns false.
*/
- static void joinFormulaCellAbove(const CellStoreType::position_type& aPos);
+ static bool joinFormulaCellAbove( const CellStoreType::position_type& aPos );
/**
* Turn a shared formula cell into a non-shared one, and split it off from
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 56af84199250..0d0a5c43a9c0 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -403,7 +403,8 @@ public:
bool TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) const;
void InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize );
void DeleteRow(
- const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize, bool* pUndoOutline = NULL );
+ const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
+ bool* pUndoOutline = NULL, std::vector<ScAddress>* pGroupPos = NULL );
bool TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) const;
void InsertCol(
@@ -1113,6 +1114,7 @@ private:
sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
std::vector<ScAddress>* pGroupPos = NULL );
+ void EndListeningGroup( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow );
void SetNeedsListeningGroup( SCCOL nCol, SCROW nRow );
/**
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index d2edf54d2e7c..0678a7febc70 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -626,6 +626,7 @@ void ScBroadcastAreaSlot::Dump() const
size_t n = rListeners.size();
cout << " * range: " << rtl::OUStringToOString(pArea->GetRange().Format(SCA_VALID|SCA_TAB_3D, pDoc), RTL_TEXTENCODING_UTF8).getStr()
+ << ", group: " << pArea->IsGroupListening()
<< ", listener count: " << n << endl;
for (size_t i = 0; i < n; ++i)
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 7d6c938ff983..33a38e031090 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -152,7 +152,7 @@ public:
}
-void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
+void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize, std::vector<ScAddress>* pGroupPos )
{
pAttrArray->DeleteRow( nStartRow, nSize );
@@ -221,7 +221,9 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
ShiftFormulaPosHandler aShiftFormulaFunc;
sc::ProcessFormula(aPos.first, maCells, nStartRow, MAXROW, aShiftFormulaFunc);
- sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+ bool bJoined = sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+ if (bJoined && pGroupPos)
+ pGroupPos->push_back(ScAddress(nCol, nStartRow, nTab));
// Shift the text attribute array too (before the broadcast).
maCellTextAttrs.erase(nStartRow, nEndRow);
@@ -2873,8 +2875,11 @@ namespace {
class GroupFormulaCells
{
ScFormulaCellGroupRef mxNone;
+ std::vector<ScAddress>* mpGroupPos;
public:
+ GroupFormulaCells( std::vector<ScAddress>* pGroupPos ) :
+ mpGroupPos(pGroupPos) {}
void operator() (sc::CellStoreType::value_type& node)
{
@@ -2977,6 +2982,9 @@ public:
++it;
}
+ if (mpGroupPos)
+ mpGroupPos->push_back(pCur->aPos);
+
pCur = pPrev;
xCurGrp = xPrevGrp;
}
@@ -2985,10 +2993,10 @@ public:
}
-void ScColumn::RegroupFormulaCells()
+void ScColumn::RegroupFormulaCells( std::vector<ScAddress>* pGroupPos )
{
// re-build formula groups.
- std::for_each(maCells.begin(), maCells.end(), GroupFormulaCells());
+ std::for_each(maCells.begin(), maCells.end(), GroupFormulaCells(pGroupPos));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index c9809f2430f7..92220f38c7eb 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1396,6 +1396,35 @@ void ScColumn::EndListeningIntersectedGroups(
}
}
+void ScColumn::EndListeningGroup( sc::EndListeningContext& rCxt, SCROW nRow )
+{
+ sc::CellStoreType::position_type aPos = maCells.position(nRow);
+ if (aPos.first->type != sc::element_type_formula)
+ // not a formula cell.
+ return;
+
+ ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second);
+
+ ScFormulaCellGroupRef xGroup = (*pp)->GetCellGroup();
+ if (!xGroup)
+ {
+ // not a formula group.
+ (*pp)->EndListeningTo(rCxt);
+ return;
+ }
+
+ // Move back to the top cell.
+ SCROW nTopDelta = (*pp)->aPos.Row() - xGroup->mpTopCell->aPos.Row();
+ for (SCROW i = 0; i < nTopDelta; ++i)
+ --pp;
+
+ // Set the needs listening flag to all cells in the group.
+ assert(*pp == xGroup->mpTopCell);
+ ScFormulaCell** ppEnd = pp + xGroup->mnLength;
+ for (; pp != ppEnd; ++pp)
+ (*pp)->EndListeningTo(rCxt);
+}
+
void ScColumn::SetNeedsListeningGroup( SCROW nRow )
{
sc::CellStoreType::position_type aPos = maCells.position(nRow);
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 4e3fd9d433b9..1a5c8be78c5b 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1307,8 +1307,7 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
nEndTab = static_cast<SCTAB>(maTabs.size())-1;
}
- bool bOldAutoCalc = GetAutoCalc();
- SetAutoCalc( false ); // avoid multiple calculations
+ sc::AutoCalcSwitch aACSwitch(*this, false); // avoid multiple calculations
// handle chunks of consecutive selected sheets together
SCTAB nTabRangeStart = nStartTab;
@@ -1349,9 +1348,20 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
if (pUndoOutline)
*pUndoOutline = false;
+ // Keep track of the positions of all formula groups that have been joined
+ // during row deletion.
+ std::vector<ScAddress> aGroupPos;
+
for ( i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
- maTabs[i]->DeleteRow(aCxt.maRegroupCols, nStartCol, nEndCol, nStartRow, nSize, pUndoOutline);
+ maTabs[i]->DeleteRow(aCxt.maRegroupCols, nStartCol, nEndCol, nStartRow, nSize, pUndoOutline, &aGroupPos);
+
+ // Newly joined groups have some of their members still listening. We
+ // need to make sure none of them are listening.
+ EndListeningGroups(aGroupPos);
+
+ // Mark all joined groups for group listening.
+ SetNeedsListeningGroups(aGroupPos);
if ( ValidRow(nStartRow+nSize) )
{
@@ -1368,7 +1378,6 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
}
- SetAutoCalc( bOldAutoCalc );
pChartListenerCollection->UpdateDirtyCharts();
}
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 48e933c9dfc5..d1b41687fb3e 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -370,6 +370,23 @@ void ScDocument::EndListeningIntersectedGroups(
}
}
+void ScDocument::EndListeningGroups( const std::vector<ScAddress>& rPosArray )
+{
+ sc::EndListeningContext aCxt(*this);
+ std::vector<ScAddress>::const_iterator it = rPosArray.begin(), itEnd = rPosArray.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScAddress& rPos = *it;
+ ScTable* pTab = FetchTable(rPos.Tab());
+ if (!pTab)
+ return;
+
+ pTab->EndListeningGroup(aCxt, rPos.Col(), rPos.Row());
+ }
+
+ aCxt.purgeEmptyBroadcasters();
+}
+
void ScDocument::SetNeedsListeningGroups( const std::vector<ScAddress>& rPosArray )
{
std::vector<ScAddress>::const_iterator it = rPosArray.begin(), itEnd = rPosArray.end();
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 938b6b0021e3..619a1f4136be 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -68,12 +68,15 @@ namespace {
class ColumnRegroupFormulaCells
{
ScColumn* mpCols;
+ std::vector<ScAddress>* mpGroupPos;
+
public:
- ColumnRegroupFormulaCells(ScColumn* pCols) : mpCols(pCols) {}
+ ColumnRegroupFormulaCells( ScColumn* pCols, std::vector<ScAddress>* pGroupPos ) :
+ mpCols(pCols), mpGroupPos(pGroupPos) {}
void operator() (SCCOL nCol)
{
- mpCols[nCol].RegroupFormulaCells();
+ mpCols[nCol].RegroupFormulaCells(mpGroupPos);
}
};
@@ -199,7 +202,7 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
void ScTable::DeleteRow(
const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
- bool* pUndoOutline )
+ bool* pUndoOutline, std::vector<ScAddress>* pGroupPos )
{
if (nStartCol==0 && nEndCol==MAXCOL)
{
@@ -240,12 +243,13 @@ void ScTable::DeleteRow(
{ // scope for bulk broadcast
ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
for (SCCOL j=nStartCol; j<=nEndCol; j++)
- aCol[j].DeleteRow( nStartRow, nSize );
+ aCol[j].DeleteRow(nStartRow, nSize, pGroupPos);
}
std::vector<SCCOL> aRegroupCols;
rRegroupCols.getColumns(nTab, aRegroupCols);
- std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
+ std::for_each(
+ aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol, pGroupPos));
InvalidatePageBreaks();
@@ -320,7 +324,7 @@ void ScTable::InsertCol(
std::vector<SCCOL> aRegroupCols;
rRegroupCols.getColumns(nTab, aRegroupCols);
- std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
+ std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol, NULL));
if (nStartCol>0) // copy old attributes
{
@@ -400,7 +404,7 @@ void ScTable::DeleteCol(
std::vector<SCCOL> aRegroupCols;
rRegroupCols.getColumns(nTab, aRegroupCols);
- std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
+ std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol, NULL));
InvalidatePageBreaks();
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index f9e429a49f06..274073508aea 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -210,6 +210,14 @@ void ScTable::EndListeningIntersectedGroups(
aCol[nCol].EndListeningIntersectedGroups(rCxt, nRow1, nRow2, pGroupPos);
}
+void ScTable::EndListeningGroup( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow )
+{
+ if (!ValidCol(nCol))
+ return;
+
+ aCol[nCol].EndListeningGroup(rCxt, nRow);
+}
+
void ScTable::SetNeedsListeningGroup( SCCOL nCol, SCROW nRow )
{
if (!ValidCol(nCol))
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index ce00fc31421e..67a40c27e79c 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -110,11 +110,12 @@ void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vecto
}
}
-void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
+bool SharedFormulaUtil::joinFormulaCells(
+ const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2 )
{
ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
if (eState == ScFormulaCell::NotEqual)
- return;
+ return false;
// Formula tokens equal those of the previous formula cell.
ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
@@ -126,7 +127,7 @@ void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPo
// Both cell 1 and cell 2 are shared. Merge them together.
if (xGroup1.get() == xGroup2.get())
// They belong to the same group.
- return;
+ return false;
// Set the group object from cell 1 to all cells in group 2.
xGroup1->mnLength += xGroup2->mnLength;
@@ -161,24 +162,26 @@ void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPo
rCell2.SetCellGroup(xGroup1);
}
}
+
+ return true;
}
-void SharedFormulaUtil::joinFormulaCellAbove(const CellStoreType::position_type& aPos)
+bool SharedFormulaUtil::joinFormulaCellAbove( const CellStoreType::position_type& aPos )
{
if (aPos.first->type != sc::element_type_formula)
// This is not a formula cell.
- return;
+ return false;
if (aPos.second == 0)
// This cell is already the top cell in a formula block; the previous
// cell is not a formula cell.
- return;
+ return false;
ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second);
sc::CellStoreType::position_type aPosPrev = aPos;
--aPosPrev.second;
- joinFormulaCells(aPosPrev, rPrev, rCell);
+ return joinFormulaCells(aPosPrev, rPrev, rCell);
}
void SharedFormulaUtil::unshareFormulaCell(const CellStoreType::position_type& aPos, ScFormulaCell& rCell)