sw/qa/core/layout/data/page-remove-fly-table.odt |binary sw/qa/core/layout/layout.cxx | 40 +++++++++++++++++++++++ sw/source/core/layout/flylay.cxx | 11 ++++++ 3 files changed, 51 insertions(+)
New commits: commit ee9e7a6645dca3d79d784fdda8dd1cd003f1b998 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Dec 9 16:52:48 2022 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Dec 12 10:00:27 2022 +0100 sw layout: invalidate margins of body content when moving a fly from page The (simplified) bugdoc has 9 pages, and once the ToC is updated, the two tables below the (only) bookmark in the document has a 5879 twips gap between them for no reason. Adding a new paragraph to the second table "fixes" the incremental layout. What seems to happen is that there is an anchored image on page 8, but the layout decides that it doesn't fit there so it gets moved to page 9. Before this move happens, SwTabFrame::Format() handles the outer of the nested table below the unwanted gap and its CalcFlyOffsets() notices that a large upper margin is wanted so that the table wraps around the anchored image. Later the image gets moved to the next page, but the removal doesn't invalidate the print area of the table with the large top margin, so the unwanted gap appears. Fix the problem by looking at the old page in SwPageFrame::MoveFly() and walking through the immediate children of the body frame: if the frame print area is invalidated, then SetYMargins() is called from SwTabFrame::Format(), which also invalidates the size of the outer table frame, so it will use Shrink() to have a correct size. This appears to be a regression from commit b9ef71476fd70bc13f50ebe80390e0730d1b7afb (tdf#134298 sw: layout: remove left-over page frame without content, 2020-11-13). (cherry picked from commit cf2c070de2bafeec3b476c6bff7bb4ac87ba46db) Conflicts: sw/qa/core/layout/layout.cxx Change-Id: I0424d9eea4d8a030959f8534985950c7efad4686 diff --git a/sw/qa/core/layout/data/page-remove-fly-table.odt b/sw/qa/core/layout/data/page-remove-fly-table.odt new file mode 100644 index 000000000000..6aaf230966ef Binary files /dev/null and b/sw/qa/core/layout/data/page-remove-fly-table.odt differ diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx index 4cc7390d63f9..1f8e2e8e5482 100644 --- a/sw/qa/core/layout/layout.cxx +++ b/sw/qa/core/layout/layout.cxx @@ -10,8 +10,16 @@ #include <swmodeltestbase.hxx> #include <vcl/gdimtf.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> #include <wrtsh.hxx> +#include <view.hxx> +#include <cmdid.h> +#include <node.hxx> +#include <ndtxt.hxx> +#include <tabfrm.hxx> +#include <cntfrm.hxx> static char const DATA_DIRECTORY[] = "/sw/qa/core/layout/data/"; @@ -164,6 +172,38 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testKeepwithnextFullheight) assertXPath(pXmlDoc, "//page[2]/body/txt/anchored/fly", 1); } +CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testPageRemoveFlyTable) +{ + // Given a document with a ToC and several tables, one table marked with a bookmark: + load(DATA_DIRECTORY, "page-remove-fly-table.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDocShell* pShell = pTextDoc->GetDocShell(); + SwDoc* pDoc = pShell->GetDoc(); + + // When updating the ToC and incrementally formatting the document: + SwView* pView = pDoc->GetDocShell()->GetView(); + SfxDispatcher& rDispatcher = *pView->GetViewFrame()->GetDispatcher(); + rDispatcher.Execute(FN_UPDATE_TOX); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->Reformat(); + + // Then make sure that the 2nd table below the bookmark has no unwanted top margin: + pWrtShell->GotoMark("test"); + pWrtShell->Down(/*bSelect=*/false, /*nCount=*/1, /*bBasicCall=*/false); + pWrtShell->Down(/*bSelect=*/false, /*nCount=*/1, /*bBasicCall=*/false); + SwPaM* pCursor = pWrtShell->GetCursor(); + SwTextNode* pTextNode = pCursor->GetPoint()->nNode.GetNode().GetTextNode(); + SwFrame* pTextFrame = pTextNode->getLayoutFrame(nullptr); + SwTabFrame* pInnerTable = pTextFrame->FindTabFrame(); + SwTabFrame* pOuterTable = pInnerTable->GetUpper()->FindTabFrame(); + long nActual = pOuterTable->getFramePrintArea().Top(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 + // - Actual : 5879 + // i.e. the bad table had a large, unwanted/leftover top margin. + CPPUNIT_ASSERT_EQUAL(static_cast<long>(0), nActual); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 72d673b224d4..b8f586938454 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -987,6 +987,17 @@ void SwPageFrame::MoveFly( SwFlyFrame *pToMove, SwPageFrame *pDest ) { m_pSortedObjs.reset(); } + + // Removing a fly from the page affects the margin of e.g. tables, so update the frame print + // area of the lowers of my body frame. + SwFrame* pBodyFrame = FindBodyCont(); + if (pBodyFrame) + { + for (SwFrame* pFrame = pBodyFrame->GetLower(); pFrame; pFrame = pFrame->GetNext()) + { + pFrame->InvalidatePrt(); + } + } } // Register