resolves tdf#164985 Incorrect bookmarks list in bookmark dialog after
[LibreOffice.git] / sw / source / core / unocore / unodraw.cxx
blob991f40fdd01334293f5b726ee15b494a3d1b3a1b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <initializer_list>
23 #include <memory>
24 #include <string_view>
26 #include <sal/log.hxx>
28 #include <cmdid.h>
29 #include <unomid.h>
31 #include <drawdoc.hxx>
32 #include <unodraw.hxx>
33 #include <unoframe.hxx>
34 #include <unoparagraph.hxx>
35 #include <unotextrange.hxx>
36 #include <svx/svditer.hxx>
37 #include <swunohelper.hxx>
38 #include <textboxhelper.hxx>
39 #include <doc.hxx>
40 #include <IDocumentUndoRedo.hxx>
41 #include <IDocumentDrawModelAccess.hxx>
42 #include <IDocumentLayoutAccess.hxx>
43 #include <fmtcntnt.hxx>
44 #include <fmtflcnt.hxx>
45 #include <txatbase.hxx>
46 #include <docsh.hxx>
47 #include <unomap.hxx>
48 #include <unoport.hxx>
49 #include <TextCursorHelper.hxx>
50 #include <dflyobj.hxx>
51 #include <ndtxt.hxx>
52 #include <svx/svdview.hxx>
53 #include <svx/unoshape.hxx>
54 #include <dcontact.hxx>
55 #include <fmtornt.hxx>
56 #include <fmtsrnd.hxx>
57 #include <fmtfollowtextflow.hxx>
58 #include <rootfrm.hxx>
59 #include <editeng/lrspitem.hxx>
60 #include <editeng/ulspitem.hxx>
61 #include <o3tl/any.hxx>
62 #include <o3tl/safeint.hxx>
63 #include <crstate.hxx>
64 #include <comphelper/extract.hxx>
65 #include <comphelper/profilezone.hxx>
66 #include <comphelper/sequence.hxx>
67 #include <cppuhelper/supportsservice.hxx>
68 #include <svx/scene3d.hxx>
69 #include <tools/UnitConversion.hxx>
70 #include <com/sun/star/beans/PropertyAttribute.hpp>
71 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
72 #include <com/sun/star/frame/XModel.hpp>
73 #include <fmtwrapinfluenceonobjpos.hxx>
74 #include <com/sun/star/text/TextContentAnchorType.hpp>
75 #include <basegfx/matrix/b2dhommatrixtools.hxx>
76 #include <com/sun/star/drawing/PointSequence.hpp>
77 #include <com/sun/star/lang/IllegalArgumentException.hpp>
78 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
79 #include <docmodel/uno/UnoTheme.hxx>
81 using namespace ::com::sun::star;
83 class SwShapeDescriptor_Impl
85 bool m_isInReading;
86 std::unique_ptr<SwFormatHoriOrient> m_pHOrient;
87 std::unique_ptr<SwFormatVertOrient> m_pVOrient;
88 std::unique_ptr<SwFormatAnchor> m_pAnchor;
89 std::unique_ptr<SwFormatSurround> m_pSurround;
90 std::unique_ptr<SvxULSpaceItem> m_pULSpace;
91 std::unique_ptr<SvxLRSpaceItem> m_pLRSpace;
92 bool m_bOpaque;
93 uno::Reference< text::XTextRange > m_xTextRange;
94 // #i26791#
95 std::unique_ptr<SwFormatFollowTextFlow> m_pFollowTextFlow;
96 // #i28701#
97 std::unique_ptr<SwFormatWrapInfluenceOnObjPos> m_pWrapInfluenceOnObjPos;
98 // #i28749#
99 sal_Int16 mnPositionLayoutDir;
101 SwShapeDescriptor_Impl(const SwShapeDescriptor_Impl&) = delete;
102 SwShapeDescriptor_Impl& operator=(const SwShapeDescriptor_Impl&) = delete;
104 public:
105 SwShapeDescriptor_Impl(SwDoc const*const pDoc)
106 : m_isInReading(pDoc && pDoc->IsInReading())
107 // #i32349# - no defaults, in order to determine on
108 // adding a shape, if positioning attributes are set or not.
109 , m_bOpaque(false)
110 // #i26791#
111 , m_pFollowTextFlow( new SwFormatFollowTextFlow(false) )
112 // #i28701# #i35017#
113 , m_pWrapInfluenceOnObjPos( new SwFormatWrapInfluenceOnObjPos(
114 text::WrapInfluenceOnPosition::ONCE_CONCURRENT) )
115 // #i28749#
116 , mnPositionLayoutDir(text::PositionLayoutDir::PositionInLayoutDirOfAnchor)
119 SwFormatAnchor* GetAnchor(bool bCreate = false)
121 if (bCreate && !m_pAnchor)
123 m_pAnchor.reset(new SwFormatAnchor(RndStdIds::FLY_AS_CHAR));
125 return m_pAnchor.get();
127 SwFormatHoriOrient* GetHOrient(bool bCreate = false)
129 if (bCreate && !m_pHOrient)
131 // #i26791#
132 m_pHOrient.reset(new SwFormatHoriOrient(0, text::HoriOrientation::NONE, text::RelOrientation::FRAME));
134 return m_pHOrient.get();
136 SwFormatVertOrient* GetVOrient(bool bCreate = false)
138 if (bCreate && !m_pVOrient)
140 if (m_isInReading && // tdf#113938 extensions might rely on old default
141 (!GetAnchor(true) || m_pAnchor->GetAnchorId() == RndStdIds::FLY_AS_CHAR))
142 { // for as-char, NONE ("from-top") is not a good default
143 m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::TOP, text::RelOrientation::FRAME));
145 else
146 { // #i26791#
147 m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::NONE, text::RelOrientation::FRAME));
150 return m_pVOrient.get();
153 SwFormatSurround* GetSurround(bool bCreate = false)
155 if (bCreate && !m_pSurround)
157 m_pSurround.reset(new SwFormatSurround());
159 return m_pSurround.get();
161 SvxLRSpaceItem* GetLRSpace(bool bCreate = false)
163 if (bCreate && !m_pLRSpace)
165 m_pLRSpace.reset(new SvxLRSpaceItem(RES_LR_SPACE));
167 return m_pLRSpace.get();
169 SvxULSpaceItem* GetULSpace(bool bCreate = false)
171 if (bCreate && !m_pULSpace)
173 m_pULSpace.reset(new SvxULSpaceItem(RES_UL_SPACE));
175 return m_pULSpace.get();
177 uno::Reference< text::XTextRange > & GetTextRange()
179 return m_xTextRange;
181 bool IsOpaque() const
183 return m_bOpaque;
185 const bool& GetOpaque() const
187 return m_bOpaque;
189 void RemoveHOrient() { m_pHOrient.reset(); }
190 void RemoveVOrient() { m_pVOrient.reset(); }
191 void RemoveAnchor() { m_pAnchor.reset(); }
192 void RemoveSurround() { m_pSurround.reset(); }
193 void RemoveULSpace() { m_pULSpace.reset(); }
194 void RemoveLRSpace() { m_pLRSpace.reset(); }
195 void SetOpaque(bool bSet){m_bOpaque = bSet;}
197 // #i26791#
198 SwFormatFollowTextFlow* GetFollowTextFlow( bool _bCreate = false )
200 if (_bCreate && !m_pFollowTextFlow)
202 m_pFollowTextFlow.reset(new SwFormatFollowTextFlow(false));
204 return m_pFollowTextFlow.get();
206 void RemoveFollowTextFlow()
208 m_pFollowTextFlow.reset();
211 // #i28749#
212 sal_Int16 GetPositionLayoutDir() const
214 return mnPositionLayoutDir;
216 void SetPositionLayoutDir( sal_Int16 _nPositionLayoutDir )
218 switch ( _nPositionLayoutDir )
220 case text::PositionLayoutDir::PositionInHoriL2R:
221 case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
223 mnPositionLayoutDir = _nPositionLayoutDir;
225 break;
226 default:
228 OSL_FAIL( "<SwShapeDescriptor_Impl::SetPositionLayoutDir(..)> - invalid attribute value." );
233 // #i28701#
234 SwFormatWrapInfluenceOnObjPos* GetWrapInfluenceOnObjPos(
235 const bool _bCreate = false )
237 if (_bCreate && !m_pWrapInfluenceOnObjPos)
239 m_pWrapInfluenceOnObjPos.reset(new SwFormatWrapInfluenceOnObjPos(
240 // #i35017#
241 text::WrapInfluenceOnPosition::ONCE_CONCURRENT));
243 return m_pWrapInfluenceOnObjPos.get();
245 void RemoveWrapInfluenceOnObjPos()
247 m_pWrapInfluenceOnObjPos.reset();
251 SwFmDrawPage::SwFmDrawPage( SwDoc* pDoc, SdrPage* pPage )
252 : SwFmDrawPage_Base(pPage)
253 , m_pDoc(pDoc)
254 , m_pPageView(nullptr)
255 , m_pPropertySet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_PAGE))
259 SwFmDrawPage::~SwFmDrawPage() noexcept
261 while (!m_vShapes.empty())
262 m_vShapes.back()->dispose();
263 RemovePageView();
266 const SdrMarkList& SwFmDrawPage::PreGroup(const uno::Reference< drawing::XShapes > & xShapes)
268 SelectObjectsInView( xShapes, GetPageView() );
269 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
270 return rMarkList;
273 void SwFmDrawPage::PreUnGroup(const uno::Reference< drawing::XShapeGroup >& rShapeGroup)
275 SelectObjectInView( rShapeGroup, GetPageView() );
278 SdrPageView* SwFmDrawPage::GetPageView()
280 if(!m_pPageView)
281 m_pPageView = mpView->ShowSdrPage( mpPage );
282 return m_pPageView;
285 void SwFmDrawPage::RemovePageView()
287 if(m_pPageView && mpView)
288 mpView->HideSdrPage();
289 m_pPageView = nullptr;
292 uno::Reference<drawing::XShape> SwFmDrawPage::GetShape(SdrObject* pObj)
294 if(!pObj)
295 return nullptr;
296 SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
297 // TODO see comment at
298 // <https://gerrit.libreoffice.org/c/core/+/78734/4#message-5ee4e724a8073c5c475f07da0b5d79bc34e61de5>
299 // "make page bookkeep the SwXShapes" [-loplugin:crosscast]:
300 SwFmDrawPage* pPage = dynamic_cast<SwFmDrawPage*>(pFormat);
301 if(!pPage || pPage->m_vShapes.empty())
302 return uno::Reference<drawing::XShape>(pObj->getUnoShape(), uno::UNO_QUERY);
303 for(const auto & pShape : pPage->m_vShapes)
305 SvxShape* pSvxShape = pShape->GetSvxShape();
306 if (pSvxShape && pSvxShape->GetSdrObject() == pObj)
307 return pShape;
309 return nullptr;
312 uno::Reference<drawing::XShapeGroup> SwFmDrawPage::GetShapeGroup(SdrObject* pObj)
314 return uno::Reference<drawing::XShapeGroup>(GetShape(pObj), uno::UNO_QUERY);
317 uno::Reference< drawing::XShape > SwFmDrawPage::CreateShape( SdrObject *pObj ) const
319 assert(pObj);
320 uno::Reference< drawing::XShape > xRet;
321 if(dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr || pObj->GetObjInventor() == SdrInventor::Swg)
323 SwFlyDrawContact* pFlyContact = static_cast<SwFlyDrawContact*>(pObj->GetUserCall());
324 if(pFlyContact)
326 SwFrameFormat* pFlyFormat = pFlyContact->GetFormat();
327 SwDoc* pDoc = pFlyFormat->GetDoc();
328 const SwNodeIndex* pIdx;
329 if( RES_FLYFRMFMT == pFlyFormat->Which()
330 && nullptr != ( pIdx = pFlyFormat->GetContent().GetContentIdx() )
331 && pIdx->GetNodes().IsDocNodes()
334 const SwNode* pNd = pDoc->GetNodes()[ pIdx->GetIndex() + 1 ];
335 if(!pNd->IsNoTextNode())
337 xRet.set(cppu::getXWeak(SwXTextFrame::CreateXTextFrame(*pDoc, pFlyFormat).get()),
338 uno::UNO_QUERY);
340 else if( pNd->IsGrfNode() )
342 xRet.set(cppu::getXWeak(SwXTextGraphicObject::CreateXTextGraphicObject(
343 *pDoc, pFlyFormat).get()), uno::UNO_QUERY);
345 else if( pNd->IsOLENode() )
347 xRet.set(cppu::getXWeak(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
348 *pDoc, pFlyFormat).get()), uno::UNO_QUERY);
351 else
353 OSL_FAIL( "<SwFmDrawPage::CreateShape(..)> - could not retrieve type. Thus, no shape created." );
354 return xRet;
358 else
360 // own block - temporary object has to be destroyed before
361 // the delegator is set #81670#
363 xRet = SvxDrawPage::CreateShape( pObj );
365 uno::Reference< XUnoTunnel > xShapeTunnel(xRet, uno::UNO_QUERY);
366 //don't create an SwXShape if it already exists
367 rtl::Reference<SwXShape> pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
368 if(!pShape)
370 xShapeTunnel = nullptr;
371 uno::Reference< uno::XInterface > xCreate(xRet, uno::UNO_QUERY);
372 xRet = nullptr;
373 if ( pObj->IsGroupObject() && (!pObj->Is3DObj() || DynCastE3dScene(pObj)) )
374 pShape = new SwXGroupShape(xCreate, nullptr);
375 else
376 pShape = new SwXShape(xCreate, nullptr);
377 xRet = pShape;
379 const_cast<std::vector<rtl::Reference<SwXShape>>*>(&m_vShapes)->push_back(pShape);
380 pShape->m_pPage = this;
382 return xRet;
385 uno::Reference<beans::XPropertySetInfo> SwFmDrawPage::getPropertySetInfo()
387 static uno::Reference<beans::XPropertySetInfo> xRet = m_pPropertySet->getPropertySetInfo();
388 return xRet;
391 void SwFmDrawPage::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
393 SolarMutexGuard aGuard;
394 const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName(rPropertyName);
396 switch (pEntry ? pEntry->nWID : -1)
398 case WID_PAGE_THEME:
400 SdrPage* pPage = GetSdrPage();
401 css::uno::Reference<css::util::XTheme> xTheme;
402 if (aValue >>= xTheme)
404 auto& rUnoTheme = dynamic_cast<UnoTheme&>(*xTheme);
405 pPage->getSdrModelFromSdrPage().setTheme(rUnoTheme.getTheme());
408 break;
409 case WID_PAGE_BOTTOM:
410 case WID_PAGE_LEFT:
411 case WID_PAGE_RIGHT:
412 case WID_PAGE_TOP:
413 case WID_PAGE_WIDTH:
414 case WID_PAGE_HEIGHT:
415 case WID_PAGE_NUMBER:
416 case WID_PAGE_ORIENT:
417 case WID_PAGE_USERATTRIBS:
418 case WID_PAGE_ISDARK:
419 case WID_NAVORDER:
420 case WID_PAGE_BACKFULL:
421 break;
423 default:
424 throw beans::UnknownPropertyException(rPropertyName, getXWeak());
428 uno::Any SwFmDrawPage::getPropertyValue(const OUString& rPropertyName)
430 SolarMutexGuard aGuard;
431 const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName( rPropertyName);
433 uno::Any aAny;
435 switch (pEntry ? pEntry->nWID : -1)
437 case WID_PAGE_THEME:
439 css::uno::Reference<css::util::XTheme> xTheme;
441 auto pTheme = GetSdrPage()->getSdrModelFromSdrPage().getTheme();
442 if (pTheme)
443 xTheme = model::theme::createXTheme(pTheme);
444 aAny <<= xTheme;
446 break;
448 case WID_PAGE_NUMBER:
450 const sal_uInt16 nPageNumber(GetSdrPage()->GetPageNum());
451 aAny <<= o3tl::narrowing<sal_Int16>(nPageNumber);
453 break;
455 case WID_PAGE_BOTTOM:
456 case WID_PAGE_LEFT:
457 case WID_PAGE_RIGHT:
458 case WID_PAGE_TOP:
459 case WID_PAGE_WIDTH:
460 case WID_PAGE_HEIGHT:
461 case WID_PAGE_ORIENT:
462 case WID_PAGE_USERATTRIBS:
463 case WID_PAGE_ISDARK:
464 case WID_NAVORDER:
465 case WID_PAGE_BACKFULL:
466 break;
468 default:
469 throw beans::UnknownPropertyException(rPropertyName, getXWeak());
471 return aAny;
474 void SwFmDrawPage::addPropertyChangeListener(const OUString& /*PropertyName*/,
475 const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
477 OSL_FAIL("not implemented");
480 void SwFmDrawPage::removePropertyChangeListener(const OUString& /*PropertyName*/,
481 const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
483 OSL_FAIL("not implemented");
486 void SwFmDrawPage::addVetoableChangeListener(const OUString& /*PropertyName*/,
487 const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
489 OSL_FAIL("not implemented");
492 void SwFmDrawPage::removeVetoableChangeListener(const OUString& /*PropertyName*/,
493 const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
495 OSL_FAIL("not implemented");
498 namespace
500 class SwXShapesEnumeration
501 : public SwSimpleEnumeration_Base
503 private:
504 std::vector< css::uno::Any > m_aShapes;
505 protected:
506 virtual ~SwXShapesEnumeration() override {};
507 public:
508 explicit SwXShapesEnumeration(SwFmDrawPage* const pDrawPage);
510 //XEnumeration
511 virtual sal_Bool SAL_CALL hasMoreElements() override;
512 virtual uno::Any SAL_CALL nextElement() override;
514 //XServiceInfo
515 virtual OUString SAL_CALL getImplementationName() override;
516 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
517 virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
521 SwXShapesEnumeration::SwXShapesEnumeration(SwFmDrawPage* const pDrawPage)
523 SolarMutexGuard aGuard;
524 sal_Int32 nCount = pDrawPage->getCount();
525 m_aShapes.reserve(nCount);
526 for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
528 uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
529 m_aShapes.push_back(uno::Any(xShape));
533 sal_Bool SwXShapesEnumeration::hasMoreElements()
535 SolarMutexGuard aGuard;
536 return !m_aShapes.empty();
539 uno::Any SwXShapesEnumeration::nextElement()
541 SolarMutexGuard aGuard;
542 if(m_aShapes.empty())
543 throw container::NoSuchElementException();
544 uno::Any aResult = m_aShapes.back();
545 m_aShapes.pop_back();
546 return aResult;
549 OUString SwXShapesEnumeration::getImplementationName()
551 return u"SwXShapeEnumeration"_ustr;
554 sal_Bool SwXShapesEnumeration::supportsService(const OUString& ServiceName)
556 return cppu::supportsService(this, ServiceName);
559 uno::Sequence< OUString > SwXShapesEnumeration::getSupportedServiceNames()
561 return { u"com.sun.star.container.XEnumeration"_ustr };
564 uno::Reference< container::XEnumeration > SwFmDrawPage::createEnumeration()
566 SolarMutexGuard aGuard;
567 return uno::Reference< container::XEnumeration >(
568 new SwXShapesEnumeration(this));
571 OUString SwFmDrawPage::getImplementationName()
573 return u"SwFmDrawPage"_ustr;
576 sal_Bool SwFmDrawPage::supportsService(const OUString& rServiceName)
578 return cppu::supportsService(this, rServiceName);
581 uno::Sequence< OUString > SwFmDrawPage::getSupportedServiceNames()
583 return { u"com.sun.star.drawing.GenericDrawPage"_ustr };
586 sal_Int32 SwFmDrawPage::getCount()
588 SolarMutexGuard aGuard;
589 if(!m_pDoc)
590 throw uno::RuntimeException();
591 if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
592 return 0;
593 else
594 return SwTextBoxHelper::getCount(GetSdrPage());
597 uno::Any SwFmDrawPage::getByIndex(sal_Int32 nIndex)
599 SolarMutexGuard aGuard;
600 if(!m_pDoc)
601 throw uno::RuntimeException();
602 if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
603 throw lang::IndexOutOfBoundsException();
605 return SwTextBoxHelper::getByIndex(GetSdrPage(), nIndex);
608 uno::Type SwFmDrawPage::getElementType()
610 return cppu::UnoType<drawing::XShape>::get();
613 sal_Bool SwFmDrawPage::hasElements()
615 SolarMutexGuard aGuard;
616 if(!m_pDoc)
617 throw uno::RuntimeException();
618 if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
619 return false;
620 return SvxDrawPage::hasElements();
623 void SwFmDrawPage::add(const uno::Reference< drawing::XShape > & xShape)
625 SolarMutexGuard aGuard;
626 if(!m_pDoc)
627 throw uno::RuntimeException();
628 uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShape, uno::UNO_QUERY);
629 SwXShape* pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
630 SvxShape* pSvxShape = comphelper::getFromUnoTunnel<SvxShape>(xShapeTunnel);
632 // this is not a writer shape
633 if(!pShape)
634 throw uno::RuntimeException(u"illegal object"_ustr,
635 getXWeak() );
637 // we're already registered in the model / SwXDrawPage::add() already called
638 if(pShape->m_pPage || !pShape->m_bDescriptor )
639 return;
641 // we're inserted elsewhere already
642 if ( pSvxShape->GetSdrObject() )
644 if ( pSvxShape->GetSdrObject()->IsInserted() )
646 return;
649 SvxDrawPage::add(xShape);
651 OSL_ENSURE(pSvxShape, "Why is here no SvxShape?");
652 // this position is definitely in 1/100 mm
653 awt::Point aMM100Pos(pSvxShape->getPosition());
655 // now evaluate the properties of SwShapeDescriptor_Impl
656 SwShapeDescriptor_Impl* pDesc = pShape->GetDescImpl();
658 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSet( m_pDoc->GetAttrPool() );
659 SwFormatAnchor aAnchor( RndStdIds::FLY_AS_CHAR );
660 bool bOpaque = false;
661 if( pDesc )
663 if(pDesc->GetSurround())
664 aSet.Put( *pDesc->GetSurround());
665 // all items are already in Twip
666 if(pDesc->GetLRSpace())
668 aSet.Put(*pDesc->GetLRSpace());
670 if(pDesc->GetULSpace())
672 aSet.Put(*pDesc->GetULSpace());
674 if(pDesc->GetAnchor())
675 aAnchor = *pDesc->GetAnchor();
677 // #i32349# - if no horizontal position exists, create one
678 if ( !pDesc->GetHOrient() )
680 SwFormatHoriOrient* pHori = pDesc->GetHOrient( true );
681 SwTwips nHoriPos = o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100);
682 pHori->SetPos( nHoriPos );
685 if(pDesc->GetHOrient()->GetHoriOrient() == text::HoriOrientation::NONE)
686 aMM100Pos.X = convertTwipToMm100(pDesc->GetHOrient()->GetPos());
687 aSet.Put( *pDesc->GetHOrient() );
689 // #i32349# - if no vertical position exists, create one
690 if ( !pDesc->GetVOrient() )
692 SwFormatVertOrient* pVert = pDesc->GetVOrient( true );
693 SwTwips nVertPos = o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100);
694 pVert->SetPos( nVertPos );
697 if(pDesc->GetVOrient()->GetVertOrient() == text::VertOrientation::NONE)
698 aMM100Pos.Y = convertTwipToMm100(pDesc->GetVOrient()->GetPos());
699 aSet.Put( *pDesc->GetVOrient() );
702 if(pDesc->GetSurround())
703 aSet.Put( *pDesc->GetSurround());
704 bOpaque = pDesc->IsOpaque();
706 // #i26791#
707 if ( pDesc->GetFollowTextFlow() )
709 aSet.Put( *pDesc->GetFollowTextFlow() );
712 // #i28701#
713 if ( pDesc->GetWrapInfluenceOnObjPos() )
715 aSet.Put( *pDesc->GetWrapInfluenceOnObjPos() );
719 pSvxShape->setPosition(aMM100Pos);
720 SdrObject* pObj = pSvxShape->GetSdrObject();
721 // #108784# - set layer of new drawing object to corresponding
722 // invisible layer.
723 if(SdrInventor::FmForm != pObj->GetObjInventor())
724 pObj->SetLayer( bOpaque ? m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() : m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
725 else
726 pObj->SetLayer(m_pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
728 std::optional<SwPaM> pPam(m_pDoc->GetNodes().GetEndOfContent());
729 std::unique_ptr<SwUnoInternalPaM> pInternalPam;
730 uno::Reference< text::XTextRange > xRg;
731 if( pDesc && (xRg = pDesc->GetTextRange()).is() )
733 pInternalPam.reset(new SwUnoInternalPaM(*m_pDoc));
734 if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg))
735 throw uno::RuntimeException();
737 if(RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId() &&
738 !pInternalPam->GetPointNode().FindFlyStartNode())
740 aAnchor.SetType(RndStdIds::FLY_AS_CHAR);
742 else if (RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId()
743 && 0 == aAnchor.GetPageNum())
745 aAnchor.SetAnchor(pInternalPam->Start());
746 aAnchor.SetType(RndStdIds::FLY_AT_CHAR); // convert invalid at-page
750 else if ((aAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
752 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
753 Point aTmp(o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100), o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100));
754 m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( pPam->GetPoint(), aTmp, &aState );
755 aAnchor.SetAnchor( pPam->GetPoint() );
757 // #i32349# - adjustment of vertical positioning
758 // attributes no longer needed, because it's already got a default.
760 else
762 aAnchor.SetType(RndStdIds::FLY_AT_PAGE);
764 // #i32349# - adjustment of vertical positioning
765 // attributes no longer needed, because it's already got a default.
767 aSet.Put(aAnchor);
768 SwPaM* pTemp = pInternalPam.get();
769 if ( !pTemp )
770 pTemp = &*pPam;
771 UnoActionContext aAction(m_pDoc);
772 m_pDoc->getIDocumentContentOperations().InsertDrawObj( *pTemp, *pObj, aSet );
774 if (pSvxShape->GetSdrObject()->GetName().isEmpty())
776 pSvxShape->GetSdrObject()->SetName(m_pDoc->GetUniqueShapeName());
779 SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
780 if (pFormat)
782 if (pFormat->GetName().isEmpty())
784 pFormat->SetFormatName(pSvxShape->GetSdrObject()->GetName(), false);
787 pShape->m_bDescriptor = false;
789 pPam.reset();
790 pInternalPam.reset();
793 void SwFmDrawPage::remove(const uno::Reference< drawing::XShape > & xShape)
795 SolarMutexGuard aGuard;
796 if(!m_pDoc)
797 throw uno::RuntimeException();
798 // tdf#41466 remove TextFrame too which is belonged to the actual shape
799 auto xTextFrame = SwTextBoxHelper::getUnoTextFrame(xShape);
800 if (xTextFrame)
802 uno::Reference<lang::XComponent> xComp(xTextFrame, uno::UNO_QUERY);
803 if (xComp)
804 xComp->dispose();
806 // remove shape
807 uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
808 xComp->dispose();
811 uno::Reference< drawing::XShapeGroup > SwFmDrawPage::group(const uno::Reference< drawing::XShapes > & xShapes)
813 SolarMutexGuard aGuard;
814 if(!m_pDoc || !xShapes.is())
815 throw uno::RuntimeException();
816 uno::Reference< drawing::XShapeGroup > xRet;
817 // mark and return MarkList
818 const SdrMarkList& rMarkList = PreGroup(xShapes);
819 if ( rMarkList.GetMarkCount() > 0 )
821 for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
823 const SdrObject *pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
824 if (RndStdIds::FLY_AS_CHAR == ::FindFrameFormat(const_cast<SdrObject*>(
825 pObj))->GetAnchor().GetAnchorId())
827 throw lang::IllegalArgumentException(
828 u"Shape must not have 'as character' anchor!"_ustr, nullptr, 0);
832 UnoActionContext aContext(m_pDoc);
833 m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
835 SwDrawContact* pContact = m_pDoc->GroupSelection( *GetDrawView() );
836 m_pDoc->ChgAnchor(
837 GetDrawView()->GetMarkedObjectList(),
838 RndStdIds::FLY_AT_PARA,
839 true, false );
841 GetDrawView()->UnmarkAll();
842 if(pContact)
843 xRet = SwFmDrawPage::GetShapeGroup( pContact->GetMaster() );
844 m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
846 RemovePageView();
847 return xRet;
850 void SwFmDrawPage::ungroup(const uno::Reference< drawing::XShapeGroup > & rShapeGroup)
852 SolarMutexGuard aGuard;
853 if(!m_pDoc)
854 throw uno::RuntimeException();
856 PreUnGroup(rShapeGroup);
857 UnoActionContext aContext(m_pDoc);
858 m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
860 m_pDoc->UnGroupSelection( *GetDrawView() );
861 m_pDoc->ChgAnchor( GetDrawView()->GetMarkedObjectList(),
862 RndStdIds::FLY_AT_PARA,
863 true, false );
864 m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
865 RemovePageView();
869 * Renamed and outlined to detect where it's called
871 void SwFmDrawPage::InvalidateSwDoc()
873 m_pDoc = nullptr;
876 const uno::Sequence< sal_Int8 > & SwXShape::getUnoTunnelId()
878 static const comphelper::UnoIdInit theSwXShapeUnoTunnelId;
879 return theSwXShapeUnoTunnelId.getSeq();
882 sal_Int64 SAL_CALL SwXShape::getSomething( const uno::Sequence< sal_Int8 >& rId )
884 if( comphelper::isUnoTunnelId<SwXShape>(rId) )
886 return comphelper::getSomething_cast(this);
889 if( m_xShapeAgg.is() )
891 const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
892 uno::Any aAgg = m_xShapeAgg->queryAggregation( rTunnelType );
893 if(auto xAggTunnel = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
894 aAgg))
896 if(xAggTunnel->is())
897 return (*xAggTunnel)->getSomething(rId);
900 return 0;
903 SwXShape::SwXShape(
904 uno::Reference<uno::XInterface> & xShape,
905 SwDoc const*const pDoc)
906 : m_pPage(nullptr)
907 , m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SHAPE))
908 , m_pPropertyMapEntries(aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_TEXT_SHAPE))
909 , m_pImpl(new SwShapeDescriptor_Impl(pDoc))
910 , m_bDescriptor(true)
912 if(!xShape.is()) // default Ctor
913 return;
915 const uno::Type& rAggType = cppu::UnoType<uno::XAggregation>::get();
916 //aAgg contains a reference of the SvxShape!
918 uno::Any aAgg = xShape->queryInterface(rAggType);
919 aAgg >>= m_xShapeAgg;
920 // #i31698#
921 if ( m_xShapeAgg.is() )
923 m_xShapeAgg->queryAggregation( cppu::UnoType<drawing::XShape>::get()) >>= mxShape;
924 OSL_ENSURE( mxShape.is(),
925 "<SwXShape::SwXShape(..)> - no XShape found at <xShapeAgg>" );
928 xShape = nullptr;
929 osl_atomic_increment(&m_refCount);
930 if( m_xShapeAgg.is() )
931 m_xShapeAgg->setDelegator( getXWeak() );
932 osl_atomic_decrement(&m_refCount);
935 SwFrameFormat* SwXShape::GetFrameFormat() const
937 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(m_xShapeAgg);
938 if(pObj)
939 return ::FindFrameFormat( pObj );
940 return nullptr;
943 void SwXShape::AddExistingShapeToFormat( SdrObject const & _rObj )
945 SdrObjListIter aIter( _rObj, SdrIterMode::DeepNoGroups );
946 while ( aIter.IsMore() )
948 SdrObject* pCurrent = aIter.Next();
949 OSL_ENSURE( pCurrent, "SwXShape::AddExistingShapeToFormat: invalid object list element!" );
950 if ( !pCurrent )
951 continue;
953 auto pSwShape = comphelper::getFromUnoTunnel<SwXShape>(pCurrent->getWeakUnoShape());
954 if ( pSwShape )
956 if ( pSwShape->m_bDescriptor )
957 pSwShape->m_bDescriptor = false;
962 SwXShape::~SwXShape()
964 SolarMutexGuard aGuard;
966 if (m_xShapeAgg.is())
968 uno::Reference< uno::XInterface > xRef;
969 m_xShapeAgg->setDelegator(xRef);
971 m_pImpl.reset();
972 if(m_pPage)
973 const_cast<SwFmDrawPage*>(m_pPage)->RemoveShape(this);
976 uno::Any SwXShape::queryInterface( const uno::Type& aType )
978 uno::Any aRet;
979 SdrObject* pObj = nullptr;
981 if ((aType == cppu::UnoType<text::XText>::get())
982 || (aType == cppu::UnoType<text::XTextRange>::get())
983 || (aType == cppu::UnoType<text::XTextAppend>::get()))
985 pObj = SdrObject::getSdrObjectFromXShape(mxShape);
987 aRet = SwTextBoxHelper::queryInterface(GetFrameFormat(), aType, pObj);
988 if (aRet.hasValue())
989 return aRet;
991 aRet = SwXShapeBaseClass::queryInterface(aType);
992 // #i53320# - follow-up of #i31698#
993 // interface drawing::XShape is overloaded. Thus, provide
994 // correct object instance.
995 if(!aRet.hasValue() && m_xShapeAgg.is())
997 if(aType == cppu::UnoType<XShape>::get())
998 aRet <<= uno::Reference<XShape>(this);
999 else
1000 aRet = m_xShapeAgg->queryAggregation(aType);
1002 return aRet;
1005 uno::Sequence< uno::Type > SwXShape::getTypes( )
1007 uno::Sequence< uno::Type > aRet = SwXShapeBaseClass::getTypes();
1008 if(m_xShapeAgg.is())
1010 uno::Any aProv = m_xShapeAgg->queryAggregation(cppu::UnoType<XTypeProvider>::get());
1011 if(aProv.hasValue())
1013 uno::Reference< XTypeProvider > xAggProv;
1014 aProv >>= xAggProv;
1015 return comphelper::concatSequences(aRet, xAggProv->getTypes());
1018 return aRet;
1021 uno::Sequence< sal_Int8 > SwXShape::getImplementationId( )
1023 return css::uno::Sequence<sal_Int8>();
1026 uno::Reference< beans::XPropertySetInfo > SwXShape::getPropertySetInfo()
1028 SolarMutexGuard aGuard;
1029 if (!mxPropertySetInfo)
1031 if(m_xShapeAgg.is())
1033 const uno::Type& rPropSetType = cppu::UnoType<beans::XPropertySet>::get();
1034 uno::Any aPSet = m_xShapeAgg->queryAggregation( rPropSetType );
1035 if(auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
1036 aPSet))
1038 uno::Reference< beans::XPropertySetInfo > xInfo = (*xPrSet)->getPropertySetInfo();
1039 // Expand PropertySetInfo!
1040 const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
1041 mxPropertySetInfo = new SfxExtItemPropertySetInfo( m_pPropertyMapEntries, aPropSeq );
1044 if(!mxPropertySetInfo)
1045 mxPropertySetInfo = m_pPropSet->getPropertySetInfo();
1047 return mxPropertySetInfo;
1050 void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
1052 SolarMutexGuard aGuard;
1053 SwFrameFormat* pFormat = GetFrameFormat();
1054 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1055 if(!m_xShapeAgg.is())
1056 return;
1058 if(pEntry)
1060 if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
1061 throw beans::PropertyVetoException ("Property is read-only: " + rPropertyName, getXWeak() );
1062 // with the layout it is possible to move the anchor without changing the position
1063 if(pFormat)
1065 SwAttrSet aSet(pFormat->GetAttrSet());
1066 SwDoc* pDoc = pFormat->GetDoc();
1067 if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
1069 bool bDone = false;
1070 uno::Reference<text::XTextFrame> xFrame;
1071 if(aValue >>= xFrame)
1073 SwXFrame* pFrame = dynamic_cast<SwXFrame*>(xFrame.get());
1074 if(pFrame && pFrame->GetFrameFormat() &&
1075 pFrame->GetFrameFormat()->GetDoc() == pDoc)
1077 UnoActionContext aCtx(pDoc);
1078 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aItemSet( pDoc->GetAttrPool() );
1079 aItemSet.SetParent(&pFormat->GetAttrSet());
1080 SwFormatAnchor aAnchor = static_cast<const SwFormatAnchor&>(aItemSet.Get(pEntry->nWID));
1081 SwPosition aPos(*pFrame->GetFrameFormat()->GetContent().GetContentIdx());
1082 aAnchor.SetAnchor(&aPos);
1083 aAnchor.SetType(RndStdIds::FLY_AT_FLY);
1084 aItemSet.Put(aAnchor);
1085 pFormat->SetFormatAttr(aItemSet);
1086 bDone = true;
1089 if(!bDone)
1090 throw lang::IllegalArgumentException();
1092 else if(RES_OPAQUE == pEntry->nWID)
1094 SvxShape* pSvxShape = GetSvxShape();
1095 SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
1096 if(pSvxShape)
1098 SdrObject* pObj = pSvxShape->GetSdrObject();
1099 // set layer of new drawing
1100 // object to corresponding invisible layer.
1101 bool bIsVisible = pDoc->getIDocumentDrawModelAccess().IsVisibleLayerId( pObj->GetLayer() );
1102 if(SdrInventor::FmForm != pObj->GetObjInventor())
1104 pObj->SetLayer( *o3tl::doAccess<bool>(aValue)
1105 ? ( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetHeavenId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() )
1106 : ( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetHellId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() ));
1108 else
1110 pObj->SetLayer( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetControlsId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
1116 // #i26791# - special handling for property FN_TEXT_RANGE
1117 else if ( FN_TEXT_RANGE == pEntry->nWID )
1119 SwFormatAnchor aAnchor( aSet.Get( RES_ANCHOR ) );
1120 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1122 // set property <TextRange> not valid for to-page anchored shapes
1123 throw lang::IllegalArgumentException();
1126 std::unique_ptr<SwUnoInternalPaM> pInternalPam(
1127 new SwUnoInternalPaM( *(pFormat->GetDoc()) ));
1128 uno::Reference< text::XTextRange > xRg;
1129 aValue >>= xRg;
1130 if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg) )
1132 throw uno::RuntimeException();
1135 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
1137 //delete old SwFormatFlyCnt
1138 //With AnchorAsCharacter the current TextAttribute has to be deleted.
1139 //Tbis removes the frame format too.
1140 //To prevent this the connection between format and attribute has to be broken before.
1141 SwTextNode *pTextNode = aAnchor.GetAnchorNode()->GetTextNode();
1142 SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno", "Missing FlyInCnt-Hint." );
1143 const sal_Int32 nIdx = aAnchor.GetAnchorContentOffset();
1144 SwTextAttr * const pHint =
1145 pTextNode->GetTextAttrForCharAt(
1146 nIdx, RES_TXTATR_FLYCNT );
1147 assert(pHint && "Missing Hint.");
1148 SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
1149 "sw.uno", "Missing FlyInCnt-Hint." );
1150 SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFormat,
1151 "sw.uno", "Wrong TextFlyCnt-Hint." );
1152 const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
1153 .SetFlyFormat();
1155 //The connection is removed now the attribute can be deleted.
1156 pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
1157 //create a new one
1158 SwTextNode *pNd = pInternalPam->GetPointNode().GetTextNode();
1159 SAL_WARN_IF( !pNd, "sw.uno", "Cursor not at TextNode." );
1160 SwFormatFlyCnt aFormat( pFormat );
1161 pNd->InsertItem(aFormat, pInternalPam->GetPoint()
1162 ->GetContentIndex(), 0 );
1163 //Refetch in case SwTextNode::InsertItem causes it to be deleted
1164 pFormat = GetFrameFormat();
1166 else
1168 aAnchor.SetAnchor( pInternalPam->GetPoint() );
1169 aSet.Put(aAnchor);
1170 pFormat->SetFormatAttr(aSet);
1173 else if (pEntry->nWID == FN_TEXT_BOX)
1175 auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
1176 if (pEntry->nMemberId == MID_TEXT_BOX)
1178 bool bValue(false);
1179 aValue >>= bValue;
1181 if (bValue)
1182 SwTextBoxHelper::create(pFormat, pObj);
1183 else
1184 SwTextBoxHelper::destroy(pFormat, pObj);
1186 else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
1188 if (uno::Reference<text::XTextFrame> xTextFrame; aValue >>= xTextFrame)
1189 SwTextBoxHelper::set(pFormat, pObj, xTextFrame);
1190 else
1191 SAL_WARN( "sw.uno", "This is not a TextFrame!" );
1194 else if (pEntry->nWID == RES_CHAIN)
1196 if (pEntry->nMemberId == MID_CHAIN_NEXTNAME || pEntry->nMemberId == MID_CHAIN_PREVNAME)
1197 SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
1198 SdrObject::getSdrObjectFromXShape(mxShape));
1200 // #i28749#
1201 else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
1203 sal_Int16 nPositionLayoutDir = 0;
1204 aValue >>= nPositionLayoutDir;
1205 pFormat->SetPositionLayoutDir( nPositionLayoutDir );
1207 else if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
1209 UnoActionContext aCtx(pDoc);
1210 if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
1212 SdrObject* pObj = pFormat->FindSdrObject();
1213 SdrMarkList aList;
1214 SdrMark aMark(pObj);
1215 aList.InsertEntry(aMark);
1216 sal_Int32 nAnchor = 0;
1217 cppu::enum2int( nAnchor, aValue );
1218 pDoc->ChgAnchor( aList, static_cast<RndStdIds>(nAnchor),
1219 false, true );
1221 else
1223 SfxItemPropertySet::setPropertyValue(*pEntry, aValue, aSet);
1224 pFormat->SetFormatAttr(aSet);
1227 else if( RES_FRM_SIZE == pEntry->nWID &&
1228 ( pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH
1229 || pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION
1230 || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION ) )
1232 SvxShape* pSvxShape = GetSvxShape();
1233 SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
1234 if(pSvxShape)
1236 SdrObject* pObj = pSvxShape->GetSdrObject();
1237 sal_Int16 nPercent(100);
1238 aValue >>= nPercent;
1239 switch (pEntry->nMemberId)
1241 case MID_FRMSIZE_REL_WIDTH:
1242 pObj->SetRelativeWidth( nPercent / 100.0 );
1243 break;
1244 case MID_FRMSIZE_REL_HEIGHT:
1245 pObj->SetRelativeHeight( nPercent / 100.0 );
1246 break;
1247 case MID_FRMSIZE_REL_WIDTH_RELATION:
1248 pObj->SetRelativeWidthRelation(nPercent);
1249 break;
1250 case MID_FRMSIZE_REL_HEIGHT_RELATION:
1251 pObj->SetRelativeHeightRelation(nPercent);
1252 break;
1256 else if (pEntry->nWID == RES_HORI_ORIENT
1257 && pEntry->nMemberId == MID_HORIORIENT_RELATION
1258 && aSet.Get(RES_ANCHOR).GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1260 uno::Any value(aValue);
1261 sal_Int16 nRelOrient(text::RelOrientation::PAGE_FRAME);
1262 aValue >>= nRelOrient;
1263 if (sw::GetAtPageRelOrientation(nRelOrient, true))
1265 SAL_WARN("sw.core", "SwXShape: fixing invalid horizontal RelOrientation for at-page anchor");
1266 value <<= nRelOrient;
1268 SfxItemPropertySet::setPropertyValue( *pEntry, value, aSet );
1269 pFormat->SetFormatAttr(aSet);
1271 else
1273 SfxItemPropertySet::setPropertyValue( *pEntry, aValue, aSet );
1275 if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
1277 bool bSetAttr = true;
1278 text::TextContentAnchorType eNewAnchor = static_cast<text::TextContentAnchorType>(SWUnoHelper::GetEnumAsInt32( aValue ));
1280 //if old anchor was in_cntnt the related text attribute has to be removed
1281 const SwFormatAnchor& rOldAnchor = pFormat->GetAnchor();
1282 RndStdIds eOldAnchorId = rOldAnchor.GetAnchorId();
1283 SdrObject* pObj = pFormat->FindSdrObject();
1284 SwFrameFormat *pFlyFormat = FindFrameFormat( pObj );
1285 pFlyFormat->DelFrames();
1286 if( text::TextContentAnchorType_AS_CHARACTER != eNewAnchor &&
1287 (RndStdIds::FLY_AS_CHAR == eOldAnchorId))
1289 //With AnchorAsCharacter the current TextAttribute has to be deleted.
1290 //Tbis removes the frame format too.
1291 //To prevent this the connection between format and attribute has to be broken before.
1292 SwTextNode *pTextNode = rOldAnchor.GetAnchorNode()->GetTextNode();
1293 SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno", "Missing FlyInCnt-Hint." );
1294 const sal_Int32 nIdx = rOldAnchor.GetAnchorContentOffset();
1295 SwTextAttr * const pHint =
1296 pTextNode->GetTextAttrForCharAt(
1297 nIdx, RES_TXTATR_FLYCNT );
1298 assert(pHint && "Missing Hint.");
1299 SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
1300 "sw.uno", "Missing FlyInCnt-Hint." );
1301 SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFlyFormat,
1302 "sw.uno", "Wrong TextFlyCnt-Hint." );
1303 const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
1304 .SetFlyFormat();
1306 //The connection is removed now the attribute can be deleted.
1307 pTextNode->DeleteAttributes(RES_TXTATR_FLYCNT, nIdx);
1309 else if( text::TextContentAnchorType_AT_PAGE != eNewAnchor &&
1310 (RndStdIds::FLY_AT_PAGE == eOldAnchorId))
1312 SwFormatAnchor aNewAnchor( aSet.Get( RES_ANCHOR ) );
1313 //if the fly has been anchored at page then it needs to be connected
1314 //to the content position
1315 SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
1316 if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
1318 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1319 Point aTmp( pObj->GetSnapRect().TopLeft() );
1320 pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
1322 else
1324 //without access to the layout the last node of the body will be used as anchor position
1325 aPam.Move( fnMoveBackward, GoInDoc );
1327 //anchor position has to be inserted after the text attribute has been inserted
1328 aNewAnchor.SetAnchor( aPam.GetPoint() );
1329 aSet.Put( aNewAnchor );
1330 pFormat->SetFormatAttr(aSet);
1331 bSetAttr = false;
1333 if( text::TextContentAnchorType_AS_CHARACTER == eNewAnchor &&
1334 (RndStdIds::FLY_AS_CHAR != eOldAnchorId))
1336 SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
1337 if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
1339 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1340 Point aTmp( pObj->GetSnapRect().TopLeft() );
1341 pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
1343 else
1345 //without access to the layout the last node of the body will be used as anchor position
1346 aPam.Move( fnMoveBackward, GoInDoc );
1348 //the RES_TXTATR_FLYCNT needs to be added now
1349 SwTextNode *pNd = aPam.GetPointNode().GetTextNode();
1350 SAL_WARN_IF( !pNd, "sw.uno", "Cursor is not in a TextNode." );
1351 SwFormatFlyCnt aFormat( pFlyFormat );
1352 pNd->InsertItem(aFormat,
1353 aPam.GetPoint()->GetContentIndex(), 0 );
1354 aPam.GetPoint()->AdjustContent(-1); // InsertItem moved it
1355 SwFormatAnchor aNewAnchor(
1356 aSet.Get(RES_ANCHOR));
1357 aNewAnchor.SetAnchor( aPam.GetPoint() );
1358 aSet.Put( aNewAnchor );
1360 if( bSetAttr )
1361 pFormat->SetFormatAttr(aSet);
1363 // If this property is an anchor change, and there is a group shape with textboxes
1364 // do anchor sync in time unless the anchor sync in the porfly will cause crash during
1365 // layout calculation (When importing an inline shape in docx via dmapper).
1366 if (pFormat->Which() == RES_DRAWFRMFMT && pFormat->GetOtherTextBoxFormats())
1368 SwTextBoxHelper::synchronizeGroupTextBoxProperty(
1369 SwTextBoxHelper::changeAnchor, pFormat,
1370 SdrObject::getSdrObjectFromXShape(mxShape));
1373 else
1374 pFormat->SetFormatAttr(aSet);
1377 // We have a pFormat and a pEntry as well: try to sync TextBox property.
1378 SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
1379 SdrObject::getSdrObjectFromXShape(mxShape));
1381 else
1383 SfxPoolItem* pItem = nullptr;
1384 switch(pEntry->nWID)
1386 case RES_ANCHOR:
1387 pItem = m_pImpl->GetAnchor(true);
1388 break;
1389 case RES_HORI_ORIENT:
1390 pItem = m_pImpl->GetHOrient(true);
1391 break;
1392 case RES_VERT_ORIENT:
1393 pItem = m_pImpl->GetVOrient(true);
1394 break;
1395 case RES_LR_SPACE:
1396 pItem = m_pImpl->GetLRSpace(true);
1397 break;
1398 case RES_UL_SPACE:
1399 pItem = m_pImpl->GetULSpace(true);
1400 break;
1401 case RES_SURROUND:
1402 pItem = m_pImpl->GetSurround(true);
1403 break;
1404 case FN_TEXT_RANGE:
1405 if(auto tr = o3tl::tryAccess<
1406 uno::Reference<text::XTextRange>>(aValue))
1408 uno::Reference< text::XTextRange > & rRange = m_pImpl->GetTextRange();
1409 rRange = *tr;
1411 break;
1412 case RES_OPAQUE :
1413 m_pImpl->SetOpaque(*o3tl::doAccess<bool>(aValue));
1414 break;
1415 // #i26791#
1416 case RES_FOLLOW_TEXT_FLOW:
1418 pItem = m_pImpl->GetFollowTextFlow( true );
1420 break;
1421 // #i28701#
1422 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1424 pItem = m_pImpl->GetWrapInfluenceOnObjPos( true );
1426 break;
1427 // #i28749#
1428 case FN_SHAPE_POSITION_LAYOUT_DIR :
1430 sal_Int16 nPositionLayoutDir = 0;
1431 aValue >>= nPositionLayoutDir;
1432 m_pImpl->SetPositionLayoutDir( nPositionLayoutDir );
1434 break;
1436 if(pItem)
1437 pItem->PutValue(aValue, pEntry->nMemberId);
1440 else
1442 const uno::Type& rPSetType =
1443 cppu::UnoType<beans::XPropertySet>::get();
1444 uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
1445 auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
1446 aPSet);
1447 if(!xPrSet)
1448 throw uno::RuntimeException();
1449 // #i31698# - setting the caption point of a
1450 // caption object doesn't have to change the object position.
1451 // Thus, keep the position, before the caption point is set and
1452 // restore it afterwards.
1453 awt::Point aKeepedPosition( 0, 0 );
1454 if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
1456 aKeepedPosition = getPosition();
1458 if( pFormat && pFormat->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() )
1460 UnoActionContext aCtx(pFormat->GetDoc());
1461 (*xPrSet)->setPropertyValue(rPropertyName, aValue);
1463 else
1464 (*xPrSet)->setPropertyValue(rPropertyName, aValue);
1466 if (pFormat)
1468 // We have a pFormat (but no pEntry): try to sync TextBox property.
1469 SwTextBoxHelper::syncProperty(pFormat, rPropertyName, aValue,
1470 SdrObject::getSdrObjectFromXShape(mxShape));
1473 // #i31698# - restore object position, if caption point is set.
1474 if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
1476 setPosition( aKeepedPosition );
1481 uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
1483 SolarMutexGuard aGuard;
1484 uno::Any aRet;
1485 SwFrameFormat* pFormat = GetFrameFormat();
1486 if(m_xShapeAgg.is())
1488 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1489 if(pEntry)
1491 if(pFormat)
1493 if(RES_OPAQUE == pEntry->nWID)
1495 SvxShape* pSvxShape = GetSvxShape();
1496 OSL_ENSURE(pSvxShape, "No SvxShape found!");
1497 if(pSvxShape)
1499 SdrObject* pObj = pSvxShape->GetSdrObject();
1500 // consider invisible layers
1501 SdrLayerID nLayerId = pObj->GetLayer();
1502 const IDocumentDrawModelAccess& rIDMA = pFormat->GetDoc()->getIDocumentDrawModelAccess();
1503 aRet <<=
1504 ( nLayerId != rIDMA.GetHellId() &&
1505 nLayerId != rIDMA.GetHeaderFooterHellId() &&
1506 nLayerId != rIDMA.GetInvisibleHellId() );
1509 else if(FN_ANCHOR_POSITION == pEntry->nWID)
1511 SvxShape* pSvxShape = GetSvxShape();
1512 OSL_ENSURE(pSvxShape, "No SvxShape found!");
1513 if(pSvxShape)
1515 SdrObject* pObj = pSvxShape->GetSdrObject();
1516 Point aPt = pObj->GetAnchorPos();
1517 awt::Point aPoint( convertTwipToMm100( aPt.X() ),
1518 convertTwipToMm100( aPt.Y() ) );
1519 aRet <<= aPoint;
1522 // #i26791# - special handling for FN_TEXT_RANGE
1523 else if ( FN_TEXT_RANGE == pEntry->nWID )
1525 const SwFormatAnchor aAnchor = pFormat->GetAnchor();
1526 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1528 // return nothing, because property <TextRange> isn't
1529 // valid for to-page anchored shapes
1530 aRet = uno::Any();
1532 else
1534 if ( aAnchor.GetAnchorNode() )
1536 const rtl::Reference<SwXTextRange> xTextRange
1537 = SwXTextRange::CreateXTextRange(
1538 *pFormat->GetDoc(),
1539 *aAnchor.GetContentAnchor(),
1540 nullptr );
1541 aRet <<= uno::Reference<text::XTextRange>(xTextRange);
1543 else
1545 // return nothing
1546 aRet = uno::Any();
1550 else if (pEntry->nWID == FN_TEXT_BOX)
1552 if (pEntry->nMemberId == MID_TEXT_BOX)
1554 auto pSvxShape = GetSvxShape();
1555 bool bValue = SwTextBoxHelper::isTextBox(
1556 pFormat, RES_DRAWFRMFMT,
1557 ((pSvxShape && pSvxShape->GetSdrObject()) ? pSvxShape->GetSdrObject()
1558 : pFormat->FindRealSdrObject()));
1559 aRet <<= bValue;
1561 else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
1563 auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
1564 auto xRange = SwTextBoxHelper::queryInterface(
1565 pFormat, cppu::UnoType<text::XText>::get(),
1566 pObj ? pObj : pFormat->FindRealSdrObject());
1567 uno::Reference<text::XTextFrame> xFrame(xRange, uno::UNO_QUERY);
1568 if (xFrame.is())
1569 aRet <<= xFrame;
1572 else if (pEntry->nWID == RES_CHAIN)
1574 switch (pEntry->nMemberId)
1576 case MID_CHAIN_PREVNAME:
1577 case MID_CHAIN_NEXTNAME:
1578 case MID_CHAIN_NAME:
1579 SwTextBoxHelper::getProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aRet);
1580 break;
1583 // #i28749#
1584 else if ( FN_SHAPE_TRANSFORMATION_IN_HORI_L2R == pEntry->nWID )
1586 // get property <::drawing::Shape::Transformation>
1587 // without conversion to layout direction as below
1588 aRet = _getPropAtAggrObj( u"Transformation"_ustr );
1590 else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
1592 aRet <<= pFormat->GetPositionLayoutDir();
1594 // #i36248#
1595 else if ( FN_SHAPE_STARTPOSITION_IN_HORI_L2R == pEntry->nWID )
1597 // get property <::drawing::Shape::StartPosition>
1598 // without conversion to layout direction as below
1599 aRet = _getPropAtAggrObj( u"StartPosition"_ustr );
1601 else if ( FN_SHAPE_ENDPOSITION_IN_HORI_L2R == pEntry->nWID )
1603 // get property <::drawing::Shape::EndPosition>
1604 // without conversion to layout direction as below
1605 aRet = _getPropAtAggrObj( u"EndPosition"_ustr );
1607 else if (pEntry->nWID == RES_FRM_SIZE &&
1608 (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT ||
1609 pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH ||
1610 pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
1611 pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
1613 SvxShape* pSvxShape = GetSvxShape();
1614 SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
1615 sal_Int16 nRet = 0;
1616 if (pSvxShape)
1618 SdrObject* pObj = pSvxShape->GetSdrObject();
1619 switch (pEntry->nMemberId)
1621 case MID_FRMSIZE_REL_WIDTH:
1622 if (pObj->GetRelativeWidth())
1623 nRet = *pObj->GetRelativeWidth() * 100;
1624 break;
1625 case MID_FRMSIZE_REL_HEIGHT:
1626 if (pObj->GetRelativeHeight())
1627 nRet = *pObj->GetRelativeHeight() * 100;
1628 break;
1629 case MID_FRMSIZE_REL_WIDTH_RELATION:
1630 nRet = pObj->GetRelativeWidthRelation();
1631 break;
1632 case MID_FRMSIZE_REL_HEIGHT_RELATION:
1633 nRet = pObj->GetRelativeHeightRelation();
1634 break;
1637 aRet <<= nRet;
1639 else
1641 const SwAttrSet& rSet = pFormat->GetAttrSet();
1642 SfxItemPropertySet::getPropertyValue(*pEntry, rSet, aRet);
1645 else
1647 SfxPoolItem* pItem = nullptr;
1648 switch(pEntry->nWID)
1650 case RES_ANCHOR:
1651 pItem = m_pImpl->GetAnchor();
1652 break;
1653 case RES_HORI_ORIENT:
1654 pItem = m_pImpl->GetHOrient();
1655 break;
1656 case RES_VERT_ORIENT:
1657 pItem = m_pImpl->GetVOrient();
1658 break;
1659 case RES_LR_SPACE:
1660 pItem = m_pImpl->GetLRSpace();
1661 break;
1662 case RES_UL_SPACE:
1663 pItem = m_pImpl->GetULSpace();
1664 break;
1665 case RES_SURROUND:
1666 pItem = m_pImpl->GetSurround();
1667 break;
1668 case FN_TEXT_RANGE :
1669 aRet <<= m_pImpl->GetTextRange();
1670 break;
1671 case RES_OPAQUE :
1672 aRet <<= m_pImpl->GetOpaque();
1673 break;
1674 case FN_ANCHOR_POSITION :
1676 aRet <<= awt::Point();
1678 break;
1679 // #i26791#
1680 case RES_FOLLOW_TEXT_FLOW :
1682 pItem = m_pImpl->GetFollowTextFlow();
1684 break;
1685 // #i28701#
1686 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1688 pItem = m_pImpl->GetWrapInfluenceOnObjPos();
1690 break;
1691 // #i28749#
1692 case FN_SHAPE_TRANSFORMATION_IN_HORI_L2R:
1694 // get property <::drawing::Shape::Transformation>
1695 // without conversion to layout direction as below
1696 aRet = _getPropAtAggrObj( u"Transformation"_ustr );
1698 break;
1699 case FN_SHAPE_POSITION_LAYOUT_DIR:
1701 aRet <<= m_pImpl->GetPositionLayoutDir();
1703 break;
1704 // #i36248#
1705 case FN_SHAPE_STARTPOSITION_IN_HORI_L2R:
1707 // get property <::drawing::Shape::StartPosition>
1708 // without conversion to layout direction as below
1709 aRet = _getPropAtAggrObj( u"StartPosition"_ustr );
1711 break;
1712 case FN_SHAPE_ENDPOSITION_IN_HORI_L2R:
1714 // get property <::drawing::Shape::StartPosition>
1715 // without conversion to layout direction as below
1716 aRet = _getPropAtAggrObj( u"EndPosition"_ustr );
1718 break;
1720 if(pItem)
1721 pItem->QueryValue(aRet, pEntry->nMemberId);
1724 else
1726 aRet = _getPropAtAggrObj( rPropertyName );
1728 // #i31698# - convert the position (translation)
1729 // of the drawing object in the transformation
1730 if ( rPropertyName == "Transformation" )
1732 drawing::HomogenMatrix3 aMatrix;
1733 aRet >>= aMatrix;
1734 aRet <<= ConvertTransformationToLayoutDir( aMatrix );
1736 // #i36248#
1737 else if ( rPropertyName == "StartPosition" )
1739 awt::Point aStartPos;
1740 aRet >>= aStartPos;
1741 // #i59051#
1742 aRet <<= ConvertStartOrEndPosToLayoutDir( aStartPos );
1744 else if ( rPropertyName == "EndPosition" )
1746 awt::Point aEndPos;
1747 aRet >>= aEndPos;
1748 // #i59051#
1749 aRet <<= ConvertStartOrEndPosToLayoutDir( aEndPos );
1751 // #i59051#
1752 else if ( rPropertyName == "PolyPolygonBezier" )
1754 drawing::PolyPolygonBezierCoords aPath;
1755 aRet >>= aPath;
1756 aRet <<= ConvertPolyPolygonBezierToLayoutDir( aPath );
1758 else if (rPropertyName == "ZOrder")
1760 // Convert the real draw page position to the logical one that ignores textboxes.
1761 if (pFormat)
1763 const SdrObject* pObj = pFormat->FindRealSdrObject();
1764 if (pObj)
1766 bool bConvert = true;
1767 if (SvxShape* pSvxShape = GetSvxShape())
1768 // In case of group shapes, pSvxShape points to the child shape, while pObj points to the outermost group shape.
1769 if (pSvxShape->GetSdrObject() != pObj)
1770 // Textboxes are not expected inside group shapes, so no conversion is necessary there.
1771 bConvert = false;
1772 if (bConvert)
1774 aRet <<= SwTextBoxHelper::getOrdNum(pObj);
1781 return aRet;
1784 uno::Any SwXShape::_getPropAtAggrObj( const OUString& _rPropertyName )
1786 uno::Any aRet;
1788 const uno::Type& rPSetType =
1789 cppu::UnoType<beans::XPropertySet>::get();
1790 uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
1791 auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(aPSet);
1792 if ( !xPrSet )
1794 throw uno::RuntimeException();
1796 aRet = (*xPrSet)->getPropertyValue( _rPropertyName );
1798 return aRet;
1801 beans::PropertyState SwXShape::getPropertyState( const OUString& rPropertyName )
1803 SolarMutexGuard aGuard;
1804 uno::Sequence< OUString > aNames { rPropertyName };
1805 uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
1806 return aStates.getConstArray()[0];
1809 uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
1810 const uno::Sequence< OUString >& aPropertyNames )
1812 SolarMutexGuard aGuard;
1813 SwFrameFormat* pFormat = GetFrameFormat();
1814 uno::Sequence< beans::PropertyState > aRet(aPropertyNames.getLength());
1815 if(!m_xShapeAgg.is())
1816 throw uno::RuntimeException();
1818 SvxShape* pSvxShape = GetSvxShape();
1819 bool bGroupMember = false;
1820 bool bFormControl = false;
1821 SdrObject* pObject = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
1822 if(pObject)
1824 bGroupMember = pObject->getParentSdrObjectFromSdrObject() != nullptr;
1825 bFormControl = pObject->GetObjInventor() == SdrInventor::FmForm;
1827 const OUString* pNames = aPropertyNames.getConstArray();
1828 beans::PropertyState* pRet = aRet.getArray();
1829 uno::Reference< XPropertyState > xShapePrState;
1830 for(sal_Int32 nProperty = 0; nProperty < aPropertyNames.getLength(); nProperty++)
1832 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( pNames[nProperty] );
1833 if(pEntry)
1835 if(RES_OPAQUE == pEntry->nWID)
1836 pRet[nProperty] = bFormControl ?
1837 beans::PropertyState_DEFAULT_VALUE : beans::PropertyState_DIRECT_VALUE;
1838 else if(FN_ANCHOR_POSITION == pEntry->nWID)
1839 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1840 else if(FN_TEXT_RANGE == pEntry->nWID)
1841 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1842 else if(bGroupMember)
1843 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1844 else if (pEntry->nWID == RES_FRM_SIZE &&
1845 (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
1846 pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
1847 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1848 else if (pEntry->nWID == FN_TEXT_BOX)
1850 // The TextBox property is set, if we can find a textbox for this shape.
1851 if (pFormat
1852 && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT,
1853 SdrObject::getSdrObjectFromXShape(mxShape)))
1854 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1855 else
1856 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1858 else if(pFormat)
1860 const SwAttrSet& rSet = pFormat->GetAttrSet();
1861 SfxItemState eItemState = rSet.GetItemState(pEntry->nWID, false);
1863 if(SfxItemState::SET == eItemState)
1864 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1865 else if(SfxItemState::DEFAULT == eItemState)
1866 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1867 else
1868 pRet[nProperty] = beans::PropertyState_AMBIGUOUS_VALUE;
1870 else
1872 SfxPoolItem* pItem = nullptr;
1873 switch(pEntry->nWID)
1875 case RES_ANCHOR:
1876 pItem = m_pImpl->GetAnchor();
1877 break;
1878 case RES_HORI_ORIENT:
1879 pItem = m_pImpl->GetHOrient();
1880 break;
1881 case RES_VERT_ORIENT:
1882 pItem = m_pImpl->GetVOrient();
1883 break;
1884 case RES_LR_SPACE:
1885 pItem = m_pImpl->GetLRSpace();
1886 break;
1887 case RES_UL_SPACE:
1888 pItem = m_pImpl->GetULSpace();
1889 break;
1890 case RES_SURROUND:
1891 pItem = m_pImpl->GetSurround();
1892 break;
1893 // #i28701#
1894 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1896 pItem = m_pImpl->GetWrapInfluenceOnObjPos();
1898 break;
1900 if(pItem)
1901 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1902 else
1903 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1906 else
1908 if(!xShapePrState.is())
1910 const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
1911 uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
1912 auto ps = o3tl::tryAccess<uno::Reference<XPropertyState>>(
1913 aPState);
1914 if(!ps)
1915 throw uno::RuntimeException();
1916 xShapePrState = *ps;
1918 pRet[nProperty] = xShapePrState->getPropertyState(pNames[nProperty]);
1922 return aRet;
1925 void SwXShape::setPropertyToDefault( const OUString& rPropertyName )
1927 SolarMutexGuard aGuard;
1928 SwFrameFormat* pFormat = GetFrameFormat();
1929 if(!m_xShapeAgg.is())
1930 throw uno::RuntimeException();
1932 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1933 if(pEntry)
1935 if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
1936 throw uno::RuntimeException("Property is read-only: " + rPropertyName, getXWeak() );
1937 if(pFormat)
1939 const SfxItemSet& rSet = pFormat->GetAttrSet();
1940 SfxItemSet aSet(pFormat->GetDoc()->GetAttrPool(), pEntry->nWID, pEntry->nWID);
1941 aSet.SetParent(&rSet);
1942 aSet.ClearItem(pEntry->nWID);
1943 pFormat->GetDoc()->SetAttr(aSet, *pFormat);
1945 else
1947 switch(pEntry->nWID)
1949 case RES_ANCHOR: m_pImpl->RemoveAnchor(); break;
1950 case RES_HORI_ORIENT: m_pImpl->RemoveHOrient(); break;
1951 case RES_VERT_ORIENT: m_pImpl->RemoveVOrient(); break;
1952 case RES_LR_SPACE: m_pImpl->RemoveLRSpace(); break;
1953 case RES_UL_SPACE: m_pImpl->RemoveULSpace(); break;
1954 case RES_SURROUND: m_pImpl->RemoveSurround();break;
1955 case RES_OPAQUE : m_pImpl->SetOpaque(false); break;
1956 case FN_TEXT_RANGE :
1957 break;
1958 // #i26791#
1959 case RES_FOLLOW_TEXT_FLOW:
1961 m_pImpl->RemoveFollowTextFlow();
1963 break;
1964 // #i28701#
1965 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1967 m_pImpl->RemoveWrapInfluenceOnObjPos();
1969 break;
1973 else
1975 const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
1976 uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
1977 auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
1978 aPState);
1979 if(!xShapePrState)
1980 throw uno::RuntimeException();
1981 (*xShapePrState)->setPropertyToDefault( rPropertyName );
1986 uno::Any SwXShape::getPropertyDefault( const OUString& rPropertyName )
1988 SolarMutexGuard aGuard;
1989 SwFrameFormat* pFormat = GetFrameFormat();
1990 uno::Any aRet;
1991 if(!m_xShapeAgg.is())
1992 throw uno::RuntimeException();
1994 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1995 if(pEntry)
1997 if(!(pEntry->nWID < RES_FRMATR_END && pFormat))
1998 throw uno::RuntimeException();
2000 const SfxPoolItem& rDefItem =
2001 pFormat->GetDoc()->GetAttrPool().GetUserOrPoolDefaultItem(pEntry->nWID);
2002 rDefItem.QueryValue(aRet, pEntry->nMemberId);
2005 else
2007 const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
2008 uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
2009 auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
2010 aPState);
2011 if(!xShapePrState)
2012 throw uno::RuntimeException();
2013 (*xShapePrState)->getPropertyDefault( rPropertyName );
2016 return aRet;
2019 void SwXShape::addPropertyChangeListener(
2020 const OUString& _propertyName,
2021 const uno::Reference< beans::XPropertyChangeListener > & _listener )
2023 if ( !m_xShapeAgg.is() )
2024 throw uno::RuntimeException(u"no shape aggregate"_ustr, *this );
2026 // must be handled by the aggregate
2027 uno::Reference< beans::XPropertySet > xShapeProps;
2028 if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
2029 xShapeProps->addPropertyChangeListener( _propertyName, _listener );
2032 void SwXShape::removePropertyChangeListener(
2033 const OUString& _propertyName,
2034 const uno::Reference< beans::XPropertyChangeListener > & _listener)
2036 if ( !m_xShapeAgg.is() )
2037 throw uno::RuntimeException(u"no shape aggregate"_ustr, *this );
2039 // must be handled by the aggregate
2040 uno::Reference< beans::XPropertySet > xShapeProps;
2041 if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
2042 xShapeProps->removePropertyChangeListener( _propertyName, _listener );
2045 void SwXShape::addVetoableChangeListener(
2046 const OUString& /*PropertyName*/,
2047 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/ )
2049 OSL_FAIL("not implemented");
2052 void SwXShape::removeVetoableChangeListener(
2053 const OUString& /*PropertyName*/,
2054 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
2056 OSL_FAIL("not implemented");
2059 void SwXShape::attach(const uno::Reference< text::XTextRange > & xTextRange)
2061 SolarMutexGuard aGuard;
2063 // get access to SwDoc
2064 // (see also SwXTextRange::XTextRangeToSwPaM)
2065 const SwDoc* pDoc = nullptr;
2066 if (auto pRange = dynamic_cast<SwXTextRange*>(xTextRange.get()))
2067 pDoc = &pRange->GetDoc();
2068 else if (auto pText = dynamic_cast<SwXText*>(xTextRange.get()))
2069 pDoc = pText->GetDoc();
2070 else if (auto pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get()))
2071 pDoc = pCursor->GetDoc();
2072 else if (auto pPortion = dynamic_cast<SwXTextPortion*>(xTextRange.get()))
2073 pDoc = &pPortion->GetCursor().GetDoc();
2074 else if (auto pParagraph = dynamic_cast<SwXParagraph*>(xTextRange.get());
2075 pParagraph && pParagraph->GetTextNode())
2076 pDoc = &pParagraph->GetTextNode()->GetDoc();
2078 if(!pDoc)
2079 throw uno::RuntimeException();
2080 const SwDocShell* pDocSh = pDoc->GetDocShell();
2081 if (!pDocSh)
2082 return;
2084 uno::Reference<frame::XModel> xModel = pDocSh->GetModel();
2085 uno::Reference< drawing::XDrawPageSupplier > xDPS(xModel, uno::UNO_QUERY);
2086 if (xDPS.is())
2088 uno::Reference< drawing::XDrawPage > xDP( xDPS->getDrawPage() );
2089 if (xDP.is())
2091 uno::Any aPos;
2092 aPos <<= xTextRange;
2093 setPropertyValue(u"TextRange"_ustr, aPos);
2094 uno::Reference< drawing::XShape > xTemp( getXWeak(), uno::UNO_QUERY );
2095 xDP->add( xTemp );
2100 uno::Reference< text::XTextRange > SwXShape::getAnchor()
2102 SolarMutexGuard aGuard;
2103 uno::Reference< text::XTextRange > aRef;
2104 SwFrameFormat* pFormat = GetFrameFormat();
2105 if(pFormat)
2107 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
2108 // return an anchor for non-page bound frames
2109 // and for page bound frames that have a page no == NULL and a content position
2110 if ((rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) ||
2111 (rAnchor.GetAnchorNode() && !rAnchor.GetPageNum()))
2113 if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA)
2114 { // ensure that SwXTextRange has SwContentIndex
2115 const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
2116 aRef = SwXTextRange::CreateXTextRange(*pFormat->GetDoc(), SwPosition(*pAnchorNode), nullptr);
2118 else
2120 aRef = SwXTextRange::CreateXTextRange(*pFormat->GetDoc(), *rAnchor.GetContentAnchor(), nullptr);
2124 else
2125 aRef = m_pImpl->GetTextRange().get();
2126 return aRef;
2129 void SwXShape::dispose()
2131 SolarMutexGuard aGuard;
2132 SwFrameFormat* pFormat = GetFrameFormat();
2133 if(pFormat)
2135 // determine correct <SdrObject>
2136 SvxShape* pSvxShape = GetSvxShape();
2137 SdrObject* pObj = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
2138 // safety assertion:
2139 // <pObj> must be the same as <pFormat->FindSdrObject()>, if <pObj> isn't
2140 // a 'virtual' drawing object.
2141 // correct assertion and refine it for safety reason.
2142 OSL_ENSURE( !pObj ||
2143 dynamic_cast<const SwDrawVirtObj*>( pObj) != nullptr ||
2144 pObj->getParentSdrObjectFromSdrObject() ||
2145 pObj == pFormat->FindSdrObject(),
2146 "<SwXShape::dispose(..) - different 'master' drawing objects!!" );
2147 // perform delete of draw frame format *not*
2148 // for 'virtual' drawing objects.
2149 // no delete of draw format for members
2150 // of a group
2151 if ( pObj &&
2152 dynamic_cast<const SwDrawVirtObj*>( pObj) == nullptr &&
2153 !pObj->getParentSdrObjectFromSdrObject() &&
2154 pObj->IsInserted() )
2156 const SwFormatAnchor& rFormatAnchor = pFormat->GetAnchor();
2157 if (rFormatAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
2159 SwTextNode *pTextNode = rFormatAnchor.GetAnchorNode()->GetTextNode();
2160 const sal_Int32 nIdx = rFormatAnchor.GetAnchorContentOffset();
2161 pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
2163 else
2164 pFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pFormat );
2167 if(m_xShapeAgg.is())
2169 uno::Any aAgg(m_xShapeAgg->queryAggregation( cppu::UnoType<XComponent>::get()));
2170 uno::Reference<XComponent> xComp;
2171 aAgg >>= xComp;
2172 if(xComp.is())
2173 xComp->dispose();
2175 if(m_pPage)
2177 auto pPage = const_cast<SwFmDrawPage*>(m_pPage);
2178 m_pPage = nullptr;
2179 pPage->RemoveShape(this);
2183 void SwXShape::addEventListener(
2184 const uno::Reference< lang::XEventListener > & aListener)
2186 SvxShape* pSvxShape = GetSvxShape();
2187 if(pSvxShape)
2188 pSvxShape->addEventListener(aListener);
2191 void SwXShape::removeEventListener(
2192 const uno::Reference< lang::XEventListener > & aListener)
2194 SvxShape* pSvxShape = GetSvxShape();
2195 if(pSvxShape)
2196 pSvxShape->removeEventListener(aListener);
2199 OUString SwXShape::getImplementationName()
2201 return u"SwXShape"_ustr;
2204 sal_Bool SwXShape::supportsService(const OUString& rServiceName)
2206 return cppu::supportsService(this, rServiceName);
2209 uno::Sequence< OUString > SwXShape::getSupportedServiceNames()
2211 uno::Sequence< OUString > aSeq;
2212 if (SvxShape* pSvxShape = GetSvxShape())
2213 aSeq = pSvxShape->getSupportedServiceNames();
2214 return comphelper::concatSequences(
2215 aSeq, std::initializer_list<OUString>{ u"com.sun.star.drawing.Shape"_ustr });
2218 SvxShape* SwXShape::GetSvxShape()
2220 if(m_xShapeAgg.is())
2221 return comphelper::getFromUnoTunnel<SvxShape>(m_xShapeAgg);
2222 return nullptr;
2225 // #i31698#
2226 // implementation of virtual methods from drawing::XShape
2227 awt::Point SAL_CALL SwXShape::getPosition()
2229 awt::Point aPos( GetAttrPosition() );
2231 // handle group members
2232 SvxShape* pSvxShape = GetSvxShape();
2233 if ( pSvxShape )
2235 SdrObject* pTopGroupObj = GetTopGroupObj( pSvxShape );
2236 if ( pTopGroupObj )
2238 // #i34750# - get attribute position of top group
2239 // shape and add offset between top group object and group member
2240 uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
2241 aPos = xGroupShape->getPosition();
2242 // add offset between top group object and group member
2243 // to the determined attribute position
2244 // #i34750#:
2245 // consider the layout direction
2246 const tools::Rectangle aMemberObjRect = GetSvxShape()->GetSdrObject()->GetSnapRect();
2247 const tools::Rectangle aGroupObjRect = pTopGroupObj->GetSnapRect();
2248 // #i53320# - relative position of group member and
2249 // top group object is always given in horizontal left-to-right layout.
2250 awt::Point aOffset( 0, 0 );
2252 aOffset.X = ( aMemberObjRect.Left() - aGroupObjRect.Left() );
2253 aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
2255 aOffset.X = convertTwipToMm100(aOffset.X);
2256 aOffset.Y = convertTwipToMm100(aOffset.Y);
2257 aPos.X += aOffset.X;
2258 aPos.Y += aOffset.Y;
2262 return aPos;
2265 void SAL_CALL SwXShape::setPosition( const awt::Point& aPosition )
2267 SdrObject* pTopGroupObj = GetTopGroupObj();
2268 if ( !pTopGroupObj )
2270 // #i37877# - no adjustment of position attributes,
2271 // if the position also has to be applied at the drawing object and
2272 // a contact object is already registered at the drawing object.
2273 bool bApplyPosAtDrawObj(false);
2274 bool bNoAdjustOfPosProp(false);
2275 // #i35798# - apply position also to drawing object,
2276 // if drawing object has no anchor position set.
2277 if ( mxShape.is() )
2279 SvxShape* pSvxShape = GetSvxShape();
2280 if ( pSvxShape )
2282 const SdrObject* pObj = pSvxShape->GetSdrObject();
2283 if ( pObj &&
2284 pObj->GetAnchorPos().X() == 0 &&
2285 pObj->GetAnchorPos().Y() == 0 )
2287 bApplyPosAtDrawObj = true;
2288 if ( pObj->GetUserCall() &&
2289 dynamic_cast<const SwDrawContact*>( pObj->GetUserCall()) != nullptr )
2291 bNoAdjustOfPosProp = true;
2296 // shape isn't a group member. Thus, set positioning attributes
2297 if ( !bNoAdjustOfPosProp )
2299 AdjustPositionProperties( aPosition );
2301 if ( bApplyPosAtDrawObj )
2303 mxShape->setPosition( aPosition );
2306 else if ( mxShape.is() )
2308 // shape is a member of a group. Thus, set its position.
2309 awt::Point aNewPos( aPosition );
2310 // The given position is given in the according layout direction. Thus,
2311 // it has to be converted to a position in horizontal left-to-right
2312 // layout.
2313 // convert given absolute attribute position in layout direction into
2314 // position in horizontal left-to-right layout.
2316 aNewPos = ConvertPositionToHoriL2R( aNewPos, getSize() );
2318 // Convert given absolute position in horizontal left-to-right
2319 // layout into relative position in horizontal left-to-right layout.
2320 uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
2322 // #i34750#
2323 // use method <xGroupShape->getPosition()> to get the correct
2324 // position of the top group object.
2325 awt::Point aAttrPosInHoriL2R(
2326 ConvertPositionToHoriL2R( xGroupShape->getPosition(),
2327 xGroupShape->getSize() ) );
2328 aNewPos.X = o3tl::saturating_sub(aNewPos.X, aAttrPosInHoriL2R.X);
2329 aNewPos.Y = o3tl::saturating_sub(aNewPos.Y, aAttrPosInHoriL2R.Y);
2331 // convert relative position in horizontal left-to-right layout into
2332 // absolute position in horizontal left-to-right layout
2334 // #i34750#
2335 // use method <SvxShape->getPosition()> to get the correct
2336 // 'Drawing layer' position of the top group shape.
2337 auto pSvxGroupShape = comphelper::getFromUnoTunnel<SvxShape>(pTopGroupObj->getUnoShape());
2338 const awt::Point aGroupPos = pSvxGroupShape->getPosition();
2339 aNewPos.X = o3tl::saturating_add(aNewPos.X, aGroupPos.X);
2340 aNewPos.Y = o3tl::saturating_add(aNewPos.Y, aGroupPos.Y);
2342 // set position
2343 mxShape->setPosition( aNewPos );
2347 awt::Size SAL_CALL SwXShape::getSize()
2349 awt::Size aSize;
2350 if ( mxShape.is() )
2352 aSize = mxShape->getSize();
2354 return aSize;
2357 void SAL_CALL SwXShape::setSize( const awt::Size& aSize )
2359 comphelper::ProfileZone aZone("SwXShape::setSize");
2361 if ( mxShape.is() )
2363 mxShape->setSize( aSize );
2365 SwTextBoxHelper::syncProperty(GetFrameFormat(), RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any(aSize));
2367 // #i31698#
2368 // implementation of virtual methods from drawing::XShapeDescriptor
2369 OUString SAL_CALL SwXShape::getShapeType()
2371 if ( mxShape.is() )
2373 return mxShape->getShapeType();
2375 return OUString();
2377 /** method to determine top group object
2378 #i31698#
2380 SdrObject* SwXShape::GetTopGroupObj( SvxShape* _pSvxShape )
2382 SdrObject* pTopGroupObj( nullptr );
2384 SvxShape* pSvxShape = _pSvxShape ? _pSvxShape : GetSvxShape();
2385 if ( pSvxShape )
2387 SdrObject* pSdrObj = pSvxShape->GetSdrObject();
2388 if ( pSdrObj && pSdrObj->getParentSdrObjectFromSdrObject() )
2390 pTopGroupObj = pSdrObj->getParentSdrObjectFromSdrObject();
2391 while ( pTopGroupObj->getParentSdrObjectFromSdrObject() )
2393 pTopGroupObj = pTopGroupObj->getParentSdrObjectFromSdrObject();
2398 return pTopGroupObj;
2401 /** method to determine position according to the positioning attributes
2402 #i31698#
2404 awt::Point SwXShape::GetAttrPosition()
2406 awt::Point aAttrPos;
2408 uno::Any aHoriPos( getPropertyValue(u"HoriOrientPosition"_ustr) );
2409 aHoriPos >>= aAttrPos.X;
2410 uno::Any aVertPos( getPropertyValue(u"VertOrientPosition"_ustr) );
2411 aVertPos >>= aAttrPos.Y;
2412 // #i35798# - fallback, if attribute position is (0,0)
2413 // and no anchor position is applied to the drawing object
2414 SvxShape* pSvxShape = GetSvxShape();
2415 if ( pSvxShape )
2417 const SdrObject* pObj = pSvxShape->GetSdrObject();
2418 if ( pObj &&
2419 pObj->GetAnchorPos().X() == 0 &&
2420 pObj->GetAnchorPos().Y() == 0 &&
2421 aAttrPos.X == 0 && aAttrPos.Y == 0 )
2423 const tools::Rectangle aObjRect = pObj->GetSnapRect();
2424 aAttrPos.X = convertTwipToMm100(aObjRect.Left());
2425 aAttrPos.Y = convertTwipToMm100(aObjRect.Top());
2428 // #i35007# - If drawing object is anchored as-character,
2429 // it's x-position isn't sensible. Thus, return the x-position as zero in this case.
2430 text::TextContentAnchorType eTextAnchorType =
2431 text::TextContentAnchorType_AT_PARAGRAPH;
2433 uno::Any aAny = getPropertyValue( u"AnchorType"_ustr );
2434 aAny >>= eTextAnchorType;
2436 if ( eTextAnchorType == text::TextContentAnchorType_AS_CHARACTER )
2438 aAttrPos.X = 0;
2441 return aAttrPos;
2444 /** method to convert the position (translation) of the drawing object to
2445 the layout direction horizontal left-to-right.
2446 #i31698#
2448 awt::Point SwXShape::ConvertPositionToHoriL2R( const awt::Point& rObjPos,
2449 const awt::Size& rObjSize )
2451 awt::Point aObjPosInHoriL2R( rObjPos );
2453 SwFrameFormat* pFrameFormat = GetFrameFormat();
2454 if ( pFrameFormat )
2456 SwFrameFormat::tLayoutDir eLayoutDir = pFrameFormat->GetLayoutDir();
2457 switch ( eLayoutDir )
2459 case SwFrameFormat::HORI_L2R:
2461 // nothing to do
2463 break;
2464 case SwFrameFormat::HORI_R2L:
2466 aObjPosInHoriL2R.X = -rObjPos.X - rObjSize.Width;
2468 break;
2469 case SwFrameFormat::VERT_R2L:
2471 aObjPosInHoriL2R.X = -rObjPos.Y - rObjSize.Width;
2472 aObjPosInHoriL2R.Y = rObjPos.X;
2474 break;
2475 default:
2477 OSL_FAIL( "<SwXShape::ConvertPositionToHoriL2R(..)> - unsupported layout direction" );
2482 return aObjPosInHoriL2R;
2485 /** method to convert the transformation of the drawing object to the layout
2486 direction, the drawing object is in
2487 #i31698#
2489 drawing::HomogenMatrix3 SwXShape::ConvertTransformationToLayoutDir(
2490 const drawing::HomogenMatrix3& rMatrixInHoriL2R )
2492 drawing::HomogenMatrix3 aMatrix(rMatrixInHoriL2R);
2494 // #i44334#, #i44681# - direct manipulation of the
2495 // transformation structure isn't valid, if it contains rotation.
2496 SvxShape* pSvxShape = GetSvxShape();
2497 OSL_ENSURE( pSvxShape,
2498 "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SvxShape found!");
2499 if ( pSvxShape )
2501 const SdrObject* pObj = pSvxShape->GetSdrObject();
2502 OSL_ENSURE( pObj,
2503 "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SdrObject found!");
2504 if ( pObj )
2506 // get position of object in Writer coordinate system.
2507 awt::Point aPos( getPosition() );
2508 // get position of object in Drawing layer coordinate system
2509 const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
2510 const awt::Point aObjPos(
2511 convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
2512 convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
2513 // determine difference between these positions according to the
2514 // Writer coordinate system
2515 const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
2516 aPos.Y - aObjPos.Y );
2517 // apply translation difference to transformation matrix.
2518 if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
2520 // #i73079# - use correct matrix type
2521 ::basegfx::B2DHomMatrix aTempMatrix;
2523 aTempMatrix.set(0, 0, aMatrix.Line1.Column1 );
2524 aTempMatrix.set(0, 1, aMatrix.Line1.Column2 );
2525 aTempMatrix.set(0, 2, aMatrix.Line1.Column3 );
2526 aTempMatrix.set(1, 0, aMatrix.Line2.Column1 );
2527 aTempMatrix.set(1, 1, aMatrix.Line2.Column2 );
2528 aTempMatrix.set(1, 2, aMatrix.Line2.Column3 );
2529 // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
2530 assert( aMatrix.Line3.Column1 == 0 );
2531 assert( aMatrix.Line3.Column2 == 0 );
2532 assert( aMatrix.Line3.Column3 == 1 );
2533 // #i73079#
2534 aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y );
2535 aMatrix.Line1.Column1 = aTempMatrix.get(0, 0);
2536 aMatrix.Line1.Column2 = aTempMatrix.get(0, 1);
2537 aMatrix.Line1.Column3 = aTempMatrix.get(0, 2);
2538 aMatrix.Line2.Column1 = aTempMatrix.get(1, 0);
2539 aMatrix.Line2.Column2 = aTempMatrix.get(1, 1);
2540 aMatrix.Line2.Column3 = aTempMatrix.get(1, 2);
2541 aMatrix.Line3.Column1 = 0;
2542 aMatrix.Line3.Column2 = 0;
2543 aMatrix.Line3.Column3 = 1;
2548 return aMatrix;
2551 /** method to adjust the positioning properties
2552 #i31698#
2554 void SwXShape::AdjustPositionProperties( const awt::Point& rPosition )
2556 // handle x-position
2557 // #i35007# - no handling of x-position, if drawing
2558 // object is anchored as-character, because it doesn't make sense.
2559 text::TextContentAnchorType eTextAnchorType =
2560 text::TextContentAnchorType_AT_PARAGRAPH;
2562 uno::Any aAny = getPropertyValue( u"AnchorType"_ustr );
2563 aAny >>= eTextAnchorType;
2565 if ( eTextAnchorType != text::TextContentAnchorType_AS_CHARACTER )
2567 // determine current x-position
2568 static constexpr OUString aHoriPosPropStr(u"HoriOrientPosition"_ustr);
2569 uno::Any aHoriPos( getPropertyValue( aHoriPosPropStr ) );
2570 sal_Int32 dCurrX = 0;
2571 aHoriPos >>= dCurrX;
2572 // change x-position attribute, if needed
2573 if ( dCurrX != rPosition.X )
2575 // adjust x-position orientation to text::HoriOrientation::NONE, if needed
2576 // Note: has to be done before setting x-position attribute
2577 static constexpr OUString aHoriOrientPropStr(u"HoriOrient"_ustr);
2578 uno::Any aHoriOrient( getPropertyValue( aHoriOrientPropStr ) );
2579 sal_Int16 eHoriOrient;
2580 if (aHoriOrient >>= eHoriOrient) // may be void
2582 if ( eHoriOrient != text::HoriOrientation::NONE )
2584 eHoriOrient = text::HoriOrientation::NONE;
2585 aHoriOrient <<= eHoriOrient;
2586 setPropertyValue( aHoriOrientPropStr, aHoriOrient );
2589 // set x-position attribute
2590 aHoriPos <<= rPosition.X;
2591 setPropertyValue( aHoriPosPropStr, aHoriPos );
2595 // handle y-position
2597 // determine current y-position
2598 static constexpr OUString aVertPosPropStr(u"VertOrientPosition"_ustr);
2599 uno::Any aVertPos( getPropertyValue( aVertPosPropStr ) );
2600 sal_Int32 dCurrY = 0;
2601 aVertPos >>= dCurrY;
2602 // change y-position attribute, if needed
2603 if ( dCurrY != rPosition.Y )
2605 // adjust y-position orientation to text::VertOrientation::NONE, if needed
2606 // Note: has to be done before setting y-position attribute
2607 static constexpr OUString aVertOrientPropStr(u"VertOrient"_ustr);
2608 uno::Any aVertOrient( getPropertyValue( aVertOrientPropStr ) );
2609 sal_Int16 eVertOrient;
2610 if (aVertOrient >>= eVertOrient) // may be void
2612 if ( eVertOrient != text::VertOrientation::NONE )
2614 eVertOrient = text::VertOrientation::NONE;
2615 aVertOrient <<= eVertOrient;
2616 setPropertyValue( aVertOrientPropStr, aVertOrient );
2619 // set y-position attribute
2620 aVertPos <<= rPosition.Y;
2621 setPropertyValue( aVertPosPropStr, aVertPos );
2626 /** method to convert start or end position of the drawing object to the
2627 Writer specific position, which is the attribute position in layout direction
2628 #i59051#
2630 css::awt::Point SwXShape::ConvertStartOrEndPosToLayoutDir(
2631 const css::awt::Point& aStartOrEndPos )
2633 awt::Point aConvertedPos( aStartOrEndPos );
2635 SvxShape* pSvxShape = GetSvxShape();
2636 OSL_ENSURE( pSvxShape,
2637 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
2638 if ( pSvxShape )
2640 const SdrObject* pObj = pSvxShape->GetSdrObject();
2641 OSL_ENSURE( pObj,
2642 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
2643 if ( pObj )
2645 // get position of object in Writer coordinate system.
2646 awt::Point aPos( getPosition() );
2647 // get position of object in Drawing layer coordinate system
2648 const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
2649 const awt::Point aObjPos(
2650 convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
2651 convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
2652 // determine difference between these positions according to the
2653 // Writer coordinate system
2654 const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
2655 aPos.Y - aObjPos.Y );
2656 // apply translation difference to transformation matrix.
2657 if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
2659 aConvertedPos.X = aConvertedPos.X + aTranslateDiff.X;
2660 aConvertedPos.Y = aConvertedPos.Y + aTranslateDiff.Y;
2665 return aConvertedPos;
2668 css::drawing::PolyPolygonBezierCoords SwXShape::ConvertPolyPolygonBezierToLayoutDir(
2669 const css::drawing::PolyPolygonBezierCoords& aPath )
2671 drawing::PolyPolygonBezierCoords aConvertedPath( aPath );
2673 SvxShape* pSvxShape = GetSvxShape();
2674 OSL_ENSURE( pSvxShape,
2675 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
2676 if ( pSvxShape )
2678 const SdrObject* pObj = pSvxShape->GetSdrObject();
2679 OSL_ENSURE( pObj,
2680 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
2681 if ( pObj )
2683 // get position of object in Writer coordinate system.
2684 awt::Point aPos( getPosition() );
2685 // get position of object in Drawing layer coordinate system
2686 const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
2687 const awt::Point aObjPos(
2688 convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
2689 convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
2690 // determine difference between these positions according to the
2691 // Writer coordinate system
2692 const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
2693 aPos.Y - aObjPos.Y );
2694 // apply translation difference to PolyPolygonBezier.
2695 if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
2697 const basegfx::B2DHomMatrix aMatrix(basegfx::utils::createTranslateB2DHomMatrix(
2698 aTranslateDiff.X, aTranslateDiff.Y));
2700 for(drawing::PointSequence& rInnerSequence : asNonConstRange(aConvertedPath.Coordinates))
2702 for(awt::Point& rPoint : asNonConstRange(rInnerSequence))
2704 basegfx::B2DPoint aNewCoordinatePair(rPoint.X, rPoint.Y);
2705 aNewCoordinatePair *= aMatrix;
2706 rPoint.X = basegfx::fround(aNewCoordinatePair.getX());
2707 rPoint.Y = basegfx::fround(aNewCoordinatePair.getY());
2714 return aConvertedPath;
2717 SwXGroupShape::SwXGroupShape(uno::Reference<XInterface> & xShape,
2718 SwDoc const*const pDoc)
2719 : SwXShape(xShape, pDoc)
2721 #if OSL_DEBUG_LEVEL > 0
2722 uno::Reference<XShapes> xShapes(m_xShapeAgg, uno::UNO_QUERY);
2723 OSL_ENSURE(xShapes.is(), "no SvxShape found or shape is not a group shape");
2724 #endif
2727 SwXGroupShape::~SwXGroupShape()
2731 uno::Any SwXGroupShape::queryInterface( const uno::Type& rType )
2733 uno::Any aRet;
2734 if(rType == cppu::UnoType<XShapes>::get())
2735 aRet <<= uno::Reference<XShapes>(this);
2736 else
2737 aRet = SwXShape::queryInterface(rType);
2738 return aRet;
2741 void SwXGroupShape::acquire( ) noexcept
2743 SwXShape::acquire();
2746 void SwXGroupShape::release( ) noexcept
2748 SwXShape::release();
2751 void SwXGroupShape::add( const uno::Reference< XShape >& xShape )
2753 SolarMutexGuard aGuard;
2754 SvxShape* pSvxShape = GetSvxShape();
2755 SwFrameFormat* pFormat = GetFrameFormat();
2756 if(!(pSvxShape && pFormat))
2757 throw uno::RuntimeException();
2759 uno::Reference<XShapes> xShapes;
2760 if( m_xShapeAgg.is() )
2762 const uno::Type& rType = cppu::UnoType<XShapes>::get();
2763 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2764 aAgg >>= xShapes;
2766 if(!xShapes.is())
2767 throw uno::RuntimeException();
2769 xShapes->add(xShape);
2772 uno::Reference<lang::XUnoTunnel> xTunnel(xShape, uno::UNO_QUERY);
2773 SwXShape* pSwShape = comphelper::getFromUnoTunnel<SwXShape>(xTunnel);
2774 if(!(pSwShape && pSwShape->m_bDescriptor))
2775 return;
2777 SvxShape* pAddShape = comphelper::getFromUnoTunnel<SvxShape>(xTunnel);
2778 if(pAddShape)
2780 SdrObject* pObj = pAddShape->GetSdrObject();
2781 if(pObj)
2783 SwDoc* pDoc = pFormat->GetDoc();
2784 // set layer of new drawing
2785 // object to corresponding invisible layer.
2786 if( SdrInventor::FmForm != pObj->GetObjInventor())
2788 pObj->SetLayer( pSwShape->m_pImpl->GetOpaque()
2789 ? pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId()
2790 : pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
2792 else
2794 pObj->SetLayer(pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
2798 pSwShape->m_bDescriptor = false;
2801 void SwXGroupShape::remove( const uno::Reference< XShape >& xShape )
2803 SolarMutexGuard aGuard;
2804 uno::Reference<XShapes> xShapes;
2805 if( m_xShapeAgg.is() )
2807 const uno::Type& rType = cppu::UnoType<XShapes>::get();
2808 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2809 aAgg >>= xShapes;
2811 if(!xShapes.is())
2812 throw uno::RuntimeException();
2813 xShapes->remove(xShape);
2816 sal_Int32 SwXGroupShape::getCount()
2818 SolarMutexGuard aGuard;
2819 uno::Reference<XIndexAccess> xAcc;
2820 if( m_xShapeAgg.is() )
2822 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2823 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2824 aAgg >>= xAcc;
2826 if(!xAcc.is())
2827 throw uno::RuntimeException();
2828 return xAcc->getCount();
2831 uno::Any SwXGroupShape::getByIndex(sal_Int32 nIndex)
2833 SolarMutexGuard aGuard;
2834 uno::Reference<XIndexAccess> xAcc;
2835 if( m_xShapeAgg.is() )
2837 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2838 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2839 aAgg >>= xAcc;
2841 if(!xAcc.is())
2842 throw uno::RuntimeException();
2843 return xAcc->getByIndex(nIndex);
2846 uno::Type SwXGroupShape::getElementType( )
2848 SolarMutexGuard aGuard;
2849 uno::Reference<XIndexAccess> xAcc;
2850 if( m_xShapeAgg.is() )
2852 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2853 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2854 aAgg >>= xAcc;
2856 if(!xAcc.is())
2857 throw uno::RuntimeException();
2858 return xAcc->getElementType();
2861 sal_Bool SwXGroupShape::hasElements( )
2863 SolarMutexGuard aGuard;
2864 uno::Reference<XIndexAccess> xAcc;
2865 if( m_xShapeAgg.is() )
2867 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2868 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2869 aAgg >>= xAcc;
2871 if(!xAcc.is())
2872 throw uno::RuntimeException();
2873 return xAcc->hasElements();
2876 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */