sw: layout: fix page breaks when unhiding a hidden section

Commit ff7f1b59e22092d8548459e75fe912db852f056f removed the
DelFrames()/MakeFrames() in SwSection::ImplSetHiddenFlag(), which was
handling the page breaks previously.

Add some code to SwSectionFrame::SwClientNotify() to call
SwLayHelper::CheckInsertPage() which appears to be the important part
called by InsertCnt_() previously.

Change-Id: Id6560d8706abf92fba259a5d534d6cd5067c8e6a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172609
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
This commit is contained in:
Michael Stahl
2024-08-30 13:44:34 +02:00
parent 4bc57fbde9
commit a97e245ba1
5 changed files with 185 additions and 31 deletions
+87
View File
@@ -1743,6 +1743,93 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf156724)
assertXPath(pXmlDoc, "/root/page"_ostr, 2);
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testHiddenSectionPageDescs)
{
createSwDoc("hidden-sections-with-pagestyles.odt");
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page"_ostr, 2);
assertXPath(pXmlDoc, "/root/page[1]"_ostr, "formatName"_ostr, "Hotti");
assertXPath(pXmlDoc, "/root/page[1]/body/section"_ostr, 1);
assertXPath(pXmlDoc, "/root/page[1]/body/section[1]"_ostr, "formatName"_ostr,
u"Verfügung"_ustr);
assertXPath(pXmlDoc, "/root/page[2]/body/section"_ostr, 2);
assertXPath(pXmlDoc, "/root/page[2]/body/section[1]"_ostr, "formatName"_ostr,
u"Verfügung"_ustr);
// should be > 0, no idea why it's different on Windows
#ifdef _WIN32
assertXPath(pXmlDoc, "/root/page[2]/body/section[1]/infos/bounds"_ostr, "height"_ostr,
"552");
#else
assertXPath(pXmlDoc, "/root/page[2]/body/section[1]/infos/bounds"_ostr, "height"_ostr,
"532");
#endif
assertXPath(pXmlDoc, "/root/page[2]/body/section[2]"_ostr, "formatName"_ostr,
"Rueckantwort");
assertXPath(pXmlDoc, "/root/page[2]/body/section[2]/infos/bounds"_ostr, "height"_ostr, "0");
assertXPath(pXmlDoc, "/root/page[2]"_ostr, "formatName"_ostr, "Folgeseite");
}
// toggle one section hidden and other visible
executeMacro(
u"vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document"_ustr);
Scheduler::ProcessEventsToIdle();
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page"_ostr, 3);
assertXPath(pXmlDoc, "/root/page[1]"_ostr, "formatName"_ostr, "Hotti");
assertXPath(pXmlDoc, "/root/page[1]/body/section"_ostr, 2);
assertXPath(pXmlDoc, "/root/page[1]/body/section[1]"_ostr, "formatName"_ostr,
u"Verfügung"_ustr);
assertXPath(pXmlDoc, "/root/page[1]/body/section[2]"_ostr, "formatName"_ostr,
"Rueckantwort");
assertXPath(pXmlDoc, "/root/page[2]"_ostr, "formatName"_ostr, "Empty Page");
assertXPath(pXmlDoc, "/root/page[3]/body/section"_ostr, 1);
assertXPath(pXmlDoc, "/root/page[3]/body/section[1]"_ostr, "formatName"_ostr,
"Rueckantwort");
// should be > 0, no idea why it's different on Windows
#ifdef _WIN32
assertXPath(pXmlDoc, "/root/page[3]/body/section[1]/infos/bounds"_ostr, "height"_ostr,
"552");
#else
assertXPath(pXmlDoc, "/root/page[3]/body/section[1]/infos/bounds"_ostr, "height"_ostr,
"532");
#endif
assertXPath(pXmlDoc, "/root/page[3]"_ostr, "formatName"_ostr, "RueckantwortRechts");
}
// toggle one section hidden and other visible
executeMacro(
u"vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document"_ustr);
Scheduler::ProcessEventsToIdle();
{
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page"_ostr, 2);
assertXPath(pXmlDoc, "/root/page[1]"_ostr, "formatName"_ostr, "Hotti");
assertXPath(pXmlDoc, "/root/page[1]/body/section"_ostr, 1);
assertXPath(pXmlDoc, "/root/page[1]/body/section[1]"_ostr, "formatName"_ostr,
u"Verfügung"_ustr);
assertXPath(pXmlDoc, "/root/page[2]/body/section"_ostr, 2);
assertXPath(pXmlDoc, "/root/page[2]/body/section[1]"_ostr, "formatName"_ostr,
u"Verfügung"_ustr);
// should be > 0, no idea why it's different on Windows
#ifdef _WIN32
assertXPath(pXmlDoc, "/root/page[2]/body/section[1]/infos/bounds"_ostr, "height"_ostr,
"552");
#else
assertXPath(pXmlDoc, "/root/page[2]/body/section[1]/infos/bounds"_ostr, "height"_ostr,
"532");
#endif
assertXPath(pXmlDoc, "/root/page[2]/body/section[2]"_ostr, "formatName"_ostr,
"Rueckantwort");
assertXPath(pXmlDoc, "/root/page[2]/body/section[2]/infos/bounds"_ostr, "height"_ostr, "0");
assertXPath(pXmlDoc, "/root/page[2]"_ostr, "formatName"_ostr, "Folgeseite");
}
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf156725)
{
createSwDoc("tdf156725.fodt");
+36 -30
View File
@@ -635,20 +635,25 @@ sal_uLong SwLayHelper::CalcPageCount()
* The break after flag is set, if the actual content
* wants a break after.
*/
bool SwLayHelper::CheckInsertPage()
bool SwLayHelper::CheckInsertPage(
SwPageFrame *& rpPage,
SwLayoutFrame *& rpLay,
SwFrame *& rpFrame,
bool & rIsBreakAfter,
bool const isForceBreak)
{
bool bEnd = nullptr == mrpPage->GetNext();
const SvxFormatBreakItem& rBrk = mrpFrame->GetBreakItem();
const SwFormatPageDesc& rDesc = mrpFrame->GetPageDescItem();
bool bEnd = nullptr == rpPage->GetNext();
const SvxFormatBreakItem& rBrk = rpFrame->GetBreakItem();
const SwFormatPageDesc& rDesc = rpFrame->GetPageDescItem();
// #118195# Do not evaluate page description if frame
// is a follow frame!
const SwPageDesc* pDesc = mrpFrame->IsFlowFrame() &&
SwFlowFrame::CastFlowFrame( mrpFrame )->IsFollow() ?
nullptr :
rDesc.GetPageDesc();
const SwPageDesc* pDesc = rpFrame->IsFlowFrame()
&& SwFlowFrame::CastFlowFrame(rpFrame)->IsFollow()
? nullptr
: rDesc.GetPageDesc();
bool bBrk = mnParagraphCnt > mnMaxParaPerPage || mbBreakAfter;
mbBreakAfter = rBrk.GetBreak() == SvxBreak::PageAfter ||
bool bBrk = isForceBreak || rIsBreakAfter;
rIsBreakAfter = rBrk.GetBreak() == SvxBreak::PageAfter ||
rBrk.GetBreak() == SvxBreak::PageBoth;
if ( !bBrk )
bBrk = rBrk.GetBreak() == SvxBreak::PageBefore ||
@@ -659,47 +664,48 @@ bool SwLayHelper::CheckInsertPage()
::std::optional<sal_uInt16> oPgNum;
if ( !pDesc )
{
pDesc = mrpPage->GetPageDesc()->GetFollow();
pDesc = rpPage->GetPageDesc()->GetFollow();
}
else
{
oPgNum = rDesc.GetNumOffset();
if ( oPgNum )
static_cast<SwRootFrame*>(mrpPage->GetUpper())->SetVirtPageNum(true);
static_cast<SwRootFrame*>(rpPage->GetUpper())->SetVirtPageNum(true);
}
bool bNextPageRight = !mrpPage->OnRightPage();
bool bNextPageRight = !rpPage->OnRightPage();
bool bInsertEmpty = false;
assert(mrpPage->GetUpper()->GetLower());
assert(rpPage->GetUpper()->GetLower());
if (oPgNum && bNextPageRight != IsRightPageByNumber(
*static_cast<SwRootFrame*>(mrpPage->GetUpper()), *oPgNum))
*static_cast<SwRootFrame*>(rpPage->GetUpper()), *oPgNum))
{
bNextPageRight = !bNextPageRight;
bInsertEmpty = true;
}
// If the page style is changing, we'll have a first page.
bool bNextPageFirst = pDesc != mrpPage->GetPageDesc();
::InsertNewPage( const_cast<SwPageDesc&>(*pDesc), mrpPage->GetUpper(),
bNextPageRight, bNextPageFirst, bInsertEmpty, false, mrpPage->GetNext());
bool bNextPageFirst = pDesc != rpPage->GetPageDesc();
::InsertNewPage( const_cast<SwPageDesc&>(*pDesc), rpPage->GetUpper(),
bNextPageRight, bNextPageFirst, bInsertEmpty, false, rpPage->GetNext());
if ( bEnd )
{
OSL_ENSURE( mrpPage->GetNext(), "No new page?" );
OSL_ENSURE( rpPage->GetNext(), "No new page?" );
do
{ mrpPage = static_cast<SwPageFrame*>(mrpPage->GetNext());
} while ( mrpPage->GetNext() );
{
rpPage = static_cast<SwPageFrame*>(rpPage->GetNext());
} while (rpPage->GetNext());
}
else
{
OSL_ENSURE( mrpPage->GetNext(), "No new page?" );
mrpPage = static_cast<SwPageFrame*>(mrpPage->GetNext());
if ( mrpPage->IsEmptyPage() )
OSL_ENSURE( rpPage->GetNext(), "No new page?" );
rpPage = static_cast<SwPageFrame*>(rpPage->GetNext());
if (rpPage->IsEmptyPage())
{
OSL_ENSURE( mrpPage->GetNext(), "No new page?" );
mrpPage = static_cast<SwPageFrame*>(mrpPage->GetNext());
OSL_ENSURE( rpPage->GetNext(), "No new page?" );
rpPage = static_cast<SwPageFrame*>(rpPage->GetNext());
}
}
mrpLay = mrpPage->FindBodyCont();
while( mrpLay->Lower() )
mrpLay = static_cast<SwLayoutFrame*>(mrpLay->Lower());
rpLay = rpPage->FindBodyCont();
while (rpLay->Lower())
rpLay = static_cast<SwLayoutFrame*>(rpLay->Lower());
return true;
}
return false;
@@ -885,7 +891,7 @@ bool SwLayHelper::CheckInsert( SwNodeOffset nNodeIndex )
}
SwPageFrame* pLastPage = mrpPage;
if( CheckInsertPage() )
if (CheckInsertPage(mrpPage, mrpLay, mrpFrame, mbBreakAfter, mnMaxParaPerPage < mnParagraphCnt))
{
CheckFlyCache_( pLastPage );
if( mrpPrv && mrpPrv->IsTextFrame() && !mrpPrv->isFrameAreaSizeValid() )
+2 -1
View File
@@ -129,7 +129,8 @@ public:
sal_uLong CalcPageCount();
bool CheckInsert( SwNodeOffset nNodeIndex );
bool CheckInsertPage();
static bool CheckInsertPage(SwPageFrame *& rpPage, SwLayoutFrame *& rpLay,
SwFrame *& rpFrame, bool & rIsBreakAfter, bool const isForceBreak);
/// Look for fresh text frames at this (new) page and set them to the right
/// position, if they are in the fly cache.
+60
View File
@@ -39,6 +39,7 @@
#include <colfrm.hxx>
#include <tabfrm.hxx>
#include <ftnfrm.hxx>
#include "layhelp.hxx"
#include <layouter.hxx>
#include <dbg_lay.hxx>
#include <viewopt.hxx>
@@ -2745,6 +2746,65 @@ void SwSectionFrame::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
pLowerFrame->InvalidateAll();
pLowerFrame->InvalidateObjs(false);
}
// Check if any page-breaks have been unhidden, create the new pages.
// Call IsHiddenNow() because a parent section could still hide.
if (!IsFollow() && IsInDocBody() && !IsInTab() && !IsHiddenNow())
{
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
SwViewShell *const pViewShell(getRootFrame()->GetCurrShell());
// no notification if SwViewShell is in construction
if (pViewShell && !pViewShell->IsInConstructor()
&& pViewShell->GetLayout()
&& pViewShell->GetLayout()->IsAnyShellAccessible())
{
auto pNext = FindNextCnt(true);
auto pPrev = FindPrevCnt();
pViewShell->InvalidateAccessibleParaFlowRelation(
pNext ? pNext->DynCastTextFrame() : nullptr,
pPrev ? pPrev->DynCastTextFrame() : nullptr );
}
#endif
SwSectionFrame * pFollow{this};
SwPageFrame * pPage{FindPageFrame()};
SwLayoutFrame * pLay{nullptr};
bool isBreakAfter{false};
SwFrame * pFirstOnPage{pPage->FindFirstBodyContent()};
while (pFirstOnPage->GetUpper()->IsInTab())
{
pFirstOnPage = pFirstOnPage->GetUpper();
}
assert(pFirstOnPage->IsContentFrame() || pFirstOnPage->IsTabFrame());
for (SwFrame* pLowerFrame = Lower(); pLowerFrame; pLowerFrame = pLowerFrame->GetNext())
{
if (pLowerFrame == pFirstOnPage)
{
continue;
}
assert(pLowerFrame->IsContentFrame() || pLowerFrame->IsTabFrame());
if (SwLayHelper::CheckInsertPage(pPage, pLay, pLowerFrame, isBreakAfter, false))
{
if (pLowerFrame == Lower())
{ // move the whole section
assert(pFollow == this);
MoveSubTree(pLay, nullptr);
}
else
{
if (GetNext())
{
assert(GetNext()->IsFlowFrame());
SwFlowFrame::CastFlowFrame(GetNext())->MoveSubTree(pLay, nullptr);
}
pFollow = new SwSectionFrame(*pFollow, false);
SimpleFormat();
pFollow->InsertBehind(pLay, nullptr);
pFollow->Init();
SwFlowFrame::CastFlowFrame(pLowerFrame)->MoveSubTree(pFollow, nullptr);
}
}
}
CheckPageDescs(FindPageFrame());
}
}
else
SwFrame::SwClientNotify(rMod, rHint);