/* -*- 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_TBLAFMT_HXX #define INCLUDED_SW_INC_TBLAFMT_HXX /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * The structure of table auto formatting should not be changed. It is used * by different code of Writer and Calc. If a change is necessary, the * source code of both applications must be changed! * * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #include #include #include #include #include #include #include "fmtpdsc.hxx" #include "fmtornt.hxx" #include "swdllapi.h" struct SwAfVersions; class SvNumberFormatter; class SwTable; class SwBoxAutoFormat : public AutoFormatBase { private: // Writer specific std::unique_ptr m_aTextOrientation; std::unique_ptr m_aVerticalAlignment; // number format OUString m_sNumFormatString; LanguageType m_eSysLanguage; LanguageType m_eNumFormatLanguage; css::uno::WeakReference m_wXObject; public: SwBoxAutoFormat(); SwBoxAutoFormat( const SwBoxAutoFormat& rNew ); ~SwBoxAutoFormat(); /// assignment-op (still used) SwBoxAutoFormat& operator=(const SwBoxAutoFormat& rRef); /// Comparing based of boxes backgrounds. bool operator==(const SwBoxAutoFormat& rRight); // The get-methods. const SvxFrameDirectionItem& GetTextOrientation() const { return *m_aTextOrientation; } const SwFormatVertOrient& GetVerticalAlignment() const { return *m_aVerticalAlignment; } void GetValueFormat( OUString& rFormat, LanguageType& rLng, LanguageType& rSys ) const { rFormat = m_sNumFormatString; rLng = m_eNumFormatLanguage; rSys = m_eSysLanguage; } const OUString& GetNumFormatString() const { return m_sNumFormatString; } const LanguageType& GetSysLanguage() const { return m_eSysLanguage; } const LanguageType& GetNumFormatLanguage() const { return m_eNumFormatLanguage; } // The set-methods. void SetTextOrientation( const SvxFrameDirectionItem& rNew ) { m_aTextOrientation.reset(static_cast(rNew.Clone())); } void SetVerticalAlignment( const SwFormatVertOrient& rNew ) { m_aVerticalAlignment.reset(static_cast(rNew.Clone())); } void SetValueFormat( const OUString& rFormat, LanguageType eLng, LanguageType eSys ) { m_sNumFormatString = rFormat; m_eNumFormatLanguage = eLng; m_eSysLanguage = eSys; } void SetNumFormatString(const OUString& rNew) { m_sNumFormatString = rNew; } void SetSysLanguage(const LanguageType& rNew) { m_eSysLanguage = rNew; } void SetNumFormatLanguage(const LanguageType& rNew) { m_eNumFormatLanguage = rNew; } css::uno::WeakReference const& GetXObject() const { return m_wXObject; } void SetXObject(css::uno::Reference const& xObject) { m_wXObject = xObject; } bool Load( SvStream& rStream, const SwAfVersions& rVersions, sal_uInt16 nVer ); bool Save( SvStream& rStream, sal_uInt16 fileVersion ) const; }; enum class SwTableAutoFormatUpdateFlags { Char = 1, Box = 2 }; namespace o3tl { template<> struct typed_flags : is_typed_flags {}; }; /* @remarks A table has a number of lines. These lines seem to correspond with rows, except in the case of rows spanning more than one line. Each line contains a number of boxes/cells. AutoFormat properties are retrieved and stored in a grid of 16 table boxes. A sampling approach is used to read the data. 4 lines are picked, and 4 boxes are picked from each. The line picking and box picking algorithms are similar. We start at the first line/box, and pick lines/boxes one by one for a maximum of 3. The 4th line/box is the last line/box in the current table/line. If we hit the end of lines/boxes, the last line/box encountered is picked several times. For example, in a 2x3 table, the 4 lines will be [0, 1, 1, 1]. In each line, the boxes will be [0, 1, 2, 2]. In a 6x5 table, the 4 lines will be [0, 1, 2, 4] and the boxes per line will be [0, 1, 2, 5]. As you can see, property extraction/application is lossless for tables that are 4x4 or smaller (and in fact has a bit of redundancy). For larger tables, we lose any individual cell formatting for the range [(3,rows - 1) -> (3, cols - 1)]. That formatting is replaced by formatting from the saved cells: 0 1 2 3 4 5 +-----------------------------------------------------------------------+ 0 | Saved | Saved | Saved | | | Saved | +-----------------------------------------------------------------------+ 1 | Saved | Saved | Saved | | | Saved | +-----------------------------------------------------------------------+ 2 | Saved | Saved | Saved | | | Saved | +-----------------------------------------------------------------------+ 3 | | | | | | | +-----------------------------------------------------------------------+ 4 | | | | | | | +-----------------------------------------------------------------------+ 5 | Saved | Saved | Saved | | | Saved | +-----------+-----------+-----------+-----------+-----------+-----------+ The properties saved are divided into three categories: 1. Character properties: Font, font size, weight, etc. 2. Box properties: Box, cell background 3. Table properties: Properties that are set in the Table->Table Properties dialog. Character and box properties are stored per cell (and are lossy for tables larger than 4x4). Table properties are stored per-table, and are lossless. */ class SW_DLLPUBLIC SwTableAutoFormat { friend class SwDocTest; friend void FinitCore(); // To destroy default pointer. static SwBoxAutoFormat* pDfltBoxAutoFormat; css::uno::WeakReference m_wXObject; OUString m_aName; sal_uInt16 m_nStrResId; // Common flags of Calc and Writer. bool m_bInclFont : 1; bool m_bInclJustify : 1; bool m_bInclFrame : 1; bool m_bInclBackground : 1; bool m_bInclValueFormat : 1; // Calc specific flags. bool m_bInclWidthHeight : 1; SwBoxAutoFormat* m_aBoxAutoFormat[ 16 ] = {}; // Writer-specific options std::shared_ptr m_aBreak; SwFormatPageDesc m_aPageDesc; std::shared_ptr m_aKeepWithNextPara; sal_uInt16 m_aRepeatHeading; bool m_bLayoutSplit; bool m_bRowSplit; bool m_bCollapsingBorders; std::shared_ptr m_aShadow; bool m_bHidden; bool m_bUserDefined; public: SwTableAutoFormat( const OUString& rName ); SwTableAutoFormat( const SwTableAutoFormat& rNew ); ~SwTableAutoFormat(); SwTableAutoFormat& operator=( const SwTableAutoFormat& rNew ); const SvxFormatBreakItem& GetBreak() const { return *m_aBreak; } const SvxFormatKeepItem& GetKeepWithNextPara() const { return *m_aKeepWithNextPara; } const SvxShadowItem& GetShadow() const { return *m_aShadow; } void SetBreak(const SvxFormatBreakItem& rNew) { m_aBreak.reset(static_cast(rNew.Clone())); } void SetKeepWithNextPara(const SvxFormatKeepItem& rNew) { m_aKeepWithNextPara.reset(static_cast(rNew.Clone())); } void SetShadow(const SvxShadowItem& rNew) { m_aShadow.reset(static_cast(rNew.Clone())); } void SetBoxFormat( const SwBoxAutoFormat& rNew, sal_uInt8 nPos ); const SwBoxAutoFormat& GetBoxFormat( sal_uInt8 nPos ) const; SwBoxAutoFormat& GetBoxFormat( sal_uInt8 nPos ); static const SwBoxAutoFormat& GetDefaultBoxFormat(); void SetName( const OUString& rNew ) { m_aName = rNew; m_nStrResId = USHRT_MAX; } const OUString& GetName() const { return m_aName; } void UpdateFromSet( sal_uInt8 nPos, const SfxItemSet& rSet, SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter const * ); void UpdateToSet( sal_uInt8 nPos, SfxItemSet& rSet, SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter* ) const ; void RestoreTableProperties(SwTable &table) const; void StoreTableProperties(const SwTable &table); bool IsFont() const { return m_bInclFont; } bool IsJustify() const { return m_bInclJustify; } bool IsFrame() const { return m_bInclFrame; } bool IsBackground() const { return m_bInclBackground; } bool IsValueFormat() const { return m_bInclValueFormat; } /// Check if style is hidden. bool IsHidden() const { return m_bHidden; } /// Check if style is defined by user. bool IsUserDefined() const { return m_bUserDefined; } void SetFont( const bool bNew ) { m_bInclFont = bNew; } void SetJustify( const bool bNew ) { m_bInclJustify = bNew; } void SetFrame( const bool bNew ) { m_bInclFrame = bNew; } void SetBackground( const bool bNew ) { m_bInclBackground = bNew; } void SetValueFormat( const bool bNew ) { m_bInclValueFormat = bNew; } void SetWidthHeight( const bool bNew ) { m_bInclWidthHeight = bNew; } /// Set if style is hidden. void SetHidden(bool bHidden) { m_bHidden = bHidden; } /// Set if style is user defined. void SetUserDefined(bool bUserDefined) { m_bUserDefined = bUserDefined; } /// These methods returns what style (row or column) is applied first on given Cell bool FirstRowEndColumnIsRow(); bool FirstRowStartColumnIsRow(); bool LastRowEndColumnIsRow(); bool LastRowStartColumnIsRow(); bool Load( SvStream& rStream, const SwAfVersions& ); bool Save( SvStream& rStream, sal_uInt16 fileVersion ) const; css::uno::WeakReference const& GetXObject() const { return m_wXObject; } void SetXObject(css::uno::Reference const& xObject) { m_wXObject = xObject; } /// Returns the cell's name postfix. eg. ".1" OUString GetTableTemplateCellSubName(const SwBoxAutoFormat& rBoxFormat) const; /// Returns a vector of indexes in aBoxAutoFormat array. Returned indexes points to cells which are mapped to a table-template. static const std::vector& GetTableTemplateMap(); /** * Calculates the relevant position in the table autoformat for a given * cell in a given table. */ static sal_uInt8 CountPos(sal_uInt32 nCol, sal_uInt32 nCols, sal_uInt32 nRow, sal_uInt32 nRows); }; class SW_DLLPUBLIC SwTableAutoFormatTable { struct Impl; std::unique_ptr m_pImpl; SAL_DLLPRIVATE bool Load( SvStream& rStream ); SAL_DLLPRIVATE bool Save( SvStream& rStream ) const; public: explicit SwTableAutoFormatTable(); ~SwTableAutoFormatTable(); size_t size() const; SwTableAutoFormat const& operator[](size_t i) const; SwTableAutoFormat & operator[](size_t i); /// Append table style to the existing styles. void AddAutoFormat(const SwTableAutoFormat& rFormat); void InsertAutoFormat(size_t i, std::unique_ptr pFormat); void EraseAutoFormat(size_t i); void EraseAutoFormat(const OUString& rName); std::unique_ptr ReleaseAutoFormat(size_t i); /// Removes an autoformat. Returns pointer to the removed autoformat or nullptr. std::unique_ptr ReleaseAutoFormat(const OUString& rName); /// Find table style with the provided name, return nullptr when not found. SwTableAutoFormat* FindAutoFormat(const OUString& rName) const; void Load(); bool Save() const; }; class SwCellStyleDescriptor { const std::pair>& m_rCellStyleDesc; public: SwCellStyleDescriptor(const std::pair>& rCellStyleDesc) : m_rCellStyleDesc(rCellStyleDesc) { } const OUString& GetName() const { return m_rCellStyleDesc.first; } }; class SwCellStyleTable { std::vector>> m_aCellStyles; public: SwCellStyleTable(); ~SwCellStyleTable(); size_t size() const; SwCellStyleDescriptor operator[](size_t i) const; void clear(); /// Add a copy of rBoxFormat void AddBoxFormat(const SwBoxAutoFormat& rBoxFormat, const OUString& sName); void RemoveBoxFormat(const OUString& sName); void ChangeBoxFormatName(const OUString& sFromName, const OUString& sToName); /// If found returns its name. If not found returns an empty OUString OUString GetBoxFormatName(const SwBoxAutoFormat& rBoxFormat) const; /// If found returns a ptr to a BoxFormat. If not found returns nullptr SwBoxAutoFormat* GetBoxFormat(const OUString& sName) const; }; #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */