1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <hintids.hxx>
22 #include <svx/svdpage.hxx>
23 #include <svx/svditer.hxx>
24 #include <svx/svdogrp.hxx>
25 #include <svx/svdotext.hxx>
26 #include <svx/svdmodel.hxx>
27 #include <svx/svdviter.hxx>
28 #include <svx/svdview.hxx>
29 #include <svx/sdr/contact/displayinfo.hxx>
30 #include <svx/sdr/contact/objectcontact.hxx>
31 #include <svx/shapepropertynotifier.hxx>
32 #include <drawdoc.hxx>
33 #include <fmtornt.hxx>
34 #include <viewimp.hxx>
35 #include <fmtsrnd.hxx>
36 #include <fmtanchr.hxx>
38 #include <fmtcntnt.hxx>
39 #include <fmtfsize.hxx>
41 #include <pagefrm.hxx>
42 #include <rootfrm.hxx>
43 #include <frmtool.hxx>
45 #include <textboxhelper.hxx>
47 #include <fmtfollowtextflow.hxx>
48 #include <dflyobj.hxx>
49 #include <dcontact.hxx>
50 #include <unodraw.hxx>
51 #include <IDocumentDrawModelAccess.hxx>
52 #include <IDocumentLayoutAccess.hxx>
53 #include <IDocumentState.hxx>
54 #include <IDocumentUndoRedo.hxx>
58 #include <frameformats.hxx>
59 #include <sortedobjs.hxx>
60 #include <basegfx/matrix/b2dhommatrix.hxx>
61 #include <basegfx/matrix/b2dhommatrixtools.hxx>
62 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
63 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
64 #include <drawinglayer/geometry/viewinformation2d.hxx>
65 #include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
66 #include <com/sun/star/text/WritingMode2.hpp>
70 #include <sal/log.hxx>
72 using namespace ::com::sun::star
;
76 /** unary function used to find a 'virtual' drawing object anchored at a given frame */
77 struct VirtObjAnchoredAtFramePred
79 const SwFrame
* m_pAnchorFrame
;
81 // #i26791# - compare with master frame
82 static const SwFrame
* FindFrame(const SwFrame
* pFrame
)
84 if(!pFrame
|| !pFrame
->IsContentFrame())
86 auto pContentFrame
= static_cast<const SwContentFrame
*>(pFrame
);
87 while(pContentFrame
->IsFollow())
88 pContentFrame
= pContentFrame
->FindMaster();
92 VirtObjAnchoredAtFramePred(const SwFrame
* pAnchorFrame
)
93 : m_pAnchorFrame(FindFrame(pAnchorFrame
))
96 bool operator()(const rtl::Reference
<SwDrawVirtObj
>& rpDrawVirtObj
)
98 return FindFrame(rpDrawVirtObj
->GetAnchorFrame()) == m_pAnchorFrame
;
103 void setContextWritingMode(SdrObject
* pObj
, SwFrame
const * pAnchor
)
105 if(!pObj
|| !pAnchor
)
107 short nWritingDirection
=
108 pAnchor
->IsVertical() ? text::WritingMode2::TB_RL
:
109 pAnchor
->IsRightToLeft() ? text::WritingMode2::RL_TB
:
110 text::WritingMode2::LR_TB
;
111 pObj
->SetContextWritingMode(nWritingDirection
);
115 /** The Get reverse way: seeks the format to the specified object.
116 * If the object is a SwVirtFlyDrawObj then the format of this
118 * Otherwise it is just a simple drawing object. This has a
119 * UserCall and is the client of the searched format.
121 SwFrameFormat
*FindFrameFormat( SdrObject
*pObj
)
123 SwFrameFormat
* pRetval
= nullptr;
125 if (SwVirtFlyDrawObj
* pFlyDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
127 pRetval
= pFlyDrawObj
->GetFormat();
131 SwContact
* pContact
= GetUserCall(pObj
);
134 pRetval
= pContact
->GetFormat();
140 bool HasWrap( const SdrObject
* pObj
)
144 const SwFrameFormat
* pFormat
= ::FindFrameFormat( pObj
);
147 return css::text::WrapTextMode_THROUGH
!= pFormat
->GetSurround().GetSurround();
154 /// returns the BoundRect _inclusive_ distance of the object.
155 SwRect
GetBoundRectOfAnchoredObj( const SdrObject
* pObj
)
157 SwRect
aRet( pObj
->GetCurrentBoundRect() );
158 // #i68520# - call cache of <SwAnchoredObject>
159 SwContact
* pContact( GetUserCall( pObj
) );
162 const SwAnchoredObject
* pAnchoredObj( pContact
->GetAnchoredObj( pObj
) );
165 aRet
= pAnchoredObj
->GetObjRectWithSpaces();
171 /// Returns the UserCall if applicable from the group object
172 SwContact
* GetUserCall( const SdrObject
* pObj
)
175 while ( !pObj
->GetUserCall() && nullptr != (pTmp
= pObj
->getParentSdrObjectFromSdrObject()) )
177 assert((!pObj
->GetUserCall() || nullptr != dynamic_cast<const SwContact
*>(pObj
->GetUserCall())) &&
178 "<::GetUserCall(..)> - wrong type of found object user call." );
179 return static_cast<SwContact
*>(pObj
->GetUserCall());
182 /// Returns true if the SrdObject is a Marquee-Object (scrolling text)
183 bool IsMarqueeTextObj( const SdrObject
& rObj
)
185 if (SdrInventor::Default
!= rObj
.GetObjInventor() ||
186 SdrObjKind::Text
!= rObj
.GetObjIdentifier())
188 SdrTextAniKind eTKind
= static_cast<const SdrTextObj
&>(rObj
).GetTextAniKind();
189 return ( SdrTextAniKind::Scroll
== eTKind
190 || SdrTextAniKind::Alternate
== eTKind
|| SdrTextAniKind::Slide
== eTKind
);
193 SwContact::SwContact( SwFrameFormat
*pToRegisterIn
) :
194 SwClient( pToRegisterIn
),
198 SwContact::~SwContact()
204 void SwContact::SetInDTOR()
209 /// method to move drawing object to corresponding visible layer
210 void SwContact::MoveObjToVisibleLayer( SdrObject
* _pDrawObj
)
212 // #i46297# - notify background about the arriving of
213 // the object and invalidate its position.
214 const bool bNotify( !GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) );
216 MoveObjToLayer( true, _pDrawObj
);
222 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( _pDrawObj
);
223 assert(pAnchoredObj
);
224 ::setContextWritingMode( _pDrawObj
, pAnchoredObj
->GetAnchorFrameContainingAnchPos() );
225 // Note: as-character anchored objects aren't registered at a page frame and
226 // a notification of its background isn't needed.
227 if ( pAnchoredObj
->GetPageFrame() )
229 ::Notify_Background( _pDrawObj
, pAnchoredObj
->GetPageFrame(),
230 pAnchoredObj
->GetObjRect(), PrepareHint::FlyFrameArrive
, true );
233 pAnchoredObj
->InvalidateObjPos();
236 /// method to move drawing object to corresponding invisible layer - #i18447#
237 void SwContact::MoveObjToInvisibleLayer( SdrObject
* _pDrawObj
)
239 // #i46297# - notify background about the leaving of the object.
240 const bool bNotify( GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) );
242 MoveObjToLayer( false, _pDrawObj
);
247 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( _pDrawObj
);
248 assert(pAnchoredObj
);
249 // Note: as-character anchored objects aren't registered at a page frame and
250 // a notification of its background isn't needed.
251 if (pAnchoredObj
->GetPageFrame())
253 ::Notify_Background( _pDrawObj
, pAnchoredObj
->GetPageFrame(),
254 pAnchoredObj
->GetObjRect(), PrepareHint::FlyFrameLeave
, true );
259 /** method to move object to visible/invisible layer - #i18447#
261 implementation for the public method <MoveObjToVisibleLayer(..)>
262 and <MoveObjToInvisibleLayer(..)>
264 void SwContact::MoveObjToLayer( const bool _bToVisible
,
265 SdrObject
* _pDrawObj
)
269 OSL_FAIL( "SwDrawContact::MoveObjToLayer(..) - no drawing object!" );
273 if ( !GetRegisteredIn() )
275 OSL_FAIL( "SwDrawContact::MoveObjToLayer(..) - no drawing frame format!" );
279 const IDocumentDrawModelAccess
& rIDDMA
= static_cast<SwFrameFormat
*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
281 SdrLayerID nToHellLayerId
=
282 _bToVisible
? rIDDMA
.GetHellId() : rIDDMA
.GetInvisibleHellId();
283 SdrLayerID nToHeavenLayerId
=
284 _bToVisible
? rIDDMA
.GetHeavenId() : rIDDMA
.GetInvisibleHeavenId();
285 SdrLayerID nToControlLayerId
=
286 _bToVisible
? rIDDMA
.GetControlsId() : rIDDMA
.GetInvisibleControlsId();
287 SdrLayerID nFromHellLayerId
=
288 _bToVisible
? rIDDMA
.GetInvisibleHellId() : rIDDMA
.GetHellId();
289 SdrLayerID nFromHeavenLayerId
=
290 _bToVisible
? rIDDMA
.GetInvisibleHeavenId() : rIDDMA
.GetHeavenId();
291 SdrLayerID nFromControlLayerId
=
292 _bToVisible
? rIDDMA
.GetInvisibleControlsId() : rIDDMA
.GetControlsId();
294 if ( dynamic_cast<const SdrObjGroup
*>( _pDrawObj
) != nullptr )
296 // determine layer for group object
298 // proposed layer of a group object is the hell layer
299 SdrLayerID nNewLayerId
= nToHellLayerId
;
300 if ( ::CheckControlLayer( _pDrawObj
) )
302 // it has to be the control layer, if one of the member
304 nNewLayerId
= nToControlLayerId
;
306 else if ( _pDrawObj
->GetLayer() == rIDDMA
.GetHeavenId() ||
307 _pDrawObj
->GetLayer() == rIDDMA
.GetInvisibleHeavenId() )
309 // it has to be the heaven layer, if method <GetLayer()> reveals
311 nNewLayerId
= nToHeavenLayerId
;
313 // set layer at group object, but do *not* broadcast and
314 // no propagation to the members.
315 // Thus, call <NbcSetLayer(..)> at super class
316 _pDrawObj
->SdrObject::NbcSetLayer( nNewLayerId
);
319 // call method recursively for group object members
320 const SdrObjList
* pLst
=
321 static_cast<SdrObjGroup
*>(_pDrawObj
)->GetSubList();
324 for ( size_t i
= 0; i
< pLst
->GetObjCount(); ++i
)
326 MoveObjToLayer( _bToVisible
, pLst
->GetObj( i
) );
332 const SdrLayerID nLayerIdOfObj
= _pDrawObj
->GetLayer();
333 if ( nLayerIdOfObj
== nFromHellLayerId
)
335 _pDrawObj
->SetLayer( nToHellLayerId
);
337 else if ( nLayerIdOfObj
== nFromHeavenLayerId
)
339 _pDrawObj
->SetLayer( nToHeavenLayerId
);
341 else if ( nLayerIdOfObj
== nFromControlLayerId
)
343 _pDrawObj
->SetLayer( nToControlLayerId
);
348 /// get minimum order number of anchored objects handled by with contact
349 sal_uInt32
SwContact::GetMinOrdNum() const
351 sal_uInt32
nMinOrdNum( SAL_MAX_UINT32
);
353 std::vector
< SwAnchoredObject
* > aObjs
;
354 GetAnchoredObjs( aObjs
);
356 while ( !aObjs
.empty() )
358 sal_uInt32 nTmpOrdNum
= aObjs
.back()->GetDrawObj()->GetOrdNum();
360 if ( nTmpOrdNum
< nMinOrdNum
)
362 nMinOrdNum
= nTmpOrdNum
;
368 OSL_ENSURE( nMinOrdNum
!= SAL_MAX_UINT32
,
369 "<SwContact::GetMinOrdNum()> - no order number found." );
373 /// get maximum order number of anchored objects handled by with contact
374 sal_uInt32
SwContact::GetMaxOrdNum() const
376 sal_uInt32
nMaxOrdNum( 0 );
378 std::vector
< SwAnchoredObject
* > aObjs
;
379 GetAnchoredObjs( aObjs
);
381 while ( !aObjs
.empty() )
383 sal_uInt32 nTmpOrdNum
= aObjs
.back()->GetDrawObj()->GetOrdNum();
385 if ( nTmpOrdNum
> nMaxOrdNum
)
387 nMaxOrdNum
= nTmpOrdNum
;
398 Point
lcl_GetWW8Pos(SwAnchoredObject
const * pAnchoredObj
, const bool bFollowTextFlow
, sw::WW8AnchorConv
& reConv
)
402 case sw::WW8AnchorConv::CONV2PG
:
404 bool bRelToTableCell(false);
405 Point
aPos(pAnchoredObj
->GetRelPosToPageFrame(bFollowTextFlow
, bRelToTableCell
));
407 reConv
= sw::WW8AnchorConv::RELTOTABLECELL
;
410 case sw::WW8AnchorConv::CONV2COL_OR_PARA
:
411 return pAnchoredObj
->GetRelPosToAnchorFrame();
412 case sw::WW8AnchorConv::CONV2CHAR
:
413 return pAnchoredObj
->GetRelPosToChar();
414 case sw::WW8AnchorConv::CONV2LINE
:
415 return pAnchoredObj
->GetRelPosToLine();
421 void SwContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
423 // this does not call SwClient::SwClientNotify and thus doesn't handle RES_OBJECTDYING as usual. Is this intentional?
424 if (rHint
.GetId() == SfxHintId::SwFindSdrObject
)
426 auto pFindSdrObjectHint
= static_cast<const sw::FindSdrObjectHint
*>(&rHint
);
427 if(!pFindSdrObjectHint
->m_rpObject
)
428 pFindSdrObjectHint
->m_rpObject
= GetMaster();
430 else if (rHint
.GetId() == SfxHintId::SwWW8AnchorConv
)
432 auto pWW8AnchorConvHint
= static_cast<const sw::WW8AnchorConvHint
*>(&rHint
);
433 // determine anchored object
434 SwAnchoredObject
* pAnchoredObj(nullptr);
436 std::vector
<SwAnchoredObject
*> aAnchoredObjs
;
437 GetAnchoredObjs(aAnchoredObjs
);
438 if(!aAnchoredObjs
.empty())
439 pAnchoredObj
= aAnchoredObjs
.front();
441 // no anchored object found. Thus, the needed layout information can't
442 // be determined. --> no conversion
445 // no conversion for anchored drawing object, which aren't attached to an
447 // This is the case for drawing objects, which are anchored inside a page
448 // header/footer of an *unused* page style.
449 if(dynamic_cast<SwAnchoredDrawObject
*>(pAnchoredObj
) && !pAnchoredObj
->GetAnchorFrame())
451 const bool bFollowTextFlow
= static_cast<const SwFrameFormat
&>(rMod
).GetFollowTextFlow().GetValue();
452 sw::WW8AnchorConvResult
& rResult(pWW8AnchorConvHint
->m_rResult
);
453 // No distinction between layout directions, because of missing
454 // information about WW8 in vertical layout.
455 rResult
.m_aPos
.setX(lcl_GetWW8Pos(pAnchoredObj
, bFollowTextFlow
, rResult
.m_eHoriConv
).getX());
456 rResult
.m_aPos
.setY(lcl_GetWW8Pos(pAnchoredObj
, bFollowTextFlow
, rResult
.m_eVertConv
).getY());
457 rResult
.m_bConverted
= true;
462 SwFlyDrawContact::SwFlyDrawContact(
463 SwFlyFrameFormat
*pToRegisterIn
,
464 SdrModel
& rTargetModel
)
465 : SwContact(pToRegisterIn
),
466 mpMasterObj(new SwFlyDrawObj(rTargetModel
))
468 // #i26791# - class <SwFlyDrawContact> contains the 'master'
469 // drawing object of type <SwFlyDrawObj> on its own.
470 mpMasterObj
->SetOrdNum( 0xFFFFFFFE );
471 mpMasterObj
->SetUserCall( this );
474 SwFlyDrawContact::~SwFlyDrawContact()
478 mpMasterObj
->SetUserCall( nullptr );
479 if ( mpMasterObj
->getSdrPageFromSdrObject() )
480 mpMasterObj
->getSdrPageFromSdrObject()->RemoveObject( mpMasterObj
->GetOrdNum() );
484 sal_uInt32
SwFlyDrawContact::GetOrdNumForNewRef(const SwFlyFrame
* pFly
,
485 SwFrame
const& rAnchorFrame
)
487 // maintain invariant that a shape's textbox immediately follows the shape
488 // also for the multiple SdrVirtObj created for shapes in header/footer
489 if (SwFrameFormat
const*const pDrawFormat
=
490 SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT
))
492 // assume that the draw SdrVirtObj is always created before the flyframe one
493 if (SwSortedObjs
const*const pObjs
= rAnchorFrame
.GetDrawObjs())
495 for (SwAnchoredObject
const*const pAnchoredObj
: *pObjs
)
497 if (&pAnchoredObj
->GetFrameFormat() == pDrawFormat
)
499 return pAnchoredObj
->GetDrawObj()->GetOrdNum() + 1;
503 // if called from AppendObjs(), this is a problem; if called from lcl_SetFlyFrameAttr() it's not
504 SAL_INFO("sw", "GetOrdNumForNewRef: cannot find SdrObject for text box's shape");
506 // search for another Writer fly frame registered at same frame format
507 SwIterator
<SwFlyFrame
,SwFormat
> aIter(*GetFormat());
508 const SwFlyFrame
* pFlyFrame(nullptr);
509 for(pFlyFrame
= aIter
.First(); pFlyFrame
; pFlyFrame
= aIter
.Next())
511 if(pFlyFrame
!= pFly
)
517 // another Writer fly frame found. Take its order number
518 return pFlyFrame
->GetVirtDrawObj()->GetOrdNum();
520 // no other Writer fly frame found. Take order number of 'master' object
521 // #i35748# - use method <GetOrdNumDirect()> instead
522 // of method <GetOrdNum()> to avoid a recalculation of the order number,
523 // which isn't intended.
524 return GetMaster()->GetOrdNumDirect();
527 SwVirtFlyDrawObj
* SwFlyDrawContact::CreateNewRef(SwFlyFrame
* pFly
,
528 SwFlyFrameFormat
* pFormat
, SwFrame
const& rAnchorFrame
)
530 // Find ContactObject from the Format. If there's already one, we just
531 // need to create a new Ref, else we create the Contact now.
533 IDocumentDrawModelAccess
& rIDDMA
= pFormat
->getIDocumentDrawModelAccess();
534 SwFlyDrawContact
* pContact
= pFormat
->GetOrCreateContact();
535 rtl::Reference
<SwVirtFlyDrawObj
> pDrawObj(
536 new SwVirtFlyDrawObj(
537 pContact
->GetMaster()->getSdrModelFromSdrObject(),
538 *pContact
->GetMaster(),
540 pDrawObj
->SetUserCall(pContact
);
542 // The Reader creates the Masters and inserts them into the Page in
543 // order to transport the z-order.
544 // After creating the first Reference the Masters are removed from the
545 // List and are not important anymore.
546 SdrPage
* pPg
= pContact
->GetMaster()->getSdrPageFromSdrObject();
549 const size_t nOrdNum
= pContact
->GetMaster()->GetOrdNum();
550 pPg
->ReplaceObject(pDrawObj
.get(), nOrdNum
);
552 // #i27030# - insert new <SwVirtFlyDrawObj> instance
553 // into drawing page with correct order number
555 rIDDMA
.GetDrawModel()->GetPage(0)->InsertObject(pDrawObj
.get(), pContact
->GetOrdNumForNewRef(pFly
, rAnchorFrame
));
556 // #i38889# - assure, that new <SwVirtFlyDrawObj> instance
557 // is in a visible layer.
558 pContact
->MoveObjToVisibleLayer(pDrawObj
.get());
559 return pDrawObj
.get();
563 const SwAnchoredObject
* SwFlyDrawContact::GetAnchoredObj(const SdrObject
* pSdrObj
) const
566 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(pSdrObj
) != nullptr);
567 assert(GetUserCall(pSdrObj
) == this &&
568 "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belong to this contact");
570 const SwAnchoredObject
*const pRetAnchoredObj
=
571 static_cast<const SwVirtFlyDrawObj
*>(pSdrObj
)->GetFlyFrame();
573 return pRetAnchoredObj
;
576 SwAnchoredObject
* SwFlyDrawContact::GetAnchoredObj(SdrObject
*const pSdrObj
)
578 return const_cast<SwAnchoredObject
*>(const_cast<SwFlyDrawContact
const*>(this)->GetAnchoredObj(pSdrObj
));
581 SdrObject
* SwFlyDrawContact::GetMaster()
583 return mpMasterObj
.get();
587 * @note Overriding method to control Writer fly frames, which are linked, and
588 * to assure that all objects anchored at/inside the Writer fly frame are
591 void SwFlyDrawContact::MoveObjToVisibleLayer( SdrObject
* _pDrawObj
)
593 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(_pDrawObj
) != nullptr);
595 if ( GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) )
601 SwFlyFrame
* pFlyFrame
= static_cast<SwVirtFlyDrawObj
*>(_pDrawObj
)->GetFlyFrame();
603 // #i44464# - consider, that Writer fly frame content
604 // already exists - (e.g. WW8 document is inserted into an existing document).
605 if ( !pFlyFrame
->Lower() )
607 pFlyFrame
->InsertColumns();
608 pFlyFrame
->Chain( pFlyFrame
->AnchorFrame() );
609 pFlyFrame
->InsertCnt();
611 if ( pFlyFrame
->GetDrawObjs() )
613 for (SwAnchoredObject
* i
: *pFlyFrame
->GetDrawObjs())
615 // #i28701# - consider type of objects in sorted object list.
616 SdrObject
* pObj
= i
->DrawObj();
617 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
618 pContact
->MoveObjToVisibleLayer( pObj
);
622 // make fly frame visible
623 SwContact::MoveObjToVisibleLayer( _pDrawObj
);
627 * @note Override method to control Writer fly frames, which are linked, and
628 * to assure that all objects anchored at/inside the Writer fly frame are
629 * also made invisible.
631 void SwFlyDrawContact::MoveObjToInvisibleLayer( SdrObject
* _pDrawObj
)
633 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(_pDrawObj
) != nullptr);
635 if ( !GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) )
641 SwFlyFrame
* pFlyFrame
= static_cast<SwVirtFlyDrawObj
*>(_pDrawObj
)->GetFlyFrame();
643 pFlyFrame
->Unchain();
644 pFlyFrame
->DeleteCnt();
645 if ( pFlyFrame
->GetDrawObjs() )
647 for (SwAnchoredObject
* i
: *pFlyFrame
->GetDrawObjs())
649 // #i28701# - consider type of objects in sorted object list.
650 SdrObject
* pObj
= i
->DrawObj();
651 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
652 pContact
->MoveObjToInvisibleLayer( pObj
);
656 // make fly frame invisible
657 SwContact::MoveObjToInvisibleLayer( _pDrawObj
);
660 /// get data collection of anchored objects, handled by with contact
661 void SwFlyDrawContact::GetAnchoredObjs( std::vector
<SwAnchoredObject
*>& _roAnchoredObjs
) const
663 const SwFrameFormat
* pFormat
= GetFormat();
664 SwFlyFrame::GetAnchoredObjects( _roAnchoredObjs
, *pFormat
);
666 void SwFlyDrawContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
668 SwContact::SwClientNotify(rMod
, rHint
);
669 if(rHint
.GetId() == SfxHintId::SwGetZOrder
)
671 auto pGetZOrdnerHint
= static_cast<const sw::GetZOrderHint
*>(&rHint
);
673 // This also needs to work when no layout exists. Thus, for
674 // FlyFrames an alternative method is used now in that case.
675 auto pFormat(dynamic_cast<const SwFrameFormat
*>(&rMod
));
676 if (pFormat
&& pFormat
->Which() == RES_FLYFRMFMT
&& !pFormat
->getIDocumentLayoutAccess().GetCurrentViewShell())
677 pGetZOrdnerHint
->m_rnZOrder
= GetMaster()->GetOrdNum();
683 bool CheckControlLayer( const SdrObject
*pObj
)
685 if ( SdrInventor::FmForm
== pObj
->GetObjInventor() )
687 if (const SdrObjGroup
*pObjGroup
= dynamic_cast<const SdrObjGroup
*>(pObj
))
689 const SdrObjList
*pLst
= pObjGroup
->GetSubList();
690 for ( size_t i
= 0; i
< pLst
->GetObjCount(); ++i
)
692 if ( ::CheckControlLayer( pLst
->GetObj( i
) ) )
694 // #i18447# - return correct value ;-)
702 SwDrawContact::SwDrawContact( SwFrameFormat
* pToRegisterIn
, SdrObject
* pObj
) :
703 SwContact( pToRegisterIn
),
704 mbMasterObjCleared( false ),
705 mbDisconnectInProgress( false ),
706 mbUserCallActive( false ),
707 // Note: value of <meEventTypeOfCurrentUserCall> isn't of relevance, because
708 // <mbUserCallActive> is false.
709 meEventTypeOfCurrentUserCall( SdrUserCallType::MoveOnly
)
711 // --> #i33909# - assure, that drawing object is inserted
712 // in the drawing page.
713 if ( !pObj
->IsInserted() )
715 pToRegisterIn
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
716 InsertObject( pObj
, pObj
->GetOrdNumDirect() );
719 // Controls have to be always in the Control-Layer. This is also true for
720 // group objects, if they contain controls.
721 if ( ::CheckControlLayer( pObj
) )
723 // set layer of object to corresponding invisible layer.
724 pObj
->SetLayer( pToRegisterIn
->getIDocumentDrawModelAccess().GetInvisibleControlsId() );
728 pObj
->SetUserCall( this );
729 maAnchoredDrawObj
.SetDrawObj( *pObj
);
731 // if there already exists an SwXShape for the object, ensure it knows about us, and the SdrObject
733 SwXShape::AddExistingShapeToFormat( *pObj
);
736 SwDrawContact::~SwDrawContact()
740 DisconnectFromLayout();
742 // remove 'master' from drawing page
743 RemoveMasterFromDrawPage();
745 // remove and destroy 'virtual' drawing objects.
748 if ( !mbMasterObjCleared
)
749 maAnchoredDrawObj
.ClearDrawObj();
752 void SwDrawContact::GetTextObjectsFromFormat(std::list
<SdrTextObj
*>& o_rTextObjects
, SwDoc
& rDoc
)
754 for(sw::SpzFrameFormat
* pFly
: *rDoc
.GetSpzFrameFormats())
756 if(dynamic_cast<const SwDrawFrameFormat
*>(pFly
))
757 pFly
->CallSwClientNotify(sw::CollectTextObjectsHint(o_rTextObjects
));
762 const SwAnchoredObject
* SwDrawContact::GetAnchoredObj(const SdrObject
* pSdrObj
) const
764 // handle default parameter value
767 pSdrObj
= GetMaster();
771 assert(dynamic_cast<const SwDrawVirtObj
*>(pSdrObj
) != nullptr ||
772 dynamic_cast<const SdrVirtObj
*>(pSdrObj
) == nullptr);
773 assert((GetUserCall(pSdrObj
) == this ||
774 pSdrObj
== GetMaster()) &&
775 "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
777 const SwAnchoredObject
* pRetAnchoredObj
= nullptr;
779 if (auto pVirtObj
= dynamic_cast<const SwDrawVirtObj
*>(pSdrObj
))
781 pRetAnchoredObj
= &(pVirtObj
->GetAnchoredObj());
785 assert(dynamic_cast<const SdrVirtObj
*>(pSdrObj
) == nullptr);
786 pRetAnchoredObj
= &maAnchoredDrawObj
;
789 return pRetAnchoredObj
;
792 SwAnchoredObject
* SwDrawContact::GetAnchoredObj(SdrObject
*const pSdrObj
)
794 return const_cast<SwAnchoredObject
*>(const_cast<SwDrawContact
const*>(this)->GetAnchoredObj(pSdrObj
));
797 SdrObject
* SwDrawContact::GetMaster()
799 return !mbMasterObjCleared
800 ? maAnchoredDrawObj
.DrawObj()
804 const SwFrame
* SwDrawContact::GetAnchorFrame( const SdrObject
* _pDrawObj
) const
806 const SwFrame
* pAnchorFrame
= nullptr;
808 _pDrawObj
== GetMaster() ||
809 ( !_pDrawObj
->GetUserCall() &&
810 GetUserCall( _pDrawObj
) == this ) )
812 pAnchorFrame
= maAnchoredDrawObj
.GetAnchorFrame();
816 assert(dynamic_cast<SwDrawVirtObj
const*>(_pDrawObj
) != nullptr);
817 pAnchorFrame
= static_cast<const SwDrawVirtObj
*>(_pDrawObj
)->GetAnchorFrame();
823 SwFrame
* SwDrawContact::GetAnchorFrame(SdrObject
const *const pDrawObj
)
825 return const_cast<SwFrame
*>(const_cast<SwDrawContact
const*>(this)->GetAnchorFrame(pDrawObj
));
828 /** add a 'virtual' drawing object to drawing page.
830 SwDrawVirtObj
* SwDrawContact::AddVirtObj(SwFrame
const& rAnchorFrame
)
832 maDrawVirtObjs
.push_back(
834 GetMaster()->getSdrModelFromSdrObject(),
837 maDrawVirtObjs
.back()->AddToDrawingPage(rAnchorFrame
);
838 return maDrawVirtObjs
.back().get();
841 /// remove 'virtual' drawing objects and destroy them.
842 void SwDrawContact::RemoveAllVirtObjs()
844 for(auto& rpDrawVirtObj
: maDrawVirtObjs
)
846 // remove and destroy 'virtual object'
847 rpDrawVirtObj
->RemoveFromWriterLayout();
848 rpDrawVirtObj
->RemoveFromDrawingPage();
849 // to break the reference cycle
850 rpDrawVirtObj
->AnchoredObj().ClearDrawObj();
852 maDrawVirtObjs
.clear();
856 /// get drawing object ('master' or 'virtual') by frame.
857 SdrObject
* SwDrawContact::GetDrawObjectByAnchorFrame( const SwFrame
& _rAnchorFrame
)
859 SdrObject
* pRetDrawObj
= nullptr;
861 // #i26791# - compare master frames instead of direct frames
862 const SwFrame
* pProposedAnchorFrame
= &_rAnchorFrame
;
863 if ( pProposedAnchorFrame
->IsContentFrame() )
865 const SwContentFrame
* pTmpFrame
=
866 static_cast<const SwContentFrame
*>( pProposedAnchorFrame
);
867 while ( pTmpFrame
->IsFollow() )
869 pTmpFrame
= pTmpFrame
->FindMaster();
871 pProposedAnchorFrame
= pTmpFrame
;
874 const SwFrame
* pMasterObjAnchorFrame
= GetAnchorFrame();
875 if ( pMasterObjAnchorFrame
&& pMasterObjAnchorFrame
->IsContentFrame() )
877 const SwContentFrame
* pTmpFrame
=
878 static_cast<const SwContentFrame
*>( pMasterObjAnchorFrame
);
879 while ( pTmpFrame
->IsFollow() )
881 pTmpFrame
= pTmpFrame
->FindMaster();
883 pMasterObjAnchorFrame
= pTmpFrame
;
886 if ( pMasterObjAnchorFrame
&& pMasterObjAnchorFrame
== pProposedAnchorFrame
)
888 pRetDrawObj
= GetMaster();
892 const auto ppFoundVirtObj(std::find_if(maDrawVirtObjs
.begin(), maDrawVirtObjs
.end(),
893 VirtObjAnchoredAtFramePred(pProposedAnchorFrame
)));
894 if(ppFoundVirtObj
!= maDrawVirtObjs
.end())
895 pRetDrawObj
= ppFoundVirtObj
->get();
901 void SwDrawContact::NotifyBackgroundOfAllVirtObjs(const tools::Rectangle
* pOldBoundRect
)
903 for(const auto& rpDrawVirtObj
: maDrawVirtObjs
)
905 SwDrawVirtObj
* pDrawVirtObj(rpDrawVirtObj
.get());
906 if ( pDrawVirtObj
->GetAnchorFrame() )
908 // #i34640# - determine correct page frame
909 SwPageFrame
* pPage
= pDrawVirtObj
->AnchoredObj().FindPageFrameOfAnchor();
910 if( pOldBoundRect
&& pPage
)
912 SwRect
aOldRect( *pOldBoundRect
);
913 aOldRect
.Pos() += pDrawVirtObj
->GetOffset();
914 if( aOldRect
.HasArea() )
915 ::Notify_Background( pDrawVirtObj
, pPage
,
916 aOldRect
, PrepareHint::FlyFrameLeave
,true);
918 // #i34640# - include spacing for wrapping
919 SwRect
aRect( pDrawVirtObj
->GetAnchoredObj().GetObjRectWithSpaces() );
920 if (aRect
.HasArea() && pPage
)
922 SwPageFrame
* pPg
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aRect
, pPage
)));
924 ::Notify_Background( pDrawVirtObj
, pPg
, aRect
,
925 PrepareHint::FlyFrameArrive
, true );
927 ::ClrContourCache( pDrawVirtObj
);
932 /// local method to notify the background for a drawing object - #i26791#
933 static void lcl_NotifyBackgroundOfObj( SwDrawContact
const & _rDrawContact
,
934 const SdrObject
& _rObj
,
935 const tools::Rectangle
* _pOldObjRect
)
938 SwAnchoredObject
* pAnchoredObj
=
939 const_cast<SwAnchoredObject
*>(_rDrawContact
.GetAnchoredObj( &_rObj
));
940 if ( !(pAnchoredObj
&& pAnchoredObj
->GetAnchorFrame()) )
943 // #i34640# - determine correct page frame
944 SwPageFrame
* pPageFrame
= pAnchoredObj
->FindPageFrameOfAnchor();
945 if( _pOldObjRect
&& pPageFrame
)
947 SwRect
aOldRect( *_pOldObjRect
);
948 if( aOldRect
.HasArea() )
950 // #i34640# - determine correct page frame
951 SwPageFrame
* pOldPageFrame
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aOldRect
, pPageFrame
)));
952 ::Notify_Background( &_rObj
, pOldPageFrame
, aOldRect
,
953 PrepareHint::FlyFrameLeave
, true);
956 // #i34640# - include spacing for wrapping
957 SwRect
aNewRect( pAnchoredObj
->GetObjRectWithSpaces() );
958 if( aNewRect
.HasArea() && pPageFrame
)
960 pPageFrame
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aNewRect
, pPageFrame
)));
961 ::Notify_Background( &_rObj
, pPageFrame
, aNewRect
,
962 PrepareHint::FlyFrameArrive
, true );
964 ClrContourCache( &_rObj
);
967 void SwDrawContact::Changed( const SdrObject
& rObj
,
968 SdrUserCallType eType
,
969 const tools::Rectangle
& rOldBoundRect
)
971 // #i26791# - no event handling, if existing <SwViewShell>
972 // is in construction
973 SwDoc
* pDoc
= GetFormat()->GetDoc();
974 if ( pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() &&
975 pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell()->IsInConstructor() )
981 // no event handling, if document is in destruction.
982 // Exception: It's the SdrUserCallType::Delete event
983 if ( pDoc
->IsInDtor() && eType
!= SdrUserCallType::Delete
)
988 //Put on Action, but not if presently anywhere an action runs.
989 bool bHasActions(true);
990 SwRootFrame
*pTmpRoot
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
991 if ( pTmpRoot
&& pTmpRoot
->IsCallbackActionEnabled() )
993 SwViewShell
* const pSh
= pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
996 for(SwViewShell
& rShell
: pSh
->GetRingContainer() )
998 if ( rShell
.Imp()->IsAction() || rShell
.Imp()->IsIdleAction() )
1003 bHasActions
= false;
1007 pTmpRoot
->StartAllAction();
1009 SdrObjUserCall::Changed( rObj
, eType
, rOldBoundRect
);
1010 Changed_( rObj
, eType
, &rOldBoundRect
); //Attention, possibly suicidal!
1013 pTmpRoot
->EndAllAction();
1016 /// helper class for method <SwDrawContact::Changed_(..)> for handling nested
1017 /// <SdrObjUserCall> events
1018 class NestedUserCallHdl
1021 SwDrawContact
* mpDrawContact
;
1022 bool mbParentUserCallActive
;
1023 SdrUserCallType meParentUserCallEventType
;
1026 NestedUserCallHdl( SwDrawContact
* _pDrawContact
,
1027 SdrUserCallType _eEventType
)
1028 : mpDrawContact( _pDrawContact
),
1029 mbParentUserCallActive( _pDrawContact
->mbUserCallActive
),
1030 meParentUserCallEventType( _pDrawContact
->meEventTypeOfCurrentUserCall
)
1032 mpDrawContact
->mbUserCallActive
= true;
1033 mpDrawContact
->meEventTypeOfCurrentUserCall
= _eEventType
;
1036 ~NestedUserCallHdl()
1038 if ( mpDrawContact
)
1040 mpDrawContact
->mbUserCallActive
= mbParentUserCallActive
;
1041 mpDrawContact
->meEventTypeOfCurrentUserCall
= meParentUserCallEventType
;
1045 void DrawContactDeleted()
1047 mpDrawContact
= nullptr;
1050 bool IsNestedUserCall() const
1052 return mbParentUserCallActive
;
1055 void AssertNestedUserCall()
1057 if ( !IsNestedUserCall() )
1060 bool bTmpAssert( true );
1061 // Currently its known, that a nested event SdrUserCallType::Resize
1062 // could occur during parent user call SdrUserCallType::Inserted,
1063 // SdrUserCallType::Delete and SdrUserCallType::Resize for edge objects.
1064 // Also possible are nested SdrUserCallType::ChildResize events for
1066 // Thus, assert all other combinations
1067 if ( ( meParentUserCallEventType
== SdrUserCallType::Inserted
||
1068 meParentUserCallEventType
== SdrUserCallType::Delete
||
1069 meParentUserCallEventType
== SdrUserCallType::Resize
) &&
1070 mpDrawContact
->meEventTypeOfCurrentUserCall
== SdrUserCallType::Resize
)
1074 else if ( meParentUserCallEventType
== SdrUserCallType::ChildResize
&&
1075 mpDrawContact
->meEventTypeOfCurrentUserCall
== SdrUserCallType::ChildResize
)
1082 OSL_FAIL( "<SwDrawContact::Changed_(..)> - unknown nested <UserCall> event. This is serious." );
1087 /// Notify the format's textbox that it should reconsider its position / size.
1088 static void lcl_textBoxSizeNotify(SwFrameFormat
* pFormat
)
1090 if (SwTextBoxHelper::isTextBox(pFormat
, RES_DRAWFRMFMT
))
1092 // Just notify the textbox that the size has changed, the actual object size is not interesting.
1093 SfxItemSetFixed
<RES_FRM_SIZE
, RES_FRM_SIZE
> aResizeSet(pFormat
->GetDoc()->GetAttrPool());
1094 SwFormatFrameSize aSize
;
1095 aResizeSet
.Put(aSize
);
1096 SwTextBoxHelper::syncFlyFrameAttr(*pFormat
, aResizeSet
, pFormat
->FindRealSdrObject());
1100 // !!!ATTENTION!!! The object may commit suicide!!!
1102 void SwDrawContact::Changed_( const SdrObject
& rObj
,
1103 SdrUserCallType eType
,
1104 const tools::Rectangle
* pOldBoundRect
)
1106 // suppress handling of nested <SdrObjUserCall> events
1107 NestedUserCallHdl
aNestedUserCallHdl( this, eType
);
1108 if ( aNestedUserCallHdl
.IsNestedUserCall() )
1110 aNestedUserCallHdl
.AssertNestedUserCall();
1113 // do *not* notify, if document is destructing
1114 // #i35912# - do *not* notify for as-character anchored
1117 // improvement: determine as-character anchored object flag only once.
1118 const bool bAnchoredAsChar
= ObjAnchoredAsChar();
1119 const bool bNotify
= !(GetFormat()->GetDoc()->IsInDtor()) &&
1120 ( css::text::WrapTextMode_THROUGH
!= GetFormat()->GetSurround().GetSurround() ) &&
1124 case SdrUserCallType::Delete
:
1128 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1129 // --> #i36181# - background of 'virtual'
1130 // drawing objects have also been notified.
1131 NotifyBackgroundOfAllVirtObjs( pOldBoundRect
);
1133 DisconnectFromLayout( false );
1134 mbMasterObjCleared
= true;
1136 // --> #i65784# Prevent memory corruption
1137 aNestedUserCallHdl
.DrawContactDeleted();
1140 case SdrUserCallType::Inserted
:
1142 if ( mbDisconnectInProgress
)
1144 OSL_FAIL( "<SwDrawContact::Changed_(..)> - Insert event during disconnection from layout is invalid." );
1151 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1156 case SdrUserCallType::Removed
:
1160 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1162 DisconnectFromLayout( false );
1165 case SdrUserCallType::ChildInserted
:
1166 case SdrUserCallType::ChildRemoved
:
1169 // force layer of controls for group objects containing control objects
1170 if(dynamic_cast< SdrObjGroup
* >(maAnchoredDrawObj
.DrawObj()))
1172 if(::CheckControlLayer(maAnchoredDrawObj
.DrawObj()))
1174 const IDocumentDrawModelAccess
& rIDDMA
= static_cast<SwFrameFormat
*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
1175 const SdrLayerID
aCurrentLayer(maAnchoredDrawObj
.DrawObj()->GetLayer());
1176 const SdrLayerID
aControlLayerID(rIDDMA
.GetControlsId());
1177 const SdrLayerID
aInvisibleControlLayerID(rIDDMA
.GetInvisibleControlsId());
1179 if(aCurrentLayer
!= aControlLayerID
&& aCurrentLayer
!= aInvisibleControlLayerID
)
1181 if ( aCurrentLayer
== rIDDMA
.GetInvisibleHellId() ||
1182 aCurrentLayer
== rIDDMA
.GetInvisibleHeavenId() )
1184 maAnchoredDrawObj
.DrawObj()->SetLayer(aInvisibleControlLayerID
);
1188 maAnchoredDrawObj
.DrawObj()->SetLayer(aControlLayerID
);
1195 case SdrUserCallType::MoveOnly
:
1196 case SdrUserCallType::Resize
:
1197 case SdrUserCallType::ChildMoveOnly
:
1198 case SdrUserCallType::ChildResize
:
1199 case SdrUserCallType::ChildChangeAttr
:
1200 case SdrUserCallType::ChildDelete
:
1202 // #i31698# - improvement
1203 // get instance <SwAnchoredDrawObject> only once
1204 const SwAnchoredDrawObject
* pAnchoredDrawObj
=
1205 static_cast<const SwAnchoredDrawObject
*>( GetAnchoredObj( &rObj
) );
1207 /* protect against NULL pointer dereferencing */
1208 if(!pAnchoredDrawObj
)
1213 // #i26791# - adjust positioning and alignment attributes,
1214 // if positioning of drawing object isn't in progress.
1215 // #i53320# - no adjust of positioning attributes,
1216 // if drawing object isn't positioned.
1217 if ( !pAnchoredDrawObj
->IsPositioningInProgress() &&
1218 !pAnchoredDrawObj
->NotYetPositioned() )
1220 // #i34748# - If no last object rectangle is
1221 // provided by the anchored object, use parameter <pOldBoundRect>.
1222 const tools::Rectangle
& aOldObjRect
= pAnchoredDrawObj
->GetLastObjRect()
1223 ? *(pAnchoredDrawObj
->GetLastObjRect())
1226 // always invalidate object rectangle inclusive spaces
1227 pAnchoredDrawObj
->InvalidateObjRectWithSpaces();
1228 // #i41324# - notify background before
1229 // adjusting position
1232 // #i31573# - correction
1233 // background of given drawing object.
1234 lcl_NotifyBackgroundOfObj( *this, rObj
, &aOldObjRect
);
1236 // #i31698# - determine layout direction
1237 // via draw frame format.
1238 SwFrameFormat::tLayoutDir eLayoutDir
=
1239 pAnchoredDrawObj
->GetFrameFormat().GetLayoutDir();
1240 // use geometry of drawing object
1241 tools::Rectangle
aObjRect( rObj
.GetSnapRect() );
1242 // If drawing object is a member of a group, the adjustment
1243 // of the positioning and the alignment attributes has to
1244 // be done for the top group object.
1245 if ( rObj
.getParentSdrObjectFromSdrObject() )
1247 const SdrObject
* pGroupObj
= rObj
.getParentSdrObjectFromSdrObject();
1248 while ( pGroupObj
->getParentSdrObjectFromSdrObject() )
1250 pGroupObj
= pGroupObj
->getParentSdrObjectFromSdrObject();
1252 // use geometry of drawing object
1253 aObjRect
= pGroupObj
->GetSnapRect();
1255 SwTextBoxHelper::synchronizeGroupTextBoxProperty(&SwTextBoxHelper::changeAnchor
, GetFormat(), &const_cast<SdrObject
&>(rObj
));
1256 SwTextBoxHelper::synchronizeGroupTextBoxProperty(&SwTextBoxHelper::syncTextBoxSize
, GetFormat(), &const_cast<SdrObject
&>(rObj
));
1259 SwTwips
nXPosDiff(0);
1260 SwTwips
nYPosDiff(0);
1261 switch ( eLayoutDir
)
1263 case SwFrameFormat::HORI_L2R
:
1265 nXPosDiff
= aObjRect
.Left() - aOldObjRect
.Left();
1266 nYPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1269 case SwFrameFormat::HORI_R2L
:
1271 nXPosDiff
= aOldObjRect
.Right() - aObjRect
.Right();
1272 nYPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1275 case SwFrameFormat::VERT_R2L
:
1277 nXPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1278 nYPosDiff
= aOldObjRect
.Right() - aObjRect
.Right();
1283 assert(!"<SwDrawContact::Changed_(..)> - unsupported layout direction");
1286 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
> aSet( GetFormat()->GetDoc()->GetAttrPool() );
1287 const SwFormatVertOrient
& rVert
= GetFormat()->GetVertOrient();
1288 if ( nYPosDiff
!= 0 )
1290 if ( rVert
.GetRelationOrient() == text::RelOrientation::CHAR
||
1291 rVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
1293 nYPosDiff
= -nYPosDiff
;
1295 aSet
.Put( SwFormatVertOrient( rVert
.GetPos()+nYPosDiff
,
1296 text::VertOrientation::NONE
,
1297 rVert
.GetRelationOrient() ) );
1300 const SwFormatHoriOrient
& rHori
= GetFormat()->GetHoriOrient();
1301 if ( !bAnchoredAsChar
&& nXPosDiff
!= 0 )
1303 aSet
.Put( SwFormatHoriOrient( rHori
.GetPos()+nXPosDiff
,
1304 text::HoriOrientation::NONE
,
1305 rHori
.GetRelationOrient() ) );
1309 ( !bAnchoredAsChar
&& nXPosDiff
!= 0 ) )
1311 GetFormat()->GetDoc()->SetFlyFrameAttr( *(GetFormat()), aSet
);
1312 // keep new object rectangle, to avoid multiple
1313 // changes of the attributes by multiple event from
1314 // the drawing layer - e.g. group objects and its members
1315 // #i34748# - use new method
1316 // <SwAnchoredDrawObject::SetLastObjRect(..)>.
1317 const_cast<SwAnchoredDrawObject
*>(pAnchoredDrawObj
)
1318 ->SetLastObjRect( aObjRect
);
1320 else if ( aObjRect
.GetSize() != aOldObjRect
.GetSize() )
1323 // #i35007# - notify anchor frame
1324 // of as-character anchored object
1325 if ( bAnchoredAsChar
)
1327 SwFrame
* pAnchorFrame
= const_cast<SwAnchoredDrawObject
*>(pAnchoredDrawObj
)->AnchorFrame();
1330 pAnchorFrame
->Prepare( PrepareHint::FlyFrameAttributesChanged
, GetFormat() );
1334 lcl_textBoxSizeNotify(GetFormat());
1336 else if (eType
== SdrUserCallType::Resize
)
1337 // Even if the bounding box of the shape didn't change,
1338 // notify about the size change, as an adjustment change
1339 // may affect the size of the underlying textbox.
1340 lcl_textBoxSizeNotify(GetFormat());
1343 // tdf#135198: keep text box together with its shape
1344 const SwPageFrame
* rPageFrame
= pAnchoredDrawObj
->GetPageFrame();
1345 if (rPageFrame
&& rPageFrame
->isFrameAreaPositionValid() && GetFormat()
1346 && GetFormat()->GetOtherTextBoxFormats())
1348 SwDoc
* const pDoc
= GetFormat()->GetDoc();
1350 // avoid Undo creation
1351 ::sw::UndoGuard
const ug(pDoc
->GetIDocumentUndoRedo());
1353 // hide any artificial "changes" made by synchronizing the textbox position
1354 const bool bEnableSetModified
= pDoc
->getIDocumentState().IsEnableSetModified();
1355 pDoc
->getIDocumentState().SetEnableSetModified(false);
1357 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
, RES_ANCHOR
, RES_ANCHOR
>
1358 aSyncSet( pDoc
->GetAttrPool() );
1359 aSyncSet
.Put(GetFormat()->GetHoriOrient());
1360 bool bRelToTableCell(false);
1361 aSyncSet
.Put(SwFormatVertOrient(pAnchoredDrawObj
->GetRelPosToPageFrame(false, bRelToTableCell
).getY(),
1362 text::VertOrientation::NONE
,
1363 text::RelOrientation::PAGE_FRAME
));
1364 aSyncSet
.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE
, rPageFrame
->GetPhyPageNum()));
1366 auto pSdrObj
= const_cast<SdrObject
*>(&rObj
);
1367 if (pSdrObj
!= GetFormat()->FindRealSdrObject())
1369 SfxItemSetFixed
<RES_FRM_SIZE
, RES_FRM_SIZE
> aSet( pDoc
->GetAttrPool() );
1372 aSet
.Put(pSdrObj
->GetMergedItem(RES_FRM_SIZE
));
1373 SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSet
, pSdrObj
);
1375 SwTextBoxHelper::synchronizeGroupTextBoxProperty(
1376 &SwTextBoxHelper::changeAnchor
, GetFormat(),
1377 GetFormat()->FindRealSdrObject());
1378 SwTextBoxHelper::synchronizeGroupTextBoxProperty(
1379 &SwTextBoxHelper::syncTextBoxSize
, GetFormat(),
1380 GetFormat()->FindRealSdrObject());
1383 SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSyncSet
, GetFormat()->FindRealSdrObject());
1385 pDoc
->getIDocumentState().SetEnableSetModified(bEnableSetModified
);
1389 case SdrUserCallType::ChangeAttr
:
1392 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1402 const SwFormatAnchor
* lcl_getAnchorFormat( const SfxPoolItem
& _rItem
)
1404 sal_uInt16 nWhich
= _rItem
.Which();
1405 const SwFormatAnchor
* pAnchorFormat
= nullptr;
1406 if ( RES_ATTRSET_CHG
== nWhich
)
1408 pAnchorFormat
= static_cast<const SwAttrSetChg
&>(_rItem
).GetChgSet()->
1409 GetItemIfSet( RES_ANCHOR
, false );
1411 else if ( RES_ANCHOR
== nWhich
)
1413 pAnchorFormat
= &static_cast<const SwFormatAnchor
&>(_rItem
);
1415 return pAnchorFormat
;
1419 void SwDrawContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
1421 SwClient::SwClientNotify(rMod
, rHint
); // needed as SwContact::SwClientNotify doesn't explicitly call SwClient::SwClientNotify
1422 SwContact::SwClientNotify(rMod
, rHint
);
1423 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
1425 auto pLegacyHint
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
1426 SAL_WARN_IF(mbDisconnectInProgress
, "sw.core", "<SwDrawContact::Modify(..)> called during disconnection.");
1428 const SfxPoolItem
* pNew
= pLegacyHint
->m_pNew
;
1429 sal_uInt16 nWhich
= pNew
? pNew
->Which() : 0;
1430 if(const SwFormatAnchor
* pNewAnchorFormat
= pNew
? lcl_getAnchorFormat(*pNew
) : nullptr)
1432 // Do not respond to a Reset Anchor!
1433 if(GetFormat()->GetAttrSet().GetItemState(RES_ANCHOR
, false) == SfxItemState::SET
)
1435 // no connect to layout during disconnection
1436 if(!mbDisconnectInProgress
)
1438 // determine old object rectangle of 'master' drawing object
1440 const tools::Rectangle
* pOldRect
= nullptr;
1441 tools::Rectangle aOldRect
;
1442 if(GetAnchorFrame())
1444 // --> #i36181# - include spacing in object
1445 // rectangle for notification.
1446 aOldRect
= maAnchoredDrawObj
.GetObjRectWithSpaces().SVRect();
1447 pOldRect
= &aOldRect
;
1449 // re-connect to layout due to anchor format change
1450 ConnectToLayout(pNewAnchorFormat
);
1451 // notify background of drawing objects
1452 lcl_NotifyBackgroundOfObj(*this, *GetMaster(), pOldRect
);
1453 NotifyBackgroundOfAllVirtObjs(pOldRect
);
1455 const SwFormatAnchor
* pOldAnchorFormat
= pLegacyHint
->m_pOld
? lcl_getAnchorFormat(*pLegacyHint
->m_pOld
) : nullptr;
1456 if(!pOldAnchorFormat
|| (pOldAnchorFormat
->GetAnchorId() != pNewAnchorFormat
->GetAnchorId()))
1458 if(maAnchoredDrawObj
.DrawObj())
1461 // assure that a ShapePropertyChangeNotifier exists
1462 maAnchoredDrawObj
.DrawObj()->notifyShapePropertyChange(svx::ShapePropertyProviderId::TextDocAnchor
);
1465 SAL_WARN("sw.core", "SwDrawContact::Modify: no draw object here?");
1470 DisconnectFromLayout();
1472 else if (nWhich
== RES_REMOVE_UNO_OBJECT
)
1474 // --> #i62875# - no further notification, if not connected to Writer layout
1475 else if ( maAnchoredDrawObj
.GetAnchorFrame() &&
1476 maAnchoredDrawObj
.GetDrawObj()->GetUserCall() )
1478 bool bUpdateSortedObjsList(false);
1483 case RES_HORI_ORIENT
:
1484 case RES_VERT_ORIENT
:
1485 case RES_FOLLOW_TEXT_FLOW
: // #i28701# - add attribute 'Follow text flow'
1489 case RES_WRAP_INFLUENCE_ON_OBJPOS
:
1490 // --> #i28701# - on change of wrapping style, hell|heaven layer,
1491 // or wrapping style influence an update of the <SwSortedObjs> list,
1492 // the drawing object is registered in, has to be performed. This is triggered
1493 // by the 1st parameter of method call <InvalidateObjs_(..)>.
1494 bUpdateSortedObjsList
= true;
1496 case RES_ATTRSET_CHG
: // #i35443#
1498 auto pChgSet
= static_cast<const SwAttrSetChg
*>(pNew
)->GetChgSet();
1499 if(pChgSet
->GetItemState(RES_SURROUND
, false) == SfxItemState::SET
||
1500 pChgSet
->GetItemState(RES_OPAQUE
, false) == SfxItemState::SET
||
1501 pChgSet
->GetItemState(RES_WRAP_INFLUENCE_ON_OBJPOS
, false) == SfxItemState::SET
)
1502 bUpdateSortedObjsList
= true;
1506 assert(!"<SwDraw Contact::Modify(..)> - unhandled attribute?");
1508 lcl_NotifyBackgroundOfObj(*this, *GetMaster(), nullptr);
1509 NotifyBackgroundOfAllVirtObjs(nullptr);
1510 InvalidateObjs_(bUpdateSortedObjsList
);
1514 GetAnchoredObj(nullptr)->ResetLayoutProcessBools();
1516 else if (rHint
.GetId() == SfxHintId::SwDrawFrameFormat
)
1518 auto pDrawFrameFormatHint
= static_cast<const sw::DrawFrameFormatHint
*>(&rHint
);
1519 switch(pDrawFrameFormatHint
->m_eId
)
1521 case sw::DrawFrameFormatHintId::DYING
:
1524 case sw::DrawFrameFormatHintId::PREPPASTING
:
1525 MoveObjToVisibleLayer(GetMaster());
1527 case sw::DrawFrameFormatHintId::PREP_INSERT_FLY
:
1528 InsertMasterIntoDrawPage();
1529 // #i40845# - follow-up of #i35635#
1530 // move object to visible layer
1531 MoveObjToVisibleLayer(GetMaster());
1532 // tdf#135661 InsertMasterIntoDrawPage may have created a new
1533 // SwXShape with null m_pFormat; fix that
1534 SwXShape::AddExistingShapeToFormat(*GetMaster());
1536 case sw::DrawFrameFormatHintId::PREP_DELETE_FLY
:
1537 RemoveMasterFromDrawPage();
1539 case sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS
:
1540 case sw::DrawFrameFormatHintId::DELETE_FRAMES
:
1541 DisconnectFromLayout();
1543 case sw::DrawFrameFormatHintId::MAKE_FRAMES
:
1546 case sw::DrawFrameFormatHintId::POST_RESTORE_FLY_ANCHOR
:
1547 GetAnchoredObj(GetMaster())->MakeObjPos();
1553 else if (rHint
.GetId() == SfxHintId::SwCheckDrawFrameFormatLayer
)
1555 auto pCheckDrawFrameFormatLayerHint
= static_cast<const sw::CheckDrawFrameFormatLayerHint
*>(&rHint
);
1556 *(pCheckDrawFrameFormatLayerHint
->m_bCheckControlLayer
) |= (GetMaster() && CheckControlLayer(GetMaster()));
1558 else if (rHint
.GetId() == SfxHintId::SwContactChanged
)
1560 auto pContactChangedHint
= static_cast<const sw::ContactChangedHint
*>(&rHint
);
1561 if(!*pContactChangedHint
->m_ppObject
)
1562 *pContactChangedHint
->m_ppObject
= GetMaster();
1563 auto pObject
= *pContactChangedHint
->m_ppObject
;
1564 Changed(*pObject
, SdrUserCallType::Delete
, pObject
->GetLastBoundRect());
1566 else if (rHint
.GetId() == SfxHintId::SwDrawFormatLayoutCopy
)
1568 auto pDrawFormatLayoutCopyHint
= static_cast<const sw::DrawFormatLayoutCopyHint
*>(&rHint
);
1569 const SwDrawFrameFormat
& rFormat
= static_cast<const SwDrawFrameFormat
&>(rMod
);
1570 rtl::Reference
<SdrObject
> xNewObj
=
1571 pDrawFormatLayoutCopyHint
->m_rDestDoc
.CloneSdrObj(
1573 pDrawFormatLayoutCopyHint
->m_rDestDoc
.IsCopyIsMove() && &pDrawFormatLayoutCopyHint
->m_rDestDoc
== rFormat
.GetDoc());
1575 &pDrawFormatLayoutCopyHint
->m_rDestFormat
, xNewObj
.get() );
1576 // #i49730# - notify draw frame format that position attributes are
1577 // already set, if the position attributes are already set at the
1578 // source draw frame format.
1579 if(rFormat
.IsPosAttrSet())
1580 pDrawFormatLayoutCopyHint
->m_rDestFormat
.PosAttrSet();
1582 else if (rHint
.GetId() == SfxHintId::SwRestoreFlyAnchor
)
1584 auto pRestoreFlyAnchorHint
= static_cast<const sw::RestoreFlyAnchorHint
*>(&rHint
);
1585 SdrObject
* pObj
= GetMaster();
1586 if(GetAnchorFrame() && !pObj
->IsInserted())
1588 auto pDrawModel
= const_cast<SwDrawFrameFormat
&>(static_cast<const SwDrawFrameFormat
&>(rMod
)).GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1590 pDrawModel
->GetPage(0)->InsertObject(pObj
);
1592 pObj
->SetRelativePos(pRestoreFlyAnchorHint
->m_aPos
);
1594 else if (rHint
.GetId() == SfxHintId::SwCreatePortion
)
1596 auto pCreatePortionHint
= static_cast<const sw::CreatePortionHint
*>(&rHint
);
1597 if(*pCreatePortionHint
->m_ppContact
)
1599 *pCreatePortionHint
->m_ppContact
= this; // This is kind of ridiculous: the FrameFormat doesn't even hold a pointer to the contact itself, but here we are leaking it out randomly
1600 if(!GetAnchorFrame())
1602 // No direct positioning needed any more
1604 // Move object to visible layer
1605 MoveObjToVisibleLayer(GetMaster());
1608 else if (rHint
.GetId() == SfxHintId::SwCollectTextObjects
)
1610 auto pCollectTextObjectsHint
= static_cast<const sw::CollectTextObjectsHint
*>(&rHint
);
1611 auto pSdrO
= GetMaster();
1614 if(dynamic_cast<const SdrObjGroup
*>(pSdrO
))
1616 SdrObjListIter
aListIter(*pSdrO
, SdrIterMode::DeepNoGroups
);
1617 //iterate inside of a grouped object
1618 while(aListIter
.IsMore())
1620 SdrTextObj
* pTextObj
= DynCastSdrTextObj(aListIter
.Next());
1621 if(pTextObj
&& pTextObj
->HasText())
1622 pCollectTextObjectsHint
->m_rTextObjects
.push_back(pTextObj
);
1625 else if(SdrTextObj
* pTextObj
= DynCastSdrTextObj(pSdrO
))
1627 if(pTextObj
->HasText())
1628 pCollectTextObjectsHint
->m_rTextObjects
.push_back(pTextObj
);
1631 else if (rHint
.GetId() == SfxHintId::SwGetZOrder
)
1633 auto pGetZOrdnerHint
= static_cast<const sw::GetZOrderHint
*>(&rHint
);
1634 auto pFormat(dynamic_cast<const SwFrameFormat
*>(&rMod
));
1635 if (pFormat
&& pFormat
->Which() == RES_DRAWFRMFMT
)
1636 pGetZOrdnerHint
->m_rnZOrder
= GetMaster()->GetOrdNum();
1638 else if (rHint
.GetId() == SfxHintId::SwGetObjectConnected
)
1640 auto pConnectedHint
= static_cast<const sw::GetObjectConnectedHint
*>(&rHint
);
1641 pConnectedHint
->m_risConnected
|= (GetAnchorFrame() != nullptr);
1646 // #i28701# - added parameter <_bUpdateSortedObjsList>
1647 void SwDrawContact::InvalidateObjs_( const bool _bUpdateSortedObjsList
)
1649 for(const auto& rpDrawVirtObj
: maDrawVirtObjs
)
1650 // invalidate position of existing 'virtual' drawing objects
1652 SwDrawVirtObj
* pDrawVirtObj(rpDrawVirtObj
.get());
1653 // #i33313# - invalidation only for connected
1654 // 'virtual' drawing objects
1655 if ( pDrawVirtObj
->IsConnected() )
1657 pDrawVirtObj
->AnchoredObj().InvalidateObjPos();
1659 if ( _bUpdateSortedObjsList
)
1661 pDrawVirtObj
->AnchoredObj().UpdateObjInSortedList();
1666 // invalidate position of 'master' drawing object
1667 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( nullptr );
1668 pAnchoredObj
->InvalidateObjPos();
1670 if ( _bUpdateSortedObjsList
)
1672 pAnchoredObj
->UpdateObjInSortedList();
1676 void SwDrawContact::DisconnectFromLayout( bool _bMoveMasterToInvisibleLayer
)
1678 mbDisconnectInProgress
= true;
1680 // --> #i36181# - notify background of drawing object
1681 if ( _bMoveMasterToInvisibleLayer
&&
1682 !(GetFormat()->GetDoc()->IsInDtor()) &&
1683 GetAnchorFrame() && !GetAnchorFrame()->IsInDtor() )
1685 const tools::Rectangle
aOldRect( maAnchoredDrawObj
.GetObjRectWithSpaces().SVRect() );
1686 lcl_NotifyBackgroundOfObj( *this, *GetMaster(), &aOldRect
);
1687 NotifyBackgroundOfAllVirtObjs( &aOldRect
);
1690 // remove 'virtual' drawing objects from writer
1691 // layout and from drawing page
1692 for(auto& rpVirtDrawObj
: maDrawVirtObjs
)
1694 rpVirtDrawObj
->RemoveFromWriterLayout();
1695 rpVirtDrawObj
->RemoveFromDrawingPage();
1698 if ( maAnchoredDrawObj
.GetAnchorFrame() )
1700 maAnchoredDrawObj
.AnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
1703 if ( _bMoveMasterToInvisibleLayer
&& GetMaster() && GetMaster()->IsInserted() )
1705 SdrViewIter
aIter( GetMaster() );
1706 for( SdrView
* pView
= aIter
.FirstView(); pView
;
1707 pView
= aIter
.NextView() )
1709 pView
->MarkObj( GetMaster(), pView
->GetSdrPageView(), true );
1712 // Instead of removing 'master' object from drawing page, move the
1713 // 'master' drawing object into the corresponding invisible layer.
1715 //static_cast<SwFrameFormat*>(GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1716 // RemoveObject( GetMaster()->GetOrdNum() );
1717 // #i18447# - in order to consider group object correct
1718 // use new method <SwDrawContact::MoveObjToInvisibleLayer(..)>
1719 MoveObjToInvisibleLayer( GetMaster() );
1723 mbDisconnectInProgress
= false;
1726 /// method to remove 'master' drawing object from drawing page.
1727 void SwDrawContact::RemoveMasterFromDrawPage()
1731 GetMaster()->SetUserCall( nullptr );
1732 if ( GetMaster()->IsInserted() )
1734 static_cast<SwFrameFormat
*>(GetRegisteredIn())->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1735 RemoveObject( GetMaster()->GetOrdNum() );
1740 // disconnect for a dedicated drawing object - could be 'master' or 'virtual'.
1741 // a 'master' drawing object will disconnect a 'virtual' drawing object
1742 // in order to take its place.
1743 // #i19919# - no special case, if drawing object isn't in
1744 // page header/footer, in order to get drawing objects in repeating table headers
1746 void SwDrawContact::DisconnectObjFromLayout( SdrObject
* _pDrawObj
)
1748 if ( auto pSwDrawVirtObj
= dynamic_cast<SwDrawVirtObj
*>( _pDrawObj
) )
1750 pSwDrawVirtObj
->RemoveFromWriterLayout();
1751 pSwDrawVirtObj
->RemoveFromDrawingPage();
1755 const auto ppVirtDrawObj(std::find_if(maDrawVirtObjs
.begin(), maDrawVirtObjs
.end(),
1756 [] (const rtl::Reference
<SwDrawVirtObj
>& pObj
) { return pObj
->IsConnected(); }));
1758 if(ppVirtDrawObj
!= maDrawVirtObjs
.end())
1760 // replace found 'virtual' drawing object by 'master' drawing
1761 // object and disconnect the 'virtual' one
1762 SwDrawVirtObj
* pDrawVirtObj(ppVirtDrawObj
->get());
1763 SwFrame
* pNewAnchorFrameOfMaster
= pDrawVirtObj
->AnchorFrame();
1764 // disconnect 'virtual' drawing object
1765 pDrawVirtObj
->RemoveFromWriterLayout();
1766 pDrawVirtObj
->RemoveFromDrawingPage();
1767 // disconnect 'master' drawing object from current frame
1768 GetAnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
1769 // re-connect 'master' drawing object to frame of found 'virtual'
1771 pNewAnchorFrameOfMaster
->AppendDrawObj( maAnchoredDrawObj
);
1775 // no connected 'virtual' drawing object found. Thus, disconnect
1776 // completely from layout.
1777 DisconnectFromLayout();
1782 static SwTextFrame
* lcl_GetFlyInContentAnchor( SwTextFrame
* _pProposedAnchorFrame
,
1783 SwPosition
const& rAnchorPos
)
1785 SwTextFrame
* pAct
= _pProposedAnchorFrame
;
1787 TextFrameIndex
const nTextOffset(_pProposedAnchorFrame
->MapModelToViewPos(rAnchorPos
));
1791 pAct
= pTmp
->GetFollow();
1793 while (pAct
&& nTextOffset
>= pAct
->GetOffset());
1797 void SwDrawContact::ConnectToLayout( const SwFormatAnchor
* pAnch
)
1799 // *no* connect to layout during disconnection from layout.
1800 if ( mbDisconnectInProgress
)
1802 OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> called during disconnection.");
1806 // --> #i33909# - *no* connect to layout, if 'master' drawing
1807 // object isn't inserted in the drawing page
1808 if ( !GetMaster()->IsInserted() )
1810 OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> - master drawing object not inserted -> no connect to layout. Please inform od@openoffice.org" );
1814 SwFrameFormat
* pDrawFrameFormat
= static_cast<SwFrameFormat
*>(GetRegisteredIn());
1816 if( !pDrawFrameFormat
->getIDocumentLayoutAccess().GetCurrentViewShell() )
1819 // remove 'virtual' drawing objects from writer
1820 // layout and from drawing page, and remove 'master' drawing object from
1821 // writer layout - 'master' object will remain in drawing page.
1822 DisconnectFromLayout( false );
1826 pAnch
= &(pDrawFrameFormat
->GetAnchor());
1829 switch ( pAnch
->GetAnchorId() )
1831 case RndStdIds::FLY_AT_PAGE
:
1833 sal_uInt16 nPgNum
= pAnch
->GetPageNum();
1834 SwViewShell
*pShell
= pDrawFrameFormat
->getIDocumentLayoutAccess().GetCurrentViewShell();
1837 SwRootFrame
* pRoot
= pShell
->GetLayout();
1838 SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(pRoot
->Lower());
1840 for ( sal_uInt16 i
= 1; i
< nPgNum
&& pPage
; ++i
)
1842 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1847 pPage
->AppendDrawObj( maAnchoredDrawObj
);
1850 //Looks stupid but is allowed (compare SwFEShell::SetPageObjsNewPage)
1851 pRoot
->SetAssertFlyPages();
1855 case RndStdIds::FLY_AT_CHAR
:
1856 case RndStdIds::FLY_AT_PARA
:
1857 case RndStdIds::FLY_AT_FLY
:
1858 case RndStdIds::FLY_AS_CHAR
:
1860 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1862 ClrContourCache( GetMaster() );
1864 // support drawing objects in header/footer,
1865 // but not control objects:
1866 // anchor at first found frame the 'master' object and
1867 // at the following frames 'virtual' drawing objects.
1868 // Note: method is similar to <SwFlyFrameFormat::MakeFrames(..)>
1869 sw::BroadcastingModify
*pModify
= nullptr;
1870 if( pAnch
->GetAnchorNode() )
1872 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AT_FLY
)
1874 SwNodeIndex
aIdx( *pAnch
->GetAnchorNode() );
1875 SwContentNode
* pCNd
= pDrawFrameFormat
->GetDoc()->GetNodes().GoNext( &aIdx
);
1876 if (SwIterator
<SwFrame
, SwContentNode
, sw::IteratorMode::UnwrapMulti
>(*pCNd
).First())
1880 const SwNode
& rIdx
= *pAnch
->GetAnchorNode();
1881 for(sw::SpzFrameFormat
* pFlyFormat
:*(pDrawFrameFormat
->GetDoc()->GetSpzFrameFormats()))
1883 if( pFlyFormat
->GetContent().GetContentIdx() &&
1884 rIdx
== pFlyFormat
->GetContent().GetContentIdx()->GetNode() )
1886 pModify
= pFlyFormat
;
1894 pModify
= pAnch
->GetAnchorNode()->GetContentNode();
1898 // #i29199# - It is possible, that
1899 // the anchor doesn't exist - E.g., reordering the
1900 // sub-documents in a master document.
1901 // Note: The anchor will be inserted later.
1904 // break to end of the current switch case.
1908 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(*pModify
);
1909 SwFrame
* pAnchorFrameOfMaster
= nullptr;
1910 for( SwFrame
*pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next() )
1912 // append drawing object, if
1913 // (1) proposed anchor frame isn't a follow and...
1914 const bool bFollow
= pFrame
->IsContentFrame() && static_cast<SwContentFrame
*>(pFrame
)->IsFollow();
1918 // (2) drawing object isn't a control object to be anchored
1919 // in header/footer.
1920 const bool bControlInHF
= ::CheckControlLayer(GetMaster()) && pFrame
->FindFooterOrHeader();
1921 // tdf#129542 but make an exception for control objects so they can get added to just the first frame,
1922 // the Master Anchor Frame and not the others
1923 if (bControlInHF
&& pAnchorFrameOfMaster
)
1927 if (RndStdIds::FLY_AT_FLY
== pAnch
->GetAnchorId())
1931 assert(pFrame
->IsTextFrame());
1932 bAdd
= IsAnchoredObjShown(*static_cast<SwTextFrame
*>(pFrame
), *pAnch
);
1937 if ( RndStdIds::FLY_AT_FLY
== pAnch
->GetAnchorId() && !pFrame
->IsFlyFrame() )
1939 pFrame
= pFrame
->FindFlyFrame();
1943 // find correct follow for as character anchored objects
1944 if ((pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
) &&
1945 pFrame
->IsTextFrame() )
1947 pFrame
= lcl_GetFlyInContentAnchor(
1948 static_cast<SwTextFrame
*>(pFrame
),
1949 *pAnch
->GetContentAnchor());
1952 if ( !pAnchorFrameOfMaster
)
1954 // append 'master' drawing object
1955 pAnchorFrameOfMaster
= pFrame
;
1957 const SwFrameFormat
* pFlyFormat
= nullptr;
1958 if (!maAnchoredDrawObj
.GetDrawObj()->IsGroupObject())
1960 pFlyFormat
= SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_DRAWFRMFMT
);
1965 // This is a master draw object and it has an associated fly format.
1966 // See if a fly frame is already inserted to the layout: if so, this
1967 // master draw object should be ordered directly before the fly one.
1968 if (const SwSortedObjs
* pObjs
= pFrame
->GetDrawObjs())
1970 for (const SwAnchoredObject
* pAnchoredObj
: *pObjs
)
1972 if (&pAnchoredObj
->GetFrameFormat() == pFlyFormat
)
1974 SdrPage
* pDrawPage
= pAnchoredObj
->GetDrawObj()->getSdrPageFromSdrObject();
1977 sal_uInt32 nOrdNum
= pAnchoredObj
->GetDrawObj()->GetOrdNum();
1978 if (maAnchoredDrawObj
.GetDrawObj()->GetOrdNum() >= nOrdNum
)
1980 pDrawPage
->SetObjectOrdNum(maAnchoredDrawObj
.GetDrawObj()->GetOrdNumDirect(), nOrdNum
);
1984 pDrawPage
->SetObjectOrdNum(nOrdNum
, maAnchoredDrawObj
.GetDrawObj()->GetOrdNumDirect() + 1);
1993 pFrame
->AppendDrawObj( maAnchoredDrawObj
);
1997 // append 'virtual' drawing object
1998 SwDrawVirtObj
* pDrawVirtObj
= AddVirtObj(*pFrame
);
1999 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
2001 ClrContourCache( pDrawVirtObj
);
2003 pFrame
->AppendDrawObj( pDrawVirtObj
->AnchoredObj() );
2005 pDrawVirtObj
->ActionChanged();
2008 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
2010 pFrame
->InvalidatePrt();
2017 assert(!"Unknown Anchor.");
2020 if ( GetAnchorFrame() )
2022 ::setContextWritingMode( maAnchoredDrawObj
.DrawObj(), GetAnchorFrame() );
2023 // #i26791# - invalidate objects instead of direct positioning
2028 /// insert 'master' drawing object into drawing page
2029 void SwDrawContact::InsertMasterIntoDrawPage()
2031 if ( !GetMaster()->IsInserted() )
2033 GetFormat()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)
2034 ->InsertObject( GetMaster(), GetMaster()->GetOrdNumDirect() );
2036 GetMaster()->SetUserCall( this );
2039 SwPageFrame
* SwDrawContact::FindPage( const SwRect
&rRect
)
2041 // --> #i28701# - use method <GetPageFrame()>
2042 SwPageFrame
* pPg
= GetPageFrame();
2043 if ( !pPg
&& GetAnchorFrame() )
2044 pPg
= GetAnchorFrame()->FindPageFrame();
2046 pPg
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( rRect
, pPg
)));
2050 void SwDrawContact::ChkPage()
2052 if ( mbDisconnectInProgress
)
2054 OSL_FAIL( "<SwDrawContact::ChkPage()> called during disconnection." );
2059 SwPageFrame
* pPg
= ( maAnchoredDrawObj
.GetAnchorFrame() &&
2060 maAnchoredDrawObj
.GetAnchorFrame()->IsPageFrame() )
2062 : FindPage( SwRect(GetMaster()->GetCurrentBoundRect()) );
2063 if ( GetPageFrame() == pPg
)
2066 // if drawing object is anchor in header/footer a change of the page
2067 // is a dramatic change. Thus, completely re-connect to the layout
2068 if ( maAnchoredDrawObj
.GetAnchorFrame() &&
2069 maAnchoredDrawObj
.GetAnchorFrame()->FindFooterOrHeader() )
2075 // --> #i28701# - use methods <GetPageFrame()> and <SetPageFrame>
2076 if ( GetPageFrame() )
2077 GetPageFrame()->RemoveDrawObjFromPage( maAnchoredDrawObj
);
2078 pPg
->AppendDrawObjToPage( maAnchoredDrawObj
);
2079 maAnchoredDrawObj
.SetPageFrame( pPg
);
2084 // method is called by method <SwDPage::ReplaceObject(..)>, which called its
2085 // corresponding superclass method <FmFormPage::ReplaceObject(..)>.
2086 // Note: 'master' drawing object *has* to be connected to layout triggered
2087 // by the caller of this, if method is called.
2088 void SwDrawContact::ChangeMasterObject(SdrObject
* pNewMaster
)
2090 DisconnectFromLayout( false );
2091 // consider 'virtual' drawing objects
2092 RemoveAllVirtObjs();
2094 GetMaster()->SetUserCall( nullptr );
2096 maAnchoredDrawObj
.SetDrawObj(*pNewMaster
);
2098 mbMasterObjCleared
= true;
2099 GetMaster()->SetUserCall( this );
2104 /// get data collection of anchored objects, handled by with contact
2105 void SwDrawContact::GetAnchoredObjs(std::vector
<SwAnchoredObject
*>& o_rAnchoredObjs
) const
2107 o_rAnchoredObjs
.push_back(const_cast<SwAnchoredDrawObject
*>(&maAnchoredDrawObj
));
2109 for(auto& rpDrawVirtObj
: maDrawVirtObjs
)
2110 o_rAnchoredObjs
.push_back(&rpDrawVirtObj
->AnchoredObj());
2113 // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
2114 // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
2115 // For paint, that offset is used by setting at the OutputDevice; for primitives this is
2116 // not possible since we have no OutputDevice, but define the geometry itself.
2118 namespace sdr::contact
2122 class VOCOfDrawVirtObj
: public ViewObjectContactOfSdrObj
2126 * This method is responsible for creating the graphical visualisation data which is
2127 * stored/cached in the local primitive. Default gets view-independent Primitive from
2128 * the ViewContact using ViewContact::getViewIndependentPrimitive2DContainer(), takes
2129 * care of visibility, handles glue and ghosted.
2131 * This method will not handle included hierarchies and not check geometric visibility.
2133 virtual void createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const override
;
2136 VOCOfDrawVirtObj(ObjectContact
& rObjectContact
, ViewContact
& rViewContact
)
2137 : ViewObjectContactOfSdrObj(rObjectContact
, rViewContact
)
2142 class VCOfDrawVirtObj
: public ViewContactOfVirtObj
2145 /** Create an Object-Specific ViewObjectContact, set ViewContact and ObjectContact.
2147 * Always needs to return something. Default is to create a standard ViewObjectContact
2148 * containing the given ObjectContact and *this.
2150 virtual ViewObjectContact
& CreateObjectSpecificViewObjectContact(ObjectContact
& rObjectContact
) override
;
2153 /// basic constructor, used from SdrObject.
2154 explicit VCOfDrawVirtObj(SwDrawVirtObj
& rObj
)
2155 : ViewContactOfVirtObj(rObj
)
2159 /// access to SwDrawVirtObj
2160 SwDrawVirtObj
& GetSwDrawVirtObj() const
2162 return static_cast<SwDrawVirtObj
&>(mrObject
);
2167 } // end of namespace sdr::contact
2169 namespace sdr::contact
2171 /// recursively collect primitive data from given VOC with given offset
2172 static void impAddPrimitivesFromGroup(const ViewObjectContact
& rVOC
, const basegfx::B2DHomMatrix
& rOffsetMatrix
, const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DContainer
& rxTarget
)
2174 const sal_uInt32
nSubHierarchyCount(rVOC
.GetViewContact().GetObjectCount());
2176 for(sal_uInt32
a(0); a
< nSubHierarchyCount
; a
++)
2178 const ViewObjectContact
& rCandidate(rVOC
.GetViewContact().GetViewContact(a
).GetViewObjectContact(rVOC
.GetObjectContact()));
2180 if(rCandidate
.GetViewContact().GetObjectCount())
2182 // is a group object itself, call recursively
2183 impAddPrimitivesFromGroup(rCandidate
, rOffsetMatrix
, rDisplayInfo
, rxTarget
);
2187 // single object, add primitives; check model-view visibility
2188 if(rCandidate
.isPrimitiveVisible(rDisplayInfo
))
2190 drawinglayer::primitive2d::Primitive2DContainer
aNewSequence(rCandidate
.getPrimitive2DSequence(rDisplayInfo
));
2192 if(!aNewSequence
.empty())
2195 const drawinglayer::geometry::ViewInformation2D
& rViewInformation2D(rCandidate
.GetObjectContact().getViewInformation2D());
2196 const basegfx::B2DRange
& aViewRange(rViewInformation2D
.getViewport());
2197 basegfx::B2DRange
aObjectRange(rCandidate
.getObjectRange());
2199 // correct with virtual object's offset
2200 aObjectRange
.transform(rOffsetMatrix
);
2202 // check geometrical visibility (with offset)
2203 if(!aViewRange
.overlaps(aObjectRange
))
2205 // not visible, release
2206 aNewSequence
.clear();
2210 if(!aNewSequence
.empty())
2212 rxTarget
.append(aNewSequence
);
2219 void VOCOfDrawVirtObj::createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const
2221 // tdf#91260 have already checked top-level one is on the right page
2222 assert(isPrimitiveVisible(rDisplayInfo
));
2223 // nasty corner case: override to clear page frame to disable the
2224 // sub-objects' anchor check, because their anchor is always on
2225 // the first page that the page style is applied to
2226 DisplayInfo
aDisplayInfo(rDisplayInfo
);
2227 aDisplayInfo
.SetWriterPageFrame(basegfx::B2IRectangle());
2228 const VCOfDrawVirtObj
& rVC
= static_cast< const VCOfDrawVirtObj
& >(GetViewContact());
2229 const SdrObject
& rReferencedObject
= rVC
.GetSwDrawVirtObj().GetReferencedObj();
2230 drawinglayer::primitive2d::Primitive2DContainer xRetval
;
2232 // create offset transformation
2233 basegfx::B2DHomMatrix aOffsetMatrix
;
2234 const Point
aLocalOffset(rVC
.GetSwDrawVirtObj().GetOffset());
2236 if(aLocalOffset
.X() || aLocalOffset
.Y())
2238 aOffsetMatrix
.set(0, 2, aLocalOffset
.X());
2239 aOffsetMatrix
.set(1, 2, aLocalOffset
.Y());
2242 if(dynamic_cast<const SdrObjGroup
*>( &rReferencedObject
) != nullptr)
2244 // group object. Since the VOC/OC/VC hierarchy does not represent the
2245 // hierarchy virtual objects when they have group objects
2246 // (ViewContactOfVirtObj::GetObjectCount() returns null for that purpose)
2247 // to avoid multiple usages of VOCs (which would not work), the primitives
2248 // for the sub-hierarchy need to be collected here
2250 // Get the VOC of the referenced object (the Group) and fetch primitives from it
2251 const ViewObjectContact
& rVOCOfRefObj
= rReferencedObject
.GetViewContact().GetViewObjectContact(GetObjectContact());
2252 impAddPrimitivesFromGroup(rVOCOfRefObj
, aOffsetMatrix
, aDisplayInfo
, xRetval
);
2256 // single object, use method from referenced object to get the Primitive2DSequence
2257 rReferencedObject
.GetViewContact().getViewIndependentPrimitive2DContainer(xRetval
);
2260 if(!xRetval
.empty())
2262 // create transform primitive
2263 drawinglayer::primitive2d::Primitive2DReference
xReference(new drawinglayer::primitive2d::TransformPrimitive2D(aOffsetMatrix
, std::move(xRetval
)));
2264 xRetval
= drawinglayer::primitive2d::Primitive2DContainer
{ xReference
};
2267 rVisitor
.visit(xRetval
);
2270 ViewObjectContact
& VCOfDrawVirtObj::CreateObjectSpecificViewObjectContact(ObjectContact
& rObjectContact
)
2272 return *(new VOCOfDrawVirtObj(rObjectContact
, *this));
2275 } // end of namespace sdr::contact
2277 /// implementation of class <SwDrawVirtObj>
2278 std::unique_ptr
<sdr::contact::ViewContact
> SwDrawVirtObj::CreateObjectSpecificViewContact()
2280 return std::make_unique
<sdr::contact::VCOfDrawVirtObj
>(*this);
2283 SwDrawVirtObj::SwDrawVirtObj(
2284 SdrModel
& rSdrModel
,
2285 SdrObject
& _rNewObj
,
2286 SwDrawContact
& _rDrawContact
)
2287 : SdrVirtObj(rSdrModel
, _rNewObj
),
2288 mrDrawContact(_rDrawContact
)
2291 maAnchoredDrawObj
.SetDrawObj( *this );
2293 // #i35635# - set initial position out of sight
2294 NbcMove( Size( -16000, -16000 ) );
2297 SwDrawVirtObj::SwDrawVirtObj(
2298 SdrModel
& rSdrModel
,
2299 SwDrawVirtObj
const & rSource
)
2300 : SdrVirtObj(rSdrModel
, rSource
),
2301 mrDrawContact(rSource
.mrDrawContact
)
2304 maAnchoredDrawObj
.SetDrawObj( *this );
2306 // #i35635# - set initial position out of sight
2307 NbcMove( Size( -16000, -16000 ) );
2309 // Note: Members <maAnchoredDrawObj> and <mrDrawContact>
2310 // haven't to be considered.
2313 SwDrawVirtObj::~SwDrawVirtObj()
2317 rtl::Reference
<SdrObject
> SwDrawVirtObj::CloneSdrObject(SdrModel
& rTargetModel
) const
2319 return new SwDrawVirtObj(rTargetModel
, *this);
2322 const SwFrame
* SwDrawVirtObj::GetAnchorFrame() const
2324 // #i26791# - use new member <maAnchoredDrawObj>
2325 return maAnchoredDrawObj
.GetAnchorFrame();
2328 SwFrame
* SwDrawVirtObj::AnchorFrame()
2330 // #i26791# - use new member <maAnchoredDrawObj>
2331 return maAnchoredDrawObj
.AnchorFrame();
2334 void SwDrawVirtObj::RemoveFromWriterLayout()
2336 // remove contact object from frame for 'virtual' drawing object
2337 // #i26791# - use new member <maAnchoredDrawObj>
2338 if ( maAnchoredDrawObj
.GetAnchorFrame() )
2340 maAnchoredDrawObj
.AnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
2344 void SwDrawVirtObj::AddToDrawingPage(SwFrame
const& rAnchorFrame
)
2346 // determine 'master'
2347 SdrObject
* pOrgMasterSdrObj
= mrDrawContact
.GetMaster();
2349 // insert 'virtual' drawing object into page, set layer and user call.
2350 SdrPage
* pDrawPg
= pOrgMasterSdrObj
->getSdrPageFromSdrObject();
2351 // default: insert before master object
2352 auto nOrdNum(GetReferencedObj().GetOrdNum());
2354 // maintain invariant that a shape's textbox immediately follows the shape
2355 // also for the multiple SdrDrawVirtObj created for shapes in header/footer
2356 if (SwFrameFormat
const*const pFlyFormat
=
2357 SwTextBoxHelper::getOtherTextBoxFormat(mrDrawContact
.GetFormat(), RES_DRAWFRMFMT
))
2359 // this is for the case when the flyframe SdrVirtObj is created before the draw one
2360 if (SwSortedObjs
const*const pObjs
= rAnchorFrame
.GetDrawObjs())
2362 for (SwAnchoredObject
const*const pAnchoredObj
: *pObjs
)
2364 if (&pAnchoredObj
->GetFrameFormat() == pFlyFormat
)
2366 assert(dynamic_cast<SwFlyFrame
const*>(pAnchoredObj
));
2368 if (pAnchoredObj
->GetDrawObj()->GetOrdNum() >= GetReferencedObj().GetOrdNum())
2370 // This virtual draw object has an associated fly one, but the fly's index
2371 // is not below the masters, fix it up.
2374 pDrawPg
->SetObjectOrdNum(pAnchoredObj
->GetDrawObj()->GetOrdNumDirect(), GetReferencedObj().GetOrdNum());
2378 nOrdNum
= pAnchoredObj
->GetDrawObj()->GetOrdNum();
2379 // the master SdrObj should have the highest index
2380 assert(nOrdNum
< GetReferencedObj().GetOrdNum());
2385 // this happens on initial insertion, the draw object is created first
2386 SAL_INFO_IF(GetReferencedObj().GetOrdNum() == nOrdNum
, "sw", "AddToDrawingPage: cannot find SdrObject for text box's shape");
2389 // #i27030# - apply order number of referenced object
2390 if ( nullptr != pDrawPg
)
2392 // #i27030# - apply order number of referenced object
2393 pDrawPg
->InsertObject(this, nOrdNum
);
2397 pDrawPg
= getSdrPageFromSdrObject();
2400 pDrawPg
->SetObjectOrdNum(GetOrdNumDirect(), nOrdNum
);
2407 SetUserCall( &mrDrawContact
);
2410 void SwDrawVirtObj::RemoveFromDrawingPage()
2412 SetUserCall( nullptr );
2413 if ( getSdrPageFromSdrObject() )
2415 getSdrPageFromSdrObject()->RemoveObject( GetOrdNum() );
2419 /// Is 'virtual' drawing object connected to writer layout and to drawing layer?
2420 bool SwDrawVirtObj::IsConnected() const
2422 bool bRetVal
= GetAnchorFrame() &&
2423 ( getSdrPageFromSdrObject() && GetUserCall() );
2428 void SwDrawVirtObj::NbcSetAnchorPos(const Point
& rPnt
)
2430 SdrObject::NbcSetAnchorPos( rPnt
);
2434 // the methods relevant for positioning
2436 const tools::Rectangle
& SwDrawVirtObj::GetCurrentBoundRect() const
2438 if (getOutRectangle().IsEmpty())
2440 const_cast<SwDrawVirtObj
*>(this)->RecalcBoundRect();
2443 return getOutRectangle();
2446 const tools::Rectangle
& SwDrawVirtObj::GetLastBoundRect() const
2448 return getOutRectangle();
2451 Point
SwDrawVirtObj::GetOffset() const
2453 // do NOT use IsEmpty() here, there is already a useful offset
2455 if (getOutRectangle() == tools::Rectangle())
2461 return getOutRectangle().TopLeft() - GetReferencedObj().GetCurrentBoundRect().TopLeft();
2465 void SwDrawVirtObj::SetBoundRectDirty()
2467 // do nothing to not lose model information in aOutRect
2470 void SwDrawVirtObj::RecalcBoundRect()
2472 // #i26791# - switch order of calling <GetOffset()> and
2473 // <ReferencedObj().GetCurrentBoundRect()>, because <GetOffset()> calculates
2474 // its value by the 'BoundRect' of the referenced object.
2476 const Point
aOffset(GetOffset());
2477 setOutRectangle(ReferencedObj().GetCurrentBoundRect() + aOffset
);
2480 basegfx::B2DPolyPolygon
SwDrawVirtObj::TakeXorPoly() const
2482 basegfx::B2DPolyPolygon
aRetval(mxRefObj
->TakeXorPoly());
2483 aRetval
.transform(basegfx::utils::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2488 basegfx::B2DPolyPolygon
SwDrawVirtObj::TakeContour() const
2490 basegfx::B2DPolyPolygon
aRetval(mxRefObj
->TakeContour());
2491 aRetval
.transform(basegfx::utils::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2496 void SwDrawVirtObj::AddToHdlList(SdrHdlList
& rHdlList
) const
2498 SdrHdlList
tmpList(nullptr);
2499 mxRefObj
->AddToHdlList(tmpList
);
2501 size_t cnt
= tmpList
.GetHdlCount();
2502 for(size_t i
=0; i
< cnt
; ++i
)
2504 SdrHdl
* pHdl
= tmpList
.GetHdl(i
);
2505 Point
aP(pHdl
->GetPos() + GetOffset());
2508 tmpList
.MoveTo(rHdlList
);
2511 void SwDrawVirtObj::NbcMove(const Size
& rSiz
)
2513 SdrObject::NbcMove( rSiz
);
2516 void SwDrawVirtObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
2518 mxRefObj
->NbcResize(rRef
- GetOffset(), xFact
, yFact
);
2519 SetBoundAndSnapRectsDirty();
2522 void SwDrawVirtObj::NbcRotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
2524 mxRefObj
->NbcRotate(rRef
- GetOffset(), nAngle
, sn
, cs
);
2525 SetBoundAndSnapRectsDirty();
2528 void SwDrawVirtObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
2530 mxRefObj
->NbcMirror(rRef1
- GetOffset(), rRef2
- GetOffset());
2531 SetBoundAndSnapRectsDirty();
2534 void SwDrawVirtObj::NbcShear(const Point
& rRef
, Degree100 nAngle
, double tn
, bool bVShear
)
2536 mxRefObj
->NbcShear(rRef
- GetOffset(), nAngle
, tn
, bVShear
);
2537 SetBoundAndSnapRectsDirty();
2540 void SwDrawVirtObj::Move(const Size
& rSiz
)
2542 SdrObject::Move( rSiz
);
2545 void SwDrawVirtObj::Resize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bUnsetRelative
)
2547 if(xFact
.GetNumerator() != xFact
.GetDenominator() || yFact
.GetNumerator() != yFact
.GetDenominator())
2549 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2550 mxRefObj
->Resize(rRef
- GetOffset(), xFact
, yFact
, bUnsetRelative
);
2551 SetBoundAndSnapRectsDirty();
2552 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2556 void SwDrawVirtObj::Rotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
2560 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2561 mxRefObj
->Rotate(rRef
- GetOffset(), nAngle
, sn
, cs
);
2562 SetBoundAndSnapRectsDirty();
2563 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2567 void SwDrawVirtObj::Mirror(const Point
& rRef1
, const Point
& rRef2
)
2569 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2570 mxRefObj
->Mirror(rRef1
- GetOffset(), rRef2
- GetOffset());
2571 SetBoundAndSnapRectsDirty();
2572 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2575 void SwDrawVirtObj::Shear(const Point
& rRef
, Degree100 nAngle
, double tn
, bool bVShear
)
2579 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2580 mxRefObj
->Shear(rRef
- GetOffset(), nAngle
, tn
, bVShear
);
2581 SetBoundAndSnapRectsDirty();
2582 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2586 void SwDrawVirtObj::RecalcSnapRect()
2588 aSnapRect
= mxRefObj
->GetSnapRect();
2589 aSnapRect
+= GetOffset();
2592 const tools::Rectangle
& SwDrawVirtObj::GetSnapRect() const
2594 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
= mxRefObj
->GetSnapRect();
2595 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
+= GetOffset();
2600 void SwDrawVirtObj::SetSnapRect(const tools::Rectangle
& rRect
)
2602 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2603 tools::Rectangle
aR(rRect
);
2605 mxRefObj
->SetSnapRect(aR
);
2606 SetBoundAndSnapRectsDirty();
2607 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2610 void SwDrawVirtObj::NbcSetSnapRect(const tools::Rectangle
& rRect
)
2612 tools::Rectangle
aR(rRect
);
2614 SetBoundAndSnapRectsDirty();
2615 mxRefObj
->NbcSetSnapRect(aR
);
2618 const tools::Rectangle
& SwDrawVirtObj::GetLogicRect() const
2620 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
= mxRefObj
->GetLogicRect();
2621 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
+= GetOffset();
2626 void SwDrawVirtObj::SetLogicRect(const tools::Rectangle
& rRect
)
2628 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2629 tools::Rectangle
aR(rRect
);
2631 mxRefObj
->SetLogicRect(aR
);
2632 SetBoundAndSnapRectsDirty();
2633 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2636 void SwDrawVirtObj::NbcSetLogicRect(const tools::Rectangle
& rRect
)
2638 tools::Rectangle
aR(rRect
);
2640 mxRefObj
->NbcSetLogicRect(aR
);
2641 SetBoundAndSnapRectsDirty();
2644 Point
SwDrawVirtObj::GetSnapPoint(sal_uInt32 i
) const
2646 Point
aP(mxRefObj
->GetSnapPoint(i
));
2652 Point
SwDrawVirtObj::GetPoint(sal_uInt32 i
) const
2654 return mxRefObj
->GetPoint(i
) + GetOffset();
2657 void SwDrawVirtObj::NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
)
2661 mxRefObj
->SetPoint(aP
, i
);
2662 SetBoundAndSnapRectsDirty();
2665 bool SwDrawVirtObj::HasTextEdit() const
2667 return mxRefObj
->HasTextEdit();
2670 // override 'layer' methods for 'virtual' drawing object to assure
2671 // that layer of 'virtual' object is the layer of the referenced object.
2672 SdrLayerID
SwDrawVirtObj::GetLayer() const
2674 return GetReferencedObj().GetLayer();
2677 void SwDrawVirtObj::NbcSetLayer(SdrLayerID nLayer
)
2679 ReferencedObj().NbcSetLayer( nLayer
);
2680 SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2683 void SwDrawVirtObj::SetLayer(SdrLayerID nLayer
)
2685 ReferencedObj().SetLayer( nLayer
);
2686 SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2689 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */