diff options
-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 | 65 | ||||
-rw-r--r-- | sc/source/core/data/column4.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 13 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 51 |
6 files changed, 129 insertions, 10 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index ecbfeea6d09f..d26214bfa9fd 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -562,6 +562,9 @@ public: void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength ); + void AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ); + void DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ); + /** * Regroup formula cells for the entire column. */ diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index ab3526d4e375..413152eadd1c 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -1041,6 +1041,9 @@ private: void EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener ); void StartAllListeners(); + void AttachFormulaCells( sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); + void DetachFormulaCells( sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); + void SetLoadingMedium(bool bLoading); SCSIZE FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2, diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 38a92c031979..3008fec88a30 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -340,15 +340,35 @@ void ScColumn::DetachFormulaCell( namespace { +class AttachFormulaCellsHandler +{ + sc::StartListeningContext& mrCxt; + +public: + AttachFormulaCellsHandler( sc::StartListeningContext& rCxt ) : + mrCxt(rCxt) {} + + void operator() (size_t /*nRow*/, ScFormulaCell* pCell) + { + pCell->StartListeningTo(mrCxt); + } +}; + class DetachFormulaCellsHandler { ScDocument* mpDoc; + sc::EndListeningContext* mpCxt; + public: - DetachFormulaCellsHandler(ScDocument* pDoc) : mpDoc(pDoc) {} + DetachFormulaCellsHandler( ScDocument* pDoc, sc::EndListeningContext* pCxt ) : + mpDoc(pDoc), mpCxt(pCxt) {} void operator() (size_t /*nRow*/, ScFormulaCell* pCell) { - pCell->EndListeningTo(mpDoc); + if (mpCxt) + pCell->EndListeningTo(*mpCxt); + else + pCell->EndListeningTo(mpDoc); } }; @@ -370,10 +390,49 @@ void ScColumn::DetachFormulaCells( if (pDocument->IsClipOrUndo()) return; - DetachFormulaCellsHandler aFunc(pDocument); + DetachFormulaCellsHandler aFunc(pDocument, NULL); sc::ProcessFormula(aPos.first, maCells, nRow, nNextTopRow-1, aFunc); } +void ScColumn::AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ) +{ + sc::CellStoreType::position_type aPos = maCells.position(nRow1); + sc::CellStoreType::iterator it = aPos.first; + + sc::SharedFormulaUtil::joinFormulaCellAbove(aPos); + if (ValidRow(nRow2+1)) + { + aPos = maCells.position(it, nRow2+1); + sc::SharedFormulaUtil::joinFormulaCellAbove(aPos); + } + + if (pDocument->IsClipOrUndo()) + return; + + AttachFormulaCellsHandler aFunc(rCxt); + sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc); +} + +void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ) +{ + sc::CellStoreType::position_type aPos = maCells.position(nRow1); + sc::CellStoreType::iterator it = aPos.first; + + // Split formula grouping at the top and bottom boundaries. + sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); + if (ValidRow(nRow2+1)) + { + aPos = maCells.position(it, nRow2+1); + sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); + } + + if (pDocument->IsClipOrUndo()) + return; + + DetachFormulaCellsHandler aFunc(pDocument, &rCxt); + sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc); +} + sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow ) { // See if we are overwriting an existing formula cell. diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index 2698f0b5f647..2bef7ba9f8cc 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -300,7 +300,7 @@ void ScColumn::TransferCellValuesFrom( SCROW nRow, sc::CellValues& rSrc ) return; sc::CellStoreType::position_type aPos = maCells.position(nRow); - DetachFormulaCells(aPos, rSrc.size()); +// DetachFormulaCells(aPos, rSrc.size()); rSrc.transferTo(*this, nRow); @@ -311,7 +311,7 @@ void ScColumn::TransferCellValuesFrom( SCROW nRow, sc::CellValues& rSrc ) for (SCROW i = nRow; i <= nLastRow; ++i) aRows.push_back(i); - BroadcastCells(aRows, SC_HINT_DATACHANGED); +// BroadcastCells(aRows, SC_HINT_DATACHANGED); } void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc ) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index af2492ea4e11..8c1842c135fa 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1031,6 +1031,19 @@ void ScTable::StartAllListeners() aCol[i].StartAllListeners(); } +void ScTable::AttachFormulaCells( + sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + aCol[nCol].AttachFormulaCells(rCxt, nRow1, nRow2); +} + +void ScTable::DetachFormulaCells( + sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + aCol[nCol].DetachFormulaCells(rCxt, nRow1, nRow2); +} void ScTable::StartNeededListeners() { diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 97c978ff149e..b8db3c614404 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -58,6 +58,7 @@ #include "columnspanset.hxx" #include <stlalgorithm.hxx> #include <cellvalues.hxx> +#include <listenercontext.hxx> #include "svl/sharedstringpool.hxx" @@ -375,6 +376,15 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 ) return pArray; } +namespace { + +struct SortedColumn : boost::noncopyable +{ + sc::CellValues maCells; /// Stores cells and cell text attributes. + sc::BroadcasterStoreType maBroadcasters; +}; + +} bool ScTable::IsSortCollatorGlobal() const { @@ -423,14 +433,18 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) ScSortInfoArray::RowsType* pRows = pArray->GetDataRows(); assert(pRows); // In sort-by-row mode we must have data rows already populated. + // Detach all formula cells within the sorted range first. + sc::EndListeningContext aCxt(*pDocument); + DetachFormulaCells(aCxt, aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2); + // Cells in the data rows only reference values in the document. Make // a copy before updating the document. size_t nColCount = aSortParam.nCol2 - aSortParam.nCol1 + 1; - boost::ptr_vector<sc::CellValues> aSortedCols; // storage for copied cells. + boost::ptr_vector<SortedColumn> aSortedCols; // storage for copied cells. aSortedCols.reserve(nColCount); for (size_t i = 0; i < nColCount; ++i) - aSortedCols.push_back(new sc::CellValues); + aSortedCols.push_back(new SortedColumn); for (size_t i = 0; i < pRows->size(); ++i) { @@ -438,9 +452,20 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) for (size_t nCol = 0; nCol < pRow->size(); ++nCol) { ScSortInfoArray::Cell& rCell = (*pRow)[nCol]; - sc::CellValues& rStore = aSortedCols.at(nCol); + + sc::CellValues& rStore = aSortedCols.at(nCol).maCells; ScAddress aCellPos(aSortParam.nCol1 + nCol, aSortParam.nRow1 + i, nTab); rStore.append(rCell.maCell, rCell.mpAttr, aCellPos); + + // At this point each broadcaster instance is managed by 2 + // containers. We will release those in the original storage + // below before transferring them to the document. + sc::BroadcasterStoreType& rBCStore = aSortedCols.at(nCol).maBroadcasters; + size_t n = rBCStore.size(); + rBCStore.resize(n+1); + if (rCell.mpBroadcaster) + // A const pointer would be implicitly converted to a bool type. + rBCStore.set(n, const_cast<SvtBroadcaster*>(rCell.mpBroadcaster)); } if (pProgress) @@ -449,9 +474,25 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) for (size_t i = 0, n = aSortedCols.size(); i < n; ++i) { - sc::CellValues& rSortedCol = aSortedCols[i]; - TransferCellValuesFrom(i+aSortParam.nCol1, aSortParam.nRow1, rSortedCol); + SCCOL nThisCol = i + aSortParam.nCol1; + TransferCellValuesFrom(nThisCol, aSortParam.nRow1, aSortedCols[i].maCells); + + sc::BroadcasterStoreType& rBCDest = aCol[nThisCol].maBroadcasters; + + // Release current broadcasters first, to prevent them from getting deleted. + SvtBroadcaster* pBC = NULL; + for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; ++nRow) + rBCDest.release(nRow, pBC); + + // Transfer sorted broadcaster segment to the document. + sc::BroadcasterStoreType& rBCSrc = aSortedCols[i].maBroadcasters; + rBCSrc.transfer(0, rBCSrc.size()-1, rBCDest, aSortParam.nRow1); } + + // Attach all formula cells within sorted range, to have them start listening again. + sc::StartListeningContext aStartListenCxt(*pDocument); + AttachFormulaCells( + aStartListenCxt, aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2); } else { |