diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-21 20:50:59 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-21 20:55:53 -0500 |
commit | 5432e2a5ef7a3e131d2496e19bd0c6a86955319f (patch) | |
tree | cf7a7139a56e88795274de6d53f2cc2362454887 /sc | |
parent | 5dd60299c668cd36cc5cc5e8bd5b162e1fc9ef13 (diff) |
Use group area listeners when deleting rows.
Change-Id: I9ceb1cabf448349e087e4d5c4c2b1a75af91dd75
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 12 | ||||
-rw-r--r-- | sc/inc/document.hxx | 1 | ||||
-rw-r--r-- | sc/inc/sharedformula.hxx | 12 | ||||
-rw-r--r-- | sc/inc/table.hxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/bcaslot.cxx | 1 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 16 | ||||
-rw-r--r-- | sc/source/core/data/column4.cxx | 29 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 17 | ||||
-rw-r--r-- | sc/source/core/data/document10.cxx | 17 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 18 | ||||
-rw-r--r-- | sc/source/core/data/table7.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/tool/sharedformula.cxx | 17 |
12 files changed, 124 insertions, 28 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 7c6b2cd0d3b8..102af126fc78 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, @@ -592,7 +599,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 3dcdf08c0082..554ee3a9afc1 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -2183,6 +2183,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 8b6fa92f7f92..ae58aecf50a5 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 43946e53503c..777f5a4666c7 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -1398,6 +1398,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 8984e28cf557..a206c09b5e04 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 a787f6374bf4..97355424c8c3 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) |