diff options
Diffstat (limited to 'sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx')
-rw-r--r-- | sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx | 1073 |
1 files changed, 1073 insertions, 0 deletions
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx new file mode 100644 index 000000000000..209ceb3c20e0 --- /dev/null +++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx @@ -0,0 +1,1073 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <tocntntanchoredobjectposition.hxx> +#include <anchoredobject.hxx> +#include <frame.hxx> +#include <txtfrm.hxx> +#include <pagefrm.hxx> +#include <sectfrm.hxx> +// --> OD 2004-10-15 #i26945# +#include <tabfrm.hxx> +// <-- +#include <frmfmt.hxx> +#include <IDocumentSettingAccess.hxx> +#include <fmtsrnd.hxx> +#include <fmtfsize.hxx> +#include <fmtanchr.hxx> +#include <fmtornt.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <svx/svdobj.hxx> +#include <pam.hxx> +#include <environmentofanchoredobject.hxx> +#include <frmtool.hxx> +#include <ndtxt.hxx> +#include <dflyobj.hxx> + +using namespace objectpositioning; +using namespace ::com::sun::star; + + +SwToCntntAnchoredObjectPosition::SwToCntntAnchoredObjectPosition( SdrObject& _rDrawObj ) + : SwAnchoredObjectPosition ( _rDrawObj ), + mpVertPosOrientFrm( 0 ), + // --> OD 2004-06-17 #i26791# + maOffsetToFrmAnchorPos( Point() ), + mbAnchorToChar ( false ), + mpToCharOrientFrm( 0 ), + mpToCharRect( 0 ), + // OD 12.11.2003 #i22341# + mnToCharTopOfLine( 0 ) +{} + +SwToCntntAnchoredObjectPosition::~SwToCntntAnchoredObjectPosition() +{} + +bool SwToCntntAnchoredObjectPosition::IsAnchoredToChar() const +{ + return mbAnchorToChar; +} + +const SwFrm* SwToCntntAnchoredObjectPosition::ToCharOrientFrm() const +{ + return mpToCharOrientFrm; +} + +const SwRect* SwToCntntAnchoredObjectPosition::ToCharRect() const +{ + return mpToCharRect; +} + +// OD 12.11.2003 #i22341# +SwTwips SwToCntntAnchoredObjectPosition::ToCharTopOfLine() const +{ + return mnToCharTopOfLine; +} + +SwTxtFrm& SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() const +{ + ASSERT( GetAnchorFrm().ISA(SwTxtFrm), + "SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" ); + + return static_cast<SwTxtFrm&>(GetAnchorFrm()); +} + +// --> OD 2004-07-20 #i23512# +bool lcl_DoesVertPosFits( const SwTwips _nRelPosY, + const SwTwips _nAvail, + const SwLayoutFrm* _pUpperOfOrientFrm, + const bool _bBrowse, + const bool _bGrowInTable, + SwLayoutFrm*& _orpLayoutFrmToGrow ) +{ + bool bVertPosFits = false; + + if ( _nRelPosY <= _nAvail ) + { + bVertPosFits = true; + } + else if ( _bBrowse ) + { + if ( _pUpperOfOrientFrm->IsInSct() ) + { + SwSectionFrm* pSctFrm = + const_cast<SwSectionFrm*>(_pUpperOfOrientFrm->FindSctFrm()); + bVertPosFits = pSctFrm->GetUpper()->Grow( _nRelPosY - _nAvail, TRUE ) > 0; + // Note: do not provide a layout frame for a grow. + } + else + { + bVertPosFits = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)-> + Grow( _nRelPosY - _nAvail, TRUE ) > 0; + if ( bVertPosFits ) + _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm); + } + } + else if ( _pUpperOfOrientFrm->IsInTab() && _bGrowInTable ) + { + // --> OD 2005-06-08 #i45085# - check, if upper frame would grow the + // excepted amount of twips. + const SwTwips nTwipsGrown = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)-> + Grow( _nRelPosY - _nAvail, TRUE ) > 0; + bVertPosFits = ( nTwipsGrown == ( _nRelPosY - _nAvail ) ); + // <-- + if ( bVertPosFits ) + _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm); + } + + return bVertPosFits; +} +// <-- + +void SwToCntntAnchoredObjectPosition::CalcPosition() +{ + // get format of object + const SwFrmFmt& rFrmFmt = GetFrmFmt(); + + // declare and set <pFooter> to footer frame, if object is anchored + // at a frame belonging to the footer. + const SwFrm* pFooter = GetAnchorFrm().FindFooterOrHeader(); + if ( pFooter && !pFooter->IsFooterFrm() ) + pFooter = NULL; + + // declare and set <bBrowse> to true, if document is in browser mode and + // object is anchored at the body, but not at frame belonging to a table. + const bool bBrowse = GetAnchorFrm().IsInDocBody() && + !GetAnchorFrm().IsInTab() + ? rFrmFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) + : false; + + // determine left/right and its upper/lower spacing. + const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace(); + const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace(); + + // determine, if object has no surrounding. + const SwFmtSurround& rSurround = rFrmFmt.GetSurround(); + const bool bNoSurround = rSurround.GetSurround() == SURROUND_NONE; + const bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT; + + // OD 29.10.2003 #110978# - new class <SwEnvironmentOfAnchoredObject> + SwEnvironmentOfAnchoredObject aEnvOfObj( DoesObjFollowsTextFlow() ); + + // OD 30.09.2003 #i18732# - grow only, if object has to follow the text flow + const bool bGrow = DoesObjFollowsTextFlow() && + ( !GetAnchorFrm().IsInTab() || + !rFrmFmt.GetFrmSize().GetHeightPercent() ); + + // get text frame the object is anchored at + const SwTxtFrm& rAnchorTxtFrm = GetAnchorTxtFrm(); + SWRECTFN( (&rAnchorTxtFrm) ) + + const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() ); + + // local variable keeping the calculated relative position; initialized with + // current relative position. + // OD 2004-03-24 #i26791# - use new object instance of <SwAnchoredObject> + Point aRelPos( GetAnchoredObj().GetCurrRelPos() ); + + SwTwips nRelDiff = 0; + + bool bMoveable = rAnchorTxtFrm.IsMoveable(); + + // determine frame the object position has to be oriented at. + const SwTxtFrm* pOrientFrm = &rAnchorTxtFrm; + const SwTxtFrm* pAnchorFrmForVertPos = &rAnchorTxtFrm; + { + // if object is at-character anchored, determine character-rectangle + // and frame, position has to be oriented at. + mbAnchorToChar = (FLY_AT_CHAR == rFrmFmt.GetAnchor().GetAnchorId()); + if ( mbAnchorToChar ) + { + const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor(); + // OD 2004-03-24 #i26791# - use new object instance of <SwAnchoredObject> + // OD 2005-01-12 - Due to table break algorithm the character + // rectangle can have no height. Thus, check also the width + if ( ( !GetAnchoredObj().GetLastCharRect().Height() && + !GetAnchoredObj().GetLastCharRect().Width() ) || + !GetAnchoredObj().GetLastTopOfLine() ) + { + // --> OD 2010-07-02 #i111886# + // Check existence of paragraph portion information in order + // to avoid formatting which could cause deletion of follow frames. + GetAnchoredObj().CheckCharRectAndTopOfLine(); + // <-- + // OD 2005-01-12 - Due to table break algorithm the character + // rectangle can have no height. Thus, check also the width + if ( ( !GetAnchoredObj().GetLastCharRect().Height() && + !GetAnchoredObj().GetLastCharRect().Width() ) || + !GetAnchoredObj().GetLastTopOfLine() ) + { + // --> OD 2005-01-12 - get default for <mpVertPosOrientFrm>, + // if it's not set. + if ( !mpVertPosOrientFrm ) + { + mpVertPosOrientFrm = rAnchorTxtFrm.GetUpper(); + } + // <-- + return; + } + } + mpToCharRect = &(GetAnchoredObj().GetLastCharRect()); + // OD 12.11.2003 #i22341# - get top of line, in which the anchor + // character is. + mnToCharTopOfLine = GetAnchoredObj().GetLastTopOfLine(); + pOrientFrm = &(const_cast<SwTxtFrm&>(rAnchorTxtFrm).GetFrmAtOfst( + rAnch.GetCntntAnchor()->nContent.GetIndex() ) ); + mpToCharOrientFrm = pOrientFrm; + } + } + SWREFRESHFN( pOrientFrm ) + + // determine vertical position + { + + // determine vertical positioning and alignment attributes + SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() ); + + // OD 22.09.2003 #i18732# - determine layout frame for vertical + // positions aligned to 'page areas'. + const SwLayoutFrm& rPageAlignLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( *pOrientFrm ); + + if ( aVert.GetVertOrient() != text::VertOrientation::NONE ) + { + // OD 22.09.2003 #i18732# - adjustments for follow text flow or not + // AND vertical alignment at 'page areas'. + SwTwips nAlignAreaHeight; + SwTwips nAlignAreaOffset; + _GetVertAlignmentValues( *pOrientFrm, rPageAlignLayFrm, + aVert.GetRelationOrient(), + nAlignAreaHeight, nAlignAreaOffset ); + + // determine relative vertical position + SwTwips nRelPosY = nAlignAreaOffset; + SwTwips nObjHeight = (aObjBoundRect.*fnRect->fnGetHeight)(); + SwTwips nUpperSpace = bVert ? rLR.GetRight() : rUL.GetUpper(); + SwTwips nLowerSpace = bVert ? rLR.GetLeft() : rUL.GetLower(); + switch ( aVert.GetVertOrient() ) + { + case text::VertOrientation::CHAR_BOTTOM: + { + if ( mbAnchorToChar ) + { + // bottom (to character anchored) + nRelPosY += nAlignAreaHeight + nUpperSpace; + if ( bVert ) + nRelPosY += nObjHeight; + break; + } + } + // no break here + case text::VertOrientation::TOP: + { + // OD 12.11.2003 #i22341# - special case for vertical + // alignment at top of line + if ( mbAnchorToChar && + aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) + { + nRelPosY -= (nObjHeight + nLowerSpace); + } + else + { + nRelPosY += nUpperSpace; + } + } + break; + // OD 14.11.2003 #i22341# + case text::VertOrientation::LINE_TOP: + { + if ( mbAnchorToChar && + aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) + { + nRelPosY -= (nObjHeight + nLowerSpace); + } + else + { + ASSERT( false, + "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." ); + } + } + break; + case text::VertOrientation::CENTER: + { + nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2); + } + break; + // OD 14.11.2003 #i22341# + case text::VertOrientation::LINE_CENTER: + { + if ( mbAnchorToChar && + aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) + { + nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2); + } + else + { + ASSERT( false, + "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." ); + } + } + break; + case text::VertOrientation::BOTTOM: + { + if ( ( aVert.GetRelationOrient() == text::RelOrientation::FRAME || + aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) && + bNoSurround ) + { + // bottom (aligned to 'paragraph areas') + nRelPosY += nAlignAreaHeight + nUpperSpace; + } + else + { + // OD 12.11.2003 #i22341# - special case for vertical + // alignment at top of line + if ( mbAnchorToChar && + aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) + { + nRelPosY += nUpperSpace; + } + else + { + nRelPosY += nAlignAreaHeight - + ( nObjHeight + nLowerSpace ); + } + } + } + break; + // OD 14.11.2003 #i22341# + case text::VertOrientation::LINE_BOTTOM: + { + if ( mbAnchorToChar && + aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) + { + nRelPosY += nUpperSpace; + } + else + { + ASSERT( false, + "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." ); + } + } + break; + default: + break; + } + + // adjust relative position by distance between anchor frame and + // the frame, the object is oriented at. + // OD 2004-05-21 #i28701# - correction: adjust relative position, + // only if the floating screen object has to follow the text flow. + if ( DoesObjFollowsTextFlow() && pOrientFrm != &rAnchorTxtFrm ) + { + // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos> + // to get top of frame for object positioning. + const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrm, fnRect, bVert ); + nRelPosY += (*fnRect->fnYDiff)( nTopOfOrient, + _GetTopForObjPos( rAnchorTxtFrm, fnRect, bVert ) ); + } + + // --> OD 2005-02-07 #i42124# - capture object inside vertical + // layout environment. + { + const SwTwips nTopOfAnch = + _GetTopForObjPos( *pOrientFrm, fnRect, bVert ); + const SwLayoutFrm& rVertEnvironLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( + *(pOrientFrm->GetUpper()) ); + const bool bCheckBottom = !DoesObjFollowsTextFlow(); + nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, + rVertEnvironLayFrm, nRelPosY, + DoesObjFollowsTextFlow(), + bCheckBottom ); + } + // <-- + // keep calculated relative vertical position - needed for filters + // (including the xml-filter) + { + // determine position + SwTwips nAttrRelPosY = nRelPosY - nAlignAreaOffset; + // set + if ( nAttrRelPosY != aVert.GetPos() ) + { + aVert.SetPos( nAttrRelPosY ); + const_cast<SwFrmFmt&>(rFrmFmt).LockModify(); + const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert ); + const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify(); + } + } + + // determine absolute 'vertical' position, depending on layout-direction + // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame + // anchor position, depending on layout-direction + if ( bVert ) + { + aRelPos.X() = nRelPosY; + maOffsetToFrmAnchorPos.X() = nAlignAreaOffset; + } + else + { + aRelPos.Y() = nRelPosY; + maOffsetToFrmAnchorPos.Y() = nAlignAreaOffset; + } + } + + // OD 29.10.2003 #110978# - determine upper of frame vertical position + // is oriented at. + // OD 2004-05-21 #i28701# - determine 'virtual' anchor frame. + // This frame is used in the following instead of the 'real' anchor + // frame <rAnchorTxtFrm> for the 'vertical' position in all cases. + const SwLayoutFrm* pUpperOfOrientFrm = 0L; + { + // OD 2004-05-21 #i28701# - As long as the anchor frame is on the + // same page as <pOrientFrm> and the vertical position isn't aligned + // automatic at the anchor character or the top of the line of the + // anchor character, the anchor frame determines the vertical position. + if ( &rAnchorTxtFrm == pOrientFrm || + ( rAnchorTxtFrm.FindPageFrm() == pOrientFrm->FindPageFrm() && + aVert.GetVertOrient() == text::VertOrientation::NONE && + aVert.GetRelationOrient() != text::RelOrientation::CHAR && + aVert.GetRelationOrient() != text::RelOrientation::TEXT_LINE ) ) + { + pUpperOfOrientFrm = rAnchorTxtFrm.GetUpper(); + pAnchorFrmForVertPos = &rAnchorTxtFrm; + } + else + { + pUpperOfOrientFrm = pOrientFrm->GetUpper(); + pAnchorFrmForVertPos = pOrientFrm; + } + } + + // ignore one-column sections. + // --> OD 2004-07-20 #i23512# - correction: also ignore one-columned + // sections with footnotes/endnotes + if ( pUpperOfOrientFrm->IsInSct() ) + { + const SwSectionFrm* pSctFrm = pUpperOfOrientFrm->FindSctFrm(); + const bool bIgnoreSection = pUpperOfOrientFrm->IsSctFrm() || + ( pSctFrm->Lower()->IsColumnFrm() && + !pSctFrm->Lower()->GetNext() ); + if ( bIgnoreSection ) + pUpperOfOrientFrm = pSctFrm->GetUpper(); + } + + if ( aVert.GetVertOrient() == text::VertOrientation::NONE ) + { + // local variable <nRelPosY> for calculation of relative vertical + // distance to anchor. + SwTwips nRelPosY = 0; + // --> OD 2004-06-17 #i26791# - local variable <nVertOffsetToFrmAnchorPos> + // for determination of the 'vertical' offset to the frame anchor + // position + SwTwips nVertOffsetToFrmAnchorPos( 0L ); + // OD 12.11.2003 #i22341# - add special case for vertical alignment + // at top of line. + if ( mbAnchorToChar && + ( aVert.GetRelationOrient() == text::RelOrientation::CHAR || + aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) ) + { + // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos> + // to get top of frame for object positioning. + SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrm, fnRect, bVert ); + if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR ) + { + nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)( + (ToCharRect()->*fnRect->fnGetBottom)(), + nTopOfOrient ); + } + else + { + nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)( ToCharTopOfLine(), + nTopOfOrient ); + } + nRelPosY = nVertOffsetToFrmAnchorPos - aVert.GetPos(); + } + else + { + // OD 2004-05-21 #i28701# - correction: use <pAnchorFrmForVertPos> + // instead of <pOrientFrm> and do not adjust relative position + // to get correct vertical position. + nVertOffsetToFrmAnchorPos = 0L; + // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos> + // to get top of frame for object positioning. + const SwTwips nTopOfOrient = + _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert ); + // OD 02.10.2002 #102646# - increase <nRelPosY> by margin height, + // if position is vertical aligned to "paragraph text area" + if ( aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) + { + // OD 2004-03-11 #i11860# - consider upper space amount + // of previous frame + SwTwips nTopMargin = (pAnchorFrmForVertPos->*fnRect->fnGetTopMargin)(); + if ( pAnchorFrmForVertPos->IsTxtFrm() ) + { + nTopMargin -= static_cast<const SwTxtFrm*>(pAnchorFrmForVertPos)-> + GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid(); + } + nVertOffsetToFrmAnchorPos += nTopMargin; + } + // OD 22.09.2003 #i18732# - adjust <nRelPosY> by difference + // between 'page area' and 'anchor' frame, if position is + // vertical aligned to 'page areas' + else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ) + { + nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)( + (rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(), + nTopOfOrient ); + } + else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) + { + SwRect aPgPrtRect( rPageAlignLayFrm.Frm() ); + if ( rPageAlignLayFrm.IsPageFrm() ) + { + aPgPrtRect = + static_cast<const SwPageFrm&>(rPageAlignLayFrm).PrtWithoutHeaderAndFooter(); + } + nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)( + (aPgPrtRect.*fnRect->fnGetTop)(), + nTopOfOrient ); + } + nRelPosY = nVertOffsetToFrmAnchorPos + aVert.GetPos(); + } + + // <pUpperOfOrientFrm>: layout frame, at which the position has to + // is oriented at + // <nRelPosY>: rest of the relative distance in the current + // layout frame + // <nAvail>: space, which is available in the current + // layout frame + + // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' + // frame anchor position, depending on layout-direction + if ( bVert ) + maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos; + else + maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos; + // <-- + // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos> + // to get top of frame for object positioning. + const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert ); + if( nRelPosY <= 0 ) + { + // OD 08.09.2003 #110354# - allow negative position, but keep it + // inside environment layout frame. + const SwLayoutFrm& rVertEnvironLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm ); + // --> OD 2004-07-22 #i31805# - do not check, if bottom of + // anchored object would fit into environment layout frame, if + // anchored object has to follow the text flow. + const bool bCheckBottom = !DoesObjFollowsTextFlow(); + nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, + rVertEnvironLayFrm, nRelPosY, + DoesObjFollowsTextFlow(), + bCheckBottom ); + // <-- + if ( bVert ) + aRelPos.X() = nRelPosY; + else + aRelPos.Y() = nRelPosY; + } + else + { + SWREFRESHFN( pAnchorFrmForVertPos ) + SwTwips nAvail = + (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(), + nTopOfAnch ); + const bool bInFtn = pAnchorFrmForVertPos->IsInFtn(); + while ( nRelPosY ) + { + // --> OD 2004-07-20 #i23512# - correction: + // consider section frame for grow in online layout. + // use new local method <lcl_DoesVertPosFits(..)> + SwLayoutFrm* pLayoutFrmToGrow = 0L; + const bool bDoesVertPosFits = lcl_DoesVertPosFits( + nRelPosY, nAvail, pUpperOfOrientFrm, bBrowse, + bGrow, pLayoutFrmToGrow ); + + if ( bDoesVertPosFits ) + { + SwTwips nTmpRelPosY = + (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(), + nTopOfAnch ) - + nAvail + nRelPosY; + // --> OD 2004-07-06 #i28701# - adjust calculated + // relative vertical position to object's environment. + const SwFrm& rVertEnvironLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm ); + // --> OD 2004-08-20 - do not check, if bottom of + // anchored object would fit into environment layout + // frame, if anchored object has to follow the text flow. + const bool bCheckBottom = !DoesObjFollowsTextFlow(); + nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, + rVertEnvironLayFrm, + nTmpRelPosY, + DoesObjFollowsTextFlow(), + bCheckBottom ); + // <-- + if ( bVert ) + aRelPos.X() = nTmpRelPosY; + else + aRelPos.Y() = nTmpRelPosY; + + // --> OD 2004-07-20 #i23512# - use local variable + // <pLayoutFrmToGrow> provided by new method + // <lcl_DoesVertPosFits(..)>. + if ( pLayoutFrmToGrow ) + { + pLayoutFrmToGrow->Grow( nRelPosY - nAvail ); + } + // <-- + nRelPosY = 0; + } + else + { + // --> OD 2004-10-04 #i26495# - floating screen objects, + // which are anchored inside a table, doesn't follow + // the text flow. + if ( DoesObjFollowsTextFlow() && + !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME || + aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) && + !GetAnchorFrm().IsInTab() ) + // <-- + { + if ( bMoveable ) + { + // follow the text flow + nRelPosY -= nAvail; + MakePageType eMakePage = bInFtn ? MAKEPAGE_NONE + : MAKEPAGE_APPEND; + const bool bInSct = pUpperOfOrientFrm->IsInSct(); + if( bInSct ) + eMakePage = MAKEPAGE_NOSECTION; + + const SwLayoutFrm* pTmp = + pUpperOfOrientFrm->GetLeaf( eMakePage, TRUE, &rAnchorTxtFrm ); + if ( pTmp && + ( !bInSct || + pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pTmp->FindSctFrm() ) ) ) + { + pUpperOfOrientFrm = pTmp; + bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm ); + SWREFRESHFN( pUpperOfOrientFrm ) + nAvail = (pUpperOfOrientFrm->Prt().*fnRect->fnGetHeight)(); + } + else + { + // if there isn't enough space in the (colmuned) + // section, leave it and set available space <nAvail> + // to the space below the section. + // if the new available space isn't also enough, + // new pages can be created. + if( bInSct ) + { + const SwFrm* pSct = pUpperOfOrientFrm->FindSctFrm(); + pUpperOfOrientFrm = pSct->GetUpper(); + nAvail = (*fnRect->fnYDiff)( + (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(), + (pSct->*fnRect->fnGetPrtBottom)() ); + } + else + { +#if OSL_DEBUG_LEVEL > 1 + ASSERT( false, "<SwToCntntAnchoredObjectPosition::CalcPosition()> - code under investigation by OD, please inform OD about this assertion!" ); +#endif + nRelDiff = nRelPosY; + nRelPosY = 0; + } + } + } + else + { + nRelPosY = 0; + } + } + else + { + // OD 06.10.2003 #i18732# - do not follow text flow respectively + // align at 'page areas', but stay inside given environment + const SwFrm& rVertEnvironLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm ); + nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, + rVertEnvironLayFrm, + nRelPosY, + DoesObjFollowsTextFlow() ); + if( bVert ) + aRelPos.X() = nRelPosY; + else + aRelPos.Y() = nRelPosY; + nRelPosY = 0; + } + } + } // end of <while ( nRelPosY )> + } // end of else <nRelPosY <= 0> + } // end of <aVert.GetVertOrient() == text::VertOrientation::NONE> + + //Damit das Teil ggf. auf die richtige Seite gestellt und in die + //PrtArea des LayLeaf gezogen werden kann, muss hier seine + //absolute Position berechnet werden. + const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert ); + if( bVert ) + { + GetAnchoredObj().SetObjLeft( nTopOfAnch - + ( aRelPos.X() - nRelDiff ) - + aObjBoundRect.Width() ); + } + else + { + GetAnchoredObj().SetObjTop( nTopOfAnch + + ( aRelPos.Y() - nRelDiff ) ); + } + + // grow environment under certain conditions + // ignore one-column sections. + // --> OD 2004-07-20 #i23512# - correction: also ignore one-columned + // sections with footnotes/endnotes + if ( pUpperOfOrientFrm->IsInSct() ) + { + const SwSectionFrm* pSctFrm = pUpperOfOrientFrm->FindSctFrm(); + const bool bIgnoreSection = pUpperOfOrientFrm->IsSctFrm() || + ( pSctFrm->Lower()->IsColumnFrm() && + !pSctFrm->Lower()->GetNext() ); + if ( bIgnoreSection ) + pUpperOfOrientFrm = pSctFrm->GetUpper(); + } + SwTwips nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() ); + if( nDist < 0 ) + { + // --> OD 2004-07-20 #i23512# - correction: + // consider section frame for grow in online layout and + // consider page alignment for grow in table. + SwLayoutFrm* pLayoutFrmToGrow = 0L; + if ( bBrowse && rAnchorTxtFrm.IsMoveable() ) + { + if ( pUpperOfOrientFrm->IsInSct() ) + { + pLayoutFrmToGrow = const_cast<SwLayoutFrm*>( + pUpperOfOrientFrm->FindSctFrm()->GetUpper()); + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pLayoutFrmToGrow->*fnRect->fnGetPrtBottom)() ); + if ( nDist >= 0 ) + { + pLayoutFrmToGrow = 0L; + } + } + else + { + pLayoutFrmToGrow = + const_cast<SwLayoutFrm*>(pUpperOfOrientFrm); + } + } + else if ( rAnchorTxtFrm.IsInTab() && bGrow ) + { + pLayoutFrmToGrow = const_cast<SwLayoutFrm*>(pUpperOfOrientFrm); + } + if ( pLayoutFrmToGrow ) + { + pLayoutFrmToGrow->Grow( -nDist ); + } + // <-- + } + + if ( DoesObjFollowsTextFlow() && + !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME || + aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) ) + { + + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() ); + // --> OD 2004-10-04 #i26945# - floating screen objects, which are + // anchored inside a table, doesn't follow the text flow. But, they + // have to stay inside its layout environment. + if ( nDist < 0 && pOrientFrm->IsInTab() ) + { + // If the anchor frame is the first content of the table cell + // and has no follow, the table frame is notified, + // that the object doesn't fit into the table cell. + // Adjustment of position isn't needed in this case. + if ( pOrientFrm == &rAnchorTxtFrm && + !pOrientFrm->GetFollow() && + !pOrientFrm->GetIndPrev() ) + { + const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm()) + ->SetDoesObjsFit( FALSE ); + } + else + { + SwTwips nTmpRelPosY( 0L ); + if ( bVert ) + nTmpRelPosY = aRelPos.X() - nDist; + else + nTmpRelPosY = aRelPos.Y() + nDist; + const SwLayoutFrm& rVertEnvironLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm ); + nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, + rVertEnvironLayFrm, + nTmpRelPosY, + DoesObjFollowsTextFlow(), + false ); + if ( bVert ) + { + aRelPos.X() = nTmpRelPosY; + GetAnchoredObj().SetObjLeft( nTopOfAnch - + aRelPos.X() - + aObjBoundRect.Width() ); + } + else + { + aRelPos.Y() = nTmpRelPosY; + GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() ); + } + // If the anchor frame is the first content of the table cell + // and the object still doesn't fit, the table frame is notified, + // that the object doesn't fit into the table cell. + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() ); + if ( nDist < 0 && + pOrientFrm == &rAnchorTxtFrm && !pOrientFrm->GetIndPrev() ) + { + const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm()) + ->SetDoesObjsFit( FALSE ); + } + } + } + else + { + // <-- + // follow text flow + const bool bInFtn = rAnchorTxtFrm.IsInFtn(); + while( bMoveable && nDist < 0 ) + { + bool bInSct = pUpperOfOrientFrm->IsInSct(); + if ( bInSct ) + { + const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper(); + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pTmp->*fnRect->fnGetPrtBottom)() ); + // --> OD 2004-11-01 #i23129# - Try to flow into next + // section|section column. Thus, do *not* leave section + // area, if anchored object doesn't fit into upper of section. + // But the anchored object is allowed to overlap bottom + // section|section column. + if ( nDist >= 0 ) + { + break; + } + // <-- + } + if ( !bInSct && + (GetAnchoredObj().GetObjRect().*fnRect->fnGetTop)() == + (pUpperOfOrientFrm->*fnRect->fnGetPrtTop)() ) + //Das teil passt nimmer, da hilft auch kein moven. + break; + + const SwLayoutFrm* pNextLay = pUpperOfOrientFrm->GetLeaf( + ( bInSct + ? MAKEPAGE_NOSECTION + : ( bInFtn ? MAKEPAGE_NONE : MAKEPAGE_APPEND ) ), + TRUE, &rAnchorTxtFrm ); + // OD 06.10.2003 #110978# - correction: + // If anchor is in footnote and proposed next layout environment + // isn't a footnote frame, object can't follow the text flow + if ( bInFtn && pNextLay && !pNextLay->IsFtnFrm() ) + { + pNextLay = 0L; + } + if ( pNextLay ) + { + SWRECTFNX( pNextLay ) + if ( !bInSct || + ( pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pNextLay->FindSctFrm() ) && + (pNextLay->Prt().*fnRectX->fnGetHeight)() ) ) + { + SwTwips nTmpRelPosY = + (*fnRect->fnYDiff)( (pNextLay->*fnRect->fnGetPrtTop)(), + nTopOfAnch ); + if ( bVert ) + aRelPos.X() = nTmpRelPosY; + else + aRelPos.Y() = nTmpRelPosY; + pUpperOfOrientFrm = pNextLay; + SWREFRESHFN( pUpperOfOrientFrm ) + bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm ); + if( bVertX ) + GetAnchoredObj().SetObjLeft( nTopOfAnch - + aRelPos.X() - + aObjBoundRect.Width() ); + else + GetAnchoredObj().SetObjTop( nTopOfAnch + + aRelPos.Y() ); + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() ); + } + // --> OD 2004-11-01 #i23129# - leave section area + else if ( bInSct ) + { + const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper(); + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pTmp->*fnRect->fnGetPrtBottom)() ); + if( nDist < 0 ) + pUpperOfOrientFrm = pTmp; + else + break; + } + // <-- + } + else if ( bInSct ) + { + // Wenn wir innerhalb des Bereich nicht genug Platz haben, gucken + // wir uns mal die Seite an. + const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper(); + nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)( + (pTmp->*fnRect->fnGetPrtBottom)() ); + if( nDist < 0 ) + pUpperOfOrientFrm = pTmp; + else + break; + } + else + bMoveable = false; + } + } + } + + // keep layout frame vertical position is oriented at. + mpVertPosOrientFrm = pUpperOfOrientFrm; + + } + + // determine 'horizontal' position + { + // determine horizontal positioning and alignment attributes + SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() ); + + // set calculated vertical position in order to determine correct + // frame, the horizontal position is oriented at. + const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert ); + if( bVert ) + GetAnchoredObj().SetObjLeft( nTopOfAnch - + aRelPos.X() - aObjBoundRect.Width() ); + else + GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() ); + + // determine frame, horizontal position is oriented at. + // OD 2004-05-21 #i28701# - If floating screen object doesn't follow + // the text flow, its horizontal position is oriented at <pOrientFrm>. + const SwFrm* pHoriOrientFrm = DoesObjFollowsTextFlow() + ? &_GetHoriVirtualAnchor( *mpVertPosOrientFrm ) + : pOrientFrm; + + // --> OD 2004-06-17 #i26791# - get 'horizontal' offset to frame anchor position. + SwTwips nHoriOffsetToFrmAnchorPos( 0L ); + SwTwips nRelPosX = _CalcRelPosX( *pHoriOrientFrm, aEnvOfObj, + aHori, rLR, rUL, bWrapThrough, + ( bVert ? aRelPos.X() : aRelPos.Y() ), + nHoriOffsetToFrmAnchorPos ); + + // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame + // anchor position, depending on layout-direction + if ( bVert ) + { + aRelPos.Y() = nRelPosX; + maOffsetToFrmAnchorPos.Y() = nHoriOffsetToFrmAnchorPos; + } + else + { + aRelPos.X() = nRelPosX; + maOffsetToFrmAnchorPos.X() = nHoriOffsetToFrmAnchorPos; + } + + // save calculated horizontal position - needed for filters + // (including the xml-filter) + { + SwTwips nAttrRelPosX = nRelPosX - nHoriOffsetToFrmAnchorPos; + if ( aHori.GetHoriOrient() != text::HoriOrientation::NONE && + aHori.GetPos() != nAttrRelPosX ) + { + aHori.SetPos( nAttrRelPosX ); + const_cast<SwFrmFmt&>(rFrmFmt).LockModify(); + const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori ); + const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify(); + } + } + } + + // set absolute position at object + const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert ); + if( bVert ) + { + GetAnchoredObj().SetObjLeft( nTopOfAnch - + aRelPos.X() - aObjBoundRect.Width() ); + GetAnchoredObj().SetObjTop( rAnchorTxtFrm.Frm().Top() + + aRelPos.Y() ); + } + else + { + GetAnchoredObj().SetObjLeft( rAnchorTxtFrm.Frm().Left() + + aRelPos.X() ); + GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() ); + } + + // set relative position at object + GetAnchoredObj().SetCurrRelPos( aRelPos ); +} + +/** determine frame for horizontal position + + @author OD +*/ +const SwFrm& SwToCntntAnchoredObjectPosition::_GetHoriVirtualAnchor( + const SwLayoutFrm& _rProposedFrm ) const +{ + const SwFrm* pHoriVirtAnchFrm = &_rProposedFrm; + + // Search for first lower content frame, which is the anchor or a follow + // of the anchor (Note: <Anchor.IsAnFollow( Anchor )> is true) + // If none found, <_rProposedFrm> is returned. + const SwFrm* pFrm = _rProposedFrm.Lower(); + while ( pFrm ) + { + if ( pFrm->IsCntntFrm() && + GetAnchorTxtFrm().IsAnFollow( static_cast<const SwCntntFrm*>(pFrm) ) ) + { + pHoriVirtAnchFrm = pFrm; + break; + } + pFrm = pFrm->GetNext(); + } + + return *pHoriVirtAnchFrm; +} + +const SwLayoutFrm& SwToCntntAnchoredObjectPosition::GetVertPosOrientFrm() const +{ + return *mpVertPosOrientFrm; +} + |