diff options
author | Caolán McNamara <caolanm@redhat.com> | 2012-08-02 17:01:19 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2012-08-03 10:55:43 +0100 |
commit | 27c2fe405ca55a2630176a657fb4895c5e31fcea (patch) | |
tree | ac4b00a96e7882647b5cc21c0c133b2ece54d538 | |
parent | ab852cc0b6fe6e3a8b398b7fa0313a1425adf31b (diff) |
Related: fdo#46757 extend ModelToViewHelper for more cases
beef up ModelToViewHelper to be able to optionally expand fields, collapse
hidden text and collapse/expand redline deleted text
Change-Id: I6d4d0969102ad9699f7fafe091b2eff6a5707bc4
-rw-r--r-- | sw/CppunitTest_sw_swdoc_test.mk | 1 | ||||
-rw-r--r-- | sw/inc/modeltoviewhelper.hxx | 37 | ||||
-rw-r--r-- | sw/qa/core/swdoc-test.cxx | 111 | ||||
-rw-r--r-- | sw/source/core/txtnode/ndtxt.cxx | 152 |
4 files changed, 263 insertions, 38 deletions
diff --git a/sw/CppunitTest_sw_swdoc_test.mk b/sw/CppunitTest_sw_swdoc_test.mk index 94ebab35597f..b3ab7d72f3f0 100644 --- a/sw/CppunitTest_sw_swdoc_test.mk +++ b/sw/CppunitTest_sw_swdoc_test.mk @@ -77,6 +77,7 @@ $(eval $(call gb_CppunitTest_use_externals,sw_swdoc_test,\ $(eval $(call gb_CppunitTest_set_include,sw_swdoc_test,\ -I$(SRCDIR)/sw/source/ui/inc \ + -I$(SRCDIR)/sw/source/core/inc \ -I$(SRCDIR)/sw/inc \ $$(INCLUDE) \ )) diff --git a/sw/inc/modeltoviewhelper.hxx b/sw/inc/modeltoviewhelper.hxx index c7a80c5b4278..835044d61e3e 100644 --- a/sw/inc/modeltoviewhelper.hxx +++ b/sw/inc/modeltoviewhelper.hxx @@ -34,7 +34,38 @@ class SwTxtNode; to expand the fields to get the string as it appears in the view. Two helper functions are provided to convert model positions to view positions and vice versa. + + CH_TXTATR_BREAKWORD -> SwTxtNode will have field attributes associated with these + . . + . . + . . + AAAAA BBBBB # CCCCC # DDDDD + | | | | + | | | | + | --------- + | | . + | | . + | | .......... bounds of a hidden text character attribute + ------ + . + . + .............. a range of text defined in redline region as deleted + + 0000: pass through gives: AAAAA BBBBB # CCCCC # DDDDD + 0001: only expanding fields gives: AAAAA BBBBB foo CCCCC foo DDDDD + 0010: only hiding hiddens gives: AAAAA CCCCC # DDDDD + 0100: only hiding redlines gives: AAAABB # CCCCC # DDDDD + 0011: expanding fields + hiding hiddens gives: AAAAA CCCC foo DDDDD + 0101: expanding fields + hiding redlines gives: AAAA B foo CCCCC foo DDDDD + 0110: hiding hiddens + hiding redlines gives: AAAACCCC # DDDDD + 0111: expanding fields + hiding hiddens + hiding redlines gives: AAAABB foo CCCCC foo DDDDD */ + +#define PASSTHROUGH 0x0000 +#define EXPANDFIELDS 0x0001 +#define HIDEINVISIBLE 0x0002 +#define HIDEREDLINED 0x0004 + class ModelToViewHelper { /** For each field in the model string, there is an entry in the conversion @@ -67,8 +98,10 @@ public: ModelPosition() : mnPos(0), mnSubPos(0), mbIsField(false) {} }; - ModelToViewHelper(const SwTxtNode &rNode); - ModelToViewHelper() {} //pass through filter, view == model + ModelToViewHelper(const SwTxtNode &rNode, int eMode = EXPANDFIELDS); + ModelToViewHelper() //pass through filter, view == model + { + } /** Converts a model position into a view position diff --git a/sw/qa/core/swdoc-test.cxx b/sw/qa/core/swdoc-test.cxx index 3e26b1f2d451..a5df1433aaa6 100644 --- a/sw/qa/core/swdoc-test.cxx +++ b/sw/qa/core/swdoc-test.cxx @@ -38,6 +38,7 @@ #include <unotools/tempfile.hxx> #include <editeng/langitem.hxx> +#include <editeng/charhiddenitem.hxx> #include <sfx2/app.hxx> #include <sfx2/docfilt.hxx> @@ -63,6 +64,8 @@ #include "fmtfld.hxx" #include "redline.hxx" #include "docary.hxx" +#include "modeltoviewhelper.hxx" +#include "scriptinfo.hxx" SO2_DECL_REF(SwDocShell) SO2_IMPL_REF(SwDocShell) @@ -81,6 +84,7 @@ public: void testPageDescName(); void testFileNameFields(); void testDocStat(); + void testModelToViewHelper(); void testSwScanner(); void testUserPerceivedCharCount(); void testGraphicAnchorDeletion(); @@ -90,6 +94,7 @@ public: CPPUNIT_TEST(testPageDescName); CPPUNIT_TEST(testFileNameFields); CPPUNIT_TEST(testDocStat); + CPPUNIT_TEST(testModelToViewHelper); CPPUNIT_TEST(testSwScanner); CPPUNIT_TEST(testUserPerceivedCharCount); CPPUNIT_TEST(testGraphicAnchorDeletion); @@ -222,6 +227,112 @@ void SwDocTest::testUserPerceivedCharCount() CPPUNIT_ASSERT_MESSAGE("Surrogate Pair should be counted as single character", nCount == 1); } +void SwDocTest::testModelToViewHelper() +{ + SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1); + SwPaM aPaM(aIdx); + + { + SwFmtFtn aFtn; + aFtn.SetNumStr(rtl::OUString("foo")); + + m_pDoc->AppendTxtNode(*aPaM.GetPoint()); + m_pDoc->InsertString(aPaM, rtl::OUString("AAAAA BBBBB ")); + SwTxtNode* pTxtNode = aPaM.GetNode()->GetTxtNode(); + xub_StrLen nPos = aPaM.GetPoint()->nContent.GetIndex(); + pTxtNode->InsertItem(aFtn, nPos, nPos); + m_pDoc->InsertString(aPaM, rtl::OUString(" CCCCC ")); + nPos = aPaM.GetPoint()->nContent.GetIndex(); + pTxtNode->InsertItem(aFtn, nPos, nPos); + m_pDoc->InsertString(aPaM, rtl::OUString(" DDDDD")); + CPPUNIT_ASSERT(pTxtNode->GetTxt().Len() == (4*5) + 5 + 2); + + //set start of selection to first B + aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 6); + aPaM.SetMark(); + //set end of selection to last C + aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 14); + //set character attribute hidden on range + SvxCharHiddenItem aHidden(true, RES_CHRATR_HIDDEN); + m_pDoc->InsertPoolItem(aPaM, aHidden, 0 ); + + //turn on red-lining and show changes + m_pDoc->SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT); + CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc->IsRedlineOn()); + CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc->GetRedlineMode())); + + //set start of selection to last A + aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 4); + aPaM.SetMark(); + //set end of selection to second last B + aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 9); + m_pDoc->DeleteAndJoin(aPaM); //redline-aware deletion api + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, PASSTHROUGH); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + rtl::OUString sModelText = pTxtNode->GetTxt(); + CPPUNIT_ASSERT(sViewText == sModelText); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + CPPUNIT_ASSERT(sViewText == "AAAAA BBBBB foo CCCCC foo DDDDD"); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEINVISIBLE); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + rtl::OUStringBuffer aBuffer; + aBuffer.append("AAAAA CCCCC "); + aBuffer.append(CH_TXTATR_BREAKWORD); + aBuffer.append(" DDDDD"); + CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear()); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEREDLINED); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + rtl::OUStringBuffer aBuffer; + aBuffer.append("AAAABB "); + aBuffer.append(CH_TXTATR_BREAKWORD); + aBuffer.append(" CCCCC "); + aBuffer.append(CH_TXTATR_BREAKWORD); + aBuffer.append(" DDDDD"); + CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear()); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEINVISIBLE); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + CPPUNIT_ASSERT(sViewText == "AAAAA CCCCC foo DDDDD"); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEREDLINED); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + CPPUNIT_ASSERT(sViewText == "AAAABB foo CCCCC foo DDDDD"); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEINVISIBLE | HIDEREDLINED); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + rtl::OUStringBuffer aBuffer; + aBuffer.append("AAAACCCCC "); + aBuffer.append(CH_TXTATR_BREAKWORD); + aBuffer.append(" DDDDD"); + CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear()); + } + + { + ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEINVISIBLE | HIDEREDLINED); + rtl::OUString sViewText = aModelToViewHelper.getViewText(); + CPPUNIT_ASSERT(sViewText == "AAAACCCCC foo DDDDD"); + } + } +} + void SwDocTest::testSwScanner() { SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1); diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index 90e9a2b6f26c..22ddb66b2934 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -37,6 +37,7 @@ #include <editeng/tstpitem.hxx> #include <svl/urihelper.hxx> #include <svl/ctloptions.hxx> +#include <tools/multisel.hxx> #include <swmodule.hxx> #include <txtfld.hxx> #include <txtinet.hxx> @@ -3092,52 +3093,131 @@ sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx, return sal_True; } -ModelToViewHelper::ModelToViewHelper(const SwTxtNode &rNode) +struct block +{ + sal_Int32 m_nStart; + sal_Int32 m_nLen; + bool m_bVisible; + std::vector<const SwTxtAttr*> m_aAttrs; + block(sal_Int32 nStart, sal_Int32 nLen, bool bVisible) + : m_nStart(nStart), m_nLen(nLen), m_bVisible(bVisible) + { + } +}; + +struct containsPos +{ + const sal_Int32 m_nPos; + containsPos(const sal_Int32 nPos) + : m_nPos(nPos) + { + } + bool operator() (const block& rIn) const + { + return m_nPos >= rIn.m_nStart && m_nPos < rIn.m_nStart + rIn.m_nLen; + } +}; + +ModelToViewHelper::ModelToViewHelper(const SwTxtNode &rNode, int eMode) { const rtl::OUString& rNodeText = rNode.GetTxt(); m_aRetText = rNodeText; - const SwpHints* pSwpHints2 = rNode.GetpSwpHints(); - xub_StrLen nPos = 0; + if (eMode == PASSTHROUGH) + return; + + Range aRange( 0, rNodeText.isEmpty() ? 0 : rNodeText.getLength() - 1); + MultiSelection aHiddenMulti(aRange); + + if (eMode & HIDEINVISIBLE) + SwScriptInfo::selectHiddenTextProperty(rNode, aHiddenMulti); - for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i ) + if (eMode & HIDEREDLINED) + SwScriptInfo::selectRedLineDeleted(rNode, aHiddenMulti); + + std::vector<block> aBlocks; + + sal_Int32 nShownStart = 0; + for (size_t i = 0; i < aHiddenMulti.GetRangeCount(); ++i) { - const SwTxtAttr* pAttr = (*pSwpHints2)[i]; - bool bReplace = false; - xub_StrLen nFieldPos(STRING_NOTFOUND); - rtl::OUString aExpand; - switch (pAttr->Which()) + const Range& rRange = aHiddenMulti.GetRange(i); + sal_Int32 nHiddenStart = rRange.Min(); + sal_Int32 nHiddenEnd = rRange.Max() + 1; + sal_Int32 nHiddenLen = nHiddenEnd - nHiddenStart; + + sal_Int32 nShownEnd = nHiddenStart; + sal_Int32 nShownLen = nShownEnd - nShownStart; + + if (nShownLen) + aBlocks.push_back(block(nShownStart, nShownLen, true)); + + if (nHiddenLen) + aBlocks.push_back(block(nHiddenStart, nHiddenLen, false)); + + nShownStart = nHiddenEnd; + } + + sal_Int32 nTrailingShownLen = rNodeText.getLength() - nShownStart; + if (nTrailingShownLen) + aBlocks.push_back(block(nShownStart, nTrailingShownLen, true)); + + if (eMode & EXPANDFIELDS) + { + const SwpHints* pSwpHints2 = rNode.GetpSwpHints(); + for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i ) { - case RES_TXTATR_FIELD: - bReplace = true; - aExpand = - static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld() - ->ExpandField(true); - nFieldPos = *pAttr->GetStart(); - break; - case RES_TXTATR_FTN: - { - bReplace = true; - const SwFmtFtn& rFtn = static_cast<SwTxtFtn const*>(pAttr)->GetFtn(); - const SwDoc *pDoc = rNode.GetDoc(); - aExpand = rFtn.GetViewNumStr(*pDoc); - nFieldPos = *pAttr->GetStart(); - } - break; - default: - if (pAttr->HasDummyChar()) - { - bReplace = true; - nFieldPos = *pAttr->GetStart(); - } - break; + const SwTxtAttr* pAttr = (*pSwpHints2)[i]; + if (pAttr->HasDummyChar()) + { + xub_StrLen nDummyCharPos = *pAttr->GetStart(); + if (aHiddenMulti.IsSelected(nDummyCharPos)) + continue; + std::vector<block>::iterator aFind = std::find_if(aBlocks.begin(), aBlocks.end(), containsPos(nDummyCharPos)); + aFind->m_aAttrs.push_back(pAttr); + } } + } + + sal_Int32 nOffset = 0; + for (std::vector<block>::iterator i = aBlocks.begin(); i != aBlocks.end(); ++i) + { + if (!i->m_bVisible) + { + const sal_Int32 nHiddenStart = i->m_nStart; + const sal_Int32 nHiddenLen = i->m_nLen; - if (bReplace) + m_aRetText = m_aRetText.replaceAt( nOffset + nHiddenStart, nHiddenLen, rtl::OUString() ); + m_aMap.push_back( ConversionMapEntry( nHiddenStart, nOffset + nHiddenStart ) ); + nOffset -= nHiddenLen; + } + else { - m_aRetText = m_aRetText.replaceAt( nPos + nFieldPos, 1, aExpand ); - m_aMap.push_back( ConversionMapEntry( nFieldPos, nPos + nFieldPos ) ); - nPos += ( aExpand.getLength() - 1 ); + for (std::vector<const SwTxtAttr*>::iterator j = i->m_aAttrs.begin(); j != i->m_aAttrs.end(); ++j) + { + const SwTxtAttr* pAttr = *j; + xub_StrLen nFieldPos = *pAttr->GetStart(); + rtl::OUString aExpand; + switch (pAttr->Which()) + { + case RES_TXTATR_FIELD: + aExpand = + static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld() + ->ExpandField(true); + break; + case RES_TXTATR_FTN: + { + const SwFmtFtn& rFtn = static_cast<SwTxtFtn const*>(pAttr)->GetFtn(); + const SwDoc *pDoc = rNode.GetDoc(); + aExpand = rFtn.GetViewNumStr(*pDoc); + } + break; + default: + break; + } + m_aRetText = m_aRetText.replaceAt( nOffset + nFieldPos, 1, aExpand ); + m_aMap.push_back( ConversionMapEntry( nFieldPos, nOffset + nFieldPos ) ); + nOffset += ( aExpand.getLength() - 1 ); + } } } |