/* -*- 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 INCLUDED_SW_INC_PAGEDESC_HXX
#define INCLUDED_SW_INC_PAGEDESC_HXX
#include <tools/fract.hxx>
#include <tools/color.hxx>
#include "swdllapi.h"
#include "swtypes.hxx"
#include "frmfmt.hxx"
#include <editeng/numitem.hxx>
#include <editeng/borderline.hxx>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/text/HorizontalAdjust.hpp>
#include <o3tl/typed_flags_set.hxx>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
using namespace ::com::sun::star;
class SwTextFormatColl;
class SwNode;
class SwPageDescs;
typedef struct _xmlTextWriter* xmlTextWriterPtr;
/// Footnote information.
class SW_DLLPUBLIC SwPageFootnoteInfo
{
private:
SwTwips m_nMaxHeight;
///< maximum height of the footnote area.
sal_uLong m_nLineWidth;
///< width of separator line
SvxBorderLineStyle m_eLineStyle;
///< Style of the separator line
Color m_LineColor;
///< color of the separator line
Fraction m_Width;
///< percentage width of the separator line.
css::text::HorizontalAdjust m_eAdjust;
///< line adjustment.
SwTwips m_nTopDist;
///< distance between body and separator.
SwTwips m_nBottomDist;
///< distance between separator and first footnote
public:
SwTwips GetHeight()
const {
return m_nMaxHeight; }
sal_uLong GetLineWidth()
const {
return m_nLineWidth; }
const Color& GetLineColor()
const {
return m_LineColor;}
SvxBorderLineStyle GetLineStyle()
const {
return m_eLineStyle; }
const Fraction& GetWidth()
const {
return m_Width; }
css::text::HorizontalAdjust GetAdj()
const {
return m_eAdjust; }
SwTwips GetTopDist()
const {
return m_nTopDist; }
SwTwips GetBottomDist()
const {
return m_nBottomDist; }
void SetHeight(SwTwips
const nNew) { m_nMaxHeight = nNew; }
void SetLineWidth(sal_uLong
const nSet) { m_nLineWidth = nSet; }
void SetLineStyle(SvxBorderLineStyle
const eSet) {m_eLineStyle = eSet;}
void SetLineColor(
const Color& rCol) { m_LineColor = rCol;}
void SetWidth(
const Fraction & rNew) { m_Width = rNew; }
void SetAdj(css::text::HorizontalAdjust
const eNew) { m_eAdjust = eNew; }
void SetTopDist (SwTwips
const nNew) { m_nTopDist = nNew; }
void SetBottomDist(SwTwips
const nNew) { m_nBottomDist = nNew; }
SwPageFootnoteInfo();
SwPageFootnoteInfo(
const SwPageFootnoteInfo& );
SwPageFootnoteInfo&
operator=(
const SwPageFootnoteInfo& );
bool operator ==(
const SwPageFootnoteInfo& )
const;
};
/*
* Use of UseOnPage (m_eUse) and of FrameFormats
*
* RIGHT - m_Master only for right hand (odd) pages, left hand (even) pages
* always empty.
* LEFT - m_Left for left-hand pages, right-hand pages always empty.
* m_Left is a copy of master.
* ALL - m_Master for right hand pages, m_Left for left hand pages.
* - m_Left is a copy of master.
* MIRROR - m_Master for right hand pages, m_Left for left hand pagers.
* m_Left is a copy of master, margins are mirrored.
*
* UI works exclusively on master! m_Left is adjusted on Chg at document
* according to m_eUse.
*
* In order to simplify the work of the filters some more values are placed
* into m_eUse:
*
* HEADERSHARE - Content of header is equal on left and right hand pages.
* FOOTERSHARE - Content of footer is equal on left and right hand pages.
*
* The values are masked out in the respective getter and setter methods.
* Access to complete m_eUse including the information on header and footer
* via ReadUseOn(), WriteUseOn() (for Filter and CopyCTor)!
*
* The Frameformats for header/footer are adjusted by the UI according to
* the attributes for header and footer at master (height, margin, back-
* ground ...)
* Header/footer for left hand pages are copied or mirrored (Chg at
* document).
* The respective attribute for content is cared for automatically on Chg at
* document (contents are created or removed according to SHARE-information).
*/
enum class UseOnPage : sal_uInt16
{
NONE = 0x0000,
///< For internal use only.
Left = 0x0001,
Right = 0x0002,
All = 0x0003,
Mirror = 0x0007,
HeaderShare = 0x0040,
FooterShare = 0x0080,
FirstShare = 0x0100,
NoHeaderShare = 0xFFBF,
///< For internal use only.
NoFooterShare = 0xFF7F,
///< For internal use only.
NoFirstShare = 0xFEFF
};
namespace o3tl {
template<>
struct typed_flags<UseOnPage> : is_typed_flags<UseOnPage, 0xffff> {};
}
class SW_DLLPUBLIC SwPageDesc final
:
public sw::BroadcastingModify
{
friend class SwDoc;
friend class SwPageDescs;
UIName m_StyleName;
SvxNumberType m_NumType;
SwFrameFormat m_Master;
SwFrameFormat m_Left;
// FIXME epicycles growing here - page margins need to be stored differently
SwFrameFormat m_FirstMaster;
SwFrameFormat m_FirstLeft;
struct StashedPageDesc
{
std::optional<SwFrameFormat> m_oStashedFirst;
std::optional<SwFrameFormat> m_oStashedLeft;
std::optional<SwFrameFormat> m_oStashedFirstLeft;
};
mutable StashedPageDesc m_aStashedHeader;
mutable StashedPageDesc m_aStashedFooter;
sw::WriterMultiListener m_aDepends;
///< Because of grid alignment (register accuracy / register-true).
mutable const SwTextFormatColl* m_pTextFormatColl;
SwPageDesc *m_pFollow;
sal_uInt16 m_nRegHeight;
///< Sentence spacing and fontascent of style.
sal_uInt16 m_nRegAscent;
///< For grid alignment (register accuracy / register-true).
drawing::TextVerticalAdjust m_nVerticalAdjustment;
// doc/docx: vertically center / justify / bottom
UseOnPage m_eUse;
bool m_IsLandscape;
bool m_IsHidden;
/// Footnote information.
SwPageFootnoteInfo m_FootnoteInfo;
/// Backref to the assigned SwPageDescs list to handle renames.
SwPageDescs *m_pdList;
/** Called for mirroring of Chg (doc).
No adjustment at any other place. */
SAL_DLLPRIVATE
void Mirror();
SAL_DLLPRIVATE
void ResetAllAttr();
SAL_DLLPRIVATE SwPageDesc(
const UIName&, SwFrameFormat*, SwDoc &rDc );
struct change_name
{
change_name(
const UIName &rName) : mName(rName) {}
void operator()(SwPageDesc *pPageDesc) { pPageDesc->m_StyleName = mName; }
const UIName &mName;
};
virtual void SwClientNotify(
const SwModify&,
const SfxHint&) override;
public:
bool IsUsed()
const;
const UIName& GetName()
const {
return m_StyleName; }
bool SetName(
const UIName& rNewName);
bool GetLandscape()
const {
return m_IsLandscape; }
void SetLandscape(
bool bNew ) { m_IsLandscape = bNew; }
const SvxNumberType &GetNumType()
const {
return m_NumType; }
void SetNumType(
const SvxNumberType& rNew) { m_NumType = rNew; }
const SwPageFootnoteInfo &GetFootnoteInfo()
const {
return m_FootnoteInfo; }
SwPageFootnoteInfo &GetFootnoteInfo() {
return m_FootnoteInfo; }
void SetFootnoteInfo(
const SwPageFootnoteInfo &rNew) { m_FootnoteInfo = rNew; }
inline bool IsHeaderShared()
const;
inline bool IsFooterShared()
const;
inline void ChgHeaderShare(
bool bNew );
inline void ChgFooterShare(
bool bNew );
bool IsFirstShared()
const;
void ChgFirstShare(
bool bNew );
bool IsHidden()
const {
return m_IsHidden; }
void SetHidden(
bool const bValue) { m_IsHidden = bValue; }
/// Remember original header/footer formats even when they are hidden by "sharing".
void StashFrameFormat(
const SwFrameFormat& rFormat,
bool bHeader,
bool bLeft,
bool bF
irst);
/// Used to restore hidden header/footer formats.
const SwFrameFormat* GetStashedFrameFormat(bool bHeader, bool bLeft, bool bFirst) const;
/// Checks if the pagedescriptor has a stashed format according to the parameters or not.
bool HasStashedFormat(bool bHeader, bool bLeft, bool bFirst) const;
/// Gives the feature of removing the stashed format by hand if it is necessary.
void RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst);
/// Same as WriteUseOn(), but the >= HeaderShare part of the bitfield is not modified.
inline void SetUseOn( UseOnPage eNew );
inline UseOnPage GetUseOn() const;
void WriteUseOn(UseOnPage const eNew) { m_eUse = eNew; }
UseOnPage ReadUseOn() const { return m_eUse; }
SwFrameFormat &GetMaster() { return m_Master; }
SwFrameFormat &GetLeft() { return m_Left; }
SwFrameFormat &GetFirstMaster() { return m_FirstMaster; }
SwFrameFormat &GetFirstLeft() { return m_FirstLeft; }
const SwFrameFormat &GetMaster() const { return m_Master; }
const SwFrameFormat &GetLeft() const { return m_Left; }
const SwFrameFormat &GetFirstMaster() const { return m_FirstMaster; }
const SwFrameFormat &GetFirstLeft() const { return m_FirstLeft; }
/** Reset all attrs of the format but keep the ones a pagedesc
cannot live without. */
inline void ResetAllMasterAttr();
/** Layout uses the following methods to obtain a format in order
to be able to create a page. */
SwFrameFormat *GetRightFormat(bool const bFirst = false);
inline const SwFrameFormat *GetRightFormat(bool const bFirst = false) const;
SwFrameFormat *GetLeftFormat(bool const bFirst = false);
inline const SwFrameFormat *GetLeftFormat(bool const bFirst = false) const;
sal_uInt16 GetRegHeight() const { return m_nRegHeight; }
sal_uInt16 GetRegAscent() const { return m_nRegAscent; }
void SetRegHeight(sal_uInt16 const nNew) { m_nRegHeight = nNew; }
void SetRegAscent(sal_uInt16 const nNew) { m_nRegAscent = nNew; }
drawing::TextVerticalAdjust GetVerticalAdjustment () const {return m_nVerticalAdjustment; }
void SetVerticalAdjustment (const drawing::TextVerticalAdjust nVA) {m_nVerticalAdjustment = nVA; }
inline void SetFollow( const SwPageDesc* pNew );
const SwPageDesc* GetFollow() const { return m_pFollow; }
SwPageDesc* GetFollow() { return m_pFollow; }
void SetRegisterFormatColl( const SwTextFormatColl* rFormat );
const SwTextFormatColl* GetRegisterFormatColl() const;
void RegisterChange();
/// Query and set PoolFormat-Id.
sal_uInt16 GetPoolFormatId() const { return m_Master.GetPoolFormatId(); }
void SetPoolFormatId(sal_uInt16 const nId) { m_Master.SetPoolFormatId(nId); }
sal_uInt16 GetPoolHelpId() const { return m_Master.GetPoolHelpId(); }
void SetPoolHelpId(sal_uInt32 const nId){ m_Master.SetPoolHelpId(nId); }
sal_uInt8 GetPoolHlpFileId() const { return m_Master.GetPoolHlpFileId(); }
void SetPoolHlpFileId(sal_uInt8 const nId) { m_Master.SetPoolHlpFileId(nId); }
/// Query information from Client.
virtual bool GetInfo( SwFindNearestNode& ) const override;
const SwFrameFormat* GetPageFormatOfNode( const SwNode& rNd,
bool bCheckForThisPgDc = true ) const;
bool IsFollowNextPageOfNode( const SwNode& rNd ) const;
/// Given a SwNode return the pagedesc in use at that location.
static const SwPageDesc* GetPageDescOfNode(const SwNode& rNd);
static SwPageDesc* GetByName(SwDoc& rDoc, const UIName& rName);
SwPageDesc& operator=( const SwPageDesc& );
SwPageDesc( const SwPageDesc& );
virtual ~SwPageDesc() override;
void dumpAsXml(xmlTextWriterPtr pWriter) const;
};
namespace std {
template<>
struct less<SwPageDesc*> {
bool operator()(const SwPageDesc *pPageDesc, const UIName& rName) const
{ return pPageDesc->GetName() < rName; }
bool operator()(const UIName& rName, const SwPageDesc *pPageDesc) const
{ return rName < pPageDesc->GetName(); }
bool operator()(const SwPageDesc *lhs, const SwPageDesc *rhs) const
{ return lhs->GetName() < rhs->GetName(); }
};
}
inline void SwPageDesc::SetFollow( const SwPageDesc* pNew )
{
m_pFollow = pNew ? const_cast<SwPageDesc*>(pNew) : this;
}
inline bool SwPageDesc::IsHeaderShared() const
{
return bool(m_eUse & UseOnPage::HeaderShare);
}
inline bool SwPageDesc::IsFooterShared() const
{
return bool(m_eUse & UseOnPage::FooterShare);
}
inline void SwPageDesc::ChgHeaderShare( bool bNew )
{
if ( bNew )
m_eUse |= UseOnPage::HeaderShare;
else
m_eUse &= UseOnPage::NoHeaderShare;
}
inline void SwPageDesc::ChgFooterShare( bool bNew )
{
if ( bNew )
m_eUse |= UseOnPage::FooterShare;
else
m_eUse &= UseOnPage::NoFooterShare;
}
inline void SwPageDesc::SetUseOn( UseOnPage eNew )
{
UseOnPage eTmp = UseOnPage::NONE;
if (m_eUse & UseOnPage::HeaderShare)
eTmp = UseOnPage::HeaderShare;
if (m_eUse & UseOnPage::FooterShare)
eTmp |= UseOnPage::FooterShare;
if (m_eUse & UseOnPage::FirstShare)
eTmp |= UseOnPage::FirstShare;
m_eUse = eTmp | eNew;
}
inline UseOnPage SwPageDesc::GetUseOn() const
{
UseOnPage eRet = m_eUse;
eRet &= UseOnPage::NoHeaderShare;
eRet &= UseOnPage::NoFooterShare;
eRet &= UseOnPage::NoFirstShare;
return eRet;
}
inline void SwPageDesc::ResetAllMasterAttr()
{
ResetAllAttr();
}
inline const SwFrameFormat *SwPageDesc::GetRightFormat(bool const bFirst) const
{
return const_cast<SwPageDesc*>(this)->GetRightFormat(bFirst);
}
inline const SwFrameFormat *SwPageDesc::GetLeftFormat(bool const bFirst) const
{
return const_cast<SwPageDesc*>(this)->GetLeftFormat(bFirst);
}
class SwPageDescExt
{
public:
SwPageDesc m_PageDesc;
private:
SwDoc& m_rDoc;
UIName m_sFollow;
void SetPageDesc(const SwPageDesc & rPageDesc);
public:
SwPageDescExt(const SwPageDesc & rPageDesc, SwDoc& rDoc);
SwPageDescExt(const SwPageDescExt & rSrc);
~SwPageDescExt();
SwPageDescExt & operator = (const SwPageDescExt & rSrc);
SwPageDescExt & operator = (const SwPageDesc & rSrc);
UIName const & GetName() const;
explicit operator SwPageDesc() const; // #i7983#
};
namespace sw {
class PageFootnoteHint final : public SfxHint
{
public:
PageFootnoteHint() : SfxHint(SfxHintId::SwPageFootnote) {}
};
SW_DLLPUBLIC SwTwips FootnoteSeparatorHeight(SwDoc& rDoc, SwPageFootnoteInfo const&);
}
typedef boost::multi_index_container<
SwPageDesc*,
boost::multi_index::indexed_by<
boost::multi_index::random_access<>,
boost::multi_index::ordered_unique<
boost::multi_index::identity<SwPageDesc*> >
>
>
SwPageDescsBase;
class SwPageDescs final
{
// function updating ByName index via modify
friend bool SwPageDesc::SetName( const UIName& rNewName );
typedef SwPageDescsBase::nth_index<0>::type ByPos;
typedef SwPageDescsBase::nth_index<1>::type ByName;
typedef ByPos::iterator iterator;
iterator find_( const UIName &name ) const;
SwPageDescsBase m_Array;
ByPos &m_PosIndex;
ByName &m_NameIndex;
public:
typedef ByPos::const_iterator const_iterator;
typedef SwPageDescsBase::size_type size_type;
typedef SwPageDescsBase::value_type value_type;
SwPageDescs();
// frees all SwPageDesc!
~SwPageDescs();
void clear() { return m_Array.clear(); }
bool empty() const { return m_Array.empty(); }
size_t size() const { return m_Array.size(); }
std::pair<const_iterator,bool> push_back( const value_type& x );
void erase( const value_type& x );
void erase( size_type index );
void erase( const_iterator const& position );
const_iterator find( const UIName &name ) const
{ return find_( name ); }
const value_type& operator[]( size_t index_ ) const
{ return m_PosIndex.operator[]( index_ ); }
const value_type& front() const { return m_PosIndex.front(); }
const value_type& back() const { return m_PosIndex.back(); }
const_iterator begin() const { return m_PosIndex.begin(); }
const_iterator end() const { return m_PosIndex.end(); }
bool contains( const value_type& x ) const
{ return x->m_pdList == this; }
void dumpAsXml(xmlTextWriterPtr pWriter) const;
};
#endif // INCLUDED_SW_INC_PAGEDESC_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */