diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-20 17:23:12 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-20 22:57:13 -0400 |
commit | 6c4bedffb98a33b202692b225fc250b858ff9f65 (patch) | |
tree | 3d1d30ff0c7dd352d2c39737a4ce38f7e93176c5 | |
parent | 9ca5e3da5ca5f68ced1917cf38773fd1060bede4 (diff) |
Add edit text iterator that iterates through only edit text cells.
Change-Id: I898d7a2d3f0ea472daddb9dd32f772a5d7268773
-rw-r--r-- | sc/Library_sc.mk | 1 | ||||
-rw-r--r-- | sc/inc/column.hxx | 2 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/edittextiterator.hxx | 61 | ||||
-rw-r--r-- | sc/inc/table.hxx | 1 | ||||
-rw-r--r-- | sc/qa/unit/ucalc.cxx | 94 | ||||
-rw-r--r-- | sc/qa/unit/ucalc.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/edittextiterator.cxx | 86 |
8 files changed, 249 insertions, 0 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 83e335856bdc..1ef9a82ea717 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -147,6 +147,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/data/dputil \ sc/source/core/data/drawpage \ sc/source/core/data/drwlayer \ + sc/source/core/data/edittextiterator \ sc/source/core/data/fillinfo \ sc/source/core/data/formulacell \ sc/source/core/data/formulaiter \ diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 49cc24aa8f38..4322c247ff81 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -51,6 +51,7 @@ namespace sc { struct RefUpdateInsertTabContext; struct RefUpdateDeleteTabContext; struct RefUpdateMoveTabContext; + class EditTextIterator; } class Fraction; @@ -132,6 +133,7 @@ friend class ScColumnTextWidthIterator; friend class ScDocumentImport; friend class sc::SingleColumnSpanSet; friend class sc::ColumnSpanSet; +friend class sc::EditTextIterator; ScColumn(const ScColumn&); // disabled ScColumn& operator= (const ScColumn&); // disabled diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index c74c6c8349d3..ab84d4c10b06 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -56,6 +56,7 @@ namespace sc { class ColumnSpanSet; struct ColumnBlockPosition; struct RefUpdateContext; + class EditTextIterator; } class SvxFontItem; @@ -231,6 +232,7 @@ friend class ScTable; friend struct ScRefCellValue; friend class ScDocumentImport; friend class sc::ColumnSpanSet; +friend class sc::EditTextIterator; typedef ::std::vector<ScTable*> TableContainer; private: diff --git a/sc/inc/edittextiterator.hxx b/sc/inc/edittextiterator.hxx new file mode 100644 index 000000000000..f160b63f58c3 --- /dev/null +++ b/sc/inc/edittextiterator.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef SC_EDITTEXTITERATOR_HXX +#define SC_EDITTEXTITERATOR_HXX + +#include "address.hxx" +#include "mtvelements.hxx" + +class ScColumn; +class ScTable; +class ScDocument; +class EditTextObject; + +namespace sc { + +/** + * Iterate through all edit text cells in a given sheet. The caller must + * check the validity of the sheet index passed to its constructor. + * + * It iterates from top to bottom, and then left to right order. + */ +class EditTextIterator +{ + const ScTable& mrTable; + const ScColumn* mpCol; + const ScColumn* mpColEnd; + const CellStoreType* mpCells; + CellStoreType::const_position_type maPos; + CellStoreType::const_iterator miEnd; + + /** + * Move to the next edit text cell position if the current position is not + * an edit text. + */ + const EditTextObject* seek(); + + /** + * Increment current position by one. + */ + void incPos(); + void incBlock(); + +public: + EditTextIterator( const ScDocument& rDoc, SCTAB nTab ); + + const EditTextObject* first(); + const EditTextObject* next(); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 06e8151ddda8..99c506bec405 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -210,6 +210,7 @@ friend class ScAttrRectIterator; friend class ScColumnTextWidthIterator; friend class ScDocumentImport; friend class sc::ColumnSpanSet; +friend class sc::EditTextIterator; public: ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName, diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 468d7c694a02..4ed2092491dd 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -49,6 +49,8 @@ #include "dociter.hxx" #include "docsh.hxx" #include "queryparam.hxx" +#include "edittextiterator.hxx" +#include "editutil.hxx" #include "formula/IFunctionDescription.hxx" @@ -4022,6 +4024,98 @@ void Test::testCellTextWidth() m_pDoc->DeleteTab(0); } +bool checkEditTextIterator(sc::EditTextIterator& rIter, const char** pChecks) +{ + const EditTextObject* pText = rIter.first(); + const char* p = *pChecks; + + for (int i = 0; i < 100; ++i) // cap it to 100 loops. + { + if (!pText) + // No more edit cells. The check string array should end too. + return p == NULL; + + if (!p) + // More edit cell, but no more check string. Bad. + return false; + + if (pText->GetParagraphCount() != 1) + // For this test, we don't handle multi-paragraph text. + return false; + + if (pText->GetText(0) != OUString::createFromAscii(p)) + // Text differs from what's expected. + return false; + + pText = rIter.next(); + ++pChecks; + p = *pChecks; + } + + return false; +} + +void Test::testEditTextIterator() +{ + m_pDoc->InsertTab(0, "Test"); + + { + // First, try with an empty sheet. + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + ScFieldEditEngine& rEditEngine = m_pDoc->GetEditEngine(); + + { + // Only set one edit cell. + rEditEngine.SetText("A2"); + m_pDoc->SetEditText(ScAddress(0,1,0), rEditEngine.CreateTextObject()); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + { + // Add a series of edit cells. + rEditEngine.SetText("A5"); + m_pDoc->SetEditText(ScAddress(0,4,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("A6"); + m_pDoc->SetEditText(ScAddress(0,5,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("A7"); + m_pDoc->SetEditText(ScAddress(0,6,0), rEditEngine.CreateTextObject()); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", "A5", "A6", "A7", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + { + // Add more edit cells to column C. Skip column B. + rEditEngine.SetText("C1"); + m_pDoc->SetEditText(ScAddress(2,0,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("C3"); + m_pDoc->SetEditText(ScAddress(2,2,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("C4"); + m_pDoc->SetEditText(ScAddress(2,3,0), rEditEngine.CreateTextObject()); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", "A5", "A6", "A7", "C1", "C3", "C4", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + { + // Add some numeric, string and formula cells. This shouldn't affect the outcome. + m_pDoc->SetString(ScAddress(0,99,0), "=ROW()"); + m_pDoc->SetValue(ScAddress(1,3,0), 1.2); + m_pDoc->SetString(ScAddress(2,4,0), "Simple string"); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", "A5", "A6", "A7", "C1", "C3", "C4", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + m_pDoc->DeleteTab(0); +} + void Test::testCondFormatINSDEL() { // fdo#62206 diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index 5e8933c90b2c..fba750f8c488 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -268,6 +268,7 @@ public: void testDeleteCol(); void testAnchoredRotatedShape(); void testCellTextWidth(); + void testEditTextIterator(); void testCondFormatINSDEL(); @@ -364,6 +365,7 @@ public: CPPUNIT_TEST(testDeleteCol); CPPUNIT_TEST(testAnchoredRotatedShape); CPPUNIT_TEST(testCellTextWidth); + CPPUNIT_TEST(testEditTextIterator); CPPUNIT_TEST(testCondFormatINSDEL); CPPUNIT_TEST_SUITE_END(); diff --git a/sc/source/core/data/edittextiterator.cxx b/sc/source/core/data/edittextiterator.cxx new file mode 100644 index 000000000000..e563f04ae562 --- /dev/null +++ b/sc/source/core/data/edittextiterator.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "edittextiterator.hxx" +#include "document.hxx" +#include "table.hxx" +#include "column.hxx" + +namespace sc { + +EditTextIterator::EditTextIterator( const ScDocument& rDoc, SCTAB nTab ) : + mrTable(*rDoc.maTabs.at(nTab)), + mpCol(&mrTable.aCol[0]), + mpColEnd(mpCol + static_cast<size_t>(MAXCOLCOUNT)), + mpCells(&mpCol->maCells), + maPos(mpCells->position(0)), + miEnd(mpCells->end()) +{ +} + +const EditTextObject* EditTextIterator::seek() +{ + while (maPos.first->type != sc::element_type_edittext) + { + incBlock(); + if (maPos.first == miEnd) + { + // Move to the next column. + ++mpCol; + if (mpCol == mpColEnd) + // No more columns. + return NULL; + + mpCells = &mpCol->maCells; + maPos = mpCells->position(0); + miEnd = mpCells->end(); + } + } + + // We are on the right block type. + return sc::edittext_block::at(*maPos.first->data, maPos.second); +} + +void EditTextIterator::incPos() +{ + if (maPos.second + 1 < maPos.first->size) + // Increment within the block. + ++maPos.second; + else + incBlock(); +} + +void EditTextIterator::incBlock() +{ + ++maPos.first; + maPos.second = 0; +} + +const EditTextObject* EditTextIterator::first() +{ + mpCol = &mrTable.aCol[0]; + mpColEnd = mpCol + static_cast<size_t>(MAXCOLCOUNT); + mpCells = &mpCol->maCells; + maPos = mpCells->position(0); + miEnd = mpCells->end(); + return seek(); +} + +const EditTextObject* EditTextIterator::next() +{ + if (maPos.first == miEnd) + return NULL; + + incPos(); + return seek(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |