sw: layout: ignore Keep-With-Next on hidden frames, part1

When a frame is hidden, don't consider it when evaluating keep-with-next
attributes - this was the case for content in hidden sections before
commit 0c96119895

~SwFrameNotify() invalidating position of hidden frame with keep
attribute causes layout loops.

Also skip hidden frames in SwFlowFrame::IsKeepFwdMoveAllowed(),
SwFlowFrame::CheckKeep(), SwFlowFrame::IsPrevObjMove(),
SwFlowFrame::MoveBwd(), CalcContent().

Change-Id: I68556ba0a8e016d962399f3ce199e5eda0378867
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177975
Tested-by: Michael Stahl <michael.stahl@allotropia.de>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
This commit is contained in:
Michael Stahl 2024-12-06 14:10:32 +01:00
parent 59891cd398
commit cd8468bcba
4 changed files with 55 additions and 8 deletions

View file

@ -184,6 +184,9 @@ public:
SvxFormatBreakItem const& rBreak,
bool bBreakCheck = false ) const;
SwFrame * FindPrevIgnoreHidden() const;
SwFrame * FindNextIgnoreHidden() const;
bool HasLockedFollow() const;
bool HasParaSpaceAtPages( bool bSct ) const;

View file

@ -131,7 +131,9 @@ bool SwFlowFrame::IsKeepFwdMoveAllowed( bool bIgnoreMyOwnKeepValue )
if ( bIgnoreMyOwnKeepValue && pFrame->GetIndPrev() )
pFrame = pFrame->GetIndPrev();
do
{ if ( pFrame->GetAttrSet()->GetKeep().GetValue() )
{
if (pFrame->GetAttrSet()->GetKeep().GetValue()
|| pFrame->IsHiddenNow())
pFrame = pFrame->GetIndPrev();
else
return true;
@ -150,22 +152,42 @@ void SwFlowFrame::CheckKeep()
// it's possible for the whole troop to move back.
SwFrame *pPre = m_rThis.GetIndPrev();
assert(pPre);
while (pPre && pPre->IsHiddenNow())
{
pPre = pPre->GetIndPrev();
}
if (!pPre)
{
return;
}
if( pPre->IsSctFrame() )
{
SwFrame *pLast = static_cast<SwSectionFrame*>(pPre)->FindLastContent();
while (pLast && pLast->IsHiddenNow())
{
pLast = pLast->GetIndPrev();
}
if( pLast && pLast->FindSctFrame() == pPre )
pPre = pLast;
else
return;
}
SwFrame* pTmp;
SwFrame* pTmp{pPre};
bool bKeep;
while ( (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
nullptr != ( pTmp = pPre->GetIndPrev() ) )
nullptr != (pTmp = pTmp->GetIndPrev()) )
{
if (pTmp->IsHiddenNow())
{
continue;
}
if( pTmp->IsSctFrame() )
{
SwFrame *pLast = static_cast<SwSectionFrame*>(pTmp)->FindLastContent();
while (pLast && pLast->IsHiddenNow())
{
pLast = pLast->GetIndPrev();
}
if( pLast && pLast->FindSctFrame() == pTmp )
pTmp = pLast;
else
@ -236,6 +258,7 @@ bool SwFlowFrame::IsKeep(SvxFormatKeepItem const& rKeep,
SvxFormatBreakItem const& rBreak,
bool const bCheckIfLastRowShouldKeep) const
{
assert(!m_rThis.IsHiddenNow()); // check it before?
// 1. The keep attribute is ignored inside footnotes
// 2. For compatibility reasons, the keep attribute is
// ignored for frames inside table cells
@ -338,6 +361,26 @@ bool SwFlowFrame::IsKeep(SvxFormatKeepItem const& rKeep,
return bKeep;
}
SwFrame * SwFlowFrame::FindPrevIgnoreHidden() const
{
SwFrame * pRet{m_rThis.FindPrev()};
while (pRet && pRet->IsHiddenNow())
{
pRet = pRet->FindPrev();
}
return pRet;
}
SwFrame * SwFlowFrame::FindNextIgnoreHidden() const
{
SwFrame * pRet{m_rThis.FindNext()};
while (pRet && pRet->IsHiddenNow())
{
pRet = pRet->FindNext();
}
return pRet;
}
sal_uInt8 SwFlowFrame::BwdMoveNecessary( const SwPageFrame *pPage, const SwRect &rRect )
{
// The return value helps deciding whether we need to flow back (3),
@ -1188,7 +1231,7 @@ bool SwFlowFrame::IsPrevObjMove() const
if( pSh && pSh->GetViewOptions()->getBrowseMode() )
return false;
SwFrame *pPre = m_rThis.FindPrev();
SwFrame *const pPre{FindPrevIgnoreHidden()};
if ( pPre && pPre->GetDrawObjs() )
{
@ -2616,7 +2659,7 @@ bool SwFlowFrame::MoveBwd( bool &rbReformat )
// keep with next frame and next frame is locked.
// i#38232 - If next frame is a table, do *not* check,
// if it's locked.
if ( pNewUpper && !IsFollow() &&
if ( pNewUpper && !IsFollow() && !m_rThis.IsHiddenNow() &&
m_rThis.GetAttrSet()->GetKeep().GetValue() && m_rThis.GetIndNext() )
{
SwFrame* pIndNext = m_rThis.GetIndNext();

View file

@ -1705,9 +1705,10 @@ void CalcContent( SwLayoutFrame *pLay, bool bNoColl )
// frame due to its keep-attribute, if it can't move forward.
// #i57765# - do not consider invalid previous
// frame, if current frame has a column/page break before attribute.
SwFrame* pTmpPrev = pFrame->FindPrev();
assert(pFrame->IsFlowFrame());
SwFlowFrame* pTmpFlowFrame = SwFlowFrame::CastFlowFrame(pFrame);
SwFrame* pTmpPrev = pTmpFlowFrame->FindPrevIgnoreHidden();
SwFlowFrame* pTmpPrevFlowFrame = pTmpPrev && pTmpPrev->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev) : nullptr;
SwFlowFrame* pTmpFlowFrame = pFrame->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pFrame) : nullptr;
bool bPrevInvalid = pTmpPrevFlowFrame && pTmpFlowFrame &&
!pTmpFlowFrame->IsFollow() &&

View file

@ -155,7 +155,7 @@ void SwFrameNotify::ImplDestroy()
{
if ( mbInvaKeep )
{
SwFrame *pPre = mpFrame->FindPrev();
SwFrame *pPre = pFlow->FindPrevIgnoreHidden();
if ( pPre && pPre->IsFlowFrame() )
{
// 1. pPre wants to keep with me: