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 <editeng/lrspitem.hxx>
23 #include <svx/svdpage.hxx>
24 #include <svx/svditer.hxx>
25 #include <svx/svdogrp.hxx>
26 #include <svx/svdotext.hxx>
27 #include <svx/svdmodel.hxx>
28 #include <svx/svdviter.hxx>
29 #include <svx/svdview.hxx>
30 #include <svx/sdr/contact/displayinfo.hxx>
31 #include <svx/sdr/contact/objectcontact.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>
60 #include <sortedobjs.hxx>
61 #include <basegfx/matrix/b2dhommatrix.hxx>
62 #include <basegfx/matrix/b2dhommatrixtools.hxx>
63 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
64 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
65 #include <drawinglayer/geometry/viewinformation2d.hxx>
66 #include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
67 #include <com/sun/star/text/WritingMode2.hpp>
71 #include <sal/log.hxx>
73 using namespace ::com::sun::star
;
77 /** unary function used to find a 'virtual' drawing object anchored at a given frame */
78 struct VirtObjAnchoredAtFramePred
80 const SwFrame
* m_pAnchorFrame
;
82 // #i26791# - compare with master frame
83 static const SwFrame
* FindFrame(const SwFrame
* pFrame
)
85 if(!pFrame
|| !pFrame
->IsContentFrame())
87 auto pContentFrame
= static_cast<const SwContentFrame
*>(pFrame
);
88 while(pContentFrame
->IsFollow())
89 pContentFrame
= pContentFrame
->FindMaster();
93 VirtObjAnchoredAtFramePred(const SwFrame
* pAnchorFrame
)
94 : m_pAnchorFrame(FindFrame(pAnchorFrame
))
97 bool operator()(const SwDrawVirtObjPtr
& rpDrawVirtObj
)
99 return FindFrame(rpDrawVirtObj
->GetAnchorFrame()) == m_pAnchorFrame
;
104 void setContextWritingMode(SdrObject
* pObj
, SwFrame
const * pAnchor
)
106 if(!pObj
|| !pAnchor
)
108 short nWritingDirection
=
109 pAnchor
->IsVertical() ? text::WritingMode2::TB_RL
:
110 pAnchor
->IsRightToLeft() ? text::WritingMode2::RL_TB
:
111 text::WritingMode2::LR_TB
;
112 pObj
->SetContextWritingMode(nWritingDirection
);
116 /** The Get reverse way: seeks the format to the specified object.
117 * If the object is a SwVirtFlyDrawObj then the format of this
119 * Otherwise it is just a simple drawing object. This has a
120 * UserCall and is the client of the searched format.
122 SwFrameFormat
*FindFrameFormat( SdrObject
*pObj
)
124 SwFrameFormat
* pRetval
= nullptr;
126 if (SwVirtFlyDrawObj
* pFlyDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
128 pRetval
= pFlyDrawObj
->GetFormat();
132 SwContact
* pContact
= GetUserCall(pObj
);
135 pRetval
= pContact
->GetFormat();
141 bool HasWrap( const SdrObject
* pObj
)
145 const SwFrameFormat
* pFormat
= ::FindFrameFormat( pObj
);
148 return css::text::WrapTextMode_THROUGH
!= pFormat
->GetSurround().GetSurround();
155 /// returns the BoundRect _inclusive_ distance of the object.
156 SwRect
GetBoundRectOfAnchoredObj( const SdrObject
* pObj
)
158 SwRect
aRet( pObj
->GetCurrentBoundRect() );
159 // #i68520# - call cache of <SwAnchoredObject>
160 SwContact
* pContact( GetUserCall( pObj
) );
163 const SwAnchoredObject
* pAnchoredObj( pContact
->GetAnchoredObj( pObj
) );
166 aRet
= pAnchoredObj
->GetObjRectWithSpaces();
172 /// Returns the UserCall if applicable from the group object
173 SwContact
* GetUserCall( const SdrObject
* pObj
)
176 while ( !pObj
->GetUserCall() && nullptr != (pTmp
= pObj
->getParentSdrObjectFromSdrObject()) )
178 assert((!pObj
->GetUserCall() || nullptr != dynamic_cast<const SwContact
*>(pObj
->GetUserCall())) &&
179 "<::GetUserCall(..)> - wrong type of found object user call." );
180 return static_cast<SwContact
*>(pObj
->GetUserCall());
183 /// Returns true if the SrdObject is a Marquee-Object (scrolling text)
184 bool IsMarqueeTextObj( const SdrObject
& rObj
)
186 if (SdrInventor::Default
!= rObj
.GetObjInventor() ||
187 OBJ_TEXT
!= rObj
.GetObjIdentifier())
189 SdrTextAniKind eTKind
= static_cast<const SdrTextObj
&>(rObj
).GetTextAniKind();
190 return ( SdrTextAniKind::Scroll
== eTKind
191 || SdrTextAniKind::Alternate
== eTKind
|| SdrTextAniKind::Slide
== eTKind
);
194 SwContact::SwContact( SwFrameFormat
*pToRegisterIn
) :
195 SwClient( pToRegisterIn
),
199 SwContact::~SwContact()
205 void SwContact::SetInDTOR()
210 /// method to move drawing object to corresponding visible layer
211 void SwContact::MoveObjToVisibleLayer( SdrObject
* _pDrawObj
)
213 // #i46297# - notify background about the arriving of
214 // the object and invalidate its position.
215 const bool bNotify( !GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) );
217 MoveObjToLayer( true, _pDrawObj
);
223 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( _pDrawObj
);
224 assert(pAnchoredObj
);
225 ::setContextWritingMode( _pDrawObj
, pAnchoredObj
->GetAnchorFrameContainingAnchPos() );
226 // Note: as-character anchored objects aren't registered at a page frame and
227 // a notification of its background isn't needed.
228 if ( pAnchoredObj
->GetPageFrame() )
230 ::Notify_Background( _pDrawObj
, pAnchoredObj
->GetPageFrame(),
231 pAnchoredObj
->GetObjRect(), PrepareHint::FlyFrameArrive
, true );
234 pAnchoredObj
->InvalidateObjPos();
237 /// method to move drawing object to corresponding invisible layer - #i18447#
238 void SwContact::MoveObjToInvisibleLayer( SdrObject
* _pDrawObj
)
240 // #i46297# - notify background about the leaving of the object.
241 const bool bNotify( GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) );
243 MoveObjToLayer( false, _pDrawObj
);
248 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( _pDrawObj
);
249 assert(pAnchoredObj
);
250 // Note: as-character anchored objects aren't registered at a page frame and
251 // a notification of its background isn't needed.
252 if (pAnchoredObj
->GetPageFrame())
254 ::Notify_Background( _pDrawObj
, pAnchoredObj
->GetPageFrame(),
255 pAnchoredObj
->GetObjRect(), PrepareHint::FlyFrameLeave
, true );
260 /** method to move object to visible/invisible layer - #i18447#
262 implementation for the public method <MoveObjToVisibleLayer(..)>
263 and <MoveObjToInvisibleLayer(..)>
265 void SwContact::MoveObjToLayer( const bool _bToVisible
,
266 SdrObject
* _pDrawObj
)
270 OSL_FAIL( "SwDrawContact::MoveObjToLayer(..) - no drawing object!" );
274 if ( !GetRegisteredIn() )
276 OSL_FAIL( "SwDrawContact::MoveObjToLayer(..) - no drawing frame format!" );
280 const IDocumentDrawModelAccess
& rIDDMA
= static_cast<SwFrameFormat
*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
282 SdrLayerID nToHellLayerId
=
283 _bToVisible
? rIDDMA
.GetHellId() : rIDDMA
.GetInvisibleHellId();
284 SdrLayerID nToHeavenLayerId
=
285 _bToVisible
? rIDDMA
.GetHeavenId() : rIDDMA
.GetInvisibleHeavenId();
286 SdrLayerID nToControlLayerId
=
287 _bToVisible
? rIDDMA
.GetControlsId() : rIDDMA
.GetInvisibleControlsId();
288 SdrLayerID nFromHellLayerId
=
289 _bToVisible
? rIDDMA
.GetInvisibleHellId() : rIDDMA
.GetHellId();
290 SdrLayerID nFromHeavenLayerId
=
291 _bToVisible
? rIDDMA
.GetInvisibleHeavenId() : rIDDMA
.GetHeavenId();
292 SdrLayerID nFromControlLayerId
=
293 _bToVisible
? rIDDMA
.GetInvisibleControlsId() : rIDDMA
.GetControlsId();
295 if ( dynamic_cast<const SdrObjGroup
*>( _pDrawObj
) != nullptr )
297 // determine layer for group object
299 // proposed layer of a group object is the hell layer
300 SdrLayerID nNewLayerId
= nToHellLayerId
;
301 if ( ::CheckControlLayer( _pDrawObj
) )
303 // it has to be the control layer, if one of the member
305 nNewLayerId
= nToControlLayerId
;
307 else if ( _pDrawObj
->GetLayer() == rIDDMA
.GetHeavenId() ||
308 _pDrawObj
->GetLayer() == rIDDMA
.GetInvisibleHeavenId() )
310 // it has to be the heaven layer, if method <GetLayer()> reveals
312 nNewLayerId
= nToHeavenLayerId
;
314 // set layer at group object, but do *not* broadcast and
315 // no propagation to the members.
316 // Thus, call <NbcSetLayer(..)> at super class
317 _pDrawObj
->SdrObject::NbcSetLayer( nNewLayerId
);
320 // call method recursively for group object members
321 const SdrObjList
* pLst
=
322 static_cast<SdrObjGroup
*>(_pDrawObj
)->GetSubList();
325 for ( size_t i
= 0; i
< pLst
->GetObjCount(); ++i
)
327 MoveObjToLayer( _bToVisible
, pLst
->GetObj( i
) );
333 const SdrLayerID nLayerIdOfObj
= _pDrawObj
->GetLayer();
334 if ( nLayerIdOfObj
== nFromHellLayerId
)
336 _pDrawObj
->SetLayer( nToHellLayerId
);
338 else if ( nLayerIdOfObj
== nFromHeavenLayerId
)
340 _pDrawObj
->SetLayer( nToHeavenLayerId
);
342 else if ( nLayerIdOfObj
== nFromControlLayerId
)
344 _pDrawObj
->SetLayer( nToControlLayerId
);
349 /// get minimum order number of anchored objects handled by with contact
350 sal_uInt32
SwContact::GetMinOrdNum() const
352 sal_uInt32
nMinOrdNum( SAL_MAX_UINT32
);
354 std::vector
< SwAnchoredObject
* > aObjs
;
355 GetAnchoredObjs( aObjs
);
357 while ( !aObjs
.empty() )
359 sal_uInt32 nTmpOrdNum
= aObjs
.back()->GetDrawObj()->GetOrdNum();
361 if ( nTmpOrdNum
< nMinOrdNum
)
363 nMinOrdNum
= nTmpOrdNum
;
369 OSL_ENSURE( nMinOrdNum
!= SAL_MAX_UINT32
,
370 "<SwContact::GetMinOrdNum()> - no order number found." );
374 /// get maximum order number of anchored objects handled by with contact
375 sal_uInt32
SwContact::GetMaxOrdNum() const
377 sal_uInt32
nMaxOrdNum( 0 );
379 std::vector
< SwAnchoredObject
* > aObjs
;
380 GetAnchoredObjs( aObjs
);
382 while ( !aObjs
.empty() )
384 sal_uInt32 nTmpOrdNum
= aObjs
.back()->GetDrawObj()->GetOrdNum();
386 if ( nTmpOrdNum
> nMaxOrdNum
)
388 nMaxOrdNum
= nTmpOrdNum
;
399 Point
lcl_GetWW8Pos(SwAnchoredObject
const * pAnchoredObj
, const bool bFollowTextFlow
, sw::WW8AnchorConv
& reConv
)
403 case sw::WW8AnchorConv::CONV2PG
:
405 bool bRelToTableCell(false);
406 Point
aPos(pAnchoredObj
->GetRelPosToPageFrame(bFollowTextFlow
, bRelToTableCell
));
408 reConv
= sw::WW8AnchorConv::RELTOTABLECELL
;
411 case sw::WW8AnchorConv::CONV2COL_OR_PARA
:
412 return pAnchoredObj
->GetRelPosToAnchorFrame();
413 case sw::WW8AnchorConv::CONV2CHAR
:
414 return pAnchoredObj
->GetRelPosToChar();
415 case sw::WW8AnchorConv::CONV2LINE
:
416 return pAnchoredObj
->GetRelPosToLine();
422 void SwContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
424 // this does not call SwClient::SwClientNotify and thus doesn't handle RES_OBJECTDYING as usual. Is this intentional?
425 if (auto pFindSdrObjectHint
= dynamic_cast<const sw::FindSdrObjectHint
*>(&rHint
))
427 if(!pFindSdrObjectHint
->m_rpObject
)
428 pFindSdrObjectHint
->m_rpObject
= GetMaster();
430 else if (auto pWW8AnchorConvHint
= dynamic_cast<const sw::WW8AnchorConvHint
*>(&rHint
))
432 // determine anchored object
433 SwAnchoredObject
* pAnchoredObj(nullptr);
435 std::vector
<SwAnchoredObject
*> aAnchoredObjs
;
436 GetAnchoredObjs(aAnchoredObjs
);
437 if(!aAnchoredObjs
.empty())
438 pAnchoredObj
= aAnchoredObjs
.front();
440 // no anchored object found. Thus, the needed layout information can't
441 // be determined. --> no conversion
444 // no conversion for anchored drawing object, which aren't attached to an
446 // This is the case for drawing objects, which are anchored inside a page
447 // header/footer of an *unused* page style.
448 if(dynamic_cast<SwAnchoredDrawObject
*>(pAnchoredObj
) && !pAnchoredObj
->GetAnchorFrame())
450 const bool bFollowTextFlow
= static_cast<const SwFrameFormat
&>(rMod
).GetFollowTextFlow().GetValue();
451 sw::WW8AnchorConvResult
& rResult(pWW8AnchorConvHint
->m_rResult
);
452 // No distinction between layout directions, because of missing
453 // information about WW8 in vertical layout.
454 rResult
.m_aPos
.setX(lcl_GetWW8Pos(pAnchoredObj
, bFollowTextFlow
, rResult
.m_eHoriConv
).getX());
455 rResult
.m_aPos
.setY(lcl_GetWW8Pos(pAnchoredObj
, bFollowTextFlow
, rResult
.m_eVertConv
).getY());
456 rResult
.m_bConverted
= true;
461 SwFlyDrawContact::SwFlyDrawContact(
462 SwFlyFrameFormat
*pToRegisterIn
,
463 SdrModel
& rTargetModel
)
464 : SwContact(pToRegisterIn
),
465 mpMasterObj(new SwFlyDrawObj(rTargetModel
))
467 // #i26791# - class <SwFlyDrawContact> contains the 'master'
468 // drawing object of type <SwFlyDrawObj> on its own.
469 mpMasterObj
->SetOrdNum( 0xFFFFFFFE );
470 mpMasterObj
->SetUserCall( this );
473 SwFlyDrawContact::~SwFlyDrawContact()
477 mpMasterObj
->SetUserCall( nullptr );
478 if ( mpMasterObj
->getSdrPageFromSdrObject() )
479 mpMasterObj
->getSdrPageFromSdrObject()->RemoveObject( mpMasterObj
->GetOrdNum() );
483 sal_uInt32
SwFlyDrawContact::GetOrdNumForNewRef(const SwFlyFrame
* pFly
,
484 SwFrame
const& rAnchorFrame
)
486 // maintain invariant that a shape's textbox immediately follows the shape
487 // also for the multiple SdrVirtObj created for shapes in header/footer
488 if (SwFrameFormat
const*const pDrawFormat
=
489 SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT
))
491 // assume that the draw SdrVirtObj is always created before the flyframe one
492 if (SwSortedObjs
const*const pObjs
= rAnchorFrame
.GetDrawObjs())
494 for (SwAnchoredObject
const*const pAnchoredObj
: *pObjs
)
496 if (&pAnchoredObj
->GetFrameFormat() == pDrawFormat
)
498 return pAnchoredObj
->GetDrawObj()->GetOrdNum() + 1;
502 // if called from AppendObjs(), this is a problem; if called from lcl_SetFlyFrameAttr() it's not
503 SAL_INFO("sw", "GetOrdNumForNewRef: cannot find SdrObject for text box's shape");
505 // search for another Writer fly frame registered at same frame format
506 SwIterator
<SwFlyFrame
,SwFormat
> aIter(*GetFormat());
507 const SwFlyFrame
* pFlyFrame(nullptr);
508 for(pFlyFrame
= aIter
.First(); pFlyFrame
; pFlyFrame
= aIter
.Next())
510 if(pFlyFrame
!= pFly
)
516 // another Writer fly frame found. Take its order number
517 return pFlyFrame
->GetVirtDrawObj()->GetOrdNum();
519 // no other Writer fly frame found. Take order number of 'master' object
520 // #i35748# - use method <GetOrdNumDirect()> instead
521 // of method <GetOrdNum()> to avoid a recalculation of the order number,
522 // which isn't intended.
523 return GetMaster()->GetOrdNumDirect();
526 SwVirtFlyDrawObj
* SwFlyDrawContact::CreateNewRef(SwFlyFrame
* pFly
,
527 SwFlyFrameFormat
* pFormat
, SwFrame
const& rAnchorFrame
)
529 // Find ContactObject from the Format. If there's already one, we just
530 // need to create a new Ref, else we create the Contact now.
532 IDocumentDrawModelAccess
& rIDDMA
= pFormat
->getIDocumentDrawModelAccess();
533 SwFlyDrawContact
* pContact
= pFormat
->GetOrCreateContact();
534 SwVirtFlyDrawObj
* pDrawObj(
535 new SwVirtFlyDrawObj(
536 pContact
->GetMaster()->getSdrModelFromSdrObject(),
537 *pContact
->GetMaster(),
539 pDrawObj
->SetUserCall(pContact
);
541 // The Reader creates the Masters and inserts them into the Page in
542 // order to transport the z-order.
543 // After creating the first Reference the Masters are removed from the
544 // List and are not important anymore.
545 SdrPage
* pPg
= pContact
->GetMaster()->getSdrPageFromSdrObject();
548 const size_t nOrdNum
= pContact
->GetMaster()->GetOrdNum();
549 pPg
->ReplaceObject(pDrawObj
, nOrdNum
);
551 // #i27030# - insert new <SwVirtFlyDrawObj> instance
552 // into drawing page with correct order number
554 rIDDMA
.GetDrawModel()->GetPage(0)->InsertObject(pDrawObj
, pContact
->GetOrdNumForNewRef(pFly
, rAnchorFrame
));
555 // #i38889# - assure, that new <SwVirtFlyDrawObj> instance
556 // is in a visible layer.
557 pContact
->MoveObjToVisibleLayer(pDrawObj
);
562 const SwAnchoredObject
* SwFlyDrawContact::GetAnchoredObj(const SdrObject
* pSdrObj
) const
565 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(pSdrObj
) != nullptr);
566 assert(GetUserCall(pSdrObj
) == this &&
567 "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belong to this contact");
569 const SwAnchoredObject
*const pRetAnchoredObj
=
570 static_cast<const SwVirtFlyDrawObj
*>(pSdrObj
)->GetFlyFrame();
572 return pRetAnchoredObj
;
575 SwAnchoredObject
* SwFlyDrawContact::GetAnchoredObj(SdrObject
*const pSdrObj
)
577 return const_cast<SwAnchoredObject
*>(const_cast<SwFlyDrawContact
const*>(this)->GetAnchoredObj(pSdrObj
));
580 SdrObject
* SwFlyDrawContact::GetMaster()
582 return mpMasterObj
.get();
586 * @note Overriding method to control Writer fly frames, which are linked, and
587 * to assure that all objects anchored at/inside the Writer fly frame are
590 void SwFlyDrawContact::MoveObjToVisibleLayer( SdrObject
* _pDrawObj
)
592 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(_pDrawObj
) != nullptr);
594 if ( GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) )
600 SwFlyFrame
* pFlyFrame
= static_cast<SwVirtFlyDrawObj
*>(_pDrawObj
)->GetFlyFrame();
602 // #i44464# - consider, that Writer fly frame content
603 // already exists - (e.g. WW8 document is inserted into an existing document).
604 if ( !pFlyFrame
->Lower() )
606 pFlyFrame
->InsertColumns();
607 pFlyFrame
->Chain( pFlyFrame
->AnchorFrame() );
608 pFlyFrame
->InsertCnt();
610 if ( pFlyFrame
->GetDrawObjs() )
612 for (SwAnchoredObject
* i
: *pFlyFrame
->GetDrawObjs())
614 // #i28701# - consider type of objects in sorted object list.
615 SdrObject
* pObj
= i
->DrawObj();
616 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
617 pContact
->MoveObjToVisibleLayer( pObj
);
621 // make fly frame visible
622 SwContact::MoveObjToVisibleLayer( _pDrawObj
);
626 * @note Override method to control Writer fly frames, which are linked, and
627 * to assure that all objects anchored at/inside the Writer fly frame are
628 * also made invisible.
630 void SwFlyDrawContact::MoveObjToInvisibleLayer( SdrObject
* _pDrawObj
)
632 assert(dynamic_cast<const SwVirtFlyDrawObj
*>(_pDrawObj
) != nullptr);
634 if ( !GetFormat()->getIDocumentDrawModelAccess().IsVisibleLayerId( _pDrawObj
->GetLayer() ) )
640 SwFlyFrame
* pFlyFrame
= static_cast<SwVirtFlyDrawObj
*>(_pDrawObj
)->GetFlyFrame();
642 pFlyFrame
->Unchain();
643 pFlyFrame
->DeleteCnt();
644 if ( pFlyFrame
->GetDrawObjs() )
646 for (SwAnchoredObject
* i
: *pFlyFrame
->GetDrawObjs())
648 // #i28701# - consider type of objects in sorted object list.
649 SdrObject
* pObj
= i
->DrawObj();
650 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
651 pContact
->MoveObjToInvisibleLayer( pObj
);
655 // make fly frame invisible
656 SwContact::MoveObjToInvisibleLayer( _pDrawObj
);
659 /// get data collection of anchored objects, handled by with contact
660 void SwFlyDrawContact::GetAnchoredObjs( std::vector
<SwAnchoredObject
*>& _roAnchoredObjs
) const
662 const SwFrameFormat
* pFormat
= GetFormat();
663 SwFlyFrame::GetAnchoredObjects( _roAnchoredObjs
, *pFormat
);
665 void SwFlyDrawContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
667 SwContact::SwClientNotify(rMod
, rHint
);
668 if(auto pGetZOrdnerHint
= dynamic_cast<const sw::GetZOrderHint
*>(&rHint
))
671 // This also needs to work when no layout exists. Thus, for
672 // FlyFrames an alternative method is used now in that case.
673 auto pFormat(dynamic_cast<const SwFrameFormat
*>(&rMod
));
674 if (pFormat
&& pFormat
->Which() == RES_FLYFRMFMT
&& !pFormat
->getIDocumentLayoutAccess().GetCurrentViewShell())
675 pGetZOrdnerHint
->m_rnZOrder
= GetMaster()->GetOrdNum();
681 bool CheckControlLayer( const SdrObject
*pObj
)
683 if ( SdrInventor::FmForm
== pObj
->GetObjInventor() )
685 if (const SdrObjGroup
*pObjGroup
= dynamic_cast<const SdrObjGroup
*>(pObj
))
687 const SdrObjList
*pLst
= pObjGroup
->GetSubList();
688 for ( size_t i
= 0; i
< pLst
->GetObjCount(); ++i
)
690 if ( ::CheckControlLayer( pLst
->GetObj( i
) ) )
692 // #i18447# - return correct value ;-)
700 SwDrawContact::SwDrawContact( SwFrameFormat
* pToRegisterIn
, SdrObject
* pObj
) :
701 SwContact( pToRegisterIn
),
703 mbMasterObjCleared( false ),
704 mbDisconnectInProgress( false ),
705 mbUserCallActive( false ),
706 // Note: value of <meEventTypeOfCurrentUserCall> isn't of relevance, because
707 // <mbUserCallActive> is false.
708 meEventTypeOfCurrentUserCall( SdrUserCallType::MoveOnly
)
710 // --> #i33909# - assure, that drawing object is inserted
711 // in the drawing page.
712 if ( !pObj
->IsInserted() )
714 pToRegisterIn
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
715 InsertObject( pObj
, pObj
->GetOrdNumDirect() );
718 // Controls have to be always in the Control-Layer. This is also true for
719 // group objects, if they contain controls.
720 if ( ::CheckControlLayer( pObj
) )
722 // set layer of object to corresponding invisible layer.
723 pObj
->SetLayer( pToRegisterIn
->getIDocumentDrawModelAccess().GetInvisibleControlsId() );
727 pObj
->SetUserCall( this );
728 maAnchoredDrawObj
.SetDrawObj( *pObj
);
730 // if there already exists an SwXShape for the object, ensure it knows about us, and the SdrObject
732 SwXShape::AddExistingShapeToFormat( *pObj
);
735 SwDrawContact::~SwDrawContact()
739 DisconnectFromLayout();
741 // remove 'master' from drawing page
742 RemoveMasterFromDrawPage();
744 // remove and destroy 'virtual' drawing objects.
747 if ( !mbMasterObjCleared
)
749 SdrObject
* pObject
= const_cast< SdrObject
* >( maAnchoredDrawObj
.GetDrawObj() );
750 SdrObject::Free( pObject
);
754 void SwDrawContact::GetTextObjectsFromFormat(std::list
<SdrTextObj
*>& o_rTextObjects
, SwDoc
& rDoc
)
756 for(auto& rpFly
: *rDoc
.GetSpzFrameFormats())
758 if(dynamic_cast<const SwDrawFrameFormat
*>(rpFly
))
759 rpFly
->CallSwClientNotify(sw::CollectTextObjectsHint(o_rTextObjects
));
764 const SwAnchoredObject
* SwDrawContact::GetAnchoredObj(const SdrObject
* pSdrObj
) const
766 // handle default parameter value
769 pSdrObj
= GetMaster();
773 assert(dynamic_cast<const SwDrawVirtObj
*>(pSdrObj
) != nullptr ||
774 dynamic_cast<const SdrVirtObj
*>(pSdrObj
) == nullptr);
775 assert((GetUserCall(pSdrObj
) == this ||
776 pSdrObj
== GetMaster()) &&
777 "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
779 const SwAnchoredObject
* pRetAnchoredObj
= nullptr;
781 if (auto pVirtObj
= dynamic_cast<const SwDrawVirtObj
*>(pSdrObj
))
783 pRetAnchoredObj
= &(pVirtObj
->GetAnchoredObj());
787 assert(dynamic_cast<const SdrVirtObj
*>(pSdrObj
) == nullptr);
788 pRetAnchoredObj
= &maAnchoredDrawObj
;
791 return pRetAnchoredObj
;
794 SwAnchoredObject
* SwDrawContact::GetAnchoredObj(SdrObject
*const pSdrObj
)
796 return const_cast<SwAnchoredObject
*>(const_cast<SwDrawContact
const*>(this)->GetAnchoredObj(pSdrObj
));
799 SdrObject
* SwDrawContact::GetMaster()
801 return !mbMasterObjCleared
802 ? maAnchoredDrawObj
.DrawObj()
806 const SwFrame
* SwDrawContact::GetAnchorFrame( const SdrObject
* _pDrawObj
) const
808 const SwFrame
* pAnchorFrame
= nullptr;
810 _pDrawObj
== GetMaster() ||
811 ( !_pDrawObj
->GetUserCall() &&
812 GetUserCall( _pDrawObj
) == this ) )
814 pAnchorFrame
= maAnchoredDrawObj
.GetAnchorFrame();
818 assert(dynamic_cast<SwDrawVirtObj
const*>(_pDrawObj
) != nullptr);
819 pAnchorFrame
= static_cast<const SwDrawVirtObj
*>(_pDrawObj
)->GetAnchorFrame();
825 SwFrame
* SwDrawContact::GetAnchorFrame(SdrObject
const *const pDrawObj
)
827 return const_cast<SwFrame
*>(const_cast<SwDrawContact
const*>(this)->GetAnchorFrame(pDrawObj
));
830 /** add a 'virtual' drawing object to drawing page.
832 SwDrawVirtObj
* SwDrawContact::AddVirtObj(SwFrame
const& rAnchorFrame
)
834 maDrawVirtObjs
.push_back(
837 GetMaster()->getSdrModelFromSdrObject(),
840 maDrawVirtObjs
.back()->AddToDrawingPage(rAnchorFrame
);
841 return maDrawVirtObjs
.back().get();
844 /// remove 'virtual' drawing objects and destroy them.
845 void SwDrawContact::RemoveAllVirtObjs()
847 for(auto& rpDrawVirtObj
: maDrawVirtObjs
)
849 // remove and destroy 'virtual object'
850 rpDrawVirtObj
->RemoveFromWriterLayout();
851 rpDrawVirtObj
->RemoveFromDrawingPage();
853 maDrawVirtObjs
.clear();
857 /// get drawing object ('master' or 'virtual') by frame.
858 SdrObject
* SwDrawContact::GetDrawObjectByAnchorFrame( const SwFrame
& _rAnchorFrame
)
860 SdrObject
* pRetDrawObj
= nullptr;
862 // #i26791# - compare master frames instead of direct frames
863 const SwFrame
* pProposedAnchorFrame
= &_rAnchorFrame
;
864 if ( pProposedAnchorFrame
->IsContentFrame() )
866 const SwContentFrame
* pTmpFrame
=
867 static_cast<const SwContentFrame
*>( pProposedAnchorFrame
);
868 while ( pTmpFrame
->IsFollow() )
870 pTmpFrame
= pTmpFrame
->FindMaster();
872 pProposedAnchorFrame
= pTmpFrame
;
875 const SwFrame
* pMasterObjAnchorFrame
= GetAnchorFrame();
876 if ( pMasterObjAnchorFrame
&& pMasterObjAnchorFrame
->IsContentFrame() )
878 const SwContentFrame
* pTmpFrame
=
879 static_cast<const SwContentFrame
*>( pMasterObjAnchorFrame
);
880 while ( pTmpFrame
->IsFollow() )
882 pTmpFrame
= pTmpFrame
->FindMaster();
884 pMasterObjAnchorFrame
= pTmpFrame
;
887 if ( pMasterObjAnchorFrame
&& pMasterObjAnchorFrame
== pProposedAnchorFrame
)
889 pRetDrawObj
= GetMaster();
893 const auto ppFoundVirtObj(std::find_if(maDrawVirtObjs
.begin(), maDrawVirtObjs
.end(),
894 VirtObjAnchoredAtFramePred(pProposedAnchorFrame
)));
895 if(ppFoundVirtObj
!= maDrawVirtObjs
.end())
896 pRetDrawObj
= ppFoundVirtObj
->get();
902 void SwDrawContact::NotifyBackgrdOfAllVirtObjs(const tools::Rectangle
* pOldBoundRect
)
904 for(const auto& rpDrawVirtObj
: maDrawVirtObjs
)
906 SwDrawVirtObj
* pDrawVirtObj(rpDrawVirtObj
.get());
907 if ( pDrawVirtObj
->GetAnchorFrame() )
909 // #i34640# - determine correct page frame
910 SwPageFrame
* pPage
= pDrawVirtObj
->AnchoredObj().FindPageFrameOfAnchor();
911 if( pOldBoundRect
&& pPage
)
913 SwRect
aOldRect( *pOldBoundRect
);
914 aOldRect
.Pos() += pDrawVirtObj
->GetOffset();
915 if( aOldRect
.HasArea() )
916 ::Notify_Background( pDrawVirtObj
, pPage
,
917 aOldRect
, PrepareHint::FlyFrameLeave
,true);
919 // #i34640# - include spacing for wrapping
920 SwRect
aRect( pDrawVirtObj
->GetAnchoredObj().GetObjRectWithSpaces() );
921 if (aRect
.HasArea() && pPage
)
923 SwPageFrame
* pPg
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aRect
, pPage
)));
925 ::Notify_Background( pDrawVirtObj
, pPg
, aRect
,
926 PrepareHint::FlyFrameArrive
, true );
928 ::ClrContourCache( pDrawVirtObj
);
933 /// local method to notify the background for a drawing object - #i26791#
934 static void lcl_NotifyBackgroundOfObj( SwDrawContact
const & _rDrawContact
,
935 const SdrObject
& _rObj
,
936 const tools::Rectangle
* _pOldObjRect
)
939 SwAnchoredObject
* pAnchoredObj
=
940 const_cast<SwAnchoredObject
*>(_rDrawContact
.GetAnchoredObj( &_rObj
));
941 if ( !(pAnchoredObj
&& pAnchoredObj
->GetAnchorFrame()) )
944 // #i34640# - determine correct page frame
945 SwPageFrame
* pPageFrame
= pAnchoredObj
->FindPageFrameOfAnchor();
946 if( _pOldObjRect
&& pPageFrame
)
948 SwRect
aOldRect( *_pOldObjRect
);
949 if( aOldRect
.HasArea() )
951 // #i34640# - determine correct page frame
952 SwPageFrame
* pOldPageFrame
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aOldRect
, pPageFrame
)));
953 ::Notify_Background( &_rObj
, pOldPageFrame
, aOldRect
,
954 PrepareHint::FlyFrameLeave
, true);
957 // #i34640# - include spacing for wrapping
958 SwRect
aNewRect( pAnchoredObj
->GetObjRectWithSpaces() );
959 if( aNewRect
.HasArea() && pPageFrame
)
961 pPageFrame
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( aNewRect
, pPageFrame
)));
962 ::Notify_Background( &_rObj
, pPageFrame
, aNewRect
,
963 PrepareHint::FlyFrameArrive
, true );
965 ClrContourCache( &_rObj
);
968 void SwDrawContact::Changed( const SdrObject
& rObj
,
969 SdrUserCallType eType
,
970 const tools::Rectangle
& rOldBoundRect
)
972 // #i26791# - no event handling, if existing <SwViewShell>
973 // is in construction
974 SwDoc
* pDoc
= GetFormat()->GetDoc();
975 if ( pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() &&
976 pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell()->IsInConstructor() )
982 // no event handling, if document is in destruction.
983 // Exception: It's the SdrUserCallType::Delete event
984 if ( pDoc
->IsInDtor() && eType
!= SdrUserCallType::Delete
)
989 //Put on Action, but not if presently anywhere an action runs.
990 bool bHasActions(true);
991 SwRootFrame
*pTmpRoot
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
992 if ( pTmpRoot
&& pTmpRoot
->IsCallbackActionEnabled() )
994 SwViewShell
* const pSh
= pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
997 for(SwViewShell
& rShell
: pSh
->GetRingContainer() )
999 if ( rShell
.Imp()->IsAction() || rShell
.Imp()->IsIdleAction() )
1004 bHasActions
= false;
1008 pTmpRoot
->StartAllAction();
1010 SdrObjUserCall::Changed( rObj
, eType
, rOldBoundRect
);
1011 Changed_( rObj
, eType
, &rOldBoundRect
); //Attention, possibly suicidal!
1014 pTmpRoot
->EndAllAction();
1017 /// helper class for method <SwDrawContact::Changed_(..)> for handling nested
1018 /// <SdrObjUserCall> events
1019 class NestedUserCallHdl
1022 SwDrawContact
* mpDrawContact
;
1023 bool mbParentUserCallActive
;
1024 SdrUserCallType meParentUserCallEventType
;
1027 NestedUserCallHdl( SwDrawContact
* _pDrawContact
,
1028 SdrUserCallType _eEventType
)
1029 : mpDrawContact( _pDrawContact
),
1030 mbParentUserCallActive( _pDrawContact
->mbUserCallActive
),
1031 meParentUserCallEventType( _pDrawContact
->meEventTypeOfCurrentUserCall
)
1033 mpDrawContact
->mbUserCallActive
= true;
1034 mpDrawContact
->meEventTypeOfCurrentUserCall
= _eEventType
;
1037 ~NestedUserCallHdl()
1039 if ( mpDrawContact
)
1041 mpDrawContact
->mbUserCallActive
= mbParentUserCallActive
;
1042 mpDrawContact
->meEventTypeOfCurrentUserCall
= meParentUserCallEventType
;
1046 void DrawContactDeleted()
1048 mpDrawContact
= nullptr;
1051 bool IsNestedUserCall() const
1053 return mbParentUserCallActive
;
1056 void AssertNestedUserCall()
1058 if ( !IsNestedUserCall() )
1061 bool bTmpAssert( true );
1062 // Currently its known, that a nested event SdrUserCallType::Resize
1063 // could occur during parent user call SdrUserCallType::Inserted,
1064 // SdrUserCallType::Delete and SdrUserCallType::Resize for edge objects.
1065 // Also possible are nested SdrUserCallType::ChildResize events for
1067 // Thus, assert all other combinations
1068 if ( ( meParentUserCallEventType
== SdrUserCallType::Inserted
||
1069 meParentUserCallEventType
== SdrUserCallType::Delete
||
1070 meParentUserCallEventType
== SdrUserCallType::Resize
) &&
1071 mpDrawContact
->meEventTypeOfCurrentUserCall
== SdrUserCallType::Resize
)
1075 else if ( meParentUserCallEventType
== SdrUserCallType::ChildResize
&&
1076 mpDrawContact
->meEventTypeOfCurrentUserCall
== SdrUserCallType::ChildResize
)
1083 OSL_FAIL( "<SwDrawContact::Changed_(..)> - unknown nested <UserCall> event. This is serious." );
1088 /// Notify the format's textbox that it should reconsider its position / size.
1089 static void lcl_textBoxSizeNotify(SwFrameFormat
* pFormat
)
1091 if (SwTextBoxHelper::isTextBox(pFormat
, RES_DRAWFRMFMT
))
1093 // Just notify the textbox that the size has changed, the actual object size is not interesting.
1094 SfxItemSet
aResizeSet(pFormat
->GetDoc()->GetAttrPool(), svl::Items
<RES_FRM_SIZE
, RES_FRM_SIZE
>{});
1095 SwFormatFrameSize aSize
;
1096 aResizeSet
.Put(aSize
);
1097 SwTextBoxHelper::syncFlyFrameAttr(*pFormat
, aResizeSet
);
1101 // !!!ATTENTION!!! The object may commit suicide!!!
1103 void SwDrawContact::Changed_( const SdrObject
& rObj
,
1104 SdrUserCallType eType
,
1105 const tools::Rectangle
* pOldBoundRect
)
1107 // suppress handling of nested <SdrObjUserCall> events
1108 NestedUserCallHdl
aNestedUserCallHdl( this, eType
);
1109 if ( aNestedUserCallHdl
.IsNestedUserCall() )
1111 aNestedUserCallHdl
.AssertNestedUserCall();
1114 // do *not* notify, if document is destructing
1115 // #i35912# - do *not* notify for as-character anchored
1118 // improvement: determine as-character anchored object flag only once.
1119 const bool bAnchoredAsChar
= ObjAnchoredAsChar();
1120 const bool bNotify
= !(GetFormat()->GetDoc()->IsInDtor()) &&
1121 ( css::text::WrapTextMode_THROUGH
!= GetFormat()->GetSurround().GetSurround() ) &&
1125 case SdrUserCallType::Delete
:
1129 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1130 // --> #i36181# - background of 'virtual'
1131 // drawing objects have also been notified.
1132 NotifyBackgrdOfAllVirtObjs( pOldBoundRect
);
1134 DisconnectFromLayout( false );
1135 mbMasterObjCleared
= true;
1137 // --> #i65784# Prevent memory corruption
1138 aNestedUserCallHdl
.DrawContactDeleted();
1141 case SdrUserCallType::Inserted
:
1143 if ( mbDisconnectInProgress
)
1145 OSL_FAIL( "<SwDrawContact::Changed_(..)> - Insert event during disconnection from layout is invalid." );
1152 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1157 case SdrUserCallType::Removed
:
1161 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1163 DisconnectFromLayout( false );
1166 case SdrUserCallType::ChildInserted
:
1167 case SdrUserCallType::ChildRemoved
:
1170 // force layer of controls for group objects containing control objects
1171 if(dynamic_cast< SdrObjGroup
* >(maAnchoredDrawObj
.DrawObj()))
1173 if(::CheckControlLayer(maAnchoredDrawObj
.DrawObj()))
1175 const IDocumentDrawModelAccess
& rIDDMA
= static_cast<SwFrameFormat
*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
1176 const SdrLayerID
aCurrentLayer(maAnchoredDrawObj
.DrawObj()->GetLayer());
1177 const SdrLayerID
aControlLayerID(rIDDMA
.GetControlsId());
1178 const SdrLayerID
aInvisibleControlLayerID(rIDDMA
.GetInvisibleControlsId());
1180 if(aCurrentLayer
!= aControlLayerID
&& aCurrentLayer
!= aInvisibleControlLayerID
)
1182 if ( aCurrentLayer
== rIDDMA
.GetInvisibleHellId() ||
1183 aCurrentLayer
== rIDDMA
.GetInvisibleHeavenId() )
1185 maAnchoredDrawObj
.DrawObj()->SetLayer(aInvisibleControlLayerID
);
1189 maAnchoredDrawObj
.DrawObj()->SetLayer(aControlLayerID
);
1196 case SdrUserCallType::MoveOnly
:
1197 case SdrUserCallType::Resize
:
1198 case SdrUserCallType::ChildMoveOnly
:
1199 case SdrUserCallType::ChildResize
:
1200 case SdrUserCallType::ChildChangeAttr
:
1201 case SdrUserCallType::ChildDelete
:
1203 // #i31698# - improvement
1204 // get instance <SwAnchoredDrawObject> only once
1205 const SwAnchoredDrawObject
* pAnchoredDrawObj
=
1206 static_cast<const SwAnchoredDrawObject
*>( GetAnchoredObj( &rObj
) );
1208 /* protect against NULL pointer dereferencing */
1209 if(!pAnchoredDrawObj
)
1214 // #i26791# - adjust positioning and alignment attributes,
1215 // if positioning of drawing object isn't in progress.
1216 // #i53320# - no adjust of positioning attributes,
1217 // if drawing object isn't positioned.
1218 if ( !pAnchoredDrawObj
->IsPositioningInProgress() &&
1219 !pAnchoredDrawObj
->NotYetPositioned() )
1221 // #i34748# - If no last object rectangle is
1222 // provided by the anchored object, use parameter <pOldBoundRect>.
1223 const tools::Rectangle
& aOldObjRect
= pAnchoredDrawObj
->GetLastObjRect()
1224 ? *(pAnchoredDrawObj
->GetLastObjRect())
1227 // always invalidate object rectangle inclusive spaces
1228 pAnchoredDrawObj
->InvalidateObjRectWithSpaces();
1229 // #i41324# - notify background before
1230 // adjusting position
1233 // #i31573# - correction
1234 // background of given drawing object.
1235 lcl_NotifyBackgroundOfObj( *this, rObj
, &aOldObjRect
);
1237 // #i31698# - determine layout direction
1238 // via draw frame format.
1239 SwFrameFormat::tLayoutDir eLayoutDir
=
1240 pAnchoredDrawObj
->GetFrameFormat().GetLayoutDir();
1241 // use geometry of drawing object
1242 SwRect
aObjRect( rObj
.GetSnapRect() );
1243 // If drawing object is a member of a group, the adjustment
1244 // of the positioning and the alignment attributes has to
1245 // be done for the top group object.
1246 if ( rObj
.getParentSdrObjectFromSdrObject() )
1248 const SdrObject
* pGroupObj
= rObj
.getParentSdrObjectFromSdrObject();
1249 while ( pGroupObj
->getParentSdrObjectFromSdrObject() )
1251 pGroupObj
= pGroupObj
->getParentSdrObjectFromSdrObject();
1253 // use geometry of drawing object
1254 aObjRect
= pGroupObj
->GetSnapRect();
1256 SwTwips
nXPosDiff(0);
1257 SwTwips
nYPosDiff(0);
1258 switch ( eLayoutDir
)
1260 case SwFrameFormat::HORI_L2R
:
1262 nXPosDiff
= aObjRect
.Left() - aOldObjRect
.Left();
1263 nYPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1266 case SwFrameFormat::HORI_R2L
:
1268 nXPosDiff
= aOldObjRect
.Right() - aObjRect
.Right();
1269 nYPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1272 case SwFrameFormat::VERT_R2L
:
1274 nXPosDiff
= aObjRect
.Top() - aOldObjRect
.Top();
1275 nYPosDiff
= aOldObjRect
.Right() - aObjRect
.Right();
1280 assert(!"<SwDrawContact::Changed_(..)> - unsupported layout direction");
1283 SfxItemSet
aSet( GetFormat()->GetDoc()->GetAttrPool(),
1284 svl::Items
<RES_VERT_ORIENT
, RES_HORI_ORIENT
>{} );
1285 const SwFormatVertOrient
& rVert
= GetFormat()->GetVertOrient();
1286 if ( nYPosDiff
!= 0 )
1288 if ( rVert
.GetRelationOrient() == text::RelOrientation::CHAR
||
1289 rVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
1291 nYPosDiff
= -nYPosDiff
;
1293 aSet
.Put( SwFormatVertOrient( rVert
.GetPos()+nYPosDiff
,
1294 text::VertOrientation::NONE
,
1295 rVert
.GetRelationOrient() ) );
1298 const SwFormatHoriOrient
& rHori
= GetFormat()->GetHoriOrient();
1299 if ( !bAnchoredAsChar
&& nXPosDiff
!= 0 )
1301 aSet
.Put( SwFormatHoriOrient( rHori
.GetPos()+nXPosDiff
,
1302 text::HoriOrientation::NONE
,
1303 rHori
.GetRelationOrient() ) );
1307 ( !bAnchoredAsChar
&& nXPosDiff
!= 0 ) )
1309 GetFormat()->GetDoc()->SetFlyFrameAttr( *(GetFormat()), aSet
);
1310 // keep new object rectangle, to avoid multiple
1311 // changes of the attributes by multiple event from
1312 // the drawing layer - e.g. group objects and its members
1313 // #i34748# - use new method
1314 // <SwAnchoredDrawObject::SetLastObjRect(..)>.
1315 const_cast<SwAnchoredDrawObject
*>(pAnchoredDrawObj
)
1316 ->SetLastObjRect( aObjRect
.SVRect() );
1318 else if ( aObjRect
.SSize() != aOldObjRect
.GetSize() )
1321 // #i35007# - notify anchor frame
1322 // of as-character anchored object
1323 if ( bAnchoredAsChar
)
1325 SwFrame
* pAnchorFrame
= const_cast<SwAnchoredDrawObject
*>(pAnchoredDrawObj
)->AnchorFrame();
1328 pAnchorFrame
->Prepare( PrepareHint::FlyFrameAttributesChanged
, GetFormat() );
1332 lcl_textBoxSizeNotify(GetFormat());
1334 else if (eType
== SdrUserCallType::Resize
)
1335 // Even if the bounding box of the shape didn't change,
1336 // notify about the size change, as an adjustment change
1337 // may affect the size of the underlying textbox.
1338 lcl_textBoxSizeNotify(GetFormat());
1341 // tdf#135198: keep text box together with its shape
1342 SwRect
aObjRect(rObj
.GetSnapRect());
1343 const SwPageFrame
* rPageFrame
= pAnchoredDrawObj
->GetPageFrame();
1344 if (rPageFrame
&& rPageFrame
->isFrameAreaPositionValid())
1346 SwDoc
* const pDoc
= GetFormat()->GetDoc();
1348 // avoid Undo creation
1349 ::sw::UndoGuard
const ug(pDoc
->GetIDocumentUndoRedo());
1351 // hide any artificial "changes" made by synchronizing the textbox position
1352 const bool bEnableSetModified
= pDoc
->getIDocumentState().IsEnableSetModified();
1353 pDoc
->getIDocumentState().SetEnableSetModified(false);
1355 SfxItemSet
aSyncSet(pDoc
->GetAttrPool(),
1356 svl::Items
<RES_VERT_ORIENT
, RES_ANCHOR
>{});
1357 aSyncSet
.Put(SwFormatVertOrient(aObjRect
.Top() - rPageFrame
->getFrameArea().Top(),
1358 text::VertOrientation::NONE
,
1359 text::RelOrientation::PAGE_FRAME
));
1360 aSyncSet
.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE
, pAnchoredDrawObj
->GetPageFrame()->GetPhyPageNum()));
1362 SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSyncSet
);
1364 pDoc
->getIDocumentState().SetEnableSetModified(bEnableSetModified
);
1368 case SdrUserCallType::ChangeAttr
:
1371 lcl_NotifyBackgroundOfObj( *this, rObj
, pOldBoundRect
);
1381 const SwFormatAnchor
* lcl_getAnchorFormat( const SfxPoolItem
& _rItem
)
1383 sal_uInt16 nWhich
= _rItem
.Which();
1384 const SwFormatAnchor
* pAnchorFormat
= nullptr;
1385 if ( RES_ATTRSET_CHG
== nWhich
)
1387 static_cast<const SwAttrSetChg
&>(_rItem
).GetChgSet()->
1388 GetItemState( RES_ANCHOR
, false, reinterpret_cast<const SfxPoolItem
**>(&pAnchorFormat
) );
1390 else if ( RES_ANCHOR
== nWhich
)
1392 pAnchorFormat
= &static_cast<const SwFormatAnchor
&>(_rItem
);
1394 return pAnchorFormat
;
1398 void SwDrawContact::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
1400 SwClient::SwClientNotify(rMod
, rHint
); // needed as SwContact::SwClientNotify doesn't explicitly call SwClient::SwClientNotify
1401 SwContact::SwClientNotify(rMod
, rHint
);
1402 if (auto pLegacyHint
= dynamic_cast<const sw::LegacyModifyHint
*>(&rHint
))
1404 SAL_WARN_IF(mbDisconnectInProgress
, "sw.core", "<SwDrawContact::Modify(..)> called during disconnection.");
1406 const SfxPoolItem
* pNew
= pLegacyHint
->m_pNew
;
1407 sal_uInt16 nWhich
= pNew
? pNew
->Which() : 0;
1408 if(const SwFormatAnchor
* pNewAnchorFormat
= pNew
? lcl_getAnchorFormat(*pNew
) : nullptr)
1410 // Do not respond to a Reset Anchor!
1411 if(GetFormat()->GetAttrSet().GetItemState(RES_ANCHOR
, false) == SfxItemState::SET
)
1413 // no connect to layout during disconnection
1414 if(!mbDisconnectInProgress
)
1416 // determine old object rectangle of 'master' drawing object
1418 const tools::Rectangle
* pOldRect
= nullptr;
1419 tools::Rectangle aOldRect
;
1420 if(GetAnchorFrame())
1422 // --> #i36181# - include spacing in object
1423 // rectangle for notification.
1424 aOldRect
= maAnchoredDrawObj
.GetObjRectWithSpaces().SVRect();
1425 pOldRect
= &aOldRect
;
1427 // re-connect to layout due to anchor format change
1428 ConnectToLayout(pNewAnchorFormat
);
1429 // notify background of drawing objects
1430 lcl_NotifyBackgroundOfObj(*this, *GetMaster(), pOldRect
);
1431 NotifyBackgrdOfAllVirtObjs(pOldRect
);
1433 const SwFormatAnchor
* pOldAnchorFormat
= pLegacyHint
->m_pOld
? lcl_getAnchorFormat(*pLegacyHint
->m_pOld
) : nullptr;
1434 if(!pOldAnchorFormat
|| (pOldAnchorFormat
->GetAnchorId() != pNewAnchorFormat
->GetAnchorId()))
1436 if(maAnchoredDrawObj
.DrawObj())
1439 // assure that a ShapePropertyChangeNotifier exists
1440 maAnchoredDrawObj
.DrawObj()->notifyShapePropertyChange(svx::ShapeProperty::TextDocAnchor
);
1443 SAL_WARN("sw.core", "SwDrawContact::Modify: no draw object here?");
1448 DisconnectFromLayout();
1450 else if (nWhich
== RES_REMOVE_UNO_OBJECT
)
1452 // --> #i62875# - no further notification, if not connected to Writer layout
1453 else if ( maAnchoredDrawObj
.GetAnchorFrame() &&
1454 maAnchoredDrawObj
.GetDrawObj()->GetUserCall() )
1456 bool bUpdateSortedObjsList(false);
1461 case RES_HORI_ORIENT
:
1462 case RES_VERT_ORIENT
:
1463 case RES_FOLLOW_TEXT_FLOW
: // #i28701# - add attribute 'Follow text flow'
1467 case RES_WRAP_INFLUENCE_ON_OBJPOS
:
1468 // --> #i28701# - on change of wrapping style, hell|heaven layer,
1469 // or wrapping style influence an update of the <SwSortedObjs> list,
1470 // the drawing object is registered in, has to be performed. This is triggered
1471 // by the 1st parameter of method call <InvalidateObjs_(..)>.
1472 bUpdateSortedObjsList
= true;
1474 case RES_ATTRSET_CHG
: // #i35443#
1476 auto pChgSet
= static_cast<const SwAttrSetChg
*>(pNew
)->GetChgSet();
1477 if(pChgSet
->GetItemState(RES_SURROUND
, false) == SfxItemState::SET
||
1478 pChgSet
->GetItemState(RES_OPAQUE
, false) == SfxItemState::SET
||
1479 pChgSet
->GetItemState(RES_WRAP_INFLUENCE_ON_OBJPOS
, false) == SfxItemState::SET
)
1480 bUpdateSortedObjsList
= true;
1484 assert(!"<SwDraw Contact::Modify(..)> - unhandled attribute?");
1486 lcl_NotifyBackgroundOfObj(*this, *GetMaster(), nullptr);
1487 NotifyBackgrdOfAllVirtObjs(nullptr);
1488 InvalidateObjs_(bUpdateSortedObjsList
);
1492 GetAnchoredObj(nullptr)->ResetLayoutProcessBools();
1494 else if (auto pDrawFrameFormatHint
= dynamic_cast<const sw::DrawFrameFormatHint
*>(&rHint
))
1496 switch(pDrawFrameFormatHint
->m_eId
)
1498 case sw::DrawFrameFormatHintId::DYING
:
1501 case sw::DrawFrameFormatHintId::PREPPASTING
:
1502 MoveObjToVisibleLayer(GetMaster());
1504 case sw::DrawFrameFormatHintId::PREP_INSERT_FLY
:
1505 InsertMasterIntoDrawPage();
1506 // #i40845# - follow-up of #i35635#
1507 // move object to visible layer
1508 MoveObjToVisibleLayer(GetMaster());
1509 // tdf#135661 InsertMasterIntoDrawPage may have created a new
1510 // SwXShape with null m_pFormat; fix that
1511 SwXShape::AddExistingShapeToFormat(*GetMaster());
1513 case sw::DrawFrameFormatHintId::PREP_DELETE_FLY
:
1514 RemoveMasterFromDrawPage();
1516 case sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS
:
1517 case sw::DrawFrameFormatHintId::DELETE_FRAMES
:
1518 DisconnectFromLayout();
1520 case sw::DrawFrameFormatHintId::MAKE_FRAMES
:
1523 case sw::DrawFrameFormatHintId::POST_RESTORE_FLY_ANCHOR
:
1524 GetAnchoredObj(GetMaster())->MakeObjPos();
1530 else if (auto pCheckDrawFrameFormatLayerHint
= dynamic_cast<const sw::CheckDrawFrameFormatLayerHint
*>(&rHint
))
1532 *(pCheckDrawFrameFormatLayerHint
->m_bCheckControlLayer
) |= (GetMaster() && CheckControlLayer(GetMaster()));
1534 else if (auto pContactChangedHint
= dynamic_cast<const sw::ContactChangedHint
*>(&rHint
))
1536 if(!*pContactChangedHint
->m_ppObject
)
1537 *pContactChangedHint
->m_ppObject
= GetMaster();
1538 auto pObject
= *pContactChangedHint
->m_ppObject
;
1539 Changed(*pObject
, SdrUserCallType::Delete
, pObject
->GetLastBoundRect());
1541 else if (auto pDrawFormatLayoutCopyHint
= dynamic_cast<const sw::DrawFormatLayoutCopyHint
*>(&rHint
))
1543 const SwDrawFrameFormat
& rFormat
= static_cast<const SwDrawFrameFormat
&>(rMod
);
1545 &pDrawFormatLayoutCopyHint
->m_rDestFormat
,
1546 pDrawFormatLayoutCopyHint
->m_rDestDoc
.CloneSdrObj(
1548 pDrawFormatLayoutCopyHint
->m_rDestDoc
.IsCopyIsMove() && &pDrawFormatLayoutCopyHint
->m_rDestDoc
== rFormat
.GetDoc()));
1549 // #i49730# - notify draw frame format that position attributes are
1550 // already set, if the position attributes are already set at the
1551 // source draw frame format.
1552 if(rFormat
.IsPosAttrSet())
1553 pDrawFormatLayoutCopyHint
->m_rDestFormat
.PosAttrSet();
1555 else if (auto pRestoreFlyAnchorHint
= dynamic_cast<const sw::RestoreFlyAnchorHint
*>(&rHint
))
1557 SdrObject
* pObj
= GetMaster();
1558 if(GetAnchorFrame() && !pObj
->IsInserted())
1560 auto pDrawModel
= const_cast<SwDrawFrameFormat
&>(static_cast<const SwDrawFrameFormat
&>(rMod
)).GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1562 pDrawModel
->GetPage(0)->InsertObject(pObj
);
1564 pObj
->SetRelativePos(pRestoreFlyAnchorHint
->m_aPos
);
1566 else if (auto pCreatePortionHint
= dynamic_cast<const sw::CreatePortionHint
*>(&rHint
))
1568 if(*pCreatePortionHint
->m_ppContact
)
1570 *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
1571 if(!GetAnchorFrame())
1573 // No direct positioning needed any more
1575 // Move object to visible layer
1576 MoveObjToVisibleLayer(GetMaster());
1579 else if (auto pCollectTextObjectsHint
= dynamic_cast<const sw::CollectTextObjectsHint
*>(&rHint
))
1581 auto pSdrO
= GetMaster();
1584 if(dynamic_cast<const SdrObjGroup
*>(pSdrO
))
1586 SdrObjListIter
aListIter(*pSdrO
, SdrIterMode::DeepNoGroups
);
1587 //iterate inside of a grouped object
1588 while(aListIter
.IsMore())
1590 SdrObject
* pSdrOElement
= aListIter
.Next();
1591 auto pTextObj
= const_cast<SdrTextObj
*>(dynamic_cast<const SdrTextObj
*>(pSdrOElement
));
1592 if(pTextObj
&& pTextObj
->HasText())
1593 pCollectTextObjectsHint
->m_rTextObjects
.push_back(pTextObj
);
1596 else if(auto pTextObj
= const_cast<SdrTextObj
*>(dynamic_cast<const SdrTextObj
*>(pSdrO
)))
1598 if(pTextObj
->HasText())
1599 pCollectTextObjectsHint
->m_rTextObjects
.push_back(pTextObj
);
1602 else if (auto pGetZOrdnerHint
= dynamic_cast<const sw::GetZOrderHint
*>(&rHint
))
1604 auto pFormat(dynamic_cast<const SwFrameFormat
*>(&rMod
));
1605 if(pFormat
->Which() == RES_DRAWFRMFMT
)
1606 pGetZOrdnerHint
->m_rnZOrder
= GetMaster()->GetOrdNum();
1608 else if (auto pConnectedHint
= dynamic_cast<const sw::GetObjectConnectedHint
*>(&rHint
))
1610 pConnectedHint
->m_risConnected
|= (GetAnchorFrame() != nullptr);
1615 // #i28701# - added parameter <_bUpdateSortedObjsList>
1616 void SwDrawContact::InvalidateObjs_( const bool _bUpdateSortedObjsList
)
1618 for(const auto& rpDrawVirtObj
: maDrawVirtObjs
)
1619 // invalidate position of existing 'virtual' drawing objects
1621 SwDrawVirtObj
* pDrawVirtObj(rpDrawVirtObj
.get());
1622 // #i33313# - invalidation only for connected
1623 // 'virtual' drawing objects
1624 if ( pDrawVirtObj
->IsConnected() )
1626 pDrawVirtObj
->AnchoredObj().InvalidateObjPos();
1628 if ( _bUpdateSortedObjsList
)
1630 pDrawVirtObj
->AnchoredObj().UpdateObjInSortedList();
1635 // invalidate position of 'master' drawing object
1636 SwAnchoredObject
* pAnchoredObj
= GetAnchoredObj( nullptr );
1637 pAnchoredObj
->InvalidateObjPos();
1639 if ( _bUpdateSortedObjsList
)
1641 pAnchoredObj
->UpdateObjInSortedList();
1645 void SwDrawContact::DisconnectFromLayout( bool _bMoveMasterToInvisibleLayer
)
1647 mbDisconnectInProgress
= true;
1649 // --> #i36181# - notify background of drawing object
1650 if ( _bMoveMasterToInvisibleLayer
&&
1651 !(GetFormat()->GetDoc()->IsInDtor()) &&
1652 GetAnchorFrame() && !GetAnchorFrame()->IsInDtor() )
1654 const tools::Rectangle
aOldRect( maAnchoredDrawObj
.GetObjRectWithSpaces().SVRect() );
1655 lcl_NotifyBackgroundOfObj( *this, *GetMaster(), &aOldRect
);
1656 NotifyBackgrdOfAllVirtObjs( &aOldRect
);
1659 // remove 'virtual' drawing objects from writer
1660 // layout and from drawing page
1661 for(auto& rpVirtDrawObj
: maDrawVirtObjs
)
1663 rpVirtDrawObj
->RemoveFromWriterLayout();
1664 rpVirtDrawObj
->RemoveFromDrawingPage();
1667 if ( maAnchoredDrawObj
.GetAnchorFrame() )
1669 maAnchoredDrawObj
.AnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
1672 if ( _bMoveMasterToInvisibleLayer
&& GetMaster() && GetMaster()->IsInserted() )
1674 SdrViewIter
aIter( GetMaster() );
1675 for( SdrView
* pView
= aIter
.FirstView(); pView
;
1676 pView
= aIter
.NextView() )
1678 pView
->MarkObj( GetMaster(), pView
->GetSdrPageView(), true );
1681 // Instead of removing 'master' object from drawing page, move the
1682 // 'master' drawing object into the corresponding invisible layer.
1684 //static_cast<SwFrameFormat*>(GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1685 // RemoveObject( GetMaster()->GetOrdNum() );
1686 // #i18447# - in order to consider group object correct
1687 // use new method <SwDrawContact::MoveObjToInvisibleLayer(..)>
1688 MoveObjToInvisibleLayer( GetMaster() );
1692 mbDisconnectInProgress
= false;
1695 /// method to remove 'master' drawing object from drawing page.
1696 void SwDrawContact::RemoveMasterFromDrawPage()
1700 GetMaster()->SetUserCall( nullptr );
1701 if ( GetMaster()->IsInserted() )
1703 static_cast<SwFrameFormat
*>(GetRegisteredIn())->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1704 RemoveObject( GetMaster()->GetOrdNum() );
1709 // disconnect for a dedicated drawing object - could be 'master' or 'virtual'.
1710 // a 'master' drawing object will disconnect a 'virtual' drawing object
1711 // in order to take its place.
1712 // #i19919# - no special case, if drawing object isn't in
1713 // page header/footer, in order to get drawing objects in repeating table headers
1715 void SwDrawContact::DisconnectObjFromLayout( SdrObject
* _pDrawObj
)
1717 if ( auto pSwDrawVirtObj
= dynamic_cast<SwDrawVirtObj
*>( _pDrawObj
) )
1719 pSwDrawVirtObj
->RemoveFromWriterLayout();
1720 pSwDrawVirtObj
->RemoveFromDrawingPage();
1724 const auto ppVirtDrawObj(std::find_if(maDrawVirtObjs
.begin(), maDrawVirtObjs
.end(),
1725 [] (const SwDrawVirtObjPtr
& pObj
) { return pObj
->IsConnected(); }));
1727 if(ppVirtDrawObj
!= maDrawVirtObjs
.end())
1729 // replace found 'virtual' drawing object by 'master' drawing
1730 // object and disconnect the 'virtual' one
1731 SwDrawVirtObj
* pDrawVirtObj(ppVirtDrawObj
->get());
1732 SwFrame
* pNewAnchorFrameOfMaster
= pDrawVirtObj
->AnchorFrame();
1733 // disconnect 'virtual' drawing object
1734 pDrawVirtObj
->RemoveFromWriterLayout();
1735 pDrawVirtObj
->RemoveFromDrawingPage();
1736 // disconnect 'master' drawing object from current frame
1737 GetAnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
1738 // re-connect 'master' drawing object to frame of found 'virtual'
1740 pNewAnchorFrameOfMaster
->AppendDrawObj( maAnchoredDrawObj
);
1744 // no connected 'virtual' drawing object found. Thus, disconnect
1745 // completely from layout.
1746 DisconnectFromLayout();
1751 static SwTextFrame
* lcl_GetFlyInContentAnchor( SwTextFrame
* _pProposedAnchorFrame
,
1752 SwPosition
const& rAnchorPos
)
1754 SwTextFrame
* pAct
= _pProposedAnchorFrame
;
1756 TextFrameIndex
const nTextOffset(_pProposedAnchorFrame
->MapModelToViewPos(rAnchorPos
));
1760 pAct
= pTmp
->GetFollow();
1762 while (pAct
&& nTextOffset
>= pAct
->GetOffset());
1766 void SwDrawContact::ConnectToLayout( const SwFormatAnchor
* pAnch
)
1768 // *no* connect to layout during disconnection from layout.
1769 if ( mbDisconnectInProgress
)
1771 OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> called during disconnection.");
1775 // --> #i33909# - *no* connect to layout, if 'master' drawing
1776 // object isn't inserted in the drawing page
1777 if ( !GetMaster()->IsInserted() )
1779 OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> - master drawing object not inserted -> no connect to layout. Please inform od@openoffice.org" );
1783 SwFrameFormat
* pDrawFrameFormat
= static_cast<SwFrameFormat
*>(GetRegisteredIn());
1785 if( !pDrawFrameFormat
->getIDocumentLayoutAccess().GetCurrentViewShell() )
1788 // remove 'virtual' drawing objects from writer
1789 // layout and from drawing page, and remove 'master' drawing object from
1790 // writer layout - 'master' object will remain in drawing page.
1791 DisconnectFromLayout( false );
1795 pAnch
= &(pDrawFrameFormat
->GetAnchor());
1798 switch ( pAnch
->GetAnchorId() )
1800 case RndStdIds::FLY_AT_PAGE
:
1802 sal_uInt16 nPgNum
= pAnch
->GetPageNum();
1803 SwViewShell
*pShell
= pDrawFrameFormat
->getIDocumentLayoutAccess().GetCurrentViewShell();
1806 SwRootFrame
* pRoot
= pShell
->GetLayout();
1807 SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(pRoot
->Lower());
1809 for ( sal_uInt16 i
= 1; i
< nPgNum
&& pPage
; ++i
)
1811 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1816 pPage
->AppendDrawObj( maAnchoredDrawObj
);
1819 //Looks stupid but is allowed (compare SwFEShell::SetPageObjsNewPage)
1820 pRoot
->SetAssertFlyPages();
1824 case RndStdIds::FLY_AT_CHAR
:
1825 case RndStdIds::FLY_AT_PARA
:
1826 case RndStdIds::FLY_AT_FLY
:
1827 case RndStdIds::FLY_AS_CHAR
:
1829 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1831 ClrContourCache( GetMaster() );
1833 // support drawing objects in header/footer,
1834 // but not control objects:
1835 // anchor at first found frame the 'master' object and
1836 // at the following frames 'virtual' drawing objects.
1837 // Note: method is similar to <SwFlyFrameFormat::MakeFrames(..)>
1838 sw::BroadcastingModify
*pModify
= nullptr;
1839 if( pAnch
->GetContentAnchor() )
1841 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AT_FLY
)
1843 SwNodeIndex
aIdx( pAnch
->GetContentAnchor()->nNode
);
1844 SwContentNode
* pCNd
= pDrawFrameFormat
->GetDoc()->GetNodes().GoNext( &aIdx
);
1845 if (SwIterator
<SwFrame
, SwContentNode
, sw::IteratorMode::UnwrapMulti
>(*pCNd
).First())
1849 const SwNodeIndex
& rIdx
= pAnch
->GetContentAnchor()->nNode
;
1850 SwFrameFormats
& rFormats
= *(pDrawFrameFormat
->GetDoc()->GetSpzFrameFormats());
1851 for( auto pFlyFormat
: rFormats
)
1853 if( pFlyFormat
->GetContent().GetContentIdx() &&
1854 rIdx
== *(pFlyFormat
->GetContent().GetContentIdx()) )
1856 pModify
= pFlyFormat
;
1864 pModify
= pAnch
->GetContentAnchor()->nNode
.GetNode().GetContentNode();
1868 // #i29199# - It is possible, that
1869 // the anchor doesn't exist - E.g., reordering the
1870 // sub-documents in a master document.
1871 // Note: The anchor will be inserted later.
1874 // break to end of the current switch case.
1878 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(*pModify
);
1879 SwFrame
* pAnchorFrameOfMaster
= nullptr;
1880 for( SwFrame
*pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next() )
1882 // append drawing object, if
1883 // (1) proposed anchor frame isn't a follow and...
1884 const bool bFollow
= pFrame
->IsContentFrame() && static_cast<SwContentFrame
*>(pFrame
)->IsFollow();
1888 // (2) drawing object isn't a control object to be anchored
1889 // in header/footer.
1890 const bool bControlInHF
= ::CheckControlLayer(GetMaster()) && pFrame
->FindFooterOrHeader();
1891 // tdf#129542 but make an exception for control objects so they can get added to just the first frame,
1892 // the Master Anchor Frame and not the others
1893 if (bControlInHF
&& pAnchorFrameOfMaster
)
1897 if (RndStdIds::FLY_AT_FLY
== pAnch
->GetAnchorId())
1901 assert(pFrame
->IsTextFrame());
1902 bAdd
= IsAnchoredObjShown(*static_cast<SwTextFrame
*>(pFrame
), *pAnch
);
1907 if ( RndStdIds::FLY_AT_FLY
== pAnch
->GetAnchorId() && !pFrame
->IsFlyFrame() )
1909 pFrame
= pFrame
->FindFlyFrame();
1913 // find correct follow for as character anchored objects
1914 if ((pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
) &&
1915 pFrame
->IsTextFrame() )
1917 pFrame
= lcl_GetFlyInContentAnchor(
1918 static_cast<SwTextFrame
*>(pFrame
),
1919 *pAnch
->GetContentAnchor());
1922 if ( !pAnchorFrameOfMaster
)
1924 // append 'master' drawing object
1925 pAnchorFrameOfMaster
= pFrame
;
1926 pFrame
->AppendDrawObj( maAnchoredDrawObj
);
1930 // append 'virtual' drawing object
1931 SwDrawVirtObj
* pDrawVirtObj
= AddVirtObj(*pFrame
);
1932 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1934 ClrContourCache( pDrawVirtObj
);
1936 pFrame
->AppendDrawObj( pDrawVirtObj
->AnchoredObj() );
1938 pDrawVirtObj
->ActionChanged();
1941 if ( pAnch
->GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1943 pFrame
->InvalidatePrt();
1950 assert(!"Unknown Anchor.");
1953 if ( GetAnchorFrame() )
1955 ::setContextWritingMode( maAnchoredDrawObj
.DrawObj(), GetAnchorFrame() );
1956 // #i26791# - invalidate objects instead of direct positioning
1961 /// insert 'master' drawing object into drawing page
1962 void SwDrawContact::InsertMasterIntoDrawPage()
1964 if ( !GetMaster()->IsInserted() )
1966 GetFormat()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)
1967 ->InsertObject( GetMaster(), GetMaster()->GetOrdNumDirect() );
1969 GetMaster()->SetUserCall( this );
1972 SwPageFrame
* SwDrawContact::FindPage( const SwRect
&rRect
)
1974 // --> #i28701# - use method <GetPageFrame()>
1975 SwPageFrame
* pPg
= GetPageFrame();
1976 if ( !pPg
&& GetAnchorFrame() )
1977 pPg
= GetAnchorFrame()->FindPageFrame();
1979 pPg
= const_cast<SwPageFrame
*>(static_cast<const SwPageFrame
*>(::FindPage( rRect
, pPg
)));
1983 void SwDrawContact::ChkPage()
1985 if ( mbDisconnectInProgress
)
1987 OSL_FAIL( "<SwDrawContact::ChkPage()> called during disconnection." );
1992 SwPageFrame
* pPg
= ( maAnchoredDrawObj
.GetAnchorFrame() &&
1993 maAnchoredDrawObj
.GetAnchorFrame()->IsPageFrame() )
1995 : FindPage( GetMaster()->GetCurrentBoundRect() );
1996 if ( GetPageFrame() == pPg
)
1999 // if drawing object is anchor in header/footer a change of the page
2000 // is a dramatic change. Thus, completely re-connect to the layout
2001 if ( maAnchoredDrawObj
.GetAnchorFrame() &&
2002 maAnchoredDrawObj
.GetAnchorFrame()->FindFooterOrHeader() )
2008 // --> #i28701# - use methods <GetPageFrame()> and <SetPageFrame>
2009 if ( GetPageFrame() )
2010 GetPageFrame()->RemoveDrawObjFromPage( maAnchoredDrawObj
);
2011 pPg
->AppendDrawObjToPage( maAnchoredDrawObj
);
2012 maAnchoredDrawObj
.SetPageFrame( pPg
);
2017 // method is called by method <SwDPage::ReplaceObject(..)>, which called its
2018 // corresponding superclass method <FmFormPage::ReplaceObject(..)>.
2019 // Note: 'master' drawing object *has* to be connected to layout triggered
2020 // by the caller of this, if method is called.
2021 void SwDrawContact::ChangeMasterObject(SdrObject
* pNewMaster
)
2023 DisconnectFromLayout( false );
2024 // consider 'virtual' drawing objects
2025 RemoveAllVirtObjs();
2027 GetMaster()->SetUserCall( nullptr );
2029 maAnchoredDrawObj
.SetDrawObj(*pNewMaster
);
2031 mbMasterObjCleared
= true;
2032 GetMaster()->SetUserCall( this );
2037 /// get data collection of anchored objects, handled by with contact
2038 void SwDrawContact::GetAnchoredObjs(std::vector
<SwAnchoredObject
*>& o_rAnchoredObjs
) const
2040 o_rAnchoredObjs
.push_back(const_cast<SwAnchoredDrawObject
*>(&maAnchoredDrawObj
));
2042 for(auto& rpDrawVirtObj
: maDrawVirtObjs
)
2043 o_rAnchoredObjs
.push_back(&rpDrawVirtObj
->AnchoredObj());
2046 // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
2047 // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
2048 // For paint, that offset is used by setting at the OutputDevice; for primitives this is
2049 // not possible since we have no OutputDevice, but define the geometry itself.
2051 namespace sdr::contact
2055 class VOCOfDrawVirtObj
: public ViewObjectContactOfSdrObj
2059 * This method is responsible for creating the graphical visualisation data which is
2060 * stored/cached in the local primitive. Default gets view-independent Primitive from
2061 * the ViewContact using ViewContact::getViewIndependentPrimitive2DContainer(), takes
2062 * care of visibility, handles glue and ghosted.
2064 * This method will not handle included hierarchies and not check geometric visibility.
2066 virtual drawinglayer::primitive2d::Primitive2DContainer
createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
) const override
;
2069 VOCOfDrawVirtObj(ObjectContact
& rObjectContact
, ViewContact
& rViewContact
)
2070 : ViewObjectContactOfSdrObj(rObjectContact
, rViewContact
)
2075 class VCOfDrawVirtObj
: public ViewContactOfVirtObj
2078 /** Create an Object-Specific ViewObjectContact, set ViewContact and ObjectContact.
2080 * Always needs to return something. Default is to create a standard ViewObjectContact
2081 * containing the given ObjectContact and *this.
2083 virtual ViewObjectContact
& CreateObjectSpecificViewObjectContact(ObjectContact
& rObjectContact
) override
;
2086 /// basic constructor, used from SdrObject.
2087 explicit VCOfDrawVirtObj(SwDrawVirtObj
& rObj
)
2088 : ViewContactOfVirtObj(rObj
)
2092 /// access to SwDrawVirtObj
2093 SwDrawVirtObj
& GetSwDrawVirtObj() const
2095 return static_cast<SwDrawVirtObj
&>(mrObject
);
2100 } // end of namespace sdr::contact
2102 namespace sdr::contact
2104 /// recursively collect primitive data from given VOC with given offset
2105 static void impAddPrimitivesFromGroup(const ViewObjectContact
& rVOC
, const basegfx::B2DHomMatrix
& rOffsetMatrix
, const DisplayInfo
& rDisplayInfo
, drawinglayer::primitive2d::Primitive2DContainer
& rxTarget
)
2107 const sal_uInt32
nSubHierarchyCount(rVOC
.GetViewContact().GetObjectCount());
2109 for(sal_uInt32
a(0); a
< nSubHierarchyCount
; a
++)
2111 const ViewObjectContact
& rCandidate(rVOC
.GetViewContact().GetViewContact(a
).GetViewObjectContact(rVOC
.GetObjectContact()));
2113 if(rCandidate
.GetViewContact().GetObjectCount())
2115 // is a group object itself, call recursively
2116 impAddPrimitivesFromGroup(rCandidate
, rOffsetMatrix
, rDisplayInfo
, rxTarget
);
2120 // single object, add primitives; check model-view visibility
2121 if(rCandidate
.isPrimitiveVisible(rDisplayInfo
))
2123 drawinglayer::primitive2d::Primitive2DContainer
aNewSequence(rCandidate
.getPrimitive2DSequence(rDisplayInfo
));
2125 if(!aNewSequence
.empty())
2128 const drawinglayer::geometry::ViewInformation2D
& rViewInformation2D(rCandidate
.GetObjectContact().getViewInformation2D());
2129 const basegfx::B2DRange
aViewRange(rViewInformation2D
.getViewport());
2130 basegfx::B2DRange
aObjectRange(rCandidate
.getObjectRange());
2132 // correct with virtual object's offset
2133 aObjectRange
.transform(rOffsetMatrix
);
2135 // check geometrical visibility (with offset)
2136 if(!aViewRange
.overlaps(aObjectRange
))
2138 // not visible, release
2139 aNewSequence
.clear();
2143 if(!aNewSequence
.empty())
2145 rxTarget
.append(aNewSequence
);
2152 drawinglayer::primitive2d::Primitive2DContainer
VOCOfDrawVirtObj::createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
) const
2154 // tdf#91260 have already checked top-level one is on the right page
2155 assert(isPrimitiveVisible(rDisplayInfo
));
2156 // nasty corner case: override to clear page frame to disable the
2157 // sub-objects' anchor check, because their anchor is always on
2158 // the first page that the page style is applied to
2159 DisplayInfo
aDisplayInfo(rDisplayInfo
);
2160 aDisplayInfo
.SetWriterPageFrame(basegfx::B2IRectangle());
2161 const VCOfDrawVirtObj
& rVC
= static_cast< const VCOfDrawVirtObj
& >(GetViewContact());
2162 const SdrObject
& rReferencedObject
= rVC
.GetSwDrawVirtObj().GetReferencedObj();
2163 drawinglayer::primitive2d::Primitive2DContainer xRetval
;
2165 // create offset transformation
2166 basegfx::B2DHomMatrix aOffsetMatrix
;
2167 const Point
aLocalOffset(rVC
.GetSwDrawVirtObj().GetOffset());
2169 if(aLocalOffset
.X() || aLocalOffset
.Y())
2171 aOffsetMatrix
.set(0, 2, aLocalOffset
.X());
2172 aOffsetMatrix
.set(1, 2, aLocalOffset
.Y());
2175 if(dynamic_cast<const SdrObjGroup
*>( &rReferencedObject
) != nullptr)
2177 // group object. Since the VOC/OC/VC hierarchy does not represent the
2178 // hierarchy virtual objects when they have group objects
2179 // (ViewContactOfVirtObj::GetObjectCount() returns null for that purpose)
2180 // to avoid multiple usages of VOCs (which would not work), the primitives
2181 // for the sub-hierarchy need to be collected here
2183 // Get the VOC of the referenced object (the Group) and fetch primitives from it
2184 const ViewObjectContact
& rVOCOfRefObj
= rReferencedObject
.GetViewContact().GetViewObjectContact(GetObjectContact());
2185 impAddPrimitivesFromGroup(rVOCOfRefObj
, aOffsetMatrix
, aDisplayInfo
, xRetval
);
2189 // single object, use method from referenced object to get the Primitive2DSequence
2190 xRetval
= rReferencedObject
.GetViewContact().getViewIndependentPrimitive2DContainer();
2193 if(!xRetval
.empty())
2195 // create transform primitive
2196 const drawinglayer::primitive2d::Primitive2DReference
xReference(new drawinglayer::primitive2d::TransformPrimitive2D(aOffsetMatrix
, xRetval
));
2197 xRetval
= drawinglayer::primitive2d::Primitive2DContainer
{ xReference
};
2203 ViewObjectContact
& VCOfDrawVirtObj::CreateObjectSpecificViewObjectContact(ObjectContact
& rObjectContact
)
2205 return *(new VOCOfDrawVirtObj(rObjectContact
, *this));
2208 } // end of namespace sdr::contact
2210 /// implementation of class <SwDrawVirtObj>
2211 std::unique_ptr
<sdr::contact::ViewContact
> SwDrawVirtObj::CreateObjectSpecificViewContact()
2213 return std::make_unique
<sdr::contact::VCOfDrawVirtObj
>(*this);
2216 SwDrawVirtObj::SwDrawVirtObj(
2217 SdrModel
& rSdrModel
,
2218 SdrObject
& _rNewObj
,
2219 SwDrawContact
& _rDrawContact
)
2220 : SdrVirtObj(rSdrModel
, _rNewObj
),
2221 maAnchoredDrawObj(),
2222 mrDrawContact(_rDrawContact
)
2225 maAnchoredDrawObj
.SetDrawObj( *this );
2227 // #i35635# - set initial position out of sight
2228 NbcMove( Size( -16000, -16000 ) );
2231 SwDrawVirtObj::~SwDrawVirtObj()
2235 SwDrawVirtObj
& SwDrawVirtObj::operator=( const SwDrawVirtObj
& rObj
)
2237 SdrVirtObj::operator=(rObj
);
2238 // Note: Members <maAnchoredDrawObj> and <mrDrawContact>
2239 // haven't to be considered.
2243 SwDrawVirtObj
* SwDrawVirtObj::CloneSdrObject(SdrModel
& rTargetModel
) const
2245 SwDrawVirtObj
* pObj
= new SwDrawVirtObj(
2250 pObj
->operator=( *this );
2251 // Note: Member <maAnchoredDrawObj> hasn't to be considered.
2256 const SwFrame
* SwDrawVirtObj::GetAnchorFrame() const
2258 // #i26791# - use new member <maAnchoredDrawObj>
2259 return maAnchoredDrawObj
.GetAnchorFrame();
2262 SwFrame
* SwDrawVirtObj::AnchorFrame()
2264 // #i26791# - use new member <maAnchoredDrawObj>
2265 return maAnchoredDrawObj
.AnchorFrame();
2268 void SwDrawVirtObj::RemoveFromWriterLayout()
2270 // remove contact object from frame for 'virtual' drawing object
2271 // #i26791# - use new member <maAnchoredDrawObj>
2272 if ( maAnchoredDrawObj
.GetAnchorFrame() )
2274 maAnchoredDrawObj
.AnchorFrame()->RemoveDrawObj( maAnchoredDrawObj
);
2278 void SwDrawVirtObj::AddToDrawingPage(SwFrame
const& rAnchorFrame
)
2280 // determine 'master'
2281 SdrObject
* pOrgMasterSdrObj
= mrDrawContact
.GetMaster();
2283 // insert 'virtual' drawing object into page, set layer and user call.
2284 SdrPage
* pDrawPg
= pOrgMasterSdrObj
->getSdrPageFromSdrObject();
2285 // default: insert before master object
2286 auto NOTM_nOrdNum(GetReferencedObj().GetOrdNum());
2288 // maintain invariant that a shape's textbox immediately follows the shape
2289 // also for the multiple SdrDrawVirtObj created for shapes in header/footer
2290 if (SwFrameFormat
const*const pFlyFormat
=
2291 SwTextBoxHelper::getOtherTextBoxFormat(mrDrawContact
.GetFormat(), RES_DRAWFRMFMT
))
2293 // this is for the case when the flyframe SdrVirtObj is created before the draw one
2294 if (SwSortedObjs
const*const pObjs
= rAnchorFrame
.GetDrawObjs())
2296 for (SwAnchoredObject
const*const pAnchoredObj
: *pObjs
)
2298 if (&pAnchoredObj
->GetFrameFormat() == pFlyFormat
)
2300 assert(dynamic_cast<SwFlyFrame
const*>(pAnchoredObj
));
2301 NOTM_nOrdNum
= pAnchoredObj
->GetDrawObj()->GetOrdNum();
2302 // the master SdrObj should have the highest index
2303 assert(NOTM_nOrdNum
< GetReferencedObj().GetOrdNum());
2308 // this happens on initial insertion, the draw object is created first
2309 SAL_INFO_IF(GetReferencedObj().GetOrdNum() == NOTM_nOrdNum
, "sw", "AddToDrawingPage: cannot find SdrObject for text box's shape");
2312 // #i27030# - apply order number of referenced object
2313 if ( nullptr != pDrawPg
)
2315 // #i27030# - apply order number of referenced object
2316 pDrawPg
->InsertObject(this, NOTM_nOrdNum
);
2320 pDrawPg
= getSdrPageFromSdrObject();
2323 pDrawPg
->SetObjectOrdNum(GetOrdNumDirect(), NOTM_nOrdNum
);
2327 SetOrdNum(NOTM_nOrdNum
);
2330 SetUserCall( &mrDrawContact
);
2333 void SwDrawVirtObj::RemoveFromDrawingPage()
2335 SetUserCall( nullptr );
2336 if ( getSdrPageFromSdrObject() )
2338 getSdrPageFromSdrObject()->RemoveObject( GetOrdNum() );
2342 /// Is 'virtual' drawing object connected to writer layout and to drawing layer?
2343 bool SwDrawVirtObj::IsConnected() const
2345 bool bRetVal
= GetAnchorFrame() &&
2346 ( getSdrPageFromSdrObject() && GetUserCall() );
2351 void SwDrawVirtObj::NbcSetAnchorPos(const Point
& rPnt
)
2353 SdrObject::NbcSetAnchorPos( rPnt
);
2357 // the methods relevant for positioning
2359 const tools::Rectangle
& SwDrawVirtObj::GetCurrentBoundRect() const
2361 if(aOutRect
.IsEmpty())
2363 const_cast<SwDrawVirtObj
*>(this)->RecalcBoundRect();
2369 const tools::Rectangle
& SwDrawVirtObj::GetLastBoundRect() const
2374 Point
SwDrawVirtObj::GetOffset() const
2376 // do NOT use IsEmpty() here, there is already a useful offset
2378 if(aOutRect
== tools::Rectangle())
2384 return aOutRect
.TopLeft() - GetReferencedObj().GetCurrentBoundRect().TopLeft();
2388 void SwDrawVirtObj::SetBoundRectDirty()
2390 // do nothing to not lose model information in aOutRect
2393 void SwDrawVirtObj::RecalcBoundRect()
2395 // #i26791# - switch order of calling <GetOffset()> and
2396 // <ReferencedObj().GetCurrentBoundRect()>, because <GetOffset()> calculates
2397 // its value by the 'BoundRect' of the referenced object.
2399 const Point
aOffset(GetOffset());
2400 aOutRect
= ReferencedObj().GetCurrentBoundRect() + aOffset
;
2403 basegfx::B2DPolyPolygon
SwDrawVirtObj::TakeXorPoly() const
2405 basegfx::B2DPolyPolygon
aRetval(rRefObj
.TakeXorPoly());
2406 aRetval
.transform(basegfx::utils::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2411 basegfx::B2DPolyPolygon
SwDrawVirtObj::TakeContour() const
2413 basegfx::B2DPolyPolygon
aRetval(rRefObj
.TakeContour());
2414 aRetval
.transform(basegfx::utils::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2419 void SwDrawVirtObj::AddToHdlList(SdrHdlList
& rHdlList
) const
2421 SdrHdlList
tmpList(nullptr);
2422 rRefObj
.AddToHdlList(tmpList
);
2424 size_t cnt
= tmpList
.GetHdlCount();
2425 for(size_t i
=0; i
< cnt
; ++i
)
2427 SdrHdl
* pHdl
= tmpList
.GetHdl(i
);
2428 Point
aP(pHdl
->GetPos() + GetOffset());
2431 tmpList
.MoveTo(rHdlList
);
2434 void SwDrawVirtObj::NbcMove(const Size
& rSiz
)
2436 SdrObject::NbcMove( rSiz
);
2439 void SwDrawVirtObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
2441 rRefObj
.NbcResize(rRef
- GetOffset(), xFact
, yFact
);
2445 void SwDrawVirtObj::NbcRotate(const Point
& rRef
, tools::Long nAngle
, double sn
, double cs
)
2447 rRefObj
.NbcRotate(rRef
- GetOffset(), nAngle
, sn
, cs
);
2451 void SwDrawVirtObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
2453 rRefObj
.NbcMirror(rRef1
- GetOffset(), rRef2
- GetOffset());
2457 void SwDrawVirtObj::NbcShear(const Point
& rRef
, tools::Long nAngle
, double tn
, bool bVShear
)
2459 rRefObj
.NbcShear(rRef
- GetOffset(), nAngle
, tn
, bVShear
);
2463 void SwDrawVirtObj::Move(const Size
& rSiz
)
2465 SdrObject::Move( rSiz
);
2468 void SwDrawVirtObj::Resize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bUnsetRelative
)
2470 if(xFact
.GetNumerator() != xFact
.GetDenominator() || yFact
.GetNumerator() != yFact
.GetDenominator())
2472 tools::Rectangle aBoundRect0
; if(pUserCall
) aBoundRect0
= GetLastBoundRect();
2473 rRefObj
.Resize(rRef
- GetOffset(), xFact
, yFact
, bUnsetRelative
);
2475 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2479 void SwDrawVirtObj::Rotate(const Point
& rRef
, tools::Long nAngle
, double sn
, double cs
)
2483 tools::Rectangle aBoundRect0
; if(pUserCall
) aBoundRect0
= GetLastBoundRect();
2484 rRefObj
.Rotate(rRef
- GetOffset(), nAngle
, sn
, cs
);
2486 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2490 void SwDrawVirtObj::Mirror(const Point
& rRef1
, const Point
& rRef2
)
2492 tools::Rectangle aBoundRect0
; if(pUserCall
) aBoundRect0
= GetLastBoundRect();
2493 rRefObj
.Mirror(rRef1
- GetOffset(), rRef2
- GetOffset());
2495 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2498 void SwDrawVirtObj::Shear(const Point
& rRef
, tools::Long nAngle
, double tn
, bool bVShear
)
2502 tools::Rectangle aBoundRect0
; if(pUserCall
) aBoundRect0
= GetLastBoundRect();
2503 rRefObj
.Shear(rRef
- GetOffset(), nAngle
, tn
, bVShear
);
2505 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2509 void SwDrawVirtObj::RecalcSnapRect()
2511 aSnapRect
= rRefObj
.GetSnapRect();
2512 aSnapRect
+= GetOffset();
2515 const tools::Rectangle
& SwDrawVirtObj::GetSnapRect() const
2517 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
= rRefObj
.GetSnapRect();
2518 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
+= GetOffset();
2523 void SwDrawVirtObj::SetSnapRect(const tools::Rectangle
& rRect
)
2525 tools::Rectangle aBoundRect0
; if(pUserCall
) aBoundRect0
= GetLastBoundRect();
2526 tools::Rectangle
aR(rRect
);
2528 rRefObj
.SetSnapRect(aR
);
2530 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2533 void SwDrawVirtObj::NbcSetSnapRect(const tools::Rectangle
& rRect
)
2535 tools::Rectangle
aR(rRect
);
2538 rRefObj
.NbcSetSnapRect(aR
);
2541 const tools::Rectangle
& SwDrawVirtObj::GetLogicRect() const
2543 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
= rRefObj
.GetLogicRect();
2544 const_cast<SwDrawVirtObj
*>(this)->aSnapRect
+= GetOffset();
2549 void SwDrawVirtObj::SetLogicRect(const tools::Rectangle
& rRect
)
2551 tools::Rectangle aBoundRect0
; if(pUserCall
) aBoundRect0
= GetLastBoundRect();
2552 tools::Rectangle
aR(rRect
);
2554 rRefObj
.SetLogicRect(aR
);
2556 SendUserCall(SdrUserCallType::Resize
, aBoundRect0
);
2559 void SwDrawVirtObj::NbcSetLogicRect(const tools::Rectangle
& rRect
)
2561 tools::Rectangle
aR(rRect
);
2563 rRefObj
.NbcSetLogicRect(aR
);
2567 Point
SwDrawVirtObj::GetSnapPoint(sal_uInt32 i
) const
2569 Point
aP(rRefObj
.GetSnapPoint(i
));
2575 Point
SwDrawVirtObj::GetPoint(sal_uInt32 i
) const
2577 return rRefObj
.GetPoint(i
) + GetOffset();
2580 void SwDrawVirtObj::NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
)
2584 rRefObj
.SetPoint(aP
, i
);
2588 bool SwDrawVirtObj::HasTextEdit() const
2590 return rRefObj
.HasTextEdit();
2593 // override 'layer' methods for 'virtual' drawing object to assure
2594 // that layer of 'virtual' object is the layer of the referenced object.
2595 SdrLayerID
SwDrawVirtObj::GetLayer() const
2597 return GetReferencedObj().GetLayer();
2600 void SwDrawVirtObj::NbcSetLayer(SdrLayerID nLayer
)
2602 ReferencedObj().NbcSetLayer( nLayer
);
2603 SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2606 void SwDrawVirtObj::SetLayer(SdrLayerID nLayer
)
2608 ReferencedObj().SetLayer( nLayer
);
2609 SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */