[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