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