[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/qa sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Thu Jul 25 18:19:38 PDT 2013
sc/inc/tokenarray.hxx | 2
sc/qa/unit/ucalc_formula.cxx | 50 ++++++++++++++++++++++++
sc/source/core/data/formulacell.cxx | 34 +++++-----------
sc/source/core/tool/token.cxx | 73 ++++++++++++++++++++++++++++++++++++
4 files changed, 136 insertions(+), 23 deletions(-)
New commits:
commit 60e9f263676c3c10cc0fcfbfc6f80c895f289e9c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Thu Jul 25 21:19:51 2013 -0400
Re-implement sheet reference adjustment on sheet move.
Change-Id: I24e93e0bbc51c7f9a1f1ea0c126a1399ace84a9e
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 1e8ced1..b3fb5ef 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -145,6 +145,8 @@ public:
bool AdjustReferenceOnInsertedTab( SCTAB nInsPos, SCTAB nSheets, const ScAddress& rOldPos );
+ void AdjustReferenceOnMovedTab( SCTAB nOldPos, SCTAB nNewPos, const ScAddress& rOldPos );
+
#if DEBUG_FORMULA_COMPILER
void Dump() const;
#endif
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 531d1d3..a8a54d3 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -813,6 +813,36 @@ void Test::testFormulaRefUpdateSheets()
if (!checkFormula(*m_pDoc, ScAddress(1,2,2), "SUM($Sheet1.$B$2:$C$3)"))
CPPUNIT_FAIL("Wrong formula in Sheet2.B3.");
+ // Move the last sheet (Sheet2) to the first position.
+ m_pDoc->MoveTab(2, 0);
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,1,0), "SUM(Sheet1.B2:C3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B2.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,2,0), "SUM($Sheet1.$B$2:$C$3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B3.");
+
+ // Move back.
+ m_pDoc->MoveTab(0, 2);
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,1,2), "SUM(Sheet1.B2:C3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B2.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,2,2), "SUM($Sheet1.$B$2:$C$3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B3.");
+
+ // Move the "Temp" sheet to the last position.
+ m_pDoc->MoveTab(1, 2);
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,1,1), "SUM(Sheet1.B2:C3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B2.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,2,1), "SUM($Sheet1.$B$2:$C$3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B3.");
+
+ // Move back.
+ m_pDoc->MoveTab(2, 1);
+
// Delete the temporary sheet.
m_pDoc->DeleteTab(1);
@@ -848,6 +878,26 @@ void Test::testFormulaRefUpdateSheets()
if (!checkFormula(*m_pDoc, ScAddress(1,2,1), "SUM($Sheet1.$B$2:$C$3)"))
CPPUNIT_FAIL("Wrong formula in Sheet2.B3.");
+ // Append a bunch of sheets.
+ m_pDoc->InsertTab(2, "Temp1");
+ m_pDoc->InsertTab(3, "Temp2");
+ m_pDoc->InsertTab(4, "Temp3");
+
+ // Move these tabs around. This shouldn't affects the first 2 sheets.
+ m_pDoc->MoveTab(2, 4);
+ m_pDoc->MoveTab(3, 2);
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,1,1), "SUM(Sheet1.B2:C3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B2.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,2,1), "SUM($Sheet1.$B$2:$C$3)"))
+ CPPUNIT_FAIL("Wrong formula in Sheet2.B3.");
+
+ // Delete the temp sheets.
+ m_pDoc->DeleteTab(4);
+ m_pDoc->DeleteTab(3);
+ m_pDoc->DeleteTab(2);
+
// Delete Sheet1.
m_pDoc->DeleteTab(0);
m_pDoc->GetName(0, aName);
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index c6fb301..b20fa0c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2598,31 +2598,19 @@ bool ScFormulaCell::UpdateDeleteTab(SCTAB nTable, bool /*bIsMove*/, SCTAB nSheet
void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
{
pCode->Reset();
- if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
+ if (!pCode->GetNextReferenceRPN() || pDocument->IsClipOrUndo())
{
- EndListeningTo( pDocument );
- // SetTab _after_ EndListeningTo und _before_ Compiler UpdateMoveTab !
- aPos.SetTab( nTabNo );
- ScRangeData* pRangeData;
- ScCompiler aComp(pDocument, aPos, *pCode);
- aComp.SetGrammar(pDocument->GetGrammar());
- pRangeData = aComp.UpdateMoveTab( nOldPos, nNewPos, false );
- if (pRangeData) // Exchange Shared Formula with real Formula
- {
- pDocument->RemoveFromFormulaTree( this ); // update formula count
- delete pCode;
- pCode = pRangeData->GetCode()->Clone();
- ScCompiler aComp2(pDocument, aPos, *pCode);
- aComp2.SetGrammar(pDocument->GetGrammar());
- aComp2.CompileTokenArray();
- aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
- aComp2.UpdateMoveTab( nOldPos, nNewPos, true );
- bCompile = true;
- }
- // no StartListeningTo because pTab[nTab] not yet correct!
+ aPos.SetTab(nTabNo);
+ return;
}
- else
- aPos.SetTab( nTabNo );
+
+ EndListeningTo(pDocument);
+ ScAddress aOldPos = aPos;
+ // SetTab _after_ EndListeningTo und _before_ Compiler UpdateMoveTab !
+ aPos.SetTab(nTabNo);
+
+ // no StartListeningTo because pTab[nTab] not yet correct!
+ pCode->AdjustReferenceOnMovedTab(nOldPos, nNewPos, aOldPos);
}
void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable)
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index e5381aa..79bdfa3 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2660,6 +2660,79 @@ bool ScTokenArray::AdjustReferenceOnInsertedTab( SCTAB nInsPos, SCTAB nSheets, c
return bRefChanged;
}
+namespace {
+
+void adjustTabOnMove( ScAddress& rPos, SCTAB nOldPos, SCTAB nNewPos )
+{
+ // Sheets below the lower bound or above the uppper bound will not change.
+ SCTAB nLowerBound = std::min(nOldPos, nNewPos);
+ SCTAB nUpperBound = std::max(nOldPos, nNewPos);
+
+ if (rPos.Tab() < nLowerBound || nUpperBound < rPos.Tab())
+ // Outside the boundary. Nothing to adjust.
+ return;
+
+ if (rPos.Tab() == nOldPos)
+ {
+ rPos.SetTab(nNewPos);
+ return;
+ }
+
+ // It's somewhere in between.
+ if (nOldPos < nNewPos)
+ {
+ // Moving a sheet to the right. The rest of the sheets shifts to the left.
+ rPos.IncTab(-1);
+ }
+ else
+ {
+ // Moving a sheet to the left. The rest of the sheets shifts to the right.
+ rPos.IncTab();
+ }
+}
+
+}
+
+void ScTokenArray::AdjustReferenceOnMovedTab( SCTAB nOldPos, SCTAB nNewPos, const ScAddress& rOldPos )
+{
+ if (nOldPos == nNewPos)
+ return;
+
+ ScAddress aNewPos = rOldPos;
+ adjustTabOnMove(aNewPos, nOldPos, nNewPos);
+
+ FormulaToken** p = pCode;
+ FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+ for (; p != pEnd; ++p)
+ {
+ switch ((*p)->GetType())
+ {
+ case svSingleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScSingleRefData& rRef = pToken->GetSingleRef();
+ ScAddress aAbs = rRef.toAbs(rOldPos);
+ adjustTabOnMove(aAbs, nOldPos, nNewPos);
+ rRef.SetAddress(aAbs, aNewPos);
+
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScComplexRefData& rRef = pToken->GetDoubleRef();
+ ScRange aAbs = rRef.toAbs(rOldPos);
+ adjustTabOnMove(aAbs.aStart, nOldPos, nNewPos);
+ adjustTabOnMove(aAbs.aEnd, nOldPos, nNewPos);
+ rRef.SetRange(aAbs, aNewPos);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
#if DEBUG_FORMULA_COMPILER
void ScTokenArray::Dump() const
{
More information about the Libreoffice-commits
mailing list