summaryrefslogtreecommitdiffstats
path: root/sw/source/core/layout/tabfrm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout/tabfrm.cxx')
-rw-r--r--sw/source/core/layout/tabfrm.cxx165
1 files changed, 144 insertions, 21 deletions
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index c1acc0c9e9..f757824561 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -286,12 +286,12 @@ static void lcl_InvalidateLowerObjs( SwLayoutFrame& _rLayoutFrame,
// that anchored object is correctly positioned.
pAnchoredObj->ClearCharRectAndTopOfLine();
pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
- if ( pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
- == RndStdIds::FLY_AS_CHAR )
+ const SwFrameFormat* pObjFormat = pAnchoredObj->GetFrameFormat();
+ if (pObjFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
{
pAnchoredObj->AnchorFrame()
->Prepare( PrepareHint::FlyFrameAttributesChanged,
- &(pAnchoredObj->GetFrameFormat()) );
+ pObjFormat );
}
if ( pFly != nullptr )
{
@@ -1451,7 +1451,102 @@ namespace
return true;
}
-}
+
+ auto IsAllHiddenSection(SwSectionFrame const& rSection) -> bool
+ {
+ for (SwFrame const* pFrame = rSection.Lower(); pFrame; pFrame = pFrame->GetNext())
+ {
+ if (pFrame->IsColumnFrame())
+ {
+ return false; // adds some padding
+ }
+ else if (pFrame->IsSctFrame())
+ {
+ assert(false); // these aren't nested?
+ if (!IsAllHiddenSection(*static_cast<SwSectionFrame const*>(pFrame)))
+ {
+ return false;
+ }
+ }
+ else if (pFrame->IsTabFrame())
+ {
+ return false; // presumably
+ }
+ else if (pFrame->IsTextFrame())
+ {
+ if (!static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ auto IsAllHiddenRow(SwRowFrame const& rRow, SwTabFrame const& rTab) -> bool;
+
+ auto IsAllHiddenCell(SwCellFrame const& rCell, SwRowFrame const& rRow, SwTabFrame const& rTab) -> bool
+ {
+ for (SwFrame const* pFrame = rCell.Lower(); pFrame; pFrame = pFrame->GetNext())
+ {
+ if (pFrame->IsRowFrame())
+ {
+ if (!IsAllHiddenRow(*static_cast<SwRowFrame const*>(pFrame), rTab))
+ {
+ return false;
+ }
+ }
+ else if (pFrame->IsSctFrame())
+ {
+ if (!IsAllHiddenSection(*static_cast<SwSectionFrame const*>(pFrame)))
+ {
+ return false;
+ }
+ }
+ else if (pFrame->IsTabFrame())
+ {
+ return false; // presumably
+ }
+ else if (pFrame->IsTextFrame())
+ {
+ if (!static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
+ {
+ return false;
+ }
+ }
+ }
+ if (rTab.IsCollapsingBorders() && !rCell.Lower()->IsRowFrame())
+ {
+ if (rRow.GetTopMarginForLowers() != 0
+ || rRow.GetBottomMarginForLowers() != 0)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ SwBorderAttrAccess border(SwFrame::GetCache(), &rCell);
+ if (border.Get()->CalcTop() != 0 || border.Get()->CalcBottom() != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ auto IsAllHiddenRow(SwRowFrame const& rRow, SwTabFrame const& rTab) -> bool
+ {
+ for (SwFrame const* pCell = rRow.Lower(); pCell; pCell = pCell->GetNext())
+ {
+ if (!IsAllHiddenCell(*static_cast<SwCellFrame const*>(pCell), rRow, rTab))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+} // namespace
void SwTabFrame::Join()
{
@@ -1471,11 +1566,20 @@ void SwTabFrame::Join()
SwFrame* pPrv = GetLastLower();
SwTwips nHeight = 0; //Total height of the inserted rows as return value.
+ bool isAllHidden(true);
while ( pRow )
{
pNxt = pRow->GetNext();
nHeight += aRectFnSet.GetHeight(pRow->getFrameArea());
+ if (nHeight != 0)
+ {
+ isAllHidden = false;
+ }
+ if (isAllHidden)
+ {
+ isAllHidden = IsAllHiddenRow(*static_cast<SwRowFrame *>(pRow), *this);
+ }
pRow->RemoveFromLayout();
pRow->InvalidateAll_();
pRow->InsertBehind( this, pPrv );
@@ -1489,6 +1593,18 @@ void SwTabFrame::Join()
SwFrame::DestroyFrame(pFoll);
Grow( nHeight );
+
+ // In case the row does not have a height, Grow(nHeight) did nothing.
+ // If this is not invalidated, subsequent follows may never be joined.
+ // Try to guess if the height of the row will be 0. If the document
+ // was just loaded, it will be 0 in any case, but probably it's not a good
+ // idea to join *all* follows for a newly loaded document, it would be
+ // easier not to split the table in the first place; presumably it is split
+ // because that improves performance.
+ if (isAllHidden)
+ {
+ InvalidateSize_();
+ }
}
static void SwInvalidatePositions( SwFrame *pFrame, tools::Long nBottom )
@@ -3180,6 +3296,7 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
bool bShiftDown = css::text::WrapTextMode_NONE == nSurround;
bool bSplitFly = pFly->IsFlySplitAllowed();
+ const SwRect aFlyRectWithoutSpaces = pFly->GetObjRect();
if (!bShiftDown && bAddVerticalFlyOffsets)
{
if (nSurround == text::WrapTextMode_PARALLEL && isHoriOrientShiftDown)
@@ -3194,7 +3311,6 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
// Ignore spacing when determining the left/right edge of the fly, like
// Word does.
- const SwRect aFlyRectWithoutSpaces = pFly->GetObjRect();
basegfx::B1DRange aFlyRange(aRectFnSet.GetLeft(aFlyRectWithoutSpaces),
aRectFnSet.GetRight(aFlyRectWithoutSpaces));
@@ -3257,9 +3373,16 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
bool bFlyHoriOrientLeft = text::HoriOrientation::LEFT == rHori.GetHoriOrient();
if (bSplitFly && !bFlyHoriOrientLeft)
{
- // If a split fly is oriented "from left", we already checked if it has enough space on
- // the right, so from-left and left means the same here.
- bFlyHoriOrientLeft = rHori.GetHoriOrient() == text::HoriOrientation::NONE;
+ // Only shift to the right if we don't have enough space on the left.
+ SwTwips nTabWidth = getFramePrintArea().Width();
+ SwTwips nWidthDeadline = aFlyRectWithoutSpaces.Left()
+ - pFly->GetAnchorFrame()->GetUpper()->getFrameArea().Left();
+ if (nTabWidth > nWidthDeadline)
+ {
+ // If a split fly is oriented "from left", we already checked if it has enough space on
+ // the right, so from-left and left means the same here.
+ bFlyHoriOrientLeft = rHori.GetHoriOrient() == text::HoriOrientation::NONE;
+ }
}
if ((css::text::WrapTextMode_RIGHT == nSurround
|| css::text::WrapTextMode_PARALLEL == nSurround)
@@ -4447,8 +4570,8 @@ tools::Long CalcHeightWithFlys( const SwFrame *pFrame )
{
// OD 30.09.2003 #i18732# - only objects, which follow
// the text flow have to be considered.
- const SwFrameFormat& rFrameFormat = pAnchoredObj->GetFrameFormat();
- bool bFollowTextFlow = rFrameFormat.GetFollowTextFlow().GetValue();
+ const SwFrameFormat* pFrameFormat = pAnchoredObj->GetFrameFormat();
+ bool bFollowTextFlow = pFrameFormat->GetFollowTextFlow().GetValue();
bool bIsFarAway = pAnchoredObj->GetObjRect().Top() != FAR_AWAY;
const SwPageFrame* pPageFrm = pTmp->FindPageFrame();
bool bIsAnchoredToTmpFrm = false;
@@ -4456,14 +4579,14 @@ tools::Long CalcHeightWithFlys( const SwFrame *pFrame )
bIsAnchoredToTmpFrm = pAnchoredObj->GetPageFrame() == pPageFrm ||
(pPageFrm->GetFormatPage().GetPhyPageNum() == pAnchoredObj->GetPageFrame()->GetFormatPage().GetPhyPageNum() + 1);
const bool bConsiderObj =
- (rFrameFormat.GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) &&
+ (pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) &&
bIsFarAway &&
bFollowTextFlow && bIsAnchoredToTmpFrm;
- bool bWrapThrough = rFrameFormat.GetSurround().GetValue() == text::WrapTextMode_THROUGH;
- bool bInBackground = !rFrameFormat.GetOpaque().GetValue();
+ bool bWrapThrough = pFrameFormat->GetSurround().GetValue() == text::WrapTextMode_THROUGH;
+ bool bInBackground = !pFrameFormat->GetOpaque().GetValue();
// Legacy render requires in-background setting, the new mode does not.
bool bConsiderFollowTextFlow = bInBackground
- || !rFrameFormat.getIDocumentSettingAccess().get(
+ || !pFrameFormat->getIDocumentSettingAccess().get(
DocumentSettingId::USE_FORMER_TEXT_WRAPPING);
if (pFrame->IsInTab() && bFollowTextFlow && bWrapThrough && bConsiderFollowTextFlow)
{
@@ -4475,7 +4598,7 @@ tools::Long CalcHeightWithFlys( const SwFrame *pFrame )
if ( bConsiderObj )
{
- const SwFormatFrameSize &rSz = rFrameFormat.GetFrameSize();
+ const SwFormatFrameSize &rSz = pFrameFormat->GetFrameSize();
if( !rSz.GetHeightPercent() )
{
const SwTwips nDistOfFlyBottomToAnchorTop =
@@ -5428,7 +5551,7 @@ static bool lcl_ArrangeLowers( SwLayoutFrame *pLay, tools::Long lYStart, bool bI
// from its anchor frame.
bool bVertPosDepOnAnchor( true );
{
- SwFormatVertOrient aVert( pAnchoredObj->GetFrameFormat().GetVertOrient() );
+ SwFormatVertOrient aVert( pAnchoredObj->GetFrameFormat()->GetVertOrient() );
switch ( aVert.GetRelationOrient() )
{
case text::RelOrientation::PAGE_FRAME:
@@ -5528,7 +5651,7 @@ static bool lcl_ArrangeLowers( SwLayoutFrame *pLay, tools::Long lYStart, bool bI
if ( pTabFrame &&
!( pTabFrame->IsFollow() &&
pTabFrame->FindMaster()->IsRebuildLastLine() ) &&
- (pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
+ (pAnchoredObj->GetFrameFormat()->GetAnchor().GetAnchorId()
!= RndStdIds::FLY_AS_CHAR))
{
SwPageFrame* pPageFrame = pAnchoredObj->GetPageFrame();
@@ -5546,7 +5669,7 @@ static bool lcl_ArrangeLowers( SwLayoutFrame *pLay, tools::Long lYStart, bool bI
// #i52904# - re-introduce direct move
// of drawing objects
const bool bDirectMove =
- static_cast<const SwDrawFrameFormat&>(pAnchoredObj->GetFrameFormat()).IsPosAttrSet() &&
+ static_cast<const SwDrawFrameFormat*>(pAnchoredObj->GetFrameFormat())->IsPosAttrSet() &&
bVertPosDepOnAnchor &&
!pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
if ( bDirectMove )
@@ -5804,8 +5927,8 @@ void SwCellFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorder
const SwFrame* pAnch = pAnchoredObj->GetAnchorFrame();
if ( (bConsiderWrapOnObjPos && IsAnLower( pAnch )) || (!bConsiderWrapOnObjPos && aTmp.Overlaps( aRect )) )
{
- const SwFrameFormat& rAnchoredObjFrameFormat = pAnchoredObj->GetFrameFormat();
- const SwFormatSurround &rSur = rAnchoredObjFrameFormat.GetSurround();
+ const SwFrameFormat* pAnchoredObjFrameFormat = pAnchoredObj->GetFrameFormat();
+ const SwFormatSurround &rSur = pAnchoredObjFrameFormat->GetSurround();
if ( bConsiderWrapOnObjPos || css::text::WrapTextMode_THROUGH != rSur.GetSurround() )
{
@@ -5825,7 +5948,7 @@ void SwCellFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorder
if ( bConsiderWrapOnObjPos ||
!IsAnLower( pAnch ) ||
pAnchoredObj->IsTmpConsiderWrapInfluence() ||
- !rAnchoredObjFrameFormat.GetFollowTextFlow().GetValue() )
+ !pAnchoredObjFrameFormat->GetFollowTextFlow().GetValue() )
{
bVertDir = false;
break;