diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2021-04-09 12:08:24 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2021-04-09 15:19:50 +0200 |
commit | c2eae4998b3ae79210ef0b5c064e9833218c22de (patch) | |
tree | c3d9bbbbef87209e1dc190d271bfa012d773b539 | |
parent | c87e0938b3ee9f4c1f87c4ec53f3e94a022fe6f0 (diff) |
tdf#141549 sw: fix ordering of virtual SdrObjects for textboxes
In header/footer it turns out that not only can the text box be inserted
after the shape, it can also be inserted before the shape.
This is because SwDrawFrameFormat::MakeFrames() ends up first destroying
all the SwDrawVirtObj and then creating them from scratch again, while
the SwVirtFlyDrawObj survives.
4 SwDrawContact::DisconnectFromLayout(bool) (this=0x6ed0200, _bMoveMasterToInvisibleLayer=false) at sw/source/core/draw/dcontact.cxx:1664
5 SwDrawContact::ConnectToLayout(SwFormatAnchor const*) (this=0x6ed0200, pAnch=0x0) at sw/source/core/draw/dcontact.cxx:1791
6 SwDrawContact::SwClientNotify(SwModify const&, SfxHint const&) (this=0x6ed0200, rMod=..., rHint=...) at sw/source/core/draw/dcontact.cxx:1521
7 SwModify::CallSwClientNotify(SfxHint const&) const (this=0x6ecfd80, rHint=...) at sw/source/core/attr/calbck.cxx:321
8 sw::BroadcastingModify::CallSwClientNotify(SfxHint const&) const (this=0x6ecfd80, rHint=...) at sw/source/core/attr/calbck.cxx:326
9 SwDrawFrameFormat::MakeFrames() (this=0x6ecfd80) at sw/source/core/layout/atrfrm.cxx:3394
10 AppendAllObjs(SwFrameFormats const*, SwFrame const*) (pTable=0x69c1920, pSib=0x38c6100) at sw/source/core/layout/frmtool.cxx:1349
11 InsertCnt_(SwLayoutFrame*, SwDoc*, unsigned long, bool, unsigned long, SwFrame*, sw::FrameMode) (pLay=0x6be4320, pDoc=0x69af7c0, nIndex=157, bPages=true, nEndIndex=0, pPrv=0x6baedc0, eMode=sw::FrameMode::New) at sw/source/core/layout/frmtool.cxx:1927
Fix this by searching for the existing SwVirtFlyDrawObj in
SwDrawVirtObj::AddToDrawingPage().
(regression from 3bc8f90e9693f710f12632f69b9348c1c833c906)
Change-Id: Ic00878685ab16018c9331190f1e80f874c1a9a4e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113844
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r-- | sw/inc/dcontact.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/draw/dcontact.cxx | 42 | ||||
-rw-r--r-- | sw/source/core/layout/frmtool.cxx | 2 |
3 files changed, 37 insertions, 11 deletions
diff --git a/sw/inc/dcontact.hxx b/sw/inc/dcontact.hxx index 52893220dde9..c596a61e4980 100644 --- a/sw/inc/dcontact.hxx +++ b/sw/inc/dcontact.hxx @@ -251,7 +251,7 @@ class SwDrawVirtObj final : public SdrVirtObj void RemoveFromWriterLayout(); /// connection to drawing layer - void AddToDrawingPage(); + void AddToDrawingPage(SwFrame const& rAnchorFrame); void RemoveFromDrawingPage(); /** is 'virtual' drawing object connected to writer layout and @@ -401,7 +401,7 @@ class SAL_DLLPUBLIC_RTTI SwDrawContact final : public SwContact /// Moves all SW-connections to new Master) void ChangeMasterObject( SdrObject *pNewMaster ); - SwDrawVirtObj* AddVirtObj(); + SwDrawVirtObj* AddVirtObj(SwFrame const& rAnchorFrame); void NotifyBackgrdOfAllVirtObjs( const tools::Rectangle* pOldBoundRect ); diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx index 11687c41d0d5..f45d7278d59c 100644 --- a/sw/source/core/draw/dcontact.cxx +++ b/sw/source/core/draw/dcontact.cxx @@ -827,7 +827,7 @@ SwFrame* SwDrawContact::GetAnchorFrame(SdrObject const *const pDrawObj) /** add a 'virtual' drawing object to drawing page. */ -SwDrawVirtObj* SwDrawContact::AddVirtObj() +SwDrawVirtObj* SwDrawContact::AddVirtObj(SwFrame const& rAnchorFrame) { maDrawVirtObjs.push_back( SwDrawVirtObjPtr( @@ -835,7 +835,7 @@ SwDrawVirtObj* SwDrawContact::AddVirtObj() GetMaster()->getSdrModelFromSdrObject(), *GetMaster(), *this))); - maDrawVirtObjs.back()->AddToDrawingPage(); + maDrawVirtObjs.back()->AddToDrawingPage(rAnchorFrame); return maDrawVirtObjs.back().get(); } @@ -1926,7 +1926,7 @@ void SwDrawContact::ConnectToLayout( const SwFormatAnchor* pAnch ) else { // append 'virtual' drawing object - SwDrawVirtObj* pDrawVirtObj = AddVirtObj(); + SwDrawVirtObj* pDrawVirtObj = AddVirtObj(*pFrame); if ( pAnch->GetAnchorId() == RndStdIds::FLY_AS_CHAR ) { ClrContourCache( pDrawVirtObj ); @@ -2274,30 +2274,56 @@ void SwDrawVirtObj::RemoveFromWriterLayout() } } -void SwDrawVirtObj::AddToDrawingPage() +void SwDrawVirtObj::AddToDrawingPage(SwFrame const& rAnchorFrame) { // determine 'master' SdrObject* pOrgMasterSdrObj = mrDrawContact.GetMaster(); // insert 'virtual' drawing object into page, set layer and user call. SdrPage* pDrawPg = pOrgMasterSdrObj->getSdrPageFromSdrObject(); + // default: insert before master object + auto NOTM_nOrdNum(GetReferencedObj().GetOrdNum()); + + // maintain invariant that a shape's textbox immediately follows the shape + // also for the multiple SdrDrawVirtObj created for shapes in header/footer + if (SwFrameFormat const*const pFlyFormat = + SwTextBoxHelper::getOtherTextBoxFormat(mrDrawContact.GetFormat(), RES_DRAWFRMFMT)) + { + // this is for the case when the flyframe SdrVirtObj is created before the draw one + if (SwSortedObjs const*const pObjs = rAnchorFrame.GetDrawObjs()) + { + for (SwAnchoredObject const*const pAnchoredObj : *pObjs) + { + if (&pAnchoredObj->GetFrameFormat() == pFlyFormat) + { + assert(dynamic_cast<SwFlyFrame const*>(pAnchoredObj)); + NOTM_nOrdNum = pAnchoredObj->GetDrawObj()->GetOrdNum(); + // the master SdrObj should have the highest index + assert(NOTM_nOrdNum < GetReferencedObj().GetOrdNum()); + break; + } + } + } + // this happens on initial insertion, the draw object is created first + SAL_INFO_IF(GetReferencedObj().GetOrdNum() == NOTM_nOrdNum, "sw", "AddToDrawingPage: cannot find SdrObject for text box's shape"); + } + // #i27030# - apply order number of referenced object if ( nullptr != pDrawPg ) { // #i27030# - apply order number of referenced object - pDrawPg->InsertObject( this, GetReferencedObj().GetOrdNum() ); + pDrawPg->InsertObject(this, NOTM_nOrdNum); } else { pDrawPg = getSdrPageFromSdrObject(); if ( pDrawPg ) { - pDrawPg->SetObjectOrdNum( GetOrdNumDirect(), - GetReferencedObj().GetOrdNum() ); + pDrawPg->SetObjectOrdNum(GetOrdNumDirect(), NOTM_nOrdNum); } else { - SetOrdNum( GetReferencedObj().GetOrdNum() ); + SetOrdNum(NOTM_nOrdNum); } } SetUserCall( &mrDrawContact ); diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index 2d5131c4e658..557bc2414e63 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -1027,7 +1027,7 @@ void AppendObj(SwFrame *const pFrame, SwPageFrame *const pPage, SwFrameFormat *c pNew->GetAnchorFrame() != pFrame && !pNew->GetDrawObjectByAnchorFrame( *pFrame ) ) { - SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj(); + SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj(*pFrame); pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) ); pDrawVirtObj->ActionChanged(); |