LibreOffice Module sw (master)  1
textboxhelper.cxx
Go to the documentation of this file.
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>
18 #include <docsh.hxx>
19 #include <unocoll.hxx>
20 #include <unoframe.hxx>
21 #include <unodraw.hxx>
22 #include <unotextrange.hxx>
23 #include <cmdid.h>
24 #include <unomid.h>
25 #include <unoprnms.hxx>
26 #include <mvsave.hxx>
27 #include <fmtsrnd.hxx>
28 #include <frmfmt.hxx>
29 
30 #include <editeng/unoprnms.hxx>
31 #include <editeng/memberids.h>
32 #include <svx/svdoashp.hxx>
33 #include <svx/svdpage.hxx>
34 #include <svl/itemiter.hxx>
36 #include <sal/log.hxx>
37 
38 #include <com/sun/star/document/XActionLockable.hpp>
39 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 #include <com/sun/star/text/SizeType.hpp>
41 #include <com/sun/star/text/TextContentAnchorType.hpp>
42 #include <com/sun/star/text/WrapTextMode.hpp>
43 #include <com/sun/star/text/XTextDocument.hpp>
44 #include <com/sun/star/table/BorderLine2.hpp>
45 #include <com/sun/star/text/WritingMode.hpp>
46 #include <com/sun/star/text/WritingMode2.hpp>
47 
48 using namespace com::sun::star;
49 
51 {
52  // If TextBox wasn't enabled previously
53  if (pShape->GetAttrSet().HasItem(RES_CNTNT))
54  return;
55 
56  // Create the associated TextFrame and insert it into the document.
57  uno::Reference<text::XTextContent> xTextFrame(
59  uno::UNO_QUERY);
60  uno::Reference<text::XTextDocument> xTextDocument(
61  pShape->GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
62  uno::Reference<text::XTextContentAppend> xTextContentAppend(xTextDocument->getText(),
63  uno::UNO_QUERY);
64  xTextContentAppend->appendTextContent(xTextFrame, uno::Sequence<beans::PropertyValue>());
65 
66  // Link FLY and DRAW formats, so it becomes a text box (needed for syncProperty calls).
67  uno::Reference<text::XTextFrame> xRealTextFrame(xTextFrame, uno::UNO_QUERY);
68  auto pTextFrame = dynamic_cast<SwXTextFrame*>(xRealTextFrame.get());
69  assert(nullptr != pTextFrame);
70  SwFrameFormat* pFormat = pTextFrame->GetFrameFormat();
71 
72  assert(nullptr != dynamic_cast<SwDrawFrameFormat*>(pShape));
73  assert(nullptr != dynamic_cast<SwFlyFrameFormat*>(pFormat));
74 
75  pShape->SetOtherTextBoxFormat(pFormat);
76  pFormat->SetOtherTextBoxFormat(pShape);
77 
78  // Initialize properties.
79  uno::Reference<beans::XPropertySet> xPropertySet(xTextFrame, uno::UNO_QUERY);
80  uno::Any aEmptyBorder = uno::makeAny(table::BorderLine2());
81  xPropertySet->setPropertyValue(UNO_NAME_TOP_BORDER, aEmptyBorder);
82  xPropertySet->setPropertyValue(UNO_NAME_BOTTOM_BORDER, aEmptyBorder);
83  xPropertySet->setPropertyValue(UNO_NAME_LEFT_BORDER, aEmptyBorder);
84  xPropertySet->setPropertyValue(UNO_NAME_RIGHT_BORDER, aEmptyBorder);
85 
86  xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(sal_Int32(100)));
87 
88  xPropertySet->setPropertyValue(UNO_NAME_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
89 
90  xPropertySet->setPropertyValue(UNO_NAME_SURROUND, uno::makeAny(text::WrapTextMode_THROUGH));
91 
92  uno::Reference<container::XNamed> xNamed(xTextFrame, uno::UNO_QUERY);
93  xNamed->setName(pShape->GetDoc()->GetUniqueFrameName());
94 
95  // Link its text range to the original shape.
96  uno::Reference<text::XTextRange> xTextBox(xTextFrame, uno::UNO_QUERY_THROW);
97  SwUnoInternalPaM aInternalPaM(*pShape->GetDoc());
98  if (sw::XTextRangeToSwPaM(aInternalPaM, xTextBox))
99  {
100  SwAttrSet aSet(pShape->GetAttrSet());
101  SwFormatContent aContent(aInternalPaM.GetNode().StartOfSectionNode());
102  aSet.Put(aContent);
103  pShape->SetFormatAttr(aSet);
104  }
105 
106  // Also initialize the properties, which are not constant, but inherited from the shape's ones.
107  uno::Reference<drawing::XShape> xShape(pShape->FindRealSdrObject()->getUnoShape(),
108  uno::UNO_QUERY);
109  syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::makeAny(xShape->getSize()));
110 
111  uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY);
112  syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT,
113  xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT));
114  syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_RELATION,
115  xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION));
116  syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_ORIENT,
117  xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT));
118  syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_RELATION,
119  xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION));
120  syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_POSITION,
121  xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION));
122  syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION,
123  xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION));
124  syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT,
125  xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT));
126  syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0,
127  xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST));
128  text::WritingMode eMode;
129  if (xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_WRITINGMODE) >>= eMode)
130  syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)));
131 }
132 
134 {
135  // If a TextBox was enabled previously
136  if (pShape->GetAttrSet().HasItem(RES_CNTNT))
137  {
138  SwFrameFormat* pFormat = pShape->GetOtherTextBoxFormat();
139 
140  // Unlink the TextBox's text range from the original shape.
141  pShape->ResetFormatAttr(RES_CNTNT);
142 
143  // Delete the associated TextFrame.
144  if (pFormat)
145  pShape->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(pFormat);
146  }
147 }
148 
149 bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType)
150 {
151  assert(nType == RES_FLYFRMFMT || nType == RES_DRAWFRMFMT);
152  if (!pFormat || pFormat->Which() != nType || !pFormat->GetAttrSet().HasItem(RES_CNTNT))
153  return false;
154 
155  sal_uInt16 nOtherType = (pFormat->Which() == RES_FLYFRMFMT) ? sal_uInt16(RES_DRAWFRMFMT)
156  : sal_uInt16(RES_FLYFRMFMT);
157  SwFrameFormat* pOtherFormat = pFormat->GetOtherTextBoxFormat();
158  if (!pOtherFormat)
159  return false;
160 
161  assert(pOtherFormat->Which() == nOtherType);
162  if (pOtherFormat->Which() != nOtherType)
163  return false;
164 
165  const SwFormatContent& rContent = pFormat->GetContent();
166  return pOtherFormat->GetAttrSet().HasItem(RES_CNTNT) && pOtherFormat->GetContent() == rContent;
167 }
168 
169 sal_Int32 SwTextBoxHelper::getCount(SdrPage const* pPage)
170 {
171  sal_Int32 nRet = 0;
172  for (std::size_t i = 0; i < pPage->GetObjCount(); ++i)
173  {
174  SdrObject* p = pPage->GetObj(i);
175  if (p && p->IsTextBox())
176  continue;
177  ++nRet;
178  }
179  return nRet;
180 }
181 
182 sal_Int32 SwTextBoxHelper::getCount(const SwDoc* pDoc)
183 {
184  sal_Int32 nRet = 0;
185  const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
186  for (const auto pFormat : rSpzFrameFormats)
187  {
188  if (isTextBox(pFormat, RES_FLYFRMFMT))
189  ++nRet;
190  }
191  return nRet;
192 }
193 
194 uno::Any SwTextBoxHelper::getByIndex(SdrPage const* pPage, sal_Int32 nIndex)
195 {
196  if (nIndex < 0)
197  throw lang::IndexOutOfBoundsException();
198 
199  SdrObject* pRet = nullptr;
200  sal_Int32 nCount = 0; // Current logical index.
201  for (std::size_t i = 0; i < pPage->GetObjCount(); ++i)
202  {
203  SdrObject* p = pPage->GetObj(i);
204  if (p && p->IsTextBox())
205  continue;
206  if (nCount == nIndex)
207  {
208  pRet = p;
209  break;
210  }
211  ++nCount;
212  }
213 
214  if (!pRet)
215  throw lang::IndexOutOfBoundsException();
216 
217  return uno::makeAny(uno::Reference<drawing::XShape>(pRet->getUnoShape(), uno::UNO_QUERY));
218 }
219 
220 sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject)
221 {
222  if (const SdrPage* pPage = pObject->getSdrPageFromSdrObject())
223  {
224  sal_Int32 nOrder = 0; // Current logical order.
225  for (std::size_t i = 0; i < pPage->GetObjCount(); ++i)
226  {
227  SdrObject* p = pPage->GetObj(i);
228  if (p && p->IsTextBox())
229  continue;
230  if (p == pObject)
231  return nOrder;
232  ++nOrder;
233  }
234  }
235 
236  SAL_WARN("sw.core", "SwTextBoxHelper::getOrdNum: no page or page doesn't contain the object");
237  return pObject->GetOrdNum();
238 }
239 
240 void SwTextBoxHelper::getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough)
241 {
243  if (pShape)
244  rWrapThrough = pShape->GetSurround().GetSurround() == css::text::WrapTextMode_THROUGH;
245 }
246 
248  sal_uInt16 nType)
249 {
250  if (!isTextBox(pFormat, nType))
251  return nullptr;
252  return pFormat->GetOtherTextBoxFormat();
253 }
254 
255 SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XShape> const& xShape)
256 {
257  auto pShape = dynamic_cast<SwXShape*>(xShape.get());
258  if (!pShape)
259  return nullptr;
260 
261  SwFrameFormat* pFormat = pShape->GetFrameFormat();
262  return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT);
263 }
264 
265 template <typename T> static void lcl_queryInterface(const SwFrameFormat* pShape, uno::Any& rAny)
266 {
268  {
269  uno::Reference<T> const xInterface(
270  SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY);
271  rAny <<= xInterface;
272  }
273 }
274 
276 {
277  uno::Any aRet;
278 
280  {
281  lcl_queryInterface<text::XTextAppend>(pShape, aRet);
282  }
283  else if (rType == cppu::UnoType<css::text::XText>::get())
284  {
285  lcl_queryInterface<text::XText>(pShape, aRet);
286  }
287  else if (rType == cppu::UnoType<css::text::XTextRange>::get())
288  {
289  lcl_queryInterface<text::XTextRange>(pShape, aRet);
290  }
291 
292  return aRet;
293 }
294 
296 {
297  tools::Rectangle aRet;
298  aRet.SetEmpty();
299  auto pSdrShape = pShape->FindRealSdrObject();
300  auto pCustomShape = dynamic_cast<SdrObjCustomShape*>(pSdrShape);
301  if (pCustomShape)
302  {
303  // Need to temporarily release the lock acquired in
304  // SdXMLShapeContext::AddShape(), otherwise we get an empty rectangle,
305  // see EnhancedCustomShapeEngine::getTextBounds().
306  uno::Reference<document::XActionLockable> xLockable(pCustomShape->getUnoShape(),
307  uno::UNO_QUERY);
308  sal_Int16 nLocks = 0;
309  if (xLockable.is())
310  nLocks = xLockable->resetActionLocks();
311  pCustomShape->GetTextBounds(aRet);
312  if (nLocks)
313  xLockable->setActionLocks(nLocks);
314  }
315  else if (pSdrShape)
316  {
317  // fallback - get *any* bound rect we can possibly get hold of
318  aRet = pSdrShape->GetCurrentBoundRect();
319  }
320 
321  if (!bAbsolute && pSdrShape)
322  {
323  // Relative, so count the logic (reference) rectangle, see the EnhancedCustomShape2d ctor.
324  Point aPoint(pSdrShape->GetSnapRect().Center());
325  Size aSize(pSdrShape->GetLogicRect().GetSize());
326  aPoint.AdjustX(-(aSize.Width() / 2));
327  aPoint.AdjustY(-(aSize.Height() / 2));
328  tools::Rectangle aLogicRect(aPoint, aSize);
329  aRet.Move(-1 * aLogicRect.Left(), -1 * aLogicRect.Top());
330  }
331 
332  return aRet;
333 }
334 
335 void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, const OUString& rPropertyName,
336  const css::uno::Any& rValue)
337 {
338  if (rPropertyName == "CustomShapeGeometry")
339  {
340  // CustomShapeGeometry changes the textbox position offset and size, so adjust both.
341  syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any());
342 
343  SdrObject* pObject = pShape->FindRealSdrObject();
344  if (pObject)
345  {
346  tools::Rectangle aRectangle(pObject->GetSnapRect());
347  syncProperty(
349  uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Left()))));
350  syncProperty(
352  uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top()))));
353  }
354 
355  SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT);
356  if (!pFormat)
357  return;
358 
359  comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue);
360  auto it = aCustomShapeGeometry.find("TextPreRotateAngle");
361  if (it != aCustomShapeGeometry.end())
362  {
363  auto nTextPreRotateAngle = it->second.get<sal_Int32>();
364  sal_Int16 nDirection = 0;
365  switch (nTextPreRotateAngle)
366  {
367  case -90:
368  nDirection = text::WritingMode2::TB_RL;
369  break;
370  case -270:
371  nDirection = text::WritingMode2::BT_LR;
372  break;
373  }
374 
375  if (nDirection)
376  {
377  syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(nDirection));
378  }
379  }
380  }
381  else if (rPropertyName == UNO_NAME_TEXT_VERT_ADJUST)
382  syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, rValue);
383  else if (rPropertyName == UNO_NAME_TEXT_AUTOGROWHEIGHT)
384  syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, rValue);
385  else if (rPropertyName == UNO_NAME_TEXT_LEFTDIST)
386  syncProperty(pShape, RES_BOX, LEFT_BORDER_DISTANCE, rValue);
387  else if (rPropertyName == UNO_NAME_TEXT_RIGHTDIST)
388  syncProperty(pShape, RES_BOX, RIGHT_BORDER_DISTANCE, rValue);
389  else if (rPropertyName == UNO_NAME_TEXT_UPPERDIST)
390  syncProperty(pShape, RES_BOX, TOP_BORDER_DISTANCE, rValue);
391  else if (rPropertyName == UNO_NAME_TEXT_LOWERDIST)
392  syncProperty(pShape, RES_BOX, BOTTOM_BORDER_DISTANCE, rValue);
393  else if (rPropertyName == UNO_NAME_TEXT_WRITINGMODE)
394  {
395  text::WritingMode eMode;
396  if (rValue >>= eMode)
397  syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)));
398  }
399 }
400 
401 void SwTextBoxHelper::getProperty(SwFrameFormat const* pShape, sal_uInt16 nWID, sal_uInt8 nMemberID,
402  css::uno::Any& rValue)
403 {
404  if (!pShape)
405  return;
406 
407  nMemberID &= ~CONVERT_TWIPS;
408 
409  if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
410  {
411  if (nWID == RES_CHAIN)
412  {
413  switch (nMemberID)
414  {
415  case MID_CHAIN_PREVNAME:
416  case MID_CHAIN_NEXTNAME:
417  {
418  const SwFormatChain& rChain = pFormat->GetChain();
419  rChain.QueryValue(rValue, nMemberID);
420  }
421  break;
422  case MID_CHAIN_NAME:
423  rValue <<= pFormat->GetName();
424  break;
425  }
426  }
427  }
428 }
429 
430 void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uInt8 nMemberID,
431  const css::uno::Any& rValue)
432 {
433  // No shape yet? Then nothing to do, initial properties are set by create().
434  if (!pShape)
435  return;
436 
437  uno::Any aValue(rValue);
438  nMemberID &= ~CONVERT_TWIPS;
439 
440  if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
441  {
442  OUString aPropertyName;
443  bool bAdjustX = false;
444  bool bAdjustY = false;
445  bool bAdjustSize = false;
446  switch (nWID)
447  {
448  case RES_HORI_ORIENT:
449  switch (nMemberID)
450  {
452  aPropertyName = UNO_NAME_HORI_ORIENT;
453  break;
455  aPropertyName = UNO_NAME_HORI_ORIENT_RELATION;
456  break;
458  aPropertyName = UNO_NAME_HORI_ORIENT_POSITION;
459  bAdjustX = true;
460  break;
461  }
462  break;
463  case RES_LR_SPACE:
464  {
465  switch (nMemberID)
466  {
467  case MID_L_MARGIN:
468  aPropertyName = UNO_NAME_LEFT_MARGIN;
469  break;
470  case MID_R_MARGIN:
471  aPropertyName = UNO_NAME_RIGHT_MARGIN;
472  break;
473  }
474  break;
475  }
476  case RES_VERT_ORIENT:
477  switch (nMemberID)
478  {
480  aPropertyName = UNO_NAME_VERT_ORIENT;
481  break;
483  aPropertyName = UNO_NAME_VERT_ORIENT_RELATION;
484  break;
486  aPropertyName = UNO_NAME_VERT_ORIENT_POSITION;
487  bAdjustY = true;
488  break;
489  }
490  break;
491  case RES_FRM_SIZE:
492  switch (nMemberID)
493  {
495  aPropertyName = UNO_NAME_FRAME_ISAUTOMATIC_HEIGHT;
496  break;
498  aPropertyName = UNO_NAME_RELATIVE_HEIGHT_RELATION;
499  break;
501  aPropertyName = UNO_NAME_RELATIVE_WIDTH_RELATION;
502  break;
503  default:
504  aPropertyName = UNO_NAME_SIZE;
505  bAdjustSize = true;
506  break;
507  }
508  break;
509  case RES_ANCHOR:
510  switch (nMemberID)
511  {
513  if (aValue.get<text::TextContentAnchorType>()
514  == text::TextContentAnchorType_AS_CHARACTER)
515  {
516  uno::Reference<beans::XPropertySet> const xPropertySet(
517  SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat),
518  uno::UNO_QUERY);
519  xPropertySet->setPropertyValue(
520  UNO_NAME_SURROUND, uno::makeAny(text::WrapTextMode_THROUGH));
521  return;
522  }
523  break;
524  }
525  break;
526  case FN_TEXT_RANGE:
527  {
528  uno::Reference<text::XTextRange> xRange;
529  rValue >>= xRange;
530  SwUnoInternalPaM aInternalPaM(*pFormat->GetDoc());
531  if (sw::XTextRangeToSwPaM(aInternalPaM, xRange))
532  {
533  SwFormatAnchor aAnchor(pFormat->GetAnchor());
534  aAnchor.SetAnchor(aInternalPaM.Start());
535  pFormat->SetFormatAttr(aAnchor);
536  }
537  }
538  break;
539  case RES_CHAIN:
540  switch (nMemberID)
541  {
542  case MID_CHAIN_PREVNAME:
543  aPropertyName = UNO_NAME_CHAIN_PREV_NAME;
544  break;
545  case MID_CHAIN_NEXTNAME:
546  aPropertyName = UNO_NAME_CHAIN_NEXT_NAME;
547  break;
548  }
549  break;
551  aPropertyName = UNO_NAME_TEXT_VERT_ADJUST;
552  break;
553  case RES_BOX:
554  switch (nMemberID)
555  {
557  aPropertyName = UNO_NAME_LEFT_BORDER_DISTANCE;
558  break;
560  aPropertyName = UNO_NAME_RIGHT_BORDER_DISTANCE;
561  break;
562  case TOP_BORDER_DISTANCE:
563  aPropertyName = UNO_NAME_TOP_BORDER_DISTANCE;
564  break;
566  aPropertyName = UNO_NAME_BOTTOM_BORDER_DISTANCE;
567  break;
568  }
569  break;
570  case RES_OPAQUE:
571  aPropertyName = UNO_NAME_OPAQUE;
572  break;
573  case RES_FRAMEDIR:
574  aPropertyName = UNO_NAME_WRITING_MODE;
575  break;
577  switch (nMemberID)
578  {
579  case MID_ALLOW_OVERLAP:
580  aPropertyName = UNO_NAME_ALLOW_OVERLAP;
581  break;
582  }
583  break;
584  }
585 
586  if (!aPropertyName.isEmpty())
587  {
588  // Position/size should be the text position/size, not the shape one as-is.
589  if (bAdjustX || bAdjustY || bAdjustSize)
590  {
591  tools::Rectangle aRect = getTextRectangle(pShape, /*bAbsolute=*/false);
592  if (!aRect.IsEmpty())
593  {
594  if (bAdjustX || bAdjustY)
595  {
596  sal_Int32 nValue;
597  if (aValue >>= nValue)
598  {
599  if (bAdjustX)
600  nValue += TWIPS_TO_MM(aRect.getX());
601  else if (bAdjustY)
602  nValue += TWIPS_TO_MM(aRect.getY());
603  aValue <<= nValue;
604  }
605  }
606  else if (bAdjustSize)
607  {
608  awt::Size aSize(TWIPS_TO_MM(aRect.getWidth()),
609  TWIPS_TO_MM(aRect.getHeight()));
610  aValue <<= aSize;
611  }
612  }
613  }
614 
615  uno::Reference<beans::XPropertySet> const xPropertySet(
616  SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY);
617  xPropertySet->setPropertyValue(aPropertyName, aValue);
618  }
619  }
620 }
621 
623  std::map<const SwFrameFormat*, const SwFrameFormat*>& rLinks)
624 {
625  for (const auto pFormat : rFormats)
626  {
627  if (SwFrameFormat* pTextBox = getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
628  rLinks[pFormat] = pTextBox;
629  }
630 }
631 
633  std::map<const SwFrameFormat*, SwFormatContent>& rOldContent)
634 {
635  if (pShape->Which() == RES_DRAWFRMFMT)
636  {
637  if (pShape->GetContent().GetContentIdx())
638  rOldContent.insert(std::make_pair(pShape, pShape->GetContent()));
639  pShape->ResetFormatAttr(RES_CNTNT);
640  }
641 }
642 
643 void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrameFormat*>& rNew,
644  SavedLink& rSavedLinks, SavedContent& rResetContent)
645 {
646  std::size_t i = 0;
647  for (const auto& rIt : rOld)
648  {
649  auto aTextBoxIt = rSavedLinks.find(rIt.GetFormat());
650  if (aTextBoxIt != rSavedLinks.end())
651  {
652  std::size_t j = 0;
653  for (const auto& rJt : rOld)
654  {
655  if (rJt.GetFormat() == aTextBoxIt->second)
656  rNew[i]->SetFormatAttr(rNew[j]->GetContent());
657  ++j;
658  }
659  }
660  if (rResetContent.find(rIt.GetFormat()) != rResetContent.end())
661  const_cast<SwFrameFormat*>(rIt.GetFormat())
662  ->SetFormatAttr(rResetContent[rIt.GetFormat()]);
663  ++i;
664  }
665 }
666 
668 {
669  if (SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT))
670  {
671  SfxItemSet aTextBoxSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange);
672 
673  SfxItemIter aIter(rSet);
674  const SfxPoolItem* pItem = aIter.GetCurItem();
675  do
676  {
677  switch (pItem->Which())
678  {
679  case RES_VERT_ORIENT:
680  {
681  auto& rOrient = static_cast<const SwFormatVertOrient&>(*pItem);
682  SwFormatVertOrient aOrient(rOrient);
683 
684  tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
685  if (!aRect.IsEmpty())
686  aOrient.SetPos(aOrient.GetPos() + aRect.getY());
687 
688  aTextBoxSet.Put(aOrient);
689 
690  // restore height (shrunk for extending beyond the page bottom - tdf#91260)
691  SwFormatFrameSize aSize(pFormat->GetFrameSize());
692  if (!aRect.IsEmpty())
693  {
694  aSize.SetHeight(aRect.getHeight());
695  aTextBoxSet.Put(aSize);
696  }
697  }
698  break;
699  case RES_HORI_ORIENT:
700  {
701  auto& rOrient = static_cast<const SwFormatHoriOrient&>(*pItem);
702  SwFormatHoriOrient aOrient(rOrient);
703 
704  tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
705  if (!aRect.IsEmpty())
706  aOrient.SetPos(aOrient.GetPos() + aRect.getX());
707 
708  aTextBoxSet.Put(aOrient);
709  }
710  break;
711  case RES_FRM_SIZE:
712  {
713  // In case the shape got resized, then we need to adjust both
714  // the position and the size of the textbox (e.g. larger
715  // rounded edges of a rectangle -> need to push right/down the
716  // textbox).
717  SwFormatVertOrient aVertOrient(rShape.GetVertOrient());
718  SwFormatHoriOrient aHoriOrient(rShape.GetHoriOrient());
719  SwFormatFrameSize aSize(pFormat->GetFrameSize());
720 
721  tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
722  if (!aRect.IsEmpty())
723  {
724  aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY());
725  aTextBoxSet.Put(aVertOrient);
726 
727  aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX());
728  aTextBoxSet.Put(aHoriOrient);
729 
730  aSize.SetWidth(aRect.getWidth());
731  aSize.SetHeight(aRect.getHeight());
732  aTextBoxSet.Put(aSize);
733  }
734  }
735  break;
736  default:
737  SAL_WARN("sw.core", "SwTextBoxHelper::syncFlyFrameAttr: unhandled which-id: "
738  << pItem->Which());
739  break;
740  }
741 
742  pItem = aIter.NextItem();
743  } while (pItem && (0 != pItem->Which()));
744 
745  if (aTextBoxSet.Count())
746  pFormat->GetDoc()->SetFlyFrameAttr(*pFormat, aTextBoxSet);
747  }
748 }
749 
750 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long getHeight() const
#define MID_CHAIN_NAME
Definition: unomid.h:58
#define RES_FRM_SIZE
Definition: hintids.hxx:289
static css::uno::Any getByIndex(SdrPage const *pPage, sal_Int32 nIndex)
Get a shape by index, excluding TextBoxes.
#define UNO_NAME_HORI_ORIENT_POSITION
Definition: unoprnms.hxx:262
#define UNO_NAME_TEXT_RIGHTDIST
SwDocShell * GetDocShell()
Definition: doc.hxx:1346
#define RES_HORI_ORIENT
Definition: hintids.hxx:303
#define UNO_NAME_BOTTOM_BORDER
Definition: unoprnms.hxx:355
#define UNO_NAME_RELATIVE_HEIGHT_RELATION
Definition: unoprnms.hxx:188
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
Definition: atrfrm.cxx:2040
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:106
static void destroy(SwFrameFormat *pShape)
Destroy a TextBox for a shape.
long getWidth() const
#define UNO_NAME_ALLOW_OVERLAP
Definition: unoprnms.hxx:862
SwTwips GetPos() const
Definition: fmtornt.hxx:92
#define RES_FRAMEDIR
Definition: hintids.hxx:320
#define MID_VERTORIENT_RELATION
Definition: unomid.h:35
static sal_Int32 getOrdNum(const SdrObject *pObject)
Get the order of the shape, excluding TextBoxes.
#define UNO_NAME_TEXT_LOWERDIST
SdrObject * GetObj(size_t nNum) const
Definition: doc.hxx:185
virtual bool IsTextBox() const
size_t GetObjCount() const
OUString GetUniqueFrameName() const
Definition: doclay.cxx:1374
#define RIGHT_BORDER_DISTANCE
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:31
#define UNO_NAME_WRITING_MODE
Definition: unoprnms.hxx:689
#define UNO_NAME_VERT_ORIENT
Definition: unoprnms.hxx:327
#define RES_WRAP_INFLUENCE_ON_OBJPOS
Definition: hintids.hxx:325
#define UNO_NAME_TEXT_UPPERDIST
long getY() const
#define RES_CNTNT
Definition: hintids.hxx:295
EmbeddedObjectRef * pObject
static SwFrameFormat * getOtherTextBoxFormat(const SwFrameFormat *pFormat, sal_uInt16 nType)
If we have an associated TextFrame, then return that.
static void resetLink(SwFrameFormat *pShape, std::map< const SwFrameFormat *, SwFormatContent > &rOldContent)
Reset the shape -> textbox link on the shape, and save it to the map, so it can be restored later...
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:738
std::map< const SwFrameFormat *, const SwFrameFormat * > SavedLink
Maps a draw format to a fly format.
static css::uno::Any queryInterface(const SwFrameFormat *pShape, const css::uno::Type &rType)
Get interface of a shape's TextBox, if there is any.
void Move(long nHorzMoveDelta, long nVertMoveDelta)
virtual const tools::Rectangle & GetSnapRect() const
bool IsEmpty() const
#define UNO_NAME_RELATIVE_WIDTH_RELATION
Definition: unoprnms.hxx:186
#define RES_CHAIN
Definition: hintids.hxx:314
#define UNO_NAME_CHAIN_NEXT_NAME
Definition: unoprnms.hxx:229
virtual css::uno::Reference< css::uno::XInterface > getUnoShape()
#define MID_FRMSIZE_SIZE
Definition: unomid.h:70
SdrPage * getSdrPageFromSdrObject() const
void SetOtherTextBoxFormat(SwFrameFormat *pFormat)
Definition: atrfrm.cxx:2477
static void restoreLinks(std::set< ZSortFly > &rOld, std::vector< SwFrameFormat * > &rNew, SavedLink &rSavedLinks, SavedContent &rResetContent)
Undo the effect of saveLinks() + individual resetLink() calls.
const OUString & GetName() const
Definition: format.hxx:111
int nCount
sal_Int16 const nValue
#define UNO_NAME_SIZE
Definition: unoprnms.hxx:301
virtual void DelLayoutFormat(SwFrameFormat *pFormat)=0
static bool isTextBox(const SwFrameFormat *pFormat, sal_uInt16 nType)
Is the frame format a text box?
Mode eMode
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
#define UNO_NAME_VERT_ORIENT_RELATION
Definition: unoprnms.hxx:330
long Top() const
long getX() const
#define UNO_NAME_TEXT_WRITINGMODE
#define FN_TEXT_RANGE
Definition: cmdid.h:792
bool XTextRangeToSwPaM(SwUnoInternalPaM &rToFill, const uno::Reference< text::XTextRange > &xTextRange)
Definition: unoobj2.cxx:950
css::uno::Reference< css::frame::XModel > GetBaseModel() const
Specific frame formats (frames, DrawObjects).
Definition: docary.hxx:201
#define LEFT_BORDER_DISTANCE
static void saveLinks(const SwFrameFormats &rFormats, std::map< const SwFrameFormat *, const SwFrameFormat * > &rLinks)
Saves the current shape -> textbox links in a map, so they can be restored later. ...
static void lcl_queryInterface(const SwFrameFormat *pShape, uno::Any &rAny)
#define UNO_NAME_HORI_ORIENT
Definition: unoprnms.hxx:258
#define RES_FLYFRMFMT
Definition: hintids.hxx:369
#define MID_CHAIN_NEXTNAME
Definition: unomid.h:57
#define MID_L_MARGIN
#define MID_ANCHOR_ANCHORTYPE
Definition: unomid.h:43
Style of a layout element.
Definition: frmfmt.hxx:57
#define MID_HORIORIENT_POSITION
Definition: unomid.h:40
#define RES_ANCHOR
Definition: hintids.hxx:304
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
#define UNO_NAME_RIGHT_BORDER
Definition: unoprnms.hxx:353
#define UNO_NAME_FILL_TRANSPARENCE
SwFrameFormat * GetOtherTextBoxFormat() const
Definition: frmfmt.hxx:101
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:108
#define RES_VERT_ORIENT
Definition: hintids.hxx:302
#define MID_VERTORIENT_POSITION
Definition: unomid.h:36
int i
void SetPos(SwTwips nNew)
Definition: fmtornt.hxx:60
FlyAnchors.
Definition: fmtanchr.hxx:34
#define BOTTOM_BORDER_DISTANCE
static void getProperty(SwFrameFormat const *pShape, sal_uInt16 nWID, sal_uInt8 nMemberID, css::uno::Any &rValue)
Get a property of the underlying TextFrame.
sal_uInt32 GetOrdNum() const
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
#define UNO_NAME_LEFT_BORDER
Definition: unoprnms.hxx:352
Connection (text flow) between two FlyFrames.
Definition: fmtcnct.hxx:31
#define MID_R_MARGIN
#define MID_FRMSIZE_IS_AUTO_HEIGHT
Definition: unomid.h:77
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
#define UNO_NAME_LEFT_BORDER_DISTANCE
Definition: unoprnms.hxx:357
#define UNO_NAME_CHAIN_PREV_NAME
Definition: unoprnms.hxx:230
bool SetFlyFrameAttr(SwFrameFormat &rFlyFormat, SfxItemSet &rSet)
Definition: docfly.cxx:540
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:404
#define UNO_NAME_RIGHT_MARGIN
Definition: unoprnms.hxx:68
#define RES_LR_SPACE
Definition: hintids.hxx:291
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
#define UNO_NAME_TOP_BORDER
Definition: unoprnms.hxx:354
sal_uInt16 const aFrameFormatSetRange[]
Definition: init.cxx:234
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
#define UNO_NAME_TOP_BORDER_DISTANCE
Definition: unoprnms.hxx:359
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:78
#define UNO_NAME_TEXT_VERT_ADJUST
Definition: unoprnms.hxx:851
#define UNO_NAME_SURROUND
Definition: unoprnms.hxx:308
#define MID_HORIORIENT_ORIENT
Definition: unomid.h:38
#define MID_FRMSIZE_REL_HEIGHT_RELATION
Definition: unomid.h:88
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:650
#define MID_CHAIN_PREVNAME
Definition: unomid.h:56
const SwFormatChain & GetChain(bool=true) const
Definition: fmtcnct.hxx:70
std::map< const SwFrameFormat *, SwFormatContent > SavedContent
Maps a draw format to content.
iterator find(const OUString &rKey)
Any makeAny(Color const &value)
#define UNO_NAME_LEFT_MARGIN
Definition: unoprnms.hxx:67
#define RES_DRAWFRMFMT
Definition: hintids.hxx:372
#define MID_VERTORIENT_ORIENT
Definition: unomid.h:34
unsigned char sal_uInt8
static void create(SwFrameFormat *pShape)
Create a TextBox for a shape.
#define UNO_NAME_BOTTOM_BORDER_DISTANCE
Definition: unoprnms.hxx:360
SwTwips GetPos() const
Definition: fmtornt.hxx:59
#define UNO_NAME_TEXT_LEFTDIST
#define MID_FRMSIZE_REL_WIDTH_RELATION
Definition: unomid.h:87
#define RES_OPAQUE
Definition: hintids.hxx:299
#define TWIPS_TO_MM(val)
#define UNO_NAME_HORI_ORIENT_RELATION
Definition: unoprnms.hxx:261
static SW_DLLPUBLIC css::uno::Reference< css::text::XTextFrame > CreateXTextFrame(SwDoc &rDoc, SwFrameFormat *pFrameFormat)
Definition: unoframe.cxx:3153
#define TOP_BORDER_DISTANCE
bool HasItem(sal_uInt16 nWhich, const SfxPoolItem **ppItem=nullptr) const
#define UNO_NAME_TEXT_AUTOGROWHEIGHT
void * p
void SetHeight(long n)
static css::uno::Reference< css::uno::XInterface > MakeInstance(SwServiceType nObjectType, SwDoc &rDoc)
Definition: unocoll.cxx:510
bool GetTextBounds(tools::Rectangle &rTextBound) const
static sal_Int32 getCount(const SwDoc *pDoc)
Count number of shapes in the document, excluding TextBoxes.
static tools::Rectangle getTextRectangle(SwFrameFormat *pShape, bool bAbsolute=true)
Return the textbox rectangle of a draw shape (in twips).
long Left() const
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
void SetPos(SwTwips nNew)
Definition: fmtornt.hxx:93
#define UNO_NAME_FRAME_ISAUTOMATIC_HEIGHT
Definition: unoprnms.hxx:589
#define MID_HORIORIENT_RELATION
Definition: unomid.h:39
#define RES_BOX
Definition: hintids.hxx:306
static void syncFlyFrameAttr(SwFrameFormat &rShape, SfxItemSet const &rSet)
Similar to syncProperty(), but used by the internal API (e.g. for UI purposes).
constexpr sal_Int64 convertTwipToMm100(sal_Int64 n)
#define SAL_WARN(area, stream)
static void syncProperty(SwFrameFormat *pShape, sal_uInt16 nWID, sal_uInt8 nMemberID, const css::uno::Any &rValue)
Sync property of TextBox with the one of the shape.
#define UNO_NAME_SIZE_TYPE
Definition: unoprnms.hxx:256
#define UNO_NAME_RIGHT_BORDER_DISTANCE
Definition: unoprnms.hxx:358
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
#define UNO_NAME_VERT_ORIENT_POSITION
Definition: unoprnms.hxx:329
#define UNO_NAME_OPAQUE
Definition: unoprnms.hxx:280
sal_uInt16 Which() const
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2700
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1313
#define RES_TEXT_VERT_ADJUST
Definition: hintids.hxx:330
#define MID_ALLOW_OVERLAP
Definition: unomid.h:149
void SetAnchor(const SwPosition *pPos)
Definition: atrfrm.cxx:1477
#define CONVERT_TWIPS
static void getShapeWrapThrough(const SwFrameFormat *pTextBox, bool &rWrapThrough)
If pTextBox is a textbox, then set rWrapThrough to the surround of its shape.