sc/inc/refupdatecontext.hxx | 3 sc/qa/unit/ucalc_formula.cxx | 85 +++++++++++++++++++++++++ sc/source/core/data/documen3.cxx | 2 sc/source/core/data/refupdatecontext.cxx | 9 ++ sc/source/core/tool/token.cxx | 104 +++++++++++++++++++++++++------ 5 files changed, 182 insertions(+), 21 deletions(-)
New commits: commit 57f9317a487f23f3f675de81bc045f3869568376 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Jul 19 15:39:36 2013 -0400 Handle range reference expansion on insertion. Change-Id: I128ed26b6d6319a7e227885801e0683b517eb439 diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx index 2f33767..91607ea 100644 --- a/sc/inc/refupdatecontext.hxx +++ b/sc/inc/refupdatecontext.hxx @@ -40,7 +40,8 @@ struct RefUpdateContext RefUpdateContext(); - bool hasDelta() const; + bool isInserted() const; + bool isDeleted() const; }; struct RefUpdateResult diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 53769ef..04973f4 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -981,7 +981,7 @@ void ScDocument::UpdateReference( return; boost::scoped_ptr<sc::ExpandRefsSwitch> pExpandRefsSwitch; - if (rCxt.meMode == URM_INSDEL && rCxt.hasDelta()) + if (rCxt.isInserted()) pExpandRefsSwitch.reset(new sc::ExpandRefsSwitch(*this, SC_MOD()->GetInputOptions().GetExpandRefs())); size_t nFirstTab, nLastTab; diff --git a/sc/source/core/data/refupdatecontext.cxx b/sc/source/core/data/refupdatecontext.cxx index 9f39f44..1ba6a6b 100644 --- a/sc/source/core/data/refupdatecontext.cxx +++ b/sc/source/core/data/refupdatecontext.cxx @@ -14,9 +14,14 @@ namespace sc { RefUpdateContext::RefUpdateContext() : meMode(URM_INSDEL), mnColDelta(0), mnRowDelta(0), mnTabDelta(0) {} -bool RefUpdateContext::hasDelta() const +bool RefUpdateContext::isInserted() const { - return (mnColDelta > 0 || mnRowDelta > 0 || mnTabDelta > 0); + return (meMode == URM_INSDEL) && (mnColDelta > 0 || mnRowDelta > 0 || mnTabDelta > 0); +} + +bool RefUpdateContext::isDeleted() const +{ + return (meMode == URM_INSDEL) && (mnColDelta < 0 || mnRowDelta < 0 || mnTabDelta < 0); } RefUpdateResult::RefUpdateResult() : mbValueChanged(false), mbRangeSizeModified(false) {} diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 981e898..30bef7b 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2195,28 +2195,45 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddres namespace { -ScRange getDeletedRange( const sc::RefUpdateContext& rCxt ) +ScRange getSelectedRange( const sc::RefUpdateContext& rCxt ) { - ScRange aDeletedRange(ScAddress::INITIALIZE_INVALID); + ScRange aSelectedRange(ScAddress::INITIALIZE_INVALID); if (rCxt.mnColDelta < 0) { // Delete and shift to left. - aDeletedRange.aStart = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), rCxt.maRange.aStart.Tab()); - aDeletedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab()); + aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), rCxt.maRange.aStart.Tab()); + aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab()); } else if (rCxt.mnRowDelta < 0) { // Delete and shift up. - aDeletedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab()); - aDeletedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab()); + aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab()); + aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab()); } else if (rCxt.mnTabDelta < 0) { // Deleting sheets. // TODO : Figure out what to do here. } + else if (rCxt.mnColDelta > 0) + { + // Insert and shift to the right. + aSelectedRange.aStart = rCxt.maRange.aStart; + aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab()); + } + else if (rCxt.mnRowDelta > 0) + { + // Insert and shift down. + aSelectedRange.aStart = rCxt.maRange.aStart; + aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta-1, rCxt.maRange.aEnd.Tab()); + } + else if (rCxt.mnTabDelta > 0) + { + // Inserting sheets. + // TODO : Figure out what to do here. + } - return aDeletedRange; + return aSelectedRange; } void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt ) @@ -2279,11 +2296,48 @@ bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc return false; } +bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rInsertedRange ) +{ + if (rCxt.mnColDelta > 0) + { + // Insert and shifting right. + if (rRefRange.aStart.Row() < rInsertedRange.aStart.Row() || rInsertedRange.aEnd.Row() < rRefRange.aEnd.Row()) + // Inserted range is only partially overlapping in vertical direction. Bail out. + return false; + + if (rInsertedRange.aStart.Col() == rRefRange.aStart.Col()) + // Inserted range is at the left end. No expansion. + return false; + + // Move the last column position to the right. + SCCOL nDelta = rInsertedRange.aEnd.Col() - rInsertedRange.aStart.Col() + 1; + rRefRange.aEnd.IncCol(nDelta); + return true; + } + else if (rCxt.mnRowDelta > 0) + { + // Insert and shifting down. + if (rRefRange.aStart.Col() < rInsertedRange.aStart.Col() || rInsertedRange.aEnd.Col() < rRefRange.aEnd.Col()) + // Inserted range is only partially overlapping in horizontal direction. Bail out. + return false; + + if (rInsertedRange.aStart.Row() == rRefRange.aStart.Row()) + // Inserted range is at the top end. No expansion. + return false; + + // Move the last row position down. + SCROW nDelta = rInsertedRange.aEnd.Row() - rInsertedRange.aStart.Row() + 1; + rRefRange.aEnd.IncRow(nDelta); + return true; + } + return false; +} + } sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos ) { - ScRange aDeletedRange = getDeletedRange(rCxt); + ScRange aSelectedRange = getSelectedRange(rCxt); sc::RefUpdateResult aRes; ScAddress aNewPos = rOldPos; @@ -2303,7 +2357,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon ScSingleRefData& rRef = pToken->GetSingleRef(); ScAddress aAbs = rRef.toAbs(rOldPos); - if (aDeletedRange.In(aAbs)) + if (rCxt.isDeleted() && aSelectedRange.In(aAbs)) { // This reference is in the deleted region. setRefDeleted(rRef, rCxt); @@ -2322,20 +2376,36 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon ScComplexRefData& rRef = pToken->GetDoubleRef(); ScRange aAbs = rRef.toAbs(rOldPos); - if (aDeletedRange.In(aAbs)) + if (rCxt.isDeleted()) { - // This reference is in the deleted region. - setRefDeleted(rRef, rCxt); - aRes.mbValueChanged = true; - break; + if (aSelectedRange.In(aAbs)) + { + // This reference is in the deleted region. + setRefDeleted(rRef, rCxt); + aRes.mbValueChanged = true; + break; + } + else if (aSelectedRange.Intersects(aAbs)) + { + if (shrinkRange(rCxt, aAbs, aSelectedRange)) + { + // The reference range has been shrunk. + rRef.SetRange(aAbs, aNewPos); + aRes.mbValueChanged = true; + aRes.mbRangeSizeModified = true; + break; + } + } } - else if (aDeletedRange.Intersects(aAbs)) + + if (rCxt.isInserted() && aSelectedRange.Intersects(aAbs)) { - if (shrinkRange(rCxt, aAbs, aDeletedRange)) + if (expandRange(rCxt, aAbs, aSelectedRange)) { - // The reference range has been shrunk. + // The reference range has been expanded. rRef.SetRange(aAbs, aNewPos); aRes.mbValueChanged = true; + aRes.mbRangeSizeModified = true; break; } } commit 043e733c15255122d6d28ca3c7f34e46449ffc08 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Jul 19 15:38:03 2013 -0400 Add test for range reference expansion on cell insertions. Change-Id: Idd8d37be518cef87ea00633774c3de846b27083a diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index 6310297..07335d4 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -568,6 +568,91 @@ void Test::testFormulaRefUpdateRange() CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,1,0))); CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,2,0))); + // Clear the range and start over. + clearRange(m_pDoc, ScRange(0,0,0,20,20,0)); + + // Disable expansion of range reference on insertion in adjacent areas. + m_pDoc->SetExpandRefs(false); + + // Fill C2:D3 with values. + m_pDoc->SetValue(ScAddress(2,1,0), 1); + m_pDoc->SetValue(ScAddress(3,1,0), 2); + m_pDoc->SetValue(ScAddress(2,2,0), 3); + m_pDoc->SetValue(ScAddress(3,2,0), 4); + + // Set formulas at A5 and A6. + m_pDoc->SetString(ScAddress(0,4,0), "=SUM(C2:D3)"); + m_pDoc->SetString(ScAddress(0,5,0), "=SUM($C$2:$D$3)"); + + if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:D3)")) + CPPUNIT_FAIL("Wrong formula in A5."); + + if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$D$3)")) + CPPUNIT_FAIL("Wrong formula in A6."); + + // Insert a column at column C. This should simply shift the reference without expansion. + m_pDoc->InsertCol(ScRange(2,0,0,2,MAXROW,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(D2:E3)")) + CPPUNIT_FAIL("Wrong formula in A5."); + + if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($D$2:$E$3)")) + CPPUNIT_FAIL("Wrong formula in A6."); + + // Shift it back. + m_pDoc->DeleteCol(ScRange(2,0,0,2,MAXROW,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:D3)")) + CPPUNIT_FAIL("Wrong formula in A5."); + + if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$D$3)")) + CPPUNIT_FAIL("Wrong formula in A6."); + + // Insert at column D. This should expand the reference by one column length. + m_pDoc->InsertCol(ScRange(3,0,0,3,MAXROW,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:E3)")) + CPPUNIT_FAIL("Wrong formula in A5."); + + if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$E$3)")) + CPPUNIT_FAIL("Wrong formula in A6."); + + // Insert at column F. No expansion should occur since the edge expansion is turned off. + m_pDoc->InsertCol(ScRange(5,0,0,5,MAXROW,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:E3)")) + CPPUNIT_FAIL("Wrong formula in A5."); + + if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$E$3)")) + CPPUNIT_FAIL("Wrong formula in A6."); + + // Insert at row 2. No expansion should occur with edge expansion turned off. + m_pDoc->InsertRow(ScRange(0,1,0,MAXCOL,1,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM(C3:E4)")) + CPPUNIT_FAIL("Wrong formula in A6."); + + if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "SUM($C$3:$E$4)")) + CPPUNIT_FAIL("Wrong formula in A7."); + + // Insert at row 4 to expand the reference range. + m_pDoc->InsertRow(ScRange(0,3,0,MAXCOL,3,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "SUM(C3:E5)")) + CPPUNIT_FAIL("Wrong formula in A7."); + + if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "SUM($C$3:$E$5)")) + CPPUNIT_FAIL("Wrong formula in A8."); + + // Insert at row 6. No expansion with edge expansion turned off. + m_pDoc->InsertRow(ScRange(0,5,0,MAXCOL,5,0)); + + if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "SUM(C3:E5)")) + CPPUNIT_FAIL("Wrong formula in A8."); + + if (!checkFormula(*m_pDoc, ScAddress(0,8,0), "SUM($C$3:$E$5)")) + CPPUNIT_FAIL("Wrong formula in A9."); + m_pDoc->DeleteTab(0); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits