1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tocntntanchoredobjectposition.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <tocntntanchoredobjectposition.hxx>
34 #include <anchoredobject.hxx>
37 #include <pagefrm.hxx>
38 #include <sectfrm.hxx>
39 // --> OD 2004-10-15 #i26945#
43 #include <IDocumentSettingAccess.hxx>
44 #include <fmtsrnd.hxx>
45 #include <fmtfsize.hxx>
46 #include <fmtanchr.hxx>
47 #include <fmtornt.hxx>
48 #include <svx/lrspitem.hxx>
49 #include <svx/ulspitem.hxx>
50 #ifndef _SVX_SVDOBJ_HXX
51 #include <svx/svdobj.hxx>
54 #ifndef _ENVIRONMENTOFANCHOREDOBJECT
55 #include <environmentofanchoredobject.hxx>
57 #include <frmtool.hxx>
59 #include <dflyobj.hxx>
61 using namespace objectpositioning
;
62 using namespace ::com::sun::star
;
65 SwToCntntAnchoredObjectPosition::SwToCntntAnchoredObjectPosition( SdrObject
& _rDrawObj
)
66 : SwAnchoredObjectPosition ( _rDrawObj
),
67 mpVertPosOrientFrm( 0 ),
68 // --> OD 2004-06-17 #i26791#
69 maOffsetToFrmAnchorPos( Point() ),
70 mbAnchorToChar ( false ),
71 mpToCharOrientFrm( 0 ),
73 // OD 12.11.2003 #i22341#
74 mnToCharTopOfLine( 0 )
77 SwToCntntAnchoredObjectPosition::~SwToCntntAnchoredObjectPosition()
80 bool SwToCntntAnchoredObjectPosition::IsAnchoredToChar() const
82 return mbAnchorToChar
;
85 const SwFrm
* SwToCntntAnchoredObjectPosition::ToCharOrientFrm() const
87 return mpToCharOrientFrm
;
90 const SwRect
* SwToCntntAnchoredObjectPosition::ToCharRect() const
95 // OD 12.11.2003 #i22341#
96 SwTwips
SwToCntntAnchoredObjectPosition::ToCharTopOfLine() const
98 return mnToCharTopOfLine
;
101 SwTxtFrm
& SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() const
103 ASSERT( GetAnchorFrm().ISA(SwTxtFrm
),
104 "SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
106 return static_cast<SwTxtFrm
&>(GetAnchorFrm());
109 // --> OD 2004-07-20 #i23512#
110 bool lcl_DoesVertPosFits( const SwTwips _nRelPosY
,
111 const SwTwips _nAvail
,
112 const SwLayoutFrm
* _pUpperOfOrientFrm
,
114 const bool _bGrowInTable
,
115 SwLayoutFrm
*& _orpLayoutFrmToGrow
)
117 bool bVertPosFits
= false;
119 if ( _nRelPosY
<= _nAvail
)
125 if ( _pUpperOfOrientFrm
->IsInSct() )
127 SwSectionFrm
* pSctFrm
=
128 const_cast<SwSectionFrm
*>(_pUpperOfOrientFrm
->FindSctFrm());
129 bVertPosFits
= pSctFrm
->GetUpper()->Grow( _nRelPosY
- _nAvail
, TRUE
) > 0;
130 // Note: do not provide a layout frame for a grow.
134 bVertPosFits
= const_cast<SwLayoutFrm
*>(_pUpperOfOrientFrm
)->
135 Grow( _nRelPosY
- _nAvail
, TRUE
) > 0;
137 _orpLayoutFrmToGrow
= const_cast<SwLayoutFrm
*>(_pUpperOfOrientFrm
);
140 else if ( _pUpperOfOrientFrm
->IsInTab() && _bGrowInTable
)
142 // --> OD 2005-06-08 #i45085# - check, if upper frame would grow the
143 // excepted amount of twips.
144 const SwTwips nTwipsGrown
= const_cast<SwLayoutFrm
*>(_pUpperOfOrientFrm
)->
145 Grow( _nRelPosY
- _nAvail
, TRUE
) > 0;
146 bVertPosFits
= ( nTwipsGrown
== ( _nRelPosY
- _nAvail
) );
149 _orpLayoutFrmToGrow
= const_cast<SwLayoutFrm
*>(_pUpperOfOrientFrm
);
156 void SwToCntntAnchoredObjectPosition::CalcPosition()
158 // get format of object
159 const SwFrmFmt
& rFrmFmt
= GetFrmFmt();
161 // declare and set <pFooter> to footer frame, if object is anchored
162 // at a frame belonging to the footer.
163 const SwFrm
* pFooter
= GetAnchorFrm().FindFooterOrHeader();
164 if ( pFooter
&& !pFooter
->IsFooterFrm() )
167 // declare and set <bBrowse> to true, if document is in browser mode and
168 // object is anchored at the body, but not at frame belonging to a table.
169 const bool bBrowse
= GetAnchorFrm().IsInDocBody() &&
170 !GetAnchorFrm().IsInTab()
171 ? rFrmFmt
.getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
)
174 // determine left/right and its upper/lower spacing.
175 const SvxLRSpaceItem
&rLR
= rFrmFmt
.GetLRSpace();
176 const SvxULSpaceItem
&rUL
= rFrmFmt
.GetULSpace();
178 // determine, if object has no surrounding.
179 const SwFmtSurround
& rSurround
= rFrmFmt
.GetSurround();
180 const bool bNoSurround
= rSurround
.GetSurround() == SURROUND_NONE
;
181 const bool bWrapThrough
= rSurround
.GetSurround() == SURROUND_THROUGHT
;
183 // OD 29.10.2003 #110978# - new class <SwEnvironmentOfAnchoredObject>
184 SwEnvironmentOfAnchoredObject
aEnvOfObj( DoesObjFollowsTextFlow() );
186 // OD 30.09.2003 #i18732# - grow only, if object has to follow the text flow
187 const bool bGrow
= DoesObjFollowsTextFlow() &&
188 ( !GetAnchorFrm().IsInTab() ||
189 !rFrmFmt
.GetFrmSize().GetHeightPercent() );
191 // get text frame the object is anchored at
192 const SwTxtFrm
& rAnchorTxtFrm
= GetAnchorTxtFrm();
193 SWRECTFN( (&rAnchorTxtFrm
) )
195 const SwRect
aObjBoundRect( GetAnchoredObj().GetObjRect() );
197 // local variable keeping the calculated relative position; initialized with
198 // current relative position.
199 // OD 2004-03-24 #i26791# - use new object instance of <SwAnchoredObject>
200 Point
aRelPos( GetAnchoredObj().GetCurrRelPos() );
202 SwTwips nRelDiff
= 0;
204 bool bMoveable
= rAnchorTxtFrm
.IsMoveable();
206 // determine frame the object position has to be oriented at.
207 const SwTxtFrm
* pOrientFrm
= &rAnchorTxtFrm
;
208 const SwTxtFrm
* pAnchorFrmForVertPos
= &rAnchorTxtFrm
;
210 // if object is at-character anchored, determine character-rectangle
211 // and frame, position has to be oriented at.
212 mbAnchorToChar
= FLY_AUTO_CNTNT
== rFrmFmt
.GetAnchor().GetAnchorId();
213 if ( mbAnchorToChar
)
215 const SwFmtAnchor
& rAnch
= rFrmFmt
.GetAnchor();
216 // OD 2004-03-24 #i26791# - use new object instance of <SwAnchoredObject>
217 // OD 2005-01-12 - Due to table break algorithm the character
218 // rectangle can have no height. Thus, check also the width
219 if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
220 !GetAnchoredObj().GetLastCharRect().Width() ) ||
221 !GetAnchoredObj().GetLastTopOfLine() )
223 // --> OD 2004-07-15 #117380# - suppress check for paragraph
224 // portion information by passing <false> as first parameter
225 GetAnchoredObj().CheckCharRectAndTopOfLine( false );
226 // OD 2005-01-12 - Due to table break algorithm the character
227 // rectangle can have no height. Thus, check also the width
228 if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
229 !GetAnchoredObj().GetLastCharRect().Width() ) ||
230 !GetAnchoredObj().GetLastTopOfLine() )
232 // --> OD 2005-01-12 - get default for <mpVertPosOrientFrm>,
234 if ( !mpVertPosOrientFrm
)
236 mpVertPosOrientFrm
= rAnchorTxtFrm
.GetUpper();
242 mpToCharRect
= &(GetAnchoredObj().GetLastCharRect());
243 // OD 12.11.2003 #i22341# - get top of line, in which the anchor
245 mnToCharTopOfLine
= GetAnchoredObj().GetLastTopOfLine();
246 pOrientFrm
= &(const_cast<SwTxtFrm
&>(rAnchorTxtFrm
).GetFrmAtOfst(
247 rAnch
.GetCntntAnchor()->nContent
.GetIndex() ) );
248 mpToCharOrientFrm
= pOrientFrm
;
251 SWREFRESHFN( pOrientFrm
)
253 // determine vertical position
256 // determine vertical positioning and alignment attributes
257 SwFmtVertOrient
aVert( rFrmFmt
.GetVertOrient() );
259 // OD 22.09.2003 #i18732# - determine layout frame for vertical
260 // positions aligned to 'page areas'.
261 const SwLayoutFrm
& rPageAlignLayFrm
=
262 aEnvOfObj
.GetVertEnvironmentLayoutFrm( *pOrientFrm
);
264 if ( aVert
.GetVertOrient() != text::VertOrientation::NONE
)
266 // OD 22.09.2003 #i18732# - adjustments for follow text flow or not
267 // AND vertical alignment at 'page areas'.
268 SwTwips nAlignAreaHeight
;
269 SwTwips nAlignAreaOffset
;
270 _GetVertAlignmentValues( *pOrientFrm
, rPageAlignLayFrm
,
271 aVert
.GetRelationOrient(),
272 nAlignAreaHeight
, nAlignAreaOffset
);
274 // determine relative vertical position
275 SwTwips nRelPosY
= nAlignAreaOffset
;
276 SwTwips nObjHeight
= (aObjBoundRect
.*fnRect
->fnGetHeight
)();
277 SwTwips nUpperSpace
= bVert
? rLR
.GetRight() : rUL
.GetUpper();
278 SwTwips nLowerSpace
= bVert
? rLR
.GetLeft() : rUL
.GetLower();
279 switch ( aVert
.GetVertOrient() )
281 case text::VertOrientation::CHAR_BOTTOM
:
283 if ( mbAnchorToChar
)
285 // bottom (to character anchored)
286 nRelPosY
+= nAlignAreaHeight
+ nUpperSpace
;
288 nRelPosY
+= nObjHeight
;
293 case text::VertOrientation::TOP
:
295 // OD 12.11.2003 #i22341# - special case for vertical
296 // alignment at top of line
297 if ( mbAnchorToChar
&&
298 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
300 nRelPosY
-= (nObjHeight
+ nLowerSpace
);
304 nRelPosY
+= nUpperSpace
;
308 // OD 14.11.2003 #i22341#
309 case text::VertOrientation::LINE_TOP
:
311 if ( mbAnchorToChar
&&
312 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
314 nRelPosY
-= (nObjHeight
+ nLowerSpace
);
319 "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
323 case text::VertOrientation::CENTER
:
325 nRelPosY
+= (nAlignAreaHeight
/ 2) - (nObjHeight
/ 2);
328 // OD 14.11.2003 #i22341#
329 case text::VertOrientation::LINE_CENTER
:
331 if ( mbAnchorToChar
&&
332 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
334 nRelPosY
+= (nAlignAreaHeight
/ 2) - (nObjHeight
/ 2);
339 "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
343 case text::VertOrientation::BOTTOM
:
345 if ( ( aVert
.GetRelationOrient() == text::RelOrientation::FRAME
||
346 aVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
) &&
349 // bottom (aligned to 'paragraph areas')
350 nRelPosY
+= nAlignAreaHeight
+ nUpperSpace
;
354 // OD 12.11.2003 #i22341# - special case for vertical
355 // alignment at top of line
356 if ( mbAnchorToChar
&&
357 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
359 nRelPosY
+= nUpperSpace
;
363 nRelPosY
+= nAlignAreaHeight
-
364 ( nObjHeight
+ nLowerSpace
);
369 // OD 14.11.2003 #i22341#
370 case text::VertOrientation::LINE_BOTTOM
:
372 if ( mbAnchorToChar
&&
373 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
375 nRelPosY
+= nUpperSpace
;
380 "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
388 // adjust relative position by distance between anchor frame and
389 // the frame, the object is oriented at.
390 // OD 2004-05-21 #i28701# - correction: adjust relative position,
391 // only if the floating screen object has to follow the text flow.
392 if ( DoesObjFollowsTextFlow() && pOrientFrm
!= &rAnchorTxtFrm
)
394 // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
395 // to get top of frame for object positioning.
396 const SwTwips nTopOfOrient
= _GetTopForObjPos( *pOrientFrm
, fnRect
, bVert
);
397 nRelPosY
+= (*fnRect
->fnYDiff
)( nTopOfOrient
,
398 _GetTopForObjPos( rAnchorTxtFrm
, fnRect
, bVert
) );
401 // --> OD 2005-02-07 #i42124# - capture object inside vertical
402 // layout environment.
404 const SwTwips nTopOfAnch
=
405 _GetTopForObjPos( *pOrientFrm
, fnRect
, bVert
);
406 const SwLayoutFrm
& rVertEnvironLayFrm
=
407 aEnvOfObj
.GetVertEnvironmentLayoutFrm(
408 *(pOrientFrm
->GetUpper()) );
409 const bool bCheckBottom
= !DoesObjFollowsTextFlow();
410 nRelPosY
= _AdjustVertRelPos( nTopOfAnch
, bVert
,
411 rVertEnvironLayFrm
, nRelPosY
,
412 DoesObjFollowsTextFlow(),
416 // keep calculated relative vertical position - needed for filters
417 // (including the xml-filter)
419 // determine position
420 SwTwips nAttrRelPosY
= nRelPosY
- nAlignAreaOffset
;
422 if ( nAttrRelPosY
!= aVert
.GetPos() )
424 aVert
.SetPos( nAttrRelPosY
);
425 const_cast<SwFrmFmt
&>(rFrmFmt
).LockModify();
426 const_cast<SwFrmFmt
&>(rFrmFmt
).SetFmtAttr( aVert
);
427 const_cast<SwFrmFmt
&>(rFrmFmt
).UnlockModify();
431 // determine absolute 'vertical' position, depending on layout-direction
432 // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame
433 // anchor position, depending on layout-direction
436 aRelPos
.X() = nRelPosY
;
437 maOffsetToFrmAnchorPos
.X() = nAlignAreaOffset
;
441 aRelPos
.Y() = nRelPosY
;
442 maOffsetToFrmAnchorPos
.Y() = nAlignAreaOffset
;
446 // OD 29.10.2003 #110978# - determine upper of frame vertical position
448 // OD 2004-05-21 #i28701# - determine 'virtual' anchor frame.
449 // This frame is used in the following instead of the 'real' anchor
450 // frame <rAnchorTxtFrm> for the 'vertical' position in all cases.
451 const SwLayoutFrm
* pUpperOfOrientFrm
= 0L;
453 // OD 2004-05-21 #i28701# - As long as the anchor frame is on the
454 // same page as <pOrientFrm> and the vertical position isn't aligned
455 // automatic at the anchor character or the top of the line of the
456 // anchor character, the anchor frame determines the vertical position.
457 if ( &rAnchorTxtFrm
== pOrientFrm
||
458 ( rAnchorTxtFrm
.FindPageFrm() == pOrientFrm
->FindPageFrm() &&
459 aVert
.GetVertOrient() == text::VertOrientation::NONE
&&
460 aVert
.GetRelationOrient() != text::RelOrientation::CHAR
&&
461 aVert
.GetRelationOrient() != text::RelOrientation::TEXT_LINE
) )
463 pUpperOfOrientFrm
= rAnchorTxtFrm
.GetUpper();
464 pAnchorFrmForVertPos
= &rAnchorTxtFrm
;
468 pUpperOfOrientFrm
= pOrientFrm
->GetUpper();
469 pAnchorFrmForVertPos
= pOrientFrm
;
473 // ignore one-column sections.
474 // --> OD 2004-07-20 #i23512# - correction: also ignore one-columned
475 // sections with footnotes/endnotes
476 if ( pUpperOfOrientFrm
->IsInSct() )
478 const SwSectionFrm
* pSctFrm
= pUpperOfOrientFrm
->FindSctFrm();
479 const bool bIgnoreSection
= pUpperOfOrientFrm
->IsSctFrm() ||
480 ( pSctFrm
->Lower()->IsColumnFrm() &&
481 !pSctFrm
->Lower()->GetNext() );
482 if ( bIgnoreSection
)
483 pUpperOfOrientFrm
= pSctFrm
->GetUpper();
486 if ( aVert
.GetVertOrient() == text::VertOrientation::NONE
)
488 // local variable <nRelPosY> for calculation of relative vertical
489 // distance to anchor.
490 SwTwips nRelPosY
= 0;
491 // --> OD 2004-06-17 #i26791# - local variable <nVertOffsetToFrmAnchorPos>
492 // for determination of the 'vertical' offset to the frame anchor
494 SwTwips
nVertOffsetToFrmAnchorPos( 0L );
495 // OD 12.11.2003 #i22341# - add special case for vertical alignment
497 if ( mbAnchorToChar
&&
498 ( aVert
.GetRelationOrient() == text::RelOrientation::CHAR
||
499 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
) )
501 // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
502 // to get top of frame for object positioning.
503 SwTwips nTopOfOrient
= _GetTopForObjPos( *pOrientFrm
, fnRect
, bVert
);
504 if ( aVert
.GetRelationOrient() == text::RelOrientation::CHAR
)
506 nVertOffsetToFrmAnchorPos
= (*fnRect
->fnYDiff
)(
507 (ToCharRect()->*fnRect
->fnGetBottom
)(),
512 nVertOffsetToFrmAnchorPos
= (*fnRect
->fnYDiff
)( ToCharTopOfLine(),
515 nRelPosY
= nVertOffsetToFrmAnchorPos
- aVert
.GetPos();
519 // OD 2004-05-21 #i28701# - correction: use <pAnchorFrmForVertPos>
520 // instead of <pOrientFrm> and do not adjust relative position
521 // to get correct vertical position.
522 nVertOffsetToFrmAnchorPos
= 0L;
523 // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
524 // to get top of frame for object positioning.
525 const SwTwips nTopOfOrient
=
526 _GetTopForObjPos( *pAnchorFrmForVertPos
, fnRect
, bVert
);
527 // OD 02.10.2002 #102646# - increase <nRelPosY> by margin height,
528 // if position is vertical aligned to "paragraph text area"
529 if ( aVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
)
531 // OD 2004-03-11 #i11860# - consider upper space amount
533 SwTwips nTopMargin
= (pAnchorFrmForVertPos
->*fnRect
->fnGetTopMargin
)();
534 if ( pAnchorFrmForVertPos
->IsTxtFrm() )
536 nTopMargin
-= static_cast<const SwTxtFrm
*>(pAnchorFrmForVertPos
)->
537 GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
539 nVertOffsetToFrmAnchorPos
+= nTopMargin
;
541 // OD 22.09.2003 #i18732# - adjust <nRelPosY> by difference
542 // between 'page area' and 'anchor' frame, if position is
543 // vertical aligned to 'page areas'
544 else if ( aVert
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
)
546 nVertOffsetToFrmAnchorPos
+= (*fnRect
->fnYDiff
)(
547 (rPageAlignLayFrm
.Frm().*fnRect
->fnGetTop
)(),
550 else if ( aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
)
552 SwRect
aPgPrtRect( rPageAlignLayFrm
.Frm() );
553 if ( rPageAlignLayFrm
.IsPageFrm() )
556 static_cast<const SwPageFrm
&>(rPageAlignLayFrm
).PrtWithoutHeaderAndFooter();
558 nVertOffsetToFrmAnchorPos
+= (*fnRect
->fnYDiff
)(
559 (aPgPrtRect
.*fnRect
->fnGetTop
)(),
562 nRelPosY
= nVertOffsetToFrmAnchorPos
+ aVert
.GetPos();
565 // <pUpperOfOrientFrm>: layout frame, at which the position has to
567 // <nRelPosY>: rest of the relative distance in the current
569 // <nAvail>: space, which is available in the current
572 // --> OD 2004-06-17 #i26791# - determine offset to 'vertical'
573 // frame anchor position, depending on layout-direction
575 maOffsetToFrmAnchorPos
.X() = nVertOffsetToFrmAnchorPos
;
577 maOffsetToFrmAnchorPos
.Y() = nVertOffsetToFrmAnchorPos
;
579 // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
580 // to get top of frame for object positioning.
581 const SwTwips nTopOfAnch
= _GetTopForObjPos( *pAnchorFrmForVertPos
, fnRect
, bVert
);
584 // OD 08.09.2003 #110354# - allow negative position, but keep it
585 // inside environment layout frame.
586 const SwLayoutFrm
& rVertEnvironLayFrm
=
587 aEnvOfObj
.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm
);
588 // --> OD 2004-07-22 #i31805# - do not check, if bottom of
589 // anchored object would fit into environment layout frame, if
590 // anchored object has to follow the text flow.
591 const bool bCheckBottom
= !DoesObjFollowsTextFlow();
592 nRelPosY
= _AdjustVertRelPos( nTopOfAnch
, bVert
,
593 rVertEnvironLayFrm
, nRelPosY
,
594 DoesObjFollowsTextFlow(),
598 aRelPos
.X() = nRelPosY
;
600 aRelPos
.Y() = nRelPosY
;
604 SWREFRESHFN( pAnchorFrmForVertPos
)
606 (*fnRect
->fnYDiff
)( (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)(),
608 const bool bInFtn
= pAnchorFrmForVertPos
->IsInFtn();
611 // --> OD 2004-07-20 #i23512# - correction:
612 // consider section frame for grow in online layout.
613 // use new local method <lcl_DoesVertPosFits(..)>
614 SwLayoutFrm
* pLayoutFrmToGrow
= 0L;
615 const bool bDoesVertPosFits
= lcl_DoesVertPosFits(
616 nRelPosY
, nAvail
, pUpperOfOrientFrm
, bBrowse
,
617 bGrow
, pLayoutFrmToGrow
);
619 if ( bDoesVertPosFits
)
621 SwTwips nTmpRelPosY
=
622 (*fnRect
->fnYDiff
)( (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)(),
625 // --> OD 2004-07-06 #i28701# - adjust calculated
626 // relative vertical position to object's environment.
627 const SwFrm
& rVertEnvironLayFrm
=
628 aEnvOfObj
.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm
);
629 // --> OD 2004-08-20 - do not check, if bottom of
630 // anchored object would fit into environment layout
631 // frame, if anchored object has to follow the text flow.
632 const bool bCheckBottom
= !DoesObjFollowsTextFlow();
633 nTmpRelPosY
= _AdjustVertRelPos( nTopOfAnch
, bVert
,
636 DoesObjFollowsTextFlow(),
640 aRelPos
.X() = nTmpRelPosY
;
642 aRelPos
.Y() = nTmpRelPosY
;
644 // --> OD 2004-07-20 #i23512# - use local variable
645 // <pLayoutFrmToGrow> provided by new method
646 // <lcl_DoesVertPosFits(..)>.
647 if ( pLayoutFrmToGrow
)
649 pLayoutFrmToGrow
->Grow( nRelPosY
- nAvail
);
656 // --> OD 2004-10-04 #i26495# - floating screen objects,
657 // which are anchored inside a table, doesn't follow
659 if ( DoesObjFollowsTextFlow() &&
660 !( aVert
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
||
661 aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
) &&
662 !GetAnchorFrm().IsInTab() )
667 // follow the text flow
669 MakePageType eMakePage
= bInFtn
? MAKEPAGE_NONE
671 const bool bInSct
= pUpperOfOrientFrm
->IsInSct();
673 eMakePage
= MAKEPAGE_NOSECTION
;
675 const SwLayoutFrm
* pTmp
=
676 pUpperOfOrientFrm
->GetLeaf( eMakePage
, TRUE
, &rAnchorTxtFrm
);
679 pUpperOfOrientFrm
->FindSctFrm()->IsAnFollow( pTmp
->FindSctFrm() ) ) )
681 pUpperOfOrientFrm
= pTmp
;
682 bMoveable
= rAnchorTxtFrm
.IsMoveable( (SwLayoutFrm
*)pUpperOfOrientFrm
);
683 SWREFRESHFN( pUpperOfOrientFrm
)
684 nAvail
= (pUpperOfOrientFrm
->Prt().*fnRect
->fnGetHeight
)();
688 // if there isn't enough space in the (colmuned)
689 // section, leave it and set available space <nAvail>
690 // to the space below the section.
691 // if the new available space isn't also enough,
692 // new pages can be created.
695 const SwFrm
* pSct
= pUpperOfOrientFrm
->FindSctFrm();
696 pUpperOfOrientFrm
= pSct
->GetUpper();
697 nAvail
= (*fnRect
->fnYDiff
)(
698 (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)(),
699 (pSct
->*fnRect
->fnGetPrtBottom
)() );
703 #if OSL_DEBUG_LEVEL > 1
704 ASSERT( false, "<SwToCntntAnchoredObjectPosition::CalcPosition()> - code under investigation by OD, please inform OD about this assertion!" );
718 // OD 06.10.2003 #i18732# - do not follow text flow respectively
719 // align at 'page areas', but stay inside given environment
720 const SwFrm
& rVertEnvironLayFrm
=
721 aEnvOfObj
.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm
);
722 nRelPosY
= _AdjustVertRelPos( nTopOfAnch
, bVert
,
725 DoesObjFollowsTextFlow() );
727 aRelPos
.X() = nRelPosY
;
729 aRelPos
.Y() = nRelPosY
;
733 } // end of <while ( nRelPosY )>
734 } // end of else <nRelPosY <= 0>
735 } // end of <aVert.GetVertOrient() == text::VertOrientation::NONE>
737 //Damit das Teil ggf. auf die richtige Seite gestellt und in die
738 //PrtArea des LayLeaf gezogen werden kann, muss hier seine
739 //absolute Position berechnet werden.
740 const SwTwips nTopOfAnch
= _GetTopForObjPos( *pAnchorFrmForVertPos
, fnRect
, bVert
);
743 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
744 ( aRelPos
.X() - nRelDiff
) -
745 aObjBoundRect
.Width() );
749 GetAnchoredObj().SetObjTop( nTopOfAnch
+
750 ( aRelPos
.Y() - nRelDiff
) );
753 // grow environment under certain conditions
754 // ignore one-column sections.
755 // --> OD 2004-07-20 #i23512# - correction: also ignore one-columned
756 // sections with footnotes/endnotes
757 if ( pUpperOfOrientFrm
->IsInSct() )
759 const SwSectionFrm
* pSctFrm
= pUpperOfOrientFrm
->FindSctFrm();
760 const bool bIgnoreSection
= pUpperOfOrientFrm
->IsSctFrm() ||
761 ( pSctFrm
->Lower()->IsColumnFrm() &&
762 !pSctFrm
->Lower()->GetNext() );
763 if ( bIgnoreSection
)
764 pUpperOfOrientFrm
= pSctFrm
->GetUpper();
766 SwTwips nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
767 (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)() );
770 // --> OD 2004-07-20 #i23512# - correction:
771 // consider section frame for grow in online layout and
772 // consider page alignment for grow in table.
773 SwLayoutFrm
* pLayoutFrmToGrow
= 0L;
774 if ( bBrowse
&& rAnchorTxtFrm
.IsMoveable() )
776 if ( pUpperOfOrientFrm
->IsInSct() )
778 pLayoutFrmToGrow
= const_cast<SwLayoutFrm
*>(
779 pUpperOfOrientFrm
->FindSctFrm()->GetUpper());
780 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
781 (pLayoutFrmToGrow
->*fnRect
->fnGetPrtBottom
)() );
784 pLayoutFrmToGrow
= 0L;
790 const_cast<SwLayoutFrm
*>(pUpperOfOrientFrm
);
793 else if ( rAnchorTxtFrm
.IsInTab() && bGrow
)
795 pLayoutFrmToGrow
= const_cast<SwLayoutFrm
*>(pUpperOfOrientFrm
);
797 if ( pLayoutFrmToGrow
)
799 pLayoutFrmToGrow
->Grow( -nDist
);
804 if ( DoesObjFollowsTextFlow() &&
805 !( aVert
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
||
806 aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
) )
809 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
810 (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)() );
811 // --> OD 2004-10-04 #i26945# - floating screen objects, which are
812 // anchored inside a table, doesn't follow the text flow. But, they
813 // have to stay inside its layout environment.
814 if ( nDist
< 0 && pOrientFrm
->IsInTab() )
816 // If the anchor frame is the first content of the table cell
817 // and has no follow, the table frame is notified,
818 // that the object doesn't fit into the table cell.
819 // Adjustment of position isn't needed in this case.
820 if ( pOrientFrm
== &rAnchorTxtFrm
&&
821 !pOrientFrm
->GetFollow() &&
822 !pOrientFrm
->GetIndPrev() )
824 const_cast<SwTabFrm
*>(pOrientFrm
->FindTabFrm())
825 ->SetDoesObjsFit( FALSE
);
829 SwTwips
nTmpRelPosY( 0L );
831 nTmpRelPosY
= aRelPos
.X() - nDist
;
833 nTmpRelPosY
= aRelPos
.Y() + nDist
;
834 const SwLayoutFrm
& rVertEnvironLayFrm
=
835 aEnvOfObj
.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm
);
836 nTmpRelPosY
= _AdjustVertRelPos( nTopOfAnch
, bVert
,
839 DoesObjFollowsTextFlow(),
843 aRelPos
.X() = nTmpRelPosY
;
844 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
846 aObjBoundRect
.Width() );
850 aRelPos
.Y() = nTmpRelPosY
;
851 GetAnchoredObj().SetObjTop( nTopOfAnch
+ aRelPos
.Y() );
853 // If the anchor frame is the first content of the table cell
854 // and the object still doesn't fit, the table frame is notified,
855 // that the object doesn't fit into the table cell.
856 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
857 (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)() );
859 pOrientFrm
== &rAnchorTxtFrm
&& !pOrientFrm
->GetIndPrev() )
861 const_cast<SwTabFrm
*>(pOrientFrm
->FindTabFrm())
862 ->SetDoesObjsFit( FALSE
);
870 const bool bInFtn
= rAnchorTxtFrm
.IsInFtn();
871 while( bMoveable
&& nDist
< 0 )
873 bool bInSct
= pUpperOfOrientFrm
->IsInSct();
876 const SwLayoutFrm
* pTmp
= pUpperOfOrientFrm
->FindSctFrm()->GetUpper();
877 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
878 (pTmp
->*fnRect
->fnGetPrtBottom
)() );
879 // --> OD 2004-11-01 #i23129# - Try to flow into next
880 // section|section column. Thus, do *not* leave section
881 // area, if anchored object doesn't fit into upper of section.
882 // But the anchored object is allowed to overlap bottom
883 // section|section column.
891 (GetAnchoredObj().GetObjRect().*fnRect
->fnGetTop
)() ==
892 (pUpperOfOrientFrm
->*fnRect
->fnGetPrtTop
)() )
893 //Das teil passt nimmer, da hilft auch kein moven.
896 const SwLayoutFrm
* pNextLay
= pUpperOfOrientFrm
->GetLeaf(
899 : ( bInFtn
? MAKEPAGE_NONE
: MAKEPAGE_APPEND
) ),
900 TRUE
, &rAnchorTxtFrm
);
901 // OD 06.10.2003 #110978# - correction:
902 // If anchor is in footnote and proposed next layout environment
903 // isn't a footnote frame, object can't follow the text flow
904 if ( bInFtn
&& pNextLay
&& !pNextLay
->IsFtnFrm() )
910 SWRECTFNX( pNextLay
)
912 ( pUpperOfOrientFrm
->FindSctFrm()->IsAnFollow( pNextLay
->FindSctFrm() ) &&
913 (pNextLay
->Prt().*fnRectX
->fnGetHeight
)() ) )
915 SwTwips nTmpRelPosY
=
916 (*fnRect
->fnYDiff
)( (pNextLay
->*fnRect
->fnGetPrtTop
)(),
919 aRelPos
.X() = nTmpRelPosY
;
921 aRelPos
.Y() = nTmpRelPosY
;
922 pUpperOfOrientFrm
= pNextLay
;
923 SWREFRESHFN( pUpperOfOrientFrm
)
924 bMoveable
= rAnchorTxtFrm
.IsMoveable( (SwLayoutFrm
*)pUpperOfOrientFrm
);
926 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
928 aObjBoundRect
.Width() );
930 GetAnchoredObj().SetObjTop( nTopOfAnch
+
932 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
933 (pUpperOfOrientFrm
->*fnRect
->fnGetPrtBottom
)() );
935 // --> OD 2004-11-01 #i23129# - leave section area
938 const SwLayoutFrm
* pTmp
= pUpperOfOrientFrm
->FindSctFrm()->GetUpper();
939 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
940 (pTmp
->*fnRect
->fnGetPrtBottom
)() );
942 pUpperOfOrientFrm
= pTmp
;
950 // Wenn wir innerhalb des Bereich nicht genug Platz haben, gucken
951 // wir uns mal die Seite an.
952 const SwLayoutFrm
* pTmp
= pUpperOfOrientFrm
->FindSctFrm()->GetUpper();
953 nDist
= (GetAnchoredObj().GetObjRect().*fnRect
->fnBottomDist
)(
954 (pTmp
->*fnRect
->fnGetPrtBottom
)() );
956 pUpperOfOrientFrm
= pTmp
;
966 // keep layout frame vertical position is oriented at.
967 mpVertPosOrientFrm
= pUpperOfOrientFrm
;
971 // determine 'horizontal' position
973 // determine horizontal positioning and alignment attributes
974 SwFmtHoriOrient
aHori( rFrmFmt
.GetHoriOrient() );
976 // set calculated vertical position in order to determine correct
977 // frame, the horizontal position is oriented at.
978 const SwTwips nTopOfAnch
= _GetTopForObjPos( *pAnchorFrmForVertPos
, fnRect
, bVert
);
980 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
981 aRelPos
.X() - aObjBoundRect
.Width() );
983 GetAnchoredObj().SetObjTop( nTopOfAnch
+ aRelPos
.Y() );
985 // determine frame, horizontal position is oriented at.
986 // OD 2004-05-21 #i28701# - If floating screen object doesn't follow
987 // the text flow, its horizontal position is oriented at <pOrientFrm>.
988 const SwFrm
* pHoriOrientFrm
= DoesObjFollowsTextFlow()
989 ? &_GetHoriVirtualAnchor( *mpVertPosOrientFrm
)
992 // --> OD 2004-06-17 #i26791# - get 'horizontal' offset to frame anchor position.
993 SwTwips
nHoriOffsetToFrmAnchorPos( 0L );
994 SwTwips nRelPosX
= _CalcRelPosX( *pHoriOrientFrm
, aEnvOfObj
,
995 aHori
, rLR
, rUL
, bWrapThrough
,
996 ( bVert
? aRelPos
.X() : aRelPos
.Y() ),
997 nHoriOffsetToFrmAnchorPos
);
999 // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame
1000 // anchor position, depending on layout-direction
1003 aRelPos
.Y() = nRelPosX
;
1004 maOffsetToFrmAnchorPos
.Y() = nHoriOffsetToFrmAnchorPos
;
1008 aRelPos
.X() = nRelPosX
;
1009 maOffsetToFrmAnchorPos
.X() = nHoriOffsetToFrmAnchorPos
;
1012 // save calculated horizontal position - needed for filters
1013 // (including the xml-filter)
1015 SwTwips nAttrRelPosX
= nRelPosX
- nHoriOffsetToFrmAnchorPos
;
1016 if ( aHori
.GetHoriOrient() != text::HoriOrientation::NONE
&&
1017 aHori
.GetPos() != nAttrRelPosX
)
1019 aHori
.SetPos( nAttrRelPosX
);
1020 const_cast<SwFrmFmt
&>(rFrmFmt
).LockModify();
1021 const_cast<SwFrmFmt
&>(rFrmFmt
).SetFmtAttr( aHori
);
1022 const_cast<SwFrmFmt
&>(rFrmFmt
).UnlockModify();
1027 // set absolute position at object
1028 const SwTwips nTopOfAnch
= _GetTopForObjPos( *pAnchorFrmForVertPos
, fnRect
, bVert
);
1031 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
1032 aRelPos
.X() - aObjBoundRect
.Width() );
1033 GetAnchoredObj().SetObjTop( rAnchorTxtFrm
.Frm().Top() +
1038 GetAnchoredObj().SetObjLeft( rAnchorTxtFrm
.Frm().Left() +
1040 GetAnchoredObj().SetObjTop( nTopOfAnch
+ aRelPos
.Y() );
1043 // set relative position at object
1044 GetAnchoredObj().SetCurrRelPos( aRelPos
);
1047 /** determine frame for horizontal position
1051 const SwFrm
& SwToCntntAnchoredObjectPosition::_GetHoriVirtualAnchor(
1052 const SwLayoutFrm
& _rProposedFrm
) const
1054 const SwFrm
* pHoriVirtAnchFrm
= &_rProposedFrm
;
1056 // Search for first lower content frame, which is the anchor or a follow
1057 // of the anchor (Note: <Anchor.IsAnFollow( Anchor )> is true)
1058 // If none found, <_rProposedFrm> is returned.
1059 const SwFrm
* pFrm
= _rProposedFrm
.Lower();
1062 if ( pFrm
->IsCntntFrm() &&
1063 GetAnchorTxtFrm().IsAnFollow( static_cast<const SwCntntFrm
*>(pFrm
) ) )
1065 pHoriVirtAnchFrm
= pFrm
;
1068 pFrm
= pFrm
->GetNext();
1071 return *pHoriVirtAnchFrm
;
1074 const SwLayoutFrm
& SwToCntntAnchoredObjectPosition::GetVertPosOrientFrm() const
1076 return *mpVertPosOrientFrm
;