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