/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
namespace
{ /** * Performs the correct type of position invalidation depending on if we're in * CalcContent().
*/ void InvalidateFramePos(SwFrame* pFrame, bool bInCalcContent)
{ if (bInCalcContent)
pFrame->InvalidatePos_(); else
pFrame->InvalidatePos();
}
}
// NOTE: call <SwSectionFrame::Init()> directly after creation of a new section // frame and its insert in the layout. void SwSectionFrame::Init()
{
assert(GetUpper() && "SwSectionFrame::Init before insertion?!");
SwRectFnSet aRectFnSet(this);
tools::Long nWidth = aRectFnSet.GetWidth(GetUpper()->getFramePrintArea());
void SwSectionFrame::DestroyImpl()
{ if( GetFormat() && !GetFormat()->GetDoc().IsInDtor() )
{
SwRootFrame *pRootFrame = getRootFrame(); if( pRootFrame )
pRootFrame->RemoveFromList( this ); if( IsFollow() )
{
SwSectionFrame *pMaster = FindMaster(); if( pMaster )
{
PROTOCOL( this, PROT::Section, DbgAction::DelFollow, pMaster )
pMaster->SetFollow( GetFollow() ); // A Master always grabs the space until the lower edge of his // Upper. If he doesn't have a Follow anymore, he can // release it, which is why the Size of the Master is // invalidated. if( !GetFollow() )
pMaster->InvalidateSize();
}
} #ifdefined DBG_UTIL elseif( HasFollow() )
{
PROTOCOL( this, PROT::Section, DbgAction::DelMaster, GetFollow() )
} #endif
}
// If we are destroyed immediately anyway, we don't need // to put us into the list if( bRemove )
{ // If we already were half dead before this DelEmpty, // we are likely in the list and have to remove us from // it if( !m_pSection && getRootFrame() )
getRootFrame()->RemoveFromList( this );
} elseif( getRootFrame() )
{
getRootFrame()->InsertEmptySct( this );
}
m_pSection = nullptr; // like this a reanimation is virtually impossible though
}
SwPageFrame *pPage = FindPageFrame();
InvalidatePage( pPage );
SwFrame *pFrame = GetNext();
SwFrame* pPrepFrame = nullptr; while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() )
pFrame = pFrame->GetNext(); if( pFrame )
{ // The former successor might have calculated a gap to the predecessor // which is now obsolete since he becomes the first
pFrame->InvalidatePrt_();
pFrame->InvalidatePos_(); if( pFrame->IsSctFrame() )
pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny(); if ( pFrame && pFrame->IsContentFrame() )
{
pFrame->InvalidatePage( pPage ); if( IsInFootnote() && !GetIndPrev() )
pPrepFrame = pFrame;
}
} else
{
InvalidateNextPos(); // Someone has to take over the retouching: predecessor or Upper
pFrame = GetPrev(); if ( nullptr != pFrame )
{
pFrame->SetRetouche();
pFrame->Prepare( PrepareHint::WidowsOrphans ); if ( pFrame->IsContentFrame() )
pFrame->InvalidatePage( pPage );
} // If I am (was) the only FlowFrame in my Upper, then he has to take over // the retouching. // Furthermore a blank page could have emerged else
{ SwRootFrame *pRoot = static_cast<SwRootFrame*>(pPage->GetUpper());
pRoot->SetSuperfluous();
GetUpper()->SetCompletePaint();
}
} // First remove, then shrink Upper
SwLayoutFrame *pUp = GetUpper(); if( bRemove )
{
RemoveFromLayout(); if( pUp && !pUp->Lower() && pUp->IsFootnoteFrame() && !pUp->IsColLocked() &&
pUp->GetUpper() )
{
pUp->Cut();
SwFrame::DestroyFrame(pUp);
pUp = nullptr;
}
} if( pPrepFrame )
pPrepFrame->Prepare( PrepareHint::FootnoteInvalidation ); if ( !pUp ) return;
void SwSectionFrame::Paste( SwFrame* pParent, SwFrame* pSibling )
{
OSL_ENSURE( pParent, "No parent for Paste()." );
OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." );
OSL_ENSURE( pParent != this, "I'm my own parent." );
OSL_ENSURE( pSibling != this, "I'm my own neighbour." );
OSL_ENSURE( !GetPrev() && !GetUpper(), "I am still registered somewhere." );
// Add to the tree
SwSectionFrame* pSect = pParent->FindSctFrame(); // Assure that parent is not inside a table frame, which is inside the found section frame. if ( pSect )
{
SwTabFrame* pTableFrame = pParent->FindTabFrame(); if ( pTableFrame &&
pSect->IsAnLower( pTableFrame ) )
{
pSect = nullptr;
}
}
SwRectFnSet aRectFnSet(pParent); if( pSect && HasToBreak( pSect ) )
{ if( pParent->IsColBodyFrame() ) // dealing with a single-column area
{ // If we are coincidentally at the end of a column, pSibling // has to point to the first frame of the next column in order // for the content of the next column to be moved correctly to the // newly created pSect by the InsertGroup
SwColumnFrame *pCol = static_cast<SwColumnFrame*>(pParent->GetUpper()); while( !pSibling && nullptr != ( pCol = static_cast<SwColumnFrame*>(pCol->GetNext()) ) )
pSibling = static_cast<SwLayoutFrame*>(pCol->Lower())->Lower(); if( pSibling )
{ // Even worse: every following column content has to // be attached to the pSibling-chain in order to be // taken along
SwFrame *pTmp = pSibling; while ( nullptr != ( pCol = static_cast<SwColumnFrame*>(pCol->GetNext()) ) )
{ while ( pTmp->GetNext() )
pTmp = pTmp->GetNext();
SwFrame* pSave = ::SaveContent( pCol ); if (pSave)
::RestoreContent( pSave, pSibling->GetUpper(), pTmp );
}
}
}
pParent = pSect;
pSect = new SwSectionFrame( *static_cast<SwSectionFrame*>(pParent)->GetSection(), pParent ); // if pParent is decomposed into two parts, its Follow has to be attached // to the new second part
pSect->SetFollow( static_cast<SwSectionFrame*>(pParent)->GetFollow() ); static_cast<SwSectionFrame*>(pParent)->SetFollow( nullptr ); if( pSect->GetFollow() )
pParent->InvalidateSize_();
if ( GetPrev() && !IsFollow() )
{
GetPrev()->InvalidateSize(); if ( GetPrev()->IsContentFrame() )
GetPrev()->InvalidatePage( pPage );
}
}
/** |* Here it's decided whether the this-SectionFrame should break up |* the passed (Section)frm (or not). |* Initially, all superior sections are broken up. Later on that could |* be made configurable.
|*/ bool SwSectionFrame::HasToBreak( const SwFrame* pFrame ) const
{ if( !pFrame->IsSctFrame() ) returnfalse;
/** |* Merges two SectionFrames, in case it's about the same section. |* This can be necessary when a (sub)section is deleted that had |* divided another part into two.
|*/ void SwSectionFrame::MergeNext( SwSectionFrame* pNxt )
{ if (pNxt->IsDeleteForbidden()) return;
if (pNxt->IsJoinLocked() || GetSection() != pNxt->GetSection()) return;
/** |* Divides a SectionFrame into two parts. The content of the second one |* starts after pFrameStartAfter; the created second section frame itself |* is put after pFramePutAfter. |* If pFrameStartAfter is nullptr, the split happens at the start. |* This is required when inserting an inner section, because the MoveFwd |* cannot have the desired effect within a frame or a table cell. |* Splitting at the start/end makes sense, because the empty frame would |* be removed after the InsertCnt_ finished.
|*/
SwSectionFrame* SwSectionFrame::SplitSect( SwFrame* pFrameStartAfter, SwFrame* pFramePutAfter )
{
assert(!pFrameStartAfter || IsAnLower(pFrameStartAfter));
SwFrame* pSav; if (pFrameStartAfter)
{
pSav = pFrameStartAfter->FindNext(); // If pFrameStartAfter is a complex object like table, and it has no next, // its FindNext may return its own last subframe. In this case, assume that // we are at the end. if (pSav && pFrameStartAfter->IsLayoutFrame()) if (static_cast<SwLayoutFrame*>(pFrameStartAfter)->IsAnLower(pSav))
pSav = nullptr;
} else
{
pSav = ContainsAny();
} if (pSav && !IsAnLower(pSav))
pSav = nullptr; // we are at the very end
// Put the content aside if (pSav)
pSav = ::SaveContent( this, pSav );
// Create a new SctFrame, not as a Follower/master if (!pFramePutAfter)
pFramePutAfter = this;
SwSectionFrame* pNew = new SwSectionFrame( *GetSection(), this );
pNew->InsertBehind( pFramePutAfter->GetUpper(), pFramePutAfter );
pNew->Init();
SwRectFnSet aRectFnSet(this);
aRectFnSet.MakePos( *pNew, nullptr, pFramePutAfter, true ); // OD 25.03.2003 #108339# - restore content: // determine layout frame for restoring content after the initialization // of the section frame. In the section initialization the columns are // created. if (pSav)
{
SwLayoutFrame* pLay = pNew; // Search for last layout frame, e.g. for columned sections.
SwFrame* pLower = pLay->Lower(); while( pLower && pLower->IsLayoutFrame() )
{
pLay = static_cast<SwLayoutFrame*>(pLower);
pLower = pLay->Lower();
}
::RestoreContent( pSav, pLay, nullptr );
}
InvalidateSize_(); if( HasFollow() )
{
pNew->SetFollow( GetFollow() );
SetFollow( nullptr );
} return pNew;
}
/** |* MoveContent is called for destroying a SectionFrames, due to |* the cancellation or hiding of a section, to handle the content. |* If the SectionFrame hasn't broken up another one, then the content |* is moved to the Upper. Otherwise the content is moved to another |* SectionFrame, which has to be potentially merged.
|*/ // If a multi-column section is cancelled, the ContentFrames have to be // invalidated staticvoid lcl_InvalidateInfFlags( SwFrame* pFrame, bool bInva )
{ while ( pFrame )
{
pFrame->InvalidateInfFlags(); if( bInva )
{
pFrame->InvalidatePos_();
pFrame->InvalidateSize_();
pFrame->InvalidatePrt_();
}
pFrame = pFrame->GetNext();
}
}
// Works like SwContentFrame::ImplGetNextContentFrame, but starts with a LayoutFrame static SwContentFrame* lcl_GetNextContentFrame( const SwLayoutFrame* pLay, bool bFwd )
{ if ( bFwd )
{ if ( pLay->GetNext() && pLay->GetNext()->IsContentFrame() ) returnconst_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pLay->GetNext()));
} else
{ if ( pLay->GetPrev() && pLay->GetPrev()->IsContentFrame() ) returnconst_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pLay->GetPrev()));
}
/// Checks if pFrame has a parent that can contain a split section frame. bool CanContainSplitSection(const SwFrame* pFrame)
{ if (!pFrame->IsInTab()) returntrue;
// The frame is in a table, see if the table is in a section. bool bRet = !pFrame->FindTabFrame()->IsInSct();
if (bRet)
{ // Don't try to split if the frame itself is a section frame with // multiple columns. if (pFrame->IsSctFrame())
{ const SwFrame* pLower = pFrame->GetLower(); if (pLower && pLower->IsColumnFrame())
bRet = false;
}
}
return bRet;
}
}
void SwSectionFrame::MoveContentAndDelete( SwSectionFrame* pDel, bool bSave )
{ bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrame();
SwFrame* pPrv = pDel->GetPrev();
SwLayoutFrame* pUp = pDel->GetUpper(); // OD 27.03.2003 #i12711# - initialize local pointer variables.
SwSectionFrame* pPrvSct = nullptr;
SwSectionFrame* pNxtSct = nullptr;
SwSectionFormat* pParent = static_cast<SwSectionFormat*>(pDel->GetFormat())->GetParent(); if( pDel->IsInTab() && pParent )
{
SwTabFrame *pTab = pDel->FindTabFrame(); // If we are within a table, we can only have broken up sections that // are inside as well, but not a section that contains the whole table. if( pTab->IsInSct() && pParent == pTab->FindSctFrame()->GetFormat() )
pParent = nullptr;
} // If our Format has a parent, we have probably broken up another // SectionFrame, which has to be checked. To do so we first acquire the // succeeding and the preceding ContentFrame, let's see if they // lay in the SectionFrames. // OD 27.03.2003 #i12711# - check, if previous and next section belonging // together and can be joined, *not* only if deleted section contains content. if ( pParent )
{
SwFrame* pPrvContent = lcl_GetNextContentFrame( pDel, false );
pPrvSct = pPrvContent ? pPrvContent->FindSctFrame() : nullptr;
SwFrame* pNxtContent = lcl_GetNextContentFrame( pDel, true );
pNxtSct = pNxtContent ? pNxtContent->FindSctFrame() : nullptr;
} else
{
pParent = nullptr;
pPrvSct = pNxtSct = nullptr;
}
// Now the content is put aside and the frame is destroyed
SwFrame *pSave = bSave ? ::SaveContent( pDel ) : nullptr; bool bOldFootnote = true; if( pSave && pUp->IsFootnoteFrame() )
{
bOldFootnote = static_cast<SwFootnoteFrame*>(pUp)->IsColLocked(); static_cast<SwFootnoteFrame*>(pUp)->ColLock();
}
pDel->DelEmpty( true );
SwFrame::DestroyFrame(pDel); if( pParent )
{ // Search for the appropriate insert position if( pNxtSct && pNxtSct->GetFormat() == pParent )
{ // Here we can insert ourselves at the beginning
pUp = FirstLeaf( pNxtSct );
pPrv = nullptr; if( pPrvSct && ( pPrvSct->GetFormat() != pParent ) )
pPrvSct = nullptr; // In order that nothing is merged
} elseif( pPrvSct && pPrvSct->GetFormat() == pParent )
{ // Wonderful, here we can insert ourselves at the end
pUp = pPrvSct;
SwFrame* pLower = pUp->Lower(); if( pLower && pLower->IsColumnFrame() )
{
pUp = static_cast<SwLayoutFrame*>(pUp->GetLastLower()); // The body of the last column
pUp = static_cast<SwLayoutFrame*>(pUp->Lower());
} // In order to perform the insertion after the last one
pPrv = pUp->GetLastLower();
pPrvSct = nullptr; // Such that nothing is merged
} else
{ if( pSave )
{ // Following situations: before and after the section-to-be // deleted there is the section boundary of the enclosing // section, or another (sibling) section connects subsequently, // that derives from the same Parent. // In that case, there's not (yet) a part of our parent available // that can store the content, so we create it here.
pPrvSct = new SwSectionFrame( *pParent->GetSection(), pUp );
pPrvSct->InsertBehind( pUp, pPrv );
pPrvSct->Init();
SwRectFnSet aRectFnSet(pUp);
aRectFnSet.MakePos( *pPrvSct, pUp, pPrv, true );
pUp = FirstLeaf( pPrvSct );
pPrv = nullptr;
}
pPrvSct = nullptr; // Such that nothing will be merged
}
} // The content is going to be inserted... if( pSave )
{
lcl_InvalidateInfFlags( pSave, bSize );
::RestoreContent( pSave, pUp, pPrv );
pUp->FindPageFrame()->InvalidateContent(); if( !bOldFootnote ) static_cast<SwFootnoteFrame*>(pUp)->ColUnlock();
} // Now two parts of the superior section could possibly be merged if( pPrvSct && !pPrvSct->IsJoinLocked() )
{
OSL_ENSURE( pNxtSct, "MoveContent: No Merge" );
pPrvSct->MergeNext( pNxtSct );
}
}
if (getFrameArea().Height() == 0)
{ // SwLayoutFrame::MakeAll() is not called for to-be-deleted // section frames (which would invalidate the position of the // next frame via the SwLayNotify dtor), so call it manually. if (SwFrame* pNext = GetNext())
pNext->InvalidatePos();
}
}
if (!GetPrev() && !IsFollow() && IsInDocBody() && IsHiddenNow())
{ // This may be the first frame on a page, and it may had moved to that page because its // content required that (a page break in the first paragraph, or a tall first line, or // "do not break paragraph" setting, or the like). Try to move back, to allow following // frames to move back, if possible. Sections cannot move back; workaround by a call to // GetPrevSctLeaf(), which may return a candidate upper frame on a previous page, or it // may create a new master for this at the end of the previous page. Cut and paste this // appropriately; then drop the temporary, if needed. if (SwLayoutFrame* moveBackPos = GetPrevSctLeaf())
{ if (moveBackPos->IsColBodyFrame())
{
moveBackPos = moveBackPos->GetUpper()->GetUpper();
}
SwLayoutFrame* newUpper = moveBackPos;
SwFrame* newSibling = nullptr; constbool temporaryMasterCreated = IsFollow(); if (temporaryMasterCreated)
{
assert(moveBackPos == &GetPrecede()->GetFrame());
newUpper = moveBackPos->GetUpper();
newSibling = moveBackPos->GetNext(); // actually, will be also nullptr
} if (newUpper != GetUpper())
{ // Can't use MoveSubTree, because the move needs to fire events to re-layout
Cut();
Paste(newUpper, newSibling);
} if (temporaryMasterCreated)
{
moveBackPos->Cut();
DestroyFrame(moveBackPos);
}
assert(!IsFollow());
}
}
LockJoin(); // I don't let myself to be destroyed on the way
if (GetFollow() && IsHiddenNow())
{ // Merge all the follows of this hidden section while (auto* follow = GetFollow())
{
MergeNext(follow); if (GetFollow() == follow) // failed to merge break; // avoid endless loop
}
}
// OD 2004-03-15 #116561# - In online layout join the follows, if section // can grow. const SwViewShell *pSh = getRootFrame()->GetCurrShell();
// Split sections inside table cells: need to merge all follows of the // section here, as later we won't attempt doing so. bool bCanContainSplitSection = false; if (IsInTab() && GetUpper())
bCanContainSplitSection = CanContainSplitSection(GetUpper());
// A section with Follow uses all the space until the lower edge of the // Upper. If it moves, its size can grow or decrease... if( !isFrameAreaPositionValid() && ToMaximize( false ) )
{
setFrameAreaSizeValid(false);
}
if (IsInTab())
{ // In case the section is in a table, then calculate the lower right // now. Just setting the valid size flag of the lower to false may not // be enough, as lcl_RecalcRow() can call // SwFrame::ValidateThisAndAllLowers(), and then we don't attempt // calculating the proper position of the lower.
SwFrame* pLower = Lower(); if (pLower && !pLower->isFrameAreaPositionValid())
pLower->Calc(pRenderContext);
}
/** * CollectEndnotes looks for endnotes in the sectionfrm and his follows, * the endnotes will cut off the layout and put into the array. * If the first endnote is not a master-SwFootnoteFrame, the whole sectionfrm * contains only endnotes and it is not necessary to collect them.
*/ static SwFootnoteFrame* lcl_FindEndnote( SwSectionFrame* &rpSect, bool &rbEmpty,
SwLayouter *pLayouter )
{ // if rEmpty is set, the rpSect is already searched
SwSectionFrame* pSect = rbEmpty ? rpSect->GetFollow() : rpSect; while( pSect )
{
SwFrame* pLower = pSect->Lower();
OSL_ENSURE( (pLower && pLower->IsColumnFrame()) || pSect->GetUpper()->IsFootnoteFrame(), "InsertEndnotes: Where's my column?" );
void SwSectionFrame::CollectEndnotes( SwLayouter* pLayouter )
{
OSL_ENSURE( IsColLocked(), "CollectEndnotes: You love the risk?" ); // i73332: Section in footnode does not have columns!
SwFrame* pLower = Lower();
OSL_ENSURE( (pLower && pLower->IsColumnFrame()) || GetUpper()->IsFootnoteFrame(), "Where's my column?" );
SwSectionFrame* pSect = this;
SwFootnoteFrame* pFootnote; bool bEmpty = false; // pSect is the last sectionfrm without endnotes or the this-pointer // the first sectionfrm with endnotes may be destroyed, when the endnotes // is cutted while( nullptr != (pFootnote = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
pLayouter->CollectEndnote( pFootnote ); if( pLayouter->HasEndnotes() )
lcl_ColumnRefresh( this, true );
}
/** Fits the size to the surroundings. |* |* Those that have a Follow or foot notes, have to extend until |* the lower edge of a upper (bMaximize) |* They must not extend above the Upper, as the case may be one can |* try to grow its upper (bGrow) |* If the size had to be changed, the content is calculated. |* |* @note: perform calculation of content, only if height has changed (OD 18.09.2002 #100522#)
|*/ void SwSectionFrame::CheckClipping( bool bGrow, bool bMaximize )
{
SwRectFnSet aRectFnSet(this);
tools::Long nDiff;
SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper()); if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrame() ||
!FindFlyFrame()->IsLocked() ) )
{
nDiff = -aRectFnSet.BottomDist( getFrameArea(), nDeadLine ); if( !bMaximize )
nDiff += Undersize(); if( nDiff > 0 )
{
tools::Long nAdd = GetUpper()->Grow( nDiff ); if( aRectFnSet.IsVert() )
nDeadLine -= nAdd; else
nDeadLine += nAdd;
}
}
nDiff = -aRectFnSet.BottomDist( getFrameArea(), nDeadLine );
SetUndersized( !bMaximize && nDiff >= 0 ); constbool bCalc = ( IsUndersized() || bMaximize ) &&
( nDiff ||
aRectFnSet.GetTop(getFramePrintArea()) > aRectFnSet.GetHeight(getFrameArea()) ); // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate // that a calculation has to be done beside the value of <bCalc>. bool bExtraCalc = false; if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFootnote() )
{
SwSectionFrame *pSect = this; bool bEmpty = false;
SwLayoutFrame* pFootnote = IsEndnAtEnd() ?
lcl_FindEndnote( pSect, bEmpty, nullptr ) : nullptr; if( pFootnote )
{
pFootnote = pFootnote->FindFootnoteBossFrame();
SwFrame* pTmp = FindLastContent( SwFindMode::LastCnt ); // OD 08.11.2002 #104840# - use <SwLayoutFrame::IsBefore(..)> if ( pTmp && pFootnote->IsBefore( pTmp->FindFootnoteBossFrame() ) )
bExtraCalc = true;
} elseif( GetFollow() && !GetFollow()->ContainsAny() )
bExtraCalc = true;
} if ( !(bCalc || bExtraCalc) ) return;
// OD 18.09.2002 #100522# // Determine, if height has changed. // Note: In vertical layout the height equals the width value. bool bHeightChanged = aRectFnSet.IsVert() ?
(aOldSz.Width() != getFramePrintArea().Width()) :
(aOldSz.Height() != getFramePrintArea().Height()); // Last but not least we have changed the height again, thus the inner // layout (columns) is calculated and the content as well. // OD 18.09.2002 #100522# // calculate content, only if height has changed. // OD 03.11.2003 #i19737# - restriction of content calculation too strong. // If an endnote has an incorrect position or a follow section contains // no content except footnotes/endnotes, the content has also been calculated. if ( !(( bHeightChanged || bExtraCalc ) && Lower()) ) return;
void SwSectionFrame::SimpleFormat()
{ if ( IsJoinLocked() || IsColLocked() ) return;
LockJoin();
SwRectFnSet aRectFnSet(this); if( GetPrev() || GetUpper() )
{ // assure notifications on position changes. const SwLayNotify aNotify( this );
aRectFnSet.MakePos( *this, GetUpper(), GetPrev(), false );
setFrameAreaPositionValid(true);
}
SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper()); // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in // order to get calculated lowers, not only if there space left in its upper. if (aRectFnSet.BottomDist(getFrameArea(), nDeadLine) >= 0)
{
{
SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
aRectFnSet.SetBottom( aFrm, nDeadLine );
}
// #i40147# - helper class to perform extra section format // to position anchored objects and to keep the position of whose objects locked. class ExtraFormatToPositionObjs
{ private:
SwSectionFrame* mpSectFrame; bool mbExtraFormatPerformed;
aRectFnSet.SetYMargins( *mpSectFrame, nTopMargin, 0 ); // #i59789# // suppress formatting, if printing area of section is too narrow if ( aRectFnSet.GetHeight(mpSectFrame->getFramePrintArea()) <= 0 )
{ return;
}
mpSectFrame->ChgLowersProp( aOldSectPrtSize );
// format column frames and its body and footnote container
SwColumnFrame* pColFrame = static_cast<SwColumnFrame*>(mpSectFrame->Lower()); while ( pColFrame )
{
pColFrame->Calc(pRenderContext); if (SwFrame* pColLower = pColFrame->Lower())
{
pColLower->Calc(pRenderContext); if ( pColLower->GetNext() )
{
pColLower->GetNext()->Calc(pRenderContext);
}
}
// unlock position of lower floating screen objects for the extra format // #i81555# // Section frame can already have changed the page and its content // can still be on the former page. // Thus, initialize objects via lower-relationship
InitObjs( *mpSectFrame );
// format content - first with collecting its foot-/endnotes before content // format, second without collecting its foot-/endnotes.
::CalcContent( mpSectFrame );
::CalcContent( mpSectFrame, true );
// keep locked position of lower floating screen objects
SwPageFrame* pPageFrame = mpSectFrame->FindPageFrame();
SwSortedObjs* pObjs = pPageFrame ? pPageFrame->GetSortedObjs() : nullptr; if ( pObjs )
{ for (SwAnchoredObject* pAnchoredObj : *pObjs)
{ if ( mpSectFrame->IsAnLower( pAnchoredObj->GetAnchorFrame() ) )
{
pAnchoredObj->SetKeepPosLocked( true );
}
}
}
mbExtraFormatPerformed = true;
}
};
}
/// "formats" the frame; Frame and PrtArea void SwSectionFrame::Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttr )
{ if( !m_pSection ) // via DelEmpty
{ #ifdef DBG_UTIL
OSL_ENSURE( getRootFrame()->IsInDelList( this ), "SectionFrame without Section" ); #endif
setFrameAreaPositionValid(true);
setFrameAreaSizeValid(true);
setFramePrintAreaValid(true); return;
}
// The size is only determined by the content, if the SectFrame does not have a // Follow. Otherwise it fills (occupies) the Upper down to the lower edge. // It is not responsible for the text flow, but the content is. bool bMaximize = ToMaximize( false );
// OD 2004-05-17 #i28701# - If the wrapping style has to be considered // on object positioning, an extra formatting has to be performed // to determine the correct positions the floating screen objects. // #i40147# // use new helper class <ExtraFormatToPositionObjs>. // This class additionally keep the locked position of the objects // and releases this position lock keeping on destruction.
ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this ); if ( !bMaximize &&
GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
!GetFormat()->GetBalancedColumns().GetValue() )
{
aExtraFormatToPosObjs.FormatSectionToPositionObjs();
}
// Column widths have to be adjusted before calling CheckClipping. // CheckClipping can cause the formatting of the lower frames // which still have a width of 0. constbool bHasColumns = Lower() && Lower()->IsColumnFrame(); if ( bHasColumns && Lower()->GetNext() )
AdjustColumns( nullptr, false );
// OD 15.10.2002 #103517# - allow grow in online layout // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling // method <CheckClipping(..)>. const SwViewShell *pSh = getRootFrame()->GetCurrShell();
CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
bMaximize = ToMaximize( false );
setFrameAreaSizeValid(true);
}
// Check the width of the columns and adjust if necessary if ( bHasColumns && ! Lower()->GetNext() && bMaximize ) static_cast<SwColumnFrame*>(Lower())->Lower()->Calc(pRenderContext);
if ( !bMaximize )
{
SwTwips nRemaining = aRectFnSet.GetTopMargin(*this);
SwFrame *pFrame = m_pLower; if( pFrame )
{ if( pFrame->IsColumnFrame() && pFrame->GetNext() )
{ // #i61435# // suppress formatting, if upper frame has height <= 0 if ( aRectFnSet.GetHeight(GetUpper()->getFrameArea()) > 0 )
{
FormatWidthCols( *pAttr, nRemaining, MINLAY );
} // #126020# - adjust check for empty section // #130797# - correct fix #126020# while( HasFollow() && !GetFollow()->ContainsContent() &&
!GetFollow()->ContainsAny( true ) )
{
SwFrame* pOld = GetFollow();
GetFollow()->DelEmpty( false ); if( pOld == GetFollow() ) break;
}
bMaximize = ToMaximize( false );
nRemaining += aRectFnSet.GetHeight(pFrame->getFrameArea());
} else
{ if( pFrame->IsColumnFrame() )
{
pFrame->Calc(pRenderContext);
pFrame = static_cast<SwColumnFrame*>(pFrame)->Lower();
pFrame->Calc(pRenderContext);
pFrame = static_cast<SwLayoutFrame*>(pFrame)->Lower();
CalcFootnoteContent();
} // If we are in a columned frame which calls a CalcContent // in the FormatWidthCols, the content might need calculating if( pFrame && !pFrame->isFrameAreaDefinitionValid() && IsInFly() &&
FindFlyFrame()->IsColLocked() )
::CalcContent( this );
nRemaining += InnerHeight();
bMaximize = HasFollow();
}
}
if (m_pLower && (!m_pLower->IsColumnFrame() || !m_pLower->GetNext()))
{ // If a single-column section just created the space that // was requested by the "undersized" paragraphs, then they // have to be invalidated and calculated, so they fully cover it
pFrame = m_pLower; if( pFrame->IsColumnFrame() )
{
pFrame->InvalidateSize_();
pFrame->InvalidatePos_();
pFrame->Calc(pRenderContext);
pFrame = static_cast<SwColumnFrame*>(pFrame)->Lower();
pFrame->Calc(pRenderContext);
pFrame = static_cast<SwLayoutFrame*>(pFrame)->Lower();
CalcFootnoteContent();
} bool bUnderSz = false; while( pFrame )
{ if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
{
pFrame->Prepare( PrepareHint::AdjustSizeWithoutFormatting );
bUnderSz = true;
}
pFrame = pFrame->GetNext();
} if( bUnderSz && !IsContentLocked() )
::CalcContent( this );
}
}
}
// Do not exceed the lower edge of the Upper. // Do not extend below the lower edge with Sections with Follows if ( GetUpper() )
CheckClipping( true, bMaximize ); if( !bOldLock )
ColUnlock();
tools::Long nDiff = nOldHeight - aRectFnSet.GetHeight(getFrameArea());
if( nDiff > 0 )
{ if( !GetNext() )
SetRetouche(); // Take over the retouching ourselves if( GetUpper() && !GetUpper()->IsFooterFrame() )
GetUpper()->Shrink( nDiff );
}
/// Returns the next layout sheet where the frame can be moved in. /// New pages are created only if specified by the parameter.
SwLayoutFrame *SwFrame::GetNextSctLeaf( MakePageType eMakePage )
{ // Attention: Nested sections are currently not supported
// Shortcuts for "columned" sections, if we're not in the last column // Can we slide to the next column of the section? if( IsColBodyFrame() && GetUpper()->GetNext() ) returnstatic_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(GetUpper()->GetNext())->Lower()); if( GetUpper()->IsColBodyFrame() && GetUpper()->GetUpper()->GetNext() ) returnstatic_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(GetUpper()->GetUpper()->GetNext())->Lower()); // Inside a table-in-section, or sections of headers/footers, there can be only // one column shift be made, one of the above shortcuts should have applied! if( !CanContainSplitSection(GetUpper()) || FindFooterOrHeader() ) return nullptr;
// Always end up in the same section: Body again inside Body etc. constbool bBody = IsInDocBody(); constbool bFootnotePage = FindPageFrame()->IsFootnotePage();
// The "pLayLeaf is in a table" case is rejected by default, so that it // can't happen that we try to move a table to one of its own cells. bool bLayLeafTableAllowed = false;
SwLayoutFrame *pLayLeaf;
SwLayoutFrame* pCellLeaf = nullptr; if (GetUpper()->IsInTab())
{ if (IsTabFrame())
{ return nullptr; // table in section in table: split disabled for now
} // We are *in* a table (not an outermost SwTabFrame), see if there // is a follow cell frame created already.
pCellLeaf = GetNextCellLeaf(); if (!pCellLeaf)
{
SAL_WARN("sw.layout", "section is in table, but the table is not split"); return nullptr;
}
}
// A shortcut for TabFrames such that not all cells need to be visited if( bWrongPage )
pLayLeaf = nullptr; elseif( IsTabFrame() )
{
SwFrame *const pTmpCnt = static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : nullptr;
} elseif (pCellLeaf && CanContainSplitSection(this))
{ // This frame is in a table-not-in-section, its follow should be // inserted under the follow of the frame's cell.
pLayLeaf = pCellLeaf; if (pLayLeaf->FindTabFrame() == FindTabFrame())
SAL_WARN("sw.layout", "my table frame and my follow's table frame is the same"); // In this case pLayLeaf pointing to an in-table frame is OK.
bLayLeafTableAllowed = true;
} else
{
pLayLeaf = GetNextLayoutLeaf(); if( IsColumnFrame() )
{ while( pLayLeaf && static_cast<SwColumnFrame*>(this)->IsAnLower( pLayLeaf ) )
pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
}
}
SwLayoutFrame *pOldLayLeaf = nullptr; // Such that in case of newly // created pages, the search is
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.28 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.