diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-12-09 16:52:48 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-12-09 18:08:59 +0000 |
commit | cf2c070de2bafeec3b476c6bff7bb4ac87ba46db (patch) | |
tree | be0fb5eead094f07e715caa12a08ff01a9e9bc6d /sw | |
parent | 31084ebb59093be7dfe5ab53a20fdb3bcfde34b6 (diff) |
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).
Change-Id: I0424d9eea4d8a030959f8534985950c7efad4686
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143881
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/core/layout/data/page-remove-fly-table.odt | bin | 0 -> 13943 bytes | |||
-rw-r--r-- | sw/qa/core/layout/layout.cxx | 38 | ||||
-rw-r--r-- | sw/source/core/layout/flylay.cxx | 11 |
3 files changed, 49 insertions, 0 deletions
diff --git a/sw/qa/core/layout/data/page-remove-fly-table.odt b/sw/qa/core/layout/data/page-remove-fly-table.odt Binary files differnew file mode 100644 index 000000000000..6aaf230966ef --- /dev/null +++ b/sw/qa/core/layout/data/page-remove-fly-table.odt diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx index f95cfcf09bc9..7a0f69bab815 100644 --- a/sw/qa/core/layout/layout.cxx +++ b/sw/qa/core/layout/layout.cxx @@ -14,6 +14,8 @@ #include <vcl/gdimtf.hxx> #include <svx/svdpage.hxx> #include <o3tl/string_view.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> #include <wrtsh.hxx> #include <docsh.hxx> @@ -29,6 +31,12 @@ #include <IDocumentContentOperations.hxx> #include <fmtfsize.hxx> #include <fmtfollowtextflow.hxx> +#include <view.hxx> +#include <cmdid.h> +#include <node.hxx> +#include <ndtxt.hxx> +#include <tabfrm.hxx> +#include <cntfrm.hxx> /// Covers sw/source/core/layout/ fixes. class SwCoreLayoutTest : public SwModelTestBase @@ -883,6 +891,36 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testFollowTextFlowWrapInBackground) CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(1000), nCellHeight); } +CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testPageRemoveFlyTable) +{ + // Given a document with a ToC and several tables, one table marked with a bookmark: + createSwDoc("page-remove-fly-table.odt"); + SwDoc* pDoc = getSwDoc(); + + // 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); + SwCursor* pCursor = pWrtShell->GetCursor(); + SwTextNode* pTextNode = pCursor->GetPoint()->GetNode().GetTextNode(); + SwFrame* pTextFrame = pTextNode->getLayoutFrame(nullptr); + SwTabFrame* pInnerTable = pTextFrame->FindTabFrame(); + SwTabFrame* pOuterTable = pInnerTable->GetUpper()->FindTabFrame(); + tools::Long nActual = pOuterTable->getFramePrintArea().Top(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 + // - Actual : 5879 + // i.e. the problematic table had a large, unwanted/leftover top margin. + CPPUNIT_ASSERT_EQUAL(static_cast<tools::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 193c678a2e18..d7c6969a4b6b 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -989,6 +989,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 |