From fa5473bb69ff04f362c1f0f14b112e533cfa501a Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Thu, 14 Mar 2013 12:14:40 -0400 Subject: Unit test for the new column-based text width storage, via new iterator. Change-Id: Ibf1e254e34df98ad5c46a46252168787b07d161c --- sc/inc/column.hxx | 2 +- sc/inc/columniterator.hxx | 11 +++ sc/inc/document.hxx | 2 + sc/inc/table.hxx | 2 +- sc/qa/unit/ucalc.cxx | 79 ++++++++++++++++++++++ sc/source/core/data/columniterator.cxx | 119 +++++++++++++++++++-------------- sc/source/core/data/document.cxx | 9 +++ 7 files changed, 171 insertions(+), 53 deletions(-) (limited to 'sc') diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 93ae44f0a523..114a39b271fc 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -97,7 +97,6 @@ class ScColumn ScAttrArray* pAttrArray; ScDocument* pDocument; -friend class ScColumnTextWidthIterator; friend class ScDocument; // for FillInfo friend class ScDocumentIterator; friend class ScValueIterator; @@ -109,6 +108,7 @@ friend class ScMarkedDataIter; friend class ScCellIterator; friend class ScHorizontalCellIterator; friend class ScHorizontalAttrIterator; +friend class ScColumnTextWidthIterator; ScColumn(const ScColumn&); // disabled ScColumn& operator= (const ScColumn&); // disabled diff --git a/sc/inc/columniterator.hxx b/sc/inc/columniterator.hxx index a70567c56c0f..7bd645d71040 100644 --- a/sc/inc/columniterator.hxx +++ b/sc/inc/columniterator.hxx @@ -31,6 +31,16 @@ class ScColumnTextWidthIterator : boost::noncopyable public: ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow); + /** + * @param rDoc document instance. + * @param rStartPos position of the first cell from which to start + * iteration. Note that the caller must ensure that this + * position is valid; the constructor does not check its + * validity. + * @param nEndRow end row position. + */ + ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow); + void next(); bool hasCell() const; SCROW getPos() const; @@ -38,6 +48,7 @@ public: void setValue(sal_uInt16 nVal); private: + void init(SCROW nStartRow, SCROW nEndRow); void getDataIterators(size_t nOffsetInBlock); void checkEndRow(); }; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 2f59ef1cdc8b..541ec05e47ee 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -214,6 +214,7 @@ friend class ScDocAttrIterator; friend class ScAttrRectIterator; friend class ScDocShell; friend class ScDocRowHeightUpdater; +friend class ScColumnTextWidthIterator; typedef ::std::vector TableContainer; private: @@ -1844,6 +1845,7 @@ public: void RemoveSubTotalCell(ScFormulaCell* pCell); void SetSubTotalCellsDirty(const ScRange& rDirtyRange); + sal_uInt16 GetTextWidth( const ScAddress& rPos ) const; void SetTextWidth( const ScAddress& rPos, sal_uInt16 nWidth ); private: // CLOOK-Impl-methods diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 8786ccf118e9..3e4d1eb9fbc4 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -187,7 +187,7 @@ friend class ScHorizontalCellIterator; friend class ScHorizontalAttrIterator; friend class ScDocAttrIterator; friend class ScAttrRectIterator; - +friend class ScColumnTextWidthIterator; public: ScTable( ScDocument* pDoc, SCTAB nNewTab, const rtl::OUString& rNewName, diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 232a50183ee9..57b00f44af98 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -65,6 +65,7 @@ #include "dpfilteredcache.hxx" #include "calcconfig.hxx" #include "interpre.hxx" +#include "columniterator.hxx" #include "formula/IFunctionDescription.hxx" @@ -262,6 +263,7 @@ public: void testDeleteRow(); void testDeleteCol(); void testAnchoredRotatedShape(); + void testCellTextWidth(); CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testCollator); @@ -323,6 +325,7 @@ public: CPPUNIT_TEST(testDeleteRow); CPPUNIT_TEST(testDeleteCol); CPPUNIT_TEST(testAnchoredRotatedShape); + CPPUNIT_TEST(testCellTextWidth); CPPUNIT_TEST_SUITE_END(); private: @@ -6025,6 +6028,82 @@ void Test::testAnchoredRotatedShape() m_pDoc->DeleteTab(0); } +void Test::testCellTextWidth() +{ + m_pDoc->InsertTab(0, "Test"); + + ScAddress aTopCell(0, 0, 0); + + // Sheet is empty. + boost::scoped_ptr pIter(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW)); + CPPUNIT_ASSERT_MESSAGE("Column should have no text widths stored.", !pIter->hasCell()); + + // Sheet only has one cell. + m_pDoc->SetString(0, 0, 0, "Only one cell"); + pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW)); + CPPUNIT_ASSERT_MESSAGE("Column should have a cell.", pIter->hasCell()); + CPPUNIT_ASSERT_EQUAL(0, pIter->getPos()); + + // Setting a text width here should commit it to the column. + sal_uInt16 nTestVal = 432; + pIter->setValue(nTestVal); + CPPUNIT_ASSERT_EQUAL(nTestVal, m_pDoc->GetTextWidth(aTopCell)); + + // Set values to row 2 through 6. + for (SCROW i = 2; i <= 6; ++i) + m_pDoc->SetString(0, i, 0, "foo"); + + // Set values to row 10 through 18. + for (SCROW i = 10; i <= 18; ++i) + m_pDoc->SetString(0, i, 0, "foo"); + + { + // Full range. + pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW)); + SCROW aRows[] = { 0, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17, 18 }; + size_t n = SAL_N_ELEMENTS(aRows); + for (size_t i = 0; i < n; ++i, pIter->next()) + { + CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter->hasCell()); + CPPUNIT_ASSERT_EQUAL(aRows[i], pIter->getPos()); + } + CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter->hasCell()); + } + + { + // Specify start and end rows (6 - 16) + ScAddress aStart = aTopCell; + aStart.SetRow(6); + pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aStart, 16)); + SCROW aRows[] = { 6, 10, 11, 12, 13, 14, 15, 16 }; + size_t n = SAL_N_ELEMENTS(aRows); + for (size_t i = 0; i < n; ++i, pIter->next()) + { + CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter->hasCell()); + CPPUNIT_ASSERT_EQUAL(aRows[i], pIter->getPos()); + } + CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter->hasCell()); + } + + // Clear from row 3 to row 17. After this, we should only have cells at rows 0, 2 and 18. + clearRange(m_pDoc, ScRange(0, 3, 0, 0, 17, 0)); + + { + // Full range again. + pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW)); + SCROW aRows[] = { 0, 2, 18 }; + size_t n = SAL_N_ELEMENTS(aRows); + for (size_t i = 0; i < n; ++i, pIter->next()) + { + CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter->hasCell()); + CPPUNIT_ASSERT_EQUAL(aRows[i], pIter->getPos()); + } + CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter->hasCell()); + } + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_SUITE_REGISTRATION(Test); } diff --git a/sc/source/core/data/columniterator.cxx b/sc/source/core/data/columniterator.cxx index 31298bc3592e..24b8c054d76b 100644 --- a/sc/source/core/data/columniterator.cxx +++ b/sc/source/core/data/columniterator.cxx @@ -9,6 +9,8 @@ #include "columniterator.hxx" #include "column.hxx" +#include "document.hxx" +#include "table.hxx" ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) : mrTextWidths(rCol.maTextWidths), @@ -17,58 +19,17 @@ ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStar miBlockCur(mrTextWidths.begin()), miBlockEnd(mrTextWidths.end()) { - if (!ValidRow(nStartRow) || !ValidRow(nEndRow)) - miBlockCur = miBlockEnd; - - size_t nStart = static_cast(nStartRow); - - // Locate the start row position. - size_t nBlockStart = 0, nBlockEnd = 0; - for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd) - { - nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point. - if (nBlockStart <= nStart && nStart < nBlockEnd) - { - // Initial block is found! - break; - } - } - - if (miBlockCur == miBlockEnd) - // Initial block not found for whatever reason... Bail out. - return; - - // Locate the initial row position within this block. - if (miBlockCur->type == mdds::mtv::element_type_ushort) - { - // This block stores text widths for non-empty cells. - size_t nOffsetInBlock = nStart - nBlockStart; - mnCurPos = nStart; - getDataIterators(nOffsetInBlock); - checkEndRow(); - return; - } - - // Current block is not of ushort type. Skip to the next block. - nBlockStart = nBlockEnd; - ++miBlockCur; - - // Look for the first ushort block. - for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd) - { - nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point. - if (miBlockCur->type != mdds::mtv::element_type_ushort) - continue; - - // Found! - mnCurPos = nBlockStart; - getDataIterators(0); - checkEndRow(); - return; - } + init(nStartRow, nEndRow); +} - // Not found. - OSL_ASSERT(miBlockCur == miBlockEnd); +ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow) : + mrTextWidths(rDoc.maTabs[rStartPos.Tab()]->aCol[rStartPos.Col()].maTextWidths), + mnEnd(static_cast(nEndRow)), + mnCurPos(0), + miBlockCur(mrTextWidths.begin()), + miBlockEnd(mrTextWidths.end()) +{ + init(rStartPos.Row(), nEndRow); } void ScColumnTextWidthIterator::next() @@ -125,6 +86,62 @@ void ScColumnTextWidthIterator::setValue(sal_uInt16 nVal) *miDataCur = nVal; } +void ScColumnTextWidthIterator::init(SCROW nStartRow, SCROW nEndRow) +{ + if (!ValidRow(nStartRow) || !ValidRow(nEndRow)) + miBlockCur = miBlockEnd; + + size_t nStart = static_cast(nStartRow); + + // Locate the start row position. + size_t nBlockStart = 0, nBlockEnd = 0; + for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd) + { + nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point. + if (nBlockStart <= nStart && nStart < nBlockEnd) + { + // Initial block is found! + break; + } + } + + if (miBlockCur == miBlockEnd) + // Initial block not found for whatever reason... Bail out. + return; + + // Locate the initial row position within this block. + if (miBlockCur->type == mdds::mtv::element_type_ushort) + { + // This block stores text widths for non-empty cells. + size_t nOffsetInBlock = nStart - nBlockStart; + mnCurPos = nStart; + getDataIterators(nOffsetInBlock); + checkEndRow(); + return; + } + + // Current block is not of ushort type. Skip to the next block. + nBlockStart = nBlockEnd; + ++miBlockCur; + + // Look for the first ushort block. + for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd) + { + nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point. + if (miBlockCur->type != mdds::mtv::element_type_ushort) + continue; + + // Found! + mnCurPos = nBlockStart; + getDataIterators(0); + checkEndRow(); + return; + } + + // Not found. + OSL_ASSERT(miBlockCur == miBlockEnd); +} + void ScColumnTextWidthIterator::getDataIterators(size_t nOffsetInBlock) { OSL_ENSURE(miBlockCur != miBlockEnd, "block is at end position"); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index acce5985ef57..a73cd60e59d3 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -5695,6 +5695,15 @@ void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange) maSubTotalCells.swap(aNewSet); // update the list. } +sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const +{ + SCTAB nTab = rPos.Tab(); + if (ValidTab(nTab) && nTab < static_cast(maTabs.size()) && maTabs[nTab]) + return maTabs[nTab]->GetTextWidth(rPos.Col(), rPos.Row()); + + return 0; +} + void ScDocument::SetTextWidth( const ScAddress& rPos, sal_uInt16 nWidth ) { SCTAB nTab = rPos.Tab(); -- cgit v1.2.3