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 <anchoreddrawobject.hxx>
30 : : #include <svx/svdobj.hxx>
31 : : #include <dcontact.hxx>
32 : : #include <rootfrm.hxx>
33 : : #include <pagefrm.hxx>
34 : : #include <cntfrm.hxx>
35 : : #include <doc.hxx>
36 : : #include <tocntntanchoredobjectposition.hxx>
37 : : #include <tolayoutanchoredobjectposition.hxx>
38 : : #include <frmtool.hxx>
39 : : #include <fmtornt.hxx>
40 : : // --> #i32795#
41 : : #include <txtfrm.hxx>
42 : : // --> #i32795#
43 : : // template class <std::vector>
44 : : #include <vector>
45 : :
46 : : // --> #i28749#
47 : : #include <com/sun/star/text/PositionLayoutDir.hpp>
48 : : // --> #i44559#
49 : : #include <ndtxt.hxx>
50 : :
51 : : using namespace ::com::sun::star;
52 : :
53 : : // ============================================================================
54 : : // helper class for correct notification due to the positioning of
55 : : // the anchored drawing object
56 : : // ============================================================================
57 : : class SwPosNotify
58 : : {
59 : : private:
60 : : SwAnchoredDrawObject* mpAnchoredDrawObj;
61 : : SwRect maOldObjRect;
62 : : SwPageFrm* mpOldPageFrm;
63 : :
64 : : public:
65 : : SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj );
66 : : ~SwPosNotify();
67 : : // #i32795#
68 : : Point LastObjPos() const;
69 : : };
70 : :
71 : 77 : SwPosNotify::SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ) :
72 : 77 : mpAnchoredDrawObj( _pAnchoredDrawObj )
73 : : {
74 : 77 : maOldObjRect = mpAnchoredDrawObj->GetObjRect();
75 : : // --> #i35640# - determine correct page frame
76 : 77 : mpOldPageFrm = mpAnchoredDrawObj->GetPageFrm();
77 : 77 : }
78 : :
79 : 77 : SwPosNotify::~SwPosNotify()
80 : : {
81 [ + + ]: 77 : if ( maOldObjRect != mpAnchoredDrawObj->GetObjRect() )
82 : : {
83 [ + - ][ + + ]: 71 : if( maOldObjRect.HasArea() && mpOldPageFrm )
[ + - ][ + + ]
84 : : {
85 : : mpAnchoredDrawObj->NotifyBackground( mpOldPageFrm, maOldObjRect,
86 [ + - ]: 68 : PREP_FLY_LEAVE );
87 : : }
88 [ + - ]: 71 : SwRect aNewObjRect( mpAnchoredDrawObj->GetObjRect() );
89 [ + - ][ + + ]: 71 : if( aNewObjRect.HasArea() )
90 : : {
91 : : // --> #i35640# - determine correct page frame
92 [ + - ]: 68 : SwPageFrm* pNewPageFrm = mpAnchoredDrawObj->GetPageFrm();
93 [ + - ]: 68 : if( pNewPageFrm )
94 : : mpAnchoredDrawObj->NotifyBackground( pNewPageFrm, aNewObjRect,
95 [ + - ]: 68 : PREP_FLY_ARRIVE );
96 : : }
97 : :
98 [ + - ][ + - ]: 71 : ::ClrContourCache( mpAnchoredDrawObj->GetDrawObj() );
99 : :
100 : : // --> #i35640# - additional notify anchor text frame
101 : : // Needed for negative positioned drawing objects
102 : : // --> #i43255# - refine condition to avoid unneeded
103 : : // invalidations: anchored object had to be on the page of its anchor
104 : : // text frame.
105 [ + - ][ + + ]: 128 : if ( mpAnchoredDrawObj->GetAnchorFrm()->IsTxtFrm() &&
[ + - ][ + + ]
106 [ + - ][ + - ]: 57 : mpOldPageFrm == mpAnchoredDrawObj->GetAnchorFrm()->FindPageFrm() )
107 : : {
108 [ + - ][ + - ]: 57 : mpAnchoredDrawObj->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
109 : : }
110 : :
111 : : // indicate a restart of the layout process
112 [ + - ]: 71 : mpAnchoredDrawObj->SetRestartLayoutProcess( true );
113 : : }
114 : : else
115 : : {
116 : : // lock position
117 : 6 : mpAnchoredDrawObj->LockPosition();
118 : :
119 [ - + ]: 6 : if ( !mpAnchoredDrawObj->ConsiderForTextWrap() )
120 : : {
121 : : // indicate that object has to be considered for text wrap
122 : 0 : mpAnchoredDrawObj->SetConsiderForTextWrap( true );
123 : : // invalidate 'background' in order to allow its 'background'
124 : : // to wrap around it.
125 : : mpAnchoredDrawObj->NotifyBackground( mpAnchoredDrawObj->GetPageFrm(),
126 : 0 : mpAnchoredDrawObj->GetObjRectWithSpaces(),
127 : 0 : PREP_FLY_ARRIVE );
128 : : // invalidate position of anchor frame in order to force
129 : : // a re-format of the anchor frame, which also causes a
130 : : // re-format of the invalid previous frames of the anchor frame.
131 : 0 : mpAnchoredDrawObj->AnchorFrm()->InvalidatePos();
132 : : }
133 : : }
134 : 77 : }
135 : :
136 : : // --> #i32795#
137 : 63 : Point SwPosNotify::LastObjPos() const
138 : : {
139 : 63 : return maOldObjRect.Pos();
140 : : }
141 : :
142 : : // ============================================================================
143 : : // #i32795#
144 : : // helper class for oscillation control on object positioning
145 : : // ============================================================================
146 : : class SwObjPosOscillationControl
147 : : {
148 : : private:
149 : : sal_uInt8 mnPosStackSize;
150 : :
151 : : const SwAnchoredDrawObject* mpAnchoredDrawObj;
152 : :
153 : : std::vector<Point*> maObjPositions;
154 : :
155 : : public:
156 : : SwObjPosOscillationControl( const SwAnchoredDrawObject& _rAnchoredDrawObj );
157 : : ~SwObjPosOscillationControl();
158 : :
159 : : bool OscillationDetected();
160 : : };
161 : :
162 : 63 : SwObjPosOscillationControl::SwObjPosOscillationControl(
163 : : const SwAnchoredDrawObject& _rAnchoredDrawObj )
164 : : : mnPosStackSize( 20 ),
165 : 63 : mpAnchoredDrawObj( &_rAnchoredDrawObj )
166 : : {
167 : 63 : }
168 : :
169 : 63 : SwObjPosOscillationControl::~SwObjPosOscillationControl()
170 : : {
171 [ + + ]: 120 : while ( !maObjPositions.empty() )
172 : : {
173 [ + - ]: 57 : Point* pPos = maObjPositions.back();
174 : 57 : delete pPos;
175 : :
176 [ + - ]: 57 : maObjPositions.pop_back();
177 : : }
178 : 63 : }
179 : :
180 : 57 : bool SwObjPosOscillationControl::OscillationDetected()
181 : : {
182 : 57 : bool bOscillationDetected = false;
183 : :
184 [ - + ]: 57 : if ( maObjPositions.size() == mnPosStackSize )
185 : : {
186 : : // position stack is full -> oscillation
187 : 0 : bOscillationDetected = true;
188 : : }
189 : : else
190 : : {
191 [ + - ][ + - ]: 57 : Point* pNewObjPos = new Point( mpAnchoredDrawObj->GetObjRect().Pos() );
192 [ + - ][ - + ]: 114 : for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
193 : 57 : aObjPosIter != maObjPositions.end();
194 : : ++aObjPosIter )
195 : : {
196 [ # # ]: 0 : if ( *(pNewObjPos) == *(*aObjPosIter) )
197 : : {
198 : : // position already occurred -> oscillation
199 : 0 : bOscillationDetected = true;
200 : 0 : delete pNewObjPos;
201 : 0 : break;
202 : : }
203 : : }
204 [ + - ]: 57 : if ( !bOscillationDetected )
205 : : {
206 [ + - ]: 57 : maObjPositions.push_back( pNewObjPos );
207 : : }
208 : : }
209 : :
210 : 57 : return bOscillationDetected;
211 : : }
212 : :
213 : : // ============================================================================
214 : : // implementation of class <SwAnchoredDrawObject>
215 : : // ============================================================================
216 [ + + ][ - + ]: 51394 : TYPEINIT1(SwAnchoredDrawObject,SwAnchoredObject);
217 : :
218 : 688 : SwAnchoredDrawObject::SwAnchoredDrawObject() :
219 : : SwAnchoredObject(),
220 : : mbValidPos( false ),
221 : : // --> #i34748#
222 : : mpLastObjRect( 0L ),
223 : : mbNotYetAttachedToAnchorFrame( true ),
224 : : // --> #i28749#
225 : : mbNotYetPositioned( true ),
226 : : // --> #i62875#
227 : 688 : mbCaptureAfterLayoutDirChange( false )
228 : : {
229 : 688 : }
230 : :
231 : 682 : SwAnchoredDrawObject::~SwAnchoredDrawObject()
232 : : {
233 : : // #i34748#
234 : 682 : delete mpLastObjRect;
235 [ - + ]: 682 : }
236 : :
237 : : // --> #i62875#
238 : 573 : void SwAnchoredDrawObject::UpdateLayoutDir()
239 : : {
240 : 573 : SwFrmFmt::tLayoutDir nOldLayoutDir( GetFrmFmt().GetLayoutDir() );
241 : :
242 : 573 : SwAnchoredObject::UpdateLayoutDir();
243 : :
244 [ - + ][ + + : 590 : if ( !NotYetPositioned() &&
- + # # #
# ]
245 : 17 : GetFrmFmt().GetLayoutDir() != nOldLayoutDir &&
246 : 0 : GetFrmFmt().GetDoc()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
247 : 0 : !IsOutsidePage() )
248 : : {
249 : 0 : mbCaptureAfterLayoutDirChange = true;
250 : : }
251 : 573 : }
252 : :
253 : : // --> #i62875#
254 : 0 : bool SwAnchoredDrawObject::IsOutsidePage() const
255 : : {
256 : 0 : bool bOutsidePage( false );
257 : :
258 [ # # ][ # # ]: 0 : if ( !NotYetPositioned() && GetPageFrm() )
[ # # ]
259 : : {
260 [ # # ]: 0 : SwRect aTmpRect( GetObjRect() );
261 : : bOutsidePage =
262 [ # # ][ # # ]: 0 : ( aTmpRect.Intersection( GetPageFrm()->Frm() ) != GetObjRect() );
[ # # ]
263 : : }
264 : :
265 : 0 : return bOutsidePage;
266 : : }
267 : :
268 : : // =============================================================================
269 : : // #i26791# - implementation of pure virtual method declared in
270 : : // base class <SwAnchoredObject>
271 : : // =============================================================================
272 : 3048 : void SwAnchoredDrawObject::MakeObjPos()
273 : : {
274 [ - + ]: 3048 : if ( IsPositioningInProgress() )
275 : : {
276 : : // nothind to do - positioning already in progress
277 : 0 : return;
278 : : }
279 : :
280 [ + + ]: 3048 : if ( mbValidPos )
281 : : {
282 : : // nothing to do - position is valid
283 : 2475 : return;
284 : : }
285 : :
286 : : // --> #i28749# - anchored drawing object has to be attached
287 : : // to anchor frame
288 [ - + ]: 573 : if ( mbNotYetAttachedToAnchorFrame )
289 : : {
290 : : OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" );
291 : 0 : return;
292 : : }
293 : :
294 : : SwDrawContact* pDrawContact =
295 : 573 : static_cast<SwDrawContact*>(::GetUserCall( GetDrawObj() ));
296 : :
297 : : // --> #i28749# - if anchored drawing object hasn't been yet
298 : : // positioned, convert its positioning attributes, if its positioning
299 : : // attributes are given in horizontal left-to-right layout.
300 : : // --> #i36010# - Note: horizontal left-to-right layout is made
301 : : // the default layout direction for <SwDrawFrmFmt> instances. Thus, it has
302 : : // to be adjusted manually, if no adjustment of the positioning attributes
303 : : // have to be performed here.
304 : : // --> #i35635# - additionally move drawing object to the visible layer.
305 [ + + ]: 573 : if ( mbNotYetPositioned )
306 : : {
307 : : // --> #i35635#
308 : 553 : pDrawContact->MoveObjToVisibleLayer( DrawObj() );
309 : : // --> perform conversion of positioning
310 : : // attributes only for 'master' drawing objects
311 : : // #i44334#, #i44681# - check, if positioning
312 : : // attributes already have been set.
313 [ + + ]: 1106 : if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
[ + - + + ]
314 : 553 : !static_cast<SwDrawFrmFmt&>(GetFrmFmt()).IsPosAttrSet() )
315 : : {
316 : 547 : _SetPositioningAttr();
317 : : }
318 : : // -->
319 : : // - reset internal flag after all needed actions are performed to
320 : : // avoid callbacks from drawing layer
321 : 553 : mbNotYetPositioned = false;
322 : : }
323 : :
324 : : // indicate that positioning is in progress
325 : : {
326 [ + - ]: 573 : SwObjPositioningInProgress aObjPosInProgress( *this );
327 : :
328 : : // determine relative position of drawing object and set it
329 [ + - ]: 573 : switch ( pDrawContact->GetAnchorId() )
[ + + + - ]
330 : : {
331 : : case FLY_AS_CHAR:
332 : : {
333 : : // indicate that position will be valid after positioning is performed
334 : 496 : mbValidPos = true;
335 : : // nothing to do, because as-character anchored objects are positioned
336 : : // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)>
337 : : }
338 : 496 : break;
339 : : case FLY_AT_PARA:
340 : : case FLY_AT_CHAR:
341 : : {
342 : : // --> #i32795# - move intrinsic positioning to
343 : : // helper method <_MakeObjPosAnchoredAtPara()>
344 [ + - ]: 63 : _MakeObjPosAnchoredAtPara();
345 : : }
346 : 63 : break;
347 : : case FLY_AT_PAGE:
348 : : case FLY_AT_FLY:
349 : : {
350 : : // --> #i32795# - move intrinsic positioning to
351 : : // helper method <_MakeObjPosAnchoredAtLayout()>
352 [ + - ]: 14 : _MakeObjPosAnchoredAtLayout();
353 : : }
354 : 14 : break;
355 : : default:
356 : : {
357 : : OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type - please inform OD." );
358 : : }
359 : : }
360 : :
361 : : // keep, current object rectangle
362 : : // --> #i34748# - use new method <SetLastObjRect(..)>
363 [ + - ][ + - ]: 573 : SetLastObjRect( GetObjRect().SVRect() );
[ + - ]
364 : :
365 : : // Assure for 'master' drawing object, that it's registered at the correct page.
366 : : // Perform check not for as-character anchored drawing objects and only if
367 : : // the anchor frame is valid.
368 [ + - ][ + - ]: 1223 : if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
[ + - ][ + - ]
[ + + + - ]
[ + + ]
369 [ + - ]: 573 : !pDrawContact->ObjAnchoredAsChar() &&
370 [ + - ]: 77 : GetAnchorFrm()->IsValid() )
371 : : {
372 [ + - ]: 77 : pDrawContact->ChkPage();
373 [ + - ]: 573 : }
374 : : }
375 : :
376 : : // --> #i62875#
377 [ - + # # ]: 573 : if ( mbCaptureAfterLayoutDirChange &&
[ - + ]
378 : 0 : GetPageFrm() )
379 : : {
380 [ # # ]: 0 : SwRect aPageRect( GetPageFrm()->Frm() );
381 [ # # ]: 0 : SwRect aObjRect( GetObjRect() );
382 [ # # ]: 0 : if ( aObjRect.Right() >= aPageRect.Right() + 10 )
383 : : {
384 : 0 : Size aSize( aPageRect.Right() - aObjRect.Right(), 0 );
385 [ # # ][ # # ]: 0 : DrawObj()->Move( aSize );
386 [ # # ]: 0 : aObjRect = GetObjRect();
387 : : }
388 : :
389 [ # # ]: 0 : if ( aObjRect.Left() + 10 <= aPageRect.Left() )
390 : : {
391 : 0 : Size aSize( aPageRect.Left() - aObjRect.Left(), 0 );
392 [ # # ][ # # ]: 0 : DrawObj()->Move( aSize );
393 : : }
394 : :
395 : 3048 : mbCaptureAfterLayoutDirChange = false;
396 : : }
397 : : }
398 : :
399 : : /** method for the intrinsic positioning of a at-paragraph|at-character
400 : : anchored drawing object
401 : :
402 : : #i32795# - helper method for method <MakeObjPos>
403 : :
404 : : @author OD
405 : : */
406 : 63 : void SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara()
407 : : {
408 : : // --> #i32795# - adopt positioning algorithm from Writer
409 : : // fly frames, which are anchored at paragraph|at character
410 : :
411 : : // Determine, if anchor frame can/has to be formatted.
412 : : // If yes, after each object positioning the anchor frame is formatted.
413 : : // If after the anchor frame format the object position isn't valid, the
414 : : // object is positioned again.
415 : : // --> #i43255# - refine condition: anchor frame format not
416 : : // allowed, if another anchored object, has to be consider its wrap influence
417 : : // --> #i50356# - format anchor frame containing the anchor
418 : : // position. E.g., for at-character anchored object this can be the follow
419 : : // frame of the anchor frame, which contains the anchor character.
420 : : const bool bFormatAnchor =
421 [ + - ][ + - ]: 63 : !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
422 [ + - ]: 63 : !ConsiderObjWrapInfluenceOnObjPos() &&
423 [ + - ][ + - ]: 126 : !ConsiderObjWrapInfluenceOfOtherObjs();
[ + - ][ + - ]
424 : :
425 [ + - ]: 63 : if ( bFormatAnchor )
426 : : {
427 : : // --> #i50356#
428 [ + - ][ + - ]: 63 : GetAnchorFrmContainingAnchPos()->Calc();
429 : : }
430 : :
431 : 63 : bool bOscillationDetected = false;
432 [ + - ]: 63 : SwObjPosOscillationControl aObjPosOscCtrl( *this );
433 : : // --> #i3317# - boolean, to apply temporarly the
434 : : // 'straightforward positioning process' for the frame due to its
435 : : // overlapping with a previous column.
436 : 63 : bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
437 [ - + ][ # # ]: 63 : do {
[ # # ][ - + ]
438 : : // indicate that position will be valid after positioning is performed
439 : 63 : mbValidPos = true;
440 : :
441 : : // --> #i35640# - correct scope for <SwPosNotify> instance
442 : : {
443 : : // create instance of <SwPosNotify> for correct notification
444 [ + - ]: 63 : SwPosNotify aPosNotify( this );
445 : :
446 : : // determine and set position
447 : : objectpositioning::SwToCntntAnchoredObjectPosition
448 [ + - ][ + - ]: 63 : aObjPositioning( *DrawObj() );
449 [ + - ]: 63 : aObjPositioning.CalcPosition();
450 : :
451 : : // get further needed results of the positioning algorithm
452 [ + - ][ + - ]: 63 : SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
453 [ + - ]: 63 : _SetDrawObjAnchor();
454 : :
455 : : // check for object position oscillation, if position has changed.
456 [ + - ][ + + ]: 63 : if ( GetObjRect().Pos() != aPosNotify.LastObjPos() )
457 : : {
458 [ + - ]: 57 : bOscillationDetected = aObjPosOscCtrl.OscillationDetected();
459 [ + - ][ + - ]: 63 : }
460 : : }
461 : : // format anchor frame, if requested.
462 : : // Note: the format of the anchor frame can cause the object position
463 : : // to be invalid.
464 [ + - ]: 63 : if ( bFormatAnchor )
465 : : {
466 : : // --> #i50356#
467 [ + - ][ + - ]: 63 : GetAnchorFrmContainingAnchPos()->Calc();
468 : : }
469 : :
470 : : // --> #i3317#
471 [ + - ][ + - ]: 126 : if ( !ConsiderObjWrapInfluenceOnObjPos() &&
[ - + ][ - + ]
472 [ + - ]: 63 : OverlapsPrevColumn() )
473 : : {
474 : 0 : bConsiderWrapInfluenceDueToOverlapPrevCol = true;
475 : : }
476 : 63 : } while ( !mbValidPos && !bOscillationDetected &&
477 : 0 : !bConsiderWrapInfluenceDueToOverlapPrevCol );
478 : :
479 : : // --> #i3317# - consider a detected oscillation and overlapping
480 : : // with previous column.
481 : : // temporarly consider the anchored objects wrapping style influence
482 [ + - ][ - + ]: 63 : if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol )
483 : : {
484 [ # # ]: 0 : SetTmpConsiderWrapInfluence( true );
485 [ # # ]: 0 : SetRestartLayoutProcess( true );
486 [ + - ]: 63 : }
487 : 63 : }
488 : :
489 : : /** method for the intrinsic positioning of a at-page|at-frame anchored
490 : : drawing object
491 : :
492 : : #i32795# - helper method for method <MakeObjPos>
493 : :
494 : : @author OD
495 : : */
496 : 14 : void SwAnchoredDrawObject::_MakeObjPosAnchoredAtLayout()
497 : : {
498 : : // indicate that position will be valid after positioning is performed
499 : 14 : mbValidPos = true;
500 : :
501 : : // create instance of <SwPosNotify> for correct notification
502 [ + - ]: 14 : SwPosNotify aPosNotify( this );
503 : :
504 : : // determine position
505 : : objectpositioning::SwToLayoutAnchoredObjectPosition
506 [ + - ][ + - ]: 14 : aObjPositioning( *DrawObj() );
507 [ + - ]: 14 : aObjPositioning.CalcPosition();
508 : :
509 : : // set position
510 : :
511 : : // --> #i31698#
512 : : // --> #i34995# - setting anchor position needed for filters,
513 : : // especially for the xml-filter to the OpenOffice.org file format
514 : : {
515 : : const Point aNewAnchorPos =
516 [ + - ][ + - ]: 14 : GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
[ + - ][ + - ]
517 [ + - ][ + - ]: 14 : DrawObj()->SetAnchorPos( aNewAnchorPos );
518 : : // --> #i70122# - missing invalidation
519 : 14 : InvalidateObjRectWithSpaces();
520 : : }
521 [ + - ][ + - ]: 14 : SetCurrRelPos( aObjPositioning.GetRelPos() );
522 [ + - ]: 14 : const SwFrm* pAnchorFrm = GetAnchorFrm();
523 [ + - ][ - + ]: 14 : SWRECTFN( pAnchorFrm );
[ # # ][ # # ]
[ - + ]
524 [ + - ][ + - ]: 14 : const Point aAnchPos( (pAnchorFrm->Frm().*fnRect->fnGetPos)() );
525 [ + - ][ + - ]: 14 : SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() );
526 [ + - ][ + - ]: 14 : SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() );
[ + - ][ + - ]
527 : 14 : }
528 : :
529 : 63 : void SwAnchoredDrawObject::_SetDrawObjAnchor()
530 : : {
531 : : // new anchor position
532 : : // --> #i31698# -
533 : : Point aNewAnchorPos =
534 [ + - ][ + - ]: 63 : GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
[ + - ][ + - ]
535 [ + - ][ + - ]: 63 : Point aCurrAnchorPos = GetDrawObj()->GetAnchorPos();
536 [ + + ]: 63 : if ( aNewAnchorPos != aCurrAnchorPos )
537 : : {
538 : : // determine movement to be applied after setting the new anchor position
539 : 57 : Size aMove( aCurrAnchorPos.X() - aNewAnchorPos.X(),
540 : 114 : aCurrAnchorPos.Y() - aNewAnchorPos.Y() );
541 : : // set new anchor position
542 [ + - ][ + - ]: 57 : DrawObj()->SetAnchorPos( aNewAnchorPos );
543 : : // correct object position, caused by setting new anchor position
544 [ + - ][ + - ]: 57 : DrawObj()->Move( aMove );
545 : : // --> #i70122# - missing invalidation
546 : 57 : InvalidateObjRectWithSpaces();
547 : : }
548 : 63 : }
549 : :
550 : : /** method to invalidate the given page frame
551 : :
552 : : #i28701#
553 : :
554 : : @author OD
555 : : */
556 : 24 : void SwAnchoredDrawObject::_InvalidatePage( SwPageFrm* _pPageFrm )
557 : : {
558 [ + - ][ + - ]: 24 : if ( _pPageFrm && !_pPageFrm->GetFmt()->GetDoc()->IsInDtor() )
[ + - ]
559 : : {
560 [ + - ]: 24 : if ( _pPageFrm->GetUpper() )
561 : : {
562 : : // --> #i35007# - correct invalidation for as-character
563 : : // anchored objects.
564 [ + + ]: 24 : if ( GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR )
565 : : {
566 : 18 : _pPageFrm->InvalidateFlyInCnt();
567 : : }
568 : : else
569 : : {
570 : 6 : _pPageFrm->InvalidateFlyLayout();
571 : : }
572 : :
573 : 24 : SwRootFrm* pRootFrm = static_cast<SwRootFrm*>(_pPageFrm->GetUpper());
574 : 24 : pRootFrm->DisallowTurbo();
575 [ - + ]: 24 : if ( pRootFrm->GetTurbo() )
576 : : {
577 : 0 : const SwCntntFrm* pTmpFrm = pRootFrm->GetTurbo();
578 : 0 : pRootFrm->ResetTurbo();
579 : 0 : pTmpFrm->InvalidatePage();
580 : : }
581 : 24 : pRootFrm->SetIdleFlags();
582 : : }
583 : : }
584 : 24 : }
585 : :
586 : 1873 : void SwAnchoredDrawObject::InvalidateObjPos()
587 : : {
588 : : // --> #i28701# - check, if invalidation is allowed
589 [ + + + - ]: 1893 : if ( mbValidPos &&
[ + + ]
590 : 20 : InvalidationOfPosAllowed() )
591 : : {
592 : 20 : mbValidPos = false;
593 : : // --> #i68520#
594 : 20 : InvalidateObjRectWithSpaces();
595 : :
596 : : // --> #i44339# - check, if anchor frame exists.
597 [ + - ]: 20 : if ( GetAnchorFrm() )
598 : : {
599 : : // --> #118547# - notify anchor frame of as-character
600 : : // anchored object, because its positioned by the format of its anchor frame.
601 : : // --> #i44559# - assure, that text hint is already
602 : : // existing in the text frame
603 [ + - + + ]: 40 : if ( GetAnchorFrm()->ISA(SwTxtFrm) &&
[ + + ]
604 : 20 : (GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
605 : : {
606 : 14 : SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
607 [ + - ]: 28 : if ( pAnchorTxtFrm->GetTxtNode()->GetpSwpHints() &&
[ + - + - ]
608 : 14 : pAnchorTxtFrm->CalcFlyPos( &GetFrmFmt() ) != STRING_LEN )
609 : : {
610 : 14 : AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
611 : : }
612 : : }
613 : :
614 : 20 : SwPageFrm* pPageFrm = AnchorFrm()->FindPageFrm();
615 : 20 : _InvalidatePage( pPageFrm );
616 : :
617 : : // --> #i32270# - also invalidate page frame, at which the
618 : : // drawing object is registered at.
619 : 20 : SwPageFrm* pPageFrmRegisteredAt = GetPageFrm();
620 [ - + ][ + + ]: 20 : if ( pPageFrmRegisteredAt &&
621 : : pPageFrmRegisteredAt != pPageFrm )
622 : : {
623 : 0 : _InvalidatePage( pPageFrmRegisteredAt );
624 : : }
625 : : // #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
626 : : // is replaced by method <FindPageFrmOfAnchor()>. It's return value
627 : : // have to be checked.
628 : 20 : SwPageFrm* pPageFrmOfAnchor = FindPageFrmOfAnchor();
629 [ + + ][ + - ]: 20 : if ( pPageFrmOfAnchor &&
[ + - ]
630 : : pPageFrmOfAnchor != pPageFrm &&
631 : : pPageFrmOfAnchor != pPageFrmRegisteredAt )
632 : : {
633 : 4 : _InvalidatePage( pPageFrmOfAnchor );
634 : : }
635 : : }
636 : : }
637 : 1873 : }
638 : :
639 : 12916 : SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt()
640 : : {
641 : : OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
642 : : "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
643 : 12916 : return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
644 : : }
645 : 6762 : const SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() const
646 : : {
647 : : OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
648 : : "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
649 : 6762 : return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
650 : : }
651 : :
652 : 9881 : const SwRect SwAnchoredDrawObject::GetObjRect() const
653 : : {
654 : : // use geometry of drawing object
655 : : //return GetDrawObj()->GetCurrentBoundRect();
656 : 9881 : return GetDrawObj()->GetSnapRect();
657 : : }
658 : :
659 : : // --> #i70122#
660 : 633 : const SwRect SwAnchoredDrawObject::GetObjBoundRect() const
661 : : {
662 : 633 : return GetDrawObj()->GetCurrentBoundRect();
663 : : }
664 : :
665 : : // --> #i68520#
666 : 203 : bool SwAnchoredDrawObject::_SetObjTop( const SwTwips _nTop )
667 : : {
668 : 203 : SwTwips nDiff = _nTop - GetObjRect().Top();
669 [ + - ]: 203 : DrawObj()->Move( Size( 0, nDiff ) );
670 : :
671 : 203 : return nDiff != 0;
672 : : }
673 : 77 : bool SwAnchoredDrawObject::_SetObjLeft( const SwTwips _nLeft )
674 : : {
675 : 77 : SwTwips nDiff = _nLeft - GetObjRect().Left();
676 [ + - ]: 77 : DrawObj()->Move( Size( nDiff, 0 ) );
677 : :
678 : 77 : return nDiff != 0;
679 : : }
680 : :
681 : : /** adjust positioning and alignment attributes for new anchor frame
682 : :
683 : : #i33313# - add second optional parameter <_pNewObjRect>
684 : :
685 : : @author OD
686 : : */
687 : 0 : void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrm* _pNewAnchorFrm,
688 : : const SwRect* _pNewObjRect )
689 : : {
690 : 0 : SwTwips nHoriRelPos = 0;
691 : 0 : SwTwips nVertRelPos = 0;
692 [ # # ][ # # ]: 0 : const Point aAnchorPos = _pNewAnchorFrm->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
[ # # ]
693 : : // --> #i33313#
694 [ # # ][ # # ]: 0 : const SwRect aObjRect( _pNewObjRect ? *_pNewObjRect : GetObjRect() );
695 [ # # ]: 0 : const bool bVert = _pNewAnchorFrm->IsVertical();
696 [ # # ]: 0 : const bool bR2L = _pNewAnchorFrm->IsRightToLeft();
697 [ # # ]: 0 : if ( bVert )
698 : : {
699 : 0 : nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
700 : 0 : nVertRelPos = aAnchorPos.X() - aObjRect.Right();
701 : : }
702 [ # # ]: 0 : else if ( bR2L )
703 : : {
704 : 0 : nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
705 : 0 : nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
706 : : }
707 : : else
708 : : {
709 : 0 : nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
710 : 0 : nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
711 : : }
712 : :
713 [ # # ][ # # ]: 0 : GetFrmFmt().SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
[ # # ][ # # ]
714 [ # # ][ # # ]: 0 : GetFrmFmt().SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
[ # # ][ # # ]
715 : 0 : }
716 : :
717 : : // --> #i34748# - change return type
718 : 0 : const Rectangle* SwAnchoredDrawObject::GetLastObjRect() const
719 : : {
720 : 0 : return mpLastObjRect;
721 : : }
722 : :
723 : : // --> #i34748# - change return type.
724 : : // If member <mpLastObjRect> is NULL, create one.
725 : 2748 : void SwAnchoredDrawObject::SetLastObjRect( const Rectangle& _rNewLastRect )
726 : : {
727 [ + + ]: 2748 : if ( !mpLastObjRect )
728 : : {
729 [ + - ]: 553 : mpLastObjRect = new Rectangle;
730 : : }
731 : 2748 : *(mpLastObjRect) = _rNewLastRect;
732 : 2748 : }
733 : :
734 : 573 : void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame()
735 : : {
736 : : // --> #i31698#
737 : 573 : SwAnchoredObject::ObjectAttachedToAnchorFrame();
738 : :
739 [ + + ]: 573 : if ( mbNotYetAttachedToAnchorFrame )
740 : : {
741 : 556 : mbNotYetAttachedToAnchorFrame = false;
742 : : }
743 : 573 : }
744 : :
745 : : /** method to set positioning attributes
746 : :
747 : : #i35798#
748 : : During load the positioning attributes aren't set.
749 : : Thus, the positioning attributes are set by the current object geometry.
750 : : This method is also used for the conversion for drawing objects
751 : : (not anchored as-character) imported from OpenOffice.org file format
752 : : once and directly before the first positioning.
753 : :
754 : : @author OD
755 : : */
756 : 547 : void SwAnchoredDrawObject::_SetPositioningAttr()
757 : : {
758 : : SwDrawContact* pDrawContact =
759 : 547 : static_cast<SwDrawContact*>(GetUserCall( GetDrawObj() ));
760 : :
761 [ + + ]: 547 : if ( !pDrawContact->ObjAnchoredAsChar() )
762 : : {
763 [ + - ]: 68 : SwRect aObjRect( GetObjRect() );
764 : :
765 : 68 : SwTwips nHoriPos = aObjRect.Left();
766 : 68 : SwTwips nVertPos = aObjRect.Top();
767 : : // #i44334#, #i44681#
768 : : // perform conversion only if position is in horizontal-left-to-right-layout.
769 [ + - ][ + + ]: 68 : if ( GetFrmFmt().GetPositionLayoutDir() ==
[ + - ]
770 : : text::PositionLayoutDir::PositionInHoriL2R )
771 : : {
772 [ + - ][ + - ]: 6 : SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt().GetLayoutDir();
773 [ + - - - ]: 6 : switch ( eLayoutDir )
774 : : {
775 : : case SwFrmFmt::HORI_L2R:
776 : : {
777 : : // nothing to do
778 : : }
779 : 6 : break;
780 : : case SwFrmFmt::HORI_R2L:
781 : : {
782 : 0 : nHoriPos = -aObjRect.Left() - aObjRect.Width();
783 : : }
784 : 0 : break;
785 : : case SwFrmFmt::VERT_R2L:
786 : : {
787 : 0 : nHoriPos = aObjRect.Top();
788 : 0 : nVertPos = -aObjRect.Left() - aObjRect.Width();
789 : : }
790 : 6 : break;
791 : : default:
792 : : {
793 : : OSL_FAIL( "<SwAnchoredDrawObject::_SetPositioningAttr()> - unsupported layout direction" );
794 : : }
795 : : }
796 : : }
797 : :
798 : : // --> #i71182#
799 : : // only change position - do not lose other attributes
800 [ + - ][ + - ]: 68 : SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
[ + - ]
801 : : // If the object is already positioned, leave it alone.
802 [ + + ]: 68 : if (!aHori.GetPos())
803 : 65 : aHori.SetPos( nHoriPos );
804 [ + - ][ + - ]: 68 : GetFrmFmt().SetFmtAttr( aHori );
805 : :
806 [ + - ][ + - ]: 68 : SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
[ + - ]
807 : :
808 [ + + ]: 68 : if (!aVert.GetPos())
809 : 65 : aVert.SetPos( nVertPos );
810 [ + - ][ + - ]: 68 : GetFrmFmt().SetFmtAttr( aVert );
811 : :
812 : : // --> #i36010# - set layout direction of the position
813 [ + - ]: 68 : GetFrmFmt().SetPositionLayoutDir(
814 [ + - ][ + - ]: 68 : text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
[ + - ]
815 : : }
816 : : // --> #i65798# - also for as-character anchored objects
817 : : // --> #i45952# - indicate that position
818 : : // attributes are set now.
819 : 547 : static_cast<SwDrawFrmFmt&>(GetFrmFmt()).PosAttrSet();
820 : 547 : }
821 : :
822 : 136 : void SwAnchoredDrawObject::NotifyBackground( SwPageFrm* _pPageFrm,
823 : : const SwRect& _rRect,
824 : : PrepareHint _eHint )
825 : : {
826 : 136 : ::Notify_Background( GetDrawObj(), _pPageFrm, _rRect, _eHint, sal_True );
827 : 136 : }
828 : :
829 : : /** method to assure that anchored object is registered at the correct
830 : : page frame
831 : :
832 : : #i28701#
833 : :
834 : : @author OD
835 : : */
836 : 63 : void SwAnchoredDrawObject::RegisterAtCorrectPage()
837 : : {
838 : 63 : SwPageFrm* pPageFrm( 0L );
839 [ + - ]: 63 : if ( GetVertPosOrientFrm() )
840 : : {
841 : 63 : pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
842 : : }
843 [ + - ][ - + ]: 63 : if ( pPageFrm && GetPageFrm() != pPageFrm )
[ - + ]
844 : : {
845 [ # # ]: 0 : if ( GetPageFrm() )
846 : 0 : GetPageFrm()->RemoveDrawObjFromPage( *this );
847 : 0 : pPageFrm->AppendDrawObjToPage( *this );
848 : : }
849 : 63 : }
850 : :
851 : : // =============================================================================
852 : :
853 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|