[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Wed Jul 3 23:17:50 PDT 2013
sc/inc/column.hxx | 2 +
sc/source/core/data/column.cxx | 77 +++++++++++++++++++++++++++++-----------
sc/source/core/data/column2.cxx | 4 --
sc/source/core/data/column3.cxx | 66 ++++++++++++++++++++++++++--------
4 files changed, 109 insertions(+), 40 deletions(-)
New commits:
commit 724077098c35e7edd4231ae95e7cddb1a1b95a0c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Thu Jul 4 02:17:03 2013 -0400
More on regrouping of formula cells.
Change-Id: Icd3403e759841dce351c932ea8915ba9819e5a29
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 62e1ddf..6bbfb6a 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -505,6 +505,8 @@ public:
*/
void SplitFormulaCellGroup( const sc::CellStoreType::position_type& aPos ) const;
+ void JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPos ) const;
+
/**
* Regroup formula cells for the entire column.
*/
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index bdfde88..7ce8668 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2127,13 +2127,29 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
sc::SingleColumnSpanSet::SpansType aRanges;
aNonEmpties.getSpans(aRanges);
+ // Split the formula grouping at the top and bottom boundaries.
+ sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
+ SplitFormulaCellGroup(aPos);
+ aPos = maCells.position(aPos.first, nEndRow+1);
+ SplitFormulaCellGroup(aPos);
+
+ // Do the same with the destination column.
+ aPos = rCol.maCells.position(nStartRow);
+ rCol.SplitFormulaCellGroup(aPos);
+ aPos = rCol.maCells.position(aPos.first, nEndRow+1);
+ rCol.SplitFormulaCellGroup(aPos);
+
// Move the broadcasters to the destination column.
maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
- RegroupFormulaCells(nStartRow, nEndRow);
- rCol.RegroupFormulaCells(nStartRow, nEndRow);
+ // Re-group transferred formula cells.
+ aPos = rCol.maCells.position(nStartRow);
+ rCol.JoinFormulaCellAbove(aPos);
+ aPos = rCol.maCells.position(aPos.first, nEndRow+1);
+ rCol.JoinFormulaCellAbove(aPos);
+
CellStorageModified();
rCol.CellStorageModified();
@@ -2267,31 +2283,47 @@ namespace {
class UpdateTransHandler
{
+ ScColumn& mrColumn;
+ sc::CellStoreType::iterator miPos;
ScRange maSource;
ScAddress maDest;
ScDocument* mpUndoDoc;
public:
- UpdateTransHandler(const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
+ UpdateTransHandler(ScColumn& rColumn, const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
+ mrColumn(rColumn),
+ miPos(rColumn.GetCellStore().begin()),
maSource(rSource), maDest(rDest), mpUndoDoc(pUndoDoc) {}
- void operator() (size_t, ScFormulaCell* pCell)
+ void operator() (size_t nRow, ScFormulaCell* pCell)
{
+ sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
+ miPos = aPos.first;
+ mrColumn.UnshareFormulaCell(aPos, *pCell);
pCell->UpdateTranspose(maSource, maDest, mpUndoDoc);
+ mrColumn.JoinNewFormulaCell(aPos, *pCell);
}
};
class UpdateGrowHandler
{
+ ScColumn& mrColumn;
+ sc::CellStoreType::iterator miPos;
ScRange maArea;
SCCOL mnGrowX;
SCROW mnGrowY;
public:
- UpdateGrowHandler(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
+ UpdateGrowHandler(ScColumn& rColumn, const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
+ mrColumn(rColumn),
+ miPos(rColumn.GetCellStore().begin()),
maArea(rArea), mnGrowX(nGrowX), mnGrowY(nGrowY) {}
- void operator() (size_t, ScFormulaCell* pCell)
+ void operator() (size_t nRow, ScFormulaCell* pCell)
{
+ sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
+ miPos = aPos.first;
+ mrColumn.UnshareFormulaCell(aPos, *pCell);
pCell->UpdateGrow(maArea, mnGrowX, mnGrowY);
+ mrColumn.JoinNewFormulaCell(aPos, *pCell);
}
};
@@ -2638,14 +2670,22 @@ public:
class CompileErrorCellsHandler
{
+ ScColumn& mrColumn;
+ sc::CellStoreType::iterator miPos;
sal_uInt16 mnErrCode;
FormulaGrammar::Grammar meGram;
bool mbCompiled;
public:
- CompileErrorCellsHandler(sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) :
- mnErrCode(nErrCode), meGram(eGram), mbCompiled(false) {}
+ CompileErrorCellsHandler(ScColumn& rColumn, sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) :
+ mrColumn(rColumn),
+ miPos(mrColumn.GetCellStore().begin()),
+ mnErrCode(nErrCode),
+ meGram(eGram),
+ mbCompiled(false)
+ {
+ }
- void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
+ void operator() (size_t nRow, ScFormulaCell* pCell)
{
sal_uInt16 nCurError = pCell->GetRawError();
if (!nCurError)
@@ -2656,10 +2696,14 @@ public:
// Error code is specified, and it doesn't match. Skip it.
return;
+ sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
+ miPos = aPos.first;
+ mrColumn.UnshareFormulaCell(aPos, *pCell);
pCell->GetCode()->SetCodeError(0);
OUStringBuffer aBuf;
pCell->GetFormula(aBuf, meGram);
pCell->Compile(aBuf.makeStringAndClear(), false, meGram);
+ mrColumn.JoinNewFormulaCell(aPos, *pCell);
mbCompiled = true;
}
@@ -2734,17 +2778,15 @@ public:
void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
ScDocument* pUndoDoc )
{
- UpdateTransHandler aFunc(rSource, rDest, pUndoDoc);
+ UpdateTransHandler aFunc(*this, rSource, rDest, pUndoDoc);
sc::ProcessFormula(maCells, aFunc);
- RegroupFormulaCells();
}
void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
{
- UpdateGrowHandler aFunc(rArea, nGrowX, nGrowY);
+ UpdateGrowHandler aFunc(*this, rArea, nGrowX, nGrowY);
sc::ProcessFormula(maCells, aFunc);
- RegroupFormulaCells();
}
@@ -2764,10 +2806,7 @@ void ScColumn::UpdateInsertTabOnlyCells(SCTAB nInsPos, SCTAB nNewSheets)
InsertTabUpdater aFunc(maCellTextAttrs, nTab, nInsPos, nNewSheets);
sc::ProcessFormulaEditText(maCells, aFunc);
if (aFunc.isModified())
- {
- RegroupFormulaCells();
CellStorageModified();
- }
}
void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* /*pRefUndo*/, SCTAB nSheets)
@@ -2910,12 +2949,8 @@ void ScColumn::CompileXML( ScProgress& rProgress )
bool ScColumn::CompileErrorCells(sal_uInt16 nErrCode)
{
- CompileErrorCellsHandler aHdl(nErrCode, pDocument->GetGrammar());
+ CompileErrorCellsHandler aHdl(*this, nErrCode, pDocument->GetGrammar());
sc::ProcessFormula(maCells, aHdl);
- if (aHdl.isCompiled())
- // TODO: Probably more efficient to do this individually rather than the whole column.
- RegroupFormulaCells();
-
return aHdl.isCompiled();
}
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 98081356..a651fa6 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1530,10 +1530,6 @@ void ScColumn::CellStorageModified()
#endif
}
-void ScColumn::RegroupFormulaCells()
-{
-}
-
void ScColumn::RegroupFormulaCells( SCROW /*nRow*/ )
{
}
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 203bb96..f39d1f8 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -326,12 +326,14 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( SCROW nRow )
namespace {
-void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
+void joinFormulaCells(const sc::CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
{
ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
if (eState == ScFormulaCell::NotEqual)
return;
+ SCROW nRow = rPos.first->position + rPos.second;
+
// Formula tokens equal those of the previous formula cell.
ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
ScFormulaCellGroupRef xGroup2 = rCell2.GetCellGroup();
@@ -339,13 +341,23 @@ void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
{
if (xGroup2)
{
- // Both cell1 and cell2 are shared. Merge them together.
+ // Both cell 1 and cell 2 are shared. Merge them together.
+ if (xGroup1.get() == xGroup2.get())
+ // They belong to the same group.
+ return;
+
+ // Set the group object from cell 1 to all cells in group 2.
xGroup1->mnLength += xGroup2->mnLength;
- rCell2.SetCellGroup(xGroup1);
+ size_t nOffset = rPos.second + 1; // position of cell 2
+ for (size_t i = 0, n = xGroup2->mnLength; i < n; ++i)
+ {
+ ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, nOffset+i);
+ rCell.SetCellGroup(xGroup1);
+ }
}
else
{
- // cell1 is shared but cell2 is not.
+ // cell 1 is shared but cell 2 is not.
rCell2.SetCellGroup(xGroup1);
++xGroup1->mnLength;
}
@@ -354,7 +366,7 @@ void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
{
if (xGroup2)
{
- // cell1 is not shared, but cell2 is already shared.
+ // cell 1 is not shared, but cell 2 is already shared.
rCell1.SetCellGroup(xGroup2);
xGroup2->mnStart = nRow;
++xGroup2->mnLength;
@@ -378,20 +390,20 @@ void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
void ScColumn::JoinNewFormulaCell(
const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
{
- SCROW nRow = aPos.first->position + aPos.second;
-
// Check the previous row position for possible grouping.
if (aPos.first->type == sc::element_type_formula && aPos.second > 0)
{
ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
- joinFormulaCells(nRow-1, rPrev, rCell);
+ sc::CellStoreType::position_type aPosPrev = aPos;
+ --aPosPrev.second;
+ joinFormulaCells(aPosPrev, rPrev, rCell);
}
// Check the next row position for possible grouping.
if (aPos.first->type == sc::element_type_formula && aPos.second+1 < aPos.first->size)
{
ScFormulaCell& rNext = *sc::formula_block::at(*aPos.first->data, aPos.second+1);
- joinFormulaCells(nRow, rCell, rNext);
+ joinFormulaCells(aPos, rCell, rNext);
}
}
@@ -575,6 +587,26 @@ void ScColumn::SplitFormulaCellGroup( const sc::CellStoreType::position_type& aP
}
}
+void ScColumn::JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPos ) const
+{
+ if (aPos.first->type != sc::element_type_formula)
+ // This is not a formula cell.
+ return;
+
+ if (aPos.second == 0)
+ // This cell is already the top cell in a formula block; the previous
+ // cell is not a formula cell.
+ return;
+
+ SCROW nRow = aPos.first->position + aPos.second;
+
+ 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);
+}
+
sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow )
{
// See if we are overwriting an existing formula cell.
@@ -740,7 +772,7 @@ class EmptyCells
sc::ColumnBlockPosition& mrPos;
sc::CellStoreType::iterator miPos;
- void splitFormulaGrouping(sc::CellStoreType& rCells, const sc::CellStoreType::position_type& rPos)
+ void splitFormulaGrouping(const sc::CellStoreType::position_type& rPos)
{
if (rPos.first->type == sc::element_type_formula)
{
@@ -760,9 +792,9 @@ public:
// First, split formula grouping at the top and bottom boundaries
// before emptying the cells.
sc::CellStoreType::position_type aPos = rCells.position(mrPos.miCellPos, rSpan.mnRow1);
- splitFormulaGrouping(rCells, aPos);
+ splitFormulaGrouping(aPos);
aPos = rCells.position(aPos.first, rSpan.mnRow2);
- splitFormulaGrouping(rCells, aPos);
+ splitFormulaGrouping(aPos);
mrPos.miCellPos = rCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
mrPos.miCellTextAttrPos = mrColumn.GetCellAttrStore().set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
@@ -2874,15 +2906,19 @@ void ScColumn::RebuildFormulaGroups()
if (!mbDirtyGroups)
return;
- // clear previous formula groups.
+ RegroupFormulaCells();
+ mbDirtyGroups = false;
+}
+
+void ScColumn::RegroupFormulaCells()
+{
+ // clear previous formula groups (if any)
ScFormulaCellGroupRef xNone;
CellGroupSetter aFunc(xNone);
sc::ProcessFormula(maCells, aFunc);
// re-build formula groups.
std::for_each(maCells.begin(), maCells.end(), GroupFormulaCells());
-
- mbDirtyGroups = false;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list