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:
Binary file not shown.
@@ -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");
|
||||
|
||||
@@ -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() )
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user