/src/libreoffice/sw/inc/textboxhelper.hxx
Line | Count | Source |
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 | | |
10 | | #ifndef INCLUDED_SW_INC_TEXTBOXHELPER_HXX |
11 | | #define INCLUDED_SW_INC_TEXTBOXHELPER_HXX |
12 | | |
13 | | #include <map> |
14 | | #include <set> |
15 | | #include <vector> |
16 | | |
17 | | #include <com/sun/star/uno/Any.hxx> |
18 | | #include <com/sun/star/uno/Type.h> |
19 | | #include <com/sun/star/text/TextContentAnchorType.hpp> |
20 | | #include <svx/swframetypes.hxx> |
21 | | |
22 | | #include "swdllapi.h" |
23 | | |
24 | | class SdrPage; |
25 | | class SdrObject; |
26 | | class SfxItemSet; |
27 | | class SwFrameFormat; |
28 | | class SwFormatAnchor; |
29 | | class SwFormatContent; |
30 | | class SwDoc; |
31 | | namespace tools |
32 | | { |
33 | | class Rectangle; |
34 | | } |
35 | | class ZSortFly; |
36 | | namespace com::sun::star::drawing |
37 | | { |
38 | | class XShape; |
39 | | } |
40 | | namespace com::sun::star::text |
41 | | { |
42 | | class XTextFrame; |
43 | | } |
44 | | namespace sw |
45 | | { |
46 | | template <class T> class FrameFormats; |
47 | | class SpzFrameFormat; |
48 | | } |
49 | | |
50 | | /** |
51 | | * A TextBox is a TextFrame, that is tied to a drawinglayer shape. |
52 | | * |
53 | | * This class provides helper methods to create, query and maintain such |
54 | | * TextBoxes. |
55 | | */ |
56 | | class SW_DLLPUBLIC SwTextBoxHelper |
57 | | { |
58 | | public: |
59 | | /// Maps a draw format to a fly format. |
60 | | using SavedLink = std::map<const SwFrameFormat*, const SwFrameFormat*>; |
61 | | /// Maps a draw format to content. |
62 | | using SavedContent = std::map<const SwFrameFormat*, SwFormatContent>; |
63 | | /// Create a TextBox for a shape. If the third parameter is true, |
64 | | /// the original text in the shape will be copied to the frame |
65 | | /// The textbox is created for the shape given by the pObject parameter. |
66 | | static void create(SwFrameFormat* pShape, SdrObject* pObject, bool bCopyText = false); |
67 | | /// Sets the given textframe as textbox for the given (group member) shape. |
68 | | static void set(SwFrameFormat* pShape, SdrObject* pObject, |
69 | | const css::uno::Reference<css::text::XTextFrame>& xNew); |
70 | | /// Destroy a TextBox for a shape. If the format has more textboxes |
71 | | /// like group shapes, it will destroy only that textbox what belongs |
72 | | /// to the given pObject shape. |
73 | | static void destroy(const SwFrameFormat* pShape, const SdrObject* pObject); |
74 | | /// Get interface of a shape's TextBox, if there is any. |
75 | | static css::uno::Any queryInterface(const SwFrameFormat* pShape, const css::uno::Type& rType, |
76 | | SdrObject* pObj); |
77 | | |
78 | | /// Sync property of TextBox with the one of the shape. |
79 | | static void syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uInt8 nMemberID, |
80 | | const css::uno::Any& rValue, SdrObject* pObj = nullptr); |
81 | | /// Does the same, but works on properties which lack an sw-specific WID / MemberID. |
82 | | static void syncProperty(SwFrameFormat* pShape, std::u16string_view rPropertyName, |
83 | | const css::uno::Any& rValue, SdrObject* pObj = nullptr); |
84 | | /// Get a property of the underlying TextFrame. |
85 | | static void getProperty(SwFrameFormat const* pShape, sal_uInt16 nWID, sal_uInt8 nMemberID, |
86 | | css::uno::Any& rValue); |
87 | | /// Get a property of the underlying TextFrame. |
88 | | static css::uno::Any getProperty(SwFrameFormat const* pShape, const OUString& rPropName); |
89 | | |
90 | | /// There are two types of enum of anchor type, so this function maps this. |
91 | | static css::text::TextContentAnchorType mapAnchorType(const RndStdIds& rAnchorID); |
92 | | |
93 | | /// Similar to syncProperty(), but used by the internal API (e.g. for UI purposes). |
94 | | static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& rSet, SdrObject* pObj); |
95 | | |
96 | | /// Copy shape attributes to the text frame |
97 | | static void updateTextBoxMargin(SdrObject* pObj); |
98 | | |
99 | | /// Sets the anchor of the associated textframe of the given shape, and |
100 | | /// returns true on success. |
101 | | static bool changeAnchor(SwFrameFormat* pShape, SdrObject* pObj); |
102 | | |
103 | | /// Does the positioning for the associated textframe of the shape, and |
104 | | /// returns true on success. |
105 | | static bool doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pObj); |
106 | | |
107 | | /// Sets the correct size of textframe depending on the given SdrObject. |
108 | | static bool syncTextBoxSize(SwFrameFormat* pShape, SdrObject* pObj); |
109 | | |
110 | | // Returns true on success. Synchronize z-order of the text frame of the given textbox |
111 | | // by setting it one level higher than the z-order of the shape of the textbox. |
112 | | static bool DoTextBoxZOrderCorrection(SwFrameFormat* pShape, const SdrObject* pObj); |
113 | | |
114 | | /** |
115 | | * If we have an associated TextFrame, then return that. |
116 | | * |
117 | | * If we have more textboxes for this format (group shape), that one will be |
118 | | * returned, what belongs to the pObject. |
119 | | * |
120 | | * @param nType Expected frame format type. |
121 | | * Valid types are RES_DRAWFRMFMT and RES_FLYFRMFMT. |
122 | | * |
123 | | * @see isTextBox |
124 | | */ |
125 | | SAL_RET_MAYBENULL static SwFrameFormat* |
126 | | getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType, |
127 | | const SdrObject* pObject = nullptr); |
128 | | /// If we have an associated TextFrame, then return that. |
129 | | SAL_RET_MAYBENULL static SwFrameFormat* |
130 | | getOtherTextBoxFormat(css::uno::Reference<css::drawing::XShape> const& xShape); |
131 | | /// If we have an associated TextFrame, then return its XTextFrame. |
132 | | static css::uno::Reference<css::text::XTextFrame> |
133 | | getUnoTextFrame(css::uno::Reference<css::drawing::XShape> const& xShape); |
134 | | /// Return the textbox rectangle of a draw shape (in relative twips). |
135 | | static tools::Rectangle getRelativeTextRectangle(SdrObject* pShape); |
136 | | |
137 | | /** |
138 | | * Is the frame format a text box? |
139 | | * |
140 | | * A text box consists of a coupled fly and draw format. Most times you |
141 | | * just want to check for a single type, otherwise you get duplicate results. |
142 | | * |
143 | | * @param pFormat: Is this format have a textbox? |
144 | | * |
145 | | * @param nType: Expected frame format input type. |
146 | | * Valid types are RES_DRAWFRMFMT and RES_FLYFRMFMT. |
147 | | * |
148 | | * @param pObject: If the pFormat has more textboxes than one, like |
149 | | * groupshapes, the textbox what belongs to the given |
150 | | * pObject will be inspected. If this parameter nullptr, |
151 | | * the textbox what belongs to the pObject will only be inspected. |
152 | | */ |
153 | | static bool isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType, |
154 | | const SdrObject* pObject = nullptr); |
155 | | |
156 | | /// Returns true if the SdrObject has a SwTextFrame otherwise false |
157 | | static bool hasTextFrame(const SdrObject* pObj); |
158 | | |
159 | | /// Count number of shapes in the document, excluding TextBoxes. |
160 | | static sal_Int32 getCount(const SwDoc& rDoc); |
161 | | /// Count number of shapes on the page, excluding TextBoxes. |
162 | | static sal_Int32 getCount(SdrPage const* pPage); |
163 | | /// Get a shape by index, excluding TextBoxes. |
164 | | /// |
165 | | /// @throws css::lang::IndexOutOfBoundsException |
166 | | static css::uno::Any getByIndex(SdrPage const* pPage, sal_Int32 nIndex); |
167 | | /// Get the order of the shape, excluding TextBoxes. |
168 | | static sal_Int32 getOrdNum(const SdrObject* pObject); |
169 | | /// If pTextBox is a textbox, then set rWrapThrough to the surround of its shape. |
170 | | static void getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough); |
171 | | |
172 | | /// Saves the current shape -> textbox links in a map, so they can be restored later. |
173 | | static void saveLinks(const sw::FrameFormats<sw::SpzFrameFormat*>& rFormats, |
174 | | std::map<const SwFrameFormat*, const SwFrameFormat*>& rLinks); |
175 | | /// Undo the effect of saveLinks() + individual resetLink() calls. |
176 | | static void restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrameFormat*>& rNew, |
177 | | SavedLink& rSavedLinks); |
178 | | |
179 | | /// Calls the method given by pFunc with every textboxes of the group given by pFormat. |
180 | | static void synchronizeGroupTextBoxProperty(bool pFunc(SwFrameFormat*, SdrObject*), |
181 | | SwFrameFormat* pFormat, SdrObject* pObj); |
182 | | |
183 | | /// Collect all textboxes of the group given by the pGroupObj Parameter. Returns with a |
184 | | /// vector filled with the textboxes. |
185 | | static std::vector<SwFrameFormat*> CollectTextBoxes(const SdrObject* pGroupObject, |
186 | | SwFrameFormat* pFormat); |
187 | | |
188 | | // Compares the anchor of the first and second given formats, and decides whether sync needed. |
189 | | static bool isAnchorSyncNeeded(const SwFrameFormat* pFirst, const SwFrameFormat* pSecond); |
190 | | |
191 | | /// Was the textbox created from a Microsoft import by a paragraph frame property (framePr) |
192 | | static bool TextBoxIsFramePr(const SwFrameFormat& rFrameFormat); |
193 | | }; |
194 | | |
195 | | /// Textboxes are basically textframe + shape pairs. This means one shape has one frame. |
196 | | /// This is not enough for group shapes, because they have only one shape format and |
197 | | /// can have many frame formats. This class provides if there is a group shape for example, |
198 | | /// it can have multiple textboxes. |
199 | | class SwTextBoxNode |
200 | | { |
201 | | friend class SwTextBoxLockGuard; |
202 | | |
203 | | // One TextBox-entry |
204 | | struct SwTextBoxElement |
205 | | { |
206 | | // The textframe format |
207 | | SwFrameFormat* m_pTextBoxFormat; |
208 | | // The Draw object where the textbox belongs to |
209 | | SdrObject* m_pDrawObject; |
210 | | }; |
211 | | |
212 | | // This vector stores the textboxes what belongs to this node |
213 | | std::vector<SwTextBoxElement> m_pTextBoxes; |
214 | | // This is the pointer to the shape format, which has this node |
215 | | // (and the textboxes) |
216 | | SwFrameFormat* m_pOwnerShapeFormat; |
217 | | |
218 | | // Prevents oscillating during recursive clone calling. |
219 | | mutable bool m_bIsCloningInProgress; |
220 | | |
221 | | // Protection against looping |
222 | | bool m_bLock; |
223 | | |
224 | | public: |
225 | | // Not needed. |
226 | | SwTextBoxNode() = delete; |
227 | | |
228 | | // ctor |
229 | | SwTextBoxNode(SwFrameFormat* pOwnerShapeFormat); |
230 | | // dtor |
231 | | ~SwTextBoxNode(); |
232 | | |
233 | | // default copy ctor is enough |
234 | 342 | SwTextBoxNode(const SwTextBoxNode&) = default; |
235 | | |
236 | | // This method adds a textbox entry to the shape |
237 | | // Parameters: |
238 | | // pDrawObject: The shape what the textbox be added to. |
239 | | // pNewTextBox: The newly created textbox format what will be added to the shape. |
240 | | void AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBox); |
241 | | |
242 | | // This will remove the textbox entry. |
243 | | // Parameters: |
244 | | // pDrawObject: The shape which have the textbox to be deleted. |
245 | | void DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc = false); |
246 | | |
247 | | // This will remove the textbox entry. |
248 | | // Parameters: |
249 | | // pTextBox: The textbox what have to be deleted. |
250 | | void DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc = false); |
251 | | |
252 | | // This will return with the frame format of the textbox what belongs |
253 | | // to the given shape (pDrawObject) |
254 | | SwFrameFormat* GetTextBox(const SdrObject* pDrawObject) const; |
255 | | |
256 | | // Clears all textboxes of this node from the doc and also from here. |
257 | | void ClearAll(); |
258 | | |
259 | | // This returns with the shape what this class belongs to. |
260 | 9.31k | SwFrameFormat* GetOwnerShape() { return m_pOwnerShapeFormat; }; |
261 | | |
262 | | // This will give the current number of textboxes. |
263 | 86.1k | size_t GetTextBoxCount() const { return m_pTextBoxes.size(); }; |
264 | | |
265 | | // Returns with a const collection of textboxes owned by this node. |
266 | | std::map<SdrObject*, SwFrameFormat*> GetAllTextBoxes() const; |
267 | | |
268 | | // Does the copy, and assign of all textboxes of this node to the given format. |
269 | | // Important: The given format has to be a shape-format, and must have same structure |
270 | | // as the owner shape has. If the structure different, the cloning will be aborted. |
271 | | void Clone(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, bool bSetAttr, |
272 | | bool bMakeFrame) const; |
273 | | |
274 | | private: |
275 | | void Clone_Impl(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, |
276 | | const SdrObject* pSrcObj, SdrObject* pDestObj, bool bSetAttr, |
277 | | bool bMakeFrame) const; |
278 | | }; |
279 | | |
280 | | // Helper class for preventing unwanted sync calls. |
281 | | class SwTextBoxLockGuard |
282 | | { |
283 | | SwTextBoxNode& m_rTextBoxes; |
284 | | |
285 | | public: |
286 | | SwTextBoxLockGuard(SwTextBoxNode& rTextBoxes) |
287 | 21.4k | : m_rTextBoxes(rTextBoxes) |
288 | 21.4k | { |
289 | 21.4k | m_rTextBoxes.m_bLock = true; |
290 | 21.4k | } |
291 | | |
292 | 21.4k | ~SwTextBoxLockGuard() { m_rTextBoxes.m_bLock = false; } |
293 | | }; |
294 | | |
295 | | #endif // INCLUDED_SW_INC_TEXTBOXHELPER_HXX |
296 | | |
297 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |