1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #ifndef INCLUDED_SW_INC_TBLAFMT_HXX
20 #define INCLUDED_SW_INC_TBLAFMT_HXX
21 /*
22  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23  *
24  *     The structure of table auto formatting should not be changed. It is used
25  *     by different code of Writer and Calc. If a change is necessary, the
26  *     source code of both applications must be changed!
27  *
28  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
29  */
30 
31 #include <memory>
32 
33 #include <editeng/formatbreakitem.hxx>
34 #include <editeng/keepitem.hxx>
35 #include <editeng/frmdiritem.hxx>
36 #include <editeng/shaditem.hxx>
37 #include <svx/autoformathelper.hxx>
38 #include "fmtpdsc.hxx"
39 #include "fmtornt.hxx"
40 #include "swdllapi.h"
41 
42 struct SwAfVersions;
43 
44 class SvNumberFormatter;
45 class SwTable;
46 
47 class SwBoxAutoFormat : public AutoFormatBase
48 {
49 private:
50     // Writer specific
51     std::unique_ptr<SvxFrameDirectionItem>  m_aTextOrientation;
52     std::unique_ptr<SwFormatVertOrient>     m_aVerticalAlignment;
53 
54     // number format
55     OUString                                m_sNumFormatString;
56     LanguageType                            m_eSysLanguage;
57     LanguageType                            m_eNumFormatLanguage;
58 
59     css::uno::WeakReference<css::uno::XInterface> m_wXObject;
60 
61 public:
62     SwBoxAutoFormat();
63     SwBoxAutoFormat( const SwBoxAutoFormat& rNew );
64     ~SwBoxAutoFormat();
65 
66     /// assignment-op (still used)
67     SwBoxAutoFormat& operator=(const SwBoxAutoFormat& rRef);
68 
69     /// Comparing based of boxes backgrounds.
70     bool operator==(const SwBoxAutoFormat& rRight);
71 
72     // The get-methods.
GetTextOrientation() const73     const SvxFrameDirectionItem& GetTextOrientation() const { return *m_aTextOrientation; }
GetVerticalAlignment() const74     const SwFormatVertOrient& GetVerticalAlignment() const { return *m_aVerticalAlignment; }
75 
GetValueFormat(OUString & rFormat,LanguageType & rLng,LanguageType & rSys) const76     void GetValueFormat( OUString& rFormat, LanguageType& rLng, LanguageType& rSys ) const
77         { rFormat = m_sNumFormatString; rLng = m_eNumFormatLanguage; rSys = m_eSysLanguage; }
78 
GetNumFormatString() const79     const OUString& GetNumFormatString() const { return m_sNumFormatString; }
GetSysLanguage() const80     const LanguageType& GetSysLanguage() const { return m_eSysLanguage; }
GetNumFormatLanguage() const81     const LanguageType& GetNumFormatLanguage() const { return m_eNumFormatLanguage; }
82 
83     // The set-methods.
SetTextOrientation(const SvxFrameDirectionItem & rNew)84     void SetTextOrientation( const SvxFrameDirectionItem& rNew ) { m_aTextOrientation.reset(static_cast<SvxFrameDirectionItem*>(rNew.Clone())); }
SetVerticalAlignment(const SwFormatVertOrient & rNew)85     void SetVerticalAlignment( const SwFormatVertOrient& rNew ) { m_aVerticalAlignment.reset(static_cast<SwFormatVertOrient*>(rNew.Clone())); }
86 
SetValueFormat(const OUString & rFormat,LanguageType eLng,LanguageType eSys)87     void SetValueFormat( const OUString& rFormat, LanguageType eLng, LanguageType eSys )
88         { m_sNumFormatString = rFormat; m_eNumFormatLanguage = eLng; m_eSysLanguage = eSys; }
89 
SetNumFormatString(const OUString & rNew)90     void SetNumFormatString(const OUString& rNew) { m_sNumFormatString = rNew; }
SetSysLanguage(const LanguageType & rNew)91     void SetSysLanguage(const LanguageType& rNew) { m_eSysLanguage = rNew; }
SetNumFormatLanguage(const LanguageType & rNew)92     void SetNumFormatLanguage(const LanguageType& rNew) { m_eNumFormatLanguage = rNew; }
93 
GetXObject() const94     css::uno::WeakReference<css::uno::XInterface> const& GetXObject() const
95         { return m_wXObject; }
SetXObject(css::uno::Reference<css::uno::XInterface> const & xObject)96     void SetXObject(css::uno::Reference<css::uno::XInterface> const& xObject)
97         { m_wXObject = xObject; }
98 
99     bool Load( SvStream& rStream, const SwAfVersions& rVersions, sal_uInt16 nVer );
100     bool Save( SvStream& rStream, sal_uInt16 fileVersion ) const;
101 };
102 
103 enum class SwTableAutoFormatUpdateFlags { Char = 1, Box = 2 };
104 namespace o3tl {
105     template<> struct typed_flags<SwTableAutoFormatUpdateFlags> : is_typed_flags<SwTableAutoFormatUpdateFlags, 0x03> {};
106 };
107 
108 /*
109 @remarks
110 A table has a number of lines. These lines seem to correspond with rows, except in the case of
111 rows spanning more than one line. Each line contains a number of boxes/cells.
112 
113 AutoFormat properties are retrieved and stored in a grid of 16 table boxes. A sampling approach
114 is used to read the data. 4 lines are picked, and 4 boxes are picked from each.
115 
116 The line picking and box picking algorithms are similar. We start at the first line/box, and pick
117 lines/boxes one by one for a maximum of 3. The 4th line/box is the last line/box in the current
118 table/line. If we hit the end of lines/boxes, the last line/box encountered is picked several times.
119 
120 For example, in a 2x3 table, the 4 lines will be [0, 1, 1, 1]. In each line, the boxes will be
121 [0, 1, 2, 2]. In a 6x5 table, the 4 lines will be [0, 1, 2, 4] and the boxes per line will be
122 [0, 1, 2, 5].
123 
124 As you can see, property extraction/application is lossless for tables that are 4x4 or smaller
125 (and in fact has a bit of redundancy). For larger tables, we lose any individual cell formatting
126 for the range [(3,rows - 1) -> (3, cols - 1)]. That formatting is replaced by formatting from
127 the saved cells:
128 
129             0            1            2           3           4           5
130         +-----------------------------------------------------------------------+
131      0  |   Saved   |  Saved    |  Saved    |           |           |  Saved    |
132         +-----------------------------------------------------------------------+
133      1  |   Saved   |  Saved    |  Saved    |           |           |  Saved    |
134         +-----------------------------------------------------------------------+
135      2  |   Saved   |  Saved    |  Saved    |           |           |  Saved    |
136         +-----------------------------------------------------------------------+
137      3  |           |           |           |           |           |           |
138         +-----------------------------------------------------------------------+
139      4  |           |           |           |           |           |           |
140         +-----------------------------------------------------------------------+
141      5  |   Saved   |  Saved    |  Saved    |           |           |  Saved    |
142         +-----------+-----------+-----------+-----------+-----------+-----------+
143 
144 The properties saved are divided into three categories:
145     1. Character properties: Font, font size, weight, etc.
146     2. Box properties: Box, cell background
147     3. Table properties: Properties that are set in the Table->Table Properties dialog.
148 
149 Character and box properties are stored per cell (and are lossy for tables larger than 4x4). Table
150 properties are stored per-table, and are lossless.
151 */
152 class SW_DLLPUBLIC SwTableAutoFormat
153 {
154     friend class SwDocTest;
155     friend void FinitCore();       // To destroy default pointer.
156     static SwBoxAutoFormat* pDfltBoxAutoFormat;
157 
158     css::uno::WeakReference<css::uno::XInterface> m_wXObject;
159 
160     OUString m_aName;
161     sal_uInt16 m_nStrResId;
162 
163     // Common flags of Calc and Writer.
164     bool m_bInclFont : 1;
165     bool m_bInclJustify : 1;
166     bool m_bInclFrame : 1;
167     bool m_bInclBackground : 1;
168     bool m_bInclValueFormat : 1;
169 
170     // Calc specific flags.
171     bool m_bInclWidthHeight : 1;
172 
173     SwBoxAutoFormat* m_aBoxAutoFormat[ 16 ] = {};
174 
175     // Writer-specific options
176     std::shared_ptr<SvxFormatBreakItem> m_aBreak;
177     SwFormatPageDesc m_aPageDesc;
178     std::shared_ptr<SvxFormatKeepItem> m_aKeepWithNextPara;
179     sal_uInt16 m_aRepeatHeading;
180     bool m_bLayoutSplit;
181     bool m_bRowSplit;
182     bool m_bCollapsingBorders;
183     std::shared_ptr<SvxShadowItem> m_aShadow;
184 
185     bool m_bHidden;
186     bool m_bUserDefined;
187 public:
188     SwTableAutoFormat( const OUString& rName );
189     SwTableAutoFormat( const SwTableAutoFormat& rNew );
190     ~SwTableAutoFormat();
191 
192     SwTableAutoFormat& operator=( const SwTableAutoFormat& rNew );
193 
GetBreak() const194     const SvxFormatBreakItem& GetBreak() const { return *m_aBreak; }
GetKeepWithNextPara() const195     const SvxFormatKeepItem& GetKeepWithNextPara() const { return *m_aKeepWithNextPara; }
GetShadow() const196     const SvxShadowItem& GetShadow() const { return *m_aShadow; }
197 
SetBreak(const SvxFormatBreakItem & rNew)198     void SetBreak(const SvxFormatBreakItem& rNew) { m_aBreak.reset(static_cast<SvxFormatBreakItem*>(rNew.Clone())); }
SetKeepWithNextPara(const SvxFormatKeepItem & rNew)199     void SetKeepWithNextPara(const SvxFormatKeepItem& rNew) { m_aKeepWithNextPara.reset(static_cast<SvxFormatKeepItem*>(rNew.Clone())); }
SetShadow(const SvxShadowItem & rNew)200     void SetShadow(const SvxShadowItem& rNew) { m_aShadow.reset(static_cast<SvxShadowItem*>(rNew.Clone())); }
201 
202     void SetBoxFormat( const SwBoxAutoFormat& rNew, sal_uInt8 nPos );
203     const SwBoxAutoFormat& GetBoxFormat( sal_uInt8 nPos ) const;
204     SwBoxAutoFormat& GetBoxFormat( sal_uInt8 nPos );
205     static const SwBoxAutoFormat& GetDefaultBoxFormat();
206 
SetName(const OUString & rNew)207     void SetName( const OUString& rNew ) { m_aName = rNew; m_nStrResId = USHRT_MAX; }
GetName() const208     const OUString& GetName() const { return m_aName; }
209 
210     void UpdateFromSet( sal_uInt8 nPos, const SfxItemSet& rSet,
211                                 SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter const * );
212     void UpdateToSet( const sal_uInt8 nPos, const bool bSingleRowTable, const bool bSingleColTable,
213                         SfxItemSet& rSet, SwTableAutoFormatUpdateFlags eFlags,
214                         SvNumberFormatter* ) const ;
215 
216     void RestoreTableProperties(SwTable &table) const;
217     void StoreTableProperties(const SwTable &table);
218 
IsFont() const219     bool IsFont() const         { return m_bInclFont; }
IsJustify() const220     bool IsJustify() const      { return m_bInclJustify; }
IsFrame() const221     bool IsFrame() const        { return m_bInclFrame; }
IsBackground() const222     bool IsBackground() const   { return m_bInclBackground; }
IsValueFormat() const223     bool IsValueFormat() const  { return m_bInclValueFormat; }
224 
225     /// Check if style is hidden.
IsHidden() const226     bool IsHidden() const       { return m_bHidden; }
227     /// Check if style is defined by user.
IsUserDefined() const228     bool IsUserDefined() const  { return m_bUserDefined; }
229 
SetFont(const bool bNew)230     void SetFont( const bool bNew )         { m_bInclFont = bNew; }
SetJustify(const bool bNew)231     void SetJustify( const  bool bNew )     { m_bInclJustify = bNew; }
SetFrame(const bool bNew)232     void SetFrame( const bool bNew )        { m_bInclFrame = bNew; }
SetBackground(const bool bNew)233     void SetBackground( const bool bNew )   { m_bInclBackground = bNew; }
SetValueFormat(const bool bNew)234     void SetValueFormat( const bool bNew )  { m_bInclValueFormat = bNew; }
SetWidthHeight(const bool bNew)235     void SetWidthHeight( const bool bNew )  { m_bInclWidthHeight = bNew; }
236 
237     /// Set if style is hidden.
SetHidden(bool bHidden)238     void SetHidden(bool bHidden)            { m_bHidden = bHidden; }
239     /// Set if style is user defined.
SetUserDefined(bool bUserDefined)240     void SetUserDefined(bool bUserDefined)  { m_bUserDefined = bUserDefined; }
241 
242     /// These methods returns what style (row or column) is applied first on given Cell
243     bool FirstRowEndColumnIsRow();
244     bool FirstRowStartColumnIsRow();
245     bool LastRowEndColumnIsRow();
246     bool LastRowStartColumnIsRow();
247 
248     bool Load( SvStream& rStream, const SwAfVersions& );
249     bool Save( SvStream& rStream, sal_uInt16 fileVersion ) const;
250 
GetXObject() const251     css::uno::WeakReference<css::uno::XInterface> const& GetXObject() const
252         { return m_wXObject; }
SetXObject(css::uno::Reference<css::uno::XInterface> const & xObject)253     void SetXObject(css::uno::Reference<css::uno::XInterface> const& xObject)
254         { m_wXObject = xObject; }
255 
256     /// Returns the cell's name postfix. eg. ".1"
257     OUString GetTableTemplateCellSubName(const SwBoxAutoFormat& rBoxFormat) const;
258     /// Returns a vector of indexes in aBoxAutoFormat array. Returned indexes points to cells which are mapped to a table-template.
259     static const std::vector<sal_Int32>& GetTableTemplateMap();
260 
261     /**
262      * Calculates the relevant position in the table autoformat for a given
263      * cell in a given table.
264      */
265     static sal_uInt8 CountPos(sal_uInt32 nCol, sal_uInt32 nCols, sal_uInt32 nRow, sal_uInt32 nRows);
266 };
267 
268 class SW_DLLPUBLIC SwTableAutoFormatTable
269 {
270     struct Impl;
271     std::unique_ptr<Impl> m_pImpl;
272 
273     SAL_DLLPRIVATE bool Load( SvStream& rStream );
274     SAL_DLLPRIVATE bool Save( SvStream& rStream ) const;
275 
276 public:
277     explicit SwTableAutoFormatTable();
278     ~SwTableAutoFormatTable();
279 
280     size_t size() const;
281     SwTableAutoFormat const& operator[](size_t i) const;
282     SwTableAutoFormat      & operator[](size_t i);
283 
284     /// Append table style to the existing styles.
285     void AddAutoFormat(const SwTableAutoFormat& rFormat);
286 
287     void InsertAutoFormat(size_t i, std::unique_ptr<SwTableAutoFormat> pFormat);
288     void EraseAutoFormat(size_t i);
289     void EraseAutoFormat(const OUString& rName);
290     std::unique_ptr<SwTableAutoFormat> ReleaseAutoFormat(size_t i);
291     /// Removes an autoformat. Returns pointer to the removed autoformat or nullptr.
292     std::unique_ptr<SwTableAutoFormat> ReleaseAutoFormat(const OUString& rName);
293 
294     /// Find table style with the provided name, return nullptr when not found.
295     SwTableAutoFormat* FindAutoFormat(const OUString& rName) const;
296 
297     void Load();
298     bool Save() const;
299 };
300 
301 class SwCellStyleDescriptor
302 {
303     const std::pair<OUString, std::unique_ptr<SwBoxAutoFormat>>& m_rCellStyleDesc;
304 public:
SwCellStyleDescriptor(const std::pair<OUString,std::unique_ptr<SwBoxAutoFormat>> & rCellStyleDesc)305     SwCellStyleDescriptor(const std::pair<OUString, std::unique_ptr<SwBoxAutoFormat>>& rCellStyleDesc) : m_rCellStyleDesc(rCellStyleDesc) { }
306 
GetName() const307     const OUString&  GetName() const   { return m_rCellStyleDesc.first; }
308 };
309 
310 class SwCellStyleTable
311 {
312     std::vector<std::pair<OUString, std::unique_ptr<SwBoxAutoFormat>>> m_aCellStyles;
313 public:
314     SwCellStyleTable();
315     ~SwCellStyleTable();
316 
317     size_t size() const;
318     SwCellStyleDescriptor operator[](size_t i) const;
319     void clear();
320 
321     /// Add a copy of rBoxFormat
322     void AddBoxFormat(const SwBoxAutoFormat& rBoxFormat, const OUString& sName);
323     void RemoveBoxFormat(const OUString& sName);
324     void ChangeBoxFormatName(const OUString& sFromName, const OUString& sToName);
325     /// If found returns its name. If not found returns an empty OUString
326     OUString GetBoxFormatName(const SwBoxAutoFormat& rBoxFormat) const;
327     /// If found returns a ptr to a BoxFormat. If not found returns nullptr
328     SwBoxAutoFormat* GetBoxFormat(const OUString& sName) const;
329 };
330 
331 #endif
332 
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
334