sw/qa/extras/layout/data/hideSection.fodt |   39 ++++++++++++++++++++++++++++++
 sw/qa/extras/layout/layout5.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 4cfd0c99d1bd85a4927cb3b433b903cc26f5ef95
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Jun 21 17:25:25 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Jun 21 17:29:36 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.
    
    Change-Id: Iafdd1c41b52d2170d5dd2b3bc2cbc1a5f657c0fb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186779
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

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/layout5.cxx b/sw/qa/extras/layout/layout5.cxx
index 075c1a58417d..de3df0d3b1d7 100644
--- a/sw/qa/extras/layout/layout5.cxx
+++ b/sw/qa/extras/layout/layout5.cxx
@@ -1785,6 +1785,30 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf166871)
     assertXPath(pXmlDoc, "//page[12]/body/column[6]/body/txt", 0);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf166978)
+{
+    // Given a document with a table, which cell has a section:
+    createSwDoc("hideSection.fodt");
+    CPPUNIT_ASSERT_EQUAL(1, getPages());
+
+    // Hide the section
+    auto xTextSectionsSupplier = 
mxComponent.queryThrow<css::text::XTextSectionsSupplier>();
+    auto xSections = xTextSectionsSupplier->getTextSections();
+    CPPUNIT_ASSERT(xSections);
+    auto xSection = 
xSections->getByName(u"Section1"_ustr).queryThrow<css::beans::XPropertySet>();
+    xSection->setPropertyValue(u"IsVisible"_ustr, 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]",
+                       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 613ac7f9194d..9b11ff0c3e31 100644
--- a/sw/source/core/layout/sectfrm.cxx
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -2364,7 +2364,7 @@ SwTwips SwSectionFrame::Grow_(SwTwips nDist, 
SwResizeLimitReason& reason, bool b
                 SetCompletePaint();
                 InvalidatePage();
             }
-            if( GetUpper() && GetUpper()->IsHeaderFrame() )
+            if (GetUpper() && (GetUpper()->IsHeaderFrame() || 
GetUpper()->IsCellFrame()))
                 GetUpper()->InvalidateSize();
         }
 
@@ -2788,13 +2788,6 @@ void SwSectionFrame::SwClientNotify(const SwModify& 
rMod, const SfxHint& rHint)
     {
         InvalidateAll();
         InvalidateObjs(false);
-        {
-            // Set it to a huge positive value, to make sure a recalculation 
fires
-            constexpr SwTwips HUGE_POSITIVE = o3tl::toTwips(100, 
o3tl::Length::m);
-            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 5fb7f94b3aaf..86cd2c1c0ca4 100644
--- a/sw/source/core/layout/trvlfrm.cxx
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -1745,10 +1745,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);

Reply via email to