sw/qa/core/doc/data/floating-table-dummy-text.docx |binary sw/qa/core/doc/doc.cxx | 33 ++++++++++++++++ sw/source/core/doc/DocumentContentOperationsManager.cxx | 21 ++++++++++ 3 files changed, 54 insertions(+)
New commits: commit 5e19348fb9507882827d29f875696ab225198be2 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Aug 1 09:06:43 2023 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Aug 2 08:06:31 2023 +0200 tdf#156260 sw floattable: avoid overlapping flys on anchor change Going to the end of the document, typing "dt" and F3 collapses the multi-page floating table into a single page, with overlapping text. In practice we insert a new paragraph before the "dt" one, insert the dummy text there and then re-anchor the floating table from the old paragraph to the new one. Such re-anchoring isn't really meant to be done with floating tables, which are always just anchored in the next paragraph in practice. An additional problem is that the amount of fly frames created depends on the position of the first fly frame, so if the anchor changes, we may need a different number of split fly frames. Fix the problem by not trying to reuse the old fly frames on anchor change: delete the old frames, change the anchor and finally create the new frames, which leads to correct layout with complicated logic trying to update the old fly chain to the new anchor. The original document still puts some dummy text on page 4 instead of starting it on page 5, that part is still unfixed. Change-Id: I74549e2ea8ca0d06a9e4814a58aaa8ca476263dc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155122 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 073072f0a3abacfe4f9cc920b8138d7abc84db70) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155137 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/core/doc/data/floating-table-dummy-text.docx b/sw/qa/core/doc/data/floating-table-dummy-text.docx new file mode 100644 index 000000000000..14de5a920a88 Binary files /dev/null and b/sw/qa/core/doc/data/floating-table-dummy-text.docx differ diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index 5b523067523a..f8faee3a1bcd 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -34,6 +34,10 @@ #include <IDocumentRedlineAccess.hxx> #include <frmmgr.hxx> #include <formatflysplit.hxx> +#include <IDocumentLayoutAccess.hxx> +#include <rootfrm.hxx> +#include <pagefrm.hxx> +#include <sortedobjs.hxx> /// Covers sw/source/core/doc/ fixes. class SwCoreDocTest : public SwModelTestBase @@ -482,6 +486,35 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testSplitFlyChain) CPPUNIT_ASSERT_EQUAL(SwChainRet::IS_IN_CHAIN, eActual); } +CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testSplitExpandGlossary) +{ + // Given a document with a split fly (2 pages) and a 'dt' at the end: + createSwDoc("floating-table-dummy-text.docx"); + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/false); + + // When expanding 'dt' to an actual dummy text: + dispatchCommand(mxComponent, ".uno:ExpandGlossary", {}); + + // Then make sure the 2 fly frames stay on the 2 pages: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower()); + CPPUNIT_ASSERT(pPage1); + CPPUNIT_ASSERT(pPage1->GetSortedObjs()); + const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. both parts of the split fly chain were on page 1. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size()); + auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext()); + CPPUNIT_ASSERT(pPage2); + CPPUNIT_ASSERT(pPage2->GetSortedObjs()); + const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 470a018eb0ef..f7d24dd55ea0 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -70,6 +70,7 @@ #include <fmtflcnt.hxx> #include <docedt.hxx> #include <frameformats.hxx> +#include <formatflysplit.hxx> #include <o3tl/safeint.hxx> #include <sal/log.hxx> #include <unotools/charclass.hxx> @@ -5238,7 +5239,27 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo { SwFormatAnchor anchor(*pAnchor); anchor.SetAnchor( &startPosAtPara ); + + bool bSplitFly = false; + if (pFly->GetFlySplit().GetValue()) + { + SwIterator<SwFrame, SwModify> aIter(*pFly); + bSplitFly = aIter.First() && aIter.Next(); + } + if (bSplitFly) + { + // This fly format has multiple frames, and we change the anchor. Remove the + // old frames, which were based on the old anchor position. + pFly->DelFrames(); + } + pFly->SetFormatAttr(anchor); + + if (bSplitFly) + { + // Re-create the frames now that the new anchor is set. + pFly->MakeFrames(); + } } } }