Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / unocore / unodraw.cxx
blobcda4850d867194a401417dae6e1a97ab41ce592a
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 <svx/shapepropertynotifier.hxx>
64 #include <crstate.hxx>
65 #include <comphelper/extract.hxx>
66 #include <comphelper/profilezone.hxx>
67 #include <comphelper/sequence.hxx>
68 #include <cppuhelper/supportsservice.hxx>
69 #include <svx/scene3d.hxx>
70 #include <tools/UnitConversion.hxx>
71 #include <com/sun/star/beans/PropertyAttribute.hpp>
72 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
73 #include <com/sun/star/frame/XModel.hpp>
74 #include <fmtwrapinfluenceonobjpos.hxx>
75 #include <com/sun/star/text/TextContentAnchorType.hpp>
76 #include <basegfx/matrix/b2dhommatrixtools.hxx>
77 #include <com/sun/star/drawing/PointSequence.hpp>
78 #include <com/sun/star/lang/IllegalArgumentException.hpp>
79 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
80 #include <docmodel/uno/UnoTheme.hxx>
82 using namespace ::com::sun::star;
84 class SwShapeDescriptor_Impl
86 bool m_isInReading;
87 std::unique_ptr<SwFormatHoriOrient> m_pHOrient;
88 std::unique_ptr<SwFormatVertOrient> m_pVOrient;
89 std::unique_ptr<SwFormatAnchor> m_pAnchor;
90 std::unique_ptr<SwFormatSurround> m_pSurround;
91 std::unique_ptr<SvxULSpaceItem> m_pULSpace;
92 std::unique_ptr<SvxLRSpaceItem> m_pLRSpace;
93 bool m_bOpaque;
94 uno::Reference< text::XTextRange > m_xTextRange;
95 // #i26791#
96 std::unique_ptr<SwFormatFollowTextFlow> m_pFollowTextFlow;
97 // #i28701#
98 std::unique_ptr<SwFormatWrapInfluenceOnObjPos> m_pWrapInfluenceOnObjPos;
99 // #i28749#
100 sal_Int16 mnPositionLayoutDir;
102 SwShapeDescriptor_Impl(const SwShapeDescriptor_Impl&) = delete;
103 SwShapeDescriptor_Impl& operator=(const SwShapeDescriptor_Impl&) = delete;
105 public:
106 bool m_bInitializedPropertyNotifier;
108 public:
109 SwShapeDescriptor_Impl(SwDoc const*const pDoc)
110 : m_isInReading(pDoc && pDoc->IsInReading())
111 // #i32349# - no defaults, in order to determine on
112 // adding a shape, if positioning attributes are set or not.
113 , m_bOpaque(false)
114 // #i26791#
115 , m_pFollowTextFlow( new SwFormatFollowTextFlow(false) )
116 // #i28701# #i35017#
117 , m_pWrapInfluenceOnObjPos( new SwFormatWrapInfluenceOnObjPos(
118 text::WrapInfluenceOnPosition::ONCE_CONCURRENT) )
119 // #i28749#
120 , mnPositionLayoutDir(text::PositionLayoutDir::PositionInLayoutDirOfAnchor)
121 , m_bInitializedPropertyNotifier(false)
124 SwFormatAnchor* GetAnchor(bool bCreate = false)
126 if (bCreate && !m_pAnchor)
128 m_pAnchor.reset(new SwFormatAnchor(RndStdIds::FLY_AS_CHAR));
130 return m_pAnchor.get();
132 SwFormatHoriOrient* GetHOrient(bool bCreate = false)
134 if (bCreate && !m_pHOrient)
136 // #i26791#
137 m_pHOrient.reset(new SwFormatHoriOrient(0, text::HoriOrientation::NONE, text::RelOrientation::FRAME));
139 return m_pHOrient.get();
141 SwFormatVertOrient* GetVOrient(bool bCreate = false)
143 if (bCreate && !m_pVOrient)
145 if (m_isInReading && // tdf#113938 extensions might rely on old default
146 (!GetAnchor(true) || m_pAnchor->GetAnchorId() == RndStdIds::FLY_AS_CHAR))
147 { // for as-char, NONE ("from-top") is not a good default
148 m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::TOP, text::RelOrientation::FRAME));
150 else
151 { // #i26791#
152 m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::NONE, text::RelOrientation::FRAME));
155 return m_pVOrient.get();
158 SwFormatSurround* GetSurround(bool bCreate = false)
160 if (bCreate && !m_pSurround)
162 m_pSurround.reset(new SwFormatSurround());
164 return m_pSurround.get();
166 SvxLRSpaceItem* GetLRSpace(bool bCreate = false)
168 if (bCreate && !m_pLRSpace)
170 m_pLRSpace.reset(new SvxLRSpaceItem(RES_LR_SPACE));
172 return m_pLRSpace.get();
174 SvxULSpaceItem* GetULSpace(bool bCreate = false)
176 if (bCreate && !m_pULSpace)
178 m_pULSpace.reset(new SvxULSpaceItem(RES_UL_SPACE));
180 return m_pULSpace.get();
182 uno::Reference< text::XTextRange > & GetTextRange()
184 return m_xTextRange;
186 bool IsOpaque() const
188 return m_bOpaque;
190 const bool& GetOpaque() const
192 return m_bOpaque;
194 void RemoveHOrient() { m_pHOrient.reset(); }
195 void RemoveVOrient() { m_pVOrient.reset(); }
196 void RemoveAnchor() { m_pAnchor.reset(); }
197 void RemoveSurround() { m_pSurround.reset(); }
198 void RemoveULSpace() { m_pULSpace.reset(); }
199 void RemoveLRSpace() { m_pLRSpace.reset(); }
200 void SetOpaque(bool bSet){m_bOpaque = bSet;}
202 // #i26791#
203 SwFormatFollowTextFlow* GetFollowTextFlow( bool _bCreate = false )
205 if (_bCreate && !m_pFollowTextFlow)
207 m_pFollowTextFlow.reset(new SwFormatFollowTextFlow(false));
209 return m_pFollowTextFlow.get();
211 void RemoveFollowTextFlow()
213 m_pFollowTextFlow.reset();
216 // #i28749#
217 sal_Int16 GetPositionLayoutDir() const
219 return mnPositionLayoutDir;
221 void SetPositionLayoutDir( sal_Int16 _nPositionLayoutDir )
223 switch ( _nPositionLayoutDir )
225 case text::PositionLayoutDir::PositionInHoriL2R:
226 case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
228 mnPositionLayoutDir = _nPositionLayoutDir;
230 break;
231 default:
233 OSL_FAIL( "<SwShapeDescriptor_Impl::SetPositionLayoutDir(..)> - invalid attribute value." );
238 // #i28701#
239 SwFormatWrapInfluenceOnObjPos* GetWrapInfluenceOnObjPos(
240 const bool _bCreate = false )
242 if (_bCreate && !m_pWrapInfluenceOnObjPos)
244 m_pWrapInfluenceOnObjPos.reset(new SwFormatWrapInfluenceOnObjPos(
245 // #i35017#
246 text::WrapInfluenceOnPosition::ONCE_CONCURRENT));
248 return m_pWrapInfluenceOnObjPos.get();
250 void RemoveWrapInfluenceOnObjPos()
252 m_pWrapInfluenceOnObjPos.reset();
256 SwFmDrawPage::SwFmDrawPage( SwDoc* pDoc, SdrPage* pPage )
257 : SwFmDrawPage_Base(pPage)
258 , m_pDoc(pDoc)
259 , m_pPageView(nullptr)
260 , m_pPropertySet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_PAGE))
264 SwFmDrawPage::~SwFmDrawPage() noexcept
266 while (!m_vShapes.empty())
267 m_vShapes.back()->dispose();
268 RemovePageView();
271 const SdrMarkList& SwFmDrawPage::PreGroup(const uno::Reference< drawing::XShapes > & xShapes)
273 SelectObjectsInView( xShapes, GetPageView() );
274 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
275 return rMarkList;
278 void SwFmDrawPage::PreUnGroup(const uno::Reference< drawing::XShapeGroup >& rShapeGroup)
280 SelectObjectInView( rShapeGroup, GetPageView() );
283 SdrPageView* SwFmDrawPage::GetPageView()
285 if(!m_pPageView)
286 m_pPageView = mpView->ShowSdrPage( mpPage );
287 return m_pPageView;
290 void SwFmDrawPage::RemovePageView()
292 if(m_pPageView && mpView)
293 mpView->HideSdrPage();
294 m_pPageView = nullptr;
297 uno::Reference<drawing::XShape> SwFmDrawPage::GetShape(SdrObject* pObj)
299 if(!pObj)
300 return nullptr;
301 SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
302 // TODO see comment at
303 // <https://gerrit.libreoffice.org/c/core/+/78734/4#message-5ee4e724a8073c5c475f07da0b5d79bc34e61de5>
304 // "make page bookkeep the SwXShapes" [-loplugin:crosscast]:
305 SwFmDrawPage* pPage = dynamic_cast<SwFmDrawPage*>(pFormat);
306 if(!pPage || pPage->m_vShapes.empty())
307 return uno::Reference<drawing::XShape>(pObj->getUnoShape(), uno::UNO_QUERY);
308 for(const auto & pShape : pPage->m_vShapes)
310 SvxShape* pSvxShape = pShape->GetSvxShape();
311 if (pSvxShape && pSvxShape->GetSdrObject() == pObj)
312 return pShape;
314 return nullptr;
317 uno::Reference<drawing::XShapeGroup> SwFmDrawPage::GetShapeGroup(SdrObject* pObj)
319 return uno::Reference<drawing::XShapeGroup>(GetShape(pObj), uno::UNO_QUERY);
322 uno::Reference< drawing::XShape > SwFmDrawPage::CreateShape( SdrObject *pObj ) const
324 uno::Reference< drawing::XShape > xRet;
325 if(dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr || pObj->GetObjInventor() == SdrInventor::Swg)
327 SwFlyDrawContact* pFlyContact = static_cast<SwFlyDrawContact*>(pObj->GetUserCall());
328 if(pFlyContact)
330 SwFrameFormat* pFlyFormat = pFlyContact->GetFormat();
331 SwDoc* pDoc = pFlyFormat->GetDoc();
332 const SwNodeIndex* pIdx;
333 if( RES_FLYFRMFMT == pFlyFormat->Which()
334 && nullptr != ( pIdx = pFlyFormat->GetContent().GetContentIdx() )
335 && pIdx->GetNodes().IsDocNodes()
338 const SwNode* pNd = pDoc->GetNodes()[ pIdx->GetIndex() + 1 ];
339 if(!pNd->IsNoTextNode())
341 xRet.set(static_cast<cppu::OWeakObject*>(SwXTextFrame::CreateXTextFrame(*pDoc, pFlyFormat).get()),
342 uno::UNO_QUERY);
344 else if( pNd->IsGrfNode() )
346 xRet.set(static_cast<cppu::OWeakObject*>(SwXTextGraphicObject::CreateXTextGraphicObject(
347 *pDoc, pFlyFormat).get()), uno::UNO_QUERY);
349 else if( pNd->IsOLENode() )
351 xRet.set(static_cast<cppu::OWeakObject*>(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
352 *pDoc, pFlyFormat).get()), uno::UNO_QUERY);
355 else
357 OSL_FAIL( "<SwFmDrawPage::CreateShape(..)> - could not retrieve type. Thus, no shape created." );
358 return xRet;
362 else
364 // own block - temporary object has to be destroyed before
365 // the delegator is set #81670#
367 xRet = SvxFmDrawPage::CreateShape( pObj );
369 uno::Reference< XUnoTunnel > xShapeTunnel(xRet, uno::UNO_QUERY);
370 //don't create an SwXShape if it already exists
371 rtl::Reference<SwXShape> pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
372 if(!pShape)
374 xShapeTunnel = nullptr;
375 uno::Reference< uno::XInterface > xCreate(xRet, uno::UNO_QUERY);
376 xRet = nullptr;
377 if ( pObj->IsGroupObject() && (!pObj->Is3DObj() || DynCastE3dScene(pObj)) )
378 pShape = new SwXGroupShape(xCreate, nullptr);
379 else
380 pShape = new SwXShape(xCreate, nullptr);
381 xRet = pShape;
383 const_cast<std::vector<rtl::Reference<SwXShape>>*>(&m_vShapes)->push_back(pShape);
384 pShape->m_pPage = this;
386 return xRet;
389 uno::Reference<beans::XPropertySetInfo> SwFmDrawPage::getPropertySetInfo()
391 static uno::Reference<beans::XPropertySetInfo> xRet = m_pPropertySet->getPropertySetInfo();
392 return xRet;
395 void SwFmDrawPage::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
397 SolarMutexGuard aGuard;
398 const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName(rPropertyName);
400 switch (pEntry ? pEntry->nWID : -1)
402 case WID_PAGE_THEME:
404 SdrPage* pPage = GetSdrPage();
405 css::uno::Reference<css::util::XTheme> xTheme;
406 if (aValue >>= xTheme)
408 auto& rUnoTheme = dynamic_cast<UnoTheme&>(*xTheme);
409 pPage->getSdrPageProperties().SetTheme(rUnoTheme.getTheme());
412 break;
413 case WID_PAGE_BOTTOM:
414 case WID_PAGE_LEFT:
415 case WID_PAGE_RIGHT:
416 case WID_PAGE_TOP:
417 case WID_PAGE_WIDTH:
418 case WID_PAGE_HEIGHT:
419 case WID_PAGE_NUMBER:
420 case WID_PAGE_ORIENT:
421 case WID_PAGE_USERATTRIBS:
422 case WID_PAGE_ISDARK:
423 case WID_NAVORDER:
424 case WID_PAGE_BACKFULL:
425 break;
427 default:
428 throw beans::UnknownPropertyException(rPropertyName, static_cast<cppu::OWeakObject*>(this));
432 uno::Any SwFmDrawPage::getPropertyValue(const OUString& rPropertyName)
434 SolarMutexGuard aGuard;
435 const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName( rPropertyName);
437 uno::Any aAny;
439 switch (pEntry ? pEntry->nWID : -1)
441 case WID_PAGE_THEME:
443 css::uno::Reference<css::util::XTheme> xTheme;
445 auto pTheme = GetSdrPage()->getSdrPageProperties().GetTheme();
446 if (pTheme)
447 xTheme = model::theme::createXTheme(pTheme);
448 aAny <<= xTheme;
450 break;
452 case WID_PAGE_NUMBER:
454 const sal_uInt16 nPageNumber(GetSdrPage()->GetPageNum());
455 aAny <<= o3tl::narrowing<sal_Int16>(nPageNumber);
457 break;
459 case WID_PAGE_BOTTOM:
460 case WID_PAGE_LEFT:
461 case WID_PAGE_RIGHT:
462 case WID_PAGE_TOP:
463 case WID_PAGE_WIDTH:
464 case WID_PAGE_HEIGHT:
465 case WID_PAGE_ORIENT:
466 case WID_PAGE_USERATTRIBS:
467 case WID_PAGE_ISDARK:
468 case WID_NAVORDER:
469 case WID_PAGE_BACKFULL:
470 break;
472 default:
473 throw beans::UnknownPropertyException(rPropertyName, static_cast<cppu::OWeakObject*>(this));
475 return aAny;
478 void SwFmDrawPage::addPropertyChangeListener(const OUString& /*PropertyName*/,
479 const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
481 OSL_FAIL("not implemented");
484 void SwFmDrawPage::removePropertyChangeListener(const OUString& /*PropertyName*/,
485 const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
487 OSL_FAIL("not implemented");
490 void SwFmDrawPage::addVetoableChangeListener(const OUString& /*PropertyName*/,
491 const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
493 OSL_FAIL("not implemented");
496 void SwFmDrawPage::removeVetoableChangeListener(const OUString& /*PropertyName*/,
497 const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
499 OSL_FAIL("not implemented");
502 namespace
504 class SwXShapesEnumeration
505 : public SwSimpleEnumeration_Base
507 private:
508 std::vector< css::uno::Any > m_aShapes;
509 protected:
510 virtual ~SwXShapesEnumeration() override {};
511 public:
512 explicit SwXShapesEnumeration(SwFmDrawPage* const pDrawPage);
514 //XEnumeration
515 virtual sal_Bool SAL_CALL hasMoreElements() override;
516 virtual uno::Any SAL_CALL nextElement() override;
518 //XServiceInfo
519 virtual OUString SAL_CALL getImplementationName() override;
520 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
521 virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
525 SwXShapesEnumeration::SwXShapesEnumeration(SwFmDrawPage* const pDrawPage)
527 SolarMutexGuard aGuard;
528 sal_Int32 nCount = pDrawPage->getCount();
529 m_aShapes.reserve(nCount);
530 for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
532 uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
533 m_aShapes.push_back(uno::Any(xShape));
537 sal_Bool SwXShapesEnumeration::hasMoreElements()
539 SolarMutexGuard aGuard;
540 return !m_aShapes.empty();
543 uno::Any SwXShapesEnumeration::nextElement()
545 SolarMutexGuard aGuard;
546 if(m_aShapes.empty())
547 throw container::NoSuchElementException();
548 uno::Any aResult = m_aShapes.back();
549 m_aShapes.pop_back();
550 return aResult;
553 OUString SwXShapesEnumeration::getImplementationName()
555 return "SwXShapeEnumeration";
558 sal_Bool SwXShapesEnumeration::supportsService(const OUString& ServiceName)
560 return cppu::supportsService(this, ServiceName);
563 uno::Sequence< OUString > SwXShapesEnumeration::getSupportedServiceNames()
565 return { OUString("com.sun.star.container.XEnumeration") };
568 uno::Reference< container::XEnumeration > SwFmDrawPage::createEnumeration()
570 SolarMutexGuard aGuard;
571 return uno::Reference< container::XEnumeration >(
572 new SwXShapesEnumeration(this));
575 OUString SwFmDrawPage::getImplementationName()
577 return "SwFmDrawPage";
580 sal_Bool SwFmDrawPage::supportsService(const OUString& rServiceName)
582 return cppu::supportsService(this, rServiceName);
585 uno::Sequence< OUString > SwFmDrawPage::getSupportedServiceNames()
587 return { "com.sun.star.drawing.GenericDrawPage" };
590 sal_Int32 SwFmDrawPage::getCount()
592 SolarMutexGuard aGuard;
593 if(!m_pDoc)
594 throw uno::RuntimeException();
595 if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
596 return 0;
597 else
598 return SwTextBoxHelper::getCount(GetSdrPage());
601 uno::Any SwFmDrawPage::getByIndex(sal_Int32 nIndex)
603 SolarMutexGuard aGuard;
604 if(!m_pDoc)
605 throw uno::RuntimeException();
606 if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
607 throw lang::IndexOutOfBoundsException();
609 return SwTextBoxHelper::getByIndex(GetSdrPage(), nIndex);
612 uno::Type SwFmDrawPage::getElementType()
614 return cppu::UnoType<drawing::XShape>::get();
617 sal_Bool SwFmDrawPage::hasElements()
619 SolarMutexGuard aGuard;
620 if(!m_pDoc)
621 throw uno::RuntimeException();
622 if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
623 return false;
624 return SvxFmDrawPage::hasElements();
627 void SwFmDrawPage::add(const uno::Reference< drawing::XShape > & xShape)
629 SolarMutexGuard aGuard;
630 if(!m_pDoc)
631 throw uno::RuntimeException();
632 uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShape, uno::UNO_QUERY);
633 SwXShape* pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
634 SvxShape* pSvxShape = comphelper::getFromUnoTunnel<SvxShape>(xShapeTunnel);
636 // this is not a writer shape
637 if(!pShape)
638 throw uno::RuntimeException("illegal object",
639 static_cast< cppu::OWeakObject * > ( this ) );
641 // we're already registered in the model / SwXDrawPage::add() already called
642 if(pShape->m_pPage || !pShape->m_bDescriptor )
643 return;
645 // we're inserted elsewhere already
646 if ( pSvxShape->GetSdrObject() )
648 if ( pSvxShape->GetSdrObject()->IsInserted() )
650 return;
653 SvxFmDrawPage::add(xShape);
655 OSL_ENSURE(pSvxShape, "Why is here no SvxShape?");
656 // this position is definitely in 1/100 mm
657 awt::Point aMM100Pos(pSvxShape->getPosition());
659 // now evaluate the properties of SwShapeDescriptor_Impl
660 SwShapeDescriptor_Impl* pDesc = pShape->GetDescImpl();
662 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSet( m_pDoc->GetAttrPool() );
663 SwFormatAnchor aAnchor( RndStdIds::FLY_AS_CHAR );
664 bool bOpaque = false;
665 if( pDesc )
667 if(pDesc->GetSurround())
668 aSet.Put( *pDesc->GetSurround());
669 // all items are already in Twip
670 if(pDesc->GetLRSpace())
672 aSet.Put(*pDesc->GetLRSpace());
674 if(pDesc->GetULSpace())
676 aSet.Put(*pDesc->GetULSpace());
678 if(pDesc->GetAnchor())
679 aAnchor = *pDesc->GetAnchor();
681 // #i32349# - if no horizontal position exists, create one
682 if ( !pDesc->GetHOrient() )
684 SwFormatHoriOrient* pHori = pDesc->GetHOrient( true );
685 SwTwips nHoriPos = o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100);
686 pHori->SetPos( nHoriPos );
689 if(pDesc->GetHOrient()->GetHoriOrient() == text::HoriOrientation::NONE)
690 aMM100Pos.X = convertTwipToMm100(pDesc->GetHOrient()->GetPos());
691 aSet.Put( *pDesc->GetHOrient() );
693 // #i32349# - if no vertical position exists, create one
694 if ( !pDesc->GetVOrient() )
696 SwFormatVertOrient* pVert = pDesc->GetVOrient( true );
697 SwTwips nVertPos = o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100);
698 pVert->SetPos( nVertPos );
701 if(pDesc->GetVOrient()->GetVertOrient() == text::VertOrientation::NONE)
702 aMM100Pos.Y = convertTwipToMm100(pDesc->GetVOrient()->GetPos());
703 aSet.Put( *pDesc->GetVOrient() );
706 if(pDesc->GetSurround())
707 aSet.Put( *pDesc->GetSurround());
708 bOpaque = pDesc->IsOpaque();
710 // #i26791#
711 if ( pDesc->GetFollowTextFlow() )
713 aSet.Put( *pDesc->GetFollowTextFlow() );
716 // #i28701#
717 if ( pDesc->GetWrapInfluenceOnObjPos() )
719 aSet.Put( *pDesc->GetWrapInfluenceOnObjPos() );
723 pSvxShape->setPosition(aMM100Pos);
724 SdrObject* pObj = pSvxShape->GetSdrObject();
725 // #108784# - set layer of new drawing object to corresponding
726 // invisible layer.
727 if(SdrInventor::FmForm != pObj->GetObjInventor())
728 pObj->SetLayer( bOpaque ? m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() : m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
729 else
730 pObj->SetLayer(m_pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
732 std::optional<SwPaM> pPam(m_pDoc->GetNodes().GetEndOfContent());
733 std::unique_ptr<SwUnoInternalPaM> pInternalPam;
734 uno::Reference< text::XTextRange > xRg;
735 if( pDesc && (xRg = pDesc->GetTextRange()).is() )
737 pInternalPam.reset(new SwUnoInternalPaM(*m_pDoc));
738 if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg))
739 throw uno::RuntimeException();
741 if(RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId() &&
742 !pInternalPam->GetPointNode().FindFlyStartNode())
744 aAnchor.SetType(RndStdIds::FLY_AS_CHAR);
746 else if (RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId()
747 && 0 == aAnchor.GetPageNum())
749 aAnchor.SetAnchor(pInternalPam->Start());
750 aAnchor.SetType(RndStdIds::FLY_AT_CHAR); // convert invalid at-page
754 else if ((aAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
756 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
757 Point aTmp(o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100), o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100));
758 m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( pPam->GetPoint(), aTmp, &aState );
759 aAnchor.SetAnchor( pPam->GetPoint() );
761 // #i32349# - adjustment of vertical positioning
762 // attributes no longer needed, because it's already got a default.
764 else
766 aAnchor.SetType(RndStdIds::FLY_AT_PAGE);
768 // #i32349# - adjustment of vertical positioning
769 // attributes no longer needed, because it's already got a default.
771 aSet.Put(aAnchor);
772 SwPaM* pTemp = pInternalPam.get();
773 if ( !pTemp )
774 pTemp = &*pPam;
775 UnoActionContext aAction(m_pDoc);
776 m_pDoc->getIDocumentContentOperations().InsertDrawObj( *pTemp, *pObj, aSet );
778 if (pSvxShape->GetSdrObject()->GetName().isEmpty())
780 pSvxShape->GetSdrObject()->SetName(m_pDoc->GetUniqueShapeName());
783 SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
784 if (pFormat)
786 if (pFormat->GetName().isEmpty())
788 pFormat->SetFormatName(pSvxShape->GetSdrObject()->GetName(), false);
791 pShape->m_bDescriptor = false;
793 pPam.reset();
794 pInternalPam.reset();
797 void SwFmDrawPage::remove(const uno::Reference< drawing::XShape > & xShape)
799 SolarMutexGuard aGuard;
800 if(!m_pDoc)
801 throw uno::RuntimeException();
802 // tdf#41466 remove TextFrame too which is belonged to the actual shape
803 auto xTextFrame = SwTextBoxHelper::getUnoTextFrame(xShape);
804 if (xTextFrame)
806 uno::Reference<lang::XComponent> xComp(xTextFrame, uno::UNO_QUERY);
807 if (xComp)
808 xComp->dispose();
810 // remove shape
811 uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
812 xComp->dispose();
815 uno::Reference< drawing::XShapeGroup > SwFmDrawPage::group(const uno::Reference< drawing::XShapes > & xShapes)
817 SolarMutexGuard aGuard;
818 if(!m_pDoc || !xShapes.is())
819 throw uno::RuntimeException();
820 uno::Reference< drawing::XShapeGroup > xRet;
821 // mark and return MarkList
822 const SdrMarkList& rMarkList = PreGroup(xShapes);
823 if ( rMarkList.GetMarkCount() > 0 )
825 for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
827 const SdrObject *pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
828 if (RndStdIds::FLY_AS_CHAR == ::FindFrameFormat(const_cast<SdrObject*>(
829 pObj))->GetAnchor().GetAnchorId())
831 throw lang::IllegalArgumentException(
832 "Shape must not have 'as character' anchor!", nullptr, 0);
836 UnoActionContext aContext(m_pDoc);
837 m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
839 SwDrawContact* pContact = m_pDoc->GroupSelection( *GetDrawView() );
840 m_pDoc->ChgAnchor(
841 GetDrawView()->GetMarkedObjectList(),
842 RndStdIds::FLY_AT_PARA,
843 true, false );
845 GetDrawView()->UnmarkAll();
846 if(pContact)
847 xRet = SwFmDrawPage::GetShapeGroup( pContact->GetMaster() );
848 m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
850 RemovePageView();
851 return xRet;
854 void SwFmDrawPage::ungroup(const uno::Reference< drawing::XShapeGroup > & rShapeGroup)
856 SolarMutexGuard aGuard;
857 if(!m_pDoc)
858 throw uno::RuntimeException();
860 PreUnGroup(rShapeGroup);
861 UnoActionContext aContext(m_pDoc);
862 m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
864 m_pDoc->UnGroupSelection( *GetDrawView() );
865 m_pDoc->ChgAnchor( GetDrawView()->GetMarkedObjectList(),
866 RndStdIds::FLY_AT_PARA,
867 true, false );
868 m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
869 RemovePageView();
873 * Renamed and outlined to detect where it's called
875 void SwFmDrawPage::InvalidateSwDoc()
877 m_pDoc = nullptr;
880 const uno::Sequence< sal_Int8 > & SwXShape::getUnoTunnelId()
882 static const comphelper::UnoIdInit theSwXShapeUnoTunnelId;
883 return theSwXShapeUnoTunnelId.getSeq();
886 sal_Int64 SAL_CALL SwXShape::getSomething( const uno::Sequence< sal_Int8 >& rId )
888 if( comphelper::isUnoTunnelId<SwXShape>(rId) )
890 return comphelper::getSomething_cast(this);
893 if( m_xShapeAgg.is() )
895 const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
896 uno::Any aAgg = m_xShapeAgg->queryAggregation( rTunnelType );
897 if(auto xAggTunnel = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
898 aAgg))
900 if(xAggTunnel->is())
901 return (*xAggTunnel)->getSomething(rId);
904 return 0;
906 namespace
908 void lcl_addShapePropertyEventFactories( SdrObject& _rObj, SwXShape& _rShape )
910 auto pProvider = std::make_unique<svx::PropertyValueProvider>( _rShape, "AnchorType" );
911 _rObj.registerProvider( svx::ShapePropertyProviderId::TextDocAnchor, std::move(pProvider) );
915 SwXShape::SwXShape(
916 uno::Reference<uno::XInterface> & xShape,
917 SwDoc const*const pDoc)
918 : m_pPage(nullptr)
919 , m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SHAPE))
920 , m_pPropertyMapEntries(aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_TEXT_SHAPE))
921 , m_pImpl(new SwShapeDescriptor_Impl(pDoc))
922 , m_bDescriptor(true)
924 if(!xShape.is()) // default Ctor
925 return;
927 const uno::Type& rAggType = cppu::UnoType<uno::XAggregation>::get();
928 //aAgg contains a reference of the SvxShape!
930 uno::Any aAgg = xShape->queryInterface(rAggType);
931 aAgg >>= m_xShapeAgg;
932 // #i31698#
933 if ( m_xShapeAgg.is() )
935 m_xShapeAgg->queryAggregation( cppu::UnoType<drawing::XShape>::get()) >>= mxShape;
936 OSL_ENSURE( mxShape.is(),
937 "<SwXShape::SwXShape(..)> - no XShape found at <xShapeAgg>" );
940 xShape = nullptr;
941 osl_atomic_increment(&m_refCount);
942 if( m_xShapeAgg.is() )
943 m_xShapeAgg->setDelegator( static_cast<cppu::OWeakObject*>(this) );
944 osl_atomic_decrement(&m_refCount);
946 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(m_xShapeAgg);
947 if(pObj)
949 lcl_addShapePropertyEventFactories( *pObj, *this );
950 m_pImpl->m_bInitializedPropertyNotifier = true;
955 SwFrameFormat* SwXShape::GetFrameFormat() const
957 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(m_xShapeAgg);
958 if(pObj)
959 return ::FindFrameFormat( pObj );
960 return nullptr;
963 void SwXShape::AddExistingShapeToFormat( SdrObject const & _rObj )
965 SdrObjListIter aIter( _rObj, SdrIterMode::DeepNoGroups );
966 while ( aIter.IsMore() )
968 SdrObject* pCurrent = aIter.Next();
969 OSL_ENSURE( pCurrent, "SwXShape::AddExistingShapeToFormat: invalid object list element!" );
970 if ( !pCurrent )
971 continue;
973 auto pSwShape = comphelper::getFromUnoTunnel<SwXShape>(pCurrent->getWeakUnoShape());
974 if ( pSwShape )
976 if ( pSwShape->m_bDescriptor )
977 pSwShape->m_bDescriptor = false;
979 if ( !pSwShape->m_pImpl->m_bInitializedPropertyNotifier )
981 lcl_addShapePropertyEventFactories( *pCurrent, *pSwShape );
982 pSwShape->m_pImpl->m_bInitializedPropertyNotifier = true;
988 SwXShape::~SwXShape()
990 SolarMutexGuard aGuard;
992 if (m_xShapeAgg.is())
994 uno::Reference< uno::XInterface > xRef;
995 m_xShapeAgg->setDelegator(xRef);
997 m_pImpl.reset();
998 if(m_pPage)
999 const_cast<SwFmDrawPage*>(m_pPage)->RemoveShape(this);
1002 uno::Any SwXShape::queryInterface( const uno::Type& aType )
1004 uno::Any aRet;
1005 SdrObject* pObj = nullptr;
1007 if ((aType == cppu::UnoType<text::XText>::get())
1008 || (aType == cppu::UnoType<text::XTextRange>::get())
1009 || (aType == cppu::UnoType<text::XTextAppend>::get()))
1011 pObj = SdrObject::getSdrObjectFromXShape(mxShape);
1013 aRet = SwTextBoxHelper::queryInterface(GetFrameFormat(), aType, pObj);
1014 if (aRet.hasValue())
1015 return aRet;
1017 aRet = SwXShapeBaseClass::queryInterface(aType);
1018 // #i53320# - follow-up of #i31698#
1019 // interface drawing::XShape is overloaded. Thus, provide
1020 // correct object instance.
1021 if(!aRet.hasValue() && m_xShapeAgg.is())
1023 if(aType == cppu::UnoType<XShape>::get())
1024 aRet <<= uno::Reference<XShape>(this);
1025 else
1026 aRet = m_xShapeAgg->queryAggregation(aType);
1028 return aRet;
1031 uno::Sequence< uno::Type > SwXShape::getTypes( )
1033 uno::Sequence< uno::Type > aRet = SwXShapeBaseClass::getTypes();
1034 if(m_xShapeAgg.is())
1036 uno::Any aProv = m_xShapeAgg->queryAggregation(cppu::UnoType<XTypeProvider>::get());
1037 if(aProv.hasValue())
1039 uno::Reference< XTypeProvider > xAggProv;
1040 aProv >>= xAggProv;
1041 return comphelper::concatSequences(aRet, xAggProv->getTypes());
1044 return aRet;
1047 uno::Sequence< sal_Int8 > SwXShape::getImplementationId( )
1049 return css::uno::Sequence<sal_Int8>();
1052 uno::Reference< beans::XPropertySetInfo > SwXShape::getPropertySetInfo()
1054 SolarMutexGuard aGuard;
1055 if (!mxPropertySetInfo)
1057 if(m_xShapeAgg.is())
1059 const uno::Type& rPropSetType = cppu::UnoType<beans::XPropertySet>::get();
1060 uno::Any aPSet = m_xShapeAgg->queryAggregation( rPropSetType );
1061 if(auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
1062 aPSet))
1064 uno::Reference< beans::XPropertySetInfo > xInfo = (*xPrSet)->getPropertySetInfo();
1065 // Expand PropertySetInfo!
1066 const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
1067 mxPropertySetInfo = new SfxExtItemPropertySetInfo( m_pPropertyMapEntries, aPropSeq );
1070 if(!mxPropertySetInfo)
1071 mxPropertySetInfo = m_pPropSet->getPropertySetInfo();
1073 return mxPropertySetInfo;
1076 void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
1078 SolarMutexGuard aGuard;
1079 SwFrameFormat* pFormat = GetFrameFormat();
1080 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1081 if(!m_xShapeAgg.is())
1082 return;
1084 if(pEntry)
1086 if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
1087 throw beans::PropertyVetoException ("Property is read-only: " + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
1088 // with the layout it is possible to move the anchor without changing the position
1089 if(pFormat)
1091 SwAttrSet aSet(pFormat->GetAttrSet());
1092 SwDoc* pDoc = pFormat->GetDoc();
1093 if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
1095 bool bDone = false;
1096 uno::Reference<text::XTextFrame> xFrame;
1097 if(aValue >>= xFrame)
1099 SwXFrame* pFrame = dynamic_cast<SwXFrame*>(xFrame.get());
1100 if(pFrame && pFrame->GetFrameFormat() &&
1101 pFrame->GetFrameFormat()->GetDoc() == pDoc)
1103 UnoActionContext aCtx(pDoc);
1104 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aItemSet( pDoc->GetAttrPool() );
1105 aItemSet.SetParent(&pFormat->GetAttrSet());
1106 SwFormatAnchor aAnchor = static_cast<const SwFormatAnchor&>(aItemSet.Get(pEntry->nWID));
1107 SwPosition aPos(*pFrame->GetFrameFormat()->GetContent().GetContentIdx());
1108 aAnchor.SetAnchor(&aPos);
1109 aAnchor.SetType(RndStdIds::FLY_AT_FLY);
1110 aItemSet.Put(aAnchor);
1111 pFormat->SetFormatAttr(aItemSet);
1112 bDone = true;
1115 if(!bDone)
1116 throw lang::IllegalArgumentException();
1118 else if(RES_OPAQUE == pEntry->nWID)
1120 SvxShape* pSvxShape = GetSvxShape();
1121 SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
1122 if(pSvxShape)
1124 SdrObject* pObj = pSvxShape->GetSdrObject();
1125 // set layer of new drawing
1126 // object to corresponding invisible layer.
1127 bool bIsVisible = pDoc->getIDocumentDrawModelAccess().IsVisibleLayerId( pObj->GetLayer() );
1128 if(SdrInventor::FmForm != pObj->GetObjInventor())
1130 pObj->SetLayer( *o3tl::doAccess<bool>(aValue)
1131 ? ( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetHeavenId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() )
1132 : ( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetHellId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() ));
1134 else
1136 pObj->SetLayer( bIsVisible ? pDoc->getIDocumentDrawModelAccess().GetControlsId() : pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
1142 // #i26791# - special handling for property FN_TEXT_RANGE
1143 else if ( FN_TEXT_RANGE == pEntry->nWID )
1145 SwFormatAnchor aAnchor( aSet.Get( RES_ANCHOR ) );
1146 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1148 // set property <TextRange> not valid for to-page anchored shapes
1149 throw lang::IllegalArgumentException();
1152 std::unique_ptr<SwUnoInternalPaM> pInternalPam(
1153 new SwUnoInternalPaM( *(pFormat->GetDoc()) ));
1154 uno::Reference< text::XTextRange > xRg;
1155 aValue >>= xRg;
1156 if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg) )
1158 throw uno::RuntimeException();
1161 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
1163 //delete old SwFormatFlyCnt
1164 //With AnchorAsCharacter the current TextAttribute has to be deleted.
1165 //Tbis removes the frame format too.
1166 //To prevent this the connection between format and attribute has to be broken before.
1167 SwTextNode *pTextNode = aAnchor.GetAnchorNode()->GetTextNode();
1168 SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno", "Missing FlyInCnt-Hint." );
1169 const sal_Int32 nIdx = aAnchor.GetAnchorContentOffset();
1170 SwTextAttr * const pHint =
1171 pTextNode->GetTextAttrForCharAt(
1172 nIdx, RES_TXTATR_FLYCNT );
1173 assert(pHint && "Missing Hint.");
1174 SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
1175 "sw.uno", "Missing FlyInCnt-Hint." );
1176 SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFormat,
1177 "sw.uno", "Wrong TextFlyCnt-Hint." );
1178 const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
1179 .SetFlyFormat();
1181 //The connection is removed now the attribute can be deleted.
1182 pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
1183 //create a new one
1184 SwTextNode *pNd = pInternalPam->GetPointNode().GetTextNode();
1185 SAL_WARN_IF( !pNd, "sw.uno", "Cursor not at TextNode." );
1186 SwFormatFlyCnt aFormat( pFormat );
1187 pNd->InsertItem(aFormat, pInternalPam->GetPoint()
1188 ->GetContentIndex(), 0 );
1189 //Refetch in case SwTextNode::InsertItem causes it to be deleted
1190 pFormat = GetFrameFormat();
1192 else
1194 aAnchor.SetAnchor( pInternalPam->GetPoint() );
1195 aSet.Put(aAnchor);
1196 pFormat->SetFormatAttr(aSet);
1199 else if (pEntry->nWID == FN_TEXT_BOX)
1201 auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
1202 if (pEntry->nMemberId == MID_TEXT_BOX)
1204 bool bValue(false);
1205 aValue >>= bValue;
1207 if (bValue)
1208 SwTextBoxHelper::create(pFormat, pObj);
1209 else
1210 SwTextBoxHelper::destroy(pFormat, pObj);
1212 else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
1214 if (aValue.getValueType()
1215 == cppu::UnoType<uno::Reference<text::XTextFrame>>::get())
1216 SwTextBoxHelper::set(pFormat, pObj,
1217 aValue.get<uno::Reference<text::XTextFrame>>());
1218 else
1219 SAL_WARN( "sw.uno", "This is not a TextFrame!" );
1222 else if (pEntry->nWID == RES_CHAIN)
1224 if (pEntry->nMemberId == MID_CHAIN_NEXTNAME || pEntry->nMemberId == MID_CHAIN_PREVNAME)
1225 SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
1226 SdrObject::getSdrObjectFromXShape(mxShape));
1228 // #i28749#
1229 else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
1231 sal_Int16 nPositionLayoutDir = 0;
1232 aValue >>= nPositionLayoutDir;
1233 pFormat->SetPositionLayoutDir( nPositionLayoutDir );
1235 else if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
1237 UnoActionContext aCtx(pDoc);
1238 if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
1240 SdrObject* pObj = pFormat->FindSdrObject();
1241 SdrMarkList aList;
1242 SdrMark aMark(pObj);
1243 aList.InsertEntry(aMark);
1244 sal_Int32 nAnchor = 0;
1245 cppu::enum2int( nAnchor, aValue );
1246 pDoc->ChgAnchor( aList, static_cast<RndStdIds>(nAnchor),
1247 false, true );
1249 else
1251 m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
1252 pFormat->SetFormatAttr(aSet);
1255 else if( RES_FRM_SIZE == pEntry->nWID &&
1256 ( pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH
1257 || pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION
1258 || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION ) )
1260 SvxShape* pSvxShape = GetSvxShape();
1261 SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
1262 if(pSvxShape)
1264 SdrObject* pObj = pSvxShape->GetSdrObject();
1265 sal_Int16 nPercent(100);
1266 aValue >>= nPercent;
1267 switch (pEntry->nMemberId)
1269 case MID_FRMSIZE_REL_WIDTH:
1270 pObj->SetRelativeWidth( nPercent / 100.0 );
1271 break;
1272 case MID_FRMSIZE_REL_HEIGHT:
1273 pObj->SetRelativeHeight( nPercent / 100.0 );
1274 break;
1275 case MID_FRMSIZE_REL_WIDTH_RELATION:
1276 pObj->SetRelativeWidthRelation(nPercent);
1277 break;
1278 case MID_FRMSIZE_REL_HEIGHT_RELATION:
1279 pObj->SetRelativeHeightRelation(nPercent);
1280 break;
1284 else if (pEntry->nWID == RES_HORI_ORIENT
1285 && pEntry->nMemberId == MID_HORIORIENT_RELATION
1286 && aSet.Get(RES_ANCHOR).GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1288 uno::Any value(aValue);
1289 sal_Int16 nRelOrient(text::RelOrientation::PAGE_FRAME);
1290 aValue >>= nRelOrient;
1291 if (sw::GetAtPageRelOrientation(nRelOrient, true))
1293 SAL_WARN("sw.core", "SwXShape: fixing invalid horizontal RelOrientation for at-page anchor");
1294 value <<= nRelOrient;
1296 m_pPropSet->setPropertyValue( *pEntry, value, aSet );
1297 pFormat->SetFormatAttr(aSet);
1299 else
1301 m_pPropSet->setPropertyValue( *pEntry, aValue, aSet );
1303 if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
1305 bool bSetAttr = true;
1306 text::TextContentAnchorType eNewAnchor = static_cast<text::TextContentAnchorType>(SWUnoHelper::GetEnumAsInt32( aValue ));
1308 //if old anchor was in_cntnt the related text attribute has to be removed
1309 const SwFormatAnchor& rOldAnchor = pFormat->GetAnchor();
1310 RndStdIds eOldAnchorId = rOldAnchor.GetAnchorId();
1311 SdrObject* pObj = pFormat->FindSdrObject();
1312 SwFrameFormat *pFlyFormat = FindFrameFormat( pObj );
1313 pFlyFormat->DelFrames();
1314 if( text::TextContentAnchorType_AS_CHARACTER != eNewAnchor &&
1315 (RndStdIds::FLY_AS_CHAR == eOldAnchorId))
1317 //With AnchorAsCharacter the current TextAttribute has to be deleted.
1318 //Tbis removes the frame format too.
1319 //To prevent this the connection between format and attribute has to be broken before.
1320 SwTextNode *pTextNode = rOldAnchor.GetAnchorNode()->GetTextNode();
1321 SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno", "Missing FlyInCnt-Hint." );
1322 const sal_Int32 nIdx = rOldAnchor.GetAnchorContentOffset();
1323 SwTextAttr * const pHint =
1324 pTextNode->GetTextAttrForCharAt(
1325 nIdx, RES_TXTATR_FLYCNT );
1326 assert(pHint && "Missing Hint.");
1327 SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
1328 "sw.uno", "Missing FlyInCnt-Hint." );
1329 SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFlyFormat,
1330 "sw.uno", "Wrong TextFlyCnt-Hint." );
1331 const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
1332 .SetFlyFormat();
1334 //The connection is removed now the attribute can be deleted.
1335 pTextNode->DeleteAttributes(RES_TXTATR_FLYCNT, nIdx);
1337 else if( text::TextContentAnchorType_AT_PAGE != eNewAnchor &&
1338 (RndStdIds::FLY_AT_PAGE == eOldAnchorId))
1340 SwFormatAnchor aNewAnchor( aSet.Get( RES_ANCHOR ) );
1341 //if the fly has been anchored at page then it needs to be connected
1342 //to the content position
1343 SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
1344 if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
1346 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1347 Point aTmp( pObj->GetSnapRect().TopLeft() );
1348 pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
1350 else
1352 //without access to the layout the last node of the body will be used as anchor position
1353 aPam.Move( fnMoveBackward, GoInDoc );
1355 //anchor position has to be inserted after the text attribute has been inserted
1356 aNewAnchor.SetAnchor( aPam.GetPoint() );
1357 aSet.Put( aNewAnchor );
1358 pFormat->SetFormatAttr(aSet);
1359 bSetAttr = false;
1361 if( text::TextContentAnchorType_AS_CHARACTER == eNewAnchor &&
1362 (RndStdIds::FLY_AS_CHAR != eOldAnchorId))
1364 SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
1365 if( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
1367 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1368 Point aTmp( pObj->GetSnapRect().TopLeft() );
1369 pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
1371 else
1373 //without access to the layout the last node of the body will be used as anchor position
1374 aPam.Move( fnMoveBackward, GoInDoc );
1376 //the RES_TXTATR_FLYCNT needs to be added now
1377 SwTextNode *pNd = aPam.GetPointNode().GetTextNode();
1378 SAL_WARN_IF( !pNd, "sw.uno", "Cursor is not in a TextNode." );
1379 SwFormatFlyCnt aFormat( pFlyFormat );
1380 pNd->InsertItem(aFormat,
1381 aPam.GetPoint()->GetContentIndex(), 0 );
1382 aPam.GetPoint()->AdjustContent(-1); // InsertItem moved it
1383 SwFormatAnchor aNewAnchor(
1384 aSet.Get(RES_ANCHOR));
1385 aNewAnchor.SetAnchor( aPam.GetPoint() );
1386 aSet.Put( aNewAnchor );
1388 if( bSetAttr )
1389 pFormat->SetFormatAttr(aSet);
1391 // If this property is an anchor change, and there is a group shape with textboxes
1392 // do anchor sync in time unless the anchor sync in the porfly will cause crash during
1393 // layout calculation (When importing an inline shape in docx via dmapper).
1394 if (pFormat->Which() == RES_DRAWFRMFMT && pFormat->GetOtherTextBoxFormats()
1395 && pFormat->GetOtherTextBoxFormats()->GetTextBoxCount()
1396 > o3tl::make_unsigned(1))
1397 SwTextBoxHelper::synchronizeGroupTextBoxProperty(
1398 SwTextBoxHelper::changeAnchor, pFormat,
1399 SdrObject::getSdrObjectFromXShape(mxShape));
1401 else
1402 pFormat->SetFormatAttr(aSet);
1405 // We have a pFormat and a pEntry as well: try to sync TextBox property.
1406 SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
1407 SdrObject::getSdrObjectFromXShape(mxShape));
1409 else
1411 SfxPoolItem* pItem = nullptr;
1412 switch(pEntry->nWID)
1414 case RES_ANCHOR:
1415 pItem = m_pImpl->GetAnchor(true);
1416 break;
1417 case RES_HORI_ORIENT:
1418 pItem = m_pImpl->GetHOrient(true);
1419 break;
1420 case RES_VERT_ORIENT:
1421 pItem = m_pImpl->GetVOrient(true);
1422 break;
1423 case RES_LR_SPACE:
1424 pItem = m_pImpl->GetLRSpace(true);
1425 break;
1426 case RES_UL_SPACE:
1427 pItem = m_pImpl->GetULSpace(true);
1428 break;
1429 case RES_SURROUND:
1430 pItem = m_pImpl->GetSurround(true);
1431 break;
1432 case FN_TEXT_RANGE:
1433 if(auto tr = o3tl::tryAccess<
1434 uno::Reference<text::XTextRange>>(aValue))
1436 uno::Reference< text::XTextRange > & rRange = m_pImpl->GetTextRange();
1437 rRange = *tr;
1439 break;
1440 case RES_OPAQUE :
1441 m_pImpl->SetOpaque(*o3tl::doAccess<bool>(aValue));
1442 break;
1443 // #i26791#
1444 case RES_FOLLOW_TEXT_FLOW:
1446 pItem = m_pImpl->GetFollowTextFlow( true );
1448 break;
1449 // #i28701#
1450 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1452 pItem = m_pImpl->GetWrapInfluenceOnObjPos( true );
1454 break;
1455 // #i28749#
1456 case FN_SHAPE_POSITION_LAYOUT_DIR :
1458 sal_Int16 nPositionLayoutDir = 0;
1459 aValue >>= nPositionLayoutDir;
1460 m_pImpl->SetPositionLayoutDir( nPositionLayoutDir );
1462 break;
1464 if(pItem)
1465 pItem->PutValue(aValue, pEntry->nMemberId);
1468 else
1470 const uno::Type& rPSetType =
1471 cppu::UnoType<beans::XPropertySet>::get();
1472 uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
1473 auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
1474 aPSet);
1475 if(!xPrSet)
1476 throw uno::RuntimeException();
1477 // #i31698# - setting the caption point of a
1478 // caption object doesn't have to change the object position.
1479 // Thus, keep the position, before the caption point is set and
1480 // restore it afterwards.
1481 awt::Point aKeepedPosition( 0, 0 );
1482 if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
1484 aKeepedPosition = getPosition();
1486 if( pFormat && pFormat->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() )
1488 UnoActionContext aCtx(pFormat->GetDoc());
1489 (*xPrSet)->setPropertyValue(rPropertyName, aValue);
1491 else
1492 (*xPrSet)->setPropertyValue(rPropertyName, aValue);
1494 if (pFormat)
1496 // We have a pFormat (but no pEntry): try to sync TextBox property.
1497 SwTextBoxHelper::syncProperty(pFormat, rPropertyName, aValue,
1498 SdrObject::getSdrObjectFromXShape(mxShape));
1501 // #i31698# - restore object position, if caption point is set.
1502 if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
1504 setPosition( aKeepedPosition );
1509 uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
1511 SolarMutexGuard aGuard;
1512 uno::Any aRet;
1513 SwFrameFormat* pFormat = GetFrameFormat();
1514 if(m_xShapeAgg.is())
1516 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1517 if(pEntry)
1519 if(pFormat)
1521 if(RES_OPAQUE == pEntry->nWID)
1523 SvxShape* pSvxShape = GetSvxShape();
1524 OSL_ENSURE(pSvxShape, "No SvxShape found!");
1525 if(pSvxShape)
1527 SdrObject* pObj = pSvxShape->GetSdrObject();
1528 // consider invisible layers
1529 aRet <<=
1530 ( pObj->GetLayer() != pFormat->GetDoc()->getIDocumentDrawModelAccess().GetHellId() &&
1531 pObj->GetLayer() != pFormat->GetDoc()->getIDocumentDrawModelAccess().GetInvisibleHellId() );
1534 else if(FN_ANCHOR_POSITION == pEntry->nWID)
1536 SvxShape* pSvxShape = GetSvxShape();
1537 OSL_ENSURE(pSvxShape, "No SvxShape found!");
1538 if(pSvxShape)
1540 SdrObject* pObj = pSvxShape->GetSdrObject();
1541 Point aPt = pObj->GetAnchorPos();
1542 awt::Point aPoint( convertTwipToMm100( aPt.X() ),
1543 convertTwipToMm100( aPt.Y() ) );
1544 aRet <<= aPoint;
1547 // #i26791# - special handling for FN_TEXT_RANGE
1548 else if ( FN_TEXT_RANGE == pEntry->nWID )
1550 const SwFormatAnchor aAnchor = pFormat->GetAnchor();
1551 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1553 // return nothing, because property <TextRange> isn't
1554 // valid for to-page anchored shapes
1555 uno::Any aAny;
1556 aRet = aAny;
1558 else
1560 if ( aAnchor.GetAnchorNode() )
1562 const rtl::Reference<SwXTextRange> xTextRange
1563 = SwXTextRange::CreateXTextRange(
1564 *pFormat->GetDoc(),
1565 *aAnchor.GetContentAnchor(),
1566 nullptr );
1567 aRet <<= uno::Reference<text::XTextRange>(xTextRange);
1569 else
1571 // return nothing
1572 uno::Any aAny;
1573 aRet = aAny;
1577 else if (pEntry->nWID == FN_TEXT_BOX)
1579 if (pEntry->nMemberId == MID_TEXT_BOX)
1581 auto pSvxShape = GetSvxShape();
1582 bool bValue = SwTextBoxHelper::isTextBox(
1583 pFormat, RES_DRAWFRMFMT,
1584 ((pSvxShape && pSvxShape->GetSdrObject()) ? pSvxShape->GetSdrObject()
1585 : pFormat->FindRealSdrObject()));
1586 aRet <<= bValue;
1588 else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
1590 auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
1591 auto xRange = SwTextBoxHelper::queryInterface(
1592 pFormat, cppu::UnoType<text::XText>::get(),
1593 pObj ? pObj : pFormat->FindRealSdrObject());
1594 uno::Reference<text::XTextFrame> xFrame(xRange, uno::UNO_QUERY);
1595 if (xFrame.is())
1596 aRet <<= xFrame;
1599 else if (pEntry->nWID == RES_CHAIN)
1601 switch (pEntry->nMemberId)
1603 case MID_CHAIN_PREVNAME:
1604 case MID_CHAIN_NEXTNAME:
1605 case MID_CHAIN_NAME:
1606 SwTextBoxHelper::getProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aRet);
1607 break;
1610 // #i28749#
1611 else if ( FN_SHAPE_TRANSFORMATION_IN_HORI_L2R == pEntry->nWID )
1613 // get property <::drawing::Shape::Transformation>
1614 // without conversion to layout direction as below
1615 aRet = _getPropAtAggrObj( "Transformation" );
1617 else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
1619 aRet <<= pFormat->GetPositionLayoutDir();
1621 // #i36248#
1622 else if ( FN_SHAPE_STARTPOSITION_IN_HORI_L2R == pEntry->nWID )
1624 // get property <::drawing::Shape::StartPosition>
1625 // without conversion to layout direction as below
1626 aRet = _getPropAtAggrObj( "StartPosition" );
1628 else if ( FN_SHAPE_ENDPOSITION_IN_HORI_L2R == pEntry->nWID )
1630 // get property <::drawing::Shape::EndPosition>
1631 // without conversion to layout direction as below
1632 aRet = _getPropAtAggrObj( "EndPosition" );
1634 else if (pEntry->nWID == RES_FRM_SIZE &&
1635 (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT ||
1636 pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH ||
1637 pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
1638 pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
1640 SvxShape* pSvxShape = GetSvxShape();
1641 SAL_WARN_IF(!pSvxShape, "sw.uno", "No SvxShape found!");
1642 sal_Int16 nRet = 0;
1643 if (pSvxShape)
1645 SdrObject* pObj = pSvxShape->GetSdrObject();
1646 switch (pEntry->nMemberId)
1648 case MID_FRMSIZE_REL_WIDTH:
1649 if (pObj->GetRelativeWidth())
1650 nRet = *pObj->GetRelativeWidth() * 100;
1651 break;
1652 case MID_FRMSIZE_REL_HEIGHT:
1653 if (pObj->GetRelativeHeight())
1654 nRet = *pObj->GetRelativeHeight() * 100;
1655 break;
1656 case MID_FRMSIZE_REL_WIDTH_RELATION:
1657 nRet = pObj->GetRelativeWidthRelation();
1658 break;
1659 case MID_FRMSIZE_REL_HEIGHT_RELATION:
1660 nRet = pObj->GetRelativeHeightRelation();
1661 break;
1664 aRet <<= nRet;
1666 else
1668 const SwAttrSet& rSet = pFormat->GetAttrSet();
1669 m_pPropSet->getPropertyValue(*pEntry, rSet, aRet);
1672 else
1674 SfxPoolItem* pItem = nullptr;
1675 switch(pEntry->nWID)
1677 case RES_ANCHOR:
1678 pItem = m_pImpl->GetAnchor();
1679 break;
1680 case RES_HORI_ORIENT:
1681 pItem = m_pImpl->GetHOrient();
1682 break;
1683 case RES_VERT_ORIENT:
1684 pItem = m_pImpl->GetVOrient();
1685 break;
1686 case RES_LR_SPACE:
1687 pItem = m_pImpl->GetLRSpace();
1688 break;
1689 case RES_UL_SPACE:
1690 pItem = m_pImpl->GetULSpace();
1691 break;
1692 case RES_SURROUND:
1693 pItem = m_pImpl->GetSurround();
1694 break;
1695 case FN_TEXT_RANGE :
1696 aRet <<= m_pImpl->GetTextRange();
1697 break;
1698 case RES_OPAQUE :
1699 aRet <<= m_pImpl->GetOpaque();
1700 break;
1701 case FN_ANCHOR_POSITION :
1703 aRet <<= awt::Point();
1705 break;
1706 // #i26791#
1707 case RES_FOLLOW_TEXT_FLOW :
1709 pItem = m_pImpl->GetFollowTextFlow();
1711 break;
1712 // #i28701#
1713 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1715 pItem = m_pImpl->GetWrapInfluenceOnObjPos();
1717 break;
1718 // #i28749#
1719 case FN_SHAPE_TRANSFORMATION_IN_HORI_L2R:
1721 // get property <::drawing::Shape::Transformation>
1722 // without conversion to layout direction as below
1723 aRet = _getPropAtAggrObj( "Transformation" );
1725 break;
1726 case FN_SHAPE_POSITION_LAYOUT_DIR:
1728 aRet <<= m_pImpl->GetPositionLayoutDir();
1730 break;
1731 // #i36248#
1732 case FN_SHAPE_STARTPOSITION_IN_HORI_L2R:
1734 // get property <::drawing::Shape::StartPosition>
1735 // without conversion to layout direction as below
1736 aRet = _getPropAtAggrObj( "StartPosition" );
1738 break;
1739 case FN_SHAPE_ENDPOSITION_IN_HORI_L2R:
1741 // get property <::drawing::Shape::StartPosition>
1742 // without conversion to layout direction as below
1743 aRet = _getPropAtAggrObj( "EndPosition" );
1745 break;
1747 if(pItem)
1748 pItem->QueryValue(aRet, pEntry->nMemberId);
1751 else
1753 aRet = _getPropAtAggrObj( rPropertyName );
1755 // #i31698# - convert the position (translation)
1756 // of the drawing object in the transformation
1757 if ( rPropertyName == "Transformation" )
1759 drawing::HomogenMatrix3 aMatrix;
1760 aRet >>= aMatrix;
1761 aRet <<= ConvertTransformationToLayoutDir( aMatrix );
1763 // #i36248#
1764 else if ( rPropertyName == "StartPosition" )
1766 awt::Point aStartPos;
1767 aRet >>= aStartPos;
1768 // #i59051#
1769 aRet <<= ConvertStartOrEndPosToLayoutDir( aStartPos );
1771 else if ( rPropertyName == "EndPosition" )
1773 awt::Point aEndPos;
1774 aRet >>= aEndPos;
1775 // #i59051#
1776 aRet <<= ConvertStartOrEndPosToLayoutDir( aEndPos );
1778 // #i59051#
1779 else if ( rPropertyName == "PolyPolygonBezier" )
1781 drawing::PolyPolygonBezierCoords aPath;
1782 aRet >>= aPath;
1783 aRet <<= ConvertPolyPolygonBezierToLayoutDir( aPath );
1785 else if (rPropertyName == "ZOrder")
1787 // Convert the real draw page position to the logical one that ignores textboxes.
1788 if (pFormat)
1790 const SdrObject* pObj = pFormat->FindRealSdrObject();
1791 if (pObj)
1793 bool bConvert = true;
1794 if (SvxShape* pSvxShape = GetSvxShape())
1795 // In case of group shapes, pSvxShape points to the child shape, while pObj points to the outermost group shape.
1796 if (pSvxShape->GetSdrObject() != pObj)
1797 // Textboxes are not expected inside group shapes, so no conversion is necessary there.
1798 bConvert = false;
1799 if (bConvert)
1801 aRet <<= SwTextBoxHelper::getOrdNum(pObj);
1808 return aRet;
1811 uno::Any SwXShape::_getPropAtAggrObj( const OUString& _rPropertyName )
1813 uno::Any aRet;
1815 const uno::Type& rPSetType =
1816 cppu::UnoType<beans::XPropertySet>::get();
1817 uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
1818 auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(aPSet);
1819 if ( !xPrSet )
1821 throw uno::RuntimeException();
1823 aRet = (*xPrSet)->getPropertyValue( _rPropertyName );
1825 return aRet;
1828 beans::PropertyState SwXShape::getPropertyState( const OUString& rPropertyName )
1830 SolarMutexGuard aGuard;
1831 uno::Sequence< OUString > aNames { rPropertyName };
1832 uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
1833 return aStates.getConstArray()[0];
1836 uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
1837 const uno::Sequence< OUString >& aPropertyNames )
1839 SolarMutexGuard aGuard;
1840 SwFrameFormat* pFormat = GetFrameFormat();
1841 uno::Sequence< beans::PropertyState > aRet(aPropertyNames.getLength());
1842 if(!m_xShapeAgg.is())
1843 throw uno::RuntimeException();
1845 SvxShape* pSvxShape = GetSvxShape();
1846 bool bGroupMember = false;
1847 bool bFormControl = false;
1848 SdrObject* pObject = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
1849 if(pObject)
1851 bGroupMember = pObject->getParentSdrObjectFromSdrObject() != nullptr;
1852 bFormControl = pObject->GetObjInventor() == SdrInventor::FmForm;
1854 const OUString* pNames = aPropertyNames.getConstArray();
1855 beans::PropertyState* pRet = aRet.getArray();
1856 uno::Reference< XPropertyState > xShapePrState;
1857 for(sal_Int32 nProperty = 0; nProperty < aPropertyNames.getLength(); nProperty++)
1859 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( pNames[nProperty] );
1860 if(pEntry)
1862 if(RES_OPAQUE == pEntry->nWID)
1863 pRet[nProperty] = bFormControl ?
1864 beans::PropertyState_DEFAULT_VALUE : beans::PropertyState_DIRECT_VALUE;
1865 else if(FN_ANCHOR_POSITION == pEntry->nWID)
1866 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1867 else if(FN_TEXT_RANGE == pEntry->nWID)
1868 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1869 else if(bGroupMember)
1870 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1871 else if (pEntry->nWID == RES_FRM_SIZE &&
1872 (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
1873 pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
1874 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1875 else if (pEntry->nWID == FN_TEXT_BOX)
1877 // The TextBox property is set, if we can find a textbox for this shape.
1878 if (pFormat
1879 && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT,
1880 SdrObject::getSdrObjectFromXShape(mxShape)))
1881 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1882 else
1883 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1885 else if(pFormat)
1887 const SwAttrSet& rSet = pFormat->GetAttrSet();
1888 SfxItemState eItemState = rSet.GetItemState(pEntry->nWID, false);
1890 if(SfxItemState::SET == eItemState)
1891 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1892 else if(SfxItemState::DEFAULT == eItemState)
1893 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1894 else
1895 pRet[nProperty] = beans::PropertyState_AMBIGUOUS_VALUE;
1897 else
1899 SfxPoolItem* pItem = nullptr;
1900 switch(pEntry->nWID)
1902 case RES_ANCHOR:
1903 pItem = m_pImpl->GetAnchor();
1904 break;
1905 case RES_HORI_ORIENT:
1906 pItem = m_pImpl->GetHOrient();
1907 break;
1908 case RES_VERT_ORIENT:
1909 pItem = m_pImpl->GetVOrient();
1910 break;
1911 case RES_LR_SPACE:
1912 pItem = m_pImpl->GetLRSpace();
1913 break;
1914 case RES_UL_SPACE:
1915 pItem = m_pImpl->GetULSpace();
1916 break;
1917 case RES_SURROUND:
1918 pItem = m_pImpl->GetSurround();
1919 break;
1920 // #i28701#
1921 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1923 pItem = m_pImpl->GetWrapInfluenceOnObjPos();
1925 break;
1927 if(pItem)
1928 pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
1929 else
1930 pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
1933 else
1935 if(!xShapePrState.is())
1937 const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
1938 uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
1939 auto ps = o3tl::tryAccess<uno::Reference<XPropertyState>>(
1940 aPState);
1941 if(!ps)
1942 throw uno::RuntimeException();
1943 xShapePrState = *ps;
1945 pRet[nProperty] = xShapePrState->getPropertyState(pNames[nProperty]);
1949 return aRet;
1952 void SwXShape::setPropertyToDefault( const OUString& rPropertyName )
1954 SolarMutexGuard aGuard;
1955 SwFrameFormat* pFormat = GetFrameFormat();
1956 if(!m_xShapeAgg.is())
1957 throw uno::RuntimeException();
1959 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1960 if(pEntry)
1962 if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
1963 throw uno::RuntimeException("Property is read-only: " + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
1964 if(pFormat)
1966 const SfxItemSet& rSet = pFormat->GetAttrSet();
1967 SfxItemSet aSet(pFormat->GetDoc()->GetAttrPool(), pEntry->nWID, pEntry->nWID);
1968 aSet.SetParent(&rSet);
1969 aSet.ClearItem(pEntry->nWID);
1970 pFormat->GetDoc()->SetAttr(aSet, *pFormat);
1972 else
1974 switch(pEntry->nWID)
1976 case RES_ANCHOR: m_pImpl->RemoveAnchor(); break;
1977 case RES_HORI_ORIENT: m_pImpl->RemoveHOrient(); break;
1978 case RES_VERT_ORIENT: m_pImpl->RemoveVOrient(); break;
1979 case RES_LR_SPACE: m_pImpl->RemoveLRSpace(); break;
1980 case RES_UL_SPACE: m_pImpl->RemoveULSpace(); break;
1981 case RES_SURROUND: m_pImpl->RemoveSurround();break;
1982 case RES_OPAQUE : m_pImpl->SetOpaque(false); break;
1983 case FN_TEXT_RANGE :
1984 break;
1985 // #i26791#
1986 case RES_FOLLOW_TEXT_FLOW:
1988 m_pImpl->RemoveFollowTextFlow();
1990 break;
1991 // #i28701#
1992 case RES_WRAP_INFLUENCE_ON_OBJPOS:
1994 m_pImpl->RemoveWrapInfluenceOnObjPos();
1996 break;
2000 else
2002 const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
2003 uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
2004 auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
2005 aPState);
2006 if(!xShapePrState)
2007 throw uno::RuntimeException();
2008 (*xShapePrState)->setPropertyToDefault( rPropertyName );
2013 uno::Any SwXShape::getPropertyDefault( const OUString& rPropertyName )
2015 SolarMutexGuard aGuard;
2016 SwFrameFormat* pFormat = GetFrameFormat();
2017 uno::Any aRet;
2018 if(!m_xShapeAgg.is())
2019 throw uno::RuntimeException();
2021 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
2022 if(pEntry)
2024 if(!(pEntry->nWID < RES_FRMATR_END && pFormat))
2025 throw uno::RuntimeException();
2027 const SfxPoolItem& rDefItem =
2028 pFormat->GetDoc()->GetAttrPool().GetDefaultItem(pEntry->nWID);
2029 rDefItem.QueryValue(aRet, pEntry->nMemberId);
2032 else
2034 const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
2035 uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
2036 auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
2037 aPState);
2038 if(!xShapePrState)
2039 throw uno::RuntimeException();
2040 (*xShapePrState)->getPropertyDefault( rPropertyName );
2043 return aRet;
2046 void SwXShape::addPropertyChangeListener(
2047 const OUString& _propertyName,
2048 const uno::Reference< beans::XPropertyChangeListener > & _listener )
2050 if ( !m_xShapeAgg.is() )
2051 throw uno::RuntimeException("no shape aggregate", *this );
2053 // must be handled by the aggregate
2054 uno::Reference< beans::XPropertySet > xShapeProps;
2055 if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
2056 xShapeProps->addPropertyChangeListener( _propertyName, _listener );
2059 void SwXShape::removePropertyChangeListener(
2060 const OUString& _propertyName,
2061 const uno::Reference< beans::XPropertyChangeListener > & _listener)
2063 if ( !m_xShapeAgg.is() )
2064 throw uno::RuntimeException("no shape aggregate", *this );
2066 // must be handled by the aggregate
2067 uno::Reference< beans::XPropertySet > xShapeProps;
2068 if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
2069 xShapeProps->removePropertyChangeListener( _propertyName, _listener );
2072 void SwXShape::addVetoableChangeListener(
2073 const OUString& /*PropertyName*/,
2074 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/ )
2076 OSL_FAIL("not implemented");
2079 void SwXShape::removeVetoableChangeListener(
2080 const OUString& /*PropertyName*/,
2081 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
2083 OSL_FAIL("not implemented");
2086 void SwXShape::attach(const uno::Reference< text::XTextRange > & xTextRange)
2088 SolarMutexGuard aGuard;
2090 // get access to SwDoc
2091 // (see also SwXTextRange::XTextRangeToSwPaM)
2092 const SwDoc* pDoc = nullptr;
2093 if (auto pRange = dynamic_cast<SwXTextRange*>(xTextRange.get()))
2094 pDoc = &pRange->GetDoc();
2095 else if (auto pText = dynamic_cast<SwXText*>(xTextRange.get()))
2096 pDoc = pText->GetDoc();
2097 else if (auto pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get()))
2098 pDoc = pCursor->GetDoc();
2099 else if (auto pPortion = dynamic_cast<SwXTextPortion*>(xTextRange.get()))
2100 pDoc = &pPortion->GetCursor().GetDoc();
2101 else if (auto pParagraph = dynamic_cast<SwXParagraph*>(xTextRange.get());
2102 pParagraph && pParagraph->GetTextNode())
2103 pDoc = &pParagraph->GetTextNode()->GetDoc();
2105 if(!pDoc)
2106 throw uno::RuntimeException();
2107 const SwDocShell* pDocSh = pDoc->GetDocShell();
2108 if (!pDocSh)
2109 return;
2111 uno::Reference<frame::XModel> xModel = pDocSh->GetModel();
2112 uno::Reference< drawing::XDrawPageSupplier > xDPS(xModel, uno::UNO_QUERY);
2113 if (xDPS.is())
2115 uno::Reference< drawing::XDrawPage > xDP( xDPS->getDrawPage() );
2116 if (xDP.is())
2118 uno::Any aPos;
2119 aPos <<= xTextRange;
2120 setPropertyValue("TextRange", aPos);
2121 uno::Reference< drawing::XShape > xTemp( static_cast<cppu::OWeakObject*>(this), uno::UNO_QUERY );
2122 xDP->add( xTemp );
2127 uno::Reference< text::XTextRange > SwXShape::getAnchor()
2129 SolarMutexGuard aGuard;
2130 uno::Reference< text::XTextRange > aRef;
2131 SwFrameFormat* pFormat = GetFrameFormat();
2132 if(pFormat)
2134 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
2135 // return an anchor for non-page bound frames
2136 // and for page bound frames that have a page no == NULL and a content position
2137 if ((rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) ||
2138 (rAnchor.GetAnchorNode() && !rAnchor.GetPageNum()))
2140 if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA)
2141 { // ensure that SwXTextRange has SwContentIndex
2142 const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
2143 aRef = SwXTextRange::CreateXTextRange(*pFormat->GetDoc(), SwPosition(*pAnchorNode), nullptr);
2145 else
2147 aRef = SwXTextRange::CreateXTextRange(*pFormat->GetDoc(), *rAnchor.GetContentAnchor(), nullptr);
2151 else
2152 aRef = m_pImpl->GetTextRange().get();
2153 return aRef;
2156 void SwXShape::dispose()
2158 SolarMutexGuard aGuard;
2159 SwFrameFormat* pFormat = GetFrameFormat();
2160 if(pFormat)
2162 // determine correct <SdrObject>
2163 SvxShape* pSvxShape = GetSvxShape();
2164 SdrObject* pObj = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
2165 // safety assertion:
2166 // <pObj> must be the same as <pFormat->FindSdrObject()>, if <pObj> isn't
2167 // a 'virtual' drawing object.
2168 // correct assertion and refine it for safety reason.
2169 OSL_ENSURE( !pObj ||
2170 dynamic_cast<const SwDrawVirtObj*>( pObj) != nullptr ||
2171 pObj->getParentSdrObjectFromSdrObject() ||
2172 pObj == pFormat->FindSdrObject(),
2173 "<SwXShape::dispose(..) - different 'master' drawing objects!!" );
2174 // perform delete of draw frame format *not*
2175 // for 'virtual' drawing objects.
2176 // no delete of draw format for members
2177 // of a group
2178 if ( pObj &&
2179 dynamic_cast<const SwDrawVirtObj*>( pObj) == nullptr &&
2180 !pObj->getParentSdrObjectFromSdrObject() &&
2181 pObj->IsInserted() )
2183 const SwFormatAnchor& rFormatAnchor = pFormat->GetAnchor();
2184 if (rFormatAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
2186 SwTextNode *pTextNode = rFormatAnchor.GetAnchorNode()->GetTextNode();
2187 const sal_Int32 nIdx = rFormatAnchor.GetAnchorContentOffset();
2188 pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
2190 else
2191 pFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pFormat );
2194 if(m_xShapeAgg.is())
2196 uno::Any aAgg(m_xShapeAgg->queryAggregation( cppu::UnoType<XComponent>::get()));
2197 uno::Reference<XComponent> xComp;
2198 aAgg >>= xComp;
2199 if(xComp.is())
2200 xComp->dispose();
2202 if(m_pPage)
2204 auto pPage = const_cast<SwFmDrawPage*>(m_pPage);
2205 m_pPage = nullptr;
2206 pPage->RemoveShape(this);
2210 void SwXShape::addEventListener(
2211 const uno::Reference< lang::XEventListener > & aListener)
2213 SvxShape* pSvxShape = GetSvxShape();
2214 if(pSvxShape)
2215 pSvxShape->addEventListener(aListener);
2218 void SwXShape::removeEventListener(
2219 const uno::Reference< lang::XEventListener > & aListener)
2221 SvxShape* pSvxShape = GetSvxShape();
2222 if(pSvxShape)
2223 pSvxShape->removeEventListener(aListener);
2226 OUString SwXShape::getImplementationName()
2228 return "SwXShape";
2231 sal_Bool SwXShape::supportsService(const OUString& rServiceName)
2233 return cppu::supportsService(this, rServiceName);
2236 uno::Sequence< OUString > SwXShape::getSupportedServiceNames()
2238 uno::Sequence< OUString > aSeq;
2239 if (SvxShape* pSvxShape = GetSvxShape())
2240 aSeq = pSvxShape->getSupportedServiceNames();
2241 return comphelper::concatSequences(
2242 aSeq, std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape" });
2245 SvxShape* SwXShape::GetSvxShape()
2247 if(m_xShapeAgg.is())
2248 return comphelper::getFromUnoTunnel<SvxShape>(m_xShapeAgg);
2249 return nullptr;
2252 // #i31698#
2253 // implementation of virtual methods from drawing::XShape
2254 awt::Point SAL_CALL SwXShape::getPosition()
2256 awt::Point aPos( GetAttrPosition() );
2258 // handle group members
2259 SvxShape* pSvxShape = GetSvxShape();
2260 if ( pSvxShape )
2262 SdrObject* pTopGroupObj = GetTopGroupObj( pSvxShape );
2263 if ( pTopGroupObj )
2265 // #i34750# - get attribute position of top group
2266 // shape and add offset between top group object and group member
2267 uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
2268 aPos = xGroupShape->getPosition();
2269 // add offset between top group object and group member
2270 // to the determined attribute position
2271 // #i34750#:
2272 // consider the layout direction
2273 const tools::Rectangle aMemberObjRect = GetSvxShape()->GetSdrObject()->GetSnapRect();
2274 const tools::Rectangle aGroupObjRect = pTopGroupObj->GetSnapRect();
2275 // #i53320# - relative position of group member and
2276 // top group object is always given in horizontal left-to-right layout.
2277 awt::Point aOffset( 0, 0 );
2279 aOffset.X = ( aMemberObjRect.Left() - aGroupObjRect.Left() );
2280 aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
2282 aOffset.X = convertTwipToMm100(aOffset.X);
2283 aOffset.Y = convertTwipToMm100(aOffset.Y);
2284 aPos.X += aOffset.X;
2285 aPos.Y += aOffset.Y;
2289 return aPos;
2292 void SAL_CALL SwXShape::setPosition( const awt::Point& aPosition )
2294 SdrObject* pTopGroupObj = GetTopGroupObj();
2295 if ( !pTopGroupObj )
2297 // #i37877# - no adjustment of position attributes,
2298 // if the position also has to be applied at the drawing object and
2299 // a contact object is already registered at the drawing object.
2300 bool bApplyPosAtDrawObj(false);
2301 bool bNoAdjustOfPosProp(false);
2302 // #i35798# - apply position also to drawing object,
2303 // if drawing object has no anchor position set.
2304 if ( mxShape.is() )
2306 SvxShape* pSvxShape = GetSvxShape();
2307 if ( pSvxShape )
2309 const SdrObject* pObj = pSvxShape->GetSdrObject();
2310 if ( pObj &&
2311 pObj->GetAnchorPos().X() == 0 &&
2312 pObj->GetAnchorPos().Y() == 0 )
2314 bApplyPosAtDrawObj = true;
2315 if ( pObj->GetUserCall() &&
2316 dynamic_cast<const SwDrawContact*>( pObj->GetUserCall()) != nullptr )
2318 bNoAdjustOfPosProp = true;
2323 // shape isn't a group member. Thus, set positioning attributes
2324 if ( !bNoAdjustOfPosProp )
2326 AdjustPositionProperties( aPosition );
2328 if ( bApplyPosAtDrawObj )
2330 mxShape->setPosition( aPosition );
2333 else if ( mxShape.is() )
2335 // shape is a member of a group. Thus, set its position.
2336 awt::Point aNewPos( aPosition );
2337 // The given position is given in the according layout direction. Thus,
2338 // it has to be converted to a position in horizontal left-to-right
2339 // layout.
2340 // convert given absolute attribute position in layout direction into
2341 // position in horizontal left-to-right layout.
2343 aNewPos = ConvertPositionToHoriL2R( aNewPos, getSize() );
2345 // Convert given absolute position in horizontal left-to-right
2346 // layout into relative position in horizontal left-to-right layout.
2347 uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
2349 // #i34750#
2350 // use method <xGroupShape->getPosition()> to get the correct
2351 // position of the top group object.
2352 awt::Point aAttrPosInHoriL2R(
2353 ConvertPositionToHoriL2R( xGroupShape->getPosition(),
2354 xGroupShape->getSize() ) );
2355 aNewPos.X = o3tl::saturating_sub(aNewPos.X, aAttrPosInHoriL2R.X);
2356 aNewPos.Y = o3tl::saturating_sub(aNewPos.Y, aAttrPosInHoriL2R.Y);
2358 // convert relative position in horizontal left-to-right layout into
2359 // absolute position in horizontal left-to-right layout
2361 // #i34750#
2362 // use method <SvxShape->getPosition()> to get the correct
2363 // 'Drawing layer' position of the top group shape.
2364 auto pSvxGroupShape = comphelper::getFromUnoTunnel<SvxShape>(pTopGroupObj->getUnoShape());
2365 const awt::Point aGroupPos = pSvxGroupShape->getPosition();
2366 aNewPos.X = o3tl::saturating_add(aNewPos.X, aGroupPos.X);
2367 aNewPos.Y = o3tl::saturating_add(aNewPos.Y, aGroupPos.Y);
2369 // set position
2370 mxShape->setPosition( aNewPos );
2374 awt::Size SAL_CALL SwXShape::getSize()
2376 awt::Size aSize;
2377 if ( mxShape.is() )
2379 aSize = mxShape->getSize();
2381 return aSize;
2384 void SAL_CALL SwXShape::setSize( const awt::Size& aSize )
2386 comphelper::ProfileZone aZone("SwXShape::setSize");
2388 if ( mxShape.is() )
2390 mxShape->setSize( aSize );
2392 SwTextBoxHelper::syncProperty(GetFrameFormat(), RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any(aSize));
2394 // #i31698#
2395 // implementation of virtual methods from drawing::XShapeDescriptor
2396 OUString SAL_CALL SwXShape::getShapeType()
2398 if ( mxShape.is() )
2400 return mxShape->getShapeType();
2402 return OUString();
2404 /** method to determine top group object
2405 #i31698#
2407 SdrObject* SwXShape::GetTopGroupObj( SvxShape* _pSvxShape )
2409 SdrObject* pTopGroupObj( nullptr );
2411 SvxShape* pSvxShape = _pSvxShape ? _pSvxShape : GetSvxShape();
2412 if ( pSvxShape )
2414 SdrObject* pSdrObj = pSvxShape->GetSdrObject();
2415 if ( pSdrObj && pSdrObj->getParentSdrObjectFromSdrObject() )
2417 pTopGroupObj = pSdrObj->getParentSdrObjectFromSdrObject();
2418 while ( pTopGroupObj->getParentSdrObjectFromSdrObject() )
2420 pTopGroupObj = pTopGroupObj->getParentSdrObjectFromSdrObject();
2425 return pTopGroupObj;
2428 /** method to determine position according to the positioning attributes
2429 #i31698#
2431 awt::Point SwXShape::GetAttrPosition()
2433 awt::Point aAttrPos;
2435 uno::Any aHoriPos( getPropertyValue("HoriOrientPosition") );
2436 aHoriPos >>= aAttrPos.X;
2437 uno::Any aVertPos( getPropertyValue("VertOrientPosition") );
2438 aVertPos >>= aAttrPos.Y;
2439 // #i35798# - fallback, if attribute position is (0,0)
2440 // and no anchor position is applied to the drawing object
2441 SvxShape* pSvxShape = GetSvxShape();
2442 if ( pSvxShape )
2444 const SdrObject* pObj = pSvxShape->GetSdrObject();
2445 if ( pObj &&
2446 pObj->GetAnchorPos().X() == 0 &&
2447 pObj->GetAnchorPos().Y() == 0 &&
2448 aAttrPos.X == 0 && aAttrPos.Y == 0 )
2450 const tools::Rectangle aObjRect = pObj->GetSnapRect();
2451 aAttrPos.X = convertTwipToMm100(aObjRect.Left());
2452 aAttrPos.Y = convertTwipToMm100(aObjRect.Top());
2455 // #i35007# - If drawing object is anchored as-character,
2456 // it's x-position isn't sensible. Thus, return the x-position as zero in this case.
2457 text::TextContentAnchorType eTextAnchorType =
2458 text::TextContentAnchorType_AT_PARAGRAPH;
2460 uno::Any aAny = getPropertyValue( "AnchorType" );
2461 aAny >>= eTextAnchorType;
2463 if ( eTextAnchorType == text::TextContentAnchorType_AS_CHARACTER )
2465 aAttrPos.X = 0;
2468 return aAttrPos;
2471 /** method to convert the position (translation) of the drawing object to
2472 the layout direction horizontal left-to-right.
2473 #i31698#
2475 awt::Point SwXShape::ConvertPositionToHoriL2R( const awt::Point& rObjPos,
2476 const awt::Size& rObjSize )
2478 awt::Point aObjPosInHoriL2R( rObjPos );
2480 SwFrameFormat* pFrameFormat = GetFrameFormat();
2481 if ( pFrameFormat )
2483 SwFrameFormat::tLayoutDir eLayoutDir = pFrameFormat->GetLayoutDir();
2484 switch ( eLayoutDir )
2486 case SwFrameFormat::HORI_L2R:
2488 // nothing to do
2490 break;
2491 case SwFrameFormat::HORI_R2L:
2493 aObjPosInHoriL2R.X = -rObjPos.X - rObjSize.Width;
2495 break;
2496 case SwFrameFormat::VERT_R2L:
2498 aObjPosInHoriL2R.X = -rObjPos.Y - rObjSize.Width;
2499 aObjPosInHoriL2R.Y = rObjPos.X;
2501 break;
2502 default:
2504 OSL_FAIL( "<SwXShape::ConvertPositionToHoriL2R(..)> - unsupported layout direction" );
2509 return aObjPosInHoriL2R;
2512 /** method to convert the transformation of the drawing object to the layout
2513 direction, the drawing object is in
2514 #i31698#
2516 drawing::HomogenMatrix3 SwXShape::ConvertTransformationToLayoutDir(
2517 const drawing::HomogenMatrix3& rMatrixInHoriL2R )
2519 drawing::HomogenMatrix3 aMatrix(rMatrixInHoriL2R);
2521 // #i44334#, #i44681# - direct manipulation of the
2522 // transformation structure isn't valid, if it contains rotation.
2523 SvxShape* pSvxShape = GetSvxShape();
2524 OSL_ENSURE( pSvxShape,
2525 "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SvxShape found!");
2526 if ( pSvxShape )
2528 const SdrObject* pObj = pSvxShape->GetSdrObject();
2529 OSL_ENSURE( pObj,
2530 "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SdrObject found!");
2531 if ( pObj )
2533 // get position of object in Writer coordinate system.
2534 awt::Point aPos( getPosition() );
2535 // get position of object in Drawing layer coordinate system
2536 const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
2537 const awt::Point aObjPos(
2538 convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
2539 convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
2540 // determine difference between these positions according to the
2541 // Writer coordinate system
2542 const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
2543 aPos.Y - aObjPos.Y );
2544 // apply translation difference to transformation matrix.
2545 if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
2547 // #i73079# - use correct matrix type
2548 ::basegfx::B2DHomMatrix aTempMatrix;
2550 aTempMatrix.set(0, 0, aMatrix.Line1.Column1 );
2551 aTempMatrix.set(0, 1, aMatrix.Line1.Column2 );
2552 aTempMatrix.set(0, 2, aMatrix.Line1.Column3 );
2553 aTempMatrix.set(1, 0, aMatrix.Line2.Column1 );
2554 aTempMatrix.set(1, 1, aMatrix.Line2.Column2 );
2555 aTempMatrix.set(1, 2, aMatrix.Line2.Column3 );
2556 // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
2557 assert( aMatrix.Line3.Column1 == 0 );
2558 assert( aMatrix.Line3.Column2 == 0 );
2559 assert( aMatrix.Line3.Column3 == 1 );
2560 // #i73079#
2561 aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y );
2562 aMatrix.Line1.Column1 = aTempMatrix.get(0, 0);
2563 aMatrix.Line1.Column2 = aTempMatrix.get(0, 1);
2564 aMatrix.Line1.Column3 = aTempMatrix.get(0, 2);
2565 aMatrix.Line2.Column1 = aTempMatrix.get(1, 0);
2566 aMatrix.Line2.Column2 = aTempMatrix.get(1, 1);
2567 aMatrix.Line2.Column3 = aTempMatrix.get(1, 2);
2568 aMatrix.Line3.Column1 = 0;
2569 aMatrix.Line3.Column2 = 0;
2570 aMatrix.Line3.Column3 = 1;
2575 return aMatrix;
2578 /** method to adjust the positioning properties
2579 #i31698#
2581 void SwXShape::AdjustPositionProperties( const awt::Point& rPosition )
2583 // handle x-position
2584 // #i35007# - no handling of x-position, if drawing
2585 // object is anchored as-character, because it doesn't make sense.
2586 text::TextContentAnchorType eTextAnchorType =
2587 text::TextContentAnchorType_AT_PARAGRAPH;
2589 uno::Any aAny = getPropertyValue( "AnchorType" );
2590 aAny >>= eTextAnchorType;
2592 if ( eTextAnchorType != text::TextContentAnchorType_AS_CHARACTER )
2594 // determine current x-position
2595 static const OUStringLiteral aHoriPosPropStr(u"HoriOrientPosition");
2596 uno::Any aHoriPos( getPropertyValue( aHoriPosPropStr ) );
2597 sal_Int32 dCurrX = 0;
2598 aHoriPos >>= dCurrX;
2599 // change x-position attribute, if needed
2600 if ( dCurrX != rPosition.X )
2602 // adjust x-position orientation to text::HoriOrientation::NONE, if needed
2603 // Note: has to be done before setting x-position attribute
2604 static const OUStringLiteral aHoriOrientPropStr(u"HoriOrient");
2605 uno::Any aHoriOrient( getPropertyValue( aHoriOrientPropStr ) );
2606 sal_Int16 eHoriOrient;
2607 if (aHoriOrient >>= eHoriOrient) // may be void
2609 if ( eHoriOrient != text::HoriOrientation::NONE )
2611 eHoriOrient = text::HoriOrientation::NONE;
2612 aHoriOrient <<= eHoriOrient;
2613 setPropertyValue( aHoriOrientPropStr, aHoriOrient );
2616 // set x-position attribute
2617 aHoriPos <<= rPosition.X;
2618 setPropertyValue( aHoriPosPropStr, aHoriPos );
2622 // handle y-position
2624 // determine current y-position
2625 static const OUStringLiteral aVertPosPropStr(u"VertOrientPosition");
2626 uno::Any aVertPos( getPropertyValue( aVertPosPropStr ) );
2627 sal_Int32 dCurrY = 0;
2628 aVertPos >>= dCurrY;
2629 // change y-position attribute, if needed
2630 if ( dCurrY != rPosition.Y )
2632 // adjust y-position orientation to text::VertOrientation::NONE, if needed
2633 // Note: has to be done before setting y-position attribute
2634 static const OUStringLiteral aVertOrientPropStr(u"VertOrient");
2635 uno::Any aVertOrient( getPropertyValue( aVertOrientPropStr ) );
2636 sal_Int16 eVertOrient;
2637 if (aVertOrient >>= eVertOrient) // may be void
2639 if ( eVertOrient != text::VertOrientation::NONE )
2641 eVertOrient = text::VertOrientation::NONE;
2642 aVertOrient <<= eVertOrient;
2643 setPropertyValue( aVertOrientPropStr, aVertOrient );
2646 // set y-position attribute
2647 aVertPos <<= rPosition.Y;
2648 setPropertyValue( aVertPosPropStr, aVertPos );
2653 /** method to convert start or end position of the drawing object to the
2654 Writer specific position, which is the attribute position in layout direction
2655 #i59051#
2657 css::awt::Point SwXShape::ConvertStartOrEndPosToLayoutDir(
2658 const css::awt::Point& aStartOrEndPos )
2660 awt::Point aConvertedPos( aStartOrEndPos );
2662 SvxShape* pSvxShape = GetSvxShape();
2663 OSL_ENSURE( pSvxShape,
2664 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
2665 if ( pSvxShape )
2667 const SdrObject* pObj = pSvxShape->GetSdrObject();
2668 OSL_ENSURE( pObj,
2669 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
2670 if ( pObj )
2672 // get position of object in Writer coordinate system.
2673 awt::Point aPos( getPosition() );
2674 // get position of object in Drawing layer coordinate system
2675 const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
2676 const awt::Point aObjPos(
2677 convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
2678 convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
2679 // determine difference between these positions according to the
2680 // Writer coordinate system
2681 const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
2682 aPos.Y - aObjPos.Y );
2683 // apply translation difference to transformation matrix.
2684 if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
2686 aConvertedPos.X = aConvertedPos.X + aTranslateDiff.X;
2687 aConvertedPos.Y = aConvertedPos.Y + aTranslateDiff.Y;
2692 return aConvertedPos;
2695 css::drawing::PolyPolygonBezierCoords SwXShape::ConvertPolyPolygonBezierToLayoutDir(
2696 const css::drawing::PolyPolygonBezierCoords& aPath )
2698 drawing::PolyPolygonBezierCoords aConvertedPath( aPath );
2700 SvxShape* pSvxShape = GetSvxShape();
2701 OSL_ENSURE( pSvxShape,
2702 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
2703 if ( pSvxShape )
2705 const SdrObject* pObj = pSvxShape->GetSdrObject();
2706 OSL_ENSURE( pObj,
2707 "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
2708 if ( pObj )
2710 // get position of object in Writer coordinate system.
2711 awt::Point aPos( getPosition() );
2712 // get position of object in Drawing layer coordinate system
2713 const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
2714 const awt::Point aObjPos(
2715 convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
2716 convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
2717 // determine difference between these positions according to the
2718 // Writer coordinate system
2719 const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
2720 aPos.Y - aObjPos.Y );
2721 // apply translation difference to PolyPolygonBezier.
2722 if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
2724 const basegfx::B2DHomMatrix aMatrix(basegfx::utils::createTranslateB2DHomMatrix(
2725 aTranslateDiff.X, aTranslateDiff.Y));
2727 for(drawing::PointSequence& rInnerSequence : asNonConstRange(aConvertedPath.Coordinates))
2729 for(awt::Point& rPoint : asNonConstRange(rInnerSequence))
2731 basegfx::B2DPoint aNewCoordinatePair(rPoint.X, rPoint.Y);
2732 aNewCoordinatePair *= aMatrix;
2733 rPoint.X = basegfx::fround(aNewCoordinatePair.getX());
2734 rPoint.Y = basegfx::fround(aNewCoordinatePair.getY());
2741 return aConvertedPath;
2744 SwXGroupShape::SwXGroupShape(uno::Reference<XInterface> & xShape,
2745 SwDoc const*const pDoc)
2746 : SwXShape(xShape, pDoc)
2748 #if OSL_DEBUG_LEVEL > 0
2749 uno::Reference<XShapes> xShapes(m_xShapeAgg, uno::UNO_QUERY);
2750 OSL_ENSURE(xShapes.is(), "no SvxShape found or shape is not a group shape");
2751 #endif
2754 SwXGroupShape::~SwXGroupShape()
2758 uno::Any SwXGroupShape::queryInterface( const uno::Type& rType )
2760 uno::Any aRet;
2761 if(rType == cppu::UnoType<XShapes>::get())
2762 aRet <<= uno::Reference<XShapes>(this);
2763 else
2764 aRet = SwXShape::queryInterface(rType);
2765 return aRet;
2768 void SwXGroupShape::acquire( ) noexcept
2770 SwXShape::acquire();
2773 void SwXGroupShape::release( ) noexcept
2775 SwXShape::release();
2778 void SwXGroupShape::add( const uno::Reference< XShape >& xShape )
2780 SolarMutexGuard aGuard;
2781 SvxShape* pSvxShape = GetSvxShape();
2782 SwFrameFormat* pFormat = GetFrameFormat();
2783 if(!(pSvxShape && pFormat))
2784 throw uno::RuntimeException();
2786 uno::Reference<XShapes> xShapes;
2787 if( m_xShapeAgg.is() )
2789 const uno::Type& rType = cppu::UnoType<XShapes>::get();
2790 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2791 aAgg >>= xShapes;
2793 if(!xShapes.is())
2794 throw uno::RuntimeException();
2796 xShapes->add(xShape);
2799 uno::Reference<lang::XUnoTunnel> xTunnel(xShape, uno::UNO_QUERY);
2800 SwXShape* pSwShape = comphelper::getFromUnoTunnel<SwXShape>(xTunnel);
2801 if(!(pSwShape && pSwShape->m_bDescriptor))
2802 return;
2804 SvxShape* pAddShape = comphelper::getFromUnoTunnel<SvxShape>(xTunnel);
2805 if(pAddShape)
2807 SdrObject* pObj = pAddShape->GetSdrObject();
2808 if(pObj)
2810 SwDoc* pDoc = pFormat->GetDoc();
2811 // set layer of new drawing
2812 // object to corresponding invisible layer.
2813 if( SdrInventor::FmForm != pObj->GetObjInventor())
2815 pObj->SetLayer( pSwShape->m_pImpl->GetOpaque()
2816 ? pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId()
2817 : pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
2819 else
2821 pObj->SetLayer(pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());
2825 pSwShape->m_bDescriptor = false;
2828 void SwXGroupShape::remove( const uno::Reference< XShape >& xShape )
2830 SolarMutexGuard aGuard;
2831 uno::Reference<XShapes> xShapes;
2832 if( m_xShapeAgg.is() )
2834 const uno::Type& rType = cppu::UnoType<XShapes>::get();
2835 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2836 aAgg >>= xShapes;
2838 if(!xShapes.is())
2839 throw uno::RuntimeException();
2840 xShapes->remove(xShape);
2843 sal_Int32 SwXGroupShape::getCount()
2845 SolarMutexGuard aGuard;
2846 uno::Reference<XIndexAccess> xAcc;
2847 if( m_xShapeAgg.is() )
2849 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2850 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2851 aAgg >>= xAcc;
2853 if(!xAcc.is())
2854 throw uno::RuntimeException();
2855 return xAcc->getCount();
2858 uno::Any SwXGroupShape::getByIndex(sal_Int32 nIndex)
2860 SolarMutexGuard aGuard;
2861 uno::Reference<XIndexAccess> xAcc;
2862 if( m_xShapeAgg.is() )
2864 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2865 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2866 aAgg >>= xAcc;
2868 if(!xAcc.is())
2869 throw uno::RuntimeException();
2870 return xAcc->getByIndex(nIndex);
2873 uno::Type SwXGroupShape::getElementType( )
2875 SolarMutexGuard aGuard;
2876 uno::Reference<XIndexAccess> xAcc;
2877 if( m_xShapeAgg.is() )
2879 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2880 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2881 aAgg >>= xAcc;
2883 if(!xAcc.is())
2884 throw uno::RuntimeException();
2885 return xAcc->getElementType();
2888 sal_Bool SwXGroupShape::hasElements( )
2890 SolarMutexGuard aGuard;
2891 uno::Reference<XIndexAccess> xAcc;
2892 if( m_xShapeAgg.is() )
2894 const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
2895 uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
2896 aAgg >>= xAcc;
2898 if(!xAcc.is())
2899 throw uno::RuntimeException();
2900 return xAcc->hasElements();
2903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */