sc/inc/column.hxx | 1 sc/inc/table.hxx | 20 ++++++++++++++- sc/source/core/data/column.cxx | 30 ++++++++++++++++++++++- sc/source/core/data/document.cxx | 50 ++++++++++++++++++++++++++++++--------- sc/source/core/data/table2.cxx | 7 +++++ 5 files changed, 94 insertions(+), 14 deletions(-)
New commits: commit fd340291c4ef579ee42850f9b7842d6afe98877d Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Tue Jul 23 16:02:37 2013 -0400 Broadcast on formula cells containing COLUMN functions on column insertion. To ensure that the change gets propagated properly. This fixes testFuncCOLUMN() cppunit test. Change-Id: Ia1ffc2880b7dae530ceb11c617c3963f7bfaeb00 diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 00b2a63..5ef6cce 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -431,6 +431,7 @@ public: void StartAllListeners(); void StartNeededListeners(); // only for cells where NeedsListening()==true void SetRelNameDirty(); + void BroadcastRecalcOnRefMove(); void CompileDBFormula(); void CompileDBFormula( bool bCreateFormulaString ); diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 0e4305a..00cc7e5 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -862,6 +862,24 @@ public: void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen ); + /** + * Have formula cells with NeedsListening() == true start listening to the + * document. + */ + void StartNeededListeners(); + + /** + * Mark dirty those formula cells that has named ranges with relative + * references. + */ + void SetRelNameDirty(); + + /** + * Broadcast dirty formula cells that contain functions such as CELL(), + * COLUMN() or ROW() which may change its value on move. + */ + void BroadcastRecalcOnRefMove(); + #if DEBUG_COLUMN_STORAGE void DumpFormulaGroups( SCCOL nCol ) const; #endif @@ -968,8 +986,6 @@ private: void StartListening( sc::StartListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener ); void EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener ); void StartAllListeners(); - void StartNeededListeners(); // only for cells where NeedsListening()==TRUE - void SetRelNameDirty(); void SetLoadingMedium(bool bLoading); diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 23a740f..da3cb49 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2144,6 +2144,7 @@ void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol) void ScColumn::SwapCol(ScColumn& rCol) { + maBroadcasters.swap(rCol.maBroadcasters); maCells.swap(rCol.maCells); maCellTextAttrs.swap(rCol.maCellTextAttrs); @@ -2163,7 +2164,6 @@ void ScColumn::SwapCol(ScColumn& rCol) CellStorageModified(); rCol.CellStorageModified(); - } void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol) @@ -3004,6 +3004,26 @@ void ScColumn::SetDirtyAfterLoad() sc::ProcessFormula(maCells, aFunc); } +namespace { + +class RecalcOnRefMoveCollector +{ + std::vector<SCROW> maDirtyRows; +public: + void operator() (size_t nRow, ScFormulaCell* pCell) + { + if (pCell->GetDirty() && pCell->GetCode()->IsRecalcModeOnRefMove()) + maDirtyRows.push_back(nRow); + } + + const std::vector<SCROW>& getDirtyRows() const + { + return maDirtyRows; + } +}; + +} + void ScColumn::SetRelNameDirty() { sc::AutoCalcSwitch aSwitch(*pDocument, false); @@ -3011,6 +3031,14 @@ void ScColumn::SetRelNameDirty() sc::ProcessFormula(maCells, aFunc); } +void ScColumn::BroadcastRecalcOnRefMove() +{ + sc::AutoCalcSwitch aSwitch(*pDocument, false); + RecalcOnRefMoveCollector aFunc; + sc::ProcessFormula(maCells, aFunc); + BroadcastCells(aFunc.getDirtyRows()); +} + void ScColumn::CalcAll() { CalcAllHandler aFunc; diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index dfc17cf..9cba374 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1334,6 +1334,36 @@ bool ScDocument::CanInsertCol( const ScRange& rRange ) const return bTest; } +namespace { + +struct StartNeededListenersHandler : std::unary_function<ScTable*, void> +{ + void operator() (ScTable* p) + { + if (p) + p->StartNeededListeners(); + } +}; + +struct SetRelNameDirtyHandler : std::unary_function<ScTable*, void> +{ + void operator() (ScTable* p) + { + if (p) + p->SetRelNameDirty(); + } +}; + +struct BroadcastRecalcOnRefMoveHandler : std::unary_function<ScTable*, void> +{ + void operator() (ScTable* p) + { + if (p) + p->BroadcastRecalcOnRefMove(); + } +}; + +} bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, @@ -1394,17 +1424,15 @@ bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab, StartAllListeners(); } else - {// Listeners have been removed in UpdateReference - TableContainer::iterator it = maTabs.begin(); - for (; it != maTabs.end(); ++it) - if (*it) - (*it)->StartNeededListeners(); - // at least all cells using range names pointing relative - // to the moved range must recalculate - it = maTabs.begin(); - for (; it != maTabs.end(); ++it) - if (*it) - (*it)->SetRelNameDirty(); + { + // Listeners have been removed in UpdateReference + std::for_each(maTabs.begin(), maTabs.end(), StartNeededListenersHandler()); + // at least all cells using range names pointing relative to the + // moved range must recalculate. + std::for_each(maTabs.begin(), maTabs.end(), SetRelNameDirtyHandler()); + // Cells containing functions such as CELL, COLUMN or ROW may have + // changed their values on relocation. Broadcast them. + std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler()); } bRet = true; } diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 96839f1..5bbb6d3 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -48,6 +48,7 @@ #include "editutil.hxx" #include "mtvcellfunc.hxx" #include "refupdatecontext.hxx" +#include "scopetools.hxx" #include "scitems.hxx" #include <editeng/boxitem.hxx> @@ -1705,6 +1706,12 @@ void ScTable::SetRelNameDirty() pDocument->SetAutoCalc( bOldAutoCalc ); } +void ScTable::BroadcastRecalcOnRefMove() +{ + sc::AutoCalcSwitch aSwitch(*pDocument, false); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].BroadcastRecalcOnRefMove(); +} void ScTable::SetLoadingMedium(bool bLoading) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits