summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-04-09 12:08:24 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2022-06-23 18:36:17 +0200
commitc6586b8f923c1c6e011ecd804e31f71f6c1dc452 (patch)
tree8eef837eaa4afed40de0328246fb724b55e5da6f
parenttdf#140292 sw: fix z-order of textbox on undo (diff)
downloadcore-c6586b8f923c1c6e011ecd804e31f71f6c1dc452.tar.gz
core-c6586b8f923c1c6e011ecd804e31f71f6c1dc452.zip
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) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113844 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit c2eae4998b3ae79210ef0b5c064e9833218c22de) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113853 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> (cherry picked from commit ad8ddc0bb2535b6d6bad53dd137c3d8e682dfd1f) Change-Id: Ic00878685ab16018c9331190f1e80f874c1a9a4e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136311 Tested-by: Michael Stahl <michael.stahl@allotropia.de> Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r--sw/inc/dcontact.hxx4
-rw-r--r--sw/source/core/draw/dcontact.cxx42
-rw-r--r--sw/source/core/layout/frmtool.cxx2
3 files changed, 37 insertions, 11 deletions
diff --git a/sw/inc/dcontact.hxx b/sw/inc/dcontact.hxx
index 8d0e03d66e50..504c512d1c8e 100644
--- a/sw/inc/dcontact.hxx
+++ b/sw/inc/dcontact.hxx
@@ -248,7 +248,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
@@ -398,7 +398,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 d9e7ce725ed1..5f05c4d21cd7 100644
--- a/sw/source/core/draw/dcontact.cxx
+++ b/sw/source/core/draw/dcontact.cxx
@@ -825,7 +825,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(
@@ -833,7 +833,7 @@ SwDrawVirtObj* SwDrawContact::AddVirtObj()
GetMaster()->getSdrModelFromSdrObject(),
*GetMaster(),
*this)));
- maDrawVirtObjs.back()->AddToDrawingPage();
+ maDrawVirtObjs.back()->AddToDrawingPage(rAnchorFrame);
return maDrawVirtObjs.back().get();
}
@@ -1892,7 +1892,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 );
@@ -2241,30 +2241,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;
+ // 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 = pOrgMasterSdrObj->getSdrPageFromSdrObject() ) )
{
// #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 9b3386a9b4df..f6bbeaae24dc 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -1019,7 +1019,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();