Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <objectformattertxtfrm.hxx>
21 : #include <anchoredobject.hxx>
22 : #include <sortedobjs.hxx>
23 : #include <flyfrms.hxx>
24 : #include <txtfrm.hxx>
25 : #include <pagefrm.hxx>
26 : #include <rowfrm.hxx>
27 : #include <layouter.hxx>
28 : #include <frmfmt.hxx>
29 : #include <fmtanchr.hxx>
30 : #include <fmtwrapinfluenceonobjpos.hxx>
31 : #include <fmtfollowtextflow.hxx>
32 : #include <layact.hxx>
33 :
34 : using namespace ::com::sun::star;
35 :
36 : // =============================================================================
37 :
38 : // little helper class to forbid follow formatting for the given text frame
39 : class SwForbidFollowFormat
40 : {
41 : private:
42 : SwTxtFrm& mrTxtFrm;
43 : const bool bOldFollowFormatAllowed;
44 :
45 : public:
46 0 : SwForbidFollowFormat( SwTxtFrm& _rTxtFrm )
47 : : mrTxtFrm( _rTxtFrm ),
48 0 : bOldFollowFormatAllowed( _rTxtFrm.FollowFormatAllowed() )
49 : {
50 0 : mrTxtFrm.ForbidFollowFormat();
51 0 : }
52 :
53 0 : ~SwForbidFollowFormat()
54 : {
55 0 : if ( bOldFollowFormatAllowed )
56 : {
57 0 : mrTxtFrm.AllowFollowFormat();
58 : }
59 0 : }
60 : };
61 :
62 : // =============================================================================
63 : // implementation of class <SwObjectFormatterTxtFrm>
64 : // =============================================================================
65 718 : SwObjectFormatterTxtFrm::SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
66 : const SwPageFrm& _rPageFrm,
67 : SwTxtFrm* _pMasterAnchorTxtFrm,
68 : SwLayAction* _pLayAction )
69 : : SwObjectFormatter( _rPageFrm, _pLayAction, true ),
70 : mrAnchorTxtFrm( _rAnchorTxtFrm ),
71 718 : mpMasterAnchorTxtFrm( _pMasterAnchorTxtFrm )
72 : {
73 718 : }
74 :
75 1436 : SwObjectFormatterTxtFrm::~SwObjectFormatterTxtFrm()
76 : {
77 1436 : }
78 :
79 2705 : SwObjectFormatterTxtFrm* SwObjectFormatterTxtFrm::CreateObjFormatter(
80 : SwTxtFrm& _rAnchorTxtFrm,
81 : const SwPageFrm& _rPageFrm,
82 : SwLayAction* _pLayAction )
83 : {
84 2705 : SwObjectFormatterTxtFrm* pObjFormatter = 0L;
85 :
86 : // determine 'master' of <_rAnchorTxtFrm>, if anchor frame is a follow text frame.
87 2705 : SwTxtFrm* pMasterOfAnchorFrm = 0L;
88 2705 : if ( _rAnchorTxtFrm.IsFollow() )
89 : {
90 0 : pMasterOfAnchorFrm = _rAnchorTxtFrm.FindMaster();
91 0 : while ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->IsFollow() )
92 : {
93 0 : pMasterOfAnchorFrm = pMasterOfAnchorFrm->FindMaster();
94 : }
95 : }
96 :
97 : // create object formatter, if floating screen objects are registered
98 : // at anchor frame (or at 'master' anchor frame)
99 2705 : if ( _rAnchorTxtFrm.GetDrawObjs() ||
100 0 : ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->GetDrawObjs() ) )
101 : {
102 : pObjFormatter =
103 : new SwObjectFormatterTxtFrm( _rAnchorTxtFrm, _rPageFrm,
104 718 : pMasterOfAnchorFrm, _pLayAction );
105 : }
106 :
107 2705 : return pObjFormatter;
108 : }
109 :
110 1486 : SwFrm& SwObjectFormatterTxtFrm::GetAnchorFrm()
111 : {
112 1486 : return mrAnchorTxtFrm;
113 : }
114 :
115 : // #i40147# - add parameter <_bCheckForMovedFwd>.
116 850 : bool SwObjectFormatterTxtFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
117 : const bool _bCheckForMovedFwd )
118 : {
119 : // check, if only as-character anchored object have to be formatted, and
120 : // check the anchor type
121 850 : if ( FormatOnlyAsCharAnchored() &&
122 0 : !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
123 : {
124 0 : return true;
125 : }
126 :
127 : // consider, if the layout action has to be
128 : // restarted due to a delete of a page frame.
129 850 : if ( GetLayAction() && GetLayAction()->IsAgain() )
130 : {
131 0 : return false;
132 : }
133 :
134 850 : bool bSuccess( true );
135 :
136 850 : if ( _rAnchoredObj.IsFormatPossible() )
137 : {
138 850 : _rAnchoredObj.SetRestartLayoutProcess( false );
139 :
140 850 : _FormatObj( _rAnchoredObj );
141 : // consider, if the layout action has to be
142 : // restarted due to a delete of a page frame.
143 850 : if ( GetLayAction() && GetLayAction()->IsAgain() )
144 : {
145 0 : return false;
146 : }
147 :
148 : // check, if layout process has to be restarted.
149 : // if yes, perform needed invalidations.
150 :
151 : // no restart of layout process,
152 : // if anchored object is anchored inside a Writer fly frame,
153 : // its position is already locked, and it follows the text flow.
154 : const bool bRestart =
155 850 : _rAnchoredObj.RestartLayoutProcess() &&
156 2 : !( _rAnchoredObj.PositionLocked() &&
157 0 : _rAnchoredObj.GetAnchorFrm()->IsInFly() &&
158 852 : _rAnchoredObj.GetFrmFmt().GetFollowTextFlow().GetValue() );
159 850 : if ( bRestart )
160 : {
161 2 : bSuccess = false;
162 2 : _InvalidatePrevObjs( _rAnchoredObj );
163 2 : _InvalidateFollowObjs( _rAnchoredObj, true );
164 : }
165 :
166 : // format anchor text frame, if wrapping style influence of the object
167 : // has to be considered and it's <NONE_SUCCESSIVE_POSITIONED>
168 : // #i3317# - consider also anchored objects, whose
169 : // wrapping style influence is temporarly considered.
170 : // #i40147# - consider also anchored objects, for
171 : // whose the check of a moved forward anchor frame is requested.
172 : // revise decision made for i3317:
173 : // anchored objects, whose wrapping style influence is temporarly considered,
174 : // have to be considered in method <SwObjectFormatterTxtFrm::DoFormatObjs()>
175 1702 : if ( bSuccess &&
176 848 : _rAnchoredObj.ConsiderObjWrapInfluenceOnObjPos() &&
177 : ( _bCheckForMovedFwd ||
178 4 : _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
179 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
180 4 : GetWrapInfluenceOnObjPos( true ) ==
181 : // #i35017# - constant name has changed
182 : text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) )
183 : {
184 : // #i26945# - check conditions for move forward of
185 : // anchor text frame
186 : // determine, if anchor text frame has previous frame
187 0 : const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
188 :
189 : // #i40141# - use new method - it also formats the
190 : // section the anchor frame is in.
191 0 : _FormatAnchorFrmForCheckMoveFwd();
192 :
193 : // #i35911#
194 0 : if ( _rAnchoredObj.HasClearedEnvironment() )
195 : {
196 0 : _rAnchoredObj.SetClearedEnvironment( true );
197 : // #i44049# - consider, that anchor frame
198 : // could already been marked to move forward.
199 0 : SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
200 0 : if ( pAnchorPageFrm != _rAnchoredObj.GetPageFrm() )
201 : {
202 0 : bool bInsert( true );
203 0 : sal_uInt32 nToPageNum( 0L );
204 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
205 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
206 0 : rDoc, mrAnchorTxtFrm, nToPageNum ) )
207 : {
208 0 : if ( nToPageNum < pAnchorPageFrm->GetPhyPageNum() )
209 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
210 : else
211 0 : bInsert = false;
212 : }
213 0 : if ( bInsert )
214 : {
215 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
216 0 : pAnchorPageFrm->GetPhyPageNum() );
217 0 : mrAnchorTxtFrm.InvalidatePos();
218 0 : bSuccess = false;
219 0 : _InvalidatePrevObjs( _rAnchoredObj );
220 0 : _InvalidateFollowObjs( _rAnchoredObj, true );
221 : }
222 : else
223 : {
224 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
225 : }
226 : }
227 : }
228 0 : else if ( !mrAnchorTxtFrm.IsFollow() && bDoesAnchorHadPrev )
229 : {
230 : // index of anchored object in collection of page numbers and
231 : // anchor types
232 0 : sal_uInt32 nIdx( CountOfCollected() );
233 : OSL_ENSURE( nIdx > 0,
234 : "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchored object not collected!?" );
235 0 : --nIdx;
236 :
237 0 : sal_uInt32 nToPageNum( 0L );
238 : // #i43913#
239 0 : bool bDummy( false );
240 : // #i58182# - consider new method signature
241 0 : if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( nIdx ),
242 : GetPgNumOfCollected( nIdx ),
243 0 : IsCollectedAnchoredAtMaster( nIdx ),
244 0 : nToPageNum, bDummy ) )
245 : {
246 : // #i49987# - consider, that anchor frame
247 : // could already been marked to move forward.
248 0 : bool bInsert( true );
249 0 : sal_uInt32 nMovedFwdToPageNum( 0L );
250 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
251 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
252 0 : rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
253 : {
254 0 : if ( nMovedFwdToPageNum < nToPageNum )
255 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
256 : else
257 0 : bInsert = false;
258 : }
259 0 : if ( bInsert )
260 : {
261 : // Indicate that anchor text frame has to move forward and
262 : // invalidate its position to force a re-format.
263 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
264 0 : nToPageNum );
265 0 : mrAnchorTxtFrm.InvalidatePos();
266 :
267 : // Indicate restart of the layout process
268 0 : bSuccess = false;
269 :
270 : // If needed, invalidate previous objects anchored at same anchor
271 : // text frame.
272 0 : _InvalidatePrevObjs( _rAnchoredObj );
273 :
274 : // Invalidate object and following objects for the restart of the
275 : // layout process
276 0 : _InvalidateFollowObjs( _rAnchoredObj, true );
277 : }
278 : else
279 : {
280 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
281 : }
282 : }
283 : }
284 : // i40155# - mark anchor frame not to wrap around
285 : // objects under the condition, that its follow contains all its text.
286 0 : else if ( !mrAnchorTxtFrm.IsFollow() &&
287 0 : mrAnchorTxtFrm.GetFollow() &&
288 0 : mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
289 : {
290 : SwLayouter::RemoveMovedFwdFrm(
291 0 : *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
292 0 : mrAnchorTxtFrm );
293 : }
294 : }
295 : }
296 :
297 850 : return bSuccess;
298 : }
299 :
300 408 : bool SwObjectFormatterTxtFrm::DoFormatObjs()
301 : {
302 408 : if ( !mrAnchorTxtFrm.IsValid() )
303 : {
304 0 : if ( GetLayAction() &&
305 0 : mrAnchorTxtFrm.FindPageFrm() != &GetPageFrm() )
306 : {
307 : // notify layout action, thus is can restart the layout process on
308 : // a previous page.
309 0 : GetLayAction()->SetAgain();
310 : }
311 : else
312 : {
313 : // the anchor text frame has to be valid, thus assert.
314 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs()> called for invalidate anchor text frame." );
315 : }
316 :
317 0 : return false;
318 : }
319 :
320 408 : bool bSuccess( true );
321 :
322 408 : if ( mrAnchorTxtFrm.IsFollow() )
323 : {
324 : // Only floating screen objects anchored as-character are directly
325 : // registered at a follow text frame. The other floating screen objects
326 : // are registered at the 'master' anchor text frame.
327 : // Thus, format the other floating screen objects through the 'master'
328 : // anchor text frame
329 : OSL_ENSURE( mpMasterAnchorTxtFrm,
330 : "SwObjectFormatterTxtFrm::DoFormatObjs() - missing 'master' anchor text frame" );
331 0 : bSuccess = _FormatObjsAtFrm( mpMasterAnchorTxtFrm );
332 :
333 0 : if ( bSuccess )
334 : {
335 : // format of as-character anchored floating screen objects - no failure
336 : // excepted on the format of these objects.
337 0 : bSuccess = _FormatObjsAtFrm();
338 : }
339 : }
340 : else
341 : {
342 408 : bSuccess = _FormatObjsAtFrm();
343 : }
344 :
345 : // consider anchored objects, whose wrapping style influence are temporarly
346 : // considered.
347 1318 : if ( bSuccess &&
348 406 : ( ConsiderWrapOnObjPos() ||
349 252 : ( !mrAnchorTxtFrm.IsFollow() &&
350 252 : _AtLeastOneObjIsTmpConsiderWrapInfluence() ) ) )
351 : {
352 154 : const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
353 :
354 : // Format anchor text frame after its objects are formatted.
355 : // Note: The format of the anchor frame also formats the invalid
356 : // previous frames of the anchor frame. The format of the previous
357 : // frames is needed to get a correct result of format of the
358 : // anchor frame for the following check for moved forward anchors
359 : // #i40141# - use new method - it also formats the
360 : // section the anchor frame is in.
361 154 : _FormatAnchorFrmForCheckMoveFwd();
362 :
363 154 : sal_uInt32 nToPageNum( 0L );
364 : // #i43913#
365 154 : bool bInFollow( false );
366 154 : SwAnchoredObject* pObj = 0L;
367 154 : if ( !mrAnchorTxtFrm.IsFollow() )
368 : {
369 : pObj = _GetFirstObjWithMovedFwdAnchor(
370 : // #i35017# - constant name has changed
371 : text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
372 154 : nToPageNum, bInFollow );
373 : }
374 : // #i35911#
375 154 : if ( pObj && pObj->HasClearedEnvironment() )
376 : {
377 0 : pObj->SetClearedEnvironment( true );
378 : // #i44049# - consider, that anchor frame
379 : // could already been marked to move forward.
380 0 : SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
381 : // #i43913# - consider, that anchor frame
382 : // is a follow or is in a follow row, which will move forward.
383 0 : if ( pAnchorPageFrm != pObj->GetPageFrm() ||
384 : bInFollow )
385 : {
386 0 : bool bInsert( true );
387 0 : sal_uInt32 nTmpToPageNum( 0L );
388 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
389 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
390 0 : rDoc, mrAnchorTxtFrm, nTmpToPageNum ) )
391 : {
392 0 : if ( nTmpToPageNum < pAnchorPageFrm->GetPhyPageNum() )
393 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
394 : else
395 0 : bInsert = false;
396 : }
397 0 : if ( bInsert )
398 : {
399 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
400 0 : pAnchorPageFrm->GetPhyPageNum() );
401 0 : mrAnchorTxtFrm.InvalidatePos();
402 0 : bSuccess = false;
403 0 : _InvalidatePrevObjs( *pObj );
404 0 : _InvalidateFollowObjs( *pObj, true );
405 : }
406 : else
407 : {
408 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
409 : }
410 : }
411 : }
412 154 : else if ( pObj && bDoesAnchorHadPrev )
413 : {
414 : // Object found, whose anchor is moved forward
415 :
416 : // #i49987# - consider, that anchor frame
417 : // could already been marked to move forward.
418 0 : bool bInsert( true );
419 0 : sal_uInt32 nMovedFwdToPageNum( 0L );
420 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
421 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
422 0 : rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
423 : {
424 0 : if ( nMovedFwdToPageNum < nToPageNum )
425 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
426 : else
427 0 : bInsert = false;
428 : }
429 0 : if ( bInsert )
430 : {
431 : // Indicate that anchor text frame has to move forward and
432 : // invalidate its position to force a re-format.
433 0 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm, nToPageNum );
434 0 : mrAnchorTxtFrm.InvalidatePos();
435 :
436 : // Indicate restart of the layout process
437 0 : bSuccess = false;
438 :
439 : // If needed, invalidate previous objects anchored at same anchor
440 : // text frame.
441 0 : _InvalidatePrevObjs( *pObj );
442 :
443 : // Invalidate object and following objects for the restart of the
444 : // layout process
445 0 : _InvalidateFollowObjs( *pObj, true );
446 : }
447 : else
448 : {
449 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
450 0 : }
451 : }
452 : // #i40155# - mark anchor frame not to wrap around
453 : // objects under the condition, that its follow contains all its text.
454 308 : else if ( !mrAnchorTxtFrm.IsFollow() &&
455 154 : mrAnchorTxtFrm.GetFollow() &&
456 0 : mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
457 : {
458 : SwLayouter::RemoveMovedFwdFrm(
459 0 : *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
460 0 : mrAnchorTxtFrm );
461 : }
462 : }
463 :
464 408 : return bSuccess;
465 : }
466 :
467 2 : void SwObjectFormatterTxtFrm::_InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj )
468 : {
469 : // invalidate all previous objects, whose wrapping influence on the object
470 : // positioning is <NONE_CONCURRENT_POSIITIONED>.
471 : // Note: list of objects at anchor frame is sorted by this property.
472 4 : if ( _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
473 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
474 2 : GetWrapInfluenceOnObjPos( true ) ==
475 : // #i35017# - constant name has changed
476 : text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
477 : {
478 2 : const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
479 2 : if ( pObjs )
480 : {
481 : // determine start index
482 2 : sal_Int32 i = pObjs->ListPosOf( _rAnchoredObj ) - 1;
483 2 : for ( ; i >= 0; --i )
484 : {
485 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
486 0 : if ( pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
487 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
488 0 : GetWrapInfluenceOnObjPos( true ) ==
489 : // #i35017# - constant name has changed
490 : text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
491 : {
492 0 : pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
493 : }
494 : }
495 : }
496 : }
497 2 : }
498 :
499 2 : void SwObjectFormatterTxtFrm::_InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
500 : const bool _bInclObj )
501 : {
502 2 : if ( _bInclObj )
503 : {
504 2 : _rAnchoredObj.InvalidateObjPosForConsiderWrapInfluence( true );
505 : }
506 :
507 2 : const SwSortedObjs* pObjs = GetPageFrm().GetSortedObjs();
508 2 : if ( pObjs )
509 : {
510 : // determine start index
511 2 : sal_uInt32 i = pObjs->ListPosOf( _rAnchoredObj ) + 1;
512 2 : for ( ; i < pObjs->Count(); ++i )
513 : {
514 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
515 0 : pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
516 : }
517 : }
518 2 : }
519 :
520 154 : SwAnchoredObject* SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(
521 : const sal_Int16 _nWrapInfluenceOnPosition,
522 : sal_uInt32& _noToPageNum,
523 : bool& _boInFollow )
524 : {
525 : // #i35017# - constant names have changed
526 : OSL_ENSURE( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
527 : _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
528 : "<SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(..)> - invalid value for parameter <_nWrapInfluenceOnPosition>" );
529 :
530 154 : SwAnchoredObject* pRetAnchoredObj = 0L;
531 :
532 154 : sal_uInt32 i = 0L;
533 380 : for ( ; i < CountOfCollected(); ++i )
534 : {
535 226 : SwAnchoredObject* pAnchoredObj = GetCollectedObj(i);
536 230 : if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() &&
537 4 : pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
538 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
539 4 : GetWrapInfluenceOnObjPos( true ) == _nWrapInfluenceOnPosition )
540 : {
541 : // #i26945# - use new method <_CheckMovedFwdCondition(..)>
542 : // #i43913#
543 : // #i58182# - consider new method signature
544 4 : if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( i ),
545 : GetPgNumOfCollected( i ),
546 4 : IsCollectedAnchoredAtMaster( i ),
547 4 : _noToPageNum, _boInFollow ) )
548 : {
549 0 : pRetAnchoredObj = pAnchoredObj;
550 0 : break;
551 : }
552 : }
553 : }
554 :
555 154 : return pRetAnchoredObj;
556 : }
557 :
558 : // #i58182#
559 : // - replace private method by corresponding static public method
560 82 : bool SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
561 : SwAnchoredObject& _rAnchoredObj,
562 : const sal_uInt32 _nFromPageNum,
563 : const bool _bAnchoredAtMasterBeforeFormatAnchor,
564 : sal_uInt32& _noToPageNum,
565 : bool& _boInFollow )
566 : {
567 82 : bool bAnchorIsMovedForward( false );
568 :
569 82 : SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
570 82 : if ( pPageFrmOfAnchor )
571 : {
572 82 : const sal_uInt32 nPageNum = pPageFrmOfAnchor->GetPhyPageNum();
573 82 : if ( nPageNum > _nFromPageNum )
574 : {
575 0 : _noToPageNum = nPageNum;
576 : // Handling of special case:
577 : // If anchor frame is move forward into a follow flow row,
578 : // <_noToPageNum> is set to <_nFromPageNum + 1>, because it is
579 : // possible that the anchor page frame isn't valid, because the
580 : // page distance between master row and follow flow row is greater
581 : // than 1.
582 0 : if ( _noToPageNum > (_nFromPageNum + 1) )
583 : {
584 0 : SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
585 0 : if ( pAnchorFrm->IsInTab() &&
586 0 : pAnchorFrm->IsInFollowFlowRow() )
587 : {
588 0 : _noToPageNum = _nFromPageNum + 1;
589 : }
590 : }
591 0 : bAnchorIsMovedForward = true;
592 : }
593 : }
594 : // #i26945# - check, if an at-paragraph|at-character
595 : // anchored object is now anchored at a follow text frame, which will be
596 : // on the next page. Also check, if an at-character anchored object
597 : // is now anchored at a text frame, which is in a follow flow row,
598 : // which will be on the next page.
599 204 : if ( !bAnchorIsMovedForward &&
600 : _bAnchoredAtMasterBeforeFormatAnchor &&
601 82 : ((_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR) ||
602 40 : (_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_PARA)))
603 : {
604 82 : SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
605 : OSL_ENSURE( pAnchorFrm->IsTxtFrm(),
606 : "<SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..) - wrong type of anchor frame>" );
607 82 : SwTxtFrm* pAnchorTxtFrm = static_cast<SwTxtFrm*>(pAnchorFrm);
608 82 : bool bCheck( false );
609 82 : if ( pAnchorTxtFrm->IsFollow() )
610 : {
611 0 : bCheck = true;
612 : }
613 82 : else if( pAnchorTxtFrm->IsInTab() )
614 : {
615 0 : const SwRowFrm* pMasterRow = pAnchorTxtFrm->IsInFollowFlowRow();
616 0 : if ( pMasterRow &&
617 0 : pMasterRow->FindPageFrm() == pPageFrmOfAnchor )
618 : {
619 0 : bCheck = true;
620 : }
621 : }
622 82 : if ( bCheck )
623 : {
624 : // check, if found text frame will be on the next page
625 : // by checking, if it's in a column, which has no next.
626 0 : SwFrm* pColFrm = pAnchorTxtFrm->FindColFrm();
627 0 : while ( pColFrm && !pColFrm->GetNext() )
628 : {
629 0 : pColFrm = pColFrm->FindColFrm();
630 : }
631 0 : if ( !pColFrm || !pColFrm->GetNext() )
632 : {
633 0 : _noToPageNum = _nFromPageNum + 1;
634 0 : bAnchorIsMovedForward = true;
635 : // #i43913#
636 0 : _boInFollow = true;
637 : }
638 : }
639 : }
640 :
641 82 : return bAnchorIsMovedForward;
642 : }
643 :
644 : // #i40140# - helper method to format layout frames used by
645 : // method <SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()>
646 : // #i44049# - format till a certain lower frame, if provided.
647 28 : static void lcl_FormatCntntOfLayoutFrm( SwLayoutFrm* pLayFrm,
648 : SwFrm* pLastLowerFrm = 0L )
649 : {
650 28 : SwFrm* pLowerFrm = pLayFrm->GetLower();
651 152 : while ( pLowerFrm )
652 : {
653 : // #i44049#
654 120 : if ( pLastLowerFrm && pLowerFrm == pLastLowerFrm )
655 : {
656 24 : break;
657 : }
658 96 : if ( pLowerFrm->IsLayoutFrm() )
659 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pLowerFrm),
660 0 : pLastLowerFrm );
661 : else
662 96 : pLowerFrm->Calc();
663 :
664 96 : pLowerFrm = pLowerFrm->GetNext();
665 : }
666 28 : }
667 :
668 : /** method to format given anchor text frame and its previous frames
669 :
670 : #i56300#
671 : Usage: Needed to check, if the anchor text frame is moved forward
672 : due to the positioning and wrapping of its anchored objects, and
673 : to format the frames, which have become invalid due to the anchored
674 : object formatting in the iterative object positioning algorithm
675 : */
676 232 : void SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm )
677 : {
678 : // #i47014# - no format of section and previous columns
679 : // for follow text frames.
680 232 : if ( !_rAnchorTxtFrm.IsFollow() )
681 : {
682 : // if anchor frame is directly inside a section, format this section and
683 : // its previous frames.
684 : // Note: It's a very simple format without formatting objects.
685 232 : if ( _rAnchorTxtFrm.IsInSct() )
686 : {
687 24 : SwFrm* pSectFrm = _rAnchorTxtFrm.GetUpper();
688 48 : while ( pSectFrm )
689 : {
690 24 : if ( pSectFrm->IsSctFrm() || pSectFrm->IsCellFrm() )
691 : {
692 24 : break;
693 : }
694 0 : pSectFrm = pSectFrm->GetUpper();
695 : }
696 24 : if ( pSectFrm && pSectFrm->IsSctFrm() )
697 : {
698 : // #i44049#
699 24 : _rAnchorTxtFrm.LockJoin();
700 24 : SwFrm* pFrm = pSectFrm->GetUpper()->GetLower();
701 : // #i49605# - section frame could move forward
702 : // by the format of its previous frame.
703 : // Thus, check for valid <pFrm>.
704 52 : while ( pFrm && pFrm != pSectFrm )
705 : {
706 4 : if ( pFrm->IsLayoutFrm() )
707 4 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
708 : else
709 0 : pFrm->Calc();
710 :
711 4 : pFrm = pFrm->GetNext();
712 : }
713 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pSectFrm),
714 24 : &_rAnchorTxtFrm );
715 : // #i44049#
716 24 : _rAnchorTxtFrm.UnlockJoin();
717 : }
718 : }
719 :
720 : // #i40140# - if anchor frame is inside a column,
721 : // format the content of the previous columns.
722 : // Note: It's a very simple format without formatting objects.
723 232 : SwFrm* pColFrmOfAnchor = _rAnchorTxtFrm.FindColFrm();
724 232 : if ( pColFrmOfAnchor )
725 : {
726 : // #i44049#
727 0 : _rAnchorTxtFrm.LockJoin();
728 0 : SwFrm* pColFrm = pColFrmOfAnchor->GetUpper()->GetLower();
729 0 : while ( pColFrm != pColFrmOfAnchor )
730 : {
731 0 : SwFrm* pFrm = pColFrm->GetLower();
732 0 : while ( pFrm )
733 : {
734 0 : if ( pFrm->IsLayoutFrm() )
735 0 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
736 : else
737 0 : pFrm->Calc();
738 :
739 0 : pFrm = pFrm->GetNext();
740 : }
741 :
742 0 : pColFrm = pColFrm->GetNext();
743 : }
744 : // #i44049#
745 0 : _rAnchorTxtFrm.UnlockJoin();
746 : }
747 : }
748 :
749 : // format anchor frame - format of its follow not needed
750 : // #i43255# - forbid follow format, only if anchor text
751 : // frame is in table
752 232 : if ( _rAnchorTxtFrm.IsInTab() )
753 : {
754 0 : SwForbidFollowFormat aForbidFollowFormat( _rAnchorTxtFrm );
755 0 : _rAnchorTxtFrm.Calc();
756 : }
757 : else
758 : {
759 232 : _rAnchorTxtFrm.Calc();
760 : }
761 232 : }
762 :
763 : /** method to format the anchor frame for checking of the move forward condition
764 :
765 : #i40141#
766 : */
767 154 : void SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()
768 : {
769 154 : SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( mrAnchorTxtFrm );
770 154 : }
771 :
772 : /** method to determine if at least one anchored object has state
773 : <temporarly consider wrapping style influence> set.
774 : */
775 252 : bool SwObjectFormatterTxtFrm::_AtLeastOneObjIsTmpConsiderWrapInfluence()
776 : {
777 252 : bool bRet( false );
778 :
779 252 : const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
780 252 : if ( pObjs && pObjs->Count() > 1 )
781 : {
782 28 : sal_uInt32 i = 0;
783 116 : for ( ; i < pObjs->Count(); ++i )
784 : {
785 88 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
786 88 : if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
787 : {
788 0 : bRet = true;
789 0 : break;
790 : }
791 : }
792 : }
793 :
794 252 : return bRet;
795 : }
796 :
797 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|