diff options
author | Tobias Lippert <drtl@fastmail.fm> | 2014-06-01 14:30:36 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2014-06-06 14:02:16 +0000 |
commit | 3aca57fb9c7c979d971cae6bb3ad73c6dc412685 (patch) | |
tree | 2f2c23fe3251ad8708337c13d064bfab010631ad | |
parent | 67b4b34cce4abf745b24c858d533a25c291b5093 (diff) |
TOX: Extract generation of tab stop attributes to its own class.
This allows us to pass through less parameters which are only used for
this functionality.
Conflicts:
sw/inc/ToxTextGenerator.hxx
sw/source/core/tox/ToxTextGenerator.cxx
Change-Id: I5a03cf8ec6d86d05f2a7f7771668585669c1e595
Reviewed-on: https://gerrit.libreoffice.org/9613
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | sw/CppunitTest_sw_tox.mk | 1 | ||||
-rw-r--r-- | sw/Library_sw.mk | 1 | ||||
-rw-r--r-- | sw/inc/ToxTabStopTokenHandler.hxx | 114 | ||||
-rw-r--r-- | sw/inc/ToxTextGenerator.hxx | 13 | ||||
-rw-r--r-- | sw/qa/cppunit/tox/test_ToxTextGenerator.cxx | 18 | ||||
-rw-r--r-- | sw/source/core/doc/doctxm.cxx | 14 | ||||
-rw-r--r-- | sw/source/core/tox/ToxTabStopTokenHandler.cxx | 126 | ||||
-rw-r--r-- | sw/source/core/tox/ToxTextGenerator.cxx | 100 |
8 files changed, 295 insertions, 92 deletions
diff --git a/sw/CppunitTest_sw_tox.mk b/sw/CppunitTest_sw_tox.mk index e45f5976ed37..23c61fe8505f 100644 --- a/sw/CppunitTest_sw_tox.mk +++ b/sw/CppunitTest_sw_tox.mk @@ -22,6 +22,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_tox_test, \ comphelper \ cppu \ cppuhelper \ + editeng \ sal \ svt \ sw \ diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index c073564030a1..aced49f8e319 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -389,6 +389,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\ sw/source/core/tox/toxhlp \ sw/source/core/tox/txmsrt \ sw/source/core/tox/ToxLinkProcessor \ + sw/source/core/tox/ToxTabStopTokenHandler \ sw/source/core/tox/ToxTextGenerator \ sw/source/core/tox/ToxWhitespaceStripper \ sw/source/core/txtnode/SwGrammarContact \ diff --git a/sw/inc/ToxTabStopTokenHandler.hxx b/sw/inc/ToxTabStopTokenHandler.hxx new file mode 100644 index 000000000000..696a4cb84701 --- /dev/null +++ b/sw/inc/ToxTabStopTokenHandler.hxx @@ -0,0 +1,114 @@ +/* -*- 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 TOXTABSTOPTOKENHANDLER_HXX_ +#define TOXTABSTOPTOKENHANDLER_HXX_ + +#include "swdllapi.h" +#include "rtl/ustring.hxx" + +#include "editeng/tstpitem.hxx" + +class SwFormToken; +class SwPageDesc; +class SwRootFrm; +class SwTxtNode; + +namespace sw { + +/** This class handles tab stop tokens in the pattern for tox entries. + * + * @internal + * This is an interface class. It allows to mock the class in unit tests + */ +class SW_DLLPUBLIC ToxTabStopTokenHandler +{ +public: + virtual ~ToxTabStopTokenHandler() {} + + /** Return value of HandleTabStopToken */ + struct HandledTabStopToken { + OUString text; + SvxTabStop tabStop; + }; + + /** Handle a tab stop token. + * + * @returns A HandledTabStopToken. Make sure to append the text field to the text of the target node + * and to provide the returned SvxTabStop to the attributes of the node. + */ + virtual HandledTabStopToken + HandleTabStopToken(const SwFormToken& aToken, const SwTxtNode& targetNode, + const SwRootFrm *currentLayout) const = 0; +}; + +/** The default implementation of ToxTabStopTokenHandler */ +class SW_DLLPUBLIC DefaultToxTabStopTokenHandler : public ToxTabStopTokenHandler +{ +public: + + enum TabStopReferencePolicy {TABSTOPS_RELATIVE_TO_INDENT, TABSTOPS_RELATIVE_TO_PAGE}; + + /** + * @param indexOfSectionNode + * The index of the section node. It is needed to determine whether a page description was given by a node + * before the tox section. + * + * @param defaultPageDescription + * Which page description shall be used if we do not find one or the found page description was provided by + * a node before the tox section + * + * @param tabPositionIsRelativeToParagraphIndent + * Whether the tab position is relative to the paragraph indent. (toxForm.IsRelTabPos() is true or false.) + * + * @param tabstopReferencePolicy + * How tab stops are positioned. (#i21237) The default behavior is to place tab stops relative to the page. + */ + DefaultToxTabStopTokenHandler(sal_uInt32 indexOfSectionNode, const SwPageDesc& defaultPageDescription, + bool tabPositionIsRelativeToParagraphIndent, + TabStopReferencePolicy referencePolicy = TABSTOPS_RELATIVE_TO_PAGE); + + /** Handle a tab stop token. + * + * If the token contains tab alignment information, that is used to create the SvxTabStop. + * Else, the information about the tab stop is taken from a page description. + * Depending on the TabStopReferencePolicy provided in the constructor, the + * method behaves differently when deriving the tab stop position. + */ + ToxTabStopTokenHandler::HandledTabStopToken + HandleTabStopToken(const SwFormToken& aToken, const SwTxtNode& targetNode, + const SwRootFrm *currentLayout) const SAL_OVERRIDE; + +private: + /** Test whether the page layout can be obtained by a layout rectangle. + * + * Is used to determine how to find tab stop position. + */ + static bool + CanUseLayoutRectangle(const SwTxtNode& targetNode, const SwRootFrm *currentLayout); + + /** Calculate the page margin from the page description. + * + * This is the fallback method to determine the position of a tab stop. + */ + long + CalculatePageMarginFromPageDescription(const SwTxtNode& targetNode) const; + + sal_uInt32 mIndexOfSectionNode; + const SwPageDesc& mDefaultPageDescription; + bool mTabPositionIsRelativeToParagraphIndent; + TabStopReferencePolicy mTabStopReferencePolicy; +}; + +} + +#endif /* TOXTABSTOPTOKENHANDLER_HXX_ */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/inc/ToxTextGenerator.hxx b/sw/inc/ToxTextGenerator.hxx index 25e49579a662..a9c9cadd279b 100644 --- a/sw/inc/ToxTextGenerator.hxx +++ b/sw/inc/ToxTextGenerator.hxx @@ -38,19 +38,26 @@ class SwDoc; class SwForm; struct SwFormToken; class SwPageDesc; +class SwRootFrm; class SwTxtAttr; class SwTxtNode; struct SwTOXSortTabBase; +class SvxTabStop; class ToxTextGeneratorTest; namespace sw { class ToxLinkProcessor; +class ToxTabStopTokenHandler; +/** This class generates text for the entries of a table of x. + * + * You can control its behavior by calling @link SetTabstopPolicy() and specifying the desired behavior. + */ class SW_DLLPUBLIC ToxTextGenerator { public: - ToxTextGenerator(const SwForm& toxForm); + ToxTextGenerator(const SwForm& toxForm, boost::shared_ptr<ToxTabStopTokenHandler> tabStopHandler); virtual ~ToxTextGenerator(); @@ -61,12 +68,12 @@ public: */ void GenerateText(SwDoc *doc, const std::vector<SwTOXSortTabBase*>& entries, - sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess, - sal_uInt32 _nTOXSectNdIdx, const SwPageDesc* _pDefaultPageDesc); + sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess); private: const SwForm& mToxForm; boost::shared_ptr<ToxLinkProcessor> mLinkProcessor; + boost::shared_ptr<ToxTabStopTokenHandler> mTabStopTokenHandler; /** A handled text token. * It contains the information which should be added to the target text node. diff --git a/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx b/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx index 0d7d75daa7cb..f3732ab9a0fa 100644 --- a/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx +++ b/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx @@ -12,13 +12,16 @@ #include "tox.hxx" #include "txmsrt.hxx" #include "ToxTextGenerator.hxx" +#include "ToxTabStopTokenHandler.hxx" + +#include <boost/make_shared.hpp> #include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/plugin/TestPlugIn.h> -using sw::ToxTextGenerator; +using namespace sw; class ToxTextGeneratorTest : public CppUnit::TestFixture { public: @@ -100,10 +103,21 @@ ToxTextGeneratorTest::EmptyStringIsReturnedAsNumStringIfToxSourcesIsEmpty() CPPUNIT_ASSERT_EQUAL(expected, actual); } +class MockedToxTabStopTokenHandler : public ToxTabStopTokenHandler { +public: + virtual HandledTabStopToken + HandleTabStopToken(const SwFormToken& aToken, const SwTxtNode& targetNode, + const SwRootFrm *currentLayout) const { + (void)(aToken); (void)(targetNode); (void)(currentLayout); // avoid unused warnings. + return HandledTabStopToken(); + } +}; + class ToxTextGeneratorWithMockedChapterField : public ToxTextGenerator { public: ToxTextGeneratorWithMockedChapterField(SwForm &form) - : ToxTextGenerator(form), mChapterFieldType(), mChapterField(&mChapterFieldType) {;} + : ToxTextGenerator(form, boost::make_shared<MockedToxTabStopTokenHandler>()), + mChapterFieldType(), mChapterField(&mChapterFieldType) {;} SwChapterField& GetChapterField() { diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx index 6ea927918123..3a80426ef4f0 100644 --- a/sw/source/core/doc/doctxm.cxx +++ b/sw/source/core/doc/doctxm.cxx @@ -65,6 +65,9 @@ #include <scriptinfo.hxx> #include <switerator.hxx> #include <ToxTextGenerator.hxx> +#include <ToxTabStopTokenHandler.hxx> + +#include <boost/make_shared.hpp> using namespace ::com::sun::star; @@ -975,8 +978,15 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr, // pass node index of table-of-content section and default page description // to method <GenerateText(..)>. ::SetProgressState( 0, pDoc->GetDocShell() ); - sw::ToxTextGenerator ttgn(GetTOXForm()); - ttgn.GenerateText((SwDoc*) GetFmt()->GetDoc(), aSortArr, nCnt, nRange, pSectNd->GetIndex(), pDefaultPageDesc); + + boost::shared_ptr<sw::ToxTabStopTokenHandler> tabStopTokenHandler = + boost::make_shared<sw::DefaultToxTabStopTokenHandler>( + pSectNd->GetIndex(), *pDefaultPageDesc, GetTOXForm().IsRelTabPos(), + pDoc->GetDocumentSettingManager().get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) ? + sw::DefaultToxTabStopTokenHandler::TABSTOPS_RELATIVE_TO_INDENT : + sw::DefaultToxTabStopTokenHandler::TABSTOPS_RELATIVE_TO_PAGE); + sw::ToxTextGenerator ttgn(GetTOXForm(), tabStopTokenHandler); + ttgn.GenerateText((SwDoc*) GetFmt()->GetDoc(), aSortArr, nCnt, nRange); nCnt += nRange - 1; } diff --git a/sw/source/core/tox/ToxTabStopTokenHandler.cxx b/sw/source/core/tox/ToxTabStopTokenHandler.cxx new file mode 100644 index 000000000000..1ab4ee4562e6 --- /dev/null +++ b/sw/source/core/tox/ToxTabStopTokenHandler.cxx @@ -0,0 +1,126 @@ +/* -*- 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 "ToxTabStopTokenHandler.hxx" + +#include "editeng/tstpitem.hxx" +#include "editeng/lrspitem.hxx" + +#include "cntfrm.hxx" +#include "fmtfsize.hxx" +#include "fmtpdsc.hxx" +#include "frmfmt.hxx" +#include "ndtxt.hxx" +#include "pagedesc.hxx" +#include "pagefrm.hxx" +#include "swrect.hxx" +#include "tox.hxx" + +namespace sw { + +DefaultToxTabStopTokenHandler::DefaultToxTabStopTokenHandler(sal_uInt32 indexOfSectionNode, + const SwPageDesc& defaultPageDescription, + bool tabPositionIsRelativeToParagraphIndent, + TabStopReferencePolicy referencePolicy) +: mIndexOfSectionNode(indexOfSectionNode), + mDefaultPageDescription(defaultPageDescription), + mTabPositionIsRelativeToParagraphIndent(tabPositionIsRelativeToParagraphIndent), + mTabStopReferencePolicy(referencePolicy) +{ +} + + +ToxTabStopTokenHandler::HandledTabStopToken +DefaultToxTabStopTokenHandler::HandleTabStopToken( + const SwFormToken& aToken, const SwTxtNode& targetNode, const SwRootFrm *currentLayout) const +{ + HandledTabStopToken result; + + if (aToken.bWithTab) { // #i21237# + result.text = "\t"; + } + + // check whether a tab adjustment has been specified. + if (SVX_TAB_ADJUST_END > aToken.eTabAlign) { + const SvxLRSpaceItem& rLR = (SvxLRSpaceItem&) targetNode.SwCntntNode::GetAttr(RES_LR_SPACE, true); + + long nTabPosition = aToken.nTabStopPosition; + if (!mTabPositionIsRelativeToParagraphIndent && rLR.GetTxtLeft()) { + nTabPosition -= rLR.GetTxtLeft(); + } + result.tabStop = SvxTabStop(nTabPosition, aToken.eTabAlign, cDfltDecimalChar, aToken.cTabFillChar); + return result; + } + + SwRect aNdRect; + if (CanUseLayoutRectangle(targetNode, currentLayout)) { + aNdRect = targetNode.FindLayoutRect(true); + } + long nRightMargin; + if (aNdRect.IsEmpty()) { + nRightMargin = CalculatePageMarginFromPageDescription(targetNode); + } else { + nRightMargin = aNdRect.Width(); + } + //#i24363# tab stops relative to indent + if (mTabStopReferencePolicy == TABSTOPS_RELATIVE_TO_INDENT) { + // left margin of paragraph style + const SvxLRSpaceItem& rLRSpace = targetNode.GetTxtColl()->GetLRSpace(); + nRightMargin -= rLRSpace.GetLeft(); + nRightMargin -= rLRSpace.GetTxtFirstLineOfst(); + } + + result.tabStop = SvxTabStop(nRightMargin, SVX_TAB_ADJUST_RIGHT, cDfltDecimalChar, aToken.cTabFillChar); + return result; +} + +long +DefaultToxTabStopTokenHandler::CalculatePageMarginFromPageDescription(const SwTxtNode& targetNode) const +{ + sal_uInt32 nPgDescNdIdx = targetNode.GetIndex() + 1; + const SwPageDesc *pPageDesc = targetNode.FindPageDesc(false, &nPgDescNdIdx); + if (!pPageDesc || nPgDescNdIdx < mIndexOfSectionNode) { + // Use default page description, if none is found or the found one is given by a Node before the + // table-of-content section. + pPageDesc = &mDefaultPageDescription; + } + const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster(); + long result = rPgDscFmt.GetFrmSize().GetWidth() - rPgDscFmt.GetLRSpace().GetLeft() + - rPgDscFmt.GetLRSpace().GetRight(); + return result; +} + + +/*static*/ bool +DefaultToxTabStopTokenHandler::CanUseLayoutRectangle(const SwTxtNode& targetNode, const SwRootFrm *currentLayout) +{ + const SwPageDesc* pageDescription = + ((SwFmtPageDesc&) targetNode.SwCntntNode::GetAttr(RES_PAGEDESC)).GetPageDesc(); + + if (!pageDescription) { + return false; + } + const SwFrm* pFrm = targetNode.getLayoutFrm(currentLayout, 0, 0, true); + if (!pFrm) { + return false; + } + pFrm = pFrm->FindPageFrm(); + if (!pFrm) { + return false; + } + const SwPageFrm* pageFrm = static_cast<const SwPageFrm*>(pFrm); + if (pageDescription != pageFrm->GetPageDesc()) { + return false; + } + return true; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/tox/ToxTextGenerator.cxx b/sw/source/core/tox/ToxTextGenerator.cxx index 67de2cde31b3..3e2581576bec 100644 --- a/sw/source/core/tox/ToxTextGenerator.cxx +++ b/sw/source/core/tox/ToxTextGenerator.cxx @@ -21,7 +21,6 @@ #include "chpfld.hxx" #include "cntfrm.hxx" -#include "pagefrm.hxx" #include "fchrfmt.hxx" #include "doc.hxx" #include "fmtinfmt.hxx" @@ -30,18 +29,14 @@ #include "tox.hxx" #include "txmsrt.hxx" #include "fmtautofmt.hxx" -#include "fmtfsize.hxx" -#include "fmtpdsc.hxx" #include "DocumentSettingManager.hxx" #include "SwStyleNameMapper.hxx" #include "swatrset.hxx" #include "ToxWhitespaceStripper.hxx" #include "ToxLinkProcessor.hxx" +#include "ToxTabStopTokenHandler.hxx" #include "txatbase.hxx" -#include "editeng/tstpitem.hxx" -#include "editeng/lrspitem.hxx" -#include "rtl/ustring.hxx" #include "svl/itemiter.hxx" #include <boost/foreach.hpp> @@ -95,9 +90,11 @@ ToxTextGenerator::GetNumStringOfFirstNode( const SwTOXSortTabBase& rBase, bool b } -ToxTextGenerator::ToxTextGenerator(const SwForm& toxForm) -:mToxForm(toxForm), - mLinkProcessor(new ToxLinkProcessor()) +ToxTextGenerator::ToxTextGenerator(const SwForm& toxForm, + boost::shared_ptr<ToxTabStopTokenHandler> tabStopHandler) +: mToxForm(toxForm), + mLinkProcessor(new ToxLinkProcessor()), + mTabStopTokenHandler(tabStopHandler) {;} ToxTextGenerator::~ToxTextGenerator() @@ -153,9 +150,9 @@ ToxTextGenerator::GenerateTextForChapterToken(const SwFormToken& chapterToken, c // Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control, // which page description is used, no appropriate one is found. -void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabBase*> &entries, - sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess, sal_uInt32 _nTOXSectNdIdx, - const SwPageDesc* _pDefaultPageDesc) +void +ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabBase*> &entries, + sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess) { // pTOXNd is only set at the first mark SwTxtNode* pTOXNd = (SwTxtNode*)entries.at(indexOfEntryToProcess)->pTOXNd; @@ -204,80 +201,13 @@ void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabB } break; - case TOKEN_TAB_STOP: - if (aToken.bWithTab) // #i21237# - rTxt += "\t"; - - if(SVX_TAB_ADJUST_END > aToken.eTabAlign) - { - const SvxLRSpaceItem& rLR = - (SvxLRSpaceItem&)pTOXNd-> - SwCntntNode::GetAttr( RES_LR_SPACE, true ); - - long nTabPosition = aToken.nTabStopPosition; - if( !mToxForm.IsRelTabPos() && rLR.GetTxtLeft() ) - nTabPosition -= rLR.GetTxtLeft(); - aTStops.Insert( SvxTabStop( nTabPosition, - aToken.eTabAlign, - cDfltDecimalChar, - aToken.cTabFillChar )); - } - else - { - const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd-> - SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc(); - - bool bCallFindRect = true; - long nRightMargin; - if( pPageDesc ) - { - const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, true ); - if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) || - pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() ) - // we have to go via the PageDesc here - bCallFindRect = false; - } - - SwRect aNdRect; - if( bCallFindRect ) - aNdRect = pTOXNd->FindLayoutRect( true ); - - if( aNdRect.IsEmpty() ) - { - // Nothing helped so far, so we go via the PageDesc - sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1; - sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx; - pPageDesc = pTOXNd->FindPageDesc( false, pPgDescNdIdx ); - if ( !pPageDesc || - *pPgDescNdIdx < _nTOXSectNdIdx ) - { - // Use default page description, if none is found - // or the found one is given by a Node before the - // table-of-content section. - pPageDesc = _pDefaultPageDesc; - } - - const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster(); - nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() - - rPgDscFmt.GetLRSpace().GetLeft() - - rPgDscFmt.GetLRSpace().GetRight(); - } - else - nRightMargin = aNdRect.Width(); - //#i24363# tab stops relative to indent - if( pDoc->GetDocumentSettingManager().get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) ) - { - // left margin of paragraph style - const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace(); - nRightMargin -= rLRSpace.GetLeft(); - nRightMargin -= rLRSpace.GetTxtFirstLineOfst(); - } - - aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT, - cDfltDecimalChar, - aToken.cTabFillChar )); - } + case TOKEN_TAB_STOP: { + ToxTabStopTokenHandler::HandledTabStopToken htst = + mTabStopTokenHandler->HandleTabStopToken(aToken, *pTOXNd, pDoc->GetCurrentLayout()); + rTxt += htst.text; + aTStops.Insert(htst.tabStop); break; + } case TOKEN_TEXT: rTxt += aToken.sText; |