diff options
author | Zolnai Tamás <tamas.zolnai@collabora.com> | 2014-03-05 22:15:09 +0100 |
---|---|---|
committer | Zolnai Tamás <tamas.zolnai@collabora.com> | 2014-03-05 22:15:09 +0100 |
commit | cb19042f4395c97d123a27c6960d5e30d666c010 (patch) | |
tree | cd14733e3eef222d07175108615df079dcced458 /sw | |
parent | 80d1a46e0f3b57f1bbaf7bc4c8aac81195ea8f4d (diff) |
New feature: vertical alignment for text frames: Layout part
- Introduce a new attribute (content position) for fly frames. Content
position specify the top-left corner of the content area (where
frame content can be placed). Add methods and members for invalidation.
- Extract content's height calculation from SwFlyFrm::Format()
to a funtction so we can use this inside SwFlyFrm::MakeContentPos.
Change-Id: I64abb70afb652ad5c11aa69b5ba12a85210e215b
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/core/inc/flyfrm.hxx | 13 | ||||
-rw-r--r-- | sw/source/core/inc/frame.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/layout/calcmove.cxx | 15 | ||||
-rw-r--r-- | sw/source/core/layout/fly.cxx | 181 | ||||
-rw-r--r-- | sw/source/core/layout/flylay.cxx | 8 |
5 files changed, 161 insertions, 58 deletions
diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx index 234e94d5dae3..a666a9da1df3 100644 --- a/sw/source/core/inc/flyfrm.hxx +++ b/sw/source/core/inc/flyfrm.hxx @@ -118,8 +118,12 @@ protected: friend class SwNoTxtFrm; // is allowed to call NotifyBackground + Point m_aContentPos; // content area's position relatively to Frm + bool m_bValidContentPos; + virtual void Format( const SwBorderAttrs *pAttrs = 0 ); void MakePrtArea( const SwBorderAttrs &rAttrs ); + void MakeContentPos( const SwBorderAttrs &rAttrs ); void Lock() { bLocked = sal_True; } void Unlock() { bLocked = sal_False; } @@ -147,6 +151,8 @@ protected: virtual const IDocumentDrawModelAccess* getIDocumentDrawModelAccess( ); + SwTwips CalcContentHeight(const SwBorderAttrs *pAttrs, const SwTwips nMinHeight, const SwTwips nUL); + public: // #i26791# TYPEINFO(); @@ -279,6 +285,13 @@ public: virtual SwFlyFrmFmt *GetFmt(); virtual void dumpAsXml( xmlTextWriterPtr writer ) { SwLayoutFrm::dumpAsXml( writer ); }; + + virtual void Calc() const; + + const Point& ContentPos() const { return m_aContentPos; } + Point& ContentPos() { return m_aContentPos; } + + void InvalidateContentPos(); }; #endif diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index c78614ab2c5e..73b32f8d7747 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -682,7 +682,7 @@ public: inline SwLayoutFrm *GetPrevLayoutLeaf(); inline SwLayoutFrm *GetNextLayoutLeaf(); - inline void Calc() const; // here might be "formatted" + virtual void Calc() const; // here might be "formatted" inline void OptCalc() const; // here we assume (for optimization) that // the predecessors are already formatted diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx index b8e9b12ca2c4..88be7b681d74 100644 --- a/sw/source/core/layout/calcmove.cxx +++ b/sw/source/core/layout/calcmove.cxx @@ -25,6 +25,7 @@ #include "fmtftn.hxx" #include <editeng/ulspitem.hxx> #include <editeng/keepitem.hxx> +#include <svx/sdtaitm.hxx> #include <fmtfsize.hxx> #include <fmtanchr.hxx> @@ -581,7 +582,11 @@ void SwFrm::MakePos() else { maFrm.Pos( GetUpper()->Frm().Pos() ); - maFrm.Pos() += GetUpper()->Prt().Pos(); + if( GetUpper()->IsFlyFrm() ) + maFrm.Pos() += static_cast<SwFlyFrm*>(GetUpper())->ContentPos(); + else + maFrm.Pos() += GetUpper()->Prt().Pos(); + if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() ) { if( bVert ) @@ -1335,6 +1340,14 @@ void SwCntntFrm::MakeAll() if ( nConsequetiveFormatsWithoutChange <= cnStopFormat ) { Format(); + + // When a lower of a vertically aligned fly frame changes it's size we need to recalculate content pos. + if( GetUpper() && GetUpper()->IsFlyFrm() && + GetUpper()->GetFmt()->GetTextVertAdjust().GetValue() != SDRTEXTVERTADJUST_TOP ) + { + static_cast<SwFlyFrm*>(GetUpper())->InvalidateContentPos(); + GetUpper()->SetCompletePaint(); + } } #if OSL_DEBUG_LEVEL > 0 else diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index df97a354ff3e..5d0aede3b8a5 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -72,7 +72,8 @@ SwFlyFrm::SwFlyFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) : bLayout( sal_False ), bAutoPosition( sal_False ), bNoShrink( sal_False ), - bLockDeleteContent( sal_False ) + bLockDeleteContent( sal_False ), + m_bValidContentPos( false ) { mnType = FRMC_FLY; @@ -931,6 +932,13 @@ void SwFlyFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew, } break; + case RES_TEXT_VERT_ADJUST: + { + InvalidateContentPos(); + rInvFlags |= 0x10; + } + break; + case RES_BOX: case RES_SHADOW: rInvFlags |= 0x17; @@ -1232,7 +1240,7 @@ void SwFlyFrm::Format( const SwBorderAttrs *pAttrs ) const SwTwips nUL = pAttrs->CalcTopLine() + pAttrs->CalcBottomLine(); const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine(); const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize(); - Size aRelSize( CalcRel( rFrmSz ) ); + Size aRelSize( CalcRel( rFrmSz ) ); OSL_ENSURE( pAttrs->GetSize().Height() != 0 || rFrmSz.GetHeightPercent(), "FrameAttr height is 0." ); OSL_ENSURE( pAttrs->GetSize().Width() != 0 || rFrmSz.GetWidthPercent(), "FrameAttr width is 0." ); @@ -1240,62 +1248,11 @@ void SwFlyFrm::Format( const SwBorderAttrs *pAttrs ) SWRECTFN( this ) if( !HasFixSize() ) { - SwTwips nRemaining = 0; - long nMinHeight = 0; if( IsMinHeight() ) nMinHeight = bVert ? aRelSize.Width() : aRelSize.Height(); - if ( Lower() ) - { - if ( Lower()->IsColumnFrm() ) - { - FormatWidthCols( *pAttrs, nUL, nMinHeight ); - nRemaining = (Lower()->Frm().*fnRect->fnGetHeight)(); - } - else - { - SwFrm *pFrm = Lower(); - while ( pFrm ) - { - nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)(); - if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() ) - // This TxtFrm would like to be a bit larger - nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight() - - (pFrm->Prt().*fnRect->fnGetHeight)(); - else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() ) - nRemaining += ((SwSectionFrm*)pFrm)->Undersize(); - pFrm = pFrm->GetNext(); - } - } - if ( GetDrawObjs() ) - { - sal_uInt32 nCnt = GetDrawObjs()->Count(); - SwTwips nTop = (Frm().*fnRect->fnGetTop)(); - SwTwips nBorder = (Frm().*fnRect->fnGetHeight)() - - (Prt().*fnRect->fnGetHeight)(); - for ( sal_uInt16 i = 0; i < nCnt; ++i ) - { - SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i]; - if ( pAnchoredObj->ISA(SwFlyFrm) ) - { - SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj); - // OD 06.11.2003 #i22305# - consider - // only Writer fly frames, which follow the text flow. - if ( pFly->IsFlyLayFrm() && - pFly->Frm().Top() != FAR_AWAY && - pFly->GetFmt()->GetFollowTextFlow().GetValue() ) - { - SwTwips nDist = -(pFly->Frm().*fnRect-> - fnBottomDist)( nTop ); - if( nDist > nBorder + nRemaining ) - nRemaining = nDist - nBorder; - } - } - } - } - } - + SwTwips nRemaining = CalcContentHeight(pAttrs, nMinHeight, nUL); if( IsMinHeight() && (nRemaining + nUL) < nMinHeight ) nRemaining = nMinHeight - nUL; // Because the Grow/Shrink of the Flys does not directly @@ -1304,8 +1261,10 @@ void SwFlyFrm::Format( const SwBorderAttrs *pAttrs ) // Notification is running along already. // As we already got a lot of zeros per attribute, we block them // from now on. + if ( nRemaining < MINFLY ) nRemaining = MINFLY; + (Prt().*fnRect->fnSetHeight)( nRemaining ); nRemaining -= (Frm().*fnRect->fnGetHeight)(); (Frm().*fnRect->fnAddBottom)( nRemaining + nUL ); @@ -1715,7 +1674,6 @@ void SwFlyFrm::MakeObjPos() void SwFlyFrm::MakePrtArea( const SwBorderAttrs &rAttrs ) { - if ( !mbValidPrtArea ) { mbValidPrtArea = sal_True; @@ -1729,6 +1687,55 @@ void SwFlyFrm::MakePrtArea( const SwBorderAttrs &rAttrs ) } } +void SwFlyFrm::MakeContentPos( const SwBorderAttrs &rAttrs ) +{ + if ( !m_bValidContentPos ) + { + m_bValidContentPos = true; + + const SwTwips nUL = rAttrs.CalcTopLine() + rAttrs.CalcBottomLine(); + Size aRelSize( CalcRel( GetFmt()->GetFrmSize() ) ); + + SWRECTFN( this ) + long nMinHeight = 0; + if( IsMinHeight() ) + nMinHeight = bVert ? aRelSize.Width() : aRelSize.Height(); + + Point aNewContentPos; + aNewContentPos = Prt().Pos(); + const SdrTextVertAdjust nAdjust = GetFmt()->GetTextVertAdjust().GetValue(); + if( nAdjust != SDRTEXTVERTADJUST_TOP ) + { + SwTwips nDiff = (Prt().*fnRect->fnGetHeight)() - CalcContentHeight(&rAttrs, nMinHeight, nUL); + if( nDiff > 0 ) + { + if( nAdjust == SDRTEXTVERTADJUST_CENTER ) + { + aNewContentPos.setY(aNewContentPos.getY() + nDiff/2); + } + else if( nAdjust == SDRTEXTVERTADJUST_BOTTOM ) + { + aNewContentPos.setY(aNewContentPos.getY() + nDiff); + } + } + } + if( aNewContentPos != ContentPos() ) + { + ContentPos() = aNewContentPos; + for( SwFrm *pFrm = Lower(); pFrm; pFrm = pFrm->GetNext()) + { + pFrm->InvalidatePos(); + } + } + } +} + +void SwFlyFrm::InvalidateContentPos() +{ + m_bValidContentPos = false; + _Invalidate(); +} + SwTwips SwFlyFrm::_Grow( SwTwips nDist, sal_Bool bTst ) { SWRECTFN( this ) @@ -2613,4 +2620,68 @@ SwFlyFrmFmt * SwFlyFrm::GetFmt() return static_cast< SwFlyFrmFmt * >( GetDep() ); } +void SwFlyFrm::Calc() const +{ + if ( !m_bValidContentPos ) + ((SwFlyFrm*)this)->PrepareMake(); + else + SwLayoutFrm::Calc(); +} + +SwTwips SwFlyFrm::CalcContentHeight(const SwBorderAttrs *pAttrs, const SwTwips nMinHeight, const SwTwips nUL) +{ + SWRECTFN( this ) + SwTwips nHeight = 0; + if ( Lower() ) + { + if ( Lower()->IsColumnFrm() ) + { + FormatWidthCols( *pAttrs, nUL, nMinHeight ); + nHeight = (Lower()->Frm().*fnRect->fnGetHeight)(); + } + else + { + SwFrm *pFrm = Lower(); + while ( pFrm ) + { + nHeight += (pFrm->Frm().*fnRect->fnGetHeight)(); + if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() ) + // This TxtFrm would like to be a bit larger + nHeight += ((SwTxtFrm*)pFrm)->GetParHeight() + - (pFrm->Prt().*fnRect->fnGetHeight)(); + else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() ) + nHeight += ((SwSectionFrm*)pFrm)->Undersize(); + pFrm = pFrm->GetNext(); + } + } + if ( GetDrawObjs() ) + { + sal_uInt32 nCnt = GetDrawObjs()->Count(); + SwTwips nTop = (Frm().*fnRect->fnGetTop)(); + SwTwips nBorder = (Frm().*fnRect->fnGetHeight)() - + (Prt().*fnRect->fnGetHeight)(); + for ( sal_uInt16 i = 0; i < nCnt; ++i ) + { + SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i]; + if ( pAnchoredObj->ISA(SwFlyFrm) ) + { + SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj); + // OD 06.11.2003 #i22305# - consider + // only Writer fly frames, which follow the text flow. + if ( pFly->IsFlyLayFrm() && + pFly->Frm().Top() != FAR_AWAY && + pFly->GetFmt()->GetFollowTextFlow().GetValue() ) + { + SwTwips nDist = -(pFly->Frm().*fnRect-> + fnBottomDist)( nTop ); + if( nDist > nBorder + nHeight ) + nHeight = nDist - nBorder; + } + } + } + } + } + return nHeight; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index ce7e0e94a1e1..554f3a4f590d 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -140,7 +140,7 @@ void SwFlyFreeFrm::MakeAll() sal_uInt16 nLoopControlRuns = 0; const sal_uInt16 nLoopControlMax = 10; - while ( !mbValidPos || !mbValidSize || !mbValidPrtArea || bFormatHeightOnly ) + while ( !mbValidPos || !mbValidSize || !mbValidPrtArea || bFormatHeightOnly || !m_bValidContentPos ) { SWRECTFN( this ) const SwFmtFrmSize *pSz; @@ -157,7 +157,10 @@ void SwFlyFreeFrm::MakeAll() } if ( !mbValidPrtArea ) + { MakePrtArea( rAttrs ); + m_bValidContentPos = false; + } if ( !mbValidSize || bFormatHeightOnly ) { @@ -185,6 +188,9 @@ void SwFlyFreeFrm::MakeAll() else mbValidSize = sal_False; } + + if ( !m_bValidContentPos ) + MakeContentPos( rAttrs ); } if ( mbValidPos && mbValidSize ) |