Line data Source code
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 : #include <textboxhelper.hxx>
11 : #include <fmtcntnt.hxx>
12 : #include <fmtanchr.hxx>
13 : #include <fmtcnct.hxx>
14 : #include <fmtornt.hxx>
15 : #include <fmtfsize.hxx>
16 : #include <doc.hxx>
17 : #include <IDocumentLayoutAccess.hxx>
18 : #include <ndtxt.hxx>
19 : #include <docsh.hxx>
20 : #include <unocoll.hxx>
21 : #include <unoframe.hxx>
22 : #include <unodraw.hxx>
23 : #include <unotextrange.hxx>
24 : #include <cmdid.h>
25 : #include <unoprnms.hxx>
26 : #include <dflyobj.hxx>
27 : #include <mvsave.hxx>
28 : #include <sortedobjs.hxx>
29 : #include <cntfrm.hxx>
30 :
31 : #include <editeng/unoprnms.hxx>
32 : #include <editeng/charrotateitem.hxx>
33 : #include <svx/svdoashp.hxx>
34 : #include <svx/svdpage.hxx>
35 : #include <svl/itemiter.hxx>
36 : #include <comphelper/sequenceashashmap.hxx>
37 :
38 : #include <com/sun/star/document/XActionLockable.hpp>
39 : #include <com/sun/star/text/SizeType.hpp>
40 : #include <com/sun/star/text/TextContentAnchorType.hpp>
41 : #include <com/sun/star/text/WrapTextMode.hpp>
42 : #include <com/sun/star/text/XTextDocument.hpp>
43 :
44 : using namespace com::sun::star;
45 :
46 452 : void SwTextBoxHelper::create(SwFrameFormat* pShape)
47 : {
48 : // If TextBox wasn't enabled previously
49 452 : if (!pShape->GetAttrSet().HasItem(RES_CNTNT))
50 : {
51 : // Create the associated TextFrame and insert it into the document.
52 452 : uno::Reference<text::XTextContent> xTextFrame(SwXServiceProvider::MakeInstance(SW_SERVICE_TYPE_TEXTFRAME, *pShape->GetDoc()), uno::UNO_QUERY);
53 904 : uno::Reference<text::XTextDocument> xTextDocument(pShape->GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
54 904 : uno::Reference<text::XTextContentAppend> xTextContentAppend(xTextDocument->getText(), uno::UNO_QUERY);
55 452 : xTextContentAppend->appendTextContent(xTextFrame, uno::Sequence<beans::PropertyValue>());
56 :
57 : // Initialize properties.
58 904 : uno::Reference<beans::XPropertySet> xPropertySet(xTextFrame, uno::UNO_QUERY);
59 904 : uno::Any aEmptyBorder = uno::makeAny(table::BorderLine2());
60 452 : xPropertySet->setPropertyValue(UNO_NAME_TOP_BORDER, aEmptyBorder);
61 452 : xPropertySet->setPropertyValue(UNO_NAME_BOTTOM_BORDER, aEmptyBorder);
62 452 : xPropertySet->setPropertyValue(UNO_NAME_LEFT_BORDER, aEmptyBorder);
63 452 : xPropertySet->setPropertyValue(UNO_NAME_RIGHT_BORDER, aEmptyBorder);
64 :
65 452 : xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(sal_Int32(100)));
66 :
67 452 : xPropertySet->setPropertyValue(UNO_NAME_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
68 :
69 904 : uno::Reference<container::XNamed> xNamed(xTextFrame, uno::UNO_QUERY);
70 452 : xNamed->setName(pShape->GetDoc()->GetUniqueFrameName());
71 :
72 : // Link its text range to the original shape.
73 904 : uno::Reference<text::XTextRange> xTextBox(xTextFrame, uno::UNO_QUERY_THROW);
74 904 : SwUnoInternalPaM aInternalPaM(*pShape->GetDoc());
75 452 : if (sw::XTextRangeToSwPaM(aInternalPaM, xTextBox))
76 : {
77 452 : SwAttrSet aSet(pShape->GetAttrSet());
78 904 : SwFormatContent aContent(aInternalPaM.GetNode().StartOfSectionNode());
79 452 : aSet.Put(aContent);
80 904 : pShape->SetFormatAttr(aSet);
81 : }
82 :
83 : // Also initialize the properties, which are not constant, but inherited from the shape's ones.
84 904 : uno::Reference<drawing::XShape> xShape(pShape->FindRealSdrObject()->getUnoShape(), uno::UNO_QUERY);
85 452 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::makeAny(xShape->getSize()));
86 :
87 904 : uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY);
88 452 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT));
89 452 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_RELATION, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION));
90 452 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_ORIENT, xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT));
91 452 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_RELATION, xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION));
92 452 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_POSITION, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION));
93 452 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION));
94 452 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT));
95 904 : syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST));
96 : }
97 452 : }
98 :
99 250 : void SwTextBoxHelper::destroy(SwFrameFormat* pShape)
100 : {
101 : // If a TextBox was enabled previously
102 250 : if (pShape->GetAttrSet().HasItem(RES_CNTNT))
103 : {
104 0 : SwFrameFormat* pFormat = findTextBox(pShape);
105 :
106 : // Unlink the TextBox's text range from the original shape.
107 0 : pShape->ResetFormatAttr(RES_CNTNT);
108 :
109 : // Delete the associated TextFrame.
110 0 : if (pFormat)
111 0 : pShape->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(pFormat);
112 : }
113 250 : }
114 :
115 4948 : std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc)
116 : {
117 4948 : std::set<const SwFrameFormat*> aTextBoxes;
118 9896 : std::map<SwNodeIndex, const SwFrameFormat*> aFlyFormats, aDrawFormats;
119 :
120 4948 : const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
121 71449 : for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
122 : {
123 66501 : const SwFrameFormat* pFormat = *it;
124 :
125 : // A TextBox in the context of this class is a fly frame that has a
126 : // matching (same RES_CNTNT) draw frame.
127 66501 : if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || !pFormat->GetContent().GetContentIdx())
128 21232 : continue;
129 :
130 45269 : const SwNodeIndex& rIndex = *pFormat->GetContent().GetContentIdx();
131 :
132 45269 : if (pFormat->Which() == RES_FLYFRMFMT)
133 : {
134 27512 : if (aDrawFormats.find(rIndex) != aDrawFormats.end())
135 17757 : aTextBoxes.insert(pFormat);
136 : else
137 9755 : aFlyFormats[rIndex] = pFormat;
138 : }
139 17757 : else if (pFormat->Which() == RES_DRAWFRMFMT)
140 : {
141 17757 : if (aFlyFormats.find(rIndex) != aFlyFormats.end())
142 0 : aTextBoxes.insert(aFlyFormats[rIndex]);
143 : else
144 17757 : aDrawFormats[rIndex] = pFormat;
145 : }
146 : }
147 :
148 9896 : return aTextBoxes;
149 : }
150 :
151 1949 : std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNode)
152 : {
153 1949 : const SwDoc* pDoc = rNode.GetDoc();
154 1949 : const SwContentNode* pContentNode = 0;
155 1949 : const SwContentFrm* pContentFrm = 0;
156 1949 : bool bHaveViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
157 1949 : if (bHaveViewShell && (pContentNode = rNode.GetContentNode()) && (pContentFrm = pContentNode->getLayoutFrm(pDoc->getIDocumentLayoutAccess().GetCurrentLayout())))
158 : {
159 : // We can use the layout information to iterate over only the frames which are anchored to us.
160 1932 : std::set<const SwFrameFormat*> aRet;
161 1932 : const SwSortedObjs* pSortedObjs = pContentFrm->GetDrawObjs();
162 1932 : if (pSortedObjs)
163 : {
164 653 : for (size_t i = 0; i < pSortedObjs->size(); ++i)
165 : {
166 475 : SwAnchoredObject* pAnchoredObject = (*pSortedObjs)[i];
167 475 : SwFrameFormat* pTextBox = findTextBox(&pAnchoredObject->GetFrameFormat());
168 475 : if (pTextBox)
169 6 : aRet.insert(pTextBox);
170 : }
171 : }
172 1932 : return aRet;
173 : }
174 : else
175 : // If necessary, here we could manually limit the returned set to the
176 : // ones which are anchored to rNode, but currently no need to do so.
177 17 : return findTextBoxes(pDoc);
178 : }
179 :
180 1913 : std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc* pDoc)
181 : {
182 1913 : std::map<SwFrameFormat*, SwFrameFormat*> aRet;
183 :
184 1913 : const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
185 16112 : for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
186 : {
187 14199 : SwFrameFormat* pTextBox = findTextBox(*it);
188 14199 : if (pTextBox)
189 2408 : aRet[pTextBox] = *it;
190 : }
191 :
192 1913 : return aRet;
193 : }
194 :
195 : /// If the passed SdrObject is in fact a TextFrame, that is used as a TextBox.
196 8002 : bool lcl_isTextBox(SdrObject* pSdrObject, std::set<const SwFrameFormat*>& rTextBoxes)
197 : {
198 8002 : SwVirtFlyDrawObj* pObject = PTR_CAST(SwVirtFlyDrawObj, pSdrObject);
199 8002 : return pObject && rTextBoxes.find(pObject->GetFormat()) != rTextBoxes.end();
200 : }
201 :
202 2730 : bool SwTextBoxHelper::isTextBox(const SdrObject* pObject)
203 : {
204 2730 : const SwVirtFlyDrawObj* pVirtFlyDrawObj = PTR_CAST(SwVirtFlyDrawObj, pObject);
205 2730 : if (!pVirtFlyDrawObj)
206 1543 : return false;
207 1187 : std::set<const SwFrameFormat*> aTextBoxes = findTextBoxes(pVirtFlyDrawObj->GetFormat()->GetDoc());
208 1187 : return aTextBoxes.find(pVirtFlyDrawObj->GetFormat()) != aTextBoxes.end();
209 : }
210 :
211 69 : sal_Int32 SwTextBoxHelper::getCount(SdrPage* pPage, std::set<const SwFrameFormat*>& rTextBoxes)
212 : {
213 69 : sal_Int32 nRet = 0;
214 419 : for (size_t i = 0; i < pPage->GetObjCount(); ++i)
215 : {
216 350 : if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
217 137 : continue;
218 213 : ++nRet;
219 : }
220 69 : return nRet;
221 : }
222 :
223 138 : uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(lang::IndexOutOfBoundsException)
224 : {
225 138 : if (nIndex < 0)
226 0 : throw lang::IndexOutOfBoundsException();
227 :
228 138 : SdrObject* pRet = 0;
229 138 : sal_Int32 nCount = 0; // Current logical index.
230 377 : for (size_t i = 0; i < pPage->GetObjCount(); ++i)
231 : {
232 377 : if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
233 34 : continue;
234 343 : if (nCount == nIndex)
235 : {
236 138 : pRet = pPage->GetObj(i);
237 138 : break;
238 : }
239 205 : ++nCount;
240 : }
241 :
242 138 : if (!pRet)
243 0 : throw lang::IndexOutOfBoundsException();
244 :
245 138 : return uno::makeAny(uno::Reference<drawing::XShape>(pRet->getUnoShape(), uno::UNO_QUERY));
246 : }
247 :
248 625 : sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes)
249 : {
250 625 : if (const SdrPage* pPage = pObject->GetPage())
251 : {
252 625 : sal_Int32 nOrder = 0; // Current logical order.
253 7275 : for (size_t i = 0; i < pPage->GetObjCount(); ++i)
254 : {
255 7275 : if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
256 3 : continue;
257 7272 : if (pPage->GetObj(i) == pObject)
258 625 : return nOrder;
259 6647 : ++nOrder;
260 : }
261 : }
262 :
263 : SAL_WARN("sw.core", "SwTextBoxHelper::getOrdNum: no page or page doesn't contain the object");
264 0 : return pObject->GetOrdNum();
265 : }
266 :
267 189 : SwFrameFormat* SwTextBoxHelper::findTextBox(uno::Reference<drawing::XShape> xShape)
268 : {
269 189 : SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get());
270 189 : if (!pShape)
271 0 : return 0;
272 :
273 189 : return findTextBox(pShape->GetFrameFormat());
274 : }
275 :
276 85199 : SwFrameFormat* SwTextBoxHelper::findTextBox(const SwFrameFormat* pShape)
277 : {
278 85199 : SwFrameFormat* pRet = 0;
279 :
280 : // Only draw frames can have TextBoxes.
281 85199 : if (pShape && pShape->Which() == RES_DRAWFRMFMT && pShape->GetAttrSet().HasItem(RES_CNTNT))
282 : {
283 24645 : const SwFormatContent& rContent = pShape->GetContent();
284 24645 : const SwFrameFormats& rSpzFrameFormats = *pShape->GetDoc()->GetSpzFrameFormats();
285 783696 : for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
286 : {
287 783696 : SwFrameFormat* pFormat = *it;
288 : // Only a fly frame can be a TextBox.
289 783696 : if (pFormat->Which() == RES_FLYFRMFMT && pFormat->GetAttrSet().HasItem(RES_CNTNT) && pFormat->GetContent() == rContent)
290 : {
291 24645 : pRet = pFormat;
292 24645 : break;
293 : }
294 : }
295 : }
296 :
297 85199 : return pRet;
298 : }
299 :
300 : template < typename T >
301 5146 : void lcl_queryInterface(SwFrameFormat* pShape, uno::Any& rAny)
302 : {
303 5146 : if (SwFrameFormat* pFormat = SwTextBoxHelper::findTextBox(pShape))
304 : {
305 : uno::Reference<T> const xInterface(
306 1546 : SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat),
307 1546 : uno::UNO_QUERY);
308 1546 : rAny <<= xInterface;
309 : }
310 5146 : }
311 :
312 457616 : uno::Any SwTextBoxHelper::queryInterface(SwFrameFormat* pShape, const uno::Type& rType)
313 : {
314 457616 : uno::Any aRet;
315 :
316 457616 : if (rType == cppu::UnoType<css::text::XTextAppend>::get())
317 : {
318 1469 : lcl_queryInterface<text::XTextAppend>(pShape, aRet);
319 : }
320 456147 : else if (rType == cppu::UnoType<css::text::XText>::get())
321 : {
322 2476 : lcl_queryInterface<text::XText>(pShape, aRet);
323 : }
324 453671 : else if (rType == cppu::UnoType<css::text::XTextRange>::get())
325 : {
326 1201 : lcl_queryInterface<text::XTextRange>(pShape, aRet);
327 : }
328 :
329 :
330 457616 : return aRet;
331 : }
332 :
333 4348 : Rectangle SwTextBoxHelper::getTextRectangle(SwFrameFormat* pShape, bool bAbsolute)
334 : {
335 4348 : Rectangle aRet;
336 4348 : aRet.SetEmpty();
337 4348 : SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>(pShape->FindRealSdrObject());
338 4348 : if (pCustomShape)
339 : {
340 : // Need to temporarily release the lock acquired in
341 : // SdXMLShapeContext::AddShape(), otherwise we get an empty rectangle,
342 : // see EnhancedCustomShapeEngine::getTextBounds().
343 4348 : uno::Reference<document::XActionLockable> xLockable(pCustomShape->getUnoShape(), uno::UNO_QUERY);
344 4348 : sal_Int16 nLocks = 0;
345 4348 : if (xLockable.is())
346 4348 : nLocks = xLockable->resetActionLocks();
347 4348 : pCustomShape->GetTextBounds(aRet);
348 4348 : if (nLocks)
349 3013 : xLockable->setActionLocks(nLocks);
350 : }
351 :
352 4348 : if (!bAbsolute && pCustomShape)
353 : {
354 : // Relative, so count the logic (reference) rectangle, see the EnhancedCustomShape2d ctor.
355 4261 : Point aPoint(pCustomShape->GetSnapRect().Center());
356 4261 : Size aSize(pCustomShape->GetLogicRect().GetSize());
357 4261 : aPoint.X() -= aSize.Width() / 2;
358 4261 : aPoint.Y() -= aSize.Height() / 2;
359 4261 : Rectangle aLogicRect(aPoint, aSize);
360 4261 : aRet.Move(-1 * aLogicRect.Left(), -1 * aLogicRect.Top());
361 : }
362 :
363 4348 : return aRet;
364 : }
365 :
366 60252 : void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, const OUString& rPropertyName, const css::uno::Any& rValue)
367 : {
368 60252 : if (rPropertyName == "CustomShapeGeometry")
369 : {
370 : // CustomShapeGeometry changes the textbox position offset and size, so adjust both.
371 2005 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any());
372 :
373 1981 : SdrObject* pObject = pShape->FindRealSdrObject();
374 1981 : if (pObject)
375 : {
376 1981 : Rectangle aRectangle(pObject->GetSnapRect());
377 1981 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_POSITION, uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Left()))));
378 1981 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top()))));
379 : }
380 :
381 1981 : if (SwFrameFormat* pFormat = findTextBox(pShape))
382 : {
383 648 : comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue);
384 : // That would be the btLr text direction which we don't support at a frame level, so do it at a character level.
385 648 : if (aCustomShapeGeometry.find("TextPreRotateAngle") != aCustomShapeGeometry.end() && aCustomShapeGeometry["TextPreRotateAngle"].get<sal_Int32>() == -270)
386 : {
387 11 : if (const SwNodeIndex* pNodeIndex = pFormat->GetContent().GetContentIdx())
388 : {
389 11 : SwPaM aPaM(*pFormat->GetDoc()->GetNodes()[pNodeIndex->GetIndex() + 1], 0);
390 11 : aPaM.SetMark();
391 11 : if (SwTextNode* pMark = pFormat->GetDoc()->GetNodes()[pNodeIndex->GetNode().EndOfSectionIndex() - 1]->GetTextNode())
392 : {
393 11 : aPaM.GetMark()->nNode = *pMark;
394 11 : aPaM.GetMark()->nContent.Assign(pMark, pMark->GetText().getLength());
395 11 : SvxCharRotateItem aItem(900, false, RES_CHRATR_ROTATE);
396 11 : pFormat->GetDoc()->getIDocumentContentOperations().InsertPoolItem(aPaM, aItem);
397 11 : }
398 : }
399 648 : }
400 : }
401 : }
402 58259 : else if (rPropertyName == UNO_NAME_TEXT_VERT_ADJUST)
403 3089 : syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, rValue);
404 55170 : else if (rPropertyName == UNO_NAME_TEXT_AUTOGROWHEIGHT)
405 4198 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, rValue);
406 60240 : }
407 :
408 9 : void SwTextBoxHelper::getProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uInt8 nMemberId, css::uno::Any& rValue)
409 : {
410 9 : if (!pShape)
411 9 : return;
412 :
413 9 : nMemberId &= ~CONVERT_TWIPS;
414 :
415 9 : if (SwFrameFormat* pFormat = findTextBox(pShape))
416 : {
417 9 : if (nWID == RES_CHAIN)
418 : {
419 9 : switch (nMemberId)
420 : {
421 : case MID_CHAIN_PREVNAME:
422 : case MID_CHAIN_NEXTNAME:
423 : {
424 0 : const SwFormatChain& rChain = pFormat->GetChain();
425 0 : rChain.QueryValue(rValue, nMemberId);
426 : }
427 0 : break;
428 : case MID_CHAIN_NAME:
429 9 : rValue = uno::makeAny(pFormat->GetName());
430 9 : break;
431 : }
432 : }
433 : }
434 : }
435 :
436 45056 : void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uInt8 nMemberId, const css::uno::Any& rValue)
437 : {
438 : // No shape yet? Then nothing to do, initial properties are set by create().
439 45056 : if (!pShape)
440 635 : return;
441 :
442 44957 : uno::Any aValue(rValue);
443 44957 : nMemberId &= ~CONVERT_TWIPS;
444 :
445 44957 : if (SwFrameFormat* pFormat = findTextBox(pShape))
446 : {
447 16287 : OUString aPropertyName;
448 16287 : bool bAdjustX = false;
449 16287 : bool bAdjustY = false;
450 16287 : bool bAdjustSize = false;
451 16287 : switch (nWID)
452 : {
453 : case RES_HORI_ORIENT:
454 3304 : switch (nMemberId)
455 : {
456 : case MID_HORIORIENT_ORIENT:
457 881 : aPropertyName = UNO_NAME_HORI_ORIENT;
458 881 : break;
459 : case MID_HORIORIENT_RELATION:
460 881 : aPropertyName = UNO_NAME_HORI_ORIENT_RELATION;
461 881 : break;
462 : case MID_HORIORIENT_POSITION:
463 1113 : aPropertyName = UNO_NAME_HORI_ORIENT_POSITION;
464 1113 : bAdjustX = true;
465 1113 : break;
466 : }
467 3304 : break;
468 : case RES_VERT_ORIENT:
469 2875 : switch (nMemberId)
470 : {
471 : case MID_VERTORIENT_ORIENT:
472 881 : aPropertyName = UNO_NAME_VERT_ORIENT;
473 881 : break;
474 : case MID_VERTORIENT_RELATION:
475 881 : aPropertyName = UNO_NAME_VERT_ORIENT_RELATION;
476 881 : break;
477 : case MID_VERTORIENT_POSITION:
478 1113 : aPropertyName = UNO_NAME_VERT_ORIENT_POSITION;
479 1113 : bAdjustY = true;
480 1113 : break;
481 : }
482 2875 : break;
483 : case RES_FRM_SIZE:
484 2842 : switch (nMemberId)
485 : {
486 : case MID_FRMSIZE_IS_AUTO_HEIGHT:
487 814 : aPropertyName = UNO_NAME_FRAME_ISAUTOMATIC_HEIGHT;
488 814 : break;
489 : default:
490 2028 : aPropertyName = UNO_NAME_SIZE;
491 2028 : bAdjustSize = true;
492 2028 : break;
493 : }
494 2842 : break;
495 : case RES_ANCHOR:
496 866 : switch (nMemberId)
497 : {
498 : case MID_ANCHOR_ANCHORTYPE:
499 866 : if (aValue.get<text::TextContentAnchorType>() == text::TextContentAnchorType_AS_CHARACTER)
500 : {
501 : uno::Reference<beans::XPropertySet> const xPropertySet(
502 437 : SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat),
503 437 : uno::UNO_QUERY);
504 437 : xPropertySet->setPropertyValue(UNO_NAME_SURROUND, uno::makeAny(text::WrapTextMode_THROUGHT));
505 437 : return;
506 : }
507 429 : break;
508 : }
509 429 : break;
510 : case FN_TEXT_RANGE:
511 : {
512 874 : uno::Reference<text::XTextRange> xRange;
513 874 : rValue >>= xRange;
514 1748 : SwUnoInternalPaM aInternalPaM(*pFormat->GetDoc());
515 874 : if (sw::XTextRangeToSwPaM(aInternalPaM, xRange))
516 : {
517 874 : SwFormatAnchor aAnchor(pFormat->GetAnchor());
518 874 : aAnchor.SetAnchor(aInternalPaM.Start());
519 874 : pFormat->SetFormatAttr(aAnchor);
520 874 : }
521 : }
522 874 : break;
523 : case RES_CHAIN:
524 12 : switch (nMemberId)
525 : {
526 : case MID_CHAIN_PREVNAME:
527 6 : aPropertyName = UNO_NAME_CHAIN_PREV_NAME;
528 6 : break;
529 : case MID_CHAIN_NEXTNAME:
530 6 : aPropertyName = UNO_NAME_CHAIN_NEXT_NAME;
531 6 : break;
532 : }
533 12 : break;
534 : case RES_TEXT_VERT_ADJUST:
535 1250 : aPropertyName = UNO_NAME_TEXT_VERT_ADJUST;
536 1250 : break;
537 : }
538 :
539 15850 : if (!aPropertyName.isEmpty())
540 : {
541 : // Position/size should be the text position/size, not the shape one as-is.
542 9854 : if (bAdjustX || bAdjustY || bAdjustSize)
543 : {
544 4254 : Rectangle aRect = getTextRectangle(pShape, /*bAbsolute=*/false);
545 4254 : if (!aRect.IsEmpty())
546 : {
547 4204 : if (bAdjustX || bAdjustY)
548 : {
549 : sal_Int32 nValue;
550 2204 : if (aValue >>= nValue)
551 : {
552 2204 : if (bAdjustX)
553 1102 : nValue += TWIPS_TO_MM(aRect.getX());
554 1102 : else if (bAdjustY)
555 1102 : nValue += TWIPS_TO_MM(aRect.getY());
556 2204 : aValue <<= nValue;
557 2204 : }
558 : }
559 2000 : else if (bAdjustSize)
560 : {
561 2000 : awt::Size aSize(TWIPS_TO_MM(aRect.getWidth()), TWIPS_TO_MM(aRect.getHeight()));
562 2000 : aValue <<= aSize;
563 : }
564 : }
565 : }
566 :
567 : uno::Reference<beans::XPropertySet> const xPropertySet(
568 9854 : SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat),
569 9854 : uno::UNO_QUERY);
570 9866 : xPropertySet->setPropertyValue(aPropertyName, aValue);
571 15850 : }
572 44520 : }
573 : }
574 :
575 5097 : void SwTextBoxHelper::saveLinks(const SwFrameFormats& rFormats, std::map<const SwFrameFormat*, const SwFrameFormat*>& rLinks)
576 : {
577 20333 : for (size_t i = 0; i < rFormats.size(); ++i)
578 : {
579 15236 : const SwFrameFormat* pFormat = rFormats[i];
580 15236 : if (pFormat->Which() != RES_DRAWFRMFMT)
581 8048 : continue;
582 7188 : if (SwFrameFormat* pTextBox = findTextBox(pFormat))
583 2710 : rLinks[pFormat] = pTextBox;
584 : }
585 5097 : }
586 :
587 542 : void SwTextBoxHelper::resetLink(SwFrameFormat* pShape, std::map<const SwFrameFormat*, SwFormatContent>& rMap)
588 : {
589 542 : if (pShape->Which() == RES_DRAWFRMFMT)
590 : {
591 245 : if (pShape->GetContent().GetContentIdx())
592 120 : rMap.insert(std::make_pair(pShape, pShape->GetContent()));
593 245 : pShape->ResetFormatAttr(RES_CNTNT);
594 : }
595 542 : }
596 :
597 5097 : void SwTextBoxHelper::restoreLinks(std::set<_ZSortFly>& rOld, std::vector<SwFrameFormat*>& rNew, SavedLink& rSavedLinks, SavedContent& rOldContent)
598 : {
599 5097 : size_t i = 0;
600 5639 : for (std::set<_ZSortFly>::iterator aSetIt = rOld.begin(); aSetIt != rOld.end(); ++aSetIt, ++i)
601 : {
602 542 : SavedLink::iterator aTextBoxIt = rSavedLinks.find(aSetIt->GetFormat());
603 542 : if (aTextBoxIt != rSavedLinks.end())
604 : {
605 120 : size_t j = 0;
606 594 : for (std::set<_ZSortFly>::iterator aSetJt = rOld.begin(); aSetJt != rOld.end(); ++aSetJt, ++j)
607 : {
608 474 : if (aSetJt->GetFormat() == aTextBoxIt->second)
609 120 : rNew[i]->SetFormatAttr(rNew[j]->GetContent());
610 : }
611 : }
612 542 : if (rOldContent.find(aSetIt->GetFormat()) != rOldContent.end())
613 120 : const_cast<SwFrameFormat*>(aSetIt->GetFormat())->SetFormatAttr(rOldContent[aSetIt->GetFormat()]);
614 : }
615 5097 : }
616 :
617 294 : void SwTextBoxHelper::syncFlyFrmAttr(SwFrameFormat& rShape, SfxItemSet& rSet)
618 : {
619 294 : if (SwFrameFormat* pFormat = findTextBox(&rShape))
620 : {
621 7 : SfxItemSet aTextBoxSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange);
622 :
623 14 : SfxItemIter aIter(rSet);
624 7 : sal_uInt16 nWhich = aIter.GetCurItem()->Which();
625 0 : do
626 : {
627 7 : switch (nWhich)
628 : {
629 : case RES_VERT_ORIENT:
630 : {
631 6 : const SwFormatVertOrient& rOrient = static_cast<const SwFormatVertOrient&>(*aIter.GetCurItem());
632 6 : SwFormatVertOrient aOrient(rOrient);
633 :
634 6 : Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
635 6 : if (!aRect.IsEmpty())
636 6 : aOrient.SetPos(aOrient.GetPos() + aRect.getY());
637 :
638 6 : aTextBoxSet.Put(aOrient);
639 :
640 : // restore height (shrinked for extending beyond the page bottom - tdf#91260)
641 12 : SwFormatFrmSize aSize(pFormat->GetFrmSize());
642 6 : if (!aRect.IsEmpty())
643 : {
644 6 : aSize.SetHeight(aRect.getHeight());
645 6 : aTextBoxSet.Put(aSize);
646 6 : }
647 : }
648 6 : break;
649 : case RES_HORI_ORIENT:
650 : {
651 0 : const SwFormatHoriOrient& rOrient = static_cast<const SwFormatHoriOrient&>(*aIter.GetCurItem());
652 0 : SwFormatHoriOrient aOrient(rOrient);
653 :
654 0 : Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
655 0 : if (!aRect.IsEmpty())
656 0 : aOrient.SetPos(aOrient.GetPos() + aRect.getX());
657 :
658 0 : aTextBoxSet.Put(aOrient);
659 : }
660 0 : break;
661 : case RES_FRM_SIZE:
662 : {
663 : // In case the shape got resized, then we need to adjust both
664 : // the position and the size of the textbox (e.g. larger
665 : // rounded edges of a rectangle -> need to push right/down the
666 : // textbox).
667 1 : SwFormatVertOrient aVertOrient(rShape.GetVertOrient());
668 2 : SwFormatHoriOrient aHoriOrient(rShape.GetHoriOrient());
669 2 : SwFormatFrmSize aSize(pFormat->GetFrmSize());
670 :
671 1 : Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
672 1 : if (!aRect.IsEmpty())
673 : {
674 1 : aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY());
675 1 : aTextBoxSet.Put(aVertOrient);
676 :
677 1 : aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX());
678 1 : aTextBoxSet.Put(aHoriOrient);
679 :
680 1 : aSize.SetWidth(aRect.getWidth());
681 1 : aSize.SetHeight(aRect.getHeight());
682 1 : aTextBoxSet.Put(aSize);
683 1 : }
684 : }
685 1 : break;
686 : default:
687 : SAL_WARN("sw.core", "SwTextBoxHelper::syncFlyFrmAttr: unhandled which-id: " << nWhich);
688 0 : break;
689 : }
690 :
691 7 : if (aIter.IsAtEnd())
692 7 : break;
693 : }
694 0 : while (0 != (nWhich = aIter.NextItem()->Which()));
695 :
696 7 : if (aTextBoxSet.Count())
697 14 : pFormat->GetDoc()->SetFlyFrmAttr(*pFormat, aTextBoxSet);
698 : }
699 471 : }
700 :
701 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|