office-gobmx/sw/inc/ToxTextGenerator.hxx
Michael Stahl 0633189fab tdf#162121 sw: fix tab stop position in columned ToX
There is a SvxTabAdjust::End but this only exists in the definition of
index entry templates, it is not possible to set this on a tab stop on a
text node.

So the ToxTabStopTokenHandler converts this into a SvxTabAdjust::Right
tab stop with a fixed position.

DefaultToxTabStopTokenHandler::CanUseLayoutRectangle() has inverted
condition but that doesn't matter because there are no layout frames at
that point.
(regression from commit 3aca57fb9c)

The main problem is that getting the with from the layout rectangle
never works because there's no layout frame, and the alternative only
takes into account the page dimensions and not any margins of the
section, columns, or gap between columns, not to mention that the ToX
could also be in a table etc.

Refactor this so that the tab stops are set only after all the layout
frames are created.

An unfixable problem remains in case the ToX has columns of different
width.

The wrong tab positions are problematic if TabOverMargin is enabled
since commit 10d753b8aa

Change-Id: Ia712c9bf42b2518e396f1b9e7efd65869ebc5ab4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171585
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Tested-by: Jenkins
2024-08-07 15:28:59 +02:00

176 lines
6.1 KiB
C++

/* -*- 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/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef SW_TOXTEXTGENERATOR_HXX_
#define SW_TOXTEXTGENERATOR_HXX_
#include <rtl/ustring.hxx>
#include <sal/types.h>
#include "fmtautofmt.hxx"
#include <memory>
#include <optional>
#include <vector>
#include <unordered_map>
class SfxItemSet;
class SwAttrPool;
class SwFormatAutoFormat;
class SwChapterField;
class SwChapterFieldType;
class SwContentFrame;
class SwRootFrame;
class SwContentNode;
class SwDoc;
class SwForm;
struct SwFormToken;
class SwTextAttr;
class SwTextNode;
struct SwTOXSortTabBase;
class ToxTextGeneratorTest;
namespace sw {
class ToxLinkProcessor;
class ToxTabStopTokenHandler;
class ToxWhitespaceStripper;
/** 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 ToxTextGenerator
{
public:
ToxTextGenerator(const SwForm& toxForm, std::shared_ptr<ToxTabStopTokenHandler> tabStopHandler);
virtual ~ToxTextGenerator();
/** Generate the text for an entry of a table of X (X is, e.g., content).
*
* This method will process the entries in @p entries, starting at @p indexOfEntryToProcess and
* process @p numberOfEntriesToProcess entries.
*/
std::optional<std::pair<SwTextNode *, SvxTabStopItem>>
GenerateText(SwDoc *doc,
std::unordered_map<OUString, int> & rMarkURLs,
const std::vector<std::unique_ptr<SwTOXSortTabBase>>& entries,
sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess,
SwRootFrame const* pLayout);
private:
const SwForm& mToxForm;
std::shared_ptr<ToxLinkProcessor> mLinkProcessor;
std::shared_ptr<ToxTabStopTokenHandler> mTabStopTokenHandler;
/** A handled text token.
* It contains the information which should be added to the target text node.
*/
struct HandledTextToken {
OUString text;
std::vector<std::unique_ptr<SwFormatAutoFormat>> autoFormats;
std::vector<sal_Int32> startPositions;
std::vector<sal_Int32> endPositions;
};
static void GetAttributesForNode(
HandledTextToken & rResult,
sal_Int32 & rOffset,
SwTextNode const& rNode,
ToxWhitespaceStripper const& rStripper,
SwAttrPool & rPool,
SwRootFrame const*const pLayout);
/** Append text (and selected attributes) to a target node.
*
* Will take the text of @p source, and return the text and the attributes which should be added to the
* target text node. @see CollectAttributesForTox() for the criteria of the attributes which are taken.
*/
static HandledTextToken
HandleTextToken(const SwTOXSortTabBase& source, SwAttrPool& attrPool,
SwRootFrame const*const pLayout);
/** Applies the result of a handled text token to a target node. */
static void
ApplyHandledTextToken(const HandledTextToken& htt, SwTextNode& targetNode);
/** Handle a page number token.
*
* Will return a string of @p numberOfToxSources concatenated '@' signs, separated by commas, and
* finished by a '~'.
* (The '@' sign is the magic character C_NUM_REPL, the '~' sign is the magic character C_END_PAGE_NUM.
*
* @internal
* The count of similar entries, i.e., nodes in aTOXSources of SwTOXSortTabBase gives the PagerNumber
* pattern.
*/
static OUString
ConstructPageNumberPlaceholder(size_t numberOfToxSources);
/** Collect the attributes of a hint that shall be copied over to the TOX.
*
* Some text attributes are used in the TOX entries. This method defines which attributes are used.
*
* @param hint The hint from which the attributes are taken
* @param pool The attribute pool for the new items
*/
static std::shared_ptr<SfxItemSet>
CollectAttributesForTox(const SwTextAttr& hint, SwAttrPool& pool);
/** This method will call GetNumStringOfFirstNode() of the first node in the provided SwTOXSortTabBase.
*
* The parameters @p bUsePrefix and @p nLevel are passed to SwTextNode::GetNumString()
*
* @internal
* The method is only called if several preconditions for @p rBase are true. Check the implementation
* for details.
*/
static OUString
GetNumStringOfFirstNode(const SwTOXSortTabBase& rBase, bool bUsePrefix,
sal_uInt8 nLevel, SwRootFrame const* pLayout, bool bAddSpace = true);
/** Handle a chapter token.
*/
OUString
HandleChapterToken(const SwTOXSortTabBase& rBase, const SwFormToken& aToken,
SwRootFrame const* pLayout) const;
/** Generate the text for a chapter token.
*/
OUString
GenerateTextForChapterToken(const SwFormToken& chapterToken, const SwContentFrame* contentFrame,
const SwContentNode *contentNode, SwRootFrame const* pLayout) const;
/** Obtain a ChapterField to use for the text generation.
* @internal
* This method is overridden in the unittests. Do not override it yourself.
*/
virtual SwChapterField
ObtainChapterField(SwChapterFieldType* chapterFieldType, const SwFormToken* chapterToken,
const SwContentFrame* contentFrame, const SwContentNode *contentNode) const;
friend class ::ToxTextGeneratorTest;
};
}
#endif /* SW_TOXTEXTGENERATOR_HXX_ */
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */