LCOV - code coverage report
Current view: top level - sw/source/core/doc - textboxhelper.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 346 368 94.0 %
Date: 2015-06-13 12:38:46 Functions: 26 26 100.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.11