merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / objectpositioning / tocntntanchoredobjectposition.cxx
blobb052e2e652163d3d864758773e7eae6cdf9570bf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tocntntanchoredobjectposition.cxx,v $
10 * $Revision: 1.23 $
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>
35 #include <frame.hxx>
36 #include <txtfrm.hxx>
37 #include <pagefrm.hxx>
38 #include <sectfrm.hxx>
39 // --> OD 2004-10-15 #i26945#
40 #include <tabfrm.hxx>
41 // <--
42 #include <frmfmt.hxx>
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>
52 #endif
53 #include <pam.hxx>
54 #ifndef _ENVIRONMENTOFANCHOREDOBJECT
55 #include <environmentofanchoredobject.hxx>
56 #endif
57 #include <frmtool.hxx>
58 #include <ndtxt.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 ),
72 mpToCharRect( 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
92 return mpToCharRect;
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,
113 const bool _bBrowse,
114 const bool _bGrowInTable,
115 SwLayoutFrm*& _orpLayoutFrmToGrow )
117 bool bVertPosFits = false;
119 if ( _nRelPosY <= _nAvail )
121 bVertPosFits = true;
123 else if ( _bBrowse )
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.
132 else
134 bVertPosFits = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)->
135 Grow( _nRelPosY - _nAvail, TRUE ) > 0;
136 if ( bVertPosFits )
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 ) );
147 // <--
148 if ( bVertPosFits )
149 _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm);
152 return bVertPosFits;
154 // <--
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() )
165 pFooter = NULL;
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)
172 : false;
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>,
233 // if it's not set.
234 if ( !mpVertPosOrientFrm )
236 mpVertPosOrientFrm = rAnchorTxtFrm.GetUpper();
238 // <--
239 return;
242 mpToCharRect = &(GetAnchoredObj().GetLastCharRect());
243 // OD 12.11.2003 #i22341# - get top of line, in which the anchor
244 // character is.
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;
287 if ( bVert )
288 nRelPosY += nObjHeight;
289 break;
292 // no break here
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);
302 else
304 nRelPosY += nUpperSpace;
307 break;
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);
316 else
318 ASSERT( false,
319 "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
322 break;
323 case text::VertOrientation::CENTER:
325 nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
327 break;
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);
336 else
338 ASSERT( false,
339 "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
342 break;
343 case text::VertOrientation::BOTTOM:
345 if ( ( aVert.GetRelationOrient() == text::RelOrientation::FRAME ||
346 aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
347 bNoSurround )
349 // bottom (aligned to 'paragraph areas')
350 nRelPosY += nAlignAreaHeight + nUpperSpace;
352 else
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;
361 else
363 nRelPosY += nAlignAreaHeight -
364 ( nObjHeight + nLowerSpace );
368 break;
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;
377 else
379 ASSERT( false,
380 "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
383 break;
384 default:
385 break;
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(),
413 bCheckBottom );
415 // <--
416 // keep calculated relative vertical position - needed for filters
417 // (including the xml-filter)
419 // determine position
420 SwTwips nAttrRelPosY = nRelPosY - nAlignAreaOffset;
421 // set
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
434 if ( bVert )
436 aRelPos.X() = nRelPosY;
437 maOffsetToFrmAnchorPos.X() = nAlignAreaOffset;
439 else
441 aRelPos.Y() = nRelPosY;
442 maOffsetToFrmAnchorPos.Y() = nAlignAreaOffset;
446 // OD 29.10.2003 #110978# - determine upper of frame vertical position
447 // is oriented at.
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;
466 else
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
493 // position
494 SwTwips nVertOffsetToFrmAnchorPos( 0L );
495 // OD 12.11.2003 #i22341# - add special case for vertical alignment
496 // at top of line.
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)(),
508 nTopOfOrient );
510 else
512 nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)( ToCharTopOfLine(),
513 nTopOfOrient );
515 nRelPosY = nVertOffsetToFrmAnchorPos - aVert.GetPos();
517 else
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
532 // of previous frame
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)(),
548 nTopOfOrient );
550 else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
552 SwRect aPgPrtRect( rPageAlignLayFrm.Frm() );
553 if ( rPageAlignLayFrm.IsPageFrm() )
555 aPgPrtRect =
556 static_cast<const SwPageFrm&>(rPageAlignLayFrm).PrtWithoutHeaderAndFooter();
558 nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)(
559 (aPgPrtRect.*fnRect->fnGetTop)(),
560 nTopOfOrient );
562 nRelPosY = nVertOffsetToFrmAnchorPos + aVert.GetPos();
565 // <pUpperOfOrientFrm>: layout frame, at which the position has to
566 // is oriented at
567 // <nRelPosY>: rest of the relative distance in the current
568 // layout frame
569 // <nAvail>: space, which is available in the current
570 // layout frame
572 // --> OD 2004-06-17 #i26791# - determine offset to 'vertical'
573 // frame anchor position, depending on layout-direction
574 if ( bVert )
575 maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
576 else
577 maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
578 // <--
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 );
582 if( nRelPosY <= 0 )
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(),
595 bCheckBottom );
596 // <--
597 if ( bVert )
598 aRelPos.X() = nRelPosY;
599 else
600 aRelPos.Y() = nRelPosY;
602 else
604 SWREFRESHFN( pAnchorFrmForVertPos )
605 SwTwips nAvail =
606 (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
607 nTopOfAnch );
608 const bool bInFtn = pAnchorFrmForVertPos->IsInFtn();
609 while ( nRelPosY )
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)(),
623 nTopOfAnch ) -
624 nAvail + nRelPosY;
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,
634 rVertEnvironLayFrm,
635 nTmpRelPosY,
636 DoesObjFollowsTextFlow(),
637 bCheckBottom );
638 // <--
639 if ( bVert )
640 aRelPos.X() = nTmpRelPosY;
641 else
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 );
651 // <--
652 nRelPosY = 0;
654 else
656 // --> OD 2004-10-04 #i26495# - floating screen objects,
657 // which are anchored inside a table, doesn't follow
658 // the text flow.
659 if ( DoesObjFollowsTextFlow() &&
660 !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
661 aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
662 !GetAnchorFrm().IsInTab() )
663 // <--
665 if ( bMoveable )
667 // follow the text flow
668 nRelPosY -= nAvail;
669 MakePageType eMakePage = bInFtn ? MAKEPAGE_NONE
670 : MAKEPAGE_APPEND;
671 const bool bInSct = pUpperOfOrientFrm->IsInSct();
672 if( bInSct )
673 eMakePage = MAKEPAGE_NOSECTION;
675 const SwLayoutFrm* pTmp =
676 pUpperOfOrientFrm->GetLeaf( eMakePage, TRUE, &rAnchorTxtFrm );
677 if ( pTmp &&
678 ( !bInSct ||
679 pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pTmp->FindSctFrm() ) ) )
681 pUpperOfOrientFrm = pTmp;
682 bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm );
683 SWREFRESHFN( pUpperOfOrientFrm )
684 nAvail = (pUpperOfOrientFrm->Prt().*fnRect->fnGetHeight)();
686 else
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.
693 if( bInSct )
695 const SwFrm* pSct = pUpperOfOrientFrm->FindSctFrm();
696 pUpperOfOrientFrm = pSct->GetUpper();
697 nAvail = (*fnRect->fnYDiff)(
698 (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
699 (pSct->*fnRect->fnGetPrtBottom)() );
701 else
703 #if OSL_DEBUG_LEVEL > 1
704 ASSERT( false, "<SwToCntntAnchoredObjectPosition::CalcPosition()> - code under investigation by OD, please inform OD about this assertion!" );
705 #endif
706 nRelDiff = nRelPosY;
707 nRelPosY = 0;
711 else
713 nRelPosY = 0;
716 else
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,
723 rVertEnvironLayFrm,
724 nRelPosY,
725 DoesObjFollowsTextFlow() );
726 if( bVert )
727 aRelPos.X() = nRelPosY;
728 else
729 aRelPos.Y() = nRelPosY;
730 nRelPosY = 0;
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 );
741 if( bVert )
743 GetAnchoredObj().SetObjLeft( nTopOfAnch -
744 ( aRelPos.X() - nRelDiff ) -
745 aObjBoundRect.Width() );
747 else
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)() );
768 if( nDist < 0 )
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)() );
782 if ( nDist >= 0 )
784 pLayoutFrmToGrow = 0L;
787 else
789 pLayoutFrmToGrow =
790 const_cast<SwLayoutFrm*>(pUpperOfOrientFrm);
793 else if ( rAnchorTxtFrm.IsInTab() && bGrow )
795 pLayoutFrmToGrow = const_cast<SwLayoutFrm*>(pUpperOfOrientFrm);
797 if ( pLayoutFrmToGrow )
799 pLayoutFrmToGrow->Grow( -nDist );
801 // <--
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 );
827 else
829 SwTwips nTmpRelPosY( 0L );
830 if ( bVert )
831 nTmpRelPosY = aRelPos.X() - nDist;
832 else
833 nTmpRelPosY = aRelPos.Y() + nDist;
834 const SwLayoutFrm& rVertEnvironLayFrm =
835 aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
836 nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert,
837 rVertEnvironLayFrm,
838 nTmpRelPosY,
839 DoesObjFollowsTextFlow(),
840 false );
841 if ( bVert )
843 aRelPos.X() = nTmpRelPosY;
844 GetAnchoredObj().SetObjLeft( nTopOfAnch -
845 aRelPos.X() -
846 aObjBoundRect.Width() );
848 else
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)() );
858 if ( nDist < 0 &&
859 pOrientFrm == &rAnchorTxtFrm && !pOrientFrm->GetIndPrev() )
861 const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm())
862 ->SetDoesObjsFit( FALSE );
866 else
868 // <--
869 // follow text flow
870 const bool bInFtn = rAnchorTxtFrm.IsInFtn();
871 while( bMoveable && nDist < 0 )
873 bool bInSct = pUpperOfOrientFrm->IsInSct();
874 if ( bInSct )
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.
884 if ( nDist >= 0 )
886 break;
888 // <--
890 if ( !bInSct &&
891 (GetAnchoredObj().GetObjRect().*fnRect->fnGetTop)() ==
892 (pUpperOfOrientFrm->*fnRect->fnGetPrtTop)() )
893 //Das teil passt nimmer, da hilft auch kein moven.
894 break;
896 const SwLayoutFrm* pNextLay = pUpperOfOrientFrm->GetLeaf(
897 ( bInSct
898 ? MAKEPAGE_NOSECTION
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() )
906 pNextLay = 0L;
908 if ( pNextLay )
910 SWRECTFNX( pNextLay )
911 if ( !bInSct ||
912 ( pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pNextLay->FindSctFrm() ) &&
913 (pNextLay->Prt().*fnRectX->fnGetHeight)() ) )
915 SwTwips nTmpRelPosY =
916 (*fnRect->fnYDiff)( (pNextLay->*fnRect->fnGetPrtTop)(),
917 nTopOfAnch );
918 if ( bVert )
919 aRelPos.X() = nTmpRelPosY;
920 else
921 aRelPos.Y() = nTmpRelPosY;
922 pUpperOfOrientFrm = pNextLay;
923 SWREFRESHFN( pUpperOfOrientFrm )
924 bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm );
925 if( bVertX )
926 GetAnchoredObj().SetObjLeft( nTopOfAnch -
927 aRelPos.X() -
928 aObjBoundRect.Width() );
929 else
930 GetAnchoredObj().SetObjTop( nTopOfAnch +
931 aRelPos.Y() );
932 nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
933 (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
935 // --> OD 2004-11-01 #i23129# - leave section area
936 else if ( bInSct )
938 const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
939 nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
940 (pTmp->*fnRect->fnGetPrtBottom)() );
941 if( nDist < 0 )
942 pUpperOfOrientFrm = pTmp;
943 else
944 break;
946 // <--
948 else if ( bInSct )
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)() );
955 if( nDist < 0 )
956 pUpperOfOrientFrm = pTmp;
957 else
958 break;
960 else
961 bMoveable = false;
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 );
979 if( bVert )
980 GetAnchoredObj().SetObjLeft( nTopOfAnch -
981 aRelPos.X() - aObjBoundRect.Width() );
982 else
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 )
990 : pOrientFrm;
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
1001 if ( bVert )
1003 aRelPos.Y() = nRelPosX;
1004 maOffsetToFrmAnchorPos.Y() = nHoriOffsetToFrmAnchorPos;
1006 else
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 );
1029 if( bVert )
1031 GetAnchoredObj().SetObjLeft( nTopOfAnch -
1032 aRelPos.X() - aObjBoundRect.Width() );
1033 GetAnchoredObj().SetObjTop( rAnchorTxtFrm.Frm().Top() +
1034 aRelPos.Y() );
1036 else
1038 GetAnchoredObj().SetObjLeft( rAnchorTxtFrm.Frm().Left() +
1039 aRelPos.X() );
1040 GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
1043 // set relative position at object
1044 GetAnchoredObj().SetCurrRelPos( aRelPos );
1047 /** determine frame for horizontal position
1049 @author OD
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();
1060 while ( pFrm )
1062 if ( pFrm->IsCntntFrm() &&
1063 GetAnchorTxtFrm().IsAnFollow( static_cast<const SwCntntFrm*>(pFrm) ) )
1065 pHoriVirtAnchFrm = pFrm;
1066 break;
1068 pFrm = pFrm->GetNext();
1071 return *pHoriVirtAnchFrm;
1074 const SwLayoutFrm& SwToCntntAnchoredObjectPosition::GetVertPosOrientFrm() const
1076 return *mpVertPosOrientFrm;