sw/qa/extras/layout/data/hideSection.fodt | 39 ++++++++++++++++++++++++++++++ sw/qa/extras/layout/layout2.cxx | 24 ++++++++++++++++++ sw/source/core/layout/sectfrm.cxx | 9 ------ sw/source/core/layout/trvlfrm.cxx | 4 ++- 4 files changed, 67 insertions(+), 9 deletions(-)
New commits: commit a3cc65d77ee8874c83f5c9ce52915ad16ee88989 Author: Mike Kaganski <[email protected]> AuthorDate: Sat Jun 21 17:25:25 2025 +0500 Commit: Michael Stahl <[email protected]> CommitDate: Tue Oct 14 20:05:04 2025 +0200 tdf#166978: replace HUGE_POSITIVE hack with proper upper invalidation The problem was, that the change of section's height (either to zero when hiding, or from zero to some height when showing) could keep its upper's size unchanged and valid. Invalidating the upper's size in SfxHintId::SwSectionHidden handler was not enough; in the following layout calculation, the upper sets its mbFrameAreaSizeValid to true before its lowers' calculation. Then, during their calculation: * If the section was hiding, SwFrame::MakeValidZeroHeight would fail in ShrinkFrame, then force its height to 0 in 'if (IsLayoutFrame())' block, and not notify upper; * If the section was showing, SwSectionFrame::Grow_ could see that the upper has space enough for the section (e.g., when there are more children after this section), and also not notify upper. The HUGE_POSITIVE hack allowed to force following re-layout in some cases; but the bugdoc failed when the cell was initially made very tall, and hat to split; then the section in it was shrinked to 0,and that didn't cause the merge with the follow. This fixes the problem by: 1. Removing of the HUGE_POSITIVE hack; 2. Invalidating upper cell frame in SwSectionFrame::Grow_, similar to commit ee57229154a91cf632871cfcb1eb9609908f3882 (Fix #88178#: Sectionframe in headerframe, don't grow without invalidation, 2001-06-13); 3. Invalidating layout frame's upper in SwFrame::MakeValidZeroHeight, when ShrinkFrame didn't make it 0-height. In #3, I decided to not check the upper's kind, for robustness; if needed, checks may be added in follow-ups, for specific problems. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186779 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> (cherry picked from commit 4cfd0c99d1bd85a4927cb3b433b903cc26f5ef95) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186788 Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit f1fa292d4a8f5553990215fb4aef919746c5bec5) Conflicts: sw/source/core/layout/sectfrm.cxx Change-Id: Iafdd1c41b52d2170d5dd2b3bc2cbc1a5f657c0fb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191740 Tested-by: allotropia jenkins <[email protected]> Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/qa/extras/layout/data/hideSection.fodt b/sw/qa/extras/layout/data/hideSection.fodt new file mode 100644 index 000000000000..ba953e5103e8 --- /dev/null +++ b/sw/qa/extras/layout/data/hideSection.fodt @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:automatic-styles> + <style:style style:name="Table1" style:family="table"> + <style:table-properties table:align="margins"/> + </style:style> + <style:style style:name="Table1.A1" style:family="table-cell"> + <style:table-cell-properties fo:border="0.05pt solid #000000"/> + </style:style> + </office:automatic-styles> + <office:body> + <office:text> + <table:table table:name="Table1" table:style-name="Table1"> + <table:table-column/> + <table:table-column/> + <table:table-row> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>A1</text:p> + </table:table-cell> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:section text:name="Section1"> + <text:p>Section1: hide me</text:p> + </text:section> + <text:p>B1</text:p> + </table:table-cell> + </table:table-row> + <table:table-row> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>A2: this row suddenly jumps to the next page</text:p> + </table:table-cell> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>B2</text:p> + </table:table-cell> + </table:table-row> + </table:table> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx index b98638c376a7..406df8998b1e 100644 --- a/sw/qa/extras/layout/layout2.cxx +++ b/sw/qa/extras/layout/layout2.cxx @@ -997,6 +997,30 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166691) assertXPath(pXmlDoc, "//page", 1); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166978) +{ + // Given a document with a table, which cell has a section: + createDoc("hideSection.fodt"); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + + // Hide the section + uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY_THROW); + auto xSections = xTextSectionsSupplier->getTextSections(); + CPPUNIT_ASSERT(xSections); + uno::Reference<beans::XPropertySet> xSection(xSections->getByName("Section1"), uno::UNO_QUERY_THROW); + xSection->setPropertyValue("IsVisible", css::uno::Any(false)); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(1, getPages()); // must not split the second row of the table to page 2 + // Check the layout dump; the whole table must be still on the first page + auto pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page", 1); + assertXPath(pXmlDoc, "//page[1]/body/tab", 1); + assertXPath(pXmlDoc, "//page[1]/body/tab/row", 2); + assertXPathContent(pXmlDoc, "//page[1]/body/tab/row[2]/cell[1]/txt", + u"A2: this row suddenly jumps to the next page"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/sectfrm.cxx b/sw/source/core/layout/sectfrm.cxx index bbb375678e97..ab474095b0be 100644 --- a/sw/source/core/layout/sectfrm.cxx +++ b/sw/source/core/layout/sectfrm.cxx @@ -2293,7 +2293,7 @@ SwTwips SwSectionFrame::Grow_( SwTwips nDist, bool bTst ) SetCompletePaint(); InvalidatePage(); } - if( GetUpper() && GetUpper()->IsHeaderFrame() ) + if (GetUpper() && (GetUpper()->IsHeaderFrame() || GetUpper()->IsCellFrame())) GetUpper()->InvalidateSize(); } @@ -2686,13 +2686,6 @@ void SwSectionFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) { InvalidateAll(); InvalidateObjs(false); - { - // Set it to a huge positive value, to make sure a recalculation fires - constexpr SwTwips HUGE_POSITIVE = 10000 * 1440 / 2.54; // 100m - SwFrameAreaDefinition::FrameAreaWriteAccess area(*this); - SwRectFnSet(this).SetHeight(area, HUGE_POSITIVE); - } - GetUpper()->InvalidateSize(); InvalidateFramesInSection(Lower()); if (Lower()) diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx index 9f6e7a074943..d499efbd0c6b 100644 --- a/sw/source/core/layout/trvlfrm.cxx +++ b/sw/source/core/layout/trvlfrm.cxx @@ -1701,10 +1701,12 @@ void SwFrame::MakeValidZeroHeight() aRectFnSet.SetHeight(area, 0); } ShrinkFrame(aRectFnSet.GetHeight(getFrameArea())); - if (IsLayoutFrame()) // ShrinkFrame might do nothing! + if (IsLayoutFrame() && aRectFnSet.GetHeight(getFrameArea())) // ShrinkFrame might do nothing! { SwFrameAreaDefinition::FrameAreaWriteAccess area(*this); aRectFnSet.SetHeight(area, 0); + if (GetUpper()) + GetUpper()->InvalidateSize(); } setFrameAreaSizeValid(true); setFramePrintAreaValid(true);
