diff options
Diffstat (limited to 'sw/source/core/layout/tabfrm.cxx')
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 165 |
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; |