summaryrefslogtreecommitdiff
path: root/sw/source/core/draw
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-04-09 12:08:24 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2021-04-09 15:19:50 +0200
commitc2eae4998b3ae79210ef0b5c064e9833218c22de (patch)
treec3d9bbbbef87209e1dc190d271bfa012d773b539 /sw/source/core/draw
parentc87e0938b3ee9f4c1f87c4ec53f3e94a022fe6f0 (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>
Diffstat (limited to 'sw/source/core/draw')
-rw-r--r--sw/source/core/draw/dcontact.cxx42
1 files changed, 34 insertions, 8 deletions
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 );