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 <anchoredobject.hxx>
30 : #include <cntfrm.hxx>
31 :
32 : #include <editeng/unoprnms.hxx>
33 : #include <editeng/charrotateitem.hxx>
34 : #include <svx/svdoashp.hxx>
35 : #include <svx/svdpage.hxx>
36 : #include <svl/itemiter.hxx>
37 : #include <comphelper/sequenceashashmap.hxx>
38 :
39 : #include <com/sun/star/document/XActionLockable.hpp>
40 : #include <com/sun/star/table/BorderLine2.hpp>
41 : #include <com/sun/star/text/SizeType.hpp>
42 : #include <com/sun/star/text/TextContentAnchorType.hpp>
43 : #include <com/sun/star/text/WrapTextMode.hpp>
44 : #include <com/sun/star/text/XTextDocument.hpp>
45 :
46 : using namespace com::sun::star;
47 :
48 824 : void SwTextBoxHelper::create(SwFrmFmt* pShape)
49 : {
50 : // If TextBox wasn't enabled previously
51 824 : if (!pShape->GetAttrSet().HasItem(RES_CNTNT))
52 : {
53 : // Create the associated TextFrame and insert it into the document.
54 824 : uno::Reference<text::XTextContent> xTextFrame(SwXServiceProvider::MakeInstance(SW_SERVICE_TYPE_TEXTFRAME, *pShape->GetDoc()), uno::UNO_QUERY);
55 1648 : uno::Reference<text::XTextDocument> xTextDocument(pShape->GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
56 1648 : uno::Reference<text::XTextContentAppend> xTextContentAppend(xTextDocument->getText(), uno::UNO_QUERY);
57 824 : xTextContentAppend->appendTextContent(xTextFrame, uno::Sequence<beans::PropertyValue>());
58 :
59 : // Initialize properties.
60 1648 : uno::Reference<beans::XPropertySet> xPropertySet(xTextFrame, uno::UNO_QUERY);
61 1648 : uno::Any aEmptyBorder = uno::makeAny(table::BorderLine2());
62 824 : xPropertySet->setPropertyValue(UNO_NAME_TOP_BORDER, aEmptyBorder);
63 824 : xPropertySet->setPropertyValue(UNO_NAME_BOTTOM_BORDER, aEmptyBorder);
64 824 : xPropertySet->setPropertyValue(UNO_NAME_LEFT_BORDER, aEmptyBorder);
65 824 : xPropertySet->setPropertyValue(UNO_NAME_RIGHT_BORDER, aEmptyBorder);
66 :
67 824 : xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(sal_Int32(100)));
68 :
69 824 : xPropertySet->setPropertyValue(UNO_NAME_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
70 :
71 1648 : uno::Reference<container::XNamed> xNamed(xTextFrame, uno::UNO_QUERY);
72 824 : xNamed->setName(pShape->GetDoc()->GetUniqueFrameName());
73 :
74 : // Link its text range to the original shape.
75 1648 : uno::Reference<text::XTextRange> xTextBox(xTextFrame, uno::UNO_QUERY_THROW);
76 1648 : SwUnoInternalPaM aInternalPaM(*pShape->GetDoc());
77 824 : if (sw::XTextRangeToSwPaM(aInternalPaM, xTextBox))
78 : {
79 824 : SwAttrSet aSet(pShape->GetAttrSet());
80 1648 : SwFmtCntnt aCntnt(aInternalPaM.GetNode().StartOfSectionNode());
81 824 : aSet.Put(aCntnt);
82 1648 : pShape->SetFmtAttr(aSet);
83 : }
84 :
85 : // Also initialize the properties, which are not constant, but inherited from the shape's ones.
86 1648 : uno::Reference<drawing::XShape> xShape(pShape->FindRealSdrObject()->getUnoShape(), uno::UNO_QUERY);
87 824 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::makeAny(xShape->getSize()));
88 :
89 1648 : uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY);
90 824 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT));
91 824 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_RELATION, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION));
92 824 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_ORIENT, xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT));
93 824 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_RELATION, xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION));
94 824 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_POSITION, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION));
95 824 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION));
96 824 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT));
97 1648 : syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST));
98 : }
99 824 : }
100 :
101 260 : void SwTextBoxHelper::destroy(SwFrmFmt* pShape)
102 : {
103 : // If a TextBox was enabled previously
104 260 : if (pShape->GetAttrSet().HasItem(RES_CNTNT))
105 : {
106 0 : SwFrmFmt* pFmt = findTextBox(pShape);
107 :
108 : // Unlink the TextBox's text range from the original shape.
109 0 : pShape->ResetFmtAttr(RES_CNTNT);
110 :
111 : // Delete the associated TextFrame.
112 0 : if (pFmt)
113 0 : pShape->GetDoc()->getIDocumentLayoutAccess().DelLayoutFmt(pFmt);
114 : }
115 260 : }
116 :
117 4604 : std::set<const SwFrmFmt*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc)
118 : {
119 4604 : std::set<const SwFrmFmt*> aRet;
120 :
121 4604 : const SwFrmFmts& rSpzFrmFmts = *pDoc->GetSpzFrmFmts();
122 16106 : for (SwFrmFmts::const_iterator it = rSpzFrmFmts.begin(); it != rSpzFrmFmts.end(); ++it)
123 : {
124 11502 : SwFrmFmt* pTextBox = findTextBox(*it);
125 11502 : if (pTextBox)
126 1050 : aRet.insert(pTextBox);
127 : }
128 :
129 4604 : return aRet;
130 : }
131 :
132 1584 : std::set<const SwFrmFmt*> SwTextBoxHelper::findTextBoxes(const SwNode& rNode)
133 : {
134 1584 : const SwDoc* pDoc = rNode.GetDoc();
135 1584 : const SwCntntNode* pCntntNode = 0;
136 1584 : const SwCntntFrm* pCntntFrm = 0;
137 1584 : bool bHaveViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
138 1584 : if (bHaveViewShell && (pCntntNode = rNode.GetCntntNode()) && (pCntntFrm = pCntntNode->getLayoutFrm(pDoc->getIDocumentLayoutAccess().GetCurrentLayout())))
139 : {
140 : // We can use the layout information to iterate over only the frames which are anchored to us.
141 1576 : std::set<const SwFrmFmt*> aRet;
142 1576 : const SwSortedObjs* pSortedObjs = pCntntFrm->GetDrawObjs();
143 1576 : if (pSortedObjs)
144 : {
145 1144 : for (size_t i = 0; i < pSortedObjs->size(); ++i)
146 : {
147 824 : SwAnchoredObject* pAnchoredObject = (*pSortedObjs)[i];
148 824 : SwFrmFmt* pTextBox = findTextBox(&pAnchoredObject->GetFrmFmt());
149 824 : if (pTextBox)
150 4 : aRet.insert(pTextBox);
151 : }
152 : }
153 1576 : return aRet;
154 : }
155 : else
156 : // If necessary, here we could manually limit the returned set to the
157 : // ones which are anchored to rNode, but currently no need to do so.
158 8 : return findTextBoxes(pDoc);
159 : }
160 :
161 3427 : std::map<SwFrmFmt*, SwFrmFmt*> SwTextBoxHelper::findShapes(const SwDoc* pDoc)
162 : {
163 3427 : std::map<SwFrmFmt*, SwFrmFmt*> aRet;
164 :
165 3427 : const SwFrmFmts& rSpzFrmFmts = *pDoc->GetSpzFrmFmts();
166 26215 : for (SwFrmFmts::const_iterator it = rSpzFrmFmts.begin(); it != rSpzFrmFmts.end(); ++it)
167 : {
168 22788 : SwFrmFmt* pTextBox = findTextBox(*it);
169 22788 : if (pTextBox)
170 4168 : aRet[pTextBox] = *it;
171 : }
172 :
173 3427 : return aRet;
174 : }
175 :
176 : /// If the passed SdrObject is in fact a TextFrame, that is used as a TextBox.
177 1710 : bool lcl_isTextBox(SdrObject* pSdrObject, std::set<const SwFrmFmt*>& rTextBoxes)
178 : {
179 1710 : SwVirtFlyDrawObj* pObject = PTR_CAST(SwVirtFlyDrawObj, pSdrObject);
180 1710 : return pObject && rTextBoxes.find(pObject->GetFmt()) != rTextBoxes.end();
181 : }
182 :
183 238 : sal_Int32 SwTextBoxHelper::getCount(SdrPage* pPage, std::set<const SwFrmFmt*>& rTextBoxes)
184 : {
185 238 : sal_Int32 nRet = 0;
186 1538 : for (size_t i = 0; i < pPage->GetObjCount(); ++i)
187 : {
188 1300 : if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
189 590 : continue;
190 710 : ++nRet;
191 : }
192 238 : return nRet;
193 : }
194 :
195 170 : uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrmFmt*>& rTextBoxes) throw(lang::IndexOutOfBoundsException)
196 : {
197 170 : if (nIndex < 0 || nIndex >= getCount(pPage, rTextBoxes))
198 0 : throw lang::IndexOutOfBoundsException();
199 :
200 170 : SdrObject* pRet = 0;
201 170 : sal_Int32 nCount = 0; // Current logical index.
202 410 : for (size_t i = 0; i < pPage->GetObjCount(); ++i)
203 : {
204 410 : if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
205 60 : continue;
206 350 : if (nCount == nIndex)
207 : {
208 170 : pRet = pPage->GetObj(i);
209 170 : break;
210 : }
211 180 : ++nCount;
212 : }
213 : assert(pRet);
214 170 : return pRet ? uno::makeAny(uno::Reference<drawing::XShape>(pRet->getUnoShape(), uno::UNO_QUERY)) : uno::Any();
215 : }
216 :
217 348 : SwFrmFmt* SwTextBoxHelper::findTextBox(uno::Reference<drawing::XShape> xShape)
218 : {
219 348 : SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get());
220 348 : if (!pShape)
221 0 : return 0;
222 :
223 348 : return findTextBox(pShape->GetFrmFmt());
224 : }
225 :
226 163125 : SwFrmFmt* SwTextBoxHelper::findTextBox(const SwFrmFmt* pShape)
227 : {
228 163125 : SwFrmFmt* pRet = 0;
229 :
230 : // Only draw frames can have TextBoxes.
231 163125 : if (pShape->Which() == RES_DRAWFRMFMT && pShape->GetAttrSet().HasItem(RES_CNTNT))
232 : {
233 45026 : const SwFmtCntnt& rCntnt = pShape->GetCntnt();
234 45026 : const SwFrmFmts& rSpzFrmFmts = *pShape->GetDoc()->GetSpzFrmFmts();
235 1457256 : for (SwFrmFmts::const_iterator it = rSpzFrmFmts.begin(); it != rSpzFrmFmts.end(); ++it)
236 : {
237 1457256 : SwFrmFmt* pFmt = *it;
238 : // Only a fly frame can be a TextBox.
239 1457256 : if (pFmt->Which() == RES_FLYFRMFMT && pFmt->GetAttrSet().HasItem(RES_CNTNT) && pFmt->GetCntnt() == rCntnt)
240 : {
241 45026 : pRet = pFmt;
242 45026 : break;
243 : }
244 : }
245 : }
246 :
247 163125 : return pRet;
248 : }
249 :
250 : template < typename T >
251 9364 : void lcl_queryInterface(SwFrmFmt* pShape, uno::Any& rAny)
252 : {
253 9364 : if (SwFrmFmt* pFmt = SwTextBoxHelper::findTextBox(pShape))
254 : {
255 : uno::Reference<T> const xInterface(
256 2818 : SwXTextFrame::CreateXTextFrame(*pFmt->GetDoc(), pFmt),
257 2818 : uno::UNO_QUERY);
258 2818 : rAny <<= xInterface;
259 : }
260 9364 : }
261 :
262 840967 : uno::Any SwTextBoxHelper::queryInterface(SwFrmFmt* pShape, const uno::Type& rType)
263 : {
264 840967 : uno::Any aRet;
265 :
266 840967 : if (rType == cppu::UnoType<css::text::XTextAppend>::get())
267 : {
268 2834 : lcl_queryInterface<text::XTextAppend>(pShape, aRet);
269 : }
270 838133 : else if (rType == cppu::UnoType<css::text::XText>::get())
271 : {
272 4240 : lcl_queryInterface<text::XText>(pShape, aRet);
273 : }
274 833893 : else if (rType == cppu::UnoType<css::text::XTextRange>::get())
275 : {
276 2290 : lcl_queryInterface<text::XTextRange>(pShape, aRet);
277 : }
278 :
279 :
280 840967 : return aRet;
281 : }
282 :
283 7942 : Rectangle SwTextBoxHelper::getTextRectangle(SwFrmFmt* pShape, bool bAbsolute)
284 : {
285 7942 : Rectangle aRet;
286 7942 : aRet.SetEmpty();
287 7942 : SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>(pShape->FindRealSdrObject());
288 7942 : if (pCustomShape)
289 : {
290 : // Need to temporarily release the lock acquired in
291 : // SdXMLShapeContext::AddShape(), otherwise we get an empty rectangle,
292 : // see EnhancedCustomShapeEngine::getTextBounds().
293 7942 : uno::Reference<document::XActionLockable> xLockable(pCustomShape->getUnoShape(), uno::UNO_QUERY);
294 7942 : sal_Int16 nLocks = 0;
295 7942 : if (xLockable.is())
296 7942 : nLocks = xLockable->resetActionLocks();
297 7942 : pCustomShape->GetTextBounds(aRet);
298 7942 : if (nLocks)
299 5534 : xLockable->setActionLocks(nLocks);
300 : }
301 :
302 7942 : if (!bAbsolute && pCustomShape)
303 : {
304 : // Relative, so count the logic (reference) rectangle, see the EnhancedCustomShape2d ctor.
305 7870 : Point aPoint(pCustomShape->GetSnapRect().Center());
306 7870 : Size aSize(pCustomShape->GetLogicRect().GetSize());
307 7870 : aPoint.X() -= aSize.Width() / 2;
308 7870 : aPoint.Y() -= aSize.Height() / 2;
309 7870 : Rectangle aLogicRect(aPoint, aSize);
310 7870 : aRet.Move(-1 * aLogicRect.Left(), -1 * aLogicRect.Top());
311 : }
312 :
313 7942 : return aRet;
314 : }
315 :
316 107248 : void SwTextBoxHelper::syncProperty(SwFrmFmt* pShape, const OUString& rPropertyName, const css::uno::Any& rValue)
317 : {
318 107248 : if (rPropertyName == "CustomShapeGeometry")
319 : {
320 : // CustomShapeGeometry changes the textbox position offset and size, so adjust both.
321 3744 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any());
322 :
323 3696 : SdrObject* pObject = pShape->FindRealSdrObject();
324 3696 : if (pObject)
325 : {
326 3696 : Rectangle aRectangle(pObject->GetSnapRect());
327 3696 : syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_POSITION, uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Left()))));
328 3696 : syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top()))));
329 : }
330 :
331 3696 : if (SwFrmFmt* pFmt = findTextBox(pShape))
332 : {
333 1204 : comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue);
334 : // That would be the btLr text direction which we don't support at a frame level, so do it at a character level.
335 1204 : if (aCustomShapeGeometry.find("TextPreRotateAngle") != aCustomShapeGeometry.end() && aCustomShapeGeometry["TextPreRotateAngle"].get<sal_Int32>() == -270)
336 : {
337 22 : if (const SwNodeIndex* pNodeIndex = pFmt->GetCntnt().GetCntntIdx())
338 : {
339 22 : SwPaM aPaM(*pFmt->GetDoc()->GetNodes()[pNodeIndex->GetIndex() + 1], 0);
340 22 : aPaM.SetMark();
341 22 : if (SwTxtNode* pMark = pFmt->GetDoc()->GetNodes()[pNodeIndex->GetNode().EndOfSectionIndex() - 1]->GetTxtNode())
342 : {
343 22 : aPaM.GetMark()->nNode = *pMark;
344 22 : aPaM.GetMark()->nContent.Assign(pMark, pMark->GetTxt().getLength());
345 22 : SvxCharRotateItem aItem(900, false, RES_CHRATR_ROTATE);
346 22 : pFmt->GetDoc()->getIDocumentContentOperations().InsertPoolItem(aPaM, aItem, 0);
347 22 : }
348 : }
349 1204 : }
350 : }
351 : }
352 103528 : else if (rPropertyName == UNO_NAME_TEXT_VERT_ADJUST)
353 5728 : syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, rValue);
354 97800 : else if (rPropertyName == UNO_NAME_TEXT_AUTOGROWHEIGHT)
355 7716 : syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, rValue);
356 107224 : }
357 :
358 18 : void SwTextBoxHelper::getProperty(SwFrmFmt* pShape, sal_uInt16 nWID, sal_uInt8 nMemberId, css::uno::Any& rValue)
359 : {
360 18 : if (!pShape)
361 18 : return;
362 :
363 18 : nMemberId &= ~CONVERT_TWIPS;
364 :
365 18 : if (SwFrmFmt* pFmt = findTextBox(pShape))
366 : {
367 18 : if (nWID == RES_CHAIN)
368 : {
369 18 : switch (nMemberId)
370 : {
371 : case MID_CHAIN_PREVNAME:
372 : case MID_CHAIN_NEXTNAME:
373 : {
374 0 : const SwFmtChain& rChain = pFmt->GetChain();
375 0 : rChain.QueryValue(rValue, nMemberId);
376 : }
377 0 : break;
378 : case MID_CHAIN_NAME:
379 18 : rValue = uno::makeAny(pFmt->GetName());
380 18 : break;
381 : }
382 : }
383 : }
384 : }
385 :
386 84134 : void SwTextBoxHelper::syncProperty(SwFrmFmt* pShape, sal_uInt16 nWID, sal_uInt8 nMemberId, const css::uno::Any& rValue)
387 : {
388 : // No shape yet? Then nothing to do, initial properties are set by create().
389 84134 : if (!pShape)
390 1196 : return;
391 :
392 83938 : uno::Any aValue(rValue);
393 83938 : nMemberId &= ~CONVERT_TWIPS;
394 :
395 83938 : if (SwFrmFmt* pFmt = findTextBox(pShape))
396 : {
397 30022 : OUString aPropertyName;
398 30022 : bool bAdjustX = false;
399 30022 : bool bAdjustY = false;
400 30022 : bool bAdjustSize = false;
401 30022 : switch (nWID)
402 : {
403 : case RES_HORI_ORIENT:
404 6078 : switch (nMemberId)
405 : {
406 : case MID_HORIORIENT_ORIENT:
407 1618 : aPropertyName = UNO_NAME_HORI_ORIENT;
408 1618 : break;
409 : case MID_HORIORIENT_RELATION:
410 1618 : aPropertyName = UNO_NAME_HORI_ORIENT_RELATION;
411 1618 : break;
412 : case MID_HORIORIENT_POSITION:
413 2048 : aPropertyName = UNO_NAME_HORI_ORIENT_POSITION;
414 2048 : bAdjustX = true;
415 2048 : break;
416 : }
417 6078 : break;
418 : case RES_VERT_ORIENT:
419 5284 : switch (nMemberId)
420 : {
421 : case MID_VERTORIENT_ORIENT:
422 1618 : aPropertyName = UNO_NAME_VERT_ORIENT;
423 1618 : break;
424 : case MID_VERTORIENT_RELATION:
425 1618 : aPropertyName = UNO_NAME_VERT_ORIENT_RELATION;
426 1618 : break;
427 : case MID_VERTORIENT_POSITION:
428 2048 : aPropertyName = UNO_NAME_VERT_ORIENT_POSITION;
429 2048 : bAdjustY = true;
430 2048 : break;
431 : }
432 5284 : break;
433 : case RES_FRM_SIZE:
434 5252 : switch (nMemberId)
435 : {
436 : case MID_FRMSIZE_IS_AUTO_HEIGHT:
437 1490 : aPropertyName = UNO_NAME_FRAME_ISAUTOMATIC_HEIGHT;
438 1490 : break;
439 : default:
440 3762 : aPropertyName = UNO_NAME_SIZE;
441 3762 : bAdjustSize = true;
442 3762 : break;
443 : }
444 5252 : break;
445 : case RES_ANCHOR:
446 1598 : switch (nMemberId)
447 : {
448 : case MID_ANCHOR_ANCHORTYPE:
449 1598 : if (aValue.get<text::TextContentAnchorType>() == text::TextContentAnchorType_AS_CHARACTER)
450 : {
451 : uno::Reference<beans::XPropertySet> const xPropertySet(
452 804 : SwXTextFrame::CreateXTextFrame(*pFmt->GetDoc(), pFmt),
453 804 : uno::UNO_QUERY);
454 804 : xPropertySet->setPropertyValue(UNO_NAME_SURROUND, uno::makeAny(text::WrapTextMode_THROUGHT));
455 804 : return;
456 : }
457 794 : break;
458 : }
459 794 : break;
460 : case FN_TEXT_RANGE:
461 : {
462 1608 : uno::Reference<text::XTextRange> xRange;
463 1608 : rValue >>= xRange;
464 3216 : SwUnoInternalPaM aInternalPaM(*pFmt->GetDoc());
465 1608 : if (sw::XTextRangeToSwPaM(aInternalPaM, xRange))
466 : {
467 1608 : SwFmtAnchor aAnchor(pFmt->GetAnchor());
468 1608 : aAnchor.SetAnchor(aInternalPaM.Start());
469 1608 : pFmt->SetFmtAttr(aAnchor);
470 1608 : }
471 : }
472 1608 : break;
473 : case RES_CHAIN:
474 24 : switch (nMemberId)
475 : {
476 : case MID_CHAIN_PREVNAME:
477 12 : aPropertyName = UNO_NAME_CHAIN_PREV_NAME;
478 12 : break;
479 : case MID_CHAIN_NEXTNAME:
480 12 : aPropertyName = UNO_NAME_CHAIN_NEXT_NAME;
481 12 : break;
482 : }
483 24 : break;
484 : case RES_TEXT_VERT_ADJUST:
485 2302 : aPropertyName = UNO_NAME_TEXT_VERT_ADJUST;
486 2302 : break;
487 : }
488 :
489 29218 : if (!aPropertyName.isEmpty())
490 : {
491 : // Position/size should be the text position/size, not the shape one as-is.
492 18146 : if (bAdjustX || bAdjustY || bAdjustSize)
493 : {
494 7858 : Rectangle aRect = getTextRectangle(pShape, /*bAbsolute=*/false);
495 7858 : if (!aRect.IsEmpty())
496 : {
497 7766 : if (bAdjustX || bAdjustY)
498 : {
499 : sal_Int32 nValue;
500 4052 : if (aValue >>= nValue)
501 : {
502 4052 : if (bAdjustX)
503 2026 : nValue += TWIPS_TO_MM(aRect.getX());
504 2026 : else if (bAdjustY)
505 2026 : nValue += TWIPS_TO_MM(aRect.getY());
506 4052 : aValue <<= nValue;
507 4052 : }
508 : }
509 3714 : else if (bAdjustSize)
510 : {
511 3714 : awt::Size aSize(TWIPS_TO_MM(aRect.getWidth()), TWIPS_TO_MM(aRect.getHeight()));
512 3714 : aValue <<= aSize;
513 : }
514 : }
515 : }
516 :
517 : uno::Reference<beans::XPropertySet> const xPropertySet(
518 18146 : SwXTextFrame::CreateXTextFrame(*pFmt->GetDoc(), pFmt),
519 18146 : uno::UNO_QUERY);
520 18170 : xPropertySet->setPropertyValue(aPropertyName, aValue);
521 29218 : }
522 83134 : }
523 : }
524 :
525 7368 : void SwTextBoxHelper::saveLinks(const SwFrmFmts& rFormats, std::map<const SwFrmFmt*, const SwFrmFmt*>& rLinks)
526 : {
527 31332 : for (size_t i = 0; i < rFormats.size(); ++i)
528 : {
529 23964 : SwFrmFmt* pFmt = rFormats[i];
530 23964 : if (pFmt->Which() != RES_DRAWFRMFMT)
531 13270 : continue;
532 10694 : if (SwFrmFmt* pTextBox = findTextBox(pFmt))
533 4012 : rLinks[pFmt] = pTextBox;
534 : }
535 7368 : }
536 :
537 840 : void SwTextBoxHelper::resetLink(SwFrmFmt* pShape, std::map<const SwFrmFmt*, SwFmtCntnt>& rMap)
538 : {
539 840 : if (pShape->Which() == RES_DRAWFRMFMT)
540 : {
541 370 : if (pShape->GetCntnt().GetCntntIdx())
542 188 : rMap.insert(std::make_pair(pShape, pShape->GetCntnt()));
543 370 : pShape->ResetFmtAttr(RES_CNTNT);
544 : }
545 840 : }
546 :
547 7368 : void SwTextBoxHelper::restoreLinks(std::set<_ZSortFly>& rOld, std::vector<SwFrmFmt*>& rNew, SavedLink& rSavedLinks, SavedContent& rOldContent)
548 : {
549 7368 : size_t i = 0;
550 8208 : for (std::set<_ZSortFly>::iterator aSetIt = rOld.begin(); aSetIt != rOld.end(); ++aSetIt, ++i)
551 : {
552 840 : SavedLink::iterator aTextBoxIt = rSavedLinks.find(aSetIt->GetFmt());
553 840 : if (aTextBoxIt != rSavedLinks.end())
554 : {
555 188 : size_t j = 0;
556 952 : for (std::set<_ZSortFly>::iterator aSetJt = rOld.begin(); aSetJt != rOld.end(); ++aSetJt, ++j)
557 : {
558 764 : if (aSetJt->GetFmt() == aTextBoxIt->second)
559 188 : rNew[i]->SetFmtAttr(rNew[j]->GetCntnt());
560 : }
561 : }
562 840 : if (rOldContent.find(aSetIt->GetFmt()) != rOldContent.end())
563 188 : const_cast<SwFrmFmt*>(aSetIt->GetFmt())->SetFmtAttr(rOldContent[aSetIt->GetFmt()]);
564 : }
565 7368 : }
566 :
567 578 : void SwTextBoxHelper::syncFlyFrmAttr(SwFrmFmt& rShape, SfxItemSet& rSet)
568 : {
569 578 : if (SwFrmFmt* pFmt = findTextBox(&rShape))
570 : {
571 12 : SfxItemSet aTextBoxSet(pFmt->GetDoc()->GetAttrPool(), aFrmFmtSetRange);
572 :
573 24 : SfxItemIter aIter(rSet);
574 12 : sal_uInt16 nWhich = aIter.GetCurItem()->Which();
575 0 : do
576 : {
577 12 : switch (nWhich)
578 : {
579 : case RES_VERT_ORIENT:
580 : {
581 6 : const SwFmtVertOrient& rOrient = static_cast<const SwFmtVertOrient&>(*aIter.GetCurItem());
582 6 : SwFmtVertOrient aOrient(rOrient);
583 :
584 6 : Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
585 6 : if (!aRect.IsEmpty())
586 6 : aOrient.SetPos(aOrient.GetPos() + aRect.getY());
587 :
588 6 : aTextBoxSet.Put(aOrient);
589 : }
590 6 : break;
591 : case RES_HORI_ORIENT:
592 : {
593 0 : const SwFmtHoriOrient& rOrient = static_cast<const SwFmtHoriOrient&>(*aIter.GetCurItem());
594 0 : SwFmtHoriOrient aOrient(rOrient);
595 :
596 0 : Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
597 0 : if (!aRect.IsEmpty())
598 0 : aOrient.SetPos(aOrient.GetPos() + aRect.getX());
599 :
600 0 : aTextBoxSet.Put(aOrient);
601 : }
602 0 : break;
603 : case RES_FRM_SIZE:
604 : {
605 : // In case the shape got resized, then we need to adjust both
606 : // the position and the size of the textbox (e.g. larger
607 : // rounded edges of a rectangle -> need to push right/down the
608 : // textbox).
609 6 : SwFmtVertOrient aVertOrient(rShape.GetVertOrient());
610 12 : SwFmtHoriOrient aHoriOrient(rShape.GetHoriOrient());
611 12 : SwFmtFrmSize aSize(pFmt->GetFrmSize());
612 :
613 6 : Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
614 6 : if (!aRect.IsEmpty())
615 : {
616 6 : aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY());
617 6 : aTextBoxSet.Put(aVertOrient);
618 :
619 6 : aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX());
620 6 : aTextBoxSet.Put(aHoriOrient);
621 :
622 6 : aSize.SetWidth(aRect.getWidth());
623 6 : aSize.SetHeight(aRect.getHeight());
624 6 : aTextBoxSet.Put(aSize);
625 6 : }
626 : }
627 6 : break;
628 : default:
629 : SAL_WARN("sw.core", "SwTextBoxHelper::syncFlyFrmAttr: unhandled which-id: " << nWhich);
630 0 : break;
631 : }
632 :
633 12 : if (aIter.IsAtEnd())
634 12 : break;
635 : }
636 0 : while (0 != (nWhich = aIter.NextItem()->Which()));
637 :
638 12 : if (aTextBoxSet.Count())
639 24 : pFmt->GetDoc()->SetFlyFrmAttr(*pFmt, aTextBoxSet);
640 : }
641 848 : }
642 :
643 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|