Kaydet (Commit) 3aca57fb authored tarafından Tobias Lippert's avatar Tobias Lippert Kaydeden (comit) Caolán McNamara

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/9613Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst 67b4b34c
......@@ -22,6 +22,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_tox_test, \
comphelper \
cppu \
cppuhelper \
editeng \
sal \
svt \
sw \
......
......@@ -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 \
......
/* -*- 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: */
......@@ -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.
......
......@@ -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() {
......
......@@ -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;
}
......
/* -*- 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: */
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment