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 <drawdoc.hxx>
32 #include <fmtornt.hxx>
33 #include <viewimp.hxx>
34 #include <fmtsrnd.hxx>
35 #include <fmtanchr.hxx>
37 #include <fmtcntnt.hxx>
38 #include <fmtfsize.hxx>
40 #include <pagefrm.hxx>
41 #include <rootfrm.hxx>
42 #include <frmtool.hxx>
44 #include <textboxhelper.hxx>
46 #include <fmtfollowtextflow.hxx>
47 #include <dflyobj.hxx>
48 #include <dcontact.hxx>
49 #include <unodraw.hxx>
50 #include <IDocumentDrawModelAccess.hxx>
51 #include <IDocumentLayoutAccess.hxx>
52 #include <IDocumentState.hxx>
53 #include <IDocumentUndoRedo.hxx>
57 #include <frameformats.hxx>
58 #include <sortedobjs.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
62 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
63 #include <drawinglayer/geometry/viewinformation2d.hxx>
64 #include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
65 #include <com/sun/star/text/WritingMode2.hpp>
69 #include <sal/log.hxx>
71 using namespace ::com::sun::star
;
75 /** unary function used to find a 'virtual' drawing object anchored at a given frame */
76 struct VirtObjAnchoredAtFramePred
78 const SwFrame
* m_pAnchorFrame
;
80 // #i26791# - compare with master frame
81 static const SwFrame
* FindFrame(const SwFrame
* pFrame
)
83 if(!pFrame
|| !pFrame
->IsContentFrame())
85 auto pContentFrame
= static_cast<const SwContentFrame
*>(pFrame
);
86 while(pContentFrame
->IsFollow())
87 pContentFrame
= pContentFrame
->FindMaster();
91 VirtObjAnchoredAtFramePred(const SwFrame
* pAnchorFrame
)
92 : m_pAnchorFrame(FindFrame(pAnchorFrame
))
95 bool operator()(const rtl::Reference
<SwDrawVirtObj
>& rpDrawVirtObj
)
97 return FindFrame(rpDrawVirtObj
->GetAnchorFrame()) == m_pAnchorFrame
;
102 void setContextWritingMode(SdrObject
* pObj
, SwFrame
const * pAnchor
)
104 if(!pObj
|| !pAnchor
)
106 short nWritingDirection
=
107 pAnchor
->IsVertical() ? text::WritingMode2::TB_RL
:
108 pAnchor
->IsRightToLeft() ? text::WritingMode2::RL_TB
:
109 text::WritingMode2::LR_TB
;
110 pObj
->SetContextWritingMode(nWritingDirection
);
114 /** The Get reverse way: seeks the format to the specified object.
115 * If the object is a SwVirtFlyDrawObj then the format of this
117 * Otherwise it is just a simple drawing object. This has a
118 * UserCall and is the client of the searched format.
120 SwFrameFormat
*FindFrameFormat( SdrObject
*pObj
)
122 if (SwVirtFlyDrawObj
* pFlyDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
123 return pFlyDrawObj
->GetFormat();
125 if (SwContact
* pContact
= GetUserCall(pObj
))
126 return pContact
->GetFormat();
131 bool HasWrap( const SdrObject
* pObj
)
135 const SwFrameFormat
* pFormat
= ::FindFrameFormat( pObj
);
138 return css::text::WrapTextMode_THROUGH
!= pFormat
->GetSurround().GetSurround();
145 /// returns the BoundRect _inclusive_ distance of the object.
146 SwRect
GetBoundRectOfAnchoredObj( const SdrObject
* pObj
)
148 SwRect
aRet( pObj
->GetCurrentBoundRect() );
149 // #i68520# - call cache of <SwAnchoredObject>
150 SwContact
* pContact( GetUserCall( pObj
) );
153 const SwAnchoredObject
* pAnchoredObj( pContact
->GetAnchoredObj( pObj
) );
156 aRet
= pAnchoredObj
->GetObjRectWithSpaces();
162 /// Returns the UserCall if applicable from the group object
163 SwContact
* GetUserCall( const SdrObject
* pObj
)
165 for (; pObj
; pObj
= pObj
->getParentSdrObjectFromSdrObject())
167 if (auto pUserCall
= pObj
->GetUserCall())
169 assert(dynamic_cast<SwContact
*>(pUserCall
)
170 && "<::GetUserCall(..)> - wrong type of found object user call.");
171 return static_cast<SwContact
*>(pUserCall
);
177 /// Returns true if the SrdObject is a Marquee-Object (scrolling text)
178 bool IsMarqueeTextObj( const SdrObject
& rObj
)
180 if (SdrInventor::Default
!= rObj
.GetObjInventor() ||
181 SdrObjKind::Text
!= rObj
.GetObjIdentifier())
183 SdrTextAniKind eTKind
= static_cast<const SdrTextObj
&>(rObj
).GetTextAniKind();
184 return ( SdrTextAniKind::Scroll
== eTKind
185 || SdrTextAniKind::Alternate
== eTKind
|| SdrTextAniKind::Slide
== eTKind
);
188 SwContact::SwContact( SwFrameFormat
*pToRegisterIn
) :
189 SwClient( pToRegisterIn
),
193 SwContact::~SwContact()
199 void SwContact::SetInDTOR()
204 /// method to move drawing object to corresponding visible layer
205 void SwContact::MoveObjToVisibleLayer( SdrObject
* _pDrawObj
)
207 // #i46297# - notify background about the arriving of
208 // the object and invalidate its position.
209 const bool bNotify( !GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) );
211 MoveObjToLayer( true, _pDrawObj
);
217 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( _pDrawObj
);
218 assert(pAnchoredObj
);
219 ::setContextWritingMode( _pDrawObj
, pAnchoredObj
->GetAnchorFrameContainingAnchPos() );
220 // Note: as-character anchored objects aren't registered at a page frame and
221 // a notification of its background isn't needed.
222 if ( pAnchoredObj
->GetPageFrame() )
224 ::Notify_Background( _pDrawObj
, pAnchoredObj
->GetPageFrame(),
225 pAnchoredObj
->GetObjRect(), PrepareHint::FlyFrameArrive
, true );
228 pAnchoredObj
->InvalidateObjPos();
231 /// method to move drawing object to corresponding invisible layer - #i18447#
232 void SwContact::MoveObjToInvisibleLayer( SdrObject
* _pDrawObj
)
234 // #i46297# - notify background about the leaving of the object.
235 const bool bNotify( GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) );
237 MoveObjToLayer( false, _pDrawObj
);
242 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( _pDrawObj
);
243 assert(pAnchoredObj
);
244 // Note: as-character anchored objects aren't registered at a page frame and
245 // a notification of its background isn't needed.
246 if (pAnchoredObj
->GetPageFrame())
248 ::Notify_Background( _pDrawObj
, pAnchoredObj
->GetPageFrame(),
249 pAnchoredObj
->GetObjRect(), PrepareHint::FlyFrameLeave
, true );
254 /** method to move object to visible/invisible layer - #i18447#
256 implementation for the public method <MoveObjToVisibleLayer(..)>
257 and <MoveObjToInvisibleLayer(..)>
259 void SwContact::MoveObjToLayer( const bool _bToVisible
,
260 SdrObject
* _pDrawObj
)
264 OSL_FAIL( "SwDrawContact::MoveObjToLayer(..) - no drawing object!" );
268 if ( !GetRegisteredIn() )
270 OSL_FAIL( "SwDrawContact::MoveObjToLayer(..) - no drawing frame format!" );
274 const IDocumentDrawModelAccess
& rIDDMA
= static_cast<SwFrameFormat
*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
276 SdrLayerID nToHellLayerId
=
277 _bToVisible
? rIDDMA
.GetHellId() : rIDDMA
.GetInvisibleHellId();
278 SdrLayerID nToHeavenLayerId
=
279 _bToVisible
? rIDDMA
.GetHeavenId() : rIDDMA
.GetInvisibleHeavenId();
280 SdrLayerID nToControlLayerId
=
281 _bToVisible
? rIDDMA
.GetControlsId() : rIDDMA
.GetInvisibleControlsId();
282 SdrLayerID nFromHellLayerId
=
283 _bToVisible
? rIDDMA
.GetInvisibleHellId() : rIDDMA
.GetHellId();
284 SdrLayerID nFromHeavenLayerId
=
285 _bToVisible
? rIDDMA
.GetInvisibleHeavenId() : rIDDMA
.GetHeavenId();
286 SdrLayerID nFromControlLayerId
=
287 _bToVisible
? rIDDMA
.GetInvisibleControlsId() : rIDDMA
.GetControlsId();
289 if ( dynamic_cast<const SdrObjGroup
*>( _pDrawObj
) != nullptr )
291 // determine layer for group object
293 // proposed layer of a group object is the hell layer
294 SdrLayerID nNewLayerId
= nToHellLayerId
;
295 if ( ::CheckControlLayer( _pDrawObj
) )
297 // it has to be the control layer, if one of the member
299 nNewLayerId
= nToControlLayerId
;
301 else if ( _pDrawObj
->GetLayer() == rIDDMA
.GetHeavenId() ||
302 _pDrawObj
->GetLayer() == rIDDMA
.GetInvisibleHeavenId() )
304 // it has to be the heaven layer, if method <GetLayer()> reveals
306 nNewLayerId
= nToHeavenLayerId
;
308 // set layer at group object, but do *not* broadcast and
309 // no propagation to the members.
310 // Thus, call <NbcSetLayer(..)> at super class
311 _pDrawObj
->SdrObject::NbcSetLayer( nNewLayerId
);
314 // call method recursively for group object members
315 const SdrObjList
* pLst
=
316 static_cast<SdrObjGroup
*>(_pDrawObj
)->GetSubList();
319 for (const rtl::Reference
<SdrObject
>& pObj
: *pLst
)
321 MoveObjToLayer( _bToVisible
, pObj
.get() );
327 const SdrLayerID nLayerIdOfObj
= _pDrawObj
->GetLayer();
328 if ( nLayerIdOfObj
== nFromHellLayerId
)
330 _pDrawObj
->SetLayer( nToHellLayerId
);
332 else if ( nLayerIdOfObj
== nFromHeavenLayerId
)
334 _pDrawObj
->SetLayer( nToHeavenLayerId
);
336 else if ( nLayerIdOfObj
== nFromControlLayerId
)
338 _pDrawObj
->SetLayer( nToControlLayerId
);
343 /// get minimum order number of anchored objects handled by with contact
344 sal_uInt32
SwContact::GetMinOrdNum() const
346 sal_uInt32
nMinOrdNum( SAL_MAX_UINT32
);
348 std::vector
< SwAnchoredObject
* > aObjs
;
349 GetAnchoredObjs( aObjs
);
351 while ( !aObjs
.empty() )
353 sal_uInt32 nTmpOrdNum
= aObjs
.back()->GetDrawObj()->GetOrdNum();
355 if ( nTmpOrdNum
< nMinOrdNum
)
357 nMinOrdNum
= nTmpOrdNum
;
363 OSL_ENSURE( nMinOrdNum
!= SAL_MAX_UINT32
,
364 "<SwContact::GetMinOrdNum()> - no order number found." );
368 /// get maximum order number of anchored objects handled by with contact
369 sal_uInt32
SwContact::GetMaxOrdNum() const
371 sal_uInt32
nMaxOrdNum( 0 );
373 std::vector
< SwAnchoredObject
* > aObjs
;
374 GetAnchoredObjs( aObjs
);
376 while ( !aObjs
.empty() )
378 sal_uInt32 nTmpOrdNum
= aObjs
.back()->GetDrawObj()->GetOrdNum();
380 if ( nTmpOrdNum
> nMaxOrdNum
)
382 nMaxOrdNum
= nTmpOrdNum
;
393 Point
lcl_GetWW8Pos(SwAnchoredObject
const * pAnchoredObj
, const bool bFollowTextFlow
, sw::WW8AnchorConv
& reConv
)
397 case sw::WW8AnchorConv::CONV2PG
:
399 bool bRelToTableCell(false);
400 Point
aPos(pAnchoredObj
->GetRelPosToPageFrame(bFollowTextFlow
, bRelToTableCell
));
402 reConv
= sw::WW8AnchorConv::RELTOTABLECELL
;
405 case sw::WW8AnchorConv::CONV2COL_OR_PARA
:
406 return pAnchoredObj
->GetRelPosToAnchorFrame();
407 case sw::WW8AnchorConv::CONV2CHAR
:
408 return pAnchoredObj
->GetRelPosToChar();
409 case sw::WW8AnchorConv::CONV2LINE
:
410 return pAnchoredObj
->GetRelPosToLine();
416 void SwContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
418 // this does not call SwClient::SwClientNotify and thus doesn't handle RES_OBJECTDYING as usual. Is this intentional?
419 if (rHint
.GetId() == SfxHintId::SwFindSdrObject
)
421 auto pFindSdrObjectHint
= static_cast<const sw::FindSdrObjectHint
*>(&rHint
);
422 if(!pFindSdrObjectHint
->m_rpObject
)
423 pFindSdrObjectHint
->m_rpObject
= GetMaster();
425 else if (rHint
.GetId() == SfxHintId::SwWW8AnchorConv
)
427 auto pWW8AnchorConvHint
= static_cast<const sw::WW8AnchorConvHint
*>(&rHint
);
428 // determine anchored object
429 SwAnchoredObject
* pAnchoredObj(nullptr);
431 std::vector
<SwAnchoredObject
*> aAnchoredObjs
;
432 GetAnchoredObjs(aAnchoredObjs
);
433 if(!aAnchoredObjs
.empty())
434 pAnchoredObj
= aAnchoredObjs
.front();
436 // no anchored object found. Thus, the needed layout information can't
437 // be determined. --> no conversion
440 // no conversion for anchored drawing object, which aren't attached to an
442 // This is the case for drawing objects, which are anchored inside a page
443 // header/footer of an *unused* page style.
444 if(dynamic_cast<SwAnchoredDrawObject
*>(pAnchoredObj
) && !pAnchoredObj
->GetAnchorFrame())
446 const bool bFollowTextFlow
= static_cast<const SwFrameFormat
&>(rMod
).GetFollowTextFlow().GetValue();
447 sw::WW8AnchorConvResult
& rResult(pWW8AnchorConvHint
->m_rResult
);
448 // No distinction between layout directions, because of missing
449 // information about WW8 in vertical layout.
450 rResult
.m_aPos
.setX(lcl_GetWW8Pos(pAnchoredObj
, bFollowTextFlow
, rResult
.m_eHoriConv
).getX());
451 rResult
.m_aPos
.setY(lcl_GetWW8Pos(pAnchoredObj
, bFollowTextFlow
, rResult
.m_eVertConv
).getY());
452 rResult
.m_bConverted
= true;
457 SwFlyDrawContact::SwFlyDrawContact(
458 SwFlyFrameFormat
*pToRegisterIn
,
459 SdrModel
& rTargetModel
)
460 : SwContact(pToRegisterIn
),
461 mpMasterObj(new SwFlyDrawObj(rTargetModel
))
463 // #i26791# - class <SwFlyDrawContact> contains the 'master'
464 // drawing object of type <SwFlyDrawObj> on its own.
465 mpMasterObj
->SetOrdNum( 0xFFFFFFFE );
466 mpMasterObj
->SetUserCall( this );
469 SwFlyDrawContact::~SwFlyDrawContact()
473 mpMasterObj
->SetUserCall( nullptr );
474 if ( mpMasterObj
->getSdrPageFromSdrObject() )
475 mpMasterObj
->getSdrPageFromSdrObject()->RemoveObject( mpMasterObj
->GetOrdNum() );
479 sal_uInt32
SwFlyDrawContact::GetOrdNumForNewRef(const SwFlyFrame
* pFly
,
480 SwFrame
const& rAnchorFrame
)
482 // maintain invariant that a shape's textbox immediately follows the shape
483 // also for the multiple SdrVirtObj created for shapes in header/footer
484 if (SwFrameFormat
const*const pDrawFormat
=
485 SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT
))
487 // assume that the draw SdrVirtObj is always created before the flyframe one
488 if (SwSortedObjs
const*const pObjs
= rAnchorFrame
.GetDrawObjs())
490 for (SwAnchoredObject
const*const pAnchoredObj
: *pObjs
)
492 if (pAnchoredObj
->GetFrameFormat() == pDrawFormat
)
494 return pAnchoredObj
->GetDrawObj()->GetOrdNum() + 1;
498 // if called from AppendObjs(), this is a problem; if called from lcl_SetFlyFrameAttr() it's not
499 SAL_INFO("sw", "GetOrdNumForNewRef: cannot find SdrObject for text box's shape");
501 // search for another Writer fly frame registered at same frame format
502 SwIterator
<SwFlyFrame
,SwFormat
> aIter(*GetFormat());
503 const SwFlyFrame
* pFlyFrame(nullptr);
504 for(pFlyFrame
= aIter
.First(); pFlyFrame
; pFlyFrame
= aIter
.Next())
506 if(pFlyFrame
!= pFly
)
512 // another Writer fly frame found. Take its order number
513 return pFlyFrame
->GetVirtDrawObj()->GetOrdNum();
515 // no other Writer fly frame found. Take order number of 'master' object
516 // #i35748# - use method <GetOrdNumDirect()> instead
517 // of method <GetOrdNum()> to avoid a recalculation of the order number,
518 // which isn't intended.
519 return GetMaster()->GetOrdNumDirect();
522 SwVirtFlyDrawObj
* SwFlyDrawContact::CreateNewRef(SwFlyFrame
* pFly
,
523 SwFlyFrameFormat
* pFormat
, SwFrame
const& rAnchorFrame
)
525 // Find ContactObject from the Format. If there's already one, we just
526 // need to create a new Ref, else we create the Contact now.
528 IDocumentDrawModelAccess
& rIDDMA
= pFormat
->getIDocumentDrawModelAccess();
529 SwFlyDrawContact
* pContact
= pFormat
->GetOrCreateContact();
530 rtl::Reference
<SwVirtFlyDrawObj
> pDrawObj(
531 new SwVirtFlyDrawObj(
532 pContact
->GetMaster()->getSdrModelFromSdrObject(),
533 *pContact
->GetMaster(),
535 pDrawObj
->SetUserCall(pContact
);
537 // The Reader creates the Masters and inserts them into the Page in
538 // order to transport the z-order.
539 // After creating the first Reference the Masters are removed from the
540 // List and are not important anymore.
541 SdrPage
* pPg
= pContact
->GetMaster()->getSdrPageFromSdrObject();
544 const size_t nOrdNum
= pContact
->GetMaster()->GetOrdNum();
545 pPg
->ReplaceObject(pDrawObj
.get(), nOrdNum
);
547 // #i27030# - insert new <SwVirtFlyDrawObj> instance
548 // into drawing page with correct order number
550 rIDDMA
.GetDrawModel()->GetPage(0)->InsertObject(pDrawObj
.get(), pContact
->GetOrdNumForNewRef(pFly
, rAnchorFrame
));
551 // #i38889# - assure, that new <SwVirtFlyDrawObj> instance
552 // is in a visible layer.
553 pContact
->MoveObjToVisibleLayer(pDrawObj
.get());
554 return pDrawObj
.get();
558 const SwAnchoredObject
* SwFlyDrawContact::GetAnchoredObj(const SdrObject
* pSdrObj
) const
561 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(pSdrObj
) != nullptr);
562 assert(GetUserCall(pSdrObj
) == this &&
563 "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belong to this contact");
565 const SwAnchoredObject
*const pRetAnchoredObj
=
566 static_cast<const SwVirtFlyDrawObj
*>(pSdrObj
)->GetFlyFrame();
568 return pRetAnchoredObj
;
571 SwAnchoredObject
* SwFlyDrawContact::GetAnchoredObj(SdrObject
*const pSdrObj
)
573 return const_cast<SwAnchoredObject
*>(const_cast<SwFlyDrawContact
const*>(this)->GetAnchoredObj(pSdrObj
));
576 SdrObject
* SwFlyDrawContact::GetMaster()
578 return mpMasterObj
.get();
582 * @note Overriding method to control Writer fly frames, which are linked, and
583 * to assure that all objects anchored at/inside the Writer fly frame are
586 void SwFlyDrawContact::MoveObjToVisibleLayer( SdrObject
* _pDrawObj
)
588 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(_pDrawObj
) != nullptr);
590 if ( GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) )
596 SwFlyFrame
* pFlyFrame
= static_cast<SwVirtFlyDrawObj
*>(_pDrawObj
)->GetFlyFrame();
598 // #i44464# - consider, that Writer fly frame content
599 // already exists - (e.g. WW8 document is inserted into an existing document).
600 if ( !pFlyFrame
->Lower() )
602 pFlyFrame
->InsertColumns();
603 pFlyFrame
->Chain( pFlyFrame
->AnchorFrame() );
604 pFlyFrame
->InsertCnt();
606 if ( pFlyFrame
->GetDrawObjs() )
608 for (SwAnchoredObject
* i
: *pFlyFrame
->GetDrawObjs())
610 // #i28701# - consider type of objects in sorted object list.
611 SdrObject
* pObj
= i
->DrawObj();
612 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
613 pContact
->MoveObjToVisibleLayer( pObj
);
617 // make fly frame visible
618 SwContact::MoveObjToVisibleLayer( _pDrawObj
);
622 * @note Override method to control Writer fly frames, which are linked, and
623 * to assure that all objects anchored at/inside the Writer fly frame are
624 * also made invisible.
626 void SwFlyDrawContact::MoveObjToInvisibleLayer( SdrObject
* _pDrawObj
)
628 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(_pDrawObj
) != nullptr);
630 if ( !GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) )
636 SwFlyFrame
* pFlyFrame
= static_cast<SwVirtFlyDrawObj
*>(_pDrawObj
)->GetFlyFrame();
638 pFlyFrame
->Unchain();
639 pFlyFrame
->DeleteCnt();
640 if ( pFlyFrame
->GetDrawObjs() )
642 for (SwAnchoredObject
* i
: *pFlyFrame
->GetDrawObjs())
644 // #i28701# - consider type of objects in sorted object list.
645 SdrObject
* pObj
= i
->DrawObj();
646 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
647 pContact
->MoveObjToInvisibleLayer( pObj
);
651 // make fly frame invisible
652 SwContact::MoveObjToInvisibleLayer( _pDrawObj
);
655 /// get data collection of anchored objects, handled by with contact
656 void SwFlyDrawContact::GetAnchoredObjs( std::vector
<SwAnchoredObject
*>& _roAnchoredObjs
) const
658 const SwFrameFormat
* pFormat
= GetFormat();
659 SwFlyFrame::GetAnchoredObjects( _roAnchoredObjs
, *pFormat
);
661 void SwFlyDrawContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
663 SwContact::SwClientNotify(rMod
, rHint
);
664 if(rHint
.GetId() == SfxHintId::SwGetZOrder
)
666 auto pGetZOrdnerHint
= static_cast<const sw::GetZOrderHint
*>(&rHint
);
668 // This also needs to work when no layout exists. Thus, for
669 // FlyFrames an alternative method is used now in that case.
670 auto pFormat(dynamic_cast<const SwFrameFormat
*>(&rMod
));
671 if (pFormat
&& pFormat
->Which() == RES_FLYFRMFMT
&& !pFormat
->getIDocumentLayoutAccess().GetCurrentViewShell())
672 pGetZOrdnerHint
->m_rnZOrder
= GetMaster()->GetOrdNum();
678 bool CheckControlLayer( const SdrObject
*pObj
)
680 if ( SdrInventor::FmForm
== pObj
->GetObjInventor() )
682 if (const SdrObjGroup
*pObjGroup
= dynamic_cast<const SdrObjGroup
*>(pObj
))
684 const SdrObjList
*pLst
= pObjGroup
->GetSubList();
685 for (const rtl::Reference
<SdrObject
>& pChildObj
: *pLst
)
687 if ( ::CheckControlLayer( pChildObj
.get() ) )
689 // #i18447# - return correct value ;-)
697 SwDrawContact::SwDrawContact( SwFrameFormat
* pToRegisterIn
, SdrObject
* pObj
) :
698 SwContact( pToRegisterIn
),
699 mbMasterObjCleared( false ),
700 mbDisconnectInProgress( false ),
701 mbUserCallActive( false ),
702 // Note: value of <meEventTypeOfCurrentUserCall> isn't of relevance, because
703 // <mbUserCallActive> is false.
704 meEventTypeOfCurrentUserCall( SdrUserCallType::MoveOnly
)
706 // --> #i33909# - assure, that drawing object is inserted
707 // in the drawing page.
708 if ( !pObj
->IsInserted() )
710 pToRegisterIn
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
711 InsertObject( pObj
, pObj
->GetOrdNumDirect() );
714 // Controls have to be always in the Control-Layer. This is also true for
715 // group objects, if they contain controls.
716 if ( ::CheckControlLayer( pObj
) )
718 // set layer of object to corresponding invisible layer.
719 pObj
->SetLayer( pToRegisterIn
->getIDocumentDrawModelAccess().GetInvisibleControlsId() );
723 pObj
->SetUserCall( this );
724 maAnchoredDrawObj
.SetDrawObj( *pObj
);
726 // if there already exists an SwXShape for the object, ensure it knows about us, and the SdrObject
728 SwXShape::AddExistingShapeToFormat( *pObj
);
731 SwDrawContact::~SwDrawContact()
735 DisconnectFromLayout();
737 // remove 'master' from drawing page
738 RemoveMasterFromDrawPage();
740 // remove and destroy 'virtual' drawing objects.
743 if ( !mbMasterObjCleared
)
744 maAnchoredDrawObj
.ClearDrawObj();
747 void SwDrawContact::GetTextObjectsFromFormat(std::list
<SdrTextObj
*>& o_rTextObjects
, SwDoc
& rDoc
)
749 for(sw::SpzFrameFormat
* pFly
: *rDoc
.GetSpzFrameFormats())
751 if(pFly
->Which() == RES_DRAWFRMFMT
) // ie. SwDrawFrameFormat*
752 pFly
->CallSwClientNotify(sw::CollectTextObjectsHint(o_rTextObjects
));
757 const SwAnchoredObject
* SwDrawContact::GetAnchoredObj(const SdrObject
* pSdrObj
) const
759 // handle default parameter value
762 pSdrObj
= GetMaster();
766 assert(dynamic_cast<const SwDrawVirtObj
*>(pSdrObj
) != nullptr ||
767 dynamic_cast<const SdrVirtObj
*>(pSdrObj
) == nullptr);
768 assert((GetUserCall(pSdrObj
) == this ||
769 pSdrObj
== GetMaster()) &&
770 "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
772 const SwAnchoredObject
* pRetAnchoredObj
= nullptr;
774 if (auto pVirtObj
= dynamic_cast<const SwDrawVirtObj
*>(pSdrObj
))
776 pRetAnchoredObj
= &(pVirtObj
->GetAnchoredObj());
780 assert(dynamic_cast<const SdrVirtObj
*>(pSdrObj
) == nullptr);
781 pRetAnchoredObj
= &maAnchoredDrawObj
;
784 return pRetAnchoredObj
;
787 SwAnchoredObject
* SwDrawContact::GetAnchoredObj(SdrObject
*const pSdrObj
)
789 return const_cast<SwAnchoredObject
*>(const_cast<SwDrawContact
const*>(this)->GetAnchoredObj(pSdrObj
));
792 SdrObject
* SwDrawContact::GetMaster()
794 return !mbMasterObjCleared
795 ? maAnchoredDrawObj
.DrawObj()
799 const SwFrame
* SwDrawContact::GetAnchorFrame( const SdrObject
* _pDrawObj
) const
801 const SwFrame
* pAnchorFrame
= nullptr;
803 _pDrawObj
== GetMaster() ||
804 ( !_pDrawObj
->GetUserCall() &&
805 GetUserCall( _pDrawObj
) == this ) )
807 pAnchorFrame
= maAnchoredDrawObj
.GetAnchorFrame();
811 assert(dynamic_cast<SwDrawVirtObj
const*>(_pDrawObj
) != nullptr);
812 pAnchorFrame
= static_cast<const SwDrawVirtObj
*>(_pDrawObj
)->GetAnchorFrame();
818 SwFrame
* SwDrawContact::GetAnchorFrame(SdrObject
const *const pDrawObj
)
820 return const_cast<SwFrame
*>(const_cast<SwDrawContact
const*>(this)->GetAnchorFrame(pDrawObj
));
823 /** add a 'virtual' drawing object to drawing page.
825 SwDrawVirtObj
* SwDrawContact::AddVirtObj(SwFrame
const& rAnchorFrame
)
827 maDrawVirtObjs
.push_back(
829 GetMaster()->getSdrModelFromSdrObject(),
832 maDrawVirtObjs
.back()->AddToDrawingPage(rAnchorFrame
);
833 return maDrawVirtObjs
.back().get();
836 /// remove 'virtual' drawing objects and destroy them.
837 void SwDrawContact::RemoveAllVirtObjs()
839 for(auto& rpDrawVirtObj
: maDrawVirtObjs
)
841 // remove and destroy 'virtual object'
842 rpDrawVirtObj
->RemoveFromWriterLayout();
843 rpDrawVirtObj
->RemoveFromDrawingPage();
844 // to break the reference cycle
845 rpDrawVirtObj
->AnchoredObj().ClearDrawObj();
847 maDrawVirtObjs
.clear();
851 /// get drawing object ('master' or 'virtual') by frame.
852 SdrObject
* SwDrawContact::GetDrawObjectByAnchorFrame( const SwFrame
& _rAnchorFrame
)
854 SdrObject
* pRetDrawObj
= nullptr;
856 // #i26791# - compare master frames instead of direct frames
857 const SwFrame
* pProposedAnchorFrame
= &_rAnchorFrame
;
858 if ( pProposedAnchorFrame
->IsContentFrame() )
860 const SwContentFrame
* pTmpFrame
=
861 static_cast<const SwContentFrame
*>( pProposedAnchorFrame
);
862 while ( pTmpFrame
->IsFollow() )
864 pTmpFrame
= pTmpFrame
->FindMaster();
866 pProposedAnchorFrame
= pTmpFrame
;
869 const SwFrame
* pMasterObjAnchorFrame
= GetAnchorFrame();
870 if ( pMasterObjAnchorFrame
&& pMasterObjAnchorFrame
->IsContentFrame() )
872 const SwContentFrame
* pTmpFrame
=
873 static_cast<const SwContentFrame
*>( pMasterObjAnchorFrame
);
874 while ( pTmpFrame
->IsFollow() )
876 pTmpFrame
= pTmpFrame
->FindMaster();
878 pMasterObjAnchorFrame
= pTmpFrame
;
881 if ( pMasterObjAnchorFrame
&& pMasterObjAnchorFrame
== pProposedAnchorFrame
)
883 pRetDrawObj
= GetMaster();
887 const auto ppFoundVirtObj(std::find_if(maDrawVirtObjs
.begin(), maDrawVirtObjs
.end(),
888 VirtObjAnchoredAtFramePred(pProposedAnchorFrame
)));
889 if(ppFoundVirtObj
!= maDrawVirtObjs
.end())
890 pRetDrawObj
= ppFoundVirtObj
->get();
896 void SwDrawContact::NotifyBackgroundOfAllVirtObjs(const tools::Rectangle
* pOldBoundRect
)
898 for(const auto& rpDrawVirtObj
: maDrawVirtObjs
)
900 SwDrawVirtObj
* pDrawVirtObj(rpDrawVirtObj
.get());
901 if ( pDrawVirtObj
->GetAnchorFrame() )
903 // #i34640# - determine correct page frame
904 SwPageFrame
* pPage
= pDrawVirtObj
->AnchoredObj().FindPageFrameOfAnchor();
905 if( pOldBoundRect
&& pPage
)
907 SwRect
aOldRect( *pOldBoundRect
);
908 aOldRect
.Pos() += pDrawVirtObj
->GetOffset();
909 if( aOldRect
.HasArea() )
910 ::Notify_Background( pDrawVirtObj
, pPage
,
911 aOldRect
, PrepareHint::FlyFrameLeave
,true);
913 // #i34640# - include spacing for wrapping
914 SwRect
aRect( pDrawVirtObj
->GetAnchoredObj().GetObjRectWithSpaces() );
915 if (aRect
.HasArea() && pPage
)
917 SwPageFrame
* pPg
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aRect
, pPage
)));
919 ::Notify_Background( pDrawVirtObj
, pPg
, aRect
,
920 PrepareHint::FlyFrameArrive
, true );
922 ::ClrContourCache( pDrawVirtObj
);
927 /// local method to notify the background for a drawing object - #i26791#
928 static void lcl_NotifyBackgroundOfObj( SwDrawContact
const & _rDrawContact
,
929 const SdrObject
& _rObj
,
930 const tools::Rectangle
* _pOldObjRect
)
933 SwAnchoredObject
* pAnchoredObj
=
934 const_cast<SwAnchoredObject
*>(_rDrawContact
.GetAnchoredObj( &_rObj
));
935 if ( !(pAnchoredObj
&& pAnchoredObj
->GetAnchorFrame()) )
938 // #i34640# - determine correct page frame
939 SwPageFrame
* pPageFrame
= pAnchoredObj
->FindPageFrameOfAnchor();
940 if( _pOldObjRect
&& pPageFrame
)
942 SwRect
aOldRect( *_pOldObjRect
);
943 if( aOldRect
.HasArea() )
945 // #i34640# - determine correct page frame
946 SwPageFrame
* pOldPageFrame
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aOldRect
, pPageFrame
)));
947 ::Notify_Background( &_rObj
, pOldPageFrame
, aOldRect
,
948 PrepareHint::FlyFrameLeave
, true);
951 // #i34640# - include spacing for wrapping
952 SwRect
aNewRect( pAnchoredObj
->GetObjRectWithSpaces() );
953 if( aNewRect
.HasArea() && pPageFrame
)
955 pPageFrame
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aNewRect
, pPageFrame
)));
956 ::Notify_Background( &_rObj
, pPageFrame
, aNewRect
,
957 PrepareHint::FlyFrameArrive
, true );
959 ClrContourCache( &_rObj
);
962 void SwDrawContact::Changed( const SdrObject
& rObj
,
963 SdrUserCallType eType
,
964 const tools::Rectangle
& rOldBoundRect
)
966 // #i26791# - no event handling, if existing <SwViewShell>
967 // is in construction
968 SwDoc
* pDoc
= GetFormat()->GetDoc();
969 if ( pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() &&
970 pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell()->IsInConstructor() )
976 // no event handling, if document is in destruction.
977 // Exception: It's the SdrUserCallType::Delete event
978 if ( pDoc
->IsInDtor() && eType
!= SdrUserCallType::Delete
)
983 //Put on Action, but not if presently anywhere an action runs.
984 bool bHasActions(true);
985 SwRootFrame
*pTmpRoot
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
986 if ( pTmpRoot
&& pTmpRoot
->IsCallbackActionEnabled() )
988 SwViewShell
* const pSh
= pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
991 for(SwViewShell
& rShell
: pSh
->GetRingContainer() )
993 if ( rShell
.Imp()->IsAction() || rShell
.Imp()->IsIdleAction() )
1002 pTmpRoot
->StartAllAction();
1004 SdrObjUserCall::Changed( rObj
, eType
, rOldBoundRect
);
1005 Changed_( rObj
, eType
, &rOldBoundRect
); //Attention, possibly suicidal!
1008 pTmpRoot
->EndAllAction();
1011 /// helper class for method <SwDrawContact::Changed_(..)> for handling nested
1012 /// <SdrObjUserCall> events
1013 class NestedUserCallHdl
1016 SwDrawContact
* mpDrawContact
;
1017 bool mbParentUserCallActive
;
1018 SdrUserCallType meParentUserCallEventType
;
1021 NestedUserCallHdl( SwDrawContact
* _pDrawContact
,
1022 SdrUserCallType _eEventType
)
1023 : mpDrawContact( _pDrawContact
),
1024 mbParentUserCallActive( _pDrawContact
->mbUserCallActive
),
1025 meParentUserCallEventType( _pDrawContact
->meEventTypeOfCurrentUserCall
)
1027 mpDrawContact
->mbUserCallActive
= true;
1028 mpDrawContact
->meEventTypeOfCurrentUserCall
= _eEventType
;
1031 ~NestedUserCallHdl()
1033 if ( mpDrawContact
)
1035 mpDrawContact
->mbUserCallActive
= mbParentUserCallActive
;
1036 mpDrawContact
->meEventTypeOfCurrentUserCall
= meParentUserCallEventType
;
1040 void DrawContactDeleted()
1042 mpDrawContact
= nullptr;
1045 bool IsNestedUserCall() const
1047 return mbParentUserCallActive
;
1050 void AssertNestedUserCall()
1052 if ( !IsNestedUserCall() )
1055 bool bTmpAssert( true );
1056 // Currently its known, that a nested event SdrUserCallType::Resize
1057 // could occur during parent user call SdrUserCallType::Inserted,
1058 // SdrUserCallType::Delete and SdrUserCallType::Resize for edge objects.
1059 // Also possible are nested SdrUserCallType::ChildResize events for
1061 // Thus, assert all other combinations
1062 if ( ( meParentUserCallEventType
== SdrUserCallType::Inserted
||
1063 meParentUserCallEventType
== SdrUserCallType::Delete
||
1064 meParentUserCallEventType
== SdrUserCallType::Resize
) &&
1065 mpDrawContact
->meEventTypeOfCurrentUserCall
== SdrUserCallType::Resize
)
1069 else if ( meParentUserCallEventType
== SdrUserCallType::ChildResize
&&
1070 mpDrawContact
->meEventTypeOfCurrentUserCall
== SdrUserCallType::ChildResize
)
1077 OSL_FAIL( "<SwDrawContact::Changed_(..)> - unknown nested <UserCall> event. This is serious." );
1082 /// Notify the format's textbox that it should reconsider its position / size.
1083 static void lcl_textBoxSizeNotify(SwFrameFormat
* pFormat
)
1085 if (SwTextBoxHelper::isTextBox(pFormat
, RES_DRAWFRMFMT
))
1087 // Just notify the textbox that the size has changed, the actual object size is not interesting.
1088 SfxItemSetFixed
<RES_FRM_SIZE
, RES_FRM_SIZE
> aResizeSet(pFormat
->GetDoc()->GetAttrPool());
1089 SwFormatFrameSize aSize
;
1090 aResizeSet
.Put(aSize
);
1091 SwTextBoxHelper::syncFlyFrameAttr(*pFormat
, aResizeSet
, pFormat
->FindRealSdrObject());
1095 // !!!ATTENTION!!! The object may commit suicide!!!
1097 void SwDrawContact::Changed_( const SdrObject
& rObj
,
1098 SdrUserCallType eType
,
1099 const tools::Rectangle
* pOldBoundRect
)
1101 // suppress handling of nested <SdrObjUserCall> events
1102 NestedUserCallHdl
aNestedUserCallHdl( this, eType
);
1103 if ( aNestedUserCallHdl
.IsNestedUserCall() )
1105 aNestedUserCallHdl
.AssertNestedUserCall();
1108 // do *not* notify, if document is destructing
1109 // #i35912# - do *not* notify for as-character anchored
1112 // improvement: determine as-character anchored object flag only once.
1113 const bool bAnchoredAsChar
= ObjAnchoredAsChar();
1114 const bool bNotify
= !(GetFormat()->GetDoc()->IsInDtor()) &&
1115 ( css::text::WrapTextMode_THROUGH
!= GetFormat()->GetSurround().GetSurround() ) &&
1119 case SdrUserCallType::Delete
:
1123 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1124 // --> #i36181# - background of 'virtual'
1125 // drawing objects have also been notified.
1126 NotifyBackgroundOfAllVirtObjs( pOldBoundRect
);
1128 DisconnectFromLayout( false );
1129 mbMasterObjCleared
= true;
1131 // --> #i65784# Prevent memory corruption
1132 aNestedUserCallHdl
.DrawContactDeleted();
1135 case SdrUserCallType::Inserted
:
1137 if ( mbDisconnectInProgress
)
1139 OSL_FAIL( "<SwDrawContact::Changed_(..)> - Insert event during disconnection from layout is invalid." );
1146 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1151 case SdrUserCallType::Removed
:
1155 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1157 DisconnectFromLayout( false );
1160 case SdrUserCallType::ChildInserted
:
1161 case SdrUserCallType::ChildRemoved
:
1164 // force layer of controls for group objects containing control objects
1165 if(dynamic_cast< SdrObjGroup
* >(maAnchoredDrawObj
.DrawObj()))
1167 if(::CheckControlLayer(maAnchoredDrawObj
.DrawObj()))
1169 const IDocumentDrawModelAccess
& rIDDMA
= static_cast<SwFrameFormat
*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
1170 const SdrLayerID
aCurrentLayer(maAnchoredDrawObj
.DrawObj()->GetLayer());
1171 const SdrLayerID
aControlLayerID(rIDDMA
.GetControlsId());
1172 const SdrLayerID
aInvisibleControlLayerID(rIDDMA
.GetInvisibleControlsId());
1174 if(aCurrentLayer
!= aControlLayerID
&& aCurrentLayer
!= aInvisibleControlLayerID
)
1176 if ( aCurrentLayer
== rIDDMA
.GetInvisibleHellId() ||
1177 aCurrentLayer
== rIDDMA
.GetInvisibleHeavenId() )
1179 maAnchoredDrawObj
.DrawObj()->SetLayer(aInvisibleControlLayerID
);
1183 maAnchoredDrawObj
.DrawObj()->SetLayer(aControlLayerID
);
1190 case SdrUserCallType::MoveOnly
:
1191 case SdrUserCallType::Resize
:
1192 case SdrUserCallType::ChildMoveOnly
:
1193 case SdrUserCallType::ChildResize
:
1194 case SdrUserCallType::ChildChangeAttr
:
1195 case SdrUserCallType::ChildDelete
:
1197 // #i31698# - improvement
1198 // get instance <SwAnchoredDrawObject> only once
1199 const SwAnchoredDrawObject
* pAnchoredDrawObj
=
1200 static_cast<const SwAnchoredDrawObject
*>( GetAnchoredObj( &rObj
) );
1202 /* protect against NULL pointer dereferencing */
1203 if(!pAnchoredDrawObj
)
1208 // #i26791# - adjust positioning and alignment attributes,
1209 // if positioning of drawing object isn't in progress.
1210 // #i53320# - no adjust of positioning attributes,
1211 // if drawing object isn't positioned.
1212 if ( !pAnchoredDrawObj
->IsPositioningInProgress() &&
1213 !pAnchoredDrawObj
->NotYetPositioned() )
1215 // #i34748# - If no last object rectangle is
1216 // provided by the anchored object, use parameter <pOldBoundRect>.
1217 const tools::Rectangle
& aOldObjRect
= pAnchoredDrawObj
->GetLastObjRect()
1218 ? *(pAnchoredDrawObj
->GetLastObjRect())
1221 // always invalidate object rectangle inclusive spaces
1222 pAnchoredDrawObj
->InvalidateObjRectWithSpaces();
1223 // #i41324# - notify background before
1224 // adjusting position
1227 // #i31573# - correction
1228 // background of given drawing object.
1229 lcl_NotifyBackgroundOfObj( *this, rObj
, &aOldObjRect
);
1231 // #i31698# - determine layout direction
1232 // via draw frame format.
1233 SwFrameFormat::tLayoutDir eLayoutDir
=
1234 pAnchoredDrawObj
->GetFrameFormat()->GetLayoutDir();
1235 // use geometry of drawing object
1236 tools::Rectangle
aObjRect( rObj
.GetSnapRect() );
1237 // If drawing object is a member of a group, the adjustment
1238 // of the positioning and the alignment attributes has to
1239 // be done for the top group object.
1240 if ( rObj
.getParentSdrObjectFromSdrObject() )
1242 const SdrObject
* pGroupObj
= rObj
.getParentSdrObjectFromSdrObject();
1243 while ( pGroupObj
->getParentSdrObjectFromSdrObject() )
1245 pGroupObj
= pGroupObj
->getParentSdrObjectFromSdrObject();
1247 // use geometry of drawing object
1248 aObjRect
= pGroupObj
->GetSnapRect();
1250 SwTextBoxHelper::synchronizeGroupTextBoxProperty(&SwTextBoxHelper::changeAnchor
, GetFormat(), &const_cast<SdrObject
&>(rObj
));
1251 SwTextBoxHelper::synchronizeGroupTextBoxProperty(&SwTextBoxHelper::syncTextBoxSize
, GetFormat(), &const_cast<SdrObject
&>(rObj
));
1254 SwTwips
nXPosDiff(0);
1255 SwTwips
nYPosDiff(0);
1256 switch ( eLayoutDir
)
1258 case SwFrameFormat::HORI_L2R
:
1260 nXPosDiff
= aObjRect
.Left() - aOldObjRect
.Left();
1261 nYPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1264 case SwFrameFormat::HORI_R2L
:
1266 nXPosDiff
= aOldObjRect
.Right() - aObjRect
.Right();
1267 nYPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1270 case SwFrameFormat::VERT_R2L
:
1272 nXPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1273 nYPosDiff
= aOldObjRect
.Right() - aObjRect
.Right();
1278 assert(!"<SwDrawContact::Changed_(..)> - unsupported layout direction");
1281 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
> aSet( GetFormat()->GetDoc()->GetAttrPool() );
1282 const SwFormatVertOrient
& rVert
= GetFormat()->GetVertOrient();
1283 if ( nYPosDiff
!= 0 )
1285 if ( rVert
.GetRelationOrient() == text::RelOrientation::CHAR
||
1286 rVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
1288 nYPosDiff
= -nYPosDiff
;
1290 aSet
.Put( SwFormatVertOrient( rVert
.GetPos()+nYPosDiff
,
1291 text::VertOrientation::NONE
,
1292 rVert
.GetRelationOrient() ) );
1295 const SwFormatHoriOrient
& rHori
= GetFormat()->GetHoriOrient();
1296 if ( !bAnchoredAsChar
&& nXPosDiff
!= 0 )
1298 aSet
.Put( SwFormatHoriOrient( rHori
.GetPos()+nXPosDiff
,
1299 text::HoriOrientation::NONE
,
1300 rHori
.GetRelationOrient() ) );
1304 ( !bAnchoredAsChar
&& nXPosDiff
!= 0 ) )
1306 GetFormat()->GetDoc()->SetFlyFrameAttr( *(GetFormat()), aSet
);
1307 // keep new object rectangle, to avoid multiple
1308 // changes of the attributes by multiple event from
1309 // the drawing layer - e.g. group objects and its members
1310 // #i34748# - use new method
1311 // <SwAnchoredDrawObject::SetLastObjRect(..)>.
1312 const_cast<SwAnchoredDrawObject
*>(pAnchoredDrawObj
)
1313 ->SetLastObjRect( aObjRect
);
1315 else if ( aObjRect
.GetSize() != aOldObjRect
.GetSize() )
1318 // #i35007# - notify anchor frame
1319 // of as-character anchored object
1320 if ( bAnchoredAsChar
)
1322 SwFrame
* pAnchorFrame
= const_cast<SwAnchoredDrawObject
*>(pAnchoredDrawObj
)->AnchorFrame();
1325 pAnchorFrame
->Prepare( PrepareHint::FlyFrameAttributesChanged
, GetFormat() );
1329 lcl_textBoxSizeNotify(GetFormat());
1331 else if (eType
== SdrUserCallType::Resize
)
1332 // Even if the bounding box of the shape didn't change,
1333 // notify about the size change, as an adjustment change
1334 // may affect the size of the underlying textbox.
1335 lcl_textBoxSizeNotify(GetFormat());
1338 // tdf#135198: keep text box together with its shape
1339 const SwPageFrame
* rPageFrame
= pAnchoredDrawObj
->GetPageFrame();
1340 if (rPageFrame
&& rPageFrame
->isFrameAreaPositionValid() && GetFormat()
1341 && GetFormat()->GetOtherTextBoxFormats())
1343 SwDoc
* const pDoc
= GetFormat()->GetDoc();
1345 // avoid Undo creation
1346 ::sw::UndoGuard
const ug(pDoc
->GetIDocumentUndoRedo());
1348 // hide any artificial "changes" made by synchronizing the textbox position
1349 const bool bEnableSetModified
= pDoc
->getIDocumentState().IsEnableSetModified();
1350 pDoc
->getIDocumentState().SetEnableSetModified(false);
1352 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
, RES_ANCHOR
, RES_ANCHOR
>
1353 aSyncSet( pDoc
->GetAttrPool() );
1354 aSyncSet
.Put(GetFormat()->GetHoriOrient());
1355 bool bRelToTableCell(false);
1356 aSyncSet
.Put(SwFormatVertOrient(pAnchoredDrawObj
->GetRelPosToPageFrame(false, bRelToTableCell
).getY(),
1357 text::VertOrientation::NONE
,
1358 text::RelOrientation::PAGE_FRAME
));
1359 aSyncSet
.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE
, rPageFrame
->GetPhyPageNum()));
1361 auto pSdrObj
= const_cast<SdrObject
*>(&rObj
);
1362 if (pSdrObj
!= GetFormat()->FindRealSdrObject())
1364 SfxItemSetFixed
<RES_FRM_SIZE
, RES_FRM_SIZE
> aSet( pDoc
->GetAttrPool() );
1367 aSet
.Put(pSdrObj
->GetMergedItem(RES_FRM_SIZE
));
1368 SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSet
, pSdrObj
);
1370 SwTextBoxHelper::synchronizeGroupTextBoxProperty(
1371 &SwTextBoxHelper::changeAnchor
, GetFormat(),
1372 GetFormat()->FindRealSdrObject());
1373 SwTextBoxHelper::synchronizeGroupTextBoxProperty(
1374 &SwTextBoxHelper::syncTextBoxSize
, GetFormat(),
1375 GetFormat()->FindRealSdrObject());
1378 SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSyncSet
, GetFormat()->FindRealSdrObject());
1380 pDoc
->getIDocumentState().SetEnableSetModified(bEnableSetModified
);
1384 case SdrUserCallType::ChangeAttr
:
1387 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1397 const SwFormatAnchor
* lcl_getAnchorFormat( const SfxPoolItem
& _rItem
)
1399 sal_uInt16 nWhich
= _rItem
.Which();
1400 const SwFormatAnchor
* pAnchorFormat
= nullptr;
1401 if ( RES_ANCHOR
== nWhich
)
1403 pAnchorFormat
= &static_cast<const SwFormatAnchor
&>(_rItem
);
1405 return pAnchorFormat
;
1407 const SwFormatAnchor
* lcl_getAnchorFormat( const SwAttrSetChg
& _rItem
)
1409 return _rItem
.GetChgSet()->GetItemIfSet( RES_ANCHOR
, false );
1413 void SwDrawContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
1415 SwClient::SwClientNotify(rMod
, rHint
); // needed as SwContact::SwClientNotify doesn't explicitly call SwClient::SwClientNotify
1416 SwContact::SwClientNotify(rMod
, rHint
);
1417 if(SfxHintId::SwRemoveUnoObject
== rHint
.GetId())
1421 GetAnchoredObj(nullptr)->ResetLayoutProcessBools();
1423 else if(SfxHintId::SwFormatChange
== rHint
.GetId()
1424 || SfxHintId::SwUpdateAttr
== rHint
.GetId())
1427 GetAnchoredObj(nullptr)->ResetLayoutProcessBools();
1429 else if (rHint
.GetId() == SfxHintId::SwLegacyModify
1430 || rHint
.GetId() == SfxHintId::SwAttrSetChange
1431 || rHint
.GetId() == SfxHintId::SwObjectDying
)
1433 SAL_WARN_IF(mbDisconnectInProgress
, "sw.core", "<SwDrawContact::Modify(..)> called during disconnection.");
1435 const SwFormatAnchor
* pNewAnchorFormat
= nullptr;
1436 const SwFormatAnchor
* pOldAnchorFormat
= nullptr;
1437 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
1439 auto pLegacyHint
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
1440 if (pLegacyHint
->m_pNew
)
1441 pNewAnchorFormat
= lcl_getAnchorFormat(*pLegacyHint
->m_pNew
);
1442 if (pLegacyHint
->m_pOld
)
1443 pOldAnchorFormat
= lcl_getAnchorFormat(*pLegacyHint
->m_pOld
);
1445 else if (rHint
.GetId() == SfxHintId::SwAttrSetChange
)
1447 auto pChangeHint
= static_cast<const sw::AttrSetChangeHint
*>(&rHint
);
1448 if (pChangeHint
->m_pNew
)
1449 pNewAnchorFormat
= lcl_getAnchorFormat(*pChangeHint
->m_pNew
);
1450 if (pChangeHint
->m_pOld
)
1451 pOldAnchorFormat
= lcl_getAnchorFormat(*pChangeHint
->m_pOld
);
1454 if(pNewAnchorFormat
)
1456 // Do not respond to a Reset Anchor!
1457 if(GetFormat()->GetAttrSet().GetItemState(RES_ANCHOR
, false) == SfxItemState::SET
)
1459 // no connect to layout during disconnection
1460 if(!mbDisconnectInProgress
)
1462 // determine old object rectangle of 'master' drawing object
1464 const tools::Rectangle
* pOldRect
= nullptr;
1465 tools::Rectangle aOldRect
;
1466 if(GetAnchorFrame())
1468 // --> #i36181# - include spacing in object
1469 // rectangle for notification.
1470 aOldRect
= maAnchoredDrawObj
.GetObjRectWithSpaces().SVRect();
1471 pOldRect
= &aOldRect
;
1473 // re-connect to layout due to anchor format change
1474 ConnectToLayout(pNewAnchorFormat
);
1475 // notify background of drawing objects
1476 lcl_NotifyBackgroundOfObj(*this, *GetMaster(), pOldRect
);
1477 NotifyBackgroundOfAllVirtObjs(pOldRect
);
1479 if(!pOldAnchorFormat
|| (pOldAnchorFormat
->GetAnchorId() != pNewAnchorFormat
->GetAnchorId()))
1481 if(maAnchoredDrawObj
.DrawObj())
1484 // assure that a ShapePropertyChangeNotifier exists
1485 maAnchoredDrawObj
.DrawObj()->notifyShapePropertyChange(u
"AnchorType"_ustr
);
1488 SAL_WARN("sw.core", "SwDrawContact::Modify: no draw object here?");
1493 DisconnectFromLayout();
1495 // --> #i62875# - no further notification, if not connected to Writer layout
1496 else if ( maAnchoredDrawObj
.GetAnchorFrame() &&
1497 maAnchoredDrawObj
.GetDrawObj()->GetUserCall() )
1499 bool bUpdateSortedObjsList(false);
1500 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
1502 auto pLegacyHint
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
1503 sal_uInt16 nWhich
= pLegacyHint
->m_pNew
? pLegacyHint
->m_pNew
->Which() : 0;
1508 case RES_HORI_ORIENT
:
1509 case RES_VERT_ORIENT
:
1510 case RES_FOLLOW_TEXT_FLOW
: // #i28701# - add attribute 'Follow text flow'
1514 case RES_WRAP_INFLUENCE_ON_OBJPOS
:
1515 // --> #i28701# - on change of wrapping style, hell|heaven layer,
1516 // or wrapping style influence an update of the <SwSortedObjs> list,
1517 // the drawing object is registered in, has to be performed. This is triggered
1518 // by the 1st parameter of method call <InvalidateObjs_(..)>.
1519 bUpdateSortedObjsList
= true;
1522 assert(!"<SwDraw Contact::Modify(..)> - unhandled attribute?");
1525 else if (rHint
.GetId() == SfxHintId::SwAttrSetChange
)
1528 auto pChangeHint
= static_cast<const sw::AttrSetChangeHint
*>(&rHint
);
1529 auto pChgSet
= pChangeHint
->m_pNew
? pChangeHint
->m_pNew
->GetChgSet() : nullptr;
1530 if(pChgSet
&& (pChgSet
->GetItemState(RES_SURROUND
, false) == SfxItemState::SET
||
1531 pChgSet
->GetItemState(RES_OPAQUE
, false) == SfxItemState::SET
||
1532 pChgSet
->GetItemState(RES_WRAP_INFLUENCE_ON_OBJPOS
, false) == SfxItemState::SET
))
1533 bUpdateSortedObjsList
= true;
1535 lcl_NotifyBackgroundOfObj(*this, *GetMaster(), nullptr);
1536 NotifyBackgroundOfAllVirtObjs(nullptr);
1537 InvalidateObjs_(bUpdateSortedObjsList
);
1541 GetAnchoredObj(nullptr)->ResetLayoutProcessBools();
1543 else if (rHint
.GetId() == SfxHintId::SwDrawFrameFormat
)
1545 auto pDrawFrameFormatHint
= static_cast<const sw::DrawFrameFormatHint
*>(&rHint
);
1546 switch(pDrawFrameFormatHint
->m_eId
)
1548 case sw::DrawFrameFormatHintId::DYING
:
1551 case sw::DrawFrameFormatHintId::PREPPASTING
:
1552 MoveObjToVisibleLayer(GetMaster());
1554 case sw::DrawFrameFormatHintId::PREP_INSERT_FLY
:
1555 InsertMasterIntoDrawPage();
1556 // #i40845# - follow-up of #i35635#
1557 // move object to visible layer
1558 MoveObjToVisibleLayer(GetMaster());
1559 // tdf#135661 InsertMasterIntoDrawPage may have created a new
1560 // SwXShape with null m_pFormat; fix that
1561 SwXShape::AddExistingShapeToFormat(*GetMaster());
1563 case sw::DrawFrameFormatHintId::PREP_DELETE_FLY
:
1564 RemoveMasterFromDrawPage();
1566 case sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS
:
1567 case sw::DrawFrameFormatHintId::DELETE_FRAMES
:
1568 DisconnectFromLayout();
1570 case sw::DrawFrameFormatHintId::MAKE_FRAMES
:
1573 case sw::DrawFrameFormatHintId::POST_RESTORE_FLY_ANCHOR
:
1574 GetAnchoredObj(GetMaster())->MakeObjPos();
1580 else if (rHint
.GetId() == SfxHintId::SwCheckDrawFrameFormatLayer
)
1582 auto pCheckDrawFrameFormatLayerHint
= static_cast<const sw::CheckDrawFrameFormatLayerHint
*>(&rHint
);
1583 *(pCheckDrawFrameFormatLayerHint
->m_bCheckControlLayer
) |= (GetMaster() && CheckControlLayer(GetMaster()));
1585 else if (rHint
.GetId() == SfxHintId::SwContactChanged
)
1587 auto pContactChangedHint
= static_cast<const sw::ContactChangedHint
*>(&rHint
);
1588 if(!*pContactChangedHint
->m_ppObject
)
1589 *pContactChangedHint
->m_ppObject
= GetMaster();
1590 auto pObject
= *pContactChangedHint
->m_ppObject
;
1591 Changed(*pObject
, SdrUserCallType::Delete
, pObject
->GetLastBoundRect());
1593 else if (rHint
.GetId() == SfxHintId::SwDrawFormatLayoutCopy
)
1595 auto pDrawFormatLayoutCopyHint
= static_cast<const sw::DrawFormatLayoutCopyHint
*>(&rHint
);
1596 const SwDrawFrameFormat
& rFormat
= static_cast<const SwDrawFrameFormat
&>(rMod
);
1597 rtl::Reference
<SdrObject
> xNewObj
=
1598 pDrawFormatLayoutCopyHint
->m_rDestDoc
.CloneSdrObj(
1600 pDrawFormatLayoutCopyHint
->m_rDestDoc
.IsCopyIsMove() && &pDrawFormatLayoutCopyHint
->m_rDestDoc
== rFormat
.GetDoc());
1602 &pDrawFormatLayoutCopyHint
->m_rDestFormat
, xNewObj
.get() );
1603 // #i49730# - notify draw frame format that position attributes are
1604 // already set, if the position attributes are already set at the
1605 // source draw frame format.
1606 if(rFormat
.IsPosAttrSet())
1607 pDrawFormatLayoutCopyHint
->m_rDestFormat
.PosAttrSet();
1609 else if (rHint
.GetId() == SfxHintId::SwRestoreFlyAnchor
)
1611 auto pRestoreFlyAnchorHint
= static_cast<const sw::RestoreFlyAnchorHint
*>(&rHint
);
1612 SdrObject
* pObj
= GetMaster();
1613 if(GetAnchorFrame() && !pObj
->IsInserted())
1615 auto pDrawModel
= const_cast<SwDrawFrameFormat
&>(static_cast<const SwDrawFrameFormat
&>(rMod
)).GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1617 pDrawModel
->GetPage(0)->InsertObject(pObj
);
1619 pObj
->SetRelativePos(pRestoreFlyAnchorHint
->m_aPos
);
1621 else if (rHint
.GetId() == SfxHintId::SwCreatePortion
)
1623 auto pCreatePortionHint
= static_cast<const sw::CreatePortionHint
*>(&rHint
);
1624 if(*pCreatePortionHint
->m_ppContact
)
1626 *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
1627 if(!GetAnchorFrame())
1629 // No direct positioning needed any more
1631 // Move object to visible layer
1632 MoveObjToVisibleLayer(GetMaster());
1635 else if (rHint
.GetId() == SfxHintId::SwCollectTextObjects
)
1637 auto pCollectTextObjectsHint
= static_cast<const sw::CollectTextObjectsHint
*>(&rHint
);
1638 auto pSdrO
= GetMaster();
1641 if(dynamic_cast<const SdrObjGroup
*>(pSdrO
))
1643 SdrObjListIter
aListIter(*pSdrO
, SdrIterMode::DeepNoGroups
);
1644 //iterate inside of a grouped object
1645 while(aListIter
.IsMore())
1647 SdrTextObj
* pTextObj
= DynCastSdrTextObj(aListIter
.Next());
1648 if(pTextObj
&& pTextObj
->HasText())
1649 pCollectTextObjectsHint
->m_rTextObjects
.push_back(pTextObj
);
1652 else if(SdrTextObj
* pTextObj
= DynCastSdrTextObj(pSdrO
))
1654 if(pTextObj
->HasText())
1655 pCollectTextObjectsHint
->m_rTextObjects
.push_back(pTextObj
);
1658 else if (rHint
.GetId() == SfxHintId::SwGetZOrder
)
1660 auto pGetZOrdnerHint
= static_cast<const sw::GetZOrderHint
*>(&rHint
);
1661 auto pFormat(dynamic_cast<const SwFrameFormat
*>(&rMod
));
1662 if (pFormat
&& pFormat
->Which() == RES_DRAWFRMFMT
)
1663 pGetZOrdnerHint
->m_rnZOrder
= GetMaster()->GetOrdNum();
1665 else if (rHint
.GetId() == SfxHintId::SwGetObjectConnected
)
1667 auto pConnectedHint
= static_cast<const sw::GetObjectConnectedHint
*>(&rHint
);
1668 pConnectedHint
->m_risConnected
|= (GetAnchorFrame() != nullptr);
1673 // #i28701# - added parameter <_bUpdateSortedObjsList>
1674 void SwDrawContact::InvalidateObjs_( const bool _bUpdateSortedObjsList
)
1676 for(const auto& rpDrawVirtObj
: maDrawVirtObjs
)
1677 // invalidate position of existing 'virtual' drawing objects
1679 SwDrawVirtObj
* pDrawVirtObj(rpDrawVirtObj
.get());
1680 // #i33313# - invalidation only for connected
1681 // 'virtual' drawing objects
1682 if ( pDrawVirtObj
->IsConnected() )
1684 pDrawVirtObj
->AnchoredObj().InvalidateObjPos();
1686 if ( _bUpdateSortedObjsList
)
1688 pDrawVirtObj
->AnchoredObj().UpdateObjInSortedList();
1693 // invalidate position of 'master' drawing object
1694 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( nullptr );
1695 pAnchoredObj
->InvalidateObjPos();
1697 if ( _bUpdateSortedObjsList
)
1699 pAnchoredObj
->UpdateObjInSortedList();
1703 void SwDrawContact::DisconnectFromLayout( bool _bMoveMasterToInvisibleLayer
)
1705 mbDisconnectInProgress
= true;
1707 // --> #i36181# - notify background of drawing object
1708 if ( _bMoveMasterToInvisibleLayer
&&
1709 !(GetFormat()->GetDoc()->IsInDtor()) &&
1710 GetAnchorFrame() && !GetAnchorFrame()->IsInDtor() )
1712 const tools::Rectangle
aOldRect( maAnchoredDrawObj
.GetObjRectWithSpaces().SVRect() );
1713 lcl_NotifyBackgroundOfObj( *this, *GetMaster(), &aOldRect
);
1714 NotifyBackgroundOfAllVirtObjs( &aOldRect
);
1717 // remove 'virtual' drawing objects from writer
1718 // layout and from drawing page
1719 for(auto& rpVirtDrawObj
: maDrawVirtObjs
)
1721 rpVirtDrawObj
->RemoveFromWriterLayout();
1722 rpVirtDrawObj
->RemoveFromDrawingPage();
1725 if ( maAnchoredDrawObj
.GetAnchorFrame() )
1727 maAnchoredDrawObj
.AnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
1730 if ( _bMoveMasterToInvisibleLayer
&& GetMaster() && GetMaster()->IsInserted() )
1732 SdrViewIter::ForAllViews( GetMaster(),
1733 [this] (SdrView
* pView
)
1735 pView
->MarkObj( GetMaster(), pView
->GetSdrPageView(), true );
1738 // Instead of removing 'master' object from drawing page, move the
1739 // 'master' drawing object into the corresponding invisible layer.
1741 //static_cast<SwFrameFormat*>(GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1742 // RemoveObject( GetMaster()->GetOrdNum() );
1743 // #i18447# - in order to consider group object correct
1744 // use new method <SwDrawContact::MoveObjToInvisibleLayer(..)>
1745 MoveObjToInvisibleLayer( GetMaster() );
1749 mbDisconnectInProgress
= false;
1752 /// method to remove 'master' drawing object from drawing page.
1753 void SwDrawContact::RemoveMasterFromDrawPage()
1757 GetMaster()->SetUserCall( nullptr );
1758 if ( GetMaster()->IsInserted() )
1760 static_cast<SwFrameFormat
*>(GetRegisteredIn())->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1761 RemoveObject( GetMaster()->GetOrdNum() );
1766 // disconnect for a dedicated drawing object - could be 'master' or 'virtual'.
1767 // a 'master' drawing object will disconnect a 'virtual' drawing object
1768 // in order to take its place.
1769 // #i19919# - no special case, if drawing object isn't in
1770 // page header/footer, in order to get drawing objects in repeating table headers
1772 void SwDrawContact::DisconnectObjFromLayout( SdrObject
* _pDrawObj
)
1774 if ( auto pSwDrawVirtObj
= dynamic_cast<SwDrawVirtObj
*>( _pDrawObj
) )
1776 pSwDrawVirtObj
->RemoveFromWriterLayout();
1777 pSwDrawVirtObj
->RemoveFromDrawingPage();
1781 const auto ppVirtDrawObj(std::find_if(maDrawVirtObjs
.begin(), maDrawVirtObjs
.end(),
1782 [] (const rtl::Reference
<SwDrawVirtObj
>& pObj
) { return pObj
->IsConnected(); }));
1784 if(ppVirtDrawObj
!= maDrawVirtObjs
.end())
1786 // replace found 'virtual' drawing object by 'master' drawing
1787 // object and disconnect the 'virtual' one
1788 SwDrawVirtObj
* pDrawVirtObj(ppVirtDrawObj
->get());
1789 SwFrame
* pNewAnchorFrameOfMaster
= pDrawVirtObj
->AnchorFrame();
1790 // disconnect 'virtual' drawing object
1791 pDrawVirtObj
->RemoveFromWriterLayout();
1792 pDrawVirtObj
->RemoveFromDrawingPage();
1793 // disconnect 'master' drawing object from current frame
1794 GetAnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
1795 // re-connect 'master' drawing object to frame of found 'virtual'
1797 pNewAnchorFrameOfMaster
->AppendDrawObj( maAnchoredDrawObj
);
1801 // no connected 'virtual' drawing object found. Thus, disconnect
1802 // completely from layout.
1803 DisconnectFromLayout();
1808 static SwTextFrame
* lcl_GetFlyInContentAnchor( SwTextFrame
* _pProposedAnchorFrame
,
1809 SwPosition
const& rAnchorPos
)
1811 SwTextFrame
* pAct
= _pProposedAnchorFrame
;
1813 TextFrameIndex
const nTextOffset(_pProposedAnchorFrame
->MapModelToViewPos(rAnchorPos
));
1817 pAct
= pTmp
->GetFollow();
1819 while (pAct
&& nTextOffset
>= pAct
->GetOffset());
1823 void SwDrawContact::ConnectToLayout( const SwFormatAnchor
* pAnch
)
1825 // *no* connect to layout during disconnection from layout.
1826 if ( mbDisconnectInProgress
)
1828 OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> called during disconnection.");
1832 // --> #i33909# - *no* connect to layout, if 'master' drawing
1833 // object isn't inserted in the drawing page
1834 if ( !GetMaster()->IsInserted() )
1836 OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> - master drawing object not inserted -> no connect to layout. Please inform od@openoffice.org" );
1840 SwFrameFormat
* pDrawFrameFormat
= static_cast<SwFrameFormat
*>(GetRegisteredIn());
1842 if( !pDrawFrameFormat
->getIDocumentLayoutAccess().GetCurrentViewShell() )
1845 // remove 'virtual' drawing objects from writer
1846 // layout and from drawing page, and remove 'master' drawing object from
1847 // writer layout - 'master' object will remain in drawing page.
1848 DisconnectFromLayout( false );
1852 pAnch
= &(pDrawFrameFormat
->GetAnchor());
1855 switch ( pAnch
->GetAnchorId() )
1857 case RndStdIds::FLY_AT_PAGE
:
1859 sal_uInt16 nPgNum
= pAnch
->GetPageNum();
1860 SwViewShell
*pShell
= pDrawFrameFormat
->getIDocumentLayoutAccess().GetCurrentViewShell();
1863 SwRootFrame
* pRoot
= pShell
->GetLayout();
1864 SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(pRoot
->Lower());
1866 for ( sal_uInt16 i
= 1; i
< nPgNum
&& pPage
; ++i
)
1868 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1873 pPage
->AppendDrawObj( maAnchoredDrawObj
);
1876 //Looks stupid but is allowed (compare SwFEShell::SetPageObjsNewPage)
1877 pRoot
->SetAssertFlyPages();
1881 case RndStdIds::FLY_AT_CHAR
:
1882 case RndStdIds::FLY_AT_PARA
:
1883 case RndStdIds::FLY_AT_FLY
:
1884 case RndStdIds::FLY_AS_CHAR
:
1886 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1888 ClrContourCache( GetMaster() );
1890 // support drawing objects in header/footer,
1891 // but not control objects:
1892 // anchor at first found frame the 'master' object and
1893 // at the following frames 'virtual' drawing objects.
1894 // Note: method is similar to <SwFlyFrameFormat::MakeFrames(..)>
1895 sw::BroadcastingModify
*pModify
= nullptr;
1896 if( pAnch
->GetAnchorNode() )
1898 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AT_FLY
)
1900 SwNodeIndex
aIdx( *pAnch
->GetAnchorNode() );
1901 SwContentNode
* pCNd
= SwNodes::GoNext(&aIdx
);
1902 if (SwIterator
<SwFrame
, SwContentNode
, sw::IteratorMode::UnwrapMulti
>(*pCNd
).First())
1906 const SwNode
& rIdx
= *pAnch
->GetAnchorNode();
1907 for(sw::SpzFrameFormat
* pFlyFormat
:*(pDrawFrameFormat
->GetDoc()->GetSpzFrameFormats()))
1909 if( pFlyFormat
->GetContent().GetContentIdx() &&
1910 rIdx
== pFlyFormat
->GetContent().GetContentIdx()->GetNode() )
1912 pModify
= pFlyFormat
;
1920 pModify
= pAnch
->GetAnchorNode()->GetContentNode();
1924 // #i29199# - It is possible, that
1925 // the anchor doesn't exist - E.g., reordering the
1926 // sub-documents in a master document.
1927 // Note: The anchor will be inserted later.
1930 // break to end of the current switch case.
1934 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(*pModify
);
1935 SwFrame
* pAnchorFrameOfMaster
= nullptr;
1936 for( SwFrame
*pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next() )
1938 // append drawing object, if
1939 // (1) proposed anchor frame isn't a follow and...
1940 const bool bFollow
= pFrame
->IsContentFrame() && static_cast<SwContentFrame
*>(pFrame
)->IsFollow();
1944 // (2) drawing object isn't a control object to be anchored
1945 // in header/footer.
1946 const bool bControlInHF
= ::CheckControlLayer(GetMaster()) && pFrame
->FindFooterOrHeader();
1947 // tdf#129542 but make an exception for control objects so they can get added to just the first frame,
1948 // the Master Anchor Frame and not the others
1949 if (bControlInHF
&& pAnchorFrameOfMaster
)
1953 if (RndStdIds::FLY_AT_FLY
== pAnch
->GetAnchorId())
1957 assert(pFrame
->IsTextFrame());
1958 bAdd
= IsAnchoredObjShown(*static_cast<SwTextFrame
*>(pFrame
), *pAnch
);
1963 if ( RndStdIds::FLY_AT_FLY
== pAnch
->GetAnchorId() && !pFrame
->IsFlyFrame() )
1965 pFrame
= pFrame
->FindFlyFrame();
1969 // find correct follow for as character anchored objects
1970 if ((pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
) &&
1971 pFrame
->IsTextFrame() )
1973 pFrame
= lcl_GetFlyInContentAnchor(
1974 static_cast<SwTextFrame
*>(pFrame
),
1975 *pAnch
->GetContentAnchor());
1978 if ( !pAnchorFrameOfMaster
)
1980 // append 'master' drawing object
1981 pAnchorFrameOfMaster
= pFrame
;
1983 const SwFrameFormat
* pFlyFormat
= nullptr;
1984 if (!maAnchoredDrawObj
.GetDrawObj()->IsGroupObject())
1986 pFlyFormat
= SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_DRAWFRMFMT
);
1991 // This is a master draw object and it has an associated fly format.
1992 // See if a fly frame is already inserted to the layout: if so, this
1993 // master draw object should be ordered directly before the fly one.
1994 if (const SwSortedObjs
* pObjs
= pFrame
->GetDrawObjs())
1996 for (const SwAnchoredObject
* pAnchoredObj
: *pObjs
)
1998 if (pAnchoredObj
->GetFrameFormat() == pFlyFormat
)
2000 SdrPage
* pDrawPage
= pAnchoredObj
->GetDrawObj()->getSdrPageFromSdrObject();
2003 sal_uInt32 nOrdNum
= pAnchoredObj
->GetDrawObj()->GetOrdNum();
2004 if (maAnchoredDrawObj
.GetDrawObj()->GetOrdNum() >= nOrdNum
)
2006 pDrawPage
->SetObjectOrdNum(maAnchoredDrawObj
.GetDrawObj()->GetOrdNumDirect(), nOrdNum
);
2010 pDrawPage
->SetObjectOrdNum(nOrdNum
, maAnchoredDrawObj
.GetDrawObj()->GetOrdNumDirect() + 1);
2019 pFrame
->AppendDrawObj( maAnchoredDrawObj
);
2023 // append 'virtual' drawing object
2024 SwDrawVirtObj
* pDrawVirtObj
= AddVirtObj(*pFrame
);
2025 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
2027 ClrContourCache( pDrawVirtObj
);
2029 pFrame
->AppendDrawObj( pDrawVirtObj
->AnchoredObj() );
2031 pDrawVirtObj
->ActionChanged();
2034 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
2036 pFrame
->InvalidatePrt();
2043 assert(!"Unknown Anchor.");
2046 if ( GetAnchorFrame() )
2048 ::setContextWritingMode( maAnchoredDrawObj
.DrawObj(), GetAnchorFrame() );
2049 // #i26791# - invalidate objects instead of direct positioning
2054 /// insert 'master' drawing object into drawing page
2055 void SwDrawContact::InsertMasterIntoDrawPage()
2057 if ( !GetMaster()->IsInserted() )
2059 GetFormat()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)
2060 ->InsertObject( GetMaster(), GetMaster()->GetOrdNumDirect() );
2062 GetMaster()->SetUserCall( this );
2065 SwPageFrame
* SwDrawContact::FindPage( const SwRect
&rRect
)
2067 // --> #i28701# - use method <GetPageFrame()>
2068 SwPageFrame
* pPg
= GetPageFrame();
2069 if ( !pPg
&& GetAnchorFrame() )
2070 pPg
= GetAnchorFrame()->FindPageFrame();
2072 pPg
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( rRect
, pPg
)));
2076 void SwDrawContact::ChkPage()
2078 if ( mbDisconnectInProgress
)
2080 OSL_FAIL( "<SwDrawContact::ChkPage()> called during disconnection." );
2085 // tdf#156287: use anchor page, not current bound rectangle's page,
2086 // because an object can't move to a page other than its anchor anyway
2087 SwPageFrame
* pPg
= ( maAnchoredDrawObj
.GetAnchorFrame() &&
2088 maAnchoredDrawObj
.GetAnchorFrame()->IsPageFrame() )
2090 : maAnchoredDrawObj
.FindPageFrameOfAnchor();
2091 if ( GetPageFrame() == pPg
)
2094 // if drawing object is anchor in header/footer a change of the page
2095 // is a dramatic change. Thus, completely re-connect to the layout
2096 if ( maAnchoredDrawObj
.GetAnchorFrame() &&
2097 maAnchoredDrawObj
.GetAnchorFrame()->FindFooterOrHeader() )
2103 // --> #i28701# - use methods <GetPageFrame()> and <SetPageFrame>
2104 maAnchoredDrawObj
.RegisterAtPage(*pPg
);
2105 maAnchoredDrawObj
.SetPageFrame( pPg
);
2110 // method is called by method <SwDPage::ReplaceObject(..)>, which called its
2111 // corresponding superclass method <FmFormPage::ReplaceObject(..)>.
2112 // Note: 'master' drawing object *has* to be connected to layout triggered
2113 // by the caller of this, if method is called.
2114 void SwDrawContact::ChangeMasterObject(SdrObject
* pNewMaster
)
2116 DisconnectFromLayout( false );
2117 // consider 'virtual' drawing objects
2118 RemoveAllVirtObjs();
2120 GetMaster()->SetUserCall( nullptr );
2122 maAnchoredDrawObj
.SetDrawObj(*pNewMaster
);
2124 mbMasterObjCleared
= true;
2125 GetMaster()->SetUserCall( this );
2130 /// get data collection of anchored objects, handled by with contact
2131 void SwDrawContact::GetAnchoredObjs(std::vector
<SwAnchoredObject
*>& o_rAnchoredObjs
) const
2133 o_rAnchoredObjs
.push_back(const_cast<SwAnchoredDrawObject
*>(&maAnchoredDrawObj
));
2135 for(auto& rpDrawVirtObj
: maDrawVirtObjs
)
2136 o_rAnchoredObjs
.push_back(&rpDrawVirtObj
->AnchoredObj());
2139 // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
2140 // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
2141 // For paint, that offset is used by setting at the OutputDevice; for primitives this is
2142 // not possible since we have no OutputDevice, but define the geometry itself.
2144 namespace sdr::contact
2148 class VOCOfDrawVirtObj
: public ViewObjectContactOfSdrObj
2152 * This method is responsible for creating the graphical visualisation data which is
2153 * stored/cached in the local primitive. Default gets view-independent Primitive from
2154 * the ViewContact using ViewContact::getViewIndependentPrimitive2DContainer(), takes
2155 * care of visibility, handles glue and ghosted.
2157 * This method will not handle included hierarchies and not check geometric visibility.
2159 virtual void createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const override
;
2162 VOCOfDrawVirtObj(ObjectContact
& rObjectContact
, ViewContact
& rViewContact
)
2163 : ViewObjectContactOfSdrObj(rObjectContact
, rViewContact
)
2168 class VCOfDrawVirtObj
: public ViewContactOfVirtObj
2171 /** Create an Object-Specific ViewObjectContact, set ViewContact and ObjectContact.
2173 * Always needs to return something. Default is to create a standard ViewObjectContact
2174 * containing the given ObjectContact and *this.
2176 virtual ViewObjectContact
& CreateObjectSpecificViewObjectContact(ObjectContact
& rObjectContact
) override
;
2179 /// basic constructor, used from SdrObject.
2180 explicit VCOfDrawVirtObj(SwDrawVirtObj
& rObj
)
2181 : ViewContactOfVirtObj(rObj
)
2185 /// access to SwDrawVirtObj
2186 SwDrawVirtObj
& GetSwDrawVirtObj() const
2188 return static_cast<SwDrawVirtObj
&>(mrObject
);
2193 } // end of namespace sdr::contact
2195 namespace sdr::contact
2197 /// recursively collect primitive data from given VOC with given offset
2198 static void impAddPrimitivesFromGroup(const ViewObjectContact
& rVOC
, const basegfx::B2DHomMatrix
& rOffsetMatrix
, const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DContainer
& rxTarget
)
2200 const sal_uInt32
nSubHierarchyCount(rVOC
.GetViewContact().GetObjectCount());
2202 for(sal_uInt32
a(0); a
< nSubHierarchyCount
; a
++)
2204 const ViewObjectContact
& rCandidate(rVOC
.GetViewContact().GetViewContact(a
).GetViewObjectContact(rVOC
.GetObjectContact()));
2206 if(rCandidate
.GetViewContact().GetObjectCount())
2208 // is a group object itself, call recursively
2209 impAddPrimitivesFromGroup(rCandidate
, rOffsetMatrix
, rDisplayInfo
, rxTarget
);
2213 // single object, add primitives; check model-view visibility
2214 if(rCandidate
.isPrimitiveVisible(rDisplayInfo
))
2216 drawinglayer::primitive2d::Primitive2DContainer
aNewSequence(rCandidate
.getPrimitive2DSequence(rDisplayInfo
));
2218 if(!aNewSequence
.empty())
2221 const drawinglayer::geometry::ViewInformation2D
& rViewInformation2D(rCandidate
.GetObjectContact().getViewInformation2D());
2222 const basegfx::B2DRange
& aViewRange(rViewInformation2D
.getViewport());
2223 basegfx::B2DRange
aObjectRange(rCandidate
.getObjectRange());
2225 // correct with virtual object's offset
2226 aObjectRange
.transform(rOffsetMatrix
);
2228 // check geometrical visibility (with offset)
2229 if(!aViewRange
.overlaps(aObjectRange
))
2231 // not visible, release
2232 aNewSequence
.clear();
2236 if(!aNewSequence
.empty())
2238 rxTarget
.append(std::move(aNewSequence
));
2245 void VOCOfDrawVirtObj::createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const
2247 // this may be called for painting where it's a precondition that
2248 // isPrimitiveVisible() is true, or for e.g. getObjectRange() (even
2249 // during layout) where there are no preconditions...
2250 // nasty corner case: override to clear page frame to disable the
2251 // sub-objects' anchor check, because their anchor is always on
2252 // the first page that the page style is applied to
2253 DisplayInfo
aDisplayInfo(rDisplayInfo
);
2254 aDisplayInfo
.SetWriterPageFrame(basegfx::B2IRectangle());
2255 const VCOfDrawVirtObj
& rVC
= static_cast< const VCOfDrawVirtObj
& >(GetViewContact());
2256 const SdrObject
& rReferencedObject
= rVC
.GetSwDrawVirtObj().GetReferencedObj();
2257 drawinglayer::primitive2d::Primitive2DContainer xRetval
;
2259 // create offset transformation
2260 basegfx::B2DHomMatrix aOffsetMatrix
;
2261 const Point
aLocalOffset(rVC
.GetSwDrawVirtObj().GetOffset());
2263 if(aLocalOffset
.X() || aLocalOffset
.Y())
2265 aOffsetMatrix
.set(0, 2, aLocalOffset
.X());
2266 aOffsetMatrix
.set(1, 2, aLocalOffset
.Y());
2269 if(dynamic_cast<const SdrObjGroup
*>( &rReferencedObject
) != nullptr)
2271 // group object. Since the VOC/OC/VC hierarchy does not represent the
2272 // hierarchy virtual objects when they have group objects
2273 // (ViewContactOfVirtObj::GetObjectCount() returns null for that purpose)
2274 // to avoid multiple usages of VOCs (which would not work), the primitives
2275 // for the sub-hierarchy need to be collected here
2277 // Get the VOC of the referenced object (the Group) and fetch primitives from it
2278 const ViewObjectContact
& rVOCOfRefObj
= rReferencedObject
.GetViewContact().GetViewObjectContact(GetObjectContact());
2279 impAddPrimitivesFromGroup(rVOCOfRefObj
, aOffsetMatrix
, aDisplayInfo
, xRetval
);
2283 // single object, use method from referenced object to get the Primitive2DSequence
2284 rReferencedObject
.GetViewContact().getViewIndependentPrimitive2DContainer(xRetval
);
2287 if(!xRetval
.empty())
2289 // create transform primitive
2290 xRetval
= drawinglayer::primitive2d::Primitive2DContainer
{
2291 new drawinglayer::primitive2d::TransformPrimitive2D(aOffsetMatrix
, std::move(xRetval
))
2295 rVisitor
.visit(xRetval
);
2298 ViewObjectContact
& VCOfDrawVirtObj::CreateObjectSpecificViewObjectContact(ObjectContact
& rObjectContact
)
2300 return *(new VOCOfDrawVirtObj(rObjectContact
, *this));
2303 } // end of namespace sdr::contact
2305 /// implementation of class <SwDrawVirtObj>
2306 std::unique_ptr
<sdr::contact::ViewContact
> SwDrawVirtObj::CreateObjectSpecificViewContact()
2308 return std::make_unique
<sdr::contact::VCOfDrawVirtObj
>(*this);
2311 SwDrawVirtObj::SwDrawVirtObj(
2312 SdrModel
& rSdrModel
,
2313 SdrObject
& _rNewObj
,
2314 SwDrawContact
& _rDrawContact
)
2315 : SdrVirtObj(rSdrModel
, _rNewObj
),
2316 mrDrawContact(_rDrawContact
)
2319 maAnchoredDrawObj
.SetDrawObj( *this );
2321 // #i35635# - set initial position out of sight
2322 NbcMove( Size( -16000, -16000 ) );
2325 SwDrawVirtObj::SwDrawVirtObj(
2326 SdrModel
& rSdrModel
,
2327 SwDrawVirtObj
const & rSource
)
2328 : SdrVirtObj(rSdrModel
, rSource
),
2329 mrDrawContact(rSource
.mrDrawContact
)
2332 maAnchoredDrawObj
.SetDrawObj( *this );
2334 // #i35635# - set initial position out of sight
2335 NbcMove( Size( -16000, -16000 ) );
2337 // Note: Members <maAnchoredDrawObj> and <mrDrawContact>
2338 // haven't to be considered.
2341 SwDrawVirtObj::~SwDrawVirtObj()
2345 rtl::Reference
<SdrObject
> SwDrawVirtObj::CloneSdrObject(SdrModel
& rTargetModel
) const
2347 return new SwDrawVirtObj(rTargetModel
, *this);
2350 const SwFrame
* SwDrawVirtObj::GetAnchorFrame() const
2352 // #i26791# - use new member <maAnchoredDrawObj>
2353 return maAnchoredDrawObj
.GetAnchorFrame();
2356 SwFrame
* SwDrawVirtObj::AnchorFrame()
2358 // #i26791# - use new member <maAnchoredDrawObj>
2359 return maAnchoredDrawObj
.AnchorFrame();
2362 void SwDrawVirtObj::RemoveFromWriterLayout()
2364 // remove contact object from frame for 'virtual' drawing object
2365 // #i26791# - use new member <maAnchoredDrawObj>
2366 if ( maAnchoredDrawObj
.GetAnchorFrame() )
2368 maAnchoredDrawObj
.AnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
2372 void SwDrawVirtObj::AddToDrawingPage(SwFrame
const& rAnchorFrame
)
2374 // determine 'master'
2375 SdrObject
* pOrgMasterSdrObj
= mrDrawContact
.GetMaster();
2377 // insert 'virtual' drawing object into page, set layer and user call.
2378 SdrPage
* pDrawPg
= pOrgMasterSdrObj
->getSdrPageFromSdrObject();
2379 // default: insert before master object
2380 auto nOrdNum(GetReferencedObj().GetOrdNum());
2382 // maintain invariant that a shape's textbox immediately follows the shape
2383 // also for the multiple SdrDrawVirtObj created for shapes in header/footer
2384 if (SwFrameFormat
const*const pFlyFormat
=
2385 SwTextBoxHelper::getOtherTextBoxFormat(mrDrawContact
.GetFormat(), RES_DRAWFRMFMT
))
2387 // this is for the case when the flyframe SdrVirtObj is created before the draw one
2388 if (SwSortedObjs
const*const pObjs
= rAnchorFrame
.GetDrawObjs())
2390 for (SwAnchoredObject
const*const pAnchoredObj
: *pObjs
)
2392 if (pAnchoredObj
->GetFrameFormat() == pFlyFormat
)
2394 assert(dynamic_cast<SwFlyFrame
const*>(pAnchoredObj
));
2396 if (pAnchoredObj
->GetDrawObj()->GetOrdNum() >= GetReferencedObj().GetOrdNum())
2398 // This virtual draw object has an associated fly one, but the fly's index
2399 // is not below the masters, fix it up.
2402 pDrawPg
->SetObjectOrdNum(pAnchoredObj
->GetDrawObj()->GetOrdNumDirect(), GetReferencedObj().GetOrdNum());
2406 nOrdNum
= pAnchoredObj
->GetDrawObj()->GetOrdNum();
2407 // the master SdrObj should have the highest index
2408 assert(nOrdNum
< GetReferencedObj().GetOrdNum());
2413 // this happens on initial insertion, the draw object is created first
2414 SAL_INFO_IF(GetReferencedObj().GetOrdNum() == nOrdNum
, "sw", "AddToDrawingPage: cannot find SdrObject for text box's shape");
2417 // #i27030# - apply order number of referenced object
2418 if ( nullptr != pDrawPg
)
2420 // #i27030# - apply order number of referenced object
2421 pDrawPg
->InsertObject(this, nOrdNum
);
2425 pDrawPg
= getSdrPageFromSdrObject();
2428 pDrawPg
->SetObjectOrdNum(GetOrdNumDirect(), nOrdNum
);
2435 SetUserCall( &mrDrawContact
);
2438 void SwDrawVirtObj::RemoveFromDrawingPage()
2440 SetUserCall( nullptr );
2441 if ( getSdrPageFromSdrObject() )
2443 getSdrPageFromSdrObject()->RemoveObject( GetOrdNum() );
2447 /// Is 'virtual' drawing object connected to writer layout and to drawing layer?
2448 bool SwDrawVirtObj::IsConnected() const
2450 bool bRetVal
= GetAnchorFrame() &&
2451 ( getSdrPageFromSdrObject() && GetUserCall() );
2456 void SwDrawVirtObj::NbcSetAnchorPos(const Point
& rPnt
)
2458 SdrObject::NbcSetAnchorPos( rPnt
);
2462 // the methods relevant for positioning
2464 const tools::Rectangle
& SwDrawVirtObj::GetCurrentBoundRect() const
2466 if (getOutRectangle().IsEmpty())
2468 const_cast<SwDrawVirtObj
*>(this)->RecalcBoundRect();
2471 return getOutRectangle();
2474 const tools::Rectangle
& SwDrawVirtObj::GetLastBoundRect() const
2476 return getOutRectangle();
2479 Point
SwDrawVirtObj::GetOffset() const
2481 // do NOT use IsEmpty() here, there is already a useful offset
2483 if (getOutRectangle() == tools::Rectangle())
2489 return getOutRectangle().TopLeft() - GetReferencedObj().GetCurrentBoundRect().TopLeft();
2493 void SwDrawVirtObj::SetBoundRectDirty()
2495 // do nothing to not lose model information in aOutRect
2498 void SwDrawVirtObj::RecalcBoundRect()
2500 // #i26791# - switch order of calling <GetOffset()> and
2501 // <ReferencedObj().GetCurrentBoundRect()>, because <GetOffset()> calculates
2502 // its value by the 'BoundRect' of the referenced object.
2504 const Point
aOffset(GetOffset());
2505 setOutRectangle(ReferencedObj().GetCurrentBoundRect() + aOffset
);
2508 basegfx::B2DPolyPolygon
SwDrawVirtObj::TakeXorPoly() const
2510 basegfx::B2DPolyPolygon
aRetval(mxRefObj
->TakeXorPoly());
2511 aRetval
.transform(basegfx::utils::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2516 basegfx::B2DPolyPolygon
SwDrawVirtObj::TakeContour() const
2518 basegfx::B2DPolyPolygon
aRetval(mxRefObj
->TakeContour());
2519 aRetval
.transform(basegfx::utils::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2524 void SwDrawVirtObj::AddToHdlList(SdrHdlList
& rHdlList
) const
2526 SdrHdlList
tmpList(nullptr);
2527 mxRefObj
->AddToHdlList(tmpList
);
2529 size_t cnt
= tmpList
.GetHdlCount();
2530 for(size_t i
=0; i
< cnt
; ++i
)
2532 SdrHdl
* pHdl
= tmpList
.GetHdl(i
);
2533 Point
aP(pHdl
->GetPos() + GetOffset());
2536 tmpList
.MoveTo(rHdlList
);
2539 void SwDrawVirtObj::NbcMove(const Size
& rSiz
)
2541 SdrObject::NbcMove( rSiz
);
2544 void SwDrawVirtObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
2546 mxRefObj
->NbcResize(rRef
- GetOffset(), xFact
, yFact
);
2547 SetBoundAndSnapRectsDirty();
2550 void SwDrawVirtObj::NbcRotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
2552 mxRefObj
->NbcRotate(rRef
- GetOffset(), nAngle
, sn
, cs
);
2553 SetBoundAndSnapRectsDirty();
2556 void SwDrawVirtObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
2558 mxRefObj
->NbcMirror(rRef1
- GetOffset(), rRef2
- GetOffset());
2559 SetBoundAndSnapRectsDirty();
2562 void SwDrawVirtObj::NbcShear(const Point
& rRef
, Degree100 nAngle
, double tn
, bool bVShear
)
2564 mxRefObj
->NbcShear(rRef
- GetOffset(), nAngle
, tn
, bVShear
);
2565 SetBoundAndSnapRectsDirty();
2568 void SwDrawVirtObj::Move(const Size
& rSiz
)
2570 SdrObject::Move( rSiz
);
2573 void SwDrawVirtObj::Resize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bUnsetRelative
)
2575 if(xFact
.GetNumerator() != xFact
.GetDenominator() || yFact
.GetNumerator() != yFact
.GetDenominator())
2577 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2578 mxRefObj
->Resize(rRef
- GetOffset(), xFact
, yFact
, bUnsetRelative
);
2579 SetBoundAndSnapRectsDirty();
2580 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2584 void SwDrawVirtObj::Rotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
2588 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2589 mxRefObj
->Rotate(rRef
- GetOffset(), nAngle
, sn
, cs
);
2590 SetBoundAndSnapRectsDirty();
2591 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2595 void SwDrawVirtObj::Mirror(const Point
& rRef1
, const Point
& rRef2
)
2597 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2598 mxRefObj
->Mirror(rRef1
- GetOffset(), rRef2
- GetOffset());
2599 SetBoundAndSnapRectsDirty();
2600 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2603 void SwDrawVirtObj::Shear(const Point
& rRef
, Degree100 nAngle
, double tn
, bool bVShear
)
2607 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2608 mxRefObj
->Shear(rRef
- GetOffset(), nAngle
, tn
, bVShear
);
2609 SetBoundAndSnapRectsDirty();
2610 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2614 void SwDrawVirtObj::RecalcSnapRect()
2616 maSnapRect
= mxRefObj
->GetSnapRect();
2617 maSnapRect
+= GetOffset();
2620 const tools::Rectangle
& SwDrawVirtObj::GetSnapRect() const
2622 const_cast<SwDrawVirtObj
*>(this)->maSnapRect
= mxRefObj
->GetSnapRect();
2623 const_cast<SwDrawVirtObj
*>(this)->maSnapRect
+= GetOffset();
2628 void SwDrawVirtObj::SetSnapRect(const tools::Rectangle
& rRect
)
2630 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2631 tools::Rectangle
aR(rRect
);
2633 mxRefObj
->SetSnapRect(aR
);
2634 SetBoundAndSnapRectsDirty();
2635 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2638 void SwDrawVirtObj::NbcSetSnapRect(const tools::Rectangle
& rRect
)
2640 tools::Rectangle
aR(rRect
);
2642 SetBoundAndSnapRectsDirty();
2643 mxRefObj
->NbcSetSnapRect(aR
);
2646 const tools::Rectangle
& SwDrawVirtObj::GetLogicRect() const
2648 const_cast<SwDrawVirtObj
*>(this)->maSnapRect
= mxRefObj
->GetLogicRect();
2649 const_cast<SwDrawVirtObj
*>(this)->maSnapRect
+= GetOffset();
2654 void SwDrawVirtObj::SetLogicRect(const tools::Rectangle
& rRect
)
2656 tools::Rectangle aBoundRect0
; if(m_pUserCall
) aBoundRect0
= GetLastBoundRect();
2657 tools::Rectangle
aR(rRect
);
2659 mxRefObj
->SetLogicRect(aR
);
2660 SetBoundAndSnapRectsDirty();
2661 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2664 void SwDrawVirtObj::NbcSetLogicRect(const tools::Rectangle
& rRect
, bool bAdaptTextMinSize
)
2666 tools::Rectangle
aR(rRect
);
2668 mxRefObj
->NbcSetLogicRect(aR
, bAdaptTextMinSize
);
2669 SetBoundAndSnapRectsDirty();
2672 Point
SwDrawVirtObj::GetSnapPoint(sal_uInt32 i
) const
2674 Point
aP(mxRefObj
->GetSnapPoint(i
));
2680 Point
SwDrawVirtObj::GetPoint(sal_uInt32 i
) const
2682 return mxRefObj
->GetPoint(i
) + GetOffset();
2685 void SwDrawVirtObj::NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
)
2689 mxRefObj
->SetPoint(aP
, i
);
2690 SetBoundAndSnapRectsDirty();
2693 bool SwDrawVirtObj::HasTextEdit() const
2695 return mxRefObj
->HasTextEdit();
2698 // override 'layer' methods for 'virtual' drawing object to assure
2699 // that layer of 'virtual' object is the layer of the referenced object.
2700 SdrLayerID
SwDrawVirtObj::GetLayer() const
2702 return GetReferencedObj().GetLayer();
2705 void SwDrawVirtObj::NbcSetLayer(SdrLayerID nLayer
)
2707 ReferencedObj().NbcSetLayer( nLayer
);
2708 SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2711 void SwDrawVirtObj::SetLayer(SdrLayerID nLayer
)
2713 ReferencedObj().SetLayer( nLayer
);
2714 SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */