merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / layout / objectformatter.cxx
blobded11f9796693d3d932912abecd1797420414a9e
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: objectformatter.cxx,v $
10 * $Revision: 1.14 $
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 <objectformatter.hxx>
34 #include <objectformattertxtfrm.hxx>
35 #include <objectformatterlayfrm.hxx>
36 #include <anchoredobject.hxx>
37 #include <anchoreddrawobject.hxx>
38 #include <sortedobjs.hxx>
39 #include <pagefrm.hxx>
40 #include <flyfrms.hxx>
41 #include <txtfrm.hxx>
42 #include <layact.hxx>
43 #include <frmfmt.hxx>
44 #include <fmtanchr.hxx>
45 #include <doc.hxx>
47 #include <vector>
49 // =============================================================================
50 // helper class <SwPageNumAndTypeOfAnchors>
51 // --> OD 2004-10-04 #i26945# - Additionally the type of the anchor text frame
52 // is collected - by type is meant 'master' or 'follow'.
53 // =============================================================================
54 class SwPageNumAndTypeOfAnchors
56 private:
57 struct tEntry
59 SwAnchoredObject* mpAnchoredObj;
60 sal_uInt32 mnPageNumOfAnchor;
61 bool mbAnchoredAtMaster;
64 std::vector< tEntry* > maObjList;
66 public:
67 inline SwPageNumAndTypeOfAnchors()
70 inline ~SwPageNumAndTypeOfAnchors()
72 for ( std::vector< tEntry* >::iterator aIter = maObjList.begin();
73 aIter != maObjList.end(); ++aIter )
75 delete (*aIter);
77 maObjList.clear();
80 inline void Collect( SwAnchoredObject& _rAnchoredObj )
82 tEntry* pNewEntry = new tEntry();
83 pNewEntry->mpAnchoredObj = &_rAnchoredObj;
84 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
85 // is replaced by method <FindPageFrmOfAnchor()>. It's return value
86 // have to be checked.
87 SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
88 if ( pPageFrmOfAnchor )
90 pNewEntry->mnPageNumOfAnchor = pPageFrmOfAnchor->GetPhyPageNum();
92 else
94 pNewEntry->mnPageNumOfAnchor = 0;
96 // <--
97 // --> OD 2004-10-04 #i26945# - collect type of anchor
98 SwTxtFrm* pAnchorCharFrm = _rAnchoredObj.FindAnchorCharFrm();
99 if ( pAnchorCharFrm )
101 pNewEntry->mbAnchoredAtMaster = !pAnchorCharFrm->IsFollow();
103 else
105 pNewEntry->mbAnchoredAtMaster = true;
107 // <--
108 maObjList.push_back( pNewEntry );
111 inline SwAnchoredObject* operator[]( sal_uInt32 _nIndex )
113 SwAnchoredObject* bRetObj = 0L;
115 if ( _nIndex < Count())
117 bRetObj = maObjList[_nIndex]->mpAnchoredObj;
120 return bRetObj;
123 inline sal_uInt32 GetPageNum( sal_uInt32 _nIndex )
125 sal_uInt32 nRetPgNum = 0L;
127 if ( _nIndex < Count())
129 nRetPgNum = maObjList[_nIndex]->mnPageNumOfAnchor;
132 return nRetPgNum;
135 // --> OD 2004-10-04 #i26945#
136 inline bool AnchoredAtMaster( sal_uInt32 _nIndex )
138 bool bAnchoredAtMaster( true );
140 if ( _nIndex < Count())
142 bAnchoredAtMaster = maObjList[_nIndex]->mbAnchoredAtMaster;
145 return bAnchoredAtMaster;
147 // <--
149 inline sal_uInt32 Count() const
151 return maObjList.size();
155 // =============================================================================
156 // implementation of class <SwObjectFormatter>
157 // =============================================================================
158 SwObjectFormatter::SwObjectFormatter( const SwPageFrm& _rPageFrm,
159 SwLayAction* _pLayAction,
160 const bool _bCollectPgNumOfAnchors )
161 : mrPageFrm( _rPageFrm ),
162 mbFormatOnlyAsCharAnchored( false ),
163 mbConsiderWrapOnObjPos( _rPageFrm.GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ),
164 mpLayAction( _pLayAction ),
165 // --> OD 2004-10-04 #i26945#
166 mpPgNumAndTypeOfAnchors( _bCollectPgNumOfAnchors ? new SwPageNumAndTypeOfAnchors() : 0L )
167 // <--
171 SwObjectFormatter::~SwObjectFormatter()
173 delete mpPgNumAndTypeOfAnchors;
176 SwObjectFormatter* SwObjectFormatter::CreateObjFormatter(
177 SwFrm& _rAnchorFrm,
178 const SwPageFrm& _rPageFrm,
179 SwLayAction* _pLayAction )
181 SwObjectFormatter* pObjFormatter = 0L;
182 if ( _rAnchorFrm.IsTxtFrm() )
184 pObjFormatter = SwObjectFormatterTxtFrm::CreateObjFormatter(
185 static_cast<SwTxtFrm&>(_rAnchorFrm),
186 _rPageFrm, _pLayAction );
188 else if ( _rAnchorFrm.IsLayoutFrm() )
190 pObjFormatter = SwObjectFormatterLayFrm::CreateObjFormatter(
191 static_cast<SwLayoutFrm&>(_rAnchorFrm),
192 _rPageFrm, _pLayAction );
194 else
196 ASSERT( false,
197 "<SwObjectFormatter::CreateObjFormatter(..)> - unexcepted type of anchor frame" );
200 return pObjFormatter;
203 /** method to format all floating screen objects at the given anchor frame
205 @author OD
207 bool SwObjectFormatter::FormatObjsAtFrm( SwFrm& _rAnchorFrm,
208 const SwPageFrm& _rPageFrm,
209 SwLayAction* _pLayAction )
211 bool bSuccess( true );
213 // create corresponding object formatter
214 SwObjectFormatter* pObjFormatter =
215 SwObjectFormatter::CreateObjFormatter( _rAnchorFrm, _rPageFrm, _pLayAction );
217 if ( pObjFormatter )
219 // format anchored floating screen objects
220 bSuccess = pObjFormatter->DoFormatObjs();
222 delete pObjFormatter;
224 return bSuccess;
227 /** method to format a given floating screen object
229 @author OD
231 bool SwObjectFormatter::FormatObj( SwAnchoredObject& _rAnchoredObj,
232 SwFrm* _pAnchorFrm,
233 const SwPageFrm* _pPageFrm,
234 SwLayAction* _pLayAction )
236 bool bSuccess( true );
238 ASSERT( _pAnchorFrm || _rAnchoredObj.GetAnchorFrm(),
239 "<SwObjectFormatter::FormatObj(..)> - missing anchor frame" );
240 SwFrm& rAnchorFrm = _pAnchorFrm ? *(_pAnchorFrm) : *(_rAnchoredObj.AnchorFrm());
242 ASSERT( _pPageFrm || rAnchorFrm.FindPageFrm(),
243 "<SwObjectFormatter::FormatObj(..)> - missing page frame" );
244 const SwPageFrm& rPageFrm = _pPageFrm ? *(_pPageFrm) : *(rAnchorFrm.FindPageFrm());
246 // create corresponding object formatter
247 SwObjectFormatter* pObjFormatter =
248 SwObjectFormatter::CreateObjFormatter( rAnchorFrm, rPageFrm, _pLayAction );
250 if ( pObjFormatter )
252 // format given floating screen object
253 // --> OD 2005-01-10 #i40147# - check for moved forward anchor frame
254 bSuccess = pObjFormatter->DoFormatObj( _rAnchoredObj, true );
255 // <--
257 delete pObjFormatter;
259 return bSuccess;
262 /** helper method for method <_FormatObj(..)> - performs the intrinsic format
263 of the layout of the given layout frame and all its lower layout frames.
265 OD 2004-06-28 #i28701#
266 IMPORTANT NOTE:
267 Method corresponds to methods <SwLayAction::FormatLayoutFly(..)> and
268 <SwLayAction::FormatLayout(..)>. Thus, its code for the formatting have
269 to be synchronised.
271 @author OD
273 void SwObjectFormatter::_FormatLayout( SwLayoutFrm& _rLayoutFrm )
275 _rLayoutFrm.Calc();
277 SwFrm* pLowerFrm = _rLayoutFrm.Lower();
278 while ( pLowerFrm )
280 if ( pLowerFrm->IsLayoutFrm() )
282 _FormatLayout( *(static_cast<SwLayoutFrm*>(pLowerFrm)) );
284 pLowerFrm = pLowerFrm->GetNext();
288 /** helper method for method <_FormatObj(..)> - performs the intrinsic
289 format of the content of the given floating screen object.
291 OD 2004-06-28 #i28701#
293 @author OD
295 void SwObjectFormatter::_FormatObjCntnt( SwAnchoredObject& _rAnchoredObj )
297 if ( !_rAnchoredObj.ISA(SwFlyFrm) )
299 // only Writer fly frames have content
300 return;
303 SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj);
304 SwCntntFrm* pCntnt = rFlyFrm.ContainsCntnt();
306 while ( pCntnt )
308 // format content
309 pCntnt->OptCalc();
311 // format floating screen objects at content text frame
312 // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame to
313 // the object formatter
314 if ( pCntnt->IsTxtFrm() &&
315 !SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
316 *(pCntnt->FindPageFrm()),
317 GetLayAction() ) )
318 // <--
320 // restart format with first content
321 pCntnt = rFlyFrm.ContainsCntnt();
322 continue;
325 // continue with next content
326 pCntnt = pCntnt->GetNextCntntFrm();
330 /** performs the intrinsic format of a given floating screen object and its content.
332 OD 2004-06-28 #i28701#
334 @author OD
336 void SwObjectFormatter::_FormatObj( SwAnchoredObject& _rAnchoredObj )
338 // check, if only as-character anchored object have to be formatted, and
339 // check the anchor type
340 if ( FormatOnlyAsCharAnchored() &&
341 !_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_IN_CNTNT )
343 return;
346 // collect anchor object and its 'anchor' page number, if requested
347 if ( mpPgNumAndTypeOfAnchors )
349 mpPgNumAndTypeOfAnchors->Collect( _rAnchoredObj );
352 if ( _rAnchoredObj.ISA(SwFlyFrm) )
354 SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj);
355 // --> OD 2004-11-15 #i34753# - reset flag, which prevents a positioning
356 if ( rFlyFrm.IsFlyLayFrm() )
358 static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( false );
360 // <--
362 // FME 2007-08-30 #i81146# new loop control
363 USHORT nLoopControlRuns = 0;
364 const USHORT nLoopControlMax = 15;
366 do {
367 if ( mpLayAction )
369 mpLayAction->FormatLayoutFly( &rFlyFrm );
370 // --> OD 2005-07-13 #124218# - consider, if the layout action
371 // has to be restarted due to a delete of a page frame.
372 if ( mpLayAction->IsAgain() )
374 break;
376 // <--
378 else
380 _FormatLayout( rFlyFrm );
382 // --> OD 2004-11-15 #i34753# - prevent further positioning, if
383 // to-page|to-fly anchored Writer fly frame is already clipped.
384 if ( rFlyFrm.IsFlyLayFrm() && rFlyFrm.IsClipped() )
386 static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( true );
388 // <--
389 // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
390 // to the object formatter
391 SwObjectFormatter::FormatObjsAtFrm( rFlyFrm,
392 *(rFlyFrm.FindPageFrm()),
393 mpLayAction );
394 // <--
395 if ( mpLayAction )
397 mpLayAction->_FormatFlyCntnt( &rFlyFrm );
398 // --> OD 2005-07-13 #124218# - consider, if the layout action
399 // has to be restarted due to a delete of a page frame.
400 if ( mpLayAction->IsAgain() )
402 break;
404 // <--
406 else
408 _FormatObjCntnt( rFlyFrm );
411 if ( ++nLoopControlRuns >= nLoopControlMax )
413 #if OSL_DEBUG_LEVEL > 1
414 ASSERT( false, "LoopControl in SwObjectFormatter::_FormatObj: Stage 3!!!" );
415 #endif
416 rFlyFrm.ValidateThisAndAllLowers( 2 );
417 nLoopControlRuns = 0;
420 // --> OD 2006-02-02 #i57917#
421 // stop formatting of anchored object, if restart of layout process is requested.
422 } while ( !rFlyFrm.IsValid() &&
423 !_rAnchoredObj.RestartLayoutProcess() &&
424 rFlyFrm.GetAnchorFrm() == &GetAnchorFrm() );
425 // <--
427 else if ( _rAnchoredObj.ISA(SwAnchoredDrawObject) )
429 _rAnchoredObj.MakeObjPos();
433 /** invokes the intrinsic format method for all floating screen objects,
434 anchored at anchor frame on the given page frame
436 OD 2004-06-28 #i28701#
437 OD 2004-10-08 #i26945# - for format of floating screen objects for
438 follow text frames, the 'master' text frame is passed to the method.
439 Thus, the objects, whose anchor character is inside the follow text
440 frame can be formatted.
442 @author OD
444 bool SwObjectFormatter::_FormatObjsAtFrm( SwTxtFrm* _pMasterTxtFrm )
446 // --> OD 2004-10-08 #i26945#
447 SwFrm* pAnchorFrm( 0L );
448 if ( GetAnchorFrm().IsTxtFrm() &&
449 static_cast<SwTxtFrm&>(GetAnchorFrm()).IsFollow() &&
450 _pMasterTxtFrm )
452 pAnchorFrm = _pMasterTxtFrm;
454 else
456 pAnchorFrm = &GetAnchorFrm();
458 // <--
459 if ( !pAnchorFrm->GetDrawObjs() )
461 // nothing to do, if no floating screen object is registered at the anchor frame.
462 return true;
465 bool bSuccess( true );
467 sal_uInt32 i = 0;
468 for ( ; i < pAnchorFrm->GetDrawObjs()->Count(); ++i )
470 SwAnchoredObject* pAnchoredObj = (*pAnchorFrm->GetDrawObjs())[i];
472 // check, if object's anchor is on the given page frame or
473 // object is registered at the given page frame.
474 // --> OD 2004-10-05 #i26945# - check, if the anchor character of the
475 // anchored object is located in a follow text frame. If this anchor
476 // follow text frame differs from the given anchor frame, the given
477 // anchor frame is a 'master' text frame of the anchor follow text frame.
478 // If the anchor follow text frame is in the same body as its 'master'
479 // text frame, do not format the anchored object.
480 // E.g., this situation can occur during the table row splitting algorithm.
481 SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm();
482 const bool bAnchoredAtFollowInSameBodyAsMaster =
483 pAnchorCharFrm && pAnchorCharFrm->IsFollow() &&
484 pAnchorCharFrm != pAnchoredObj->GetAnchorFrm() &&
485 pAnchorCharFrm->FindBodyFrm() ==
486 static_cast<SwTxtFrm*>(pAnchoredObj->AnchorFrm())->FindBodyFrm();
487 if ( bAnchoredAtFollowInSameBodyAsMaster )
489 continue;
491 // <--
492 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
493 // is replaced by method <FindPageFrmOfAnchor()>. It's return value
494 // have to be checked.
495 SwPageFrm* pPageFrmOfAnchor = pAnchoredObj->FindPageFrmOfAnchor();
496 ASSERT( pPageFrmOfAnchor,
497 "<SwObjectFormatter::_FormatObjsAtFrm()> - missing page frame." );
498 // --> OD 2004-10-08 #i26945#
499 if ( pPageFrmOfAnchor && pPageFrmOfAnchor == &mrPageFrm )
500 // <--
502 // if format of object fails, stop formatting and pass fail to
503 // calling method via the return value.
504 if ( !DoFormatObj( *pAnchoredObj ) )
506 bSuccess = false;
507 break;
510 // considering changes at <pAnchorFrm->GetDrawObjs()> during
511 // format of the object.
512 if ( !pAnchorFrm->GetDrawObjs() ||
513 i > pAnchorFrm->GetDrawObjs()->Count() )
515 break;
517 else
519 sal_uInt32 nActPosOfObj =
520 pAnchorFrm->GetDrawObjs()->ListPosOf( *pAnchoredObj );
521 if ( nActPosOfObj == pAnchorFrm->GetDrawObjs()->Count() ||
522 nActPosOfObj > i )
524 --i;
526 else if ( nActPosOfObj < i )
528 i = nActPosOfObj;
532 } // end of loop on <pAnchorFrm->.GetDrawObjs()>
534 return bSuccess;
537 /** accessor to collected anchored object
539 OD 2004-07-05 #i28701#
541 @author OD
543 SwAnchoredObject* SwObjectFormatter::GetCollectedObj( const sal_uInt32 _nIndex )
545 return mpPgNumAndTypeOfAnchors ? (*mpPgNumAndTypeOfAnchors)[_nIndex] : 0L;
548 /** accessor to 'anchor' page number of collected anchored object
550 OD 2004-07-05 #i28701#
552 @author OD
554 sal_uInt32 SwObjectFormatter::GetPgNumOfCollected( const sal_uInt32 _nIndex )
556 return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->GetPageNum(_nIndex) : 0L;
559 /** accessor to 'anchor' type of collected anchored object
561 OD 2004-10-04 #i26945#
563 @author OD
565 bool SwObjectFormatter::IsCollectedAnchoredAtMaster( const sal_uInt32 _nIndex )
567 return mpPgNumAndTypeOfAnchors
568 ? mpPgNumAndTypeOfAnchors->AnchoredAtMaster(_nIndex)
569 : true;
572 /** accessor to total number of collected anchored objects
574 OD 2004-07-05 #i28701#
576 @author OD
578 sal_uInt32 SwObjectFormatter::CountOfCollected()
580 return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->Count() : 0L;