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 "doc.hxx"
21 : #include "pagefrm.hxx"
22 : #include "rootfrm.hxx"
23 : #include "cntfrm.hxx"
24 : #include "dview.hxx"
25 : #include "dflyobj.hxx"
26 : #include "dcontact.hxx"
27 : #include "flyfrm.hxx"
28 : #include "ftnfrm.hxx"
29 : #include "frmtool.hxx"
30 : #include "frmfmt.hxx"
31 : #include "hints.hxx"
32 : #include "pam.hxx"
33 : #include "sectfrm.hxx"
34 :
35 :
36 : #include <svx/svdpage.hxx>
37 : #include <editeng/ulspitem.hxx>
38 : #include <fmtanchr.hxx>
39 : #include <fmtornt.hxx>
40 : #include <fmtfsize.hxx>
41 : #include "ndole.hxx"
42 : #include "tabfrm.hxx"
43 : #include "flyfrms.hxx"
44 : // #i18732#
45 : #include <fmtfollowtextflow.hxx>
46 : #include <environmentofanchoredobject.hxx>
47 : // #i28701#
48 : #include <sortedobjs.hxx>
49 : #include <viewsh.hxx>
50 : #include <viewimp.hxx>
51 :
52 :
53 : using namespace ::com::sun::star;
54 :
55 :
56 : /*************************************************************************
57 : |*
58 : |* SwFlyFreeFrm::SwFlyFreeFrm(), ~SwFlyFreeFrm()
59 : |*
60 : |*************************************************************************/
61 :
62 139 : SwFlyFreeFrm::SwFlyFreeFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
63 : SwFlyFrm( pFmt, pSib, pAnch ),
64 : pPage( 0 ),
65 : // #i34753#
66 : mbNoMakePos( false ),
67 : // #i37068#
68 : mbNoMoveOnCheckClip( false ),
69 139 : maUnclippedFrm( )
70 : {
71 139 : }
72 :
73 278 : SwFlyFreeFrm::~SwFlyFreeFrm()
74 : {
75 : // and goodbye.
76 : // #i28701# - use new method <GetPageFrm()>
77 139 : if( GetPageFrm() )
78 : {
79 13 : if( GetFmt()->GetDoc()->IsInDtor() )
80 : {
81 : // #i29879# - remove also to-frame anchored Writer
82 : // fly frame from page.
83 : const bool bRemoveFromPage =
84 0 : GetPageFrm()->GetSortedObjs() &&
85 0 : ( IsFlyAtCntFrm() ||
86 0 : ( GetAnchorFrm() && GetAnchorFrm()->IsFlyFrm() ) );
87 0 : if ( bRemoveFromPage )
88 : {
89 0 : GetPageFrm()->GetSortedObjs()->Remove( *this );
90 : }
91 : }
92 : else
93 : {
94 13 : SwRect aTmp( GetObjRectWithSpaces() );
95 13 : SwFlyFreeFrm::NotifyBackground( GetPageFrm(), aTmp, PREP_FLY_LEAVE );
96 : }
97 : }
98 139 : }
99 :
100 : // #i28701#
101 11005 : TYPEINIT1(SwFlyFreeFrm,SwFlyFrm);
102 : /*************************************************************************
103 : |*
104 : |* SwFlyFreeFrm::NotifyBackground()
105 : |*
106 : |* Description notifies the background (all CntntFrms that currently
107 : |* are overlapping). Additionally, the window is also directly
108 : |* invalidated (especially where there are no overlapping CntntFrms)
109 : |* This also takes CntntFrms within other Flys into account.
110 : |*
111 : |*************************************************************************/
112 :
113 386 : void SwFlyFreeFrm::NotifyBackground( SwPageFrm *pPageFrm,
114 : const SwRect& rRect, PrepareHint eHint )
115 : {
116 386 : ::Notify_Background( GetVirtDrawObj(), pPageFrm, rRect, eHint, sal_True );
117 386 : }
118 :
119 : /*************************************************************************
120 : |*
121 : |* SwFlyFreeFrm::MakeAll()
122 : |*
123 : |*************************************************************************/
124 :
125 361 : void SwFlyFreeFrm::MakeAll()
126 : {
127 361 : if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
128 : {
129 0 : return;
130 : }
131 :
132 361 : if ( !GetAnchorFrm() || IsLocked() || IsColLocked() )
133 0 : return;
134 : // #i28701# - use new method <GetPageFrm()>
135 361 : if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
136 : {
137 0 : SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
138 0 : SwPageFrm *pPageFrm = pFly ? pFly->FindPageFrm() : NULL;
139 0 : if( pPageFrm )
140 0 : pPageFrm->AppendFlyToPage( this );
141 : }
142 361 : if( !GetPageFrm() )
143 0 : return;
144 :
145 361 : Lock(); // The curtain drops
146 :
147 : // takes care of the notification in the dtor
148 361 : const SwFlyNotify aNotify( this );
149 :
150 361 : if ( IsClipped() )
151 : {
152 16 : mbValidSize = bHeightClipped = bWidthClipped = sal_False;
153 : // no invalidation of position,
154 : // if anchored object is anchored inside a Writer fly frame,
155 : // its position is already locked, and it follows the text flow.
156 : // #i34753# - add condition:
157 : // no invalidation of position, if no direct move is requested in <CheckClip(..)>
158 26 : if ( !IsNoMoveOnCheckClip() &&
159 5 : !( PositionLocked() &&
160 0 : GetAnchorFrm()->IsInFly() &&
161 0 : GetFrmFmt().GetFollowTextFlow().GetValue() ) )
162 : {
163 5 : mbValidPos = sal_False;
164 : }
165 : }
166 :
167 : // #i81146# new loop control
168 361 : sal_uInt16 nLoopControlRuns = 0;
169 361 : const sal_uInt16 nLoopControlMax = 10;
170 :
171 1231 : while ( !mbValidPos || !mbValidSize || !mbValidPrtArea || bFormatHeightOnly )
172 : {
173 509 : SWRECTFN( this )
174 : const SwFmtFrmSize *pSz;
175 : { // Additional scope, so aAccess will be destroyed before the check!
176 :
177 509 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
178 509 : const SwBorderAttrs &rAttrs = *aAccess.Get();
179 509 : pSz = &rAttrs.GetAttrSet().GetFrmSize();
180 :
181 : // Only set when the flag is set!
182 509 : if ( !mbValidSize )
183 : {
184 475 : mbValidPrtArea = sal_False;
185 : }
186 :
187 509 : if ( !mbValidPrtArea )
188 475 : MakePrtArea( rAttrs );
189 :
190 509 : if ( !mbValidSize || bFormatHeightOnly )
191 : {
192 475 : mbValidSize = sal_False;
193 475 : Format( &rAttrs );
194 475 : bFormatHeightOnly = sal_False;
195 : }
196 :
197 509 : if ( !mbValidPos )
198 : {
199 263 : const Point aOldPos( (Frm().*fnRect->fnGetPos)() );
200 : // #i26791# - use new method <MakeObjPos()>
201 : // #i34753# - no positioning, if requested.
202 263 : if ( IsNoMakePos() )
203 1 : mbValidPos = sal_True;
204 : else
205 : // #i26791# - use new method <MakeObjPos()>
206 262 : MakeObjPos();
207 263 : if( aOldPos == (Frm().*fnRect->fnGetPos)() )
208 : {
209 119 : if( !mbValidPos && GetAnchorFrm()->IsInSct() &&
210 0 : !GetAnchorFrm()->FindSctFrm()->IsValid() )
211 0 : mbValidPos = sal_True;
212 : }
213 : else
214 144 : mbValidSize = sal_False;
215 509 : }
216 : }
217 :
218 509 : if ( mbValidPos && mbValidSize )
219 : {
220 365 : ++nLoopControlRuns;
221 :
222 : OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrm::MakeAll" );
223 :
224 730 : if ( nLoopControlRuns < nLoopControlMax )
225 365 : CheckClip( *pSz );
226 : }
227 : else
228 144 : nLoopControlRuns = 0;
229 : }
230 361 : Unlock();
231 :
232 : #if OSL_DEBUG_LEVEL > 0
233 : SWRECTFN( this )
234 : OSL_ENSURE( bHeightClipped || ( (Frm().*fnRect->fnGetHeight)() > 0 &&
235 : (Prt().*fnRect->fnGetHeight)() > 0),
236 : "SwFlyFreeFrm::Format(), flipping Fly." );
237 :
238 : #endif
239 : }
240 :
241 : /** determines, if direct environment of fly frame has 'auto' size
242 :
243 : #i17297#
244 : start with anchor frame and search via <GetUpper()> for a header, footer,
245 : row or fly frame stopping at page frame.
246 : return <true>, if such a frame is found and it has 'auto' size.
247 : otherwise <false> is returned.
248 :
249 : @return boolean indicating, that direct environment has 'auto' size
250 : */
251 0 : bool SwFlyFreeFrm::HasEnvironmentAutoSize() const
252 : {
253 0 : bool bRetVal = false;
254 :
255 0 : const SwFrm* pToBeCheckedFrm = GetAnchorFrm();
256 0 : while ( pToBeCheckedFrm &&
257 0 : !pToBeCheckedFrm->IsPageFrm() )
258 : {
259 0 : if ( pToBeCheckedFrm->IsHeaderFrm() ||
260 0 : pToBeCheckedFrm->IsFooterFrm() ||
261 0 : pToBeCheckedFrm->IsRowFrm() ||
262 0 : pToBeCheckedFrm->IsFlyFrm() )
263 : {
264 : bRetVal = ATT_FIX_SIZE !=
265 0 : pToBeCheckedFrm->GetAttrSet()->GetFrmSize().GetHeightSizeType();
266 0 : break;
267 : }
268 : else
269 : {
270 0 : pToBeCheckedFrm = pToBeCheckedFrm->GetUpper();
271 : }
272 : }
273 :
274 0 : return bRetVal;
275 : }
276 :
277 : /*************************************************************************
278 : |*
279 : |* SwFlyFreeFrm::CheckClip()
280 : |*
281 : |*************************************************************************/
282 :
283 365 : void SwFlyFreeFrm::CheckClip( const SwFmtFrmSize &rSz )
284 : {
285 : // It's probably time now to take appropriate measures, if the Fly
286 : // doesn't fit into its surrounding.
287 : // First, the Fly gives up its position, then it's formatted.
288 : // Only if it still doesn't fit after giving up its position, the
289 : // width or height are given up as well. The frame will be squeezed
290 : // as much as needed.
291 :
292 365 : const SwVirtFlyDrawObj *pObj = GetVirtDrawObj();
293 365 : SwRect aClip, aTmpStretch;
294 365 : ::CalcClipRect( pObj, aClip, sal_True );
295 365 : ::CalcClipRect( pObj, aTmpStretch, sal_False );
296 365 : aClip._Intersection( aTmpStretch );
297 :
298 365 : const long nBot = Frm().Top() + Frm().Height();
299 365 : const long nRig = Frm().Left() + Frm().Width();
300 365 : const long nClipBot = aClip.Top() + aClip.Height();
301 365 : const long nClipRig = aClip.Left() + aClip.Width();
302 :
303 365 : const bool bBot = nBot > nClipBot;
304 365 : const bool bRig = nRig > nClipRig;
305 365 : if ( bBot || bRig )
306 : {
307 20 : bool bAgain = false;
308 : // #i37068# - no move, if it's requested
309 49 : if ( bBot && !IsNoMoveOnCheckClip() &&
310 38 : !GetDrawObjs() && !GetAnchorFrm()->IsInTab() )
311 : {
312 9 : SwFrm* pHeader = FindFooterOrHeader();
313 : // In a header, correction of the position is no good idea.
314 : // If the fly moves, some paragraphs have to be formatted, this
315 : // could cause a change of the height of the headerframe,
316 : // now the flyframe can change its position and so on ...
317 9 : if ( !pHeader || !pHeader->IsHeaderFrm() )
318 : {
319 9 : const long nOld = Frm().Top();
320 9 : Frm().Pos().Y() = std::max( aClip.Top(), nClipBot - Frm().Height() );
321 9 : if ( Frm().Top() != nOld )
322 4 : bAgain = true;
323 9 : bHeightClipped = sal_True;
324 : }
325 : }
326 20 : if ( bRig )
327 : {
328 0 : const long nOld = Frm().Left();
329 0 : Frm().Pos().X() = std::max( aClip.Left(), nClipRig - Frm().Width() );
330 0 : if ( Frm().Left() != nOld )
331 : {
332 0 : const SwFmtHoriOrient &rH = GetFmt()->GetHoriOrient();
333 : // Left-aligned ones may not be moved to the left when they
334 : // are avoiding another one.
335 0 : if( rH.GetHoriOrient() == text::HoriOrientation::LEFT )
336 0 : Frm().Pos().X() = nOld;
337 : else
338 0 : bAgain = true;
339 : }
340 0 : bWidthClipped = sal_True;
341 : }
342 20 : if ( bAgain )
343 4 : mbValidSize = sal_False;
344 : else
345 : {
346 : // If we reach this branch, the Frm protrudes into forbidden
347 : // areas, and correcting the position is not allowed or not
348 : // possible or not required.
349 :
350 : // For Flys with OLE objects as lower, we make sure that
351 : // we always resize proportionally
352 16 : Size aOldSize( Frm().SSize() );
353 :
354 : // First, setup the FrmRect, then transfer it to the Frm.
355 16 : SwRect aFrmRect( Frm() );
356 :
357 16 : if ( bBot )
358 : {
359 16 : long nDiff = nClipBot;
360 16 : nDiff -= aFrmRect.Top(); // nDiff represents the available distance
361 16 : nDiff = aFrmRect.Height() - nDiff;
362 16 : aFrmRect.Height( aFrmRect.Height() - nDiff );
363 16 : bHeightClipped = sal_True;
364 : }
365 16 : if ( bRig )
366 : {
367 0 : long nDiff = nClipRig;
368 0 : nDiff -= aFrmRect.Left();// nDiff represents the available distance
369 0 : nDiff = aFrmRect.Width() - nDiff;
370 0 : aFrmRect.Width( aFrmRect.Width() - nDiff );
371 0 : bWidthClipped = sal_True;
372 : }
373 :
374 : // #i17297# - no proportional
375 : // scaling of graphics in environments, which determines its size
376 : // by its content ('auto' size). Otherwise layout loops can occur and
377 : // layout sizes of the environment can be incorrect.
378 : // Such environment are:
379 : // (1) header and footer frames with 'auto' size
380 : // (2) table row frames with 'auto' size
381 : // (3) fly frames with 'auto' size
382 : // Note: section frames seems to be not critical - didn't found
383 : // any critical layout situation so far.
384 16 : if ( Lower() && Lower()->IsNoTxtFrm() &&
385 0 : ( static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() ||
386 0 : !HasEnvironmentAutoSize() ) )
387 : {
388 : // If width and height got adjusted, then the bigger
389 : // change is relevant.
390 0 : if ( aFrmRect.Width() != aOldSize.Width() &&
391 0 : aFrmRect.Height()!= aOldSize.Height() )
392 : {
393 0 : if ( (aOldSize.Width() - aFrmRect.Width()) >
394 0 : (aOldSize.Height()- aFrmRect.Height()) )
395 0 : aFrmRect.Height( aOldSize.Height() );
396 : else
397 0 : aFrmRect.Width( aOldSize.Width() );
398 : }
399 :
400 : // Adjusted the width? change height proportionally
401 0 : if( aFrmRect.Width() != aOldSize.Width() )
402 : {
403 0 : aFrmRect.Height( aFrmRect.Width() * aOldSize.Height() /
404 0 : aOldSize.Width() );
405 0 : bHeightClipped = sal_True;
406 : }
407 : // Adjusted the height? change width proportionally
408 0 : else if( aFrmRect.Height() != aOldSize.Height() )
409 : {
410 0 : aFrmRect.Width( aFrmRect.Height() * aOldSize.Width() /
411 0 : aOldSize.Height() );
412 0 : bWidthClipped = sal_True;
413 : }
414 :
415 : // #i17297# - reactivate change
416 : // of size attribute for fly frames containing an ole object.
417 :
418 : // Added the aFrmRect.HasArea() hack, because
419 : // the environment of the ole object does not have to be valid
420 : // at this moment, or even worse, it does not have to have a
421 : // resonable size. In this case we do not want to change to
422 : // attributes permanentely. Maybe one day somebody dares to remove
423 : // this code.
424 0 : if ( aFrmRect.HasArea() &&
425 0 : static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() &&
426 0 : ( bWidthClipped || bHeightClipped ) )
427 : {
428 0 : SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
429 0 : pFmt->LockModify();
430 0 : SwFmtFrmSize aFrmSize( rSz );
431 0 : aFrmSize.SetWidth( aFrmRect.Width() );
432 0 : aFrmSize.SetHeight( aFrmRect.Height() );
433 0 : pFmt->SetFmtAttr( aFrmSize );
434 0 : pFmt->UnlockModify();
435 : }
436 : }
437 :
438 : // Now change the Frm; for columns, we put the new values into the attributes,
439 : // otherwise we'll end up with unwanted side-effects/oscillations
440 16 : const long nPrtHeightDiff = Frm().Height() - Prt().Height();
441 16 : const long nPrtWidthDiff = Frm().Width() - Prt().Width();
442 16 : maUnclippedFrm = SwRect( Frm() );
443 16 : Frm().Height( aFrmRect.Height() );
444 16 : Frm().Width ( std::max( long(MINLAY), aFrmRect.Width() ) );
445 16 : if ( Lower() && Lower()->IsColumnFrm() )
446 : {
447 0 : ColLock(); //lock grow/shrink
448 0 : const Size aTmpOldSize( Prt().SSize() );
449 0 : Prt().Height( Frm().Height() - nPrtHeightDiff );
450 0 : Prt().Width ( Frm().Width() - nPrtWidthDiff );
451 0 : ChgLowersProp( aTmpOldSize );
452 0 : SwFrm *pLow = Lower();
453 0 : do
454 0 : { pLow->Calc();
455 : // also calculate the (Column)BodyFrm
456 0 : ((SwLayoutFrm*)pLow)->Lower()->Calc();
457 0 : pLow = pLow->GetNext();
458 : } while ( pLow );
459 0 : ::CalcCntnt( this );
460 0 : ColUnlock();
461 0 : if ( !mbValidSize && !bWidthClipped )
462 0 : bFormatHeightOnly = mbValidSize = sal_True;
463 : }
464 : else
465 : {
466 16 : Prt().Height( Frm().Height() - nPrtHeightDiff );
467 16 : Prt().Width ( Frm().Width() - nPrtWidthDiff );
468 : }
469 : }
470 : }
471 :
472 : // #i26945#
473 : OSL_ENSURE( Frm().Height() >= 0,
474 : "<SwFlyFreeFrm::CheckClip(..)> - fly frame has negative height now." );
475 365 : }
476 :
477 : /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
478 : #i43771#
479 : */
480 558 : bool SwFlyFreeFrm::IsFormatPossible() const
481 : {
482 1674 : return SwFlyFrm::IsFormatPossible() &&
483 558 : ( GetPageFrm() ||
484 558 : ( GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) );
485 : }
486 :
487 : /*************************************************************************
488 : |*
489 : |* SwFlyLayFrm::SwFlyLayFrm()
490 : |*
491 : |*************************************************************************/
492 :
493 9 : SwFlyLayFrm::SwFlyLayFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
494 9 : SwFlyFreeFrm( pFmt, pSib, pAnch )
495 : {
496 9 : bLayout = sal_True;
497 9 : }
498 :
499 : // #i28701#
500 1965 : TYPEINIT1(SwFlyLayFrm,SwFlyFreeFrm);
501 : /*************************************************************************
502 : |*
503 : |* SwFlyLayFrm::Modify()
504 : |*
505 : |*************************************************************************/
506 :
507 1 : void SwFlyLayFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
508 : {
509 1 : sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
510 :
511 1 : SwFmtAnchor *pAnch = 0;
512 2 : if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
513 1 : ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
514 1 : (const SfxPoolItem**)&pAnch ))
515 : ; // GetItemState sets the anchor pointer!
516 :
517 1 : else if( RES_ANCHOR == nWhich )
518 : {
519 : // Change of anchor. I'm attaching myself to the new place.
520 : // It's not allowed to change the anchor type. This is only
521 : // possible via SwFEShell.
522 0 : pAnch = (SwFmtAnchor*)pNew;
523 : }
524 :
525 1 : if( pAnch )
526 : {
527 : OSL_ENSURE( pAnch->GetAnchorId() ==
528 : GetFmt()->GetAnchor().GetAnchorId(),
529 : "8-) Invalid change of anchor type." );
530 :
531 : // Unregister, get hold of the page, attach to the corresponding LayoutFrm.
532 0 : SwRect aOld( GetObjRectWithSpaces() );
533 : // #i28701# - use new method <GetPageFrm()>
534 0 : SwPageFrm *pOldPage = GetPageFrm();
535 0 : AnchorFrm()->RemoveFly( this );
536 :
537 0 : if ( FLY_AT_PAGE == pAnch->GetAnchorId() )
538 : {
539 0 : sal_uInt16 nPgNum = pAnch->GetPageNum();
540 0 : SwRootFrm *pRoot = getRootFrm();
541 0 : SwPageFrm *pTmpPage = (SwPageFrm*)pRoot->Lower();
542 0 : for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i,
543 0 : pTmpPage = (SwPageFrm*)pTmpPage->GetNext() )
544 : {
545 0 : if ( i == nPgNum )
546 : {
547 : // #i50432# - adjust synopsis of <PlaceFly(..)>
548 0 : pTmpPage->PlaceFly( this, 0 );
549 : }
550 : }
551 0 : if( !pTmpPage )
552 : {
553 0 : pRoot->SetAssertFlyPages();
554 0 : pRoot->AssertFlyPages();
555 : }
556 : }
557 : else
558 : {
559 0 : SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
560 0 : SwCntntFrm *pCntnt = GetFmt()->GetDoc()->GetNodes().GoNext( &aIdx )->
561 0 : GetCntntNode()->getLayoutFrm( getRootFrm(), 0, 0, sal_False );
562 0 : if( pCntnt )
563 : {
564 0 : SwFlyFrm *pTmp = pCntnt->FindFlyFrm();
565 0 : if( pTmp )
566 0 : pTmp->AppendFly( this );
567 0 : }
568 : }
569 : // #i28701# - use new method <GetPageFrm()>
570 0 : if ( pOldPage && pOldPage != GetPageFrm() )
571 0 : NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
572 0 : SetCompletePaint();
573 0 : InvalidateAll();
574 0 : SetNotifyBack();
575 : }
576 : else
577 1 : SwFlyFrm::Modify( pOld, pNew );
578 1 : }
579 :
580 : /*************************************************************************
581 : |*
582 : |* SwPageFrm::AppendFly()
583 : |*
584 : |*************************************************************************/
585 :
586 328 : void SwPageFrm::AppendFlyToPage( SwFlyFrm *pNew )
587 : {
588 328 : if ( !pNew->GetVirtDrawObj()->IsInserted() )
589 0 : getRootFrm()->GetDrawPage()->InsertObject(
590 0 : (SdrObject*)pNew->GetVirtDrawObj(),
591 0 : pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
592 :
593 328 : InvalidateSpelling();
594 328 : InvalidateSmartTags(); // SMARTTAGS
595 328 : InvalidateAutoCompleteWords();
596 328 : InvalidateWordCount();
597 :
598 328 : if ( GetUpper() )
599 : {
600 328 : ((SwRootFrm*)GetUpper())->SetIdleFlags();
601 328 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
602 : }
603 :
604 328 : SdrObject* pObj = pNew->GetVirtDrawObj();
605 : OSL_ENSURE( pNew->GetAnchorFrm(), "Fly without Anchor" );
606 328 : SwFlyFrm* pFly = (SwFlyFrm*)pNew->GetAnchorFrm()->FindFlyFrm();
607 328 : if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() )
608 : {
609 : //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
610 0 : sal_uInt32 nNewNum = pObj->GetOrdNumDirect();
611 0 : if ( pObj->GetPage() )
612 0 : pObj->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum );
613 : else
614 0 : pFly->GetVirtDrawObj()->SetOrdNum( nNewNum );
615 : }
616 :
617 : // Don't look further at Flys that sit inside the Cntnt.
618 328 : if ( pNew->IsFlyInCntFrm() )
619 189 : InvalidateFlyInCnt();
620 : else
621 : {
622 139 : InvalidateFlyCntnt();
623 :
624 139 : if ( !pSortedObjs )
625 90 : pSortedObjs = new SwSortedObjs();
626 :
627 139 : const bool bSucessInserted = pSortedObjs->Insert( *pNew );
628 : OSL_ENSURE( bSucessInserted, "Fly not inserted in Sorted." );
629 : (void) bSucessInserted;
630 :
631 : // #i87493#
632 : OSL_ENSURE( pNew->GetPageFrm() == 0 || pNew->GetPageFrm() == this,
633 : "<SwPageFrm::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect -> please inform OD." );
634 : // #i28701# - use new method <SetPageFrm(..)>
635 139 : pNew->SetPageFrm( this );
636 139 : pNew->InvalidatePage( this );
637 : // #i28701#
638 139 : pNew->UnlockPosition();
639 :
640 : // Notify accessible layout. That's required at this place for
641 : // frames only where the anchor is moved. Creation of new frames
642 : // is additionally handled by the SwFrmNotify class.
643 417 : if( GetUpper() &&
644 139 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
645 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
646 : {
647 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
648 0 : ->AddAccessibleFrm( pNew );
649 : }
650 : }
651 :
652 : // #i28701# - correction: consider also drawing objects
653 328 : if ( pNew->GetDrawObjs() )
654 : {
655 0 : SwSortedObjs &rObjs = *pNew->GetDrawObjs();
656 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
657 : {
658 0 : SwAnchoredObject* pTmpObj = rObjs[i];
659 0 : if ( pTmpObj->ISA(SwFlyFrm) )
660 : {
661 0 : SwFlyFrm* pTmpFly = static_cast<SwFlyFrm*>(pTmpObj);
662 : // #i28701# - use new method <GetPageFrm()>
663 0 : if ( pTmpFly->IsFlyFreeFrm() && !pTmpFly->GetPageFrm() )
664 0 : AppendFlyToPage( pTmpFly );
665 : }
666 0 : else if ( pTmpObj->ISA(SwAnchoredDrawObject) )
667 : {
668 : // #i87493#
669 0 : if ( pTmpObj->GetPageFrm() != this )
670 : {
671 0 : if ( pTmpObj->GetPageFrm() != 0 )
672 : {
673 0 : pTmpObj->GetPageFrm()->RemoveDrawObjFromPage( *pTmpObj );
674 : }
675 0 : AppendDrawObjToPage( *pTmpObj );
676 : }
677 : }
678 : }
679 : }
680 328 : }
681 :
682 : /*************************************************************************
683 : |*
684 : |* SwPageFrm::RemoveFly()
685 : |*
686 : |*************************************************************************/
687 :
688 16 : void SwPageFrm::RemoveFlyFromPage( SwFlyFrm *pToRemove )
689 : {
690 16 : const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum();
691 16 : getRootFrm()->GetDrawPage()->RemoveObject( nOrdNum );
692 16 : pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum );
693 :
694 16 : if ( GetUpper() )
695 : {
696 16 : if ( !pToRemove->IsFlyInCntFrm() )
697 13 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
698 16 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
699 : }
700 :
701 : // Don't look further at Flys that sit inside the Cntnt.
702 16 : if ( pToRemove->IsFlyInCntFrm() )
703 19 : return;
704 :
705 : // Don't delete collections just yet. This will happen at the end of the
706 : // action in the RemoveSuperfluous of the page, kicked off by a method of
707 : // the same name in the root.
708 : // The FlyColl might be gone already, because the page's dtor is being
709 : // executed.
710 : // Remove it _before_ disposing accessible frames to avoid accesses to
711 : // the Frm from event handlers.
712 13 : if (pSortedObjs)
713 : {
714 13 : pSortedObjs->Remove(*pToRemove);
715 13 : if (!pSortedObjs->Count())
716 : {
717 3 : delete pSortedObjs;
718 3 : pSortedObjs = 0;
719 : }
720 : }
721 :
722 : // Notify accessible layout. That's required at this place for
723 : // frames only where the anchor is moved. Creation of new frames
724 : // is additionally handled by the SwFrmNotify class.
725 39 : if( GetUpper() &&
726 13 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
727 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
728 : {
729 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
730 0 : ->DisposeAccessibleFrm( pToRemove, sal_True );
731 : }
732 :
733 : // #i28701# - use new method <SetPageFrm(..)>
734 13 : pToRemove->SetPageFrm( 0L );
735 : }
736 :
737 : /*************************************************************************
738 : |*
739 : |* SwPageFrm::MoveFly
740 : |*
741 : |*************************************************************************/
742 :
743 0 : void SwPageFrm::MoveFly( SwFlyFrm *pToMove, SwPageFrm *pDest )
744 : {
745 : // Invalidations
746 0 : if ( GetUpper() )
747 : {
748 0 : ((SwRootFrm*)GetUpper())->SetIdleFlags();
749 0 : if ( !pToMove->IsFlyInCntFrm() && pDest->GetPhyPageNum() < GetPhyPageNum() )
750 0 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
751 : }
752 :
753 0 : pDest->InvalidateSpelling();
754 0 : pDest->InvalidateSmartTags(); // SMARTTAGS
755 0 : pDest->InvalidateAutoCompleteWords();
756 0 : pDest->InvalidateWordCount();
757 :
758 0 : if ( pToMove->IsFlyInCntFrm() )
759 : {
760 0 : pDest->InvalidateFlyInCnt();
761 0 : return;
762 : }
763 :
764 : // Notify accessible layout. That's required at this place for
765 : // frames only where the anchor is moved. Creation of new frames
766 : // is additionally handled by the SwFrmNotify class.
767 0 : if( GetUpper() &&
768 0 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
769 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
770 : {
771 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
772 0 : ->DisposeAccessibleFrm( pToMove, sal_True );
773 : }
774 :
775 : // The FlyColl might be gone already, because the page's dtor is being executed.
776 0 : if ( pSortedObjs )
777 : {
778 0 : pSortedObjs->Remove( *pToMove );
779 0 : if ( !pSortedObjs->Count() )
780 0 : { DELETEZ( pSortedObjs );
781 : }
782 : }
783 :
784 : // Register
785 0 : if ( !pDest->GetSortedObjs() )
786 0 : pDest->pSortedObjs = new SwSortedObjs();
787 :
788 0 : const bool bSucessInserted = pDest->GetSortedObjs()->Insert( *pToMove );
789 : OSL_ENSURE( bSucessInserted, "Fly not inserted in Sorted." );
790 : (void) bSucessInserted;
791 :
792 : // #i28701# - use new method <SetPageFrm(..)>
793 0 : pToMove->SetPageFrm( pDest );
794 0 : pToMove->InvalidatePage( pDest );
795 0 : pToMove->SetNotifyBack();
796 0 : pDest->InvalidateFlyCntnt();
797 : // #i28701#
798 0 : pToMove->UnlockPosition();
799 :
800 : // Notify accessible layout. That's required at this place for
801 : // frames only where the anchor is moved. Creation of new frames
802 : // is additionally handled by the SwFrmNotify class.
803 0 : if( GetUpper() &&
804 0 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
805 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
806 : {
807 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
808 0 : ->AddAccessibleFrm( pToMove );
809 : }
810 :
811 : // #i28701# - correction: move lowers of Writer fly frame
812 0 : if ( pToMove->GetDrawObjs() )
813 : {
814 0 : SwSortedObjs &rObjs = *pToMove->GetDrawObjs();
815 0 : for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
816 : {
817 0 : SwAnchoredObject* pObj = rObjs[i];
818 0 : if ( pObj->ISA(SwFlyFrm) )
819 : {
820 0 : SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
821 0 : if ( pFly->IsFlyFreeFrm() )
822 : {
823 : // #i28701# - use new method <GetPageFrm()>
824 0 : SwPageFrm* pPageFrm = pFly->GetPageFrm();
825 0 : if ( pPageFrm )
826 0 : pPageFrm->MoveFly( pFly, pDest );
827 : else
828 0 : pDest->AppendFlyToPage( pFly );
829 : }
830 : }
831 0 : else if ( pObj->ISA(SwAnchoredDrawObject) )
832 : {
833 0 : RemoveDrawObjFromPage( *pObj );
834 0 : pDest->AppendDrawObjToPage( *pObj );
835 : }
836 : }
837 : }
838 : }
839 :
840 : /*************************************************************************
841 : |*
842 : |* SwPageFrm::AppendDrawObjToPage(), RemoveDrawObjFromPage()
843 : |*
844 : |* #i28701# - new methods
845 : |*
846 : |*************************************************************************/
847 311 : void SwPageFrm::AppendDrawObjToPage( SwAnchoredObject& _rNewObj )
848 : {
849 311 : if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
850 : {
851 : OSL_FAIL( "SwPageFrm::AppendDrawObjToPage(..) - anchored object of unexcepted type -> object not appended" );
852 0 : return;
853 : }
854 :
855 311 : if ( GetUpper() )
856 : {
857 311 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
858 : }
859 :
860 : OSL_ENSURE( _rNewObj.GetAnchorFrm(), "anchored draw object without anchor" );
861 311 : SwFlyFrm* pFlyFrm = (SwFlyFrm*)_rNewObj.GetAnchorFrm()->FindFlyFrm();
862 312 : if ( pFlyFrm &&
863 1 : _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrm->GetVirtDrawObj()->GetOrdNum() )
864 : {
865 : //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
866 0 : sal_uInt32 nNewNum = _rNewObj.GetDrawObj()->GetOrdNumDirect();
867 0 : if ( _rNewObj.GetDrawObj()->GetPage() )
868 0 : _rNewObj.DrawObj()->GetPage()->SetObjectOrdNum( pFlyFrm->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum );
869 : else
870 0 : pFlyFrm->GetVirtDrawObj()->SetOrdNum( nNewNum );
871 : }
872 :
873 311 : if ( FLY_AS_CHAR == _rNewObj.GetFrmFmt().GetAnchor().GetAnchorId() )
874 : {
875 249 : return;
876 : }
877 :
878 62 : if ( !pSortedObjs )
879 : {
880 32 : pSortedObjs = new SwSortedObjs();
881 : }
882 62 : if ( !pSortedObjs->Insert( _rNewObj ) )
883 : {
884 : OSL_ENSURE( pSortedObjs->Contains( _rNewObj ),
885 : "Drawing object not appended into list <pSortedObjs>." );
886 : }
887 : // #i87493#
888 : OSL_ENSURE( _rNewObj.GetPageFrm() == 0 || _rNewObj.GetPageFrm() == this,
889 : "<SwPageFrm::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect -> please inform OD." );
890 62 : _rNewObj.SetPageFrm( this );
891 :
892 : // invalidate page in order to force a reformat of object layout of the page.
893 62 : InvalidateFlyLayout();
894 : }
895 :
896 17 : void SwPageFrm::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj )
897 : {
898 17 : if ( !_rToRemoveObj.ISA(SwAnchoredDrawObject) )
899 : {
900 : OSL_FAIL( "SwPageFrm::RemoveDrawObjFromPage(..) - anchored object of unexcepted type -> object not removed" );
901 17 : return;
902 : }
903 :
904 17 : if ( pSortedObjs )
905 : {
906 17 : pSortedObjs->Remove( _rToRemoveObj );
907 17 : if ( !pSortedObjs->Count() )
908 : {
909 6 : DELETEZ( pSortedObjs );
910 : }
911 17 : if ( GetUpper() )
912 : {
913 17 : if (FLY_AS_CHAR !=
914 17 : _rToRemoveObj.GetFrmFmt().GetAnchor().GetAnchorId())
915 : {
916 17 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
917 17 : InvalidatePage();
918 : }
919 17 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
920 : }
921 : }
922 17 : _rToRemoveObj.SetPageFrm( 0 );
923 : }
924 :
925 : /*************************************************************************
926 : |*
927 : |* SwPageFrm::PlaceFly
928 : |*
929 : |*************************************************************************/
930 :
931 : // #i50432# - adjust method description and synopsis.
932 8 : void SwPageFrm::PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt )
933 : {
934 : // #i50432# - consider the case that page is an empty page:
935 : // In this case append the fly frame at the next page
936 : OSL_ENSURE( !IsEmptyPage() || GetNext(),
937 : "<SwPageFrm::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" );
938 8 : if ( IsEmptyPage() && GetNext() )
939 : {
940 0 : static_cast<SwPageFrm*>(GetNext())->PlaceFly( pFly, pFmt );
941 : }
942 : else
943 : {
944 : // If we received a Fly, we use that one. Otherwise, create a new
945 : // one using the Format.
946 8 : if ( pFly )
947 0 : AppendFly( pFly );
948 : else
949 : { OSL_ENSURE( pFmt, ":-( No Format given for Fly." );
950 8 : pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, this, this );
951 8 : AppendFly( pFly );
952 8 : ::RegistFlys( this, pFly );
953 : }
954 : }
955 8 : }
956 :
957 : /*************************************************************************
958 : |*
959 : |* ::CalcClipRect
960 : |*
961 : |*************************************************************************/
962 : // #i18732# - adjustments for following text flow or not
963 : // AND alignment at 'page areas' for to paragraph/to character anchored objects
964 : // #i22305# - adjustment for following text flow for to frame anchored objects
965 : // #i29778# - Because calculating the floating screen object's position
966 : // (Writer fly frame or drawing object) doesn't perform a calculation on its
967 : // upper frames and its anchor frame, a calculation of the upper frames in this
968 : // method is no longer sensible.
969 : // #i28701# - if document compatibility option 'Consider wrapping style influence
970 : // on object positioning' is ON, the clip area corresponds to the one as the
971 : // object doesn't follow the text flow.
972 731 : sal_Bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, sal_Bool bMove )
973 : {
974 731 : sal_Bool bRet = sal_True;
975 731 : if ( pSdrObj->ISA(SwVirtFlyDrawObj) )
976 : {
977 731 : const SwFlyFrm* pFly = ((const SwVirtFlyDrawObj*)pSdrObj)->GetFlyFrm();
978 731 : const bool bFollowTextFlow = pFly->GetFmt()->GetFollowTextFlow().GetValue();
979 : // #i28701#
980 : const bool bConsiderWrapOnObjPos =
981 731 : pFly->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
982 731 : const SwFmtVertOrient &rV = pFly->GetFmt()->GetVertOrient();
983 731 : if( pFly->IsFlyLayFrm() )
984 : {
985 : const SwFrm* pClip;
986 : // #i22305#
987 : // #i28701#
988 202 : if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
989 : {
990 202 : pClip = pFly->GetAnchorFrm()->FindPageFrm();
991 : }
992 : else
993 : {
994 0 : pClip = pFly->GetAnchorFrm();
995 : }
996 :
997 202 : rRect = pClip->Frm();
998 202 : SWRECTFN( pClip )
999 :
1000 : // vertical clipping: Top and Bottom, also to PrtArea if necessary
1001 402 : if( rV.GetVertOrient() != text::VertOrientation::NONE &&
1002 200 : rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
1003 : {
1004 198 : (rRect.*fnRect->fnSetTop)( (pClip->*fnRect->fnGetPrtTop)() );
1005 198 : (rRect.*fnRect->fnSetBottom)( (pClip->*fnRect->fnGetPrtBottom)() );
1006 : }
1007 : // horizontal clipping: Top and Bottom, also to PrtArea if necessary
1008 202 : const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
1009 402 : if( rH.GetHoriOrient() != text::HoriOrientation::NONE &&
1010 200 : rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
1011 : {
1012 198 : (rRect.*fnRect->fnSetLeft)( (pClip->*fnRect->fnGetPrtLeft)() );
1013 198 : (rRect.*fnRect->fnSetRight)((pClip->*fnRect->fnGetPrtRight)());
1014 : }
1015 : }
1016 529 : else if( pFly->IsFlyAtCntFrm() )
1017 : {
1018 : // #i18732# - consider following text flow or not
1019 : // AND alignment at 'page areas'
1020 529 : const SwFrm* pVertPosOrientFrm = pFly->GetVertPosOrientFrm();
1021 529 : if ( !pVertPosOrientFrm )
1022 : {
1023 : OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
1024 0 : pVertPosOrientFrm = pFly->GetAnchorFrm();
1025 : }
1026 :
1027 529 : if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
1028 : {
1029 529 : const SwLayoutFrm* pClipFrm = pVertPosOrientFrm->FindPageFrm();
1030 529 : if (!pClipFrm)
1031 : {
1032 : OSL_FAIL("!pClipFrm: "
1033 : "if you can reproduce this please file a bug");
1034 0 : return false;
1035 : }
1036 794 : rRect = bMove ? pClipFrm->GetUpper()->Frm()
1037 794 : : pClipFrm->Frm();
1038 : // #i26945# - consider that a table, during
1039 : // its format, can exceed its upper printing area bottom.
1040 : // Thus, enlarge the clip rectangle, if such a case occurred
1041 529 : if ( pFly->GetAnchorFrm()->IsInTab() )
1042 : {
1043 : const SwTabFrm* pTabFrm = const_cast<SwFlyFrm*>(pFly)
1044 12 : ->GetAnchorFrmContainingAnchPos()->FindTabFrm();
1045 12 : SwRect aTmp( pTabFrm->Prt() );
1046 12 : aTmp += pTabFrm->Frm().Pos();
1047 12 : rRect.Union( aTmp );
1048 : // #i43913# - consider also the cell frame
1049 : const SwFrm* pCellFrm = const_cast<SwFlyFrm*>(pFly)
1050 12 : ->GetAnchorFrmContainingAnchPos()->GetUpper();
1051 24 : while ( pCellFrm && !pCellFrm->IsCellFrm() )
1052 : {
1053 0 : pCellFrm = pCellFrm->GetUpper();
1054 : }
1055 12 : if ( pCellFrm )
1056 : {
1057 12 : aTmp = pCellFrm->Prt();
1058 12 : aTmp += pCellFrm->Frm().Pos();
1059 12 : rRect.Union( aTmp );
1060 : }
1061 529 : }
1062 : }
1063 0 : else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
1064 0 : rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
1065 : {
1066 : // new class <SwEnvironmentOfAnchoredObject>
1067 : objectpositioning::SwEnvironmentOfAnchoredObject
1068 0 : aEnvOfObj( bFollowTextFlow );
1069 : const SwLayoutFrm& rVertClipFrm =
1070 0 : aEnvOfObj.GetVertEnvironmentLayoutFrm( *pVertPosOrientFrm );
1071 0 : if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
1072 : {
1073 0 : rRect = rVertClipFrm.Frm();
1074 : }
1075 0 : else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
1076 : {
1077 0 : if ( rVertClipFrm.IsPageFrm() )
1078 : {
1079 0 : rRect = static_cast<const SwPageFrm&>(rVertClipFrm).PrtWithoutHeaderAndFooter();
1080 : }
1081 : else
1082 : {
1083 0 : rRect = rVertClipFrm.Frm();
1084 : }
1085 : }
1086 : const SwLayoutFrm* pHoriClipFrm =
1087 0 : pFly->GetAnchorFrm()->FindPageFrm()->GetUpper();
1088 0 : SWRECTFN( pFly->GetAnchorFrm() )
1089 0 : (rRect.*fnRect->fnSetLeft)( (pHoriClipFrm->Frm().*fnRect->fnGetLeft)() );
1090 0 : (rRect.*fnRect->fnSetRight)((pHoriClipFrm->Frm().*fnRect->fnGetRight)());
1091 : }
1092 : else
1093 : {
1094 : // #i26945#
1095 : const SwFrm *pClip =
1096 0 : const_cast<SwFlyFrm*>(pFly)->GetAnchorFrmContainingAnchPos();
1097 0 : SWRECTFN( pClip )
1098 0 : const SwLayoutFrm *pUp = pClip->GetUpper();
1099 0 : const SwFrm *pCell = pUp->IsCellFrm() ? pUp : 0;
1100 : sal_uInt16 nType = bMove ? FRM_ROOT | FRM_FLY | FRM_HEADER |
1101 : FRM_FOOTER | FRM_FTN
1102 : : FRM_BODY | FRM_FLY | FRM_HEADER |
1103 0 : FRM_FOOTER | FRM_CELL| FRM_FTN;
1104 :
1105 0 : while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrm() )
1106 : {
1107 0 : pUp = pUp->GetUpper();
1108 0 : if ( !pCell && pUp->IsCellFrm() )
1109 0 : pCell = pUp;
1110 : }
1111 0 : if ( bMove )
1112 : {
1113 0 : if ( pUp->IsRootFrm() )
1114 : {
1115 0 : rRect = pUp->Prt();
1116 0 : rRect += pUp->Frm().Pos();
1117 0 : pUp = 0;
1118 : }
1119 : }
1120 0 : if ( pUp )
1121 : {
1122 0 : if ( pUp->GetType() & FRM_BODY )
1123 : {
1124 : const SwPageFrm *pPg;
1125 0 : if ( pUp->GetUpper() != (pPg = pFly->FindPageFrm()) )
1126 0 : pUp = pPg->FindBodyCont();
1127 0 : rRect = pUp->GetUpper()->Frm();
1128 0 : (rRect.*fnRect->fnSetTop)( (pUp->*fnRect->fnGetPrtTop)() );
1129 0 : (rRect.*fnRect->fnSetBottom)((pUp->*fnRect->fnGetPrtBottom)());
1130 : }
1131 : else
1132 : {
1133 0 : if( ( pUp->GetType() & (FRM_FLY | FRM_FTN ) ) &&
1134 0 : !pUp->Frm().IsInside( pFly->Frm().Pos() ) )
1135 : {
1136 0 : if( pUp->IsFlyFrm() )
1137 : {
1138 0 : SwFlyFrm *pTmpFly = (SwFlyFrm*)pUp;
1139 0 : while( pTmpFly->GetNextLink() )
1140 : {
1141 0 : pTmpFly = pTmpFly->GetNextLink();
1142 0 : if( pTmpFly->Frm().IsInside( pFly->Frm().Pos() ) )
1143 0 : break;
1144 : }
1145 0 : pUp = pTmpFly;
1146 : }
1147 0 : else if( pUp->IsInFtn() )
1148 : {
1149 0 : const SwFtnFrm *pTmp = pUp->FindFtnFrm();
1150 0 : while( pTmp->GetFollow() )
1151 : {
1152 0 : pTmp = pTmp->GetFollow();
1153 0 : if( pTmp->Frm().IsInside( pFly->Frm().Pos() ) )
1154 0 : break;
1155 : }
1156 0 : pUp = pTmp;
1157 : }
1158 : }
1159 0 : rRect = pUp->Prt();
1160 0 : rRect.Pos() += pUp->Frm().Pos();
1161 0 : if ( pUp->GetType() & (FRM_HEADER | FRM_FOOTER) )
1162 : {
1163 0 : rRect.Left ( pUp->GetUpper()->Frm().Left() );
1164 0 : rRect.Width( pUp->GetUpper()->Frm().Width());
1165 : }
1166 0 : else if ( pUp->IsCellFrm() ) //MA_FLY_HEIGHT
1167 : {
1168 0 : const SwFrm *pTab = pUp->FindTabFrm();
1169 : (rRect.*fnRect->fnSetBottom)(
1170 0 : (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
1171 : // expand to left and right cell border
1172 0 : rRect.Left ( pUp->Frm().Left() );
1173 0 : rRect.Width( pUp->Frm().Width() );
1174 : }
1175 : }
1176 : }
1177 0 : if ( pCell )
1178 : {
1179 : // CellFrms might also sit in unallowed areas. In this case,
1180 : // the Fly is allowed to do so as well
1181 0 : SwRect aTmp( pCell->Prt() );
1182 0 : aTmp += pCell->Frm().Pos();
1183 0 : rRect.Union( aTmp );
1184 : }
1185 : }
1186 : }
1187 : else
1188 : {
1189 0 : const SwFrm *pUp = pFly->GetAnchorFrm()->GetUpper();
1190 0 : SWRECTFN( pFly->GetAnchorFrm() )
1191 0 : while( pUp->IsColumnFrm() || pUp->IsSctFrm() || pUp->IsColBodyFrm())
1192 0 : pUp = pUp->GetUpper();
1193 0 : rRect = pUp->Frm();
1194 0 : if( !pUp->IsBodyFrm() )
1195 : {
1196 0 : rRect += pUp->Prt().Pos();
1197 0 : rRect.SSize( pUp->Prt().SSize() );
1198 0 : if ( pUp->IsCellFrm() )
1199 : {
1200 0 : const SwFrm *pTab = pUp->FindTabFrm();
1201 : (rRect.*fnRect->fnSetBottom)(
1202 0 : (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
1203 : }
1204 : }
1205 0 : else if ( pUp->GetUpper()->IsPageFrm() )
1206 : {
1207 : // Objects anchored as character may exceed right margin
1208 : // of body frame:
1209 0 : (rRect.*fnRect->fnSetRight)( (pUp->GetUpper()->Frm().*fnRect->fnGetRight)() );
1210 : }
1211 0 : long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
1212 : long nTop;
1213 0 : const SwFmt *pFmt = ((SwContact*)GetUserCall(pSdrObj))->GetFmt();
1214 0 : const SvxULSpaceItem &rUL = pFmt->GetULSpace();
1215 0 : if( bMove )
1216 : {
1217 0 : nTop = bVert ? ((SwFlyInCntFrm*)pFly)->GetRefPoint().X() :
1218 0 : ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y();
1219 0 : nTop = (*fnRect->fnYInc)( nTop, -nHeight );
1220 0 : long nWidth = (pFly->Frm().*fnRect->fnGetWidth)();
1221 : (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
1222 0 : ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y() :
1223 0 : ((SwFlyInCntFrm*)pFly)->GetRefPoint().X(), nWidth );
1224 0 : nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper();
1225 : }
1226 : else
1227 : {
1228 0 : nTop = (*fnRect->fnYInc)( (pFly->Frm().*fnRect->fnGetBottom)(),
1229 0 : rUL.GetLower() - nHeight );
1230 0 : nHeight = 2*nHeight - (pFly->Frm().*fnRect->fnGetHeight)()
1231 0 : - rUL.GetLower() - rUL.GetUpper();
1232 : }
1233 0 : (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
1234 : }
1235 : }
1236 : else
1237 : {
1238 0 : const SwDrawContact *pC = (const SwDrawContact*)GetUserCall(pSdrObj);
1239 0 : const SwFrmFmt *pFmt = (const SwFrmFmt*)pC->GetFmt();
1240 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1241 0 : if ( FLY_AS_CHAR == rAnch.GetAnchorId() )
1242 : {
1243 0 : const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
1244 0 : if( !pAnchorFrm )
1245 : {
1246 : OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." );
1247 0 : ((SwDrawContact*)pC)->ConnectToLayout();
1248 0 : pAnchorFrm = pC->GetAnchorFrm();
1249 : }
1250 0 : const SwFrm* pUp = pAnchorFrm->GetUpper();
1251 0 : rRect = pUp->Prt();
1252 0 : rRect += pUp->Frm().Pos();
1253 0 : SWRECTFN( pAnchorFrm )
1254 0 : long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
1255 : long nTop;
1256 0 : const SvxULSpaceItem &rUL = pFmt->GetULSpace();
1257 0 : SwRect aSnapRect( pSdrObj->GetSnapRect() );
1258 0 : long nTmpH = 0;
1259 0 : if( bMove )
1260 : {
1261 0 : nTop = (*fnRect->fnYInc)( bVert ? pSdrObj->GetAnchorPos().X() :
1262 0 : pSdrObj->GetAnchorPos().Y(), -nHeight );
1263 0 : long nWidth = (aSnapRect.*fnRect->fnGetWidth)();
1264 : (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
1265 0 : pSdrObj->GetAnchorPos().Y() :
1266 0 : pSdrObj->GetAnchorPos().X(), nWidth );
1267 : }
1268 : else
1269 : {
1270 : // #i26791# - value of <nTmpH> is needed to
1271 : // calculate value of <nTop>.
1272 0 : nTmpH = bVert ? pSdrObj->GetCurrentBoundRect().GetWidth() :
1273 0 : pSdrObj->GetCurrentBoundRect().GetHeight();
1274 0 : nTop = (*fnRect->fnYInc)( (aSnapRect.*fnRect->fnGetTop)(),
1275 0 : rUL.GetLower() + nTmpH - nHeight );
1276 : }
1277 0 : nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper();
1278 0 : (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
1279 : }
1280 : else
1281 : {
1282 : // restrict clip rectangle for drawing
1283 : // objects in header/footer to the page frame.
1284 : // #i26791#
1285 0 : const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
1286 0 : if ( pAnchorFrm && pAnchorFrm->FindFooterOrHeader() )
1287 : {
1288 : // clip frame is the page frame the header/footer is on.
1289 0 : const SwFrm* pClipFrm = pAnchorFrm->FindPageFrm();
1290 0 : rRect = pClipFrm->Frm();
1291 : }
1292 : else
1293 : {
1294 0 : bRet = sal_False;
1295 : }
1296 : }
1297 : }
1298 731 : return bRet;
1299 99 : }
1300 :
1301 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|