Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "doc.hxx"
30 : : #include "pagefrm.hxx"
31 : : #include "rootfrm.hxx"
32 : : #include "cntfrm.hxx"
33 : : #include "dview.hxx"
34 : : #include "dflyobj.hxx"
35 : : #include "dcontact.hxx"
36 : : #include "flyfrm.hxx"
37 : : #include "ftnfrm.hxx"
38 : : #include "frmtool.hxx"
39 : : #include "frmfmt.hxx"
40 : : #include "hints.hxx"
41 : : #include "pam.hxx"
42 : : #include "sectfrm.hxx"
43 : :
44 : :
45 : : #include <svx/svdpage.hxx>
46 : : #include <editeng/ulspitem.hxx>
47 : : #include <fmtanchr.hxx>
48 : : #include <fmtornt.hxx>
49 : : #include <fmtfsize.hxx>
50 : : #include "ndole.hxx"
51 : : #include "tabfrm.hxx"
52 : : #include "flyfrms.hxx"
53 : : // #i18732#
54 : : #include <fmtfollowtextflow.hxx>
55 : : #include <environmentofanchoredobject.hxx>
56 : : // #i28701#
57 : : #include <sortedobjs.hxx>
58 : : #include <viewsh.hxx>
59 : : #include <viewimp.hxx>
60 : :
61 : :
62 : : using namespace ::com::sun::star;
63 : :
64 : :
65 : : /*************************************************************************
66 : : |*
67 : : |* SwFlyFreeFrm::SwFlyFreeFrm(), ~SwFlyFreeFrm()
68 : : |*
69 : : |*************************************************************************/
70 : :
71 : 147 : SwFlyFreeFrm::SwFlyFreeFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
72 : : SwFlyFrm( pFmt, pSib, pAnch ),
73 : : pPage( 0 ),
74 : : // #i34753#
75 : : mbNoMakePos( false ),
76 : : // #i37068#
77 : 147 : mbNoMoveOnCheckClip( false )
78 : : {
79 : 147 : }
80 : :
81 : 144 : SwFlyFreeFrm::~SwFlyFreeFrm()
82 : : {
83 : : // and goodbye.
84 : : // #i28701# - use new method <GetPageFrm()>
85 [ + - ][ + + ]: 144 : if( GetPageFrm() )
86 : : {
87 [ + - ][ - + ]: 26 : if( GetFmt()->GetDoc()->IsInDtor() )
88 : : {
89 : : // #i29879# - remove also to-frame anchored Writer
90 : : // fly frame from page.
91 : : const bool bRemoveFromPage =
92 [ # # ]: 0 : GetPageFrm()->GetSortedObjs() &&
93 : 0 : ( IsFlyAtCntFrm() ||
94 [ # # ][ # # ]: 0 : ( GetAnchorFrm() && GetAnchorFrm()->IsFlyFrm() ) );
[ # # ][ # # ]
[ # # # # ]
95 [ # # ]: 0 : if ( bRemoveFromPage )
96 : : {
97 [ # # ][ # # ]: 0 : GetPageFrm()->GetSortedObjs()->Remove( *this );
98 : : }
99 : : }
100 : : else
101 : : {
102 [ + - ]: 26 : SwRect aTmp( GetObjRectWithSpaces() );
103 [ + - ][ + - ]: 26 : SwFlyFreeFrm::NotifyBackground( GetPageFrm(), aTmp, PREP_FLY_LEAVE );
104 : : }
105 : : }
106 [ - + ]: 144 : }
107 : :
108 : : // #i28701#
109 [ + + ][ + + ]: 13106 : TYPEINIT1(SwFlyFreeFrm,SwFlyFrm);
110 : : /*************************************************************************
111 : : |*
112 : : |* SwFlyFreeFrm::NotifyBackground()
113 : : |*
114 : : |* Description notifies the background (all CntntFrms that currently
115 : : |* are overlapping. Additionally, the window is also directly
116 : : |* invalidated (especially where there are no overlapping CntntFrms)
117 : : |* This also takes CntntFrms within other Flys into account.
118 : : |*
119 : : |*************************************************************************/
120 : :
121 : 500 : void SwFlyFreeFrm::NotifyBackground( SwPageFrm *pPageFrm,
122 : : const SwRect& rRect, PrepareHint eHint )
123 : : {
124 : 500 : ::Notify_Background( GetVirtDrawObj(), pPageFrm, rRect, eHint, sal_True );
125 : 500 : }
126 : :
127 : : /*************************************************************************
128 : : |*
129 : : |* SwFlyFreeFrm::MakeAll()
130 : : |*
131 : : |*************************************************************************/
132 : :
133 : 490 : void SwFlyFreeFrm::MakeAll()
134 : : {
135 [ + - ][ + - ]: 490 : if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
[ + - ][ + - ]
[ + - ]
136 : : {
137 : : return;
138 : : }
139 : :
140 [ + - ][ + - ]: 490 : if ( !GetAnchorFrm() || IsLocked() || IsColLocked() )
[ + - ][ - + ]
[ + - ]
141 : : return;
142 : : // #i28701# - use new method <GetPageFrm()>
143 [ + - ][ - + ]: 490 : if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ - + ]
144 : : {
145 [ # # ][ # # ]: 0 : SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
146 [ # # ][ # # ]: 0 : SwPageFrm *pPageFrm = pFly ? pFly->FindPageFrm() : NULL;
147 [ # # ]: 0 : if( pPageFrm )
148 [ # # ]: 0 : pPageFrm->AppendFlyToPage( this );
149 : : }
150 [ + - ][ + - ]: 490 : if( !GetPageFrm() )
151 : : return;
152 : :
153 : 490 : Lock(); // The courtain drops
154 : :
155 : : // takes care of the notification in the dtor
156 [ + - ]: 490 : const SwFlyNotify aNotify( this );
157 : :
158 [ + + ]: 490 : if ( IsClipped() )
159 : : {
160 : 34 : bValidSize = bHeightClipped = bWidthClipped = sal_False;
161 : : // no invalidation of position,
162 : : // if anchored object is anchored inside a Writer fly frame,
163 : : // its position is already locked, and it follows the text flow.
164 : : // #i34753# - add condition:
165 : : // no invalidation of position, if no direct move is requested in <CheckClip(..)>
166 [ + + ][ - + ]: 44 : if ( !IsNoMoveOnCheckClip() &&
[ + + ]
167 [ + - ]: 10 : !( PositionLocked() &&
168 [ # # ][ # # ]: 0 : GetAnchorFrm()->IsInFly() &&
169 [ # # ][ # # ]: 0 : GetFrmFmt().GetFollowTextFlow().GetValue() ) )
[ # # ][ # # ]
170 : : {
171 : 10 : bValidPos = sal_False;
172 : : }
173 : : }
174 : :
175 : : // #i81146# new loop control
176 : 490 : sal_uInt16 nLoopControlRuns = 0;
177 : 490 : const sal_uInt16 nLoopControlMax = 10;
178 : :
179 [ + + ][ + + ]: 1147 : while ( !bValidPos || !bValidSize || !bValidPrtArea || bFormatHeightOnly )
[ + - ][ - + ]
[ + + ]
180 : : {
181 [ + - ][ - + ]: 657 : SWRECTFN( this )
[ # # ][ # # ]
[ - + ]
182 : : const SwFmtFrmSize *pSz;
183 : : { // Additional scope, so aAccess will be destroyed before the check!
184 : :
185 [ + - ]: 657 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
186 [ + - ]: 657 : const SwBorderAttrs &rAttrs = *aAccess.Get();
187 [ + - ]: 657 : pSz = &rAttrs.GetAttrSet().GetFrmSize();
188 : :
189 : : // Only set when the flag is set!
190 [ + + ]: 657 : if ( !bValidSize )
191 : : {
192 : 608 : bValidPrtArea = sal_False;
193 : : }
194 : :
195 [ + + ]: 657 : if ( !bValidPrtArea )
196 [ + - ]: 608 : MakePrtArea( rAttrs );
197 : :
198 [ + + ][ - + ]: 657 : if ( !bValidSize || bFormatHeightOnly )
199 : : {
200 : 608 : bValidSize = sal_False;
201 [ + - ]: 608 : Format( &rAttrs );
202 : 608 : bFormatHeightOnly = sal_False;
203 : : }
204 : :
205 [ + + ]: 657 : if ( !bValidPos )
206 : : {
207 [ + - ][ + - ]: 354 : const Point aOldPos( (Frm().*fnRect->fnGetPos)() );
208 : : // #i26791# - use new method <MakeObjPos()>
209 : : // #i34753# - no positioning, if requested.
210 [ + + ]: 354 : if ( IsNoMakePos() )
211 : 2 : bValidPos = sal_True;
212 : : else
213 : : // #i26791# - use new method <MakeObjPos()>
214 [ + - ]: 352 : MakeObjPos();
215 [ + - ][ + - ]: 354 : if( aOldPos == (Frm().*fnRect->fnGetPos)() )
[ + + ]
216 : : {
217 [ - + ][ # # ]: 195 : if( !bValidPos && GetAnchorFrm()->IsInSct() &&
[ # # ]
[ # # # # ]
[ - + ]
218 [ # # ][ # # ]: 0 : !GetAnchorFrm()->FindSctFrm()->IsValid() )
219 : 0 : bValidPos = sal_True;
220 : : }
221 : : else
222 : 354 : bValidSize = sal_False;
223 [ + - ]: 657 : }
224 : : }
225 : :
226 [ + + ][ + + ]: 657 : if ( bValidPos && bValidSize )
227 : : {
228 : 498 : ++nLoopControlRuns;
229 : :
230 : : OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrm::MakeAll" );
231 : :
232 [ + - ]: 996 : if ( nLoopControlRuns < nLoopControlMax )
233 [ + - ]: 498 : CheckClip( *pSz );
234 : : }
235 : : else
236 : 159 : nLoopControlRuns = 0;
237 : : }
238 [ + - ]: 490 : Unlock();
239 : :
240 : : #if OSL_DEBUG_LEVEL > 0
241 : : SWRECTFN( this )
242 : : OSL_ENSURE( bHeightClipped || ( (Frm().*fnRect->fnGetHeight)() > 0 &&
243 : : (Prt().*fnRect->fnGetHeight)() > 0),
244 : : "SwFlyFreeFrm::Format(), flipping Fly." );
245 : :
246 : : #endif
247 : : }
248 : :
249 : : /** determines, if direct environment of fly frame has 'auto' size
250 : :
251 : : #i17297#
252 : : start with anchor frame and search via <GetUpper()> for a header, footer,
253 : : row or fly frame stopping at page frame.
254 : : return <true>, if such a frame is found and it has 'auto' size.
255 : : otherwise <false> is returned.
256 : :
257 : : @return boolean indicating, that direct environment has 'auto' size
258 : : */
259 : 0 : bool SwFlyFreeFrm::HasEnvironmentAutoSize() const
260 : : {
261 : 0 : bool bRetVal = false;
262 : :
263 : 0 : const SwFrm* pToBeCheckedFrm = GetAnchorFrm();
264 [ # # # # ]: 0 : while ( pToBeCheckedFrm &&
[ # # ]
265 : 0 : !pToBeCheckedFrm->IsPageFrm() )
266 : : {
267 [ # # # # : 0 : if ( pToBeCheckedFrm->IsHeaderFrm() ||
# # # # ]
[ # # ]
268 : 0 : pToBeCheckedFrm->IsFooterFrm() ||
269 : 0 : pToBeCheckedFrm->IsRowFrm() ||
270 : 0 : pToBeCheckedFrm->IsFlyFrm() )
271 : : {
272 : : bRetVal = ATT_FIX_SIZE !=
273 : 0 : pToBeCheckedFrm->GetAttrSet()->GetFrmSize().GetHeightSizeType();
274 : 0 : break;
275 : : }
276 : : else
277 : : {
278 : 0 : pToBeCheckedFrm = pToBeCheckedFrm->GetUpper();
279 : : }
280 : : }
281 : :
282 : 0 : return bRetVal;
283 : : }
284 : :
285 : : /*************************************************************************
286 : : |*
287 : : |* SwFlyFreeFrm::CheckClip()
288 : : |*
289 : : |*************************************************************************/
290 : :
291 : 498 : void SwFlyFreeFrm::CheckClip( const SwFmtFrmSize &rSz )
292 : : {
293 : : // It's probably time now to take appropriate measures, if the Fly
294 : : // doesn't fit into its surrounding.
295 : : // First, the Fly gives up its position, then it's formatted.
296 : : // Only if it still doesn't fit after giving up its position, the
297 : : // width or height are given up as well. The frame will be squeezed
298 : : // as much as needed.
299 : :
300 [ + - ]: 498 : const SwVirtFlyDrawObj *pObj = GetVirtDrawObj();
301 : 498 : SwRect aClip, aTmpStretch;
302 [ + - ]: 498 : ::CalcClipRect( pObj, aClip, sal_True );
303 [ + - ]: 498 : ::CalcClipRect( pObj, aTmpStretch, sal_False );
304 [ + - ]: 498 : aClip._Intersection( aTmpStretch );
305 : :
306 : 498 : const long nBot = Frm().Top() + Frm().Height();
307 : 498 : const long nRig = Frm().Left() + Frm().Width();
308 : 498 : const long nClipBot = aClip.Top() + aClip.Height();
309 : 498 : const long nClipRig = aClip.Left() + aClip.Width();
310 : :
311 : 498 : const sal_Bool bBot = nBot > nClipBot;
312 : 498 : const sal_Bool bRig = nRig > nClipRig;
313 [ - + ][ + + ]: 498 : if ( bBot || bRig )
314 : : {
315 : 42 : sal_Bool bAgain = sal_False;
316 : : // #i37068# - no move, if it's requested
317 [ + - ]: 78 : if ( bBot && !IsNoMoveOnCheckClip() &&
[ + + + - ]
[ + - ][ + + ]
318 [ + - ][ + - ]: 36 : !GetDrawObjs() && !GetAnchorFrm()->IsInTab() )
319 : : {
320 [ + - ]: 18 : SwFrm* pHeader = FindFooterOrHeader();
321 : : // In a header, correction of the position is no good idea.
322 : : // If the fly moves, some paragraphs has to be formatted, this
323 : : // could cause a change of the height of the headerframe,
324 : : // now the flyframe can change its position and so on ...
325 [ - + ][ # # ]: 18 : if ( !pHeader || !pHeader->IsHeaderFrm() )
[ + - ]
326 : : {
327 : 18 : const long nOld = Frm().Top();
328 : 18 : Frm().Pos().Y() = Max( aClip.Top(), nClipBot - Frm().Height() );
329 [ + + ]: 18 : if ( Frm().Top() != nOld )
330 : 8 : bAgain = sal_True;
331 : 18 : bHeightClipped = sal_True;
332 : : }
333 : : }
334 [ - + ]: 42 : if ( bRig )
335 : : {
336 : 0 : const long nOld = Frm().Left();
337 : 0 : Frm().Pos().X() = Max( aClip.Left(), nClipRig - Frm().Width() );
338 [ # # ]: 0 : if ( Frm().Left() != nOld )
339 : : {
340 [ # # ][ # # ]: 0 : const SwFmtHoriOrient &rH = GetFmt()->GetHoriOrient();
341 : : // Left-aligned ones may not be moved to the left when they
342 : : // are avoiding another one.
343 [ # # ]: 0 : if( rH.GetHoriOrient() == text::HoriOrientation::LEFT )
344 : 0 : Frm().Pos().X() = nOld;
345 : : else
346 : 0 : bAgain = sal_True;
347 : : }
348 : 0 : bWidthClipped = sal_True;
349 : : }
350 [ + + ]: 42 : if ( bAgain )
351 : 8 : bValidSize = sal_False;
352 : : else
353 : : {
354 : : // If we reach this branch, the Frm protrudes into forbidden
355 : : // sections, and correcting the position is neither allowed
356 : : // nor possible nor required.
357 : :
358 : : // For Flys with OLE objects as lower, we make sure that
359 : : // we always resize proportionally
360 : 34 : Size aOldSize( Frm().SSize() );
361 : :
362 : : // First, setup the FrmRect, then transfer it to the Frm.
363 : 34 : SwRect aFrmRect( Frm() );
364 : :
365 [ + - ]: 34 : if ( bBot )
366 : : {
367 : 34 : long nDiff = nClipBot;
368 : 34 : nDiff -= aFrmRect.Top(); // nDiff represents the available distance
369 : 34 : nDiff = aFrmRect.Height() - nDiff;
370 : 34 : aFrmRect.Height( aFrmRect.Height() - nDiff );
371 : 34 : bHeightClipped = sal_True;
372 : : }
373 [ - + ]: 34 : if ( bRig )
374 : : {
375 : 0 : long nDiff = nClipRig;
376 : 0 : nDiff -= aFrmRect.Left();// nDiff represents the available distance
377 : 0 : nDiff = aFrmRect.Width() - nDiff;
378 : 0 : aFrmRect.Width( aFrmRect.Width() - nDiff );
379 : 0 : bWidthClipped = sal_True;
380 : : }
381 : :
382 : : // #i17297# - no proportional
383 : : // scaling of graphics in environments, which determines its size
384 : : // by its content ('auto' size). Otherwise layout loops can occur and
385 : : // layout sizes of the environment can be incorrect.
386 : : // Such environment are:
387 : : // (1) header and footer frames with 'auto' size
388 : : // (2) table row frames with 'auto' size
389 : : // (3) fly frames with 'auto' size
390 : : // Note: section frames seems to be not critical - didn't found
391 : : // any critical layout situation so far.
392 [ + - ]: 34 : if ( Lower() && Lower()->IsNoTxtFrm() &&
[ - + # # ]
[ # # ][ - + ]
393 : 0 : ( static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() ||
394 [ # # ]: 0 : !HasEnvironmentAutoSize() ) )
395 : : {
396 : : // If width and height got adjusted, then the bigger
397 : : // change is relevant.
398 [ # # # # ]: 0 : if ( aFrmRect.Width() != aOldSize.Width() &&
[ # # ]
399 : 0 : aFrmRect.Height()!= aOldSize.Height() )
400 : : {
401 [ # # ]: 0 : if ( (aOldSize.Width() - aFrmRect.Width()) >
402 : 0 : (aOldSize.Height()- aFrmRect.Height()) )
403 : 0 : aFrmRect.Height( aOldSize.Height() );
404 : : else
405 : 0 : aFrmRect.Width( aOldSize.Width() );
406 : : }
407 : :
408 : : // Adjusted the width? change height proportionally
409 [ # # ]: 0 : if( aFrmRect.Width() != aOldSize.Width() )
410 : : {
411 : 0 : aFrmRect.Height( aFrmRect.Width() * aOldSize.Height() /
412 : 0 : aOldSize.Width() );
413 : 0 : bHeightClipped = sal_True;
414 : : }
415 : : // Adjusted the height? change width proportionally
416 [ # # ]: 0 : else if( aFrmRect.Height() != aOldSize.Height() )
417 : : {
418 : 0 : aFrmRect.Width( aFrmRect.Height() * aOldSize.Width() /
419 : 0 : aOldSize.Height() );
420 : 0 : bWidthClipped = sal_True;
421 : : }
422 : :
423 : : // #i17297# - reactivate change
424 : : // of size attribute for fly frames containing an ole object.
425 : :
426 : : // Added the aFrmRect.HasArea() hack, because
427 : : // the environment of the ole object does not have to be valid
428 : : // at this moment, or even worse, it does not have to have a
429 : : // resonable size. In this case we do not want to change to
430 : : // attributes permanentely. Maybe one day somebody dares to remove
431 : : // this code.
432 [ # # ]: 0 : if ( aFrmRect.HasArea() &&
[ # # # # ]
[ # # ][ # # ]
[ # # ]
433 : 0 : static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() &&
434 : : ( bWidthClipped || bHeightClipped ) )
435 : : {
436 [ # # ]: 0 : SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
437 : 0 : pFmt->LockModify();
438 [ # # ]: 0 : SwFmtFrmSize aFrmSize( rSz );
439 : 0 : aFrmSize.SetWidth( aFrmRect.Width() );
440 : 0 : aFrmSize.SetHeight( aFrmRect.Height() );
441 [ # # ]: 0 : pFmt->SetFmtAttr( aFrmSize );
442 [ # # ]: 0 : pFmt->UnlockModify();
443 : : }
444 : : }
445 : :
446 : : // Now change the Frm; for columns, we put the new values into the attributes,
447 : : // otherwise we'll end up with unwanted side-effects
448 : 34 : const long nPrtHeightDiff = Frm().Height() - Prt().Height();
449 : 34 : const long nPrtWidthDiff = Frm().Width() - Prt().Width();
450 : 34 : Frm().Height( aFrmRect.Height() );
451 : 34 : Frm().Width ( Max( long(MINLAY), aFrmRect.Width() ) );
452 [ - + ][ - + ]: 34 : if ( Lower() && Lower()->IsColumnFrm() )
[ + - ]
453 : : {
454 : 0 : ColLock(); //lock grow/shrink
455 : 0 : const Size aTmpOldSize( Prt().SSize() );
456 : 0 : Prt().Height( Frm().Height() - nPrtHeightDiff );
457 : 0 : Prt().Width ( Frm().Width() - nPrtWidthDiff );
458 [ # # ]: 0 : ChgLowersProp( aTmpOldSize );
459 : 0 : SwFrm *pLow = Lower();
460 [ # # ]: 0 : do
461 [ # # ]: 0 : { pLow->Calc();
462 : : // also calculate the (Column)BodyFrm
463 [ # # ]: 0 : ((SwLayoutFrm*)pLow)->Lower()->Calc();
464 : 0 : pLow = pLow->GetNext();
465 : : } while ( pLow );
466 [ # # ]: 0 : ::CalcCntnt( this );
467 : 0 : ColUnlock();
468 [ # # ][ # # ]: 0 : if ( !bValidSize && !bWidthClipped )
469 : 0 : bFormatHeightOnly = bValidSize = sal_True;
470 : : }
471 : : else
472 : : {
473 : 34 : Prt().Height( Frm().Height() - nPrtHeightDiff );
474 : 34 : Prt().Width ( Frm().Width() - nPrtWidthDiff );
475 : : }
476 : : }
477 : : }
478 : :
479 : : // #i26945#
480 : : OSL_ENSURE( Frm().Height() >= 0,
481 : : "<SwFlyFreeFrm::CheckClip(..)> - fly frame has negative height now." );
482 : 498 : }
483 : :
484 : : /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
485 : : #i43771#
486 : : */
487 : 537 : bool SwFlyFreeFrm::IsFormatPossible() const
488 : : {
489 : 537 : return SwFlyFrm::IsFormatPossible() &&
490 : 537 : ( GetPageFrm() ||
491 [ # # ][ # # ]: 1074 : ( GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) );
[ + - - + ]
492 : : }
493 : :
494 : : /*************************************************************************
495 : : |*
496 : : |* SwFlyLayFrm::SwFlyLayFrm()
497 : : |*
498 : : |*************************************************************************/
499 : :
500 : 18 : SwFlyLayFrm::SwFlyLayFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
501 : 18 : SwFlyFreeFrm( pFmt, pSib, pAnch )
502 : : {
503 : 18 : bLayout = sal_True;
504 : 18 : }
505 : :
506 : : // #i28701#
507 [ - + ][ + + ]: 4074 : TYPEINIT1(SwFlyLayFrm,SwFlyFreeFrm);
508 : : /*************************************************************************
509 : : |*
510 : : |* SwFlyLayFrm::Modify()
511 : : |*
512 : : |*************************************************************************/
513 : :
514 : 0 : void SwFlyLayFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
515 : : {
516 [ # # ]: 0 : sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
517 : :
518 : 0 : SwFmtAnchor *pAnch = 0;
519 [ # # ][ # # ]: 0 : if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
[ # # ]
520 : 0 : ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
521 [ # # ]: 0 : (const SfxPoolItem**)&pAnch ))
522 : : ; // GetItemState sets the anchor pointer!
523 : :
524 [ # # ]: 0 : else if( RES_ANCHOR == nWhich )
525 : : {
526 : : // Change of anchor. I'm attaching myself to the new place.
527 : : // It's not allowed to change the anchor type. This is only
528 : : // possible via SwFEShell.
529 : 0 : pAnch = (SwFmtAnchor*)pNew;
530 : : }
531 : :
532 [ # # ]: 0 : if( pAnch )
533 : : {
534 : : OSL_ENSURE( pAnch->GetAnchorId() ==
535 : : GetFmt()->GetAnchor().GetAnchorId(),
536 : : "8-) Invalid change of anchor type." );
537 : :
538 : : // Unregister, get hold of the page, attach to the corresponding LayoutFrm.
539 [ # # ]: 0 : SwRect aOld( GetObjRectWithSpaces() );
540 : : // #i28701# - use new method <GetPageFrm()>
541 [ # # ]: 0 : SwPageFrm *pOldPage = GetPageFrm();
542 [ # # ][ # # ]: 0 : AnchorFrm()->RemoveFly( this );
543 : :
544 [ # # ]: 0 : if ( FLY_AT_PAGE == pAnch->GetAnchorId() )
545 : : {
546 : 0 : sal_uInt16 nPgNum = pAnch->GetPageNum();
547 : 0 : SwRootFrm *pRoot = getRootFrm();
548 : 0 : SwPageFrm *pTmpPage = (SwPageFrm*)pRoot->Lower();
549 [ # # ][ # # ]: 0 : for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i,
[ # # ]
550 : 0 : pTmpPage = (SwPageFrm*)pTmpPage->GetNext() )
551 : : {
552 [ # # ]: 0 : if ( i == nPgNum )
553 : : {
554 : : // #i50432# - adjust synopsis of <PlaceFly(..)>
555 [ # # ]: 0 : pTmpPage->PlaceFly( this, 0 );
556 : : }
557 : : }
558 [ # # ]: 0 : if( !pTmpPage )
559 : : {
560 : 0 : pRoot->SetAssertFlyPages();
561 [ # # ]: 0 : pRoot->AssertFlyPages();
562 : : }
563 : : }
564 : : else
565 : : {
566 [ # # ][ # # ]: 0 : SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
567 [ # # ][ # # ]: 0 : SwCntntFrm *pCntnt = GetFmt()->GetDoc()->GetNodes().GoNext( &aIdx )->
[ # # ]
568 [ # # ]: 0 : GetCntntNode()->getLayoutFrm( getRootFrm(), 0, 0, sal_False );
569 [ # # ]: 0 : if( pCntnt )
570 : : {
571 [ # # ]: 0 : SwFlyFrm *pTmp = pCntnt->FindFlyFrm();
572 [ # # ]: 0 : if( pTmp )
573 [ # # ]: 0 : pTmp->AppendFly( this );
574 [ # # ]: 0 : }
575 : : }
576 : : // #i28701# - use new method <GetPageFrm()>
577 [ # # ][ # # ]: 0 : if ( pOldPage && pOldPage != GetPageFrm() )
[ # # ][ # # ]
578 [ # # ]: 0 : NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
579 : 0 : SetCompletePaint();
580 [ # # ]: 0 : InvalidateAll();
581 : 0 : SetNotifyBack();
582 : : }
583 : : else
584 [ # # ]: 0 : SwFlyFrm::Modify( pOld, pNew );
585 : 0 : }
586 : :
587 : : /*************************************************************************
588 : : |*
589 : : |* SwPageFrm::AppendFly()
590 : : |*
591 : : |*************************************************************************/
592 : :
593 : 611 : void SwPageFrm::AppendFlyToPage( SwFlyFrm *pNew )
594 : : {
595 [ - + ]: 611 : if ( !pNew->GetVirtDrawObj()->IsInserted() )
596 : 0 : getRootFrm()->GetDrawPage()->InsertObject(
597 : 0 : (SdrObject*)pNew->GetVirtDrawObj(),
598 : 0 : pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
599 : :
600 : 611 : InvalidateSpelling();
601 : 611 : InvalidateSmartTags(); // SMARTTAGS
602 : 611 : InvalidateAutoCompleteWords();
603 : 611 : InvalidateWordCount();
604 : :
605 [ + - ]: 611 : if ( GetUpper() )
606 : : {
607 : 611 : ((SwRootFrm*)GetUpper())->SetIdleFlags();
608 : 611 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
609 : : }
610 : :
611 : 611 : SdrObject* pObj = pNew->GetVirtDrawObj();
612 : : OSL_ENSURE( pNew->GetAnchorFrm(), "Fly without Anchor" );
613 : 611 : const SwFlyFrm* pFly = pNew->GetAnchorFrm()->FindFlyFrm();
614 [ # # ][ - + ]: 611 : if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() )
[ - + ]
615 : : {
616 : 0 : sal_uInt32 nNewNum = pFly->GetVirtDrawObj()->GetOrdNumDirect();
617 [ # # ]: 0 : if ( pObj->GetPage() )
618 : 0 : pObj->GetPage()->SetObjectOrdNum( pObj->GetOrdNumDirect(), nNewNum);
619 : : else
620 : 0 : pObj->SetOrdNum( nNewNum );
621 : : }
622 : :
623 : : // Don't look further at Flys that sit inside the Cntnt.
624 [ + + ]: 611 : if ( pNew->IsFlyInCntFrm() )
625 : 464 : InvalidateFlyInCnt();
626 : : else
627 : : {
628 : 147 : InvalidateFlyCntnt();
629 : :
630 [ + + ]: 147 : if ( !pSortedObjs )
631 [ + - ]: 79 : pSortedObjs = new SwSortedObjs();
632 : :
633 : 147 : const bool bSucessInserted = pSortedObjs->Insert( *pNew );
634 : : OSL_ENSURE( bSucessInserted, "Fly not inserted in Sorted." );
635 : : (void) bSucessInserted;
636 : :
637 : : // #i87493#
638 : : OSL_ENSURE( pNew->GetPageFrm() == 0 || pNew->GetPageFrm() == this,
639 : : "<SwPageFrm::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect -> please inform OD." );
640 : : // #i28701# - use new method <SetPageFrm(..)>
641 : 147 : pNew->SetPageFrm( this );
642 : 147 : pNew->InvalidatePage( this );
643 : : // #i28701#
644 : 147 : pNew->UnlockPosition();
645 : :
646 : : // Notify accessible layout. That's required at this place for
647 : : // frames only where the anchor is moved. Creation of new frames
648 : : // is additionally handled by the SwFrmNotify class.
649 [ - + ][ + - : 294 : if( GetUpper() &&
- + # # ]
650 : 147 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
651 : 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
652 : : {
653 : 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
654 : 0 : ->AddAccessibleFrm( pNew );
655 : : }
656 : : }
657 : :
658 : : // #i28701# - correction: consider also drawing objects
659 [ - + ]: 611 : if ( pNew->GetDrawObjs() )
660 : : {
661 : 0 : SwSortedObjs &rObjs = *pNew->GetDrawObjs();
662 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
663 : : {
664 : 0 : SwAnchoredObject* pTmpObj = rObjs[i];
665 [ # # ]: 0 : if ( pTmpObj->ISA(SwFlyFrm) )
666 : : {
667 [ # # ]: 0 : SwFlyFrm* pTmpFly = static_cast<SwFlyFrm*>(pTmpObj);
668 : : // #i28701# - use new method <GetPageFrm()>
669 [ # # ][ # # ]: 0 : if ( pTmpFly->IsFlyFreeFrm() && !pTmpFly->GetPageFrm() )
[ # # ]
670 : 0 : AppendFlyToPage( pTmpFly );
671 : : }
672 [ # # ]: 0 : else if ( pTmpObj->ISA(SwAnchoredDrawObject) )
673 : : {
674 : : // #i87493#
675 [ # # ]: 0 : if ( pTmpObj->GetPageFrm() != this )
676 : : {
677 [ # # ]: 0 : if ( pTmpObj->GetPageFrm() != 0 )
678 : : {
679 : 0 : pTmpObj->GetPageFrm()->RemoveDrawObjFromPage( *pTmpObj );
680 : : }
681 : 0 : AppendDrawObjToPage( *pTmpObj );
682 : : }
683 : : }
684 : : }
685 : : }
686 : 611 : }
687 : :
688 : : /*************************************************************************
689 : : |*
690 : : |* SwPageFrm::RemoveFly()
691 : : |*
692 : : |*************************************************************************/
693 : :
694 : 32 : void SwPageFrm::RemoveFlyFromPage( SwFlyFrm *pToRemove )
695 : : {
696 : 32 : const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum();
697 : 32 : getRootFrm()->GetDrawPage()->RemoveObject( nOrdNum );
698 : 32 : pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum );
699 : :
700 [ + - ]: 32 : if ( GetUpper() )
701 : : {
702 [ + + ]: 32 : if ( !pToRemove->IsFlyInCntFrm() )
703 : 26 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
704 : 32 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
705 : : }
706 : :
707 : : // Don't look further at Flys that sit inside the Cntnt.
708 [ + + ]: 32 : if ( pToRemove->IsFlyInCntFrm() )
709 : 32 : return;
710 : :
711 : : // Notify accessible layout. That's required at this place for
712 : : // frames only where the anchor is moved. Creation of new frames
713 : : // is additionally handled by the SwFrmNotify class.
714 [ + - - + : 52 : if( GetUpper() &&
# # ][ - + ]
715 : 26 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
716 : 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
717 : : {
718 : 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
719 : 0 : ->DisposeAccessibleFrm( pToRemove, sal_True );
720 : : }
721 : :
722 : : // Don't delete collections just yet. This will happen at the end of the
723 : : // action in the RemoveSuperfluous of the page, kicked off by a method of
724 : : // the same name in the root.
725 : : // The FlyColl might be gone already, because the page's dtor is being executed.
726 [ + - ]: 26 : if ( pSortedObjs )
727 : : {
728 : 26 : pSortedObjs->Remove( *pToRemove );
729 [ + + ]: 26 : if ( !pSortedObjs->Count() )
730 [ + - ]: 6 : { DELETEZ( pSortedObjs );
731 : : }
732 : : }
733 : : // #i28701# - use new method <SetPageFrm(..)>
734 : 26 : 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 : 573 : void SwPageFrm::AppendDrawObjToPage( SwAnchoredObject& _rNewObj )
848 : : {
849 [ - + ]: 573 : if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
850 : : {
851 : : OSL_FAIL( "SwPageFrm::AppendDrawObjToPage(..) - anchored object of unexcepted type -> object not appended" );
852 : 0 : return;
853 : : }
854 : :
855 [ + - ]: 573 : if ( GetUpper() )
856 : : {
857 : 573 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
858 : : }
859 : :
860 : : OSL_ENSURE( _rNewObj.GetAnchorFrm(), "anchored draw object without anchor" );
861 : 573 : const SwFlyFrm* pFlyFrm = _rNewObj.GetAnchorFrm()->FindFlyFrm();
862 [ - + ]: 573 : if ( pFlyFrm &&
[ - + # # ]
863 : 0 : _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrm->GetVirtDrawObj()->GetOrdNum() )
864 : : {
865 : 0 : sal_uInt32 nNewNum = pFlyFrm->GetVirtDrawObj()->GetOrdNumDirect();
866 [ # # ]: 0 : if ( _rNewObj.GetDrawObj()->GetPage() )
867 : 0 : _rNewObj.DrawObj()->GetPage()->SetObjectOrdNum(
868 : 0 : _rNewObj.GetDrawObj()->GetOrdNumDirect(), nNewNum);
869 : : else
870 : 0 : _rNewObj.DrawObj()->SetOrdNum( nNewNum );
871 : : }
872 : :
873 [ + + ]: 573 : if ( FLY_AS_CHAR == _rNewObj.GetFrmFmt().GetAnchor().GetAnchorId() )
874 : : {
875 : 496 : return;
876 : : }
877 : :
878 [ + + ]: 77 : if ( !pSortedObjs )
879 : : {
880 [ + - ]: 43 : pSortedObjs = new SwSortedObjs();
881 : : }
882 : 77 : 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 : 77 : _rNewObj.SetPageFrm( this );
891 : :
892 : : // invalidate page in order to force a reformat of object layout of the page.
893 : 573 : 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 [ + - ]: 7 : 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 : 16 : 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 [ - + ][ # # ]: 16 : 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 [ - + ]: 16 : if ( pFly )
947 : 0 : AppendFly( pFly );
948 : : else
949 : : { OSL_ENSURE( pFmt, ":-( No Format given for Fly." );
950 [ + - ]: 16 : pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, this, this );
951 : 16 : AppendFly( pFly );
952 : 16 : ::RegistFlys( this, pFly );
953 : : }
954 : : }
955 : 16 : }
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 : 998 : sal_Bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, sal_Bool bMove )
973 : : {
974 : 998 : sal_Bool bRet = sal_True;
975 [ + - ]: 998 : if ( pSdrObj->ISA(SwVirtFlyDrawObj) )
976 : : {
977 : 998 : const SwFlyFrm* pFly = ((const SwVirtFlyDrawObj*)pSdrObj)->GetFlyFrm();
978 : 998 : const bool bFollowTextFlow = pFly->GetFmt()->GetFollowTextFlow().GetValue();
979 : : // #i28701#
980 : : const bool bConsiderWrapOnObjPos =
981 : 998 : pFly->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
982 : 998 : const SwFmtVertOrient &rV = pFly->GetFmt()->GetVertOrient();
983 [ + + ]: 998 : if( pFly->IsFlyLayFrm() )
984 : : {
985 : : const SwFrm* pClip;
986 : : // #i22305#
987 : : // #i28701#
988 [ - + ][ # # ]: 408 : if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
989 : : {
990 : 408 : pClip = pFly->GetAnchorFrm()->FindPageFrm();
991 : : }
992 : : else
993 : : {
994 : 0 : pClip = pFly->GetAnchorFrm();
995 : : }
996 : :
997 : 408 : rRect = pClip->Frm();
998 [ # # ][ # # ]: 408 : SWRECTFN( pClip )
[ - + ][ - + ]
999 : :
1000 : : // vertical clipping: Top and Bottom, also to PrtArea if neccessary
1001 [ + + + + ]: 812 : if( rV.GetVertOrient() != text::VertOrientation::NONE &&
[ + + ]
1002 : 404 : rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
1003 : : {
1004 [ + - ][ + - ]: 400 : (rRect.*fnRect->fnSetTop)( (pClip->*fnRect->fnGetPrtTop)() );
1005 [ + - ][ + - ]: 400 : (rRect.*fnRect->fnSetBottom)( (pClip->*fnRect->fnGetPrtBottom)() );
1006 : : }
1007 : : // horizontal clipping: Top and Bottom, also to PrtArea if necessary
1008 : 408 : const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
1009 [ + + ]: 812 : if( rH.GetHoriOrient() != text::HoriOrientation::NONE &&
[ + + + + ]
1010 : 404 : rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
1011 : : {
1012 [ + - ][ + - ]: 400 : (rRect.*fnRect->fnSetLeft)( (pClip->*fnRect->fnGetPrtLeft)() );
1013 [ + - ][ + - ]: 400 : (rRect.*fnRect->fnSetRight)((pClip->*fnRect->fnGetPrtRight)());
1014 : : }
1015 : : }
1016 [ + - ]: 590 : else if( pFly->IsFlyAtCntFrm() )
1017 : : {
1018 : : // #i18732# - consider following text flow or not
1019 : : // AND alignment at 'page areas'
1020 : 590 : const SwFrm* pVertPosOrientFrm = pFly->GetVertPosOrientFrm();
1021 [ - + ]: 590 : if ( !pVertPosOrientFrm )
1022 : : {
1023 : : OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
1024 : 0 : pVertPosOrientFrm = pFly->GetAnchorFrm();
1025 : : }
1026 : :
1027 [ - + ][ # # ]: 590 : if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
1028 : : {
1029 : 590 : const SwLayoutFrm* pClipFrm = pVertPosOrientFrm->FindPageFrm();
1030 [ - + ]: 590 : if (!pClipFrm)
1031 : : {
1032 : : OSL_FAIL("!pClipFrm: "
1033 : : "if you can reproduce this please file a bug");
1034 : 0 : return false;
1035 : : }
1036 : 294 : rRect = bMove ? pClipFrm->GetUpper()->Frm()
1037 [ + + ]: 884 : : 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 [ - + ]: 590 : if ( pFly->GetAnchorFrm()->IsInTab() )
1042 : : {
1043 : : const SwTabFrm* pTabFrm = const_cast<SwFlyFrm*>(pFly)
1044 [ # # ][ # # ]: 0 : ->GetAnchorFrmContainingAnchPos()->FindTabFrm();
1045 : 0 : SwRect aTmp( pTabFrm->Prt() );
1046 : 0 : aTmp += pTabFrm->Frm().Pos();
1047 [ # # ]: 0 : rRect.Union( aTmp );
1048 : : // #i43913# - consider also the cell frame
1049 : : const SwFrm* pCellFrm = const_cast<SwFlyFrm*>(pFly)
1050 [ # # ]: 0 : ->GetAnchorFrmContainingAnchPos()->GetUpper();
1051 [ # # ][ # # ]: 0 : while ( pCellFrm && !pCellFrm->IsCellFrm() )
[ # # ]
1052 : : {
1053 : 0 : pCellFrm = pCellFrm->GetUpper();
1054 : : }
1055 [ # # ]: 0 : if ( pCellFrm )
1056 : : {
1057 : 0 : aTmp = pCellFrm->Prt();
1058 : 0 : aTmp += pCellFrm->Frm().Pos();
1059 [ # # ]: 0 : rRect.Union( aTmp );
1060 : : }
1061 : 590 : }
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 sections. 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 [ # # ]: 590 : 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 : 998 : return bRet;
1299 : : }
1300 : :
1301 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|