[Libreoffice-commits] core.git: sw/inc sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 9 13:20:31 UTC 2021


 sw/inc/dcontact.hxx               |    4 +--
 sw/source/core/draw/dcontact.cxx  |   42 ++++++++++++++++++++++++++++++--------
 sw/source/core/layout/frmtool.cxx |    2 -
 3 files changed, 37 insertions(+), 11 deletions(-)

New commits:
commit c2eae4998b3ae79210ef0b5c064e9833218c22de
Author:     Michael Stahl <michael.stahl at allotropia.de>
AuthorDate: Fri Apr 9 12:08:24 2021 +0200
Commit:     Michael Stahl <michael.stahl at allotropia.de>
CommitDate: Fri Apr 9 15:19:50 2021 +0200

    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 at allotropia.de>

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();


More information about the Libreoffice-commits mailing list