summaryrefslogtreecommitdiffstats
path: root/sw/source/core/unocore/unodraw.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/unocore/unodraw.cxx')
-rw-r--r--sw/source/core/unocore/unodraw.cxx2876
1 files changed, 2876 insertions, 0 deletions
diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx
new file mode 100644
index 0000000000..5bb5621d95
--- /dev/null
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -0,0 +1,2876 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <initializer_list>
+#include <memory>
+#include <string_view>
+
+#include <sal/log.hxx>
+
+#include <cmdid.h>
+#include <unomid.h>
+
+#include <drawdoc.hxx>
+#include <unodraw.hxx>
+#include <unoframe.hxx>
+#include <unoparagraph.hxx>
+#include <unotextrange.hxx>
+#include <svx/svditer.hxx>
+#include <swunohelper.hxx>
+#include <textboxhelper.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtflcnt.hxx>
+#include <txatbase.hxx>
+#include <docsh.hxx>
+#include <unomap.hxx>
+#include <unoport.hxx>
+#include <TextCursorHelper.hxx>
+#include <dflyobj.hxx>
+#include <ndtxt.hxx>
+#include <svx/svdview.hxx>
+#include <svx/unoshape.hxx>
+#include <dcontact.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <rootfrm.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <crstate.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/profilezone.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <svx/scene3d.hxx>
+#include <tools/UnitConversion.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <docmodel/uno/UnoTheme.hxx>
+
+using namespace ::com::sun::star;
+
+class SwShapeDescriptor_Impl
+{
+ bool m_isInReading;
+ std::unique_ptr<SwFormatHoriOrient> m_pHOrient;
+ std::unique_ptr<SwFormatVertOrient> m_pVOrient;
+ std::unique_ptr<SwFormatAnchor> m_pAnchor;
+ std::unique_ptr<SwFormatSurround> m_pSurround;
+ std::unique_ptr<SvxULSpaceItem> m_pULSpace;
+ std::unique_ptr<SvxLRSpaceItem> m_pLRSpace;
+ bool m_bOpaque;
+ uno::Reference< text::XTextRange > m_xTextRange;
+ // #i26791#
+ std::unique_ptr<SwFormatFollowTextFlow> m_pFollowTextFlow;
+ // #i28701#
+ std::unique_ptr<SwFormatWrapInfluenceOnObjPos> m_pWrapInfluenceOnObjPos;
+ // #i28749#
+ sal_Int16 mnPositionLayoutDir;
+
+ SwShapeDescriptor_Impl(const SwShapeDescriptor_Impl&) = delete;
+ SwShapeDescriptor_Impl& operator=(const SwShapeDescriptor_Impl&) = delete;
+
+public:
+ SwShapeDescriptor_Impl(SwDoc const*const pDoc)
+ : m_isInReading(pDoc && pDoc->IsInReading())
+ // #i32349# - no defaults, in order to determine on
+ // adding a shape, if positioning attributes are set or not.
+ , m_bOpaque(false)
+ // #i26791#
+ , m_pFollowTextFlow( new SwFormatFollowTextFlow(false) )
+ // #i28701# #i35017#
+ , m_pWrapInfluenceOnObjPos( new SwFormatWrapInfluenceOnObjPos(
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT) )
+ // #i28749#
+ , mnPositionLayoutDir(text::PositionLayoutDir::PositionInLayoutDirOfAnchor)
+ {}
+
+ SwFormatAnchor* GetAnchor(bool bCreate = false)
+ {
+ if (bCreate && !m_pAnchor)
+ {
+ m_pAnchor.reset(new SwFormatAnchor(RndStdIds::FLY_AS_CHAR));
+ }
+ return m_pAnchor.get();
+ }
+ SwFormatHoriOrient* GetHOrient(bool bCreate = false)
+ {
+ if (bCreate && !m_pHOrient)
+ {
+ // #i26791#
+ m_pHOrient.reset(new SwFormatHoriOrient(0, text::HoriOrientation::NONE, text::RelOrientation::FRAME));
+ }
+ return m_pHOrient.get();
+ }
+ SwFormatVertOrient* GetVOrient(bool bCreate = false)
+ {
+ if (bCreate && !m_pVOrient)
+ {
+ if (m_isInReading && // tdf#113938 extensions might rely on old default
+ (!GetAnchor(true) || m_pAnchor->GetAnchorId() == RndStdIds::FLY_AS_CHAR))
+ { // for as-char, NONE ("from-top") is not a good default
+ m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::TOP, text::RelOrientation::FRAME));
+ }
+ else
+ { // #i26791#
+ m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::NONE, text::RelOrientation::FRAME));
+ }
+ }
+ return m_pVOrient.get();
+ }
+
+ SwFormatSurround* GetSurround(bool bCreate = false)
+ {
+ if (bCreate && !m_pSurround)
+ {
+ m_pSurround.reset(new SwFormatSurround());
+ }
+ return m_pSurround.get();
+ }
+ SvxLRSpaceItem* GetLRSpace(bool bCreate = false)
+ {
+ if (bCreate && !m_pLRSpace)
+ {
+ m_pLRSpace.reset(new SvxLRSpaceItem(RES_LR_SPACE));
+ }
+ return m_pLRSpace.get();
+ }
+ SvxULSpaceItem* GetULSpace(bool bCreate = false)
+ {
+ if (bCreate && !m_pULSpace)
+ {
+ m_pULSpace.reset(new SvxULSpaceItem(RES_UL_SPACE));
+ }
+ return m_pULSpace.get();
+ }
+ uno::Reference< text::XTextRange > & GetTextRange()
+ {
+ return m_xTextRange;
+ }
+ bool IsOpaque() const
+ {
+ return m_bOpaque;
+ }
+ const bool& GetOpaque() const
+ {
+ return m_bOpaque;
+ }
+ void RemoveHOrient() { m_pHOrient.reset(); }
+ void RemoveVOrient() { m_pVOrient.reset(); }
+ void RemoveAnchor() { m_pAnchor.reset(); }
+ void RemoveSurround() { m_pSurround.reset(); }
+ void RemoveULSpace() { m_pULSpace.reset(); }
+ void RemoveLRSpace() { m_pLRSpace.reset(); }
+ void SetOpaque(bool bSet){m_bOpaque = bSet;}
+
+ // #i26791#
+ SwFormatFollowTextFlow* GetFollowTextFlow( bool _bCreate = false )
+ {
+ if (_bCreate && !m_pFollowTextFlow)
+ {
+ m_pFollowTextFlow.reset(new SwFormatFollowTextFlow(false));
+ }
+ return m_pFollowTextFlow.get();
+ }
+ void RemoveFollowTextFlow()
+ {
+ m_pFollowTextFlow.reset();
+ }
+
+ // #i28749#
+ sal_Int16 GetPositionLayoutDir() const
+ {
+ return mnPositionLayoutDir;
+ }
+ void SetPositionLayoutDir( sal_Int16 _nPositionLayoutDir )
+ {
+ switch ( _nPositionLayoutDir )
+ {
+ case text::PositionLayoutDir::PositionInHoriL2R:
+ case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
+ {
+ mnPositionLayoutDir = _nPositionLayoutDir;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwShapeDescriptor_Impl::SetPositionLayoutDir(..)> - invalid attribute value." );
+ }
+ }
+ }
+
+ // #i28701#
+ SwFormatWrapInfluenceOnObjPos* GetWrapInfluenceOnObjPos(
+ const bool _bCreate = false )
+ {
+ if (_bCreate && !m_pWrapInfluenceOnObjPos)
+ {
+ m_pWrapInfluenceOnObjPos.reset(new SwFormatWrapInfluenceOnObjPos(
+ // #i35017#
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT));
+ }
+ return m_pWrapInfluenceOnObjPos.get();
+ }
+ void RemoveWrapInfluenceOnObjPos()
+ {
+ m_pWrapInfluenceOnObjPos.reset();
+ }
+};
+
+SwFmDrawPage::SwFmDrawPage( SwDoc* pDoc, SdrPage* pPage )
+ : SwFmDrawPage_Base(pPage)
+ , m_pDoc(pDoc)
+ , m_pPageView(nullptr)
+ , m_pPropertySet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_PAGE))
+{
+}
+
+SwFmDrawPage::~SwFmDrawPage() noexcept
+{
+ while (!m_vShapes.empty())
+ m_vShapes.back()->dispose();
+ RemovePageView();
+}
+
+const SdrMarkList& SwFmDrawPage::PreGroup(const uno::Reference< drawing::XShapes > & xShapes)
+{
+ SelectObjectsInView( xShapes, GetPageView() );
+ const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
+ return rMarkList;
+}
+
+void SwFmDrawPage::PreUnGroup(const uno::Reference< drawing::XShapeGroup >& rShapeGroup)
+{
+ SelectObjectInView( rShapeGroup, GetPageView() );
+}
+
+SdrPageView* SwFmDrawPage::GetPageView()
+{
+ if(!m_pPageView)
+ m_pPageView = mpView->ShowSdrPage( mpPage );
+ return m_pPageView;
+}
+
+void SwFmDrawPage::RemovePageView()
+{
+ if(m_pPageView && mpView)
+ mpView->HideSdrPage();
+ m_pPageView = nullptr;
+}
+
+uno::Reference<drawing::XShape> SwFmDrawPage::GetShape(SdrObject* pObj)
+{
+ if(!pObj)
+ return nullptr;
+ SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
+ // TODO see comment at
+ // <https://gerrit.libreoffice.org/c/core/+/78734/4#message-5ee4e724a8073c5c475f07da0b5d79bc34e61de5>
+ // "make page bookkeep the SwXShapes" [-loplugin:crosscast]:
+ SwFmDrawPage* pPage = dynamic_cast<SwFmDrawPage*>(pFormat);
+ if(!pPage || pPage->m_vShapes.empty())
+ return uno::Reference<drawing::XShape>(pObj->getUnoShape(), uno::UNO_QUERY);
+ for(const auto & pShape : pPage->m_vShapes)
+ {
+ SvxShape* pSvxShape = pShape->GetSvxShape();
+ if (pSvxShape && pSvxShape->GetSdrObject() == pObj)
+ return pShape;
+ }
+ return nullptr;
+}
+
+uno::Reference<drawing::XShapeGroup> SwFmDrawPage::GetShapeGroup(SdrObject* pObj)
+{
+ return uno::Reference<drawing::XShapeGroup>(GetShape(pObj), uno::UNO_QUERY);
+}
+
+uno::Reference< drawing::XShape > SwFmDrawPage::CreateShape( SdrObject *pObj ) const
+{
+ uno::Reference< drawing::XShape > xRet;
+ if(dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr || pObj->GetObjInventor() == SdrInventor::Swg)
+ {
+ SwFlyDrawContact* pFlyContact = static_cast<SwFlyDrawContact*>(pObj->GetUserCall());
+ if(pFlyContact)
+ {
+ SwFrameFormat* pFlyFormat = pFlyContact->GetFormat();
+ SwDoc* pDoc = pFlyFormat->GetDoc();
+ const SwNodeIndex* pIdx;
+ if( RES_FLYFRMFMT == pFlyFormat->Which()
+ && nullptr != ( pIdx = pFlyFormat->GetContent().GetContentIdx() )
+ && pIdx->GetNodes().IsDocNodes()
+ )
+ {
+ const SwNode* pNd = pDoc->GetNodes()[ pIdx->GetIndex() + 1 ];
+ if(!pNd->IsNoTextNode())
+ {
+ xRet.set(cppu::getXWeak(SwXTextFrame::CreateXTextFrame(*pDoc, pFlyFormat).get()),
+ uno::UNO_QUERY);
+ }
+ else if( pNd->IsGrfNode() )
+ {
+ xRet.set(cppu::getXWeak(SwXTextGraphicObject::CreateXTextGraphicObject(
+ *pDoc, pFlyFormat).get()), uno::UNO_QUERY);
+ }
+ else if( pNd->IsOLENode() )
+ {
+ xRet.set(cppu::getXWeak(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
+ *pDoc, pFlyFormat).get()), uno::UNO_QUERY);
+ }
+ }
+ else
+ {
+ OSL_FAIL( "<SwFmDrawPage::CreateShape(..)> - could not retrieve type. Thus, no shape created." );
+ return xRet;
+ }
+ }
+ }
+ else
+ {
+ // own block - temporary object has to be destroyed before
+ // the delegator is set #81670#
+ {
+ xRet = SvxDrawPage::CreateShape( pObj );
+ }
+ uno::Reference< XUnoTunnel > xShapeTunnel(xRet, uno::UNO_QUERY);
+ //don't create an SwXShape if it already exists
+ rtl::Reference<SwXShape> pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
+ if(!pShape)
+ {
+ xShapeTunnel = nullptr;
+ uno::Reference< uno::XInterface > xCreate(xRet, uno::UNO_QUERY);
+ xRet = nullptr;
+ if ( pObj->IsGroupObject() && (!pObj->Is3DObj() || DynCastE3dScene(pObj)) )
+ pShape = new SwXGroupShape(xCreate, nullptr);
+ else
+ pShape = new SwXShape(xCreate, nullptr);
+ xRet = pShape;
+ }
+ const_cast<std::vector<rtl::Reference<SwXShape>>*>(&m_vShapes)->push_back(pShape);
+ pShape->m_pPage = this;
+ }
+ return xRet;
+}
+
+uno::Reference<beans::XPropertySetInfo> SwFmDrawPage::getPropertySetInfo()
+{
+ static uno::Reference<beans::XPropertySetInfo> xRet = m_pPropertySet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwFmDrawPage::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName(rPropertyName);
+
+ switch (pEntry ? pEntry->nWID : -1)
+ {
+ case WID_PAGE_THEME:
+ {
+ SdrPage* pPage = GetSdrPage();
+ css::uno::Reference<css::util::XTheme> xTheme;
+ if (aValue >>= xTheme)
+ {
+ auto& rUnoTheme = dynamic_cast<UnoTheme&>(*xTheme);
+ pPage->getSdrModelFromSdrPage().setTheme(rUnoTheme.getTheme());
+ }
+ }
+ break;
+ case WID_PAGE_BOTTOM:
+ case WID_PAGE_LEFT:
+ case WID_PAGE_RIGHT:
+ case WID_PAGE_TOP:
+ case WID_PAGE_WIDTH:
+ case WID_PAGE_HEIGHT:
+ case WID_PAGE_NUMBER:
+ case WID_PAGE_ORIENT:
+ case WID_PAGE_USERATTRIBS:
+ case WID_PAGE_ISDARK:
+ case WID_NAVORDER:
+ case WID_PAGE_BACKFULL:
+ break;
+
+ default:
+ throw beans::UnknownPropertyException(rPropertyName, getXWeak());
+ }
+}
+
+uno::Any SwFmDrawPage::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName( rPropertyName);
+
+ uno::Any aAny;
+
+ switch (pEntry ? pEntry->nWID : -1)
+ {
+ case WID_PAGE_THEME:
+ {
+ css::uno::Reference<css::util::XTheme> xTheme;
+
+ auto pTheme = GetSdrPage()->getSdrModelFromSdrPage().getTheme();
+ if (pTheme)
+ xTheme = model::theme::createXTheme(pTheme);
+ aAny <<= xTheme;
+ }
+ break;
+
+ case WID_PAGE_NUMBER:
+ {
+ const sal_uInt16 nPageNumber(GetSdrPage()->GetPageNum());
+ aAny <<= o3tl::narrowing<sal_Int16>(nPageNumber);
+ }
+ break;
+
+ case WID_PAGE_BOTTOM:
+ case WID_PAGE_LEFT:
+ case WID_PAGE_RIGHT:
+ case WID_PAGE_TOP:
+ case WID_PAGE_WIDTH:
+ case WID_PAGE_HEIGHT:
+ case WID_PAGE_ORIENT:
+ case WID_PAGE_USERATTRIBS:
+ case WID_PAGE_ISDARK:
+ case WID_NAVORDER:
+ case WID_PAGE_BACKFULL:
+ break;
+
+ default:
+ throw beans::UnknownPropertyException(rPropertyName, getXWeak());
+ }
+ return aAny;
+}
+
+void SwFmDrawPage::addPropertyChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwFmDrawPage::removePropertyChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwFmDrawPage::addVetoableChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwFmDrawPage::removeVetoableChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+namespace
+{
+ class SwXShapesEnumeration
+ : public SwSimpleEnumeration_Base
+ {
+ private:
+ std::vector< css::uno::Any > m_aShapes;
+ protected:
+ virtual ~SwXShapesEnumeration() override {};
+ public:
+ explicit SwXShapesEnumeration(SwFmDrawPage* const pDrawPage);
+
+ //XEnumeration
+ virtual sal_Bool SAL_CALL hasMoreElements() override;
+ virtual uno::Any SAL_CALL nextElement() override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+ };
+}
+
+SwXShapesEnumeration::SwXShapesEnumeration(SwFmDrawPage* const pDrawPage)
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nCount = pDrawPage->getCount();
+ m_aShapes.reserve(nCount);
+ for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
+ {
+ uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
+ m_aShapes.push_back(uno::Any(xShape));
+ }
+}
+
+sal_Bool SwXShapesEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+ return !m_aShapes.empty();
+}
+
+uno::Any SwXShapesEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+ if(m_aShapes.empty())
+ throw container::NoSuchElementException();
+ uno::Any aResult = m_aShapes.back();
+ m_aShapes.pop_back();
+ return aResult;
+}
+
+OUString SwXShapesEnumeration::getImplementationName()
+{
+ return "SwXShapeEnumeration";
+}
+
+sal_Bool SwXShapesEnumeration::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SwXShapesEnumeration::getSupportedServiceNames()
+{
+ return { OUString("com.sun.star.container.XEnumeration") };
+}
+
+uno::Reference< container::XEnumeration > SwFmDrawPage::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ return uno::Reference< container::XEnumeration >(
+ new SwXShapesEnumeration(this));
+}
+
+OUString SwFmDrawPage::getImplementationName()
+{
+ return "SwFmDrawPage";
+}
+
+sal_Bool SwFmDrawPage::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwFmDrawPage::getSupportedServiceNames()
+{
+ return { "com.sun.star.drawing.GenericDrawPage" };
+}
+
+sal_Int32 SwFmDrawPage::getCount()
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc)
+ throw uno::RuntimeException();
+ if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
+ return 0;
+ else
+ return SwTextBoxHelper::getCount(GetSdrPage());
+}
+
+uno::Any SwFmDrawPage::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc)
+ throw uno::RuntimeException();
+ if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
+ throw lang::IndexOutOfBoundsException();
+
+ return SwTextBoxHelper::getByIndex(GetSdrPage(), nIndex);
+}
+
+uno::Type SwFmDrawPage::getElementType()
+{
+ return cppu::UnoType<drawing::XShape>::get();
+}
+
+sal_Bool SwFmDrawPage::hasElements()
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc)
+ throw uno::RuntimeException();
+ if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
+ return false;
+ return SvxDrawPage::hasElements();
+}
+
+void SwFmDrawPage::add(const uno::Reference< drawing::XShape > & xShape)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc)
+ throw uno::RuntimeException();
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShape, uno::UNO_QUERY);
+ SwXShape* pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
+ SvxShape* pSvxShape = comphelper::getFromUnoTunnel<SvxShape>(xShapeTunnel);
+
+ // this is not a writer shape
+ if(!pShape)
+ throw uno::RuntimeException("illegal object",
+ getXWeak() );
+
+ // we're already registered in the model / SwXDrawPage::add() already called
+ if(pShape->m_pPage || !pShape->m_bDescriptor )
+ return;
+
+ // we're inserted elsewhere already
+ if ( pSvxShape->GetSdrObject() )
+ {
+ if ( pSvxShape->GetSdrObject()->IsInserted() )
+ {
+ return;
+ }
+ }
+ SvxDrawPage::add(xShape);
+
+ OSL_ENSURE(pSvxShape, "Why is here no SvxShape?");
+ // this position is definitely in 1/100 mm
+ awt::Point aMM100Pos(pSvxShape->getPosition());
+
+ // now evaluate the properties of SwShapeDescriptor_Impl
+ SwShapeDescriptor_Impl* pDesc = pShape->GetDescImpl();
+
+ SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSet( m_pDoc->GetAttrPool() );
+ SwFormatAnchor aAnchor( RndStdIds::FLY_AS_CHAR );
+ bool bOpaque = false;
+ if( pDesc )
+ {
+ if(pDesc->GetSurround())
+ aSet.Put( *pDesc->GetSurround());
+ // all items are already in Twip
+ if(pDesc->GetLRSpace())
+ {
+ aSet.Put(*pDesc->GetLRSpace());
+ }
+ if(pDesc->GetULSpace())
+ {
+ aSet.Put(*pDesc->GetULSpace());
+ }
+ if(pDesc->GetAnchor())
+ aAnchor = *pDesc->GetAnchor();
+
+ // #i32349# - if no horizontal position exists, create one
+ if ( !pDesc->GetHOrient() )
+ {
+ SwFormatHoriOrient* pHori = pDesc->GetHOrient( true );
+ SwTwips nHoriPos = o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100);
+ pHori->SetPos( nHoriPos );
+ }
+ {
+ if(pDesc->GetHOrient()->GetHoriOrient() == text::HoriOrientation::NONE)
+ aMM100Pos.X = convertTwipToMm100(pDesc->GetHOrient()->GetPos());
+ aSet.Put( *pDesc->GetHOrient() );
+ }
+ // #i32349# - if no vertical position exists, create one
+ if ( !pDesc->GetVOrient() )
+ {
+ SwFormatVertOrient* pVert = pDesc->GetVOrient( true );
+ SwTwips nVertPos = o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100);
+ pVert->SetPos( nVertPos );
+ }
+ {
+ if(pDesc->GetVOrient()->GetVertOrient() == text::VertOrientation::NONE)
+ aMM100Pos.Y = convertTwipToMm100(pDesc->GetVOrient()->GetPos());
+ aSet.Put( *pDesc->GetVOrient() );
+ }
+
+ if(pDesc->GetSurround())
+ aSet.Put( *pDesc->GetSurround());
+ bOpaque = pDesc->IsOpaque();
+
+ // #i26791#
+ if ( pDesc->GetFollowTextFlow() )
+ {
+ aSet.Put( *pDesc->GetFollowTextFlow() );
+ }
+
+ // #i28701#
+ if ( pDesc->GetWrapInfluenceOnObjPos() )
+ {
+ aSet.Put( *pDesc->GetWrapInfluenceOnObjPos() );
+ }
+ }
+
+ pSvxShape->setPosition(aMM100Pos);
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ // #108784# - set layer of new drawing object to corresponding
+ // invisible layer.
+ if(SdrInventor::FmForm != pObj->GetObjInventor())
+ pObj->SetLayer( bOpaque ? m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() : m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
+ else
+ pObj->SetLayer(m_pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
+
+ std::optional<SwPaM> pPam(m_pDoc->GetNodes().GetEndOfContent());
+ std::unique_ptr<SwUnoInternalPaM> pInternalPam;
+ uno::Reference< text::XTextRange > xRg;
+ if( pDesc && (xRg = pDesc->GetTextRange()).is() )
+ {
+ pInternalPam.reset(new SwUnoInternalPaM(*m_pDoc));
+ if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg))
+ throw uno::RuntimeException();
+
+ if(RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId() &&
+ !pInternalPam->GetPointNode().FindFlyStartNode())
+ {
+ aAnchor.SetType(RndStdIds::FLY_AS_CHAR);
+ }
+ else if (RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId()
+ && 0 == aAnchor.GetPageNum())
+ {
+ aAnchor.SetAnchor(pInternalPam->Start());
+ aAnchor.SetType(RndStdIds::FLY_AT_CHAR); // convert invalid at-page
+ }
+
+ }
+ else if ((aAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
+ {
+ SwCursorMoveState aState( CursorMoveState::SetOnlyText );
+ Point aTmp(o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100), o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100));
+ m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( pPam->GetPoint(), aTmp, &aState );
+ aAnchor.SetAnchor( pPam->GetPoint() );
+
+ // #i32349# - adjustment of vertical positioning
+ // attributes no longer needed, because it's already got a default.
+ }
+ else
+ {
+ aAnchor.SetType(RndStdIds::FLY_AT_PAGE);
+
+ // #i32349# - adjustment of vertical positioning
+ // attributes no longer needed, because it's already got a default.
+ }
+ aSet.Put(aAnchor);
+ SwPaM* pTemp = pInternalPam.get();
+ if ( !pTemp )
+ pTemp = &*pPam;
+ UnoActionContext aAction(m_pDoc);
+ m_pDoc->getIDocumentContentOperations().InsertDrawObj( *pTemp, *pObj, aSet );
+
+ if (pSvxShape->GetSdrObject()->GetName().isEmpty())
+ {
+ pSvxShape->GetSdrObject()->SetName(m_pDoc->GetUniqueShapeName());
+ }
+
+ SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
+ if (pFormat)
+ {
+ if (pFormat->GetName().isEmpty())
+ {
+ pFormat->SetFormatName(pSvxShape->GetSdrObject()->GetName(), false);
+ }
+ }
+ pShape->m_bDescriptor = false;
+
+ pPam.reset();
+ pInternalPam.reset();
+}
+
+void SwFmDrawPage::remove(const uno::Reference< drawing::XShape > & xShape)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc)
+ throw uno::RuntimeException();
+ // tdf#41466 remove TextFrame too which is belonged to the actual shape
+ auto xTextFrame = SwTextBoxHelper::getUnoTextFrame(xShape);
+ if (xTextFrame)
+ {
+ uno::Reference<lang::XComponent> xComp(xTextFrame, uno::UNO_QUERY);
+ if (xComp)
+ xComp->dispose();
+ }
+ // remove shape
+ uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
+ xComp->dispose();
+}
+
+uno::Reference< drawing::XShapeGroup > SwFmDrawPage::group(const uno::Reference< drawing::XShapes > & xShapes)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc || !xShapes.is())
+ throw uno::RuntimeException();
+ uno::Reference< drawing::XShapeGroup > xRet;
+ // mark and return MarkList
+ const SdrMarkList& rMarkList = PreGroup(xShapes);
+ if ( rMarkList.GetMarkCount() > 0 )
+ {
+ for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
+ {
+ const SdrObject *pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
+ if (RndStdIds::FLY_AS_CHAR == ::FindFrameFormat(const_cast<SdrObject*>(
+ pObj))->GetAnchor().GetAnchorId())
+ {
+ throw lang::IllegalArgumentException(
+ "Shape must not have 'as character' anchor!", nullptr, 0);
+ }
+ }
+
+ UnoActionContext aContext(m_pDoc);
+ m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
+
+ SwDrawContact* pContact = m_pDoc->GroupSelection( *GetDrawView() );
+ m_pDoc->ChgAnchor(
+ GetDrawView()->GetMarkedObjectList(),
+ RndStdIds::FLY_AT_PARA,
+ true, false );
+
+ GetDrawView()->UnmarkAll();
+ if(pContact)
+ xRet = SwFmDrawPage::GetShapeGroup( pContact->GetMaster() );
+ m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
+ }
+ RemovePageView();
+ return xRet;
+}
+
+void SwFmDrawPage::ungroup(const uno::Reference< drawing::XShapeGroup > & rShapeGroup)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDoc)
+ throw uno::RuntimeException();
+
+ PreUnGroup(rShapeGroup);
+ UnoActionContext aContext(m_pDoc);
+ m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
+
+ m_pDoc->UnGroupSelection( *GetDrawView() );
+ m_pDoc->ChgAnchor( GetDrawView()->GetMarkedObjectList(),
+ RndStdIds::FLY_AT_PARA,
+ true, false );
+ m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
+ RemovePageView();
+}
+
+/**
+ * Renamed and outlined to detect where it's called
+ */
+void SwFmDrawPage::InvalidateSwDoc()
+{
+ m_pDoc = nullptr;
+}
+
+const uno::Sequence< sal_Int8 > & SwXShape::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit theSwXShapeUnoTunnelId;
+ return theSwXShapeUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SwXShape::getSomething( const uno::Sequence< sal_Int8 >& rId )
+{
+ if( comphelper::isUnoTunnelId<SwXShape>(rId) )
+ {
+ return comphelper::getSomething_cast(this);
+ }
+
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rTunnelType );
+ if(auto xAggTunnel = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
+ aAgg))
+ {
+ if(xAggTunnel->is())
+ return (*xAggTunnel)->getSomething(rId);
+ }
+ }
+ return 0;
+}
+
+SwXShape::SwXShape(
+ uno::Reference<uno::XInterface> & xShape,
+ SwDoc const*const pDoc)
+ : m_pPage(nullptr)
+ , m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SHAPE))
+ , m_pPropertyMapEntries(aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_TEXT_SHAPE))
+ , m_pImpl(new SwShapeDescriptor_Impl(pDoc))
+ , m_bDescriptor(true)
+{
+ if(!xShape.is()) // default Ctor
+ return;
+
+ const uno::Type& rAggType = cppu::UnoType<uno::XAggregation>::get();
+ //aAgg contains a reference of the SvxShape!
+ {
+ uno::Any aAgg = xShape->queryInterface(rAggType);
+ aAgg >>= m_xShapeAgg;
+ // #i31698#
+ if ( m_xShapeAgg.is() )
+ {
+ m_xShapeAgg->queryAggregation( cppu::UnoType<drawing::XShape>::get()) >>= mxShape;
+ OSL_ENSURE( mxShape.is(),
+ "<SwXShape::SwXShape(..)> - no XShape found at <xShapeAgg>" );
+ }
+ }
+ xShape = nullptr;
+ osl_atomic_increment(&m_refCount);
+ if( m_xShapeAgg.is() )
+ m_xShapeAgg->setDelegator( getXWeak() );
+ osl_atomic_decrement(&m_refCount);
+}
+
+SwFrameFormat* SwXShape::GetFrameFormat() const
+{
+ SdrObject* pObj = SdrObject::getSdrObjectFromXShape(m_xShapeAgg);
+ if(pObj)
+ return ::FindFrameFormat( pObj );
+ return nullptr;
+}
+
+void SwXShape::AddExistingShapeToFormat( SdrObject const & _rObj )
+{
+ SdrObjListIter aIter( _rObj, SdrIterMode::DeepNoGroups );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pCurrent = aIter.Next();
+ OSL_ENSURE( pCurrent, "SwXShape::AddExistingShapeToFormat: invalid object list element!" );
+ if ( !pCurrent )
+ continue;
+
+ auto pSwShape = comphelper::getFromUnoTunnel<SwXShape>(pCurrent->getWeakUnoShape());
+ if ( pSwShape )
+ {
+ if ( pSwShape->m_bDescriptor )
+ pSwShape->m_bDescriptor = false;
+ }
+ }
+}
+
+SwXShape::~SwXShape()
+{
+ SolarMutexGuard aGuard;
+
+ if (m_xShapeAgg.is())
+ {
+ uno::Reference< uno::XInterface > xRef;
+ m_xShapeAgg->setDelegator(xRef);
+ }
+ m_pImpl.reset();
+ if(m_pPage)
+ const_cast<SwFmDrawPage*>(m_pPage)->RemoveShape(this);
+}
+
+uno::Any SwXShape::queryInterface( const uno::Type& aType )
+{
+ uno::Any aRet;
+ SdrObject* pObj = nullptr;
+
+ if ((aType == cppu::UnoType<text::XText>::get())
+ || (aType == cppu::UnoType<text::XTextRange>::get())
+ || (aType == cppu::UnoType<text::XTextAppend>::get()))
+ {
+ pObj = SdrObject::getSdrObjectFromXShape(mxShape);
+
+ aRet = SwTextBoxHelper::queryInterface(GetFrameFormat(), aType, pObj);
+ if (aRet.hasValue())
+ return aRet;
+ }
+ aRet = SwXShapeBaseClass::queryInterface(aType);
+ // #i53320# - follow-up of #i31698#
+ // interface drawing::XShape is overloaded. Thus, provide
+ // correct object instance.
+ if(!aRet.hasValue() && m_xShapeAgg.is())
+ {
+ if(aType == cppu::UnoType<XShape>::get())
+ aRet <<= uno::Reference<XShape>(this);
+ else
+ aRet = m_xShapeAgg->queryAggregation(aType);
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SwXShape::getTypes( )
+{
+ uno::Sequence< uno::Type > aRet = SwXShapeBaseClass::getTypes();
+ if(m_xShapeAgg.is())
+ {
+ uno::Any aProv = m_xShapeAgg->queryAggregation(cppu::UnoType<XTypeProvider>::get());
+ if(aProv.hasValue())
+ {
+ uno::Reference< XTypeProvider > xAggProv;
+ aProv >>= xAggProv;
+ return comphelper::concatSequences(aRet, xAggProv->getTypes());
+ }
+ }
+ return aRet;
+}
+
+uno::Sequence< sal_Int8 > SwXShape::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXShape::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ if (!mxPropertySetInfo)
+ {
+ if(m_xShapeAgg.is())
+ {
+ const uno::Type& rPropSetType = cppu::UnoType<beans::XPropertySet>::get();
+ uno::Any aPSet = m_xShapeAgg->queryAggregation( rPropSetType );
+ if(auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
+ aPSet))
+ {
+ uno::Reference< beans::XPropertySetInfo > xInfo = (*xPrSet)->getPropertySetInfo();
+ // Expand PropertySetInfo!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ mxPropertySetInfo = new SfxExtItemPropertySetInfo( m_pPropertyMapEntries, aPropSeq );
+ }
+ }
+ if(!mxPropertySetInfo)
+ mxPropertySetInfo = m_pPropSet->getPropertySetInfo();
+ }
+ return mxPropertySetInfo;
+}
+
+void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
+{
+ SolarMutexGuard aGuard;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if(!m_xShapeAgg.is())
+ return;
+
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ("Property is read-only: " + rPropertyName, getXWeak() );
+ // with the layout it is possible to move the anchor without changing the position
+ if(pFormat)
+ {
+ SwAttrSet aSet(pFormat->GetAttrSet());
+ SwDoc* pDoc = pFormat->GetDoc();
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
+ {
+ bool bDone = false;
+ uno::Reference<text::XTextFrame> xFrame;
+ if(aValue >>= xFrame)
+ {
+ SwXFrame* pFrame = dynamic_cast<SwXFrame*>(xFrame.get());
+ if(pFrame && pFrame->GetFrameFormat() &&
+ pFrame->GetFrameFormat()->GetDoc() == pDoc)
+ {
+ UnoActionContext aCtx(pDoc);
+ SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aItemSet( pDoc->GetAttrPool() );
+ aItemSet.SetParent(&pFormat->GetAttrSet());
+ SwFormatAnchor aAnchor = static_cast<const SwFormatAnchor&>(aItemSet.Get(pEntry->nWID));
+ SwPosition aPos(*pFrame->GetFrameFormat()->GetContent().GetContentIdx());
+ aAnchor.SetAnchor(&aPos);
+ aAnchor.SetType(RndStdIds::FLY_AT_FLY);
+ aItemSet.Put(aAnchor);
+ pFormat->SetFormatAttr(aItemSet);
+ bDone = true;
+ }
+ }
+ if(!bDone)
+ throw lang::IllegalArgumentException();
+ }
+ else if(RES_OPAQUE == pEntry->nWID)
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ // set layer of new drawing
+ // object to corresponding invisible layer.
+ bool bIsVisible = pDoc->getIDocumentDrawModelAccess().IsVisibleLayerId( pObj->GetLayer() );
+ if(SdrInventor::FmForm != pObj->GetObjInventor())
+ {
+ pObj->SetLayer( *o3tl::doAccess<bool>(aValue)
+ ? ( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetHeavenId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() )
+ : ( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetHellId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() ));
+ }
+ else
+ {
+ pObj->SetLayer( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetControlsId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
+ }
+
+ }
+
+ }
+ // #i26791# - special handling for property FN_TEXT_RANGE
+ else if ( FN_TEXT_RANGE == pEntry->nWID )
+ {
+ SwFormatAnchor aAnchor( aSet.Get( RES_ANCHOR ) );
+ if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ {
+ // set property <TextRange> not valid for to-page anchored shapes
+ throw lang::IllegalArgumentException();
+ }
+
+ std::unique_ptr<SwUnoInternalPaM> pInternalPam(
+ new SwUnoInternalPaM( *(pFormat->GetDoc()) ));
+ uno::Reference< text::XTextRange > xRg;
+ aValue >>= xRg;
+ if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg) )
+ {
+ throw uno::RuntimeException();
+ }
+
+ if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+ {
+ //delete old SwFormatFlyCnt
+ //With AnchorAsCharacter the current TextAttribute has to be deleted.
+ //Tbis removes the frame format too.
+ //To prevent this the connection between format and attribute has to be broken before.
+ SwTextNode *pTextNode = aAnchor.GetAnchorNode()->GetTextNode();
+ SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno", "Missing FlyInCnt-Hint." );
+ const sal_Int32 nIdx = aAnchor.GetAnchorContentOffset();
+ SwTextAttr * const pHint =
+ pTextNode->GetTextAttrForCharAt(
+ nIdx, RES_TXTATR_FLYCNT );
+ assert(pHint && "Missing Hint.");
+ SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
+ "sw.uno", "Missing FlyInCnt-Hint." );
+ SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFormat,
+ "sw.uno", "Wrong TextFlyCnt-Hint." );
+ const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
+ .SetFlyFormat();
+
+ //The connection is removed now the attribute can be deleted.
+ pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
+ //create a new one
+ SwTextNode *pNd = pInternalPam->GetPointNode().GetTextNode();
+ SAL_WARN_IF( !pNd, "sw.uno", "Cursor not at TextNode." );
+ SwFormatFlyCnt aFormat( pFormat );
+ pNd->InsertItem(aFormat, pInternalPam->GetPoint()
+ ->GetContentIndex(), 0 );
+ //Refetch in case SwTextNode::InsertItem causes it to be deleted
+ pFormat = GetFrameFormat();
+ }
+ else
+ {
+ aAnchor.SetAnchor( pInternalPam->GetPoint() );
+ aSet.Put(aAnchor);
+ pFormat->SetFormatAttr(aSet);
+ }
+ }
+ else if (pEntry->nWID == FN_TEXT_BOX)
+ {
+ auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
+ if (pEntry->nMemberId == MID_TEXT_BOX)
+ {
+ bool bValue(false);
+ aValue >>= bValue;
+
+ if (bValue)
+ SwTextBoxHelper::create(pFormat, pObj);
+ else
+ SwTextBoxHelper::destroy(pFormat, pObj);
+ }
+ else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
+ {
+ if (aValue.getValueType()
+ == cppu::UnoType<uno::Reference<text::XTextFrame>>::get())
+ SwTextBoxHelper::set(pFormat, pObj,
+ aValue.get<uno::Reference<text::XTextFrame>>());
+ else
+ SAL_WARN( "sw.uno", "This is not a TextFrame!" );
+ }
+ }
+ else if (pEntry->nWID == RES_CHAIN)
+ {
+ if (pEntry->nMemberId == MID_CHAIN_NEXTNAME || pEntry->nMemberId == MID_CHAIN_PREVNAME)
+ SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
+ SdrObject::getSdrObjectFromXShape(mxShape));
+ }
+ // #i28749#
+ else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
+ {
+ sal_Int16 nPositionLayoutDir = 0;
+ aValue >>= nPositionLayoutDir;
+ pFormat->SetPositionLayoutDir( nPositionLayoutDir );
+ }
+ else if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
+ {
+ UnoActionContext aCtx(pDoc);
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
+ {
+ SdrObject* pObj = pFormat->FindSdrObject();
+ SdrMarkList aList;
+ SdrMark aMark(pObj);
+ aList.InsertEntry(aMark);
+ sal_Int32 nAnchor = 0;
+ cppu::enum2int( nAnchor, aValue );
+ pDoc->ChgAnchor( aList, static_cast<RndStdIds>(nAnchor),
+ false, true );
+ }
+ else
+ {
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
+ pFormat->SetFormatAttr(aSet);
+ }
+ }
+ else if( RES_FRM_SIZE == pEntry->nWID &&
+ ( pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH
+ || pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION
+ || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION ) )
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ sal_Int16 nPercent(100);
+ aValue >>= nPercent;
+ switch (pEntry->nMemberId)
+ {
+ case MID_FRMSIZE_REL_WIDTH:
+ pObj->SetRelativeWidth( nPercent / 100.0 );
+ break;
+ case MID_FRMSIZE_REL_HEIGHT:
+ pObj->SetRelativeHeight( nPercent / 100.0 );
+ break;
+ case MID_FRMSIZE_REL_WIDTH_RELATION:
+ pObj->SetRelativeWidthRelation(nPercent);
+ break;
+ case MID_FRMSIZE_REL_HEIGHT_RELATION:
+ pObj->SetRelativeHeightRelation(nPercent);
+ break;
+ }
+ }
+ }
+ else if (pEntry->nWID == RES_HORI_ORIENT
+ && pEntry->nMemberId == MID_HORIORIENT_RELATION
+ && aSet.Get(RES_ANCHOR).GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ {
+ uno::Any value(aValue);
+ sal_Int16 nRelOrient(text::RelOrientation::PAGE_FRAME);
+ aValue >>= nRelOrient;
+ if (sw::GetAtPageRelOrientation(nRelOrient, true))
+ {
+ SAL_WARN("sw.core", "SwXShape: fixing invalid horizontal RelOrientation for at-page anchor");
+ value <<= nRelOrient;
+ }
+ m_pPropSet->setPropertyValue( *pEntry, value, aSet );
+ pFormat->SetFormatAttr(aSet);
+ }
+ else
+ {
+ m_pPropSet->setPropertyValue( *pEntry, aValue, aSet );
+
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
+ {
+ bool bSetAttr = true;
+ text::TextContentAnchorType eNewAnchor = static_cast<text::TextContentAnchorType>(SWUnoHelper::GetEnumAsInt32( aValue ));
+
+ //if old anchor was in_cntnt the related text attribute has to be removed
+ const SwFormatAnchor& rOldAnchor = pFormat->GetAnchor();
+ RndStdIds eOldAnchorId = rOldAnchor.GetAnchorId();
+ SdrObject* pObj = pFormat->FindSdrObject();
+ SwFrameFormat *pFlyFormat = FindFrameFormat( pObj );
+ pFlyFormat->DelFrames();
+ if( text::TextContentAnchorType_AS_CHARACTER != eNewAnchor &&
+ (RndStdIds::FLY_AS_CHAR == eOldAnchorId))
+ {
+ //With AnchorAsCharacter the current TextAttribute has to be deleted.
+ //Tbis removes the frame format too.
+ //To prevent this the connection between format and attribute has to be broken before.
+ SwTextNode *pTextNode = rOldAnchor.GetAnchorNode()->GetTextNode();
+ SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno", "Missing FlyInCnt-Hint." );
+ const sal_Int32 nIdx = rOldAnchor.GetAnchorContentOffset();
+ SwTextAttr * const pHint =
+ pTextNode->GetTextAttrForCharAt(
+ nIdx, RES_TXTATR_FLYCNT );
+ assert(pHint && "Missing Hint.");
+ SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
+ "sw.uno", "Missing FlyInCnt-Hint." );
+ SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFlyFormat,
+ "sw.uno", "Wrong TextFlyCnt-Hint." );
+ const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
+ .SetFlyFormat();
+
+ //The connection is removed now the attribute can be deleted.
+ pTextNode->DeleteAttributes(RES_TXTATR_FLYCNT, nIdx);
+ }
+ else if( text::TextContentAnchorType_AT_PAGE != eNewAnchor &&
+ (RndStdIds::FLY_AT_PAGE == eOldAnchorId))
+ {
+ SwFormatAnchor aNewAnchor( aSet.Get( RES_ANCHOR ) );
+ //if the fly has been anchored at page then it needs to be connected
+ //to the content position
+ SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
+ if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
+ {
+ SwCursorMoveState aState( CursorMoveState::SetOnlyText );
+ Point aTmp( pObj->GetSnapRect().TopLeft() );
+ pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
+ }
+ else
+ {
+ //without access to the layout the last node of the body will be used as anchor position
+ aPam.Move( fnMoveBackward, GoInDoc );
+ }
+ //anchor position has to be inserted after the text attribute has been inserted
+ aNewAnchor.SetAnchor( aPam.GetPoint() );
+ aSet.Put( aNewAnchor );
+ pFormat->SetFormatAttr(aSet);
+ bSetAttr = false;
+ }
+ if( text::TextContentAnchorType_AS_CHARACTER == eNewAnchor &&
+ (RndStdIds::FLY_AS_CHAR != eOldAnchorId))
+ {
+ SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
+ if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
+ {
+ SwCursorMoveState aState( CursorMoveState::SetOnlyText );
+ Point aTmp( pObj->GetSnapRect().TopLeft() );
+ pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
+ }
+ else
+ {
+ //without access to the layout the last node of the body will be used as anchor position
+ aPam.Move( fnMoveBackward, GoInDoc );
+ }
+ //the RES_TXTATR_FLYCNT needs to be added now
+ SwTextNode *pNd = aPam.GetPointNode().GetTextNode();
+ SAL_WARN_IF( !pNd, "sw.uno", "Cursor is not in a TextNode." );
+ SwFormatFlyCnt aFormat( pFlyFormat );
+ pNd->InsertItem(aFormat,
+ aPam.GetPoint()->GetContentIndex(), 0 );
+ aPam.GetPoint()->AdjustContent(-1); // InsertItem moved it
+ SwFormatAnchor aNewAnchor(
+ aSet.Get(RES_ANCHOR));
+ aNewAnchor.SetAnchor( aPam.GetPoint() );
+ aSet.Put( aNewAnchor );
+ }
+ if( bSetAttr )
+ pFormat->SetFormatAttr(aSet);
+
+ // If this property is an anchor change, and there is a group shape with textboxes
+ // do anchor sync in time unless the anchor sync in the porfly will cause crash during
+ // layout calculation (When importing an inline shape in docx via dmapper).
+ if (pFormat->Which() == RES_DRAWFRMFMT && pFormat->GetOtherTextBoxFormats())
+ {
+ SwTextBoxHelper::synchronizeGroupTextBoxProperty(
+ SwTextBoxHelper::changeAnchor, pFormat,
+ SdrObject::getSdrObjectFromXShape(mxShape));
+ }
+ }
+ else
+ pFormat->SetFormatAttr(aSet);
+ }
+
+ // We have a pFormat and a pEntry as well: try to sync TextBox property.
+ SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
+ SdrObject::getSdrObjectFromXShape(mxShape));
+ }
+ else
+ {
+ SfxPoolItem* pItem = nullptr;
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR:
+ pItem = m_pImpl->GetAnchor(true);
+ break;
+ case RES_HORI_ORIENT:
+ pItem = m_pImpl->GetHOrient(true);
+ break;
+ case RES_VERT_ORIENT:
+ pItem = m_pImpl->GetVOrient(true);
+ break;
+ case RES_LR_SPACE:
+ pItem = m_pImpl->GetLRSpace(true);
+ break;
+ case RES_UL_SPACE:
+ pItem = m_pImpl->GetULSpace(true);
+ break;
+ case RES_SURROUND:
+ pItem = m_pImpl->GetSurround(true);
+ break;
+ case FN_TEXT_RANGE:
+ if(auto tr = o3tl::tryAccess<
+ uno::Reference<text::XTextRange>>(aValue))
+ {
+ uno::Reference< text::XTextRange > & rRange = m_pImpl->GetTextRange();
+ rRange = *tr;
+ }
+ break;
+ case RES_OPAQUE :
+ m_pImpl->SetOpaque(*o3tl::doAccess<bool>(aValue));
+ break;
+ // #i26791#
+ case RES_FOLLOW_TEXT_FLOW:
+ {
+ pItem = m_pImpl->GetFollowTextFlow( true );
+ }
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pItem = m_pImpl->GetWrapInfluenceOnObjPos( true );
+ }
+ break;
+ // #i28749#
+ case FN_SHAPE_POSITION_LAYOUT_DIR :
+ {
+ sal_Int16 nPositionLayoutDir = 0;
+ aValue >>= nPositionLayoutDir;
+ m_pImpl->SetPositionLayoutDir( nPositionLayoutDir );
+ }
+ break;
+ }
+ if(pItem)
+ pItem->PutValue(aValue, pEntry->nMemberId);
+ }
+ }
+ else
+ {
+ const uno::Type& rPSetType =
+ cppu::UnoType<beans::XPropertySet>::get();
+ uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
+ auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
+ aPSet);
+ if(!xPrSet)
+ throw uno::RuntimeException();
+ // #i31698# - setting the caption point of a
+ // caption object doesn't have to change the object position.
+ // Thus, keep the position, before the caption point is set and
+ // restore it afterwards.
+ awt::Point aKeepedPosition( 0, 0 );
+ if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
+ {
+ aKeepedPosition = getPosition();
+ }
+ if( pFormat && pFormat->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() )
+ {
+ UnoActionContext aCtx(pFormat->GetDoc());
+ (*xPrSet)->setPropertyValue(rPropertyName, aValue);
+ }
+ else
+ (*xPrSet)->setPropertyValue(rPropertyName, aValue);
+
+ if (pFormat)
+ {
+ // We have a pFormat (but no pEntry): try to sync TextBox property.
+ SwTextBoxHelper::syncProperty(pFormat, rPropertyName, aValue,
+ SdrObject::getSdrObjectFromXShape(mxShape));
+ }
+
+ // #i31698# - restore object position, if caption point is set.
+ if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
+ {
+ setPosition( aKeepedPosition );
+ }
+ }
+}
+
+uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ if(m_xShapeAgg.is())
+ {
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if(pEntry)
+ {
+ if(pFormat)
+ {
+ if(RES_OPAQUE == pEntry->nWID)
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE(pSvxShape, "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ // consider invisible layers
+ aRet <<=
+ ( pObj->GetLayer() != pFormat->GetDoc()->getIDocumentDrawModelAccess().GetHellId() &&
+ pObj->GetLayer() != pFormat->GetDoc()->getIDocumentDrawModelAccess().GetInvisibleHellId() );
+ }
+ }
+ else if(FN_ANCHOR_POSITION == pEntry->nWID)
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE(pSvxShape, "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ Point aPt = pObj->GetAnchorPos();
+ awt::Point aPoint( convertTwipToMm100( aPt.X() ),
+ convertTwipToMm100( aPt.Y() ) );
+ aRet <<= aPoint;
+ }
+ }
+ // #i26791# - special handling for FN_TEXT_RANGE
+ else if ( FN_TEXT_RANGE == pEntry->nWID )
+ {
+ const SwFormatAnchor aAnchor = pFormat->GetAnchor();
+ if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ {
+ // return nothing, because property <TextRange> isn't
+ // valid for to-page anchored shapes
+ uno::Any aAny;
+ aRet = aAny;
+ }
+ else
+ {
+ if ( aAnchor.GetAnchorNode() )
+ {
+ const rtl::Reference<SwXTextRange> xTextRange
+ = SwXTextRange::CreateXTextRange(
+ *pFormat->GetDoc(),
+ *aAnchor.GetContentAnchor(),
+ nullptr );
+ aRet <<= uno::Reference<text::XTextRange>(xTextRange);
+ }
+ else
+ {
+ // return nothing
+ uno::Any aAny;
+ aRet = aAny;
+ }
+ }
+ }
+ else if (pEntry->nWID == FN_TEXT_BOX)
+ {
+ if (pEntry->nMemberId == MID_TEXT_BOX)
+ {
+ auto pSvxShape = GetSvxShape();
+ bool bValue = SwTextBoxHelper::isTextBox(
+ pFormat, RES_DRAWFRMFMT,
+ ((pSvxShape && pSvxShape->GetSdrObject()) ? pSvxShape->GetSdrObject()
+ : pFormat->FindRealSdrObject()));
+ aRet <<= bValue;
+ }
+ else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
+ {
+ auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
+ auto xRange = SwTextBoxHelper::queryInterface(
+ pFormat, cppu::UnoType<text::XText>::get(),
+ pObj ? pObj : pFormat->FindRealSdrObject());
+ uno::Reference<text::XTextFrame> xFrame(xRange, uno::UNO_QUERY);
+ if (xFrame.is())
+ aRet <<= xFrame;
+ }
+ }
+ else if (pEntry->nWID == RES_CHAIN)
+ {
+ switch (pEntry->nMemberId)
+ {
+ case MID_CHAIN_PREVNAME:
+ case MID_CHAIN_NEXTNAME:
+ case MID_CHAIN_NAME:
+ SwTextBoxHelper::getProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aRet);
+ break;
+ }
+ }
+ // #i28749#
+ else if ( FN_SHAPE_TRANSFORMATION_IN_HORI_L2R == pEntry->nWID )
+ {
+ // get property <::drawing::Shape::Transformation>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( "Transformation" );
+ }
+ else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
+ {
+ aRet <<= pFormat->GetPositionLayoutDir();
+ }
+ // #i36248#
+ else if ( FN_SHAPE_STARTPOSITION_IN_HORI_L2R == pEntry->nWID )
+ {
+ // get property <::drawing::Shape::StartPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( "StartPosition" );
+ }
+ else if ( FN_SHAPE_ENDPOSITION_IN_HORI_L2R == pEntry->nWID )
+ {
+ // get property <::drawing::Shape::EndPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( "EndPosition" );
+ }
+ else if (pEntry->nWID == RES_FRM_SIZE &&
+ (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT ||
+ pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH ||
+ pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
+ pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
+ sal_Int16 nRet = 0;
+ if (pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ switch (pEntry->nMemberId)
+ {
+ case MID_FRMSIZE_REL_WIDTH:
+ if (pObj->GetRelativeWidth())
+ nRet = *pObj->GetRelativeWidth() * 100;
+ break;
+ case MID_FRMSIZE_REL_HEIGHT:
+ if (pObj->GetRelativeHeight())
+ nRet = *pObj->GetRelativeHeight() * 100;
+ break;
+ case MID_FRMSIZE_REL_WIDTH_RELATION:
+ nRet = pObj->GetRelativeWidthRelation();
+ break;
+ case MID_FRMSIZE_REL_HEIGHT_RELATION:
+ nRet = pObj->GetRelativeHeightRelation();
+ break;
+ }
+ }
+ aRet <<= nRet;
+ }
+ else
+ {
+ const SwAttrSet& rSet = pFormat->GetAttrSet();
+ m_pPropSet->getPropertyValue(*pEntry, rSet, aRet);
+ }
+ }
+ else
+ {
+ SfxPoolItem* pItem = nullptr;
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR:
+ pItem = m_pImpl->GetAnchor();
+ break;
+ case RES_HORI_ORIENT:
+ pItem = m_pImpl->GetHOrient();
+ break;
+ case RES_VERT_ORIENT:
+ pItem = m_pImpl->GetVOrient();
+ break;
+ case RES_LR_SPACE:
+ pItem = m_pImpl->GetLRSpace();
+ break;
+ case RES_UL_SPACE:
+ pItem = m_pImpl->GetULSpace();
+ break;
+ case RES_SURROUND:
+ pItem = m_pImpl->GetSurround();
+ break;
+ case FN_TEXT_RANGE :
+ aRet <<= m_pImpl->GetTextRange();
+ break;
+ case RES_OPAQUE :
+ aRet <<= m_pImpl->GetOpaque();
+ break;
+ case FN_ANCHOR_POSITION :
+ {
+ aRet <<= awt::Point();
+ }
+ break;
+ // #i26791#
+ case RES_FOLLOW_TEXT_FLOW :
+ {
+ pItem = m_pImpl->GetFollowTextFlow();
+ }
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pItem = m_pImpl->GetWrapInfluenceOnObjPos();
+ }
+ break;
+ // #i28749#
+ case FN_SHAPE_TRANSFORMATION_IN_HORI_L2R:
+ {
+ // get property <::drawing::Shape::Transformation>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( "Transformation" );
+ }
+ break;
+ case FN_SHAPE_POSITION_LAYOUT_DIR:
+ {
+ aRet <<= m_pImpl->GetPositionLayoutDir();
+ }
+ break;
+ // #i36248#
+ case FN_SHAPE_STARTPOSITION_IN_HORI_L2R:
+ {
+ // get property <::drawing::Shape::StartPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( "StartPosition" );
+ }
+ break;
+ case FN_SHAPE_ENDPOSITION_IN_HORI_L2R:
+ {
+ // get property <::drawing::Shape::StartPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( "EndPosition" );
+ }
+ break;
+ }
+ if(pItem)
+ pItem->QueryValue(aRet, pEntry->nMemberId);
+ }
+ }
+ else
+ {
+ aRet = _getPropAtAggrObj( rPropertyName );
+
+ // #i31698# - convert the position (translation)
+ // of the drawing object in the transformation
+ if ( rPropertyName == "Transformation" )
+ {
+ drawing::HomogenMatrix3 aMatrix;
+ aRet >>= aMatrix;
+ aRet <<= ConvertTransformationToLayoutDir( aMatrix );
+ }
+ // #i36248#
+ else if ( rPropertyName == "StartPosition" )
+ {
+ awt::Point aStartPos;
+ aRet >>= aStartPos;
+ // #i59051#
+ aRet <<= ConvertStartOrEndPosToLayoutDir( aStartPos );
+ }
+ else if ( rPropertyName == "EndPosition" )
+ {
+ awt::Point aEndPos;
+ aRet >>= aEndPos;
+ // #i59051#
+ aRet <<= ConvertStartOrEndPosToLayoutDir( aEndPos );
+ }
+ // #i59051#
+ else if ( rPropertyName == "PolyPolygonBezier" )
+ {
+ drawing::PolyPolygonBezierCoords aPath;
+ aRet >>= aPath;
+ aRet <<= ConvertPolyPolygonBezierToLayoutDir( aPath );
+ }
+ else if (rPropertyName == "ZOrder")
+ {
+ // Convert the real draw page position to the logical one that ignores textboxes.
+ if (pFormat)
+ {
+ const SdrObject* pObj = pFormat->FindRealSdrObject();
+ if (pObj)
+ {
+ bool bConvert = true;
+ if (SvxShape* pSvxShape = GetSvxShape())
+ // In case of group shapes, pSvxShape points to the child shape, while pObj points to the outermost group shape.
+ if (pSvxShape->GetSdrObject() != pObj)
+ // Textboxes are not expected inside group shapes, so no conversion is necessary there.
+ bConvert = false;
+ if (bConvert)
+ {
+ aRet <<= SwTextBoxHelper::getOrdNum(pObj);
+ }
+ }
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+uno::Any SwXShape::_getPropAtAggrObj( const OUString& _rPropertyName )
+{
+ uno::Any aRet;
+
+ const uno::Type& rPSetType =
+ cppu::UnoType<beans::XPropertySet>::get();
+ uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
+ auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(aPSet);
+ if ( !xPrSet )
+ {
+ throw uno::RuntimeException();
+ }
+ aRet = (*xPrSet)->getPropertyValue( _rPropertyName );
+
+ return aRet;
+}
+
+beans::PropertyState SwXShape::getPropertyState( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aNames { rPropertyName };
+ uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
+ return aStates.getConstArray()[0];
+}
+
+uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
+ const uno::Sequence< OUString >& aPropertyNames )
+{
+ SolarMutexGuard aGuard;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ uno::Sequence< beans::PropertyState > aRet(aPropertyNames.getLength());
+ if(!m_xShapeAgg.is())
+ throw uno::RuntimeException();
+
+ SvxShape* pSvxShape = GetSvxShape();
+ bool bGroupMember = false;
+ bool bFormControl = false;
+ SdrObject* pObject = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
+ if(pObject)
+ {
+ bGroupMember = pObject->getParentSdrObjectFromSdrObject() != nullptr;
+ bFormControl = pObject->GetObjInventor() == SdrInventor::FmForm;
+ }
+ const OUString* pNames = aPropertyNames.getConstArray();
+ beans::PropertyState* pRet = aRet.getArray();
+ uno::Reference< XPropertyState > xShapePrState;
+ for(sal_Int32 nProperty = 0; nProperty < aPropertyNames.getLength(); nProperty++)
+ {
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( pNames[nProperty] );
+ if(pEntry)
+ {
+ if(RES_OPAQUE == pEntry->nWID)
+ pRet[nProperty] = bFormControl ?
+ beans::PropertyState_DEFAULT_VALUE : beans::PropertyState_DIRECT_VALUE;
+ else if(FN_ANCHOR_POSITION == pEntry->nWID)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if(FN_TEXT_RANGE == pEntry->nWID)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if(bGroupMember)
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ else if (pEntry->nWID == RES_FRM_SIZE &&
+ (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
+ pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if (pEntry->nWID == FN_TEXT_BOX)
+ {
+ // The TextBox property is set, if we can find a textbox for this shape.
+ if (pFormat
+ && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT,
+ SdrObject::getSdrObjectFromXShape(mxShape)))
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ else if(pFormat)
+ {
+ const SwAttrSet& rSet = pFormat->GetAttrSet();
+ SfxItemState eItemState = rSet.GetItemState(pEntry->nWID, false);
+
+ if(SfxItemState::SET == eItemState)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if(SfxItemState::DEFAULT == eItemState)
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ else
+ pRet[nProperty] = beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ else
+ {
+ SfxPoolItem* pItem = nullptr;
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR:
+ pItem = m_pImpl->GetAnchor();
+ break;
+ case RES_HORI_ORIENT:
+ pItem = m_pImpl->GetHOrient();
+ break;
+ case RES_VERT_ORIENT:
+ pItem = m_pImpl->GetVOrient();
+ break;
+ case RES_LR_SPACE:
+ pItem = m_pImpl->GetLRSpace();
+ break;
+ case RES_UL_SPACE:
+ pItem = m_pImpl->GetULSpace();
+ break;
+ case RES_SURROUND:
+ pItem = m_pImpl->GetSurround();
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pItem = m_pImpl->GetWrapInfluenceOnObjPos();
+ }
+ break;
+ }
+ if(pItem)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ else
+ {
+ if(!xShapePrState.is())
+ {
+ const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
+ uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
+ auto ps = o3tl::tryAccess<uno::Reference<XPropertyState>>(
+ aPState);
+ if(!ps)
+ throw uno::RuntimeException();
+ xShapePrState = *ps;
+ }
+ pRet[nProperty] = xShapePrState->getPropertyState(pNames[nProperty]);
+ }
+ }
+
+ return aRet;
+}
+
+void SwXShape::setPropertyToDefault( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ if(!m_xShapeAgg.is())
+ throw uno::RuntimeException();
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw uno::RuntimeException("Property is read-only: " + rPropertyName, getXWeak() );
+ if(pFormat)
+ {
+ const SfxItemSet& rSet = pFormat->GetAttrSet();
+ SfxItemSet aSet(pFormat->GetDoc()->GetAttrPool(), pEntry->nWID, pEntry->nWID);
+ aSet.SetParent(&rSet);
+ aSet.ClearItem(pEntry->nWID);
+ pFormat->GetDoc()->SetAttr(aSet, *pFormat);
+ }
+ else
+ {
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR: m_pImpl->RemoveAnchor(); break;
+ case RES_HORI_ORIENT: m_pImpl->RemoveHOrient(); break;
+ case RES_VERT_ORIENT: m_pImpl->RemoveVOrient(); break;
+ case RES_LR_SPACE: m_pImpl->RemoveLRSpace(); break;
+ case RES_UL_SPACE: m_pImpl->RemoveULSpace(); break;
+ case RES_SURROUND: m_pImpl->RemoveSurround();break;
+ case RES_OPAQUE : m_pImpl->SetOpaque(false); break;
+ case FN_TEXT_RANGE :
+ break;
+ // #i26791#
+ case RES_FOLLOW_TEXT_FLOW:
+ {
+ m_pImpl->RemoveFollowTextFlow();
+ }
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ m_pImpl->RemoveWrapInfluenceOnObjPos();
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
+ uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
+ auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
+ aPState);
+ if(!xShapePrState)
+ throw uno::RuntimeException();
+ (*xShapePrState)->setPropertyToDefault( rPropertyName );
+ }
+
+}
+
+uno::Any SwXShape::getPropertyDefault( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ uno::Any aRet;
+ if(!m_xShapeAgg.is())
+ throw uno::RuntimeException();
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if(pEntry)
+ {
+ if(!(pEntry->nWID < RES_FRMATR_END && pFormat))
+ throw uno::RuntimeException();
+
+ const SfxPoolItem& rDefItem =
+ pFormat->GetDoc()->GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(aRet, pEntry->nMemberId);
+
+ }
+ else
+ {
+ const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
+ uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
+ auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
+ aPState);
+ if(!xShapePrState)
+ throw uno::RuntimeException();
+ (*xShapePrState)->getPropertyDefault( rPropertyName );
+ }
+
+ return aRet;
+}
+
+void SwXShape::addPropertyChangeListener(
+ const OUString& _propertyName,
+ const uno::Reference< beans::XPropertyChangeListener > & _listener )
+{
+ if ( !m_xShapeAgg.is() )
+ throw uno::RuntimeException("no shape aggregate", *this );
+
+ // must be handled by the aggregate
+ uno::Reference< beans::XPropertySet > xShapeProps;
+ if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
+ xShapeProps->addPropertyChangeListener( _propertyName, _listener );
+}
+
+void SwXShape::removePropertyChangeListener(
+ const OUString& _propertyName,
+ const uno::Reference< beans::XPropertyChangeListener > & _listener)
+{
+ if ( !m_xShapeAgg.is() )
+ throw uno::RuntimeException("no shape aggregate", *this );
+
+ // must be handled by the aggregate
+ uno::Reference< beans::XPropertySet > xShapeProps;
+ if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
+ xShapeProps->removePropertyChangeListener( _propertyName, _listener );
+}
+
+void SwXShape::addVetoableChangeListener(
+ const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXShape::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXShape::attach(const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ // get access to SwDoc
+ // (see also SwXTextRange::XTextRangeToSwPaM)
+ const SwDoc* pDoc = nullptr;
+ if (auto pRange = dynamic_cast<SwXTextRange*>(xTextRange.get()))
+ pDoc = &pRange->GetDoc();
+ else if (auto pText = dynamic_cast<SwXText*>(xTextRange.get()))
+ pDoc = pText->GetDoc();
+ else if (auto pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get()))
+ pDoc = pCursor->GetDoc();
+ else if (auto pPortion = dynamic_cast<SwXTextPortion*>(xTextRange.get()))
+ pDoc = &pPortion->GetCursor().GetDoc();
+ else if (auto pParagraph = dynamic_cast<SwXParagraph*>(xTextRange.get());
+ pParagraph && pParagraph->GetTextNode())
+ pDoc = &pParagraph->GetTextNode()->GetDoc();
+
+ if(!pDoc)
+ throw uno::RuntimeException();
+ const SwDocShell* pDocSh = pDoc->GetDocShell();
+ if (!pDocSh)
+ return;
+
+ uno::Reference<frame::XModel> xModel = pDocSh->GetModel();
+ uno::Reference< drawing::XDrawPageSupplier > xDPS(xModel, uno::UNO_QUERY);
+ if (xDPS.is())
+ {
+ uno::Reference< drawing::XDrawPage > xDP( xDPS->getDrawPage() );
+ if (xDP.is())
+ {
+ uno::Any aPos;
+ aPos <<= xTextRange;
+ setPropertyValue("TextRange", aPos);
+ uno::Reference< drawing::XShape > xTemp( getXWeak(), uno::UNO_QUERY );
+ xDP->add( xTemp );
+ }
+ }
+}
+
+uno::Reference< text::XTextRange > SwXShape::getAnchor()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > aRef;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ if(pFormat)
+ {
+ const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
+ // return an anchor for non-page bound frames
+ // and for page bound frames that have a page no == NULL and a content position
+ if ((rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) ||
+ (rAnchor.GetAnchorNode() && !rAnchor.GetPageNum()))
+ {
+ if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA)
+ { // ensure that SwXTextRange has SwContentIndex
+ const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
+ aRef = SwXTextRange::CreateXTextRange(*pFormat->GetDoc(), SwPosition(*pAnchorNode), nullptr);
+ }
+ else
+ {
+ aRef = SwXTextRange::CreateXTextRange(*pFormat->GetDoc(), *rAnchor.GetContentAnchor(), nullptr);
+ }
+ }
+ }
+ else
+ aRef = m_pImpl->GetTextRange().get();
+ return aRef;
+}
+
+void SwXShape::dispose()
+{
+ SolarMutexGuard aGuard;
+ SwFrameFormat* pFormat = GetFrameFormat();
+ if(pFormat)
+ {
+ // determine correct <SdrObject>
+ SvxShape* pSvxShape = GetSvxShape();
+ SdrObject* pObj = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
+ // safety assertion:
+ // <pObj> must be the same as <pFormat->FindSdrObject()>, if <pObj> isn't
+ // a 'virtual' drawing object.
+ // correct assertion and refine it for safety reason.
+ OSL_ENSURE( !pObj ||
+ dynamic_cast<const SwDrawVirtObj*>( pObj) != nullptr ||
+ pObj->getParentSdrObjectFromSdrObject() ||
+ pObj == pFormat->FindSdrObject(),
+ "<SwXShape::dispose(..) - different 'master' drawing objects!!" );
+ // perform delete of draw frame format *not*
+ // for 'virtual' drawing objects.
+ // no delete of draw format for members
+ // of a group
+ if ( pObj &&
+ dynamic_cast<const SwDrawVirtObj*>( pObj) == nullptr &&
+ !pObj->getParentSdrObjectFromSdrObject() &&
+ pObj->IsInserted() )
+ {
+ const SwFormatAnchor& rFormatAnchor = pFormat->GetAnchor();
+ if (rFormatAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+ {
+ SwTextNode *pTextNode = rFormatAnchor.GetAnchorNode()->GetTextNode();
+ const sal_Int32 nIdx = rFormatAnchor.GetAnchorContentOffset();
+ pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
+ }
+ else
+ pFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pFormat );
+ }
+ }
+ if(m_xShapeAgg.is())
+ {
+ uno::Any aAgg(m_xShapeAgg->queryAggregation( cppu::UnoType<XComponent>::get()));
+ uno::Reference<XComponent> xComp;
+ aAgg >>= xComp;
+ if(xComp.is())
+ xComp->dispose();
+ }
+ if(m_pPage)
+ {
+ auto pPage = const_cast<SwFmDrawPage*>(m_pPage);
+ m_pPage = nullptr;
+ pPage->RemoveShape(this);
+ }
+}
+
+void SwXShape::addEventListener(
+ const uno::Reference< lang::XEventListener > & aListener)
+{
+ SvxShape* pSvxShape = GetSvxShape();
+ if(pSvxShape)
+ pSvxShape->addEventListener(aListener);
+}
+
+void SwXShape::removeEventListener(
+ const uno::Reference< lang::XEventListener > & aListener)
+{
+ SvxShape* pSvxShape = GetSvxShape();
+ if(pSvxShape)
+ pSvxShape->removeEventListener(aListener);
+}
+
+OUString SwXShape::getImplementationName()
+{
+ return "SwXShape";
+}
+
+sal_Bool SwXShape::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXShape::getSupportedServiceNames()
+{
+ uno::Sequence< OUString > aSeq;
+ if (SvxShape* pSvxShape = GetSvxShape())
+ aSeq = pSvxShape->getSupportedServiceNames();
+ return comphelper::concatSequences(
+ aSeq, std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape" });
+}
+
+SvxShape* SwXShape::GetSvxShape()
+{
+ if(m_xShapeAgg.is())
+ return comphelper::getFromUnoTunnel<SvxShape>(m_xShapeAgg);
+ return nullptr;
+}
+
+// #i31698#
+// implementation of virtual methods from drawing::XShape
+awt::Point SAL_CALL SwXShape::getPosition()
+{
+ awt::Point aPos( GetAttrPosition() );
+
+ // handle group members
+ SvxShape* pSvxShape = GetSvxShape();
+ if ( pSvxShape )
+ {
+ SdrObject* pTopGroupObj = GetTopGroupObj( pSvxShape );
+ if ( pTopGroupObj )
+ {
+ // #i34750# - get attribute position of top group
+ // shape and add offset between top group object and group member
+ uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
+ aPos = xGroupShape->getPosition();
+ // add offset between top group object and group member
+ // to the determined attribute position
+ // #i34750#:
+ // consider the layout direction
+ const tools::Rectangle aMemberObjRect = GetSvxShape()->GetSdrObject()->GetSnapRect();
+ const tools::Rectangle aGroupObjRect = pTopGroupObj->GetSnapRect();
+ // #i53320# - relative position of group member and
+ // top group object is always given in horizontal left-to-right layout.
+ awt::Point aOffset( 0, 0 );
+ {
+ aOffset.X = ( aMemberObjRect.Left() - aGroupObjRect.Left() );
+ aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
+ }
+ aOffset.X = convertTwipToMm100(aOffset.X);
+ aOffset.Y = convertTwipToMm100(aOffset.Y);
+ aPos.X += aOffset.X;
+ aPos.Y += aOffset.Y;
+ }
+ }
+
+ return aPos;
+}
+
+void SAL_CALL SwXShape::setPosition( const awt::Point& aPosition )
+{
+ SdrObject* pTopGroupObj = GetTopGroupObj();
+ if ( !pTopGroupObj )
+ {
+ // #i37877# - no adjustment of position attributes,
+ // if the position also has to be applied at the drawing object and
+ // a contact object is already registered at the drawing object.
+ bool bApplyPosAtDrawObj(false);
+ bool bNoAdjustOfPosProp(false);
+ // #i35798# - apply position also to drawing object,
+ // if drawing object has no anchor position set.
+ if ( mxShape.is() )
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ if ( pObj &&
+ pObj->GetAnchorPos().X() == 0 &&
+ pObj->GetAnchorPos().Y() == 0 )
+ {
+ bApplyPosAtDrawObj = true;
+ if ( pObj->GetUserCall() &&
+ dynamic_cast<const SwDrawContact*>( pObj->GetUserCall()) != nullptr )
+ {
+ bNoAdjustOfPosProp = true;
+ }
+ }
+ }
+ }
+ // shape isn't a group member. Thus, set positioning attributes
+ if ( !bNoAdjustOfPosProp )
+ {
+ AdjustPositionProperties( aPosition );
+ }
+ if ( bApplyPosAtDrawObj )
+ {
+ mxShape->setPosition( aPosition );
+ }
+ }
+ else if ( mxShape.is() )
+ {
+ // shape is a member of a group. Thus, set its position.
+ awt::Point aNewPos( aPosition );
+ // The given position is given in the according layout direction. Thus,
+ // it has to be converted to a position in horizontal left-to-right
+ // layout.
+ // convert given absolute attribute position in layout direction into
+ // position in horizontal left-to-right layout.
+ {
+ aNewPos = ConvertPositionToHoriL2R( aNewPos, getSize() );
+ }
+ // Convert given absolute position in horizontal left-to-right
+ // layout into relative position in horizontal left-to-right layout.
+ uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
+ {
+ // #i34750#
+ // use method <xGroupShape->getPosition()> to get the correct
+ // position of the top group object.
+ awt::Point aAttrPosInHoriL2R(
+ ConvertPositionToHoriL2R( xGroupShape->getPosition(),
+ xGroupShape->getSize() ) );
+ aNewPos.X = o3tl::saturating_sub(aNewPos.X, aAttrPosInHoriL2R.X);
+ aNewPos.Y = o3tl::saturating_sub(aNewPos.Y, aAttrPosInHoriL2R.Y);
+ }
+ // convert relative position in horizontal left-to-right layout into
+ // absolute position in horizontal left-to-right layout
+ {
+ // #i34750#
+ // use method <SvxShape->getPosition()> to get the correct
+ // 'Drawing layer' position of the top group shape.
+ auto pSvxGroupShape = comphelper::getFromUnoTunnel<SvxShape>(pTopGroupObj->getUnoShape());
+ const awt::Point aGroupPos = pSvxGroupShape->getPosition();
+ aNewPos.X = o3tl::saturating_add(aNewPos.X, aGroupPos.X);
+ aNewPos.Y = o3tl::saturating_add(aNewPos.Y, aGroupPos.Y);
+ }
+ // set position
+ mxShape->setPosition( aNewPos );
+ }
+}
+
+awt::Size SAL_CALL SwXShape::getSize()
+{
+ awt::Size aSize;
+ if ( mxShape.is() )
+ {
+ aSize = mxShape->getSize();
+ }
+ return aSize;
+}
+
+void SAL_CALL SwXShape::setSize( const awt::Size& aSize )
+{
+ comphelper::ProfileZone aZone("SwXShape::setSize");
+
+ if ( mxShape.is() )
+ {
+ mxShape->setSize( aSize );
+ }
+ SwTextBoxHelper::syncProperty(GetFrameFormat(), RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any(aSize));
+}
+// #i31698#
+// implementation of virtual methods from drawing::XShapeDescriptor
+OUString SAL_CALL SwXShape::getShapeType()
+{
+ if ( mxShape.is() )
+ {
+ return mxShape->getShapeType();
+ }
+ return OUString();
+}
+/** method to determine top group object
+ #i31698#
+*/
+SdrObject* SwXShape::GetTopGroupObj( SvxShape* _pSvxShape )
+{
+ SdrObject* pTopGroupObj( nullptr );
+
+ SvxShape* pSvxShape = _pSvxShape ? _pSvxShape : GetSvxShape();
+ if ( pSvxShape )
+ {
+ SdrObject* pSdrObj = pSvxShape->GetSdrObject();
+ if ( pSdrObj && pSdrObj->getParentSdrObjectFromSdrObject() )
+ {
+ pTopGroupObj = pSdrObj->getParentSdrObjectFromSdrObject();
+ while ( pTopGroupObj->getParentSdrObjectFromSdrObject() )
+ {
+ pTopGroupObj = pTopGroupObj->getParentSdrObjectFromSdrObject();
+ }
+ }
+ }
+
+ return pTopGroupObj;
+}
+
+/** method to determine position according to the positioning attributes
+ #i31698#
+*/
+awt::Point SwXShape::GetAttrPosition()
+{
+ awt::Point aAttrPos;
+
+ uno::Any aHoriPos( getPropertyValue("HoriOrientPosition") );
+ aHoriPos >>= aAttrPos.X;
+ uno::Any aVertPos( getPropertyValue("VertOrientPosition") );
+ aVertPos >>= aAttrPos.Y;
+ // #i35798# - fallback, if attribute position is (0,0)
+ // and no anchor position is applied to the drawing object
+ SvxShape* pSvxShape = GetSvxShape();
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ if ( pObj &&
+ pObj->GetAnchorPos().X() == 0 &&
+ pObj->GetAnchorPos().Y() == 0 &&
+ aAttrPos.X == 0 && aAttrPos.Y == 0 )
+ {
+ const tools::Rectangle aObjRect = pObj->GetSnapRect();
+ aAttrPos.X = convertTwipToMm100(aObjRect.Left());
+ aAttrPos.Y = convertTwipToMm100(aObjRect.Top());
+ }
+ }
+ // #i35007# - If drawing object is anchored as-character,
+ // it's x-position isn't sensible. Thus, return the x-position as zero in this case.
+ text::TextContentAnchorType eTextAnchorType =
+ text::TextContentAnchorType_AT_PARAGRAPH;
+ {
+ uno::Any aAny = getPropertyValue( "AnchorType" );
+ aAny >>= eTextAnchorType;
+ }
+ if ( eTextAnchorType == text::TextContentAnchorType_AS_CHARACTER )
+ {
+ aAttrPos.X = 0;
+ }
+
+ return aAttrPos;
+}
+
+/** method to convert the position (translation) of the drawing object to
+ the layout direction horizontal left-to-right.
+ #i31698#
+*/
+awt::Point SwXShape::ConvertPositionToHoriL2R( const awt::Point& rObjPos,
+ const awt::Size& rObjSize )
+{
+ awt::Point aObjPosInHoriL2R( rObjPos );
+
+ SwFrameFormat* pFrameFormat = GetFrameFormat();
+ if ( pFrameFormat )
+ {
+ SwFrameFormat::tLayoutDir eLayoutDir = pFrameFormat->GetLayoutDir();
+ switch ( eLayoutDir )
+ {
+ case SwFrameFormat::HORI_L2R:
+ {
+ // nothing to do
+ }
+ break;
+ case SwFrameFormat::HORI_R2L:
+ {
+ aObjPosInHoriL2R.X = -rObjPos.X - rObjSize.Width;
+ }
+ break;
+ case SwFrameFormat::VERT_R2L:
+ {
+ aObjPosInHoriL2R.X = -rObjPos.Y - rObjSize.Width;
+ aObjPosInHoriL2R.Y = rObjPos.X;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwXShape::ConvertPositionToHoriL2R(..)> - unsupported layout direction" );
+ }
+ }
+ }
+
+ return aObjPosInHoriL2R;
+}
+
+/** method to convert the transformation of the drawing object to the layout
+ direction, the drawing object is in
+ #i31698#
+*/
+drawing::HomogenMatrix3 SwXShape::ConvertTransformationToLayoutDir(
+ const drawing::HomogenMatrix3& rMatrixInHoriL2R )
+{
+ drawing::HomogenMatrix3 aMatrix(rMatrixInHoriL2R);
+
+ // #i44334#, #i44681# - direct manipulation of the
+ // transformation structure isn't valid, if it contains rotation.
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE( pSvxShape,
+ "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SvxShape found!");
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ OSL_ENSURE( pObj,
+ "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SdrObject found!");
+ if ( pObj )
+ {
+ // get position of object in Writer coordinate system.
+ awt::Point aPos( getPosition() );
+ // get position of object in Drawing layer coordinate system
+ const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
+ const awt::Point aObjPos(
+ convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
+ convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
+ // determine difference between these positions according to the
+ // Writer coordinate system
+ const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
+ aPos.Y - aObjPos.Y );
+ // apply translation difference to transformation matrix.
+ if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
+ {
+ // #i73079# - use correct matrix type
+ ::basegfx::B2DHomMatrix aTempMatrix;
+
+ aTempMatrix.set(0, 0, aMatrix.Line1.Column1 );
+ aTempMatrix.set(0, 1, aMatrix.Line1.Column2 );
+ aTempMatrix.set(0, 2, aMatrix.Line1.Column3 );
+ aTempMatrix.set(1, 0, aMatrix.Line2.Column1 );
+ aTempMatrix.set(1, 1, aMatrix.Line2.Column2 );
+ aTempMatrix.set(1, 2, aMatrix.Line2.Column3 );
+ // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
+ assert( aMatrix.Line3.Column1 == 0 );
+ assert( aMatrix.Line3.Column2 == 0 );
+ assert( aMatrix.Line3.Column3 == 1 );
+ // #i73079#
+ aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y );
+ aMatrix.Line1.Column1 = aTempMatrix.get(0, 0);
+ aMatrix.Line1.Column2 = aTempMatrix.get(0, 1);
+ aMatrix.Line1.Column3 = aTempMatrix.get(0, 2);
+ aMatrix.Line2.Column1 = aTempMatrix.get(1, 0);
+ aMatrix.Line2.Column2 = aTempMatrix.get(1, 1);
+ aMatrix.Line2.Column3 = aTempMatrix.get(1, 2);
+ aMatrix.Line3.Column1 = 0;
+ aMatrix.Line3.Column2 = 0;
+ aMatrix.Line3.Column3 = 1;
+ }
+ }
+ }
+
+ return aMatrix;
+}
+
+/** method to adjust the positioning properties
+ #i31698#
+*/
+void SwXShape::AdjustPositionProperties( const awt::Point& rPosition )
+{
+ // handle x-position
+ // #i35007# - no handling of x-position, if drawing
+ // object is anchored as-character, because it doesn't make sense.
+ text::TextContentAnchorType eTextAnchorType =
+ text::TextContentAnchorType_AT_PARAGRAPH;
+ {
+ uno::Any aAny = getPropertyValue( "AnchorType" );
+ aAny >>= eTextAnchorType;
+ }
+ if ( eTextAnchorType != text::TextContentAnchorType_AS_CHARACTER )
+ {
+ // determine current x-position
+ static constexpr OUString aHoriPosPropStr(u"HoriOrientPosition"_ustr);
+ uno::Any aHoriPos( getPropertyValue( aHoriPosPropStr ) );
+ sal_Int32 dCurrX = 0;
+ aHoriPos >>= dCurrX;
+ // change x-position attribute, if needed
+ if ( dCurrX != rPosition.X )
+ {
+ // adjust x-position orientation to text::HoriOrientation::NONE, if needed
+ // Note: has to be done before setting x-position attribute
+ static constexpr OUString aHoriOrientPropStr(u"HoriOrient"_ustr);
+ uno::Any aHoriOrient( getPropertyValue( aHoriOrientPropStr ) );
+ sal_Int16 eHoriOrient;
+ if (aHoriOrient >>= eHoriOrient) // may be void
+ {
+ if ( eHoriOrient != text::HoriOrientation::NONE )
+ {
+ eHoriOrient = text::HoriOrientation::NONE;
+ aHoriOrient <<= eHoriOrient;
+ setPropertyValue( aHoriOrientPropStr, aHoriOrient );
+ }
+ }
+ // set x-position attribute
+ aHoriPos <<= rPosition.X;
+ setPropertyValue( aHoriPosPropStr, aHoriPos );
+ }
+ }
+
+ // handle y-position
+ {
+ // determine current y-position
+ static constexpr OUString aVertPosPropStr(u"VertOrientPosition"_ustr);
+ uno::Any aVertPos( getPropertyValue( aVertPosPropStr ) );
+ sal_Int32 dCurrY = 0;
+ aVertPos >>= dCurrY;
+ // change y-position attribute, if needed
+ if ( dCurrY != rPosition.Y )
+ {
+ // adjust y-position orientation to text::VertOrientation::NONE, if needed
+ // Note: has to be done before setting y-position attribute
+ static constexpr OUString aVertOrientPropStr(u"VertOrient"_ustr);
+ uno::Any aVertOrient( getPropertyValue( aVertOrientPropStr ) );
+ sal_Int16 eVertOrient;
+ if (aVertOrient >>= eVertOrient) // may be void
+ {
+ if ( eVertOrient != text::VertOrientation::NONE )
+ {
+ eVertOrient = text::VertOrientation::NONE;
+ aVertOrient <<= eVertOrient;
+ setPropertyValue( aVertOrientPropStr, aVertOrient );
+ }
+ }
+ // set y-position attribute
+ aVertPos <<= rPosition.Y;
+ setPropertyValue( aVertPosPropStr, aVertPos );
+ }
+ }
+}
+
+/** method to convert start or end position of the drawing object to the
+ Writer specific position, which is the attribute position in layout direction
+ #i59051#
+*/
+css::awt::Point SwXShape::ConvertStartOrEndPosToLayoutDir(
+ const css::awt::Point& aStartOrEndPos )
+{
+ awt::Point aConvertedPos( aStartOrEndPos );
+
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE( pSvxShape,
+ "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ OSL_ENSURE( pObj,
+ "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
+ if ( pObj )
+ {
+ // get position of object in Writer coordinate system.
+ awt::Point aPos( getPosition() );
+ // get position of object in Drawing layer coordinate system
+ const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
+ const awt::Point aObjPos(
+ convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
+ convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
+ // determine difference between these positions according to the
+ // Writer coordinate system
+ const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
+ aPos.Y - aObjPos.Y );
+ // apply translation difference to transformation matrix.
+ if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
+ {
+ aConvertedPos.X = aConvertedPos.X + aTranslateDiff.X;
+ aConvertedPos.Y = aConvertedPos.Y + aTranslateDiff.Y;
+ }
+ }
+ }
+
+ return aConvertedPos;
+}
+
+css::drawing::PolyPolygonBezierCoords SwXShape::ConvertPolyPolygonBezierToLayoutDir(
+ const css::drawing::PolyPolygonBezierCoords& aPath )
+{
+ drawing::PolyPolygonBezierCoords aConvertedPath( aPath );
+
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE( pSvxShape,
+ "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ OSL_ENSURE( pObj,
+ "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
+ if ( pObj )
+ {
+ // get position of object in Writer coordinate system.
+ awt::Point aPos( getPosition() );
+ // get position of object in Drawing layer coordinate system
+ const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
+ const awt::Point aObjPos(
+ convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
+ convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
+ // determine difference between these positions according to the
+ // Writer coordinate system
+ const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
+ aPos.Y - aObjPos.Y );
+ // apply translation difference to PolyPolygonBezier.
+ if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
+ {
+ const basegfx::B2DHomMatrix aMatrix(basegfx::utils::createTranslateB2DHomMatrix(
+ aTranslateDiff.X, aTranslateDiff.Y));
+
+ for(drawing::PointSequence& rInnerSequence : asNonConstRange(aConvertedPath.Coordinates))
+ {
+ for(awt::Point& rPoint : asNonConstRange(rInnerSequence))
+ {
+ basegfx::B2DPoint aNewCoordinatePair(rPoint.X, rPoint.Y);
+ aNewCoordinatePair *= aMatrix;
+ rPoint.X = basegfx::fround(aNewCoordinatePair.getX());
+ rPoint.Y = basegfx::fround(aNewCoordinatePair.getY());
+ }
+ }
+ }
+ }
+ }
+
+ return aConvertedPath;
+}
+
+SwXGroupShape::SwXGroupShape(uno::Reference<XInterface> & xShape,
+ SwDoc const*const pDoc)
+ : SwXShape(xShape, pDoc)
+{
+#if OSL_DEBUG_LEVEL > 0
+ uno::Reference<XShapes> xShapes(m_xShapeAgg, uno::UNO_QUERY);
+ OSL_ENSURE(xShapes.is(), "no SvxShape found or shape is not a group shape");
+#endif
+}
+
+SwXGroupShape::~SwXGroupShape()
+{
+}
+
+uno::Any SwXGroupShape::queryInterface( const uno::Type& rType )
+{
+ uno::Any aRet;
+ if(rType == cppu::UnoType<XShapes>::get())
+ aRet <<= uno::Reference<XShapes>(this);
+ else
+ aRet = SwXShape::queryInterface(rType);
+ return aRet;
+}
+
+void SwXGroupShape::acquire( ) noexcept
+{
+ SwXShape::acquire();
+}
+
+void SwXGroupShape::release( ) noexcept
+{
+ SwXShape::release();
+}
+
+void SwXGroupShape::add( const uno::Reference< XShape >& xShape )
+{
+ SolarMutexGuard aGuard;
+ SvxShape* pSvxShape = GetSvxShape();
+ SwFrameFormat* pFormat = GetFrameFormat();
+ if(!(pSvxShape && pFormat))
+ throw uno::RuntimeException();
+
+ uno::Reference<XShapes> xShapes;
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rType = cppu::UnoType<XShapes>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
+ aAgg >>= xShapes;
+ }
+ if(!xShapes.is())
+ throw uno::RuntimeException();
+
+ xShapes->add(xShape);
+
+
+ uno::Reference<lang::XUnoTunnel> xTunnel(xShape, uno::UNO_QUERY);
+ SwXShape* pSwShape = comphelper::getFromUnoTunnel<SwXShape>(xTunnel);
+ if(!(pSwShape && pSwShape->m_bDescriptor))
+ return;
+
+ SvxShape* pAddShape = comphelper::getFromUnoTunnel<SvxShape>(xTunnel);
+ if(pAddShape)
+ {
+ SdrObject* pObj = pAddShape->GetSdrObject();
+ if(pObj)
+ {
+ SwDoc* pDoc = pFormat->GetDoc();
+ // set layer of new drawing
+ // object to corresponding invisible layer.
+ if( SdrInventor::FmForm != pObj->GetObjInventor())
+ {
+ pObj->SetLayer( pSwShape->m_pImpl->GetOpaque()
+ ? pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId()
+ : pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
+ }
+ else
+ {
+ pObj->SetLayer(pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
+ }
+ }
+ }
+ pSwShape->m_bDescriptor = false;
+}
+
+void SwXGroupShape::remove( const uno::Reference< XShape >& xShape )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XShapes> xShapes;
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rType = cppu::UnoType<XShapes>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
+ aAgg >>= xShapes;
+ }
+ if(!xShapes.is())
+ throw uno::RuntimeException();
+ xShapes->remove(xShape);
+}
+
+sal_Int32 SwXGroupShape::getCount()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->getCount();
+}
+
+uno::Any SwXGroupShape::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->getByIndex(nIndex);
+}
+
+uno::Type SwXGroupShape::getElementType( )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->getElementType();
+}
+
+sal_Bool SwXGroupShape::hasElements( )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( m_xShapeAgg.is() )
+ {
+ const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
+ uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->hasElements();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */