1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_wasm_strip.h>
22 #include <dcontact.hxx>
23 #include <rootfrm.hxx>
24 #include <pagefrm.hxx>
25 #include <tocntntanchoredobjectposition.hxx>
26 #include <tolayoutanchoredobjectposition.hxx>
27 #include <frmtool.hxx>
28 #include <fmtornt.hxx>
31 #include <svx/svdogrp.hxx>
32 #include <tools/fract.hxx>
33 #include <DocumentSettingManager.hxx>
34 #include <IDocumentState.hxx>
35 #include <IDocumentLayoutAccess.hxx>
37 #include <viewimp.hxx>
38 #include <textboxhelper.hxx>
40 #include <svx/svdoashp.hxx>
41 #include <osl/diagnose.h>
43 using namespace ::com::sun::star
;
47 /// helper class for correct notification due to the positioning of
48 /// the anchored drawing object
52 SwAnchoredDrawObject
* mpAnchoredDrawObj
;
54 SwPageFrame
* mpOldPageFrame
;
57 explicit SwPosNotify( SwAnchoredDrawObject
* _pAnchoredDrawObj
);
58 ~SwPosNotify() COVERITY_NOEXCEPT_FALSE
;
60 Point
const & LastObjPos() const;
65 SwPosNotify::SwPosNotify( SwAnchoredDrawObject
* _pAnchoredDrawObj
) :
66 mpAnchoredDrawObj( _pAnchoredDrawObj
)
68 maOldObjRect
= mpAnchoredDrawObj
->GetObjRect();
69 // --> #i35640# - determine correct page frame
70 mpOldPageFrame
= mpAnchoredDrawObj
->GetPageFrame();
73 SwPosNotify::~SwPosNotify() COVERITY_NOEXCEPT_FALSE
75 if ( maOldObjRect
!= mpAnchoredDrawObj
->GetObjRect() )
77 if( maOldObjRect
.HasArea() && mpOldPageFrame
)
79 mpAnchoredDrawObj
->NotifyBackground( mpOldPageFrame
, maOldObjRect
,
80 PrepareHint::FlyFrameLeave
);
82 SwRect
aNewObjRect( mpAnchoredDrawObj
->GetObjRect() );
83 if( aNewObjRect
.HasArea() )
85 // --> #i35640# - determine correct page frame
86 SwPageFrame
* pNewPageFrame
= mpAnchoredDrawObj
->GetPageFrame();
88 mpAnchoredDrawObj
->NotifyBackground( pNewPageFrame
, aNewObjRect
,
89 PrepareHint::FlyFrameArrive
);
92 ::ClrContourCache( mpAnchoredDrawObj
->GetDrawObj() );
94 // --> #i35640# - additional notify anchor text frame
95 // Needed for negative positioned drawing objects
96 // --> #i43255# - refine condition to avoid unneeded
97 // invalidations: anchored object had to be on the page of its anchor
99 if ( mpAnchoredDrawObj
->GetAnchorFrame()->IsTextFrame() &&
100 mpOldPageFrame
== mpAnchoredDrawObj
->GetAnchorFrame()->FindPageFrame() )
102 mpAnchoredDrawObj
->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave
);
105 // indicate a restart of the layout process
106 mpAnchoredDrawObj
->SetRestartLayoutProcess( true );
111 mpAnchoredDrawObj
->LockPosition();
113 if ( !mpAnchoredDrawObj
->ConsiderForTextWrap() )
115 // indicate that object has to be considered for text wrap
116 mpAnchoredDrawObj
->SetConsiderForTextWrap( true );
117 // invalidate 'background' in order to allow its 'background'
118 // to wrap around it.
119 mpAnchoredDrawObj
->NotifyBackground( mpAnchoredDrawObj
->GetPageFrame(),
120 mpAnchoredDrawObj
->GetObjRectWithSpaces(),
121 PrepareHint::FlyFrameArrive
);
122 // invalidate position of anchor frame in order to force
123 // a re-format of the anchor frame, which also causes a
124 // re-format of the invalid previous frames of the anchor frame.
125 mpAnchoredDrawObj
->AnchorFrame()->InvalidatePos();
128 // tdf#101464 notify SwAccessibleMap about new drawing object position
129 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
130 if (mpOldPageFrame
&& mpOldPageFrame
->getRootFrame()->IsAnyShellAccessible())
132 mpOldPageFrame
->getRootFrame()->GetCurrShell()->Imp()->MoveAccessible(
133 nullptr, mpAnchoredDrawObj
->GetDrawObj(), maOldObjRect
);
139 Point
const & SwPosNotify::LastObjPos() const
141 return maOldObjRect
.Pos();
147 /// helper class for oscillation control on object positioning
148 class SwObjPosOscillationControl
151 const SwAnchoredDrawObject
* mpAnchoredDrawObj
;
153 std::vector
<Point
> maObjPositions
;
156 explicit SwObjPosOscillationControl( const SwAnchoredDrawObject
& _rAnchoredDrawObj
);
158 bool OscillationDetected();
163 SwObjPosOscillationControl::SwObjPosOscillationControl(
164 const SwAnchoredDrawObject
& _rAnchoredDrawObj
)
165 : mpAnchoredDrawObj( &_rAnchoredDrawObj
)
169 bool SwObjPosOscillationControl::OscillationDetected()
171 bool bOscillationDetected
= false;
173 if ( maObjPositions
.size() == 20 )
175 // position stack is full -> oscillation
176 bOscillationDetected
= true;
180 Point aNewObjPos
= mpAnchoredDrawObj
->GetObjRect().Pos();
181 for ( auto const & pt
: maObjPositions
)
183 if ( aNewObjPos
== pt
)
185 // position already occurred -> oscillation
186 bOscillationDetected
= true;
190 if ( !bOscillationDetected
)
192 maObjPositions
.push_back( aNewObjPos
);
196 return bOscillationDetected
;
200 SwAnchoredDrawObject::SwAnchoredDrawObject() :
202 mbNotYetAttachedToAnchorFrame( true ),
204 mbNotYetPositioned( true ),
206 mbCaptureAfterLayoutDirChange( false )
210 SwAnchoredDrawObject::~SwAnchoredDrawObject()
215 void SwAnchoredDrawObject::UpdateLayoutDir()
217 SwFrameFormat::tLayoutDir
nOldLayoutDir( GetFrameFormat().GetLayoutDir() );
219 SwAnchoredObject::UpdateLayoutDir();
221 if ( !NotYetPositioned() &&
222 GetFrameFormat().GetLayoutDir() != nOldLayoutDir
&&
223 GetFrameFormat().GetDoc()->GetDocumentSettingManager().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE
) &&
226 mbCaptureAfterLayoutDirChange
= true;
231 bool SwAnchoredDrawObject::IsOutsidePage() const
233 bool bOutsidePage( false );
235 if ( !NotYetPositioned() && GetPageFrame() )
237 SwRect
aTmpRect( GetObjRect() );
239 ( aTmpRect
.Intersection( GetPageFrame()->getFrameArea() ) != GetObjRect() );
245 void SwAnchoredDrawObject::MakeObjPos()
247 if ( IsPositioningInProgress() )
249 // nothing to do - positioning already in progress
255 // nothing to do - position is valid
259 // --> #i28749# - anchored drawing object has to be attached
261 if ( mbNotYetAttachedToAnchorFrame
)
263 OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" );
267 SwDrawContact
* pDrawContact
=
268 static_cast<SwDrawContact
*>(::GetUserCall( GetDrawObj() ));
270 // --> #i28749# - if anchored drawing object hasn't been yet
271 // positioned, convert its positioning attributes, if its positioning
272 // attributes are given in horizontal left-to-right layout.
273 // --> #i36010# - Note: horizontal left-to-right layout is made
274 // the default layout direction for <SwDrawFrameFormat> instances. Thus, it has
275 // to be adjusted manually, if no adjustment of the positioning attributes
276 // have to be performed here.
277 // --> #i35635# - additionally move drawing object to the visible layer.
278 if ( mbNotYetPositioned
)
281 pDrawContact
->MoveObjToVisibleLayer( DrawObj() );
282 // --> perform conversion of positioning
283 // attributes only for 'master' drawing objects
284 // #i44334#, #i44681# - check, if positioning
285 // attributes already have been set.
286 if ( dynamic_cast< const SwDrawVirtObj
* >(GetDrawObj()) == nullptr &&
287 !static_cast<SwDrawFrameFormat
&>(GetFrameFormat()).IsPosAttrSet() )
289 SetPositioningAttr();
292 // - reset internal flag after all needed actions are performed to
293 // avoid callbacks from drawing layer
294 mbNotYetPositioned
= false;
297 // indicate that positioning is in progress
299 SwObjPositioningInProgress
aObjPosInProgress( *this );
301 // determine relative position of drawing object and set it
302 switch ( pDrawContact
->GetAnchorId() )
304 case RndStdIds::FLY_AS_CHAR
:
306 // indicate that position will be valid after positioning is performed
308 // nothing to do, because as-character anchored objects are positioned
309 // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)>
312 case RndStdIds::FLY_AT_PARA
:
313 case RndStdIds::FLY_AT_CHAR
:
315 // --> #i32795# - move intrinsic positioning to
316 // helper method <MakeObjPosAnchoredAtPara()>
317 MakeObjPosAnchoredAtPara();
320 case RndStdIds::FLY_AT_PAGE
:
321 case RndStdIds::FLY_AT_FLY
:
323 // --> #i32795# - move intrinsic positioning to
324 // helper method <MakeObjPosAnchoredAtLayout()>
325 MakeObjPosAnchoredAtLayout();
330 assert(!"<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type.");
334 // keep, current object rectangle
335 // --> #i34748# - use new method <SetLastObjRect(..)>
336 SetLastObjRect( GetObjRect().SVRect() );
338 // Assure for 'master' drawing object, that it's registered at the correct page.
339 // Perform check not for as-character anchored drawing objects and only if
340 // the anchor frame is valid.
341 if ( dynamic_cast< const SwDrawVirtObj
* >(GetDrawObj()) == nullptr &&
342 !pDrawContact
->ObjAnchoredAsChar() &&
343 GetAnchorFrame()->isFrameAreaDefinitionValid() )
345 pDrawContact
->ChkPage();
350 if ( !(mbCaptureAfterLayoutDirChange
&&
354 SwRect
aPageRect( GetPageFrame()->getFrameArea() );
355 SwRect
aObjRect( GetObjRect() );
356 if ( aObjRect
.Right() >= aPageRect
.Right() + 10 )
358 Size
aSize( aPageRect
.Right() - aObjRect
.Right(), 0 );
359 DrawObj()->Move( aSize
);
360 aObjRect
= GetObjRect();
363 if ( aObjRect
.Left() + 10 <= aPageRect
.Left() )
365 Size
aSize( aPageRect
.Left() - aObjRect
.Left(), 0 );
366 DrawObj()->Move( aSize
);
369 mbCaptureAfterLayoutDirChange
= false;
372 /** method for the intrinsic positioning of an at-paragraph|at-character
373 anchored drawing object
375 #i32795# - helper method for method <MakeObjPos>
377 void SwAnchoredDrawObject::MakeObjPosAnchoredAtPara()
379 // --> #i32795# - adopt positioning algorithm from Writer
380 // fly frames, which are anchored at paragraph|at character
382 // Determine, if anchor frame can/has to be formatted.
383 // If yes, after each object positioning the anchor frame is formatted.
384 // If after the anchor frame format the object position isn't valid, the
385 // object is positioned again.
386 // --> #i43255# - refine condition: anchor frame format not
387 // allowed, if another anchored object, has to be consider its wrap influence
388 // --> #i50356# - format anchor frame containing the anchor
389 // position. E.g., for at-character anchored object this can be the follow
390 // frame of the anchor frame, which contains the anchor character.
392 = static_cast<const SwTextFrame
*>(GetAnchorFrameContainingAnchPos())->IsAnyJoinLocked();
393 const bool bFormatAnchor
= !bJoinLocked
&& !ConsiderObjWrapInfluenceOnObjPos()
394 && !ConsiderObjWrapInfluenceOfOtherObjs();
396 // Format of anchor is needed for (vertical) fly offsets, otherwise the
397 // lack of fly portions will result in an incorrect 0 offset.
398 bool bAddVerticalFlyOffsets
= GetFrameFormat().getIDocumentSettingAccess().get(
399 DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS
);
400 bool bFormatAnchorOnce
= !bJoinLocked
&& bAddVerticalFlyOffsets
;
402 if (bFormatAnchor
|| bFormatAnchorOnce
)
405 GetAnchorFrameContainingAnchPos()->Calc(GetAnchorFrameContainingAnchPos()->getRootFrame()->GetCurrShell()->GetOut());
408 bool bOscillationDetected
= false;
409 SwObjPosOscillationControl
aObjPosOscCtrl( *this );
410 // --> #i3317# - boolean, to apply temporarily the
411 // 'straightforward positioning process' for the frame due to its
412 // overlapping with a previous column.
413 bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
415 // indicate that position will be valid after positioning is performed
418 // --> #i35640# - correct scope for <SwPosNotify> instance
420 // create instance of <SwPosNotify> for correct notification
421 SwPosNotify
aPosNotify( this );
423 // determine and set position
424 objectpositioning::SwToContentAnchoredObjectPosition
425 aObjPositioning( *DrawObj() );
426 aObjPositioning
.CalcPosition();
428 // get further needed results of the positioning algorithm
429 SetVertPosOrientFrame ( aObjPositioning
.GetVertPosOrientFrame() );
432 // check for object position oscillation, if position has changed.
433 if ( GetObjRect().Pos() != aPosNotify
.LastObjPos() )
435 bOscillationDetected
= aObjPosOscCtrl
.OscillationDetected();
438 // format anchor frame, if requested.
439 // Note: the format of the anchor frame can cause the object position
444 GetAnchorFrameContainingAnchPos()->Calc(GetAnchorFrameContainingAnchPos()->getRootFrame()->GetCurrShell()->GetOut());
448 if ( !ConsiderObjWrapInfluenceOnObjPos() &&
449 OverlapsPrevColumn() )
451 bConsiderWrapInfluenceDueToOverlapPrevCol
= true;
453 } while ( !mbValidPos
&& !bOscillationDetected
&&
454 !bConsiderWrapInfluenceDueToOverlapPrevCol
);
456 // --> #i3317# - consider a detected oscillation and overlapping
457 // with previous column.
458 // temporarily consider the anchored objects wrapping style influence
459 if ( bOscillationDetected
|| bConsiderWrapInfluenceDueToOverlapPrevCol
)
461 SetTmpConsiderWrapInfluence( true );
462 SetRestartLayoutProcess( true );
466 /** method for the intrinsic positioning of an at-page|at-frame anchored
469 #i32795# - helper method for method <MakeObjPos>
471 void SwAnchoredDrawObject::MakeObjPosAnchoredAtLayout()
473 // indicate that position will be valid after positioning is performed
476 // create instance of <SwPosNotify> for correct notification
477 SwPosNotify
aPosNotify( this );
479 // determine position
480 objectpositioning::SwToLayoutAnchoredObjectPosition
481 aObjPositioning( *DrawObj() );
482 aObjPositioning
.CalcPosition();
487 // --> #i34995# - setting anchor position needed for filters,
488 // especially for the xml-filter to the OpenOffice.org file format
490 const Point aNewAnchorPos
=
491 GetAnchorFrame()->GetFrameAnchorPos( ::HasWrap( GetDrawObj() ) );
492 DrawObj()->SetAnchorPos( aNewAnchorPos
);
493 // --> #i70122# - missing invalidation
494 InvalidateObjRectWithSpaces();
496 SetCurrRelPos( aObjPositioning
.GetRelPos() );
497 const SwFrame
* pAnchorFrame
= GetAnchorFrame();
498 SwRectFnSet
aRectFnSet(pAnchorFrame
);
499 const Point
aAnchPos( aRectFnSet
.GetPos(pAnchorFrame
->getFrameArea()) );
500 SetObjLeft( aAnchPos
.X() + GetCurrRelPos().X() );
501 SetObjTop( aAnchPos
.Y() + GetCurrRelPos().Y() );
504 void SwAnchoredDrawObject::SetDrawObjAnchor()
506 // new anchor position
508 Point aNewAnchorPos
=
509 GetAnchorFrame()->GetFrameAnchorPos( ::HasWrap( GetDrawObj() ) );
510 Point aCurrAnchorPos
= GetDrawObj()->GetAnchorPos();
511 if ( aNewAnchorPos
!= aCurrAnchorPos
)
513 // determine movement to be applied after setting the new anchor position
514 Size
aMove( aCurrAnchorPos
.getX() - aNewAnchorPos
.getX(),
515 aCurrAnchorPos
.getY() - aNewAnchorPos
.getY() );
516 // set new anchor position
517 DrawObj()->SetAnchorPos( aNewAnchorPos
);
518 // correct object position, caused by setting new anchor position
519 DrawObj()->Move( aMove
);
520 // Sync textbox if it wasn't done at move
521 if ( SwTextBoxHelper::isTextBox(&GetFrameFormat(), RES_DRAWFRMFMT
) && GetFrameFormat().GetDoc() &&
522 GetFrameFormat().GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() &&
523 GetFrameFormat().GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()->IsInConstructor())
525 SwTextBoxHelper::changeAnchor(&GetFrameFormat(), GetFrameFormat().FindRealSdrObject());
527 // --> #i70122# - missing invalidation
528 InvalidateObjRectWithSpaces();
532 /** method to invalidate the given page frame
536 void SwAnchoredDrawObject::InvalidatePage_( SwPageFrame
* _pPageFrame
)
538 if ( !_pPageFrame
|| _pPageFrame
->GetFormat()->GetDoc()->IsInDtor() )
541 if ( !_pPageFrame
->GetUpper() )
544 // --> #i35007# - correct invalidation for as-character
546 if ( GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
548 _pPageFrame
->InvalidateFlyInCnt();
552 _pPageFrame
->InvalidateFlyLayout();
555 SwRootFrame
* pRootFrame
= static_cast<SwRootFrame
*>(_pPageFrame
->GetUpper());
556 pRootFrame
->DisallowTurbo();
557 if ( pRootFrame
->GetTurbo() )
559 const SwContentFrame
* pTmpFrame
= pRootFrame
->GetTurbo();
560 pRootFrame
->ResetTurbo();
561 pTmpFrame
->InvalidatePage();
563 pRootFrame
->SetIdleFlags();
566 void SwAnchoredDrawObject::InvalidateObjPos()
568 // --> #i28701# - check, if invalidation is allowed
570 InvalidationOfPosAllowed()) )
575 InvalidateObjRectWithSpaces();
577 // --> #i44339# - check, if anchor frame exists.
578 if ( !GetAnchorFrame() )
581 // --> #118547# - notify anchor frame of as-character
582 // anchored object, because its positioned by the format of its anchor frame.
583 // --> #i44559# - assure, that text hint is already
584 // existing in the text frame
585 if ( GetAnchorFrame()->DynCastTextFrame() != nullptr &&
586 (GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR
) )
588 SwTextFrame
* pAnchorTextFrame( static_cast<SwTextFrame
*>(AnchorFrame()) );
589 if (pAnchorTextFrame
->CalcFlyPos(&GetFrameFormat()) != TextFrameIndex(COMPLETE_STRING
))
591 AnchorFrame()->Prepare( PrepareHint::FlyFrameAttributesChanged
, &GetFrameFormat() );
595 SwPageFrame
* pPageFrame
= AnchorFrame()->FindPageFrame();
596 InvalidatePage_( pPageFrame
);
598 // --> #i32270# - also invalidate page frame, at which the
599 // drawing object is registered at.
600 SwPageFrame
* pPageFrameRegisteredAt
= GetPageFrame();
601 if ( pPageFrameRegisteredAt
&&
602 pPageFrameRegisteredAt
!= pPageFrame
)
604 InvalidatePage_( pPageFrameRegisteredAt
);
606 // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
607 // is replaced by method <FindPageFrameOfAnchor()>. It's return value
608 // have to be checked.
609 SwPageFrame
* pPageFrameOfAnchor
= FindPageFrameOfAnchor();
610 if ( pPageFrameOfAnchor
&&
611 pPageFrameOfAnchor
!= pPageFrame
&&
612 pPageFrameOfAnchor
!= pPageFrameRegisteredAt
)
614 InvalidatePage_( pPageFrameOfAnchor
);
618 SwFrameFormat
& SwAnchoredDrawObject::GetFrameFormat()
620 assert(static_cast<SwDrawContact
*>(GetUserCall(GetDrawObj()))->GetFormat());
621 return *(static_cast<SwDrawContact
*>(GetUserCall(GetDrawObj()))->GetFormat());
623 const SwFrameFormat
& SwAnchoredDrawObject::GetFrameFormat() const
625 assert(static_cast<SwDrawContact
*>(GetUserCall(GetDrawObj()))->GetFormat());
626 return *(static_cast<SwDrawContact
*>(GetUserCall(GetDrawObj()))->GetFormat());
629 SwRect
SwAnchoredDrawObject::GetObjRect() const
631 // use geometry of drawing object
632 //return GetDrawObj()->GetCurrentBoundRect();
633 return SwRect(GetDrawObj()->GetSnapRect());
638 // Imagine an open book, inside margin is the one that is at the inner side of the pages, at the center of the book,
639 // outside margin is at the two opposite edges of the book.
640 // outside --text-- inside | inside --text-- outside
641 // With mirrored margins, when relating the size of an object from the inside margin for example, on the
642 // first page we calculate the new size of the object using the size of the right margin,
643 // on second page the left margin, third page right margin, etc.
644 tools::Long
getInsideOutsideRelativeWidth(bool isOutside
, const SwPageFrame
* const pPageFrame
)
646 // Alternating between the only two possible cases: inside and outside.
647 // Inside = false, Outside = true.
648 auto nPageNum
= pPageFrame
->GetPhyPageNum();
649 if (nPageNum
% 2 == (isOutside
? 0 : 1))
650 return pPageFrame
->GetRightMargin();
652 return pPageFrame
->GetLeftMargin();
657 SwRect
SwAnchoredDrawObject::GetObjBoundRect() const
659 bool bGroupShape
= dynamic_cast<const SdrObjGroup
*>( GetDrawObj() );
660 // Resize objects with relative width or height
661 if ( !bGroupShape
&& GetPageFrame( ) && ( GetDrawObj( )->GetRelativeWidth( ) || GetDrawObj()->GetRelativeHeight( ) ) )
663 tools::Rectangle aCurrObjRect
= GetDrawObj()->GetCurrentBoundRect();
665 tools::Long nTargetWidth
= aCurrObjRect
.GetWidth( );
666 if ( GetDrawObj( )->GetRelativeWidth( ) )
668 tools::Long nWidth
= 0;
669 if (GetDrawObj()->GetRelativeWidthRelation() == text::RelOrientation::FRAME
)
671 nWidth
= GetPageFrame()->getFramePrintArea().SVRect().GetWidth();
672 // Here we handle the relative size of the width of some shape.
673 // The size of the shape's width is going to be relative to the size of the left margin.
674 // E.g.: (left margin = 8 && relative size = 150%) -> width of some shape = 12.
675 else if (GetDrawObj()->GetRelativeWidthRelation() == text::RelOrientation::PAGE_LEFT
)
677 if (GetPageFrame()->GetPageDesc()->GetUseOn() == UseOnPage::Mirror
)
678 // We want to get the width of whatever is going through here using the size of the
680 nWidth
= getInsideOutsideRelativeWidth(true, GetPageFrame());
682 nWidth
= GetPageFrame()->GetLeftMargin();
684 // Same as the left margin above.
685 else if (GetDrawObj()->GetRelativeWidthRelation() == text::RelOrientation::PAGE_RIGHT
)
686 if (GetPageFrame()->GetPageDesc()->GetUseOn() == UseOnPage::Mirror
)
687 // We want to get the width of whatever is going through here using the size of the
689 nWidth
= getInsideOutsideRelativeWidth(false, GetPageFrame());
691 nWidth
= GetPageFrame()->GetRightMargin();
693 nWidth
= GetPageFrame( )->GetBoundRect( GetPageFrame()->getRootFrame()->GetCurrShell()->GetOut() ).SVRect().GetWidth();
694 nTargetWidth
= nWidth
* (*GetDrawObj( )->GetRelativeWidth());
697 bool bCheck
= GetDrawObj()->GetRelativeHeight();
700 auto pObjCustomShape
= dynamic_cast<const SdrObjCustomShape
*>(GetDrawObj());
701 bCheck
= !pObjCustomShape
|| !pObjCustomShape
->IsAutoGrowHeight();
704 tools::Long nTargetHeight
= aCurrObjRect
.GetHeight();
707 tools::Long nHeight
= 0;
708 if (GetDrawObj()->GetRelativeHeightRelation() == text::RelOrientation::FRAME
)
710 nHeight
= GetPageFrame()->getFramePrintArea().SVRect().GetHeight();
711 else if (GetDrawObj()->GetRelativeHeightRelation() == text::RelOrientation::PAGE_PRINT_AREA
)
713 // count required height: print area top = top margin + header
715 const SwHeaderFrame
* pHeaderFrame
= GetPageFrame()->GetHeaderFrame();
717 aHeaderRect
= pHeaderFrame
->GetPaintArea();
718 nHeight
= GetPageFrame()->GetTopMargin() + aHeaderRect
.Height();
720 else if (GetDrawObj()->GetRelativeHeightRelation() == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
)
722 // count required height: print area bottom = bottom margin + footer
724 auto pFooterFrame
= GetPageFrame()->GetFooterFrame();
726 aFooterRect
= pFooterFrame
->GetPaintArea();
727 nHeight
= GetPageFrame()->GetBottomMargin() + aFooterRect
.Height();
730 nHeight
= GetPageFrame( )->GetBoundRect( GetPageFrame()->getRootFrame()->GetCurrShell()->GetOut() ).SVRect().GetHeight();
731 nTargetHeight
= nHeight
* (*GetDrawObj()->GetRelativeHeight());
734 if ( nTargetWidth
!= aCurrObjRect
.GetWidth( ) || nTargetHeight
!= aCurrObjRect
.GetHeight( ) )
736 SwDoc
* pDoc
= const_cast<SwDoc
*>(GetPageFrame()->GetFormat()->GetDoc());
738 bool bEnableSetModified
= pDoc
->getIDocumentState().IsEnableSetModified();
739 pDoc
->getIDocumentState().SetEnableSetModified(false);
740 auto pObject
= const_cast<SdrObject
*>(GetDrawObj());
741 pObject
->Resize( aCurrObjRect
.TopLeft(),
742 Fraction( nTargetWidth
, aCurrObjRect
.GetWidth() ),
743 Fraction( nTargetHeight
, aCurrObjRect
.GetHeight() ), false );
745 if (SwFrameFormat
* pFrameFormat
= FindFrameFormat(pObject
))
747 if (SwTextBoxHelper::isTextBox(pFrameFormat
, RES_DRAWFRMFMT
))
749 // Shape has relative size and also a textbox, update its text area as well.
750 uno::Reference
<drawing::XShape
> xShape(pObject
->getUnoShape(), uno::UNO_QUERY
);
751 SwTextBoxHelper::syncProperty(pFrameFormat
, RES_FRM_SIZE
, MID_FRMSIZE_SIZE
,
752 uno::Any(xShape
->getSize()));
756 pDoc
->getIDocumentState().SetEnableSetModified(bEnableSetModified
);
759 return SwRect(GetDrawObj()->GetCurrentBoundRect());
763 bool SwAnchoredDrawObject::SetObjTop_( const SwTwips _nTop
)
765 SwTwips nDiff
= _nTop
- GetObjRect().Top();
766 DrawObj()->Move( Size( 0, nDiff
) );
770 bool SwAnchoredDrawObject::SetObjLeft_( const SwTwips _nLeft
)
772 SwTwips nDiff
= _nLeft
- GetObjRect().Left();
773 DrawObj()->Move( Size( nDiff
, 0 ) );
778 /** adjust positioning and alignment attributes for new anchor frame
780 #i33313# - add second optional parameter <_pNewObjRect>
782 void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrame
* _pNewAnchorFrame
,
783 const SwRect
* _pNewObjRect
)
785 SwTwips nHoriRelPos
= 0;
786 SwTwips nVertRelPos
= 0;
787 const Point aAnchorPos
= _pNewAnchorFrame
->GetFrameAnchorPos( ::HasWrap( GetDrawObj() ) );
789 const SwRect
aObjRect( _pNewObjRect
? *_pNewObjRect
: GetObjRect() );
790 const bool bVert
= _pNewAnchorFrame
->IsVertical();
791 const bool bR2L
= _pNewAnchorFrame
->IsRightToLeft();
794 nHoriRelPos
= aObjRect
.Top() - aAnchorPos
.Y();
795 nVertRelPos
= aAnchorPos
.X() - aObjRect
.Right();
799 nHoriRelPos
= aAnchorPos
.X() - aObjRect
.Right();
800 nVertRelPos
= aObjRect
.Top() - aAnchorPos
.Y();
804 nHoriRelPos
= aObjRect
.Left() - aAnchorPos
.X();
805 nVertRelPos
= aObjRect
.Top() - aAnchorPos
.Y();
808 SwFormatHoriOrient
hori(nHoriRelPos
, text::HoriOrientation::NONE
, text::RelOrientation::FRAME
);
809 SwFormatVertOrient
vert(nVertRelPos
, text::VertOrientation::NONE
, text::RelOrientation::FRAME
);
810 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
> items(GetFrameFormat().GetDoc()->GetAttrPool());
813 GetFrameFormat().GetDoc()->SetAttr(items
, GetFrameFormat());
816 // --> #i34748# - change return type.
817 // If member <mpLastObjRect> is NULL, create one.
818 void SwAnchoredDrawObject::SetLastObjRect( const tools::Rectangle
& _rNewLastRect
)
820 maLastObjRect
= _rNewLastRect
;
823 void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame()
826 SwAnchoredObject::ObjectAttachedToAnchorFrame();
828 if ( mbNotYetAttachedToAnchorFrame
)
830 mbNotYetAttachedToAnchorFrame
= false;
834 /** method to set positioning attributes
837 During load the positioning attributes aren't set.
838 Thus, the positioning attributes are set by the current object geometry.
839 This method is also used for the conversion for drawing objects
840 (not anchored as-character) imported from OpenOffice.org file format
841 once and directly before the first positioning.
843 void SwAnchoredDrawObject::SetPositioningAttr()
845 SwDrawContact
* pDrawContact
=
846 static_cast<SwDrawContact
*>(GetUserCall( GetDrawObj() ));
848 if ( !pDrawContact
->ObjAnchoredAsChar() )
850 SwRect
aObjRect( GetObjRect() );
852 SwTwips nHoriPos
= aObjRect
.Left();
853 SwTwips nVertPos
= aObjRect
.Top();
854 // #i44334#, #i44681#
855 // perform conversion only if position is in horizontal-left-to-right-layout.
856 if ( GetFrameFormat().GetPositionLayoutDir() ==
857 text::PositionLayoutDir::PositionInHoriL2R
)
859 SwFrameFormat::tLayoutDir eLayoutDir
= GetFrameFormat().GetLayoutDir();
860 switch ( eLayoutDir
)
862 case SwFrameFormat::HORI_L2R
:
867 case SwFrameFormat::HORI_R2L
:
869 nHoriPos
= -aObjRect
.Left() - aObjRect
.Width();
872 case SwFrameFormat::VERT_R2L
:
874 nHoriPos
= aObjRect
.Top();
875 nVertPos
= -aObjRect
.Left() - aObjRect
.Width();
880 assert(!"<SwAnchoredDrawObject::SetPositioningAttr()> - unsupported layout direction");
886 // only change position - do not lose other attributes
888 SwFormatHoriOrient
aHori( GetFrameFormat().GetHoriOrient() );
889 if (nHoriPos
!= aHori
.GetPos()) {
890 aHori
.SetPos( nHoriPos
);
891 InvalidateObjRectWithSpaces();
892 GetFrameFormat().SetFormatAttr( aHori
);
895 SwFormatVertOrient
aVert( GetFrameFormat().GetVertOrient() );
896 if (nVertPos
!= aVert
.GetPos()) {
897 aVert
.SetPos( nVertPos
);
898 InvalidateObjRectWithSpaces();
899 GetFrameFormat().SetFormatAttr( aVert
);
902 // --> #i36010# - set layout direction of the position
903 GetFrameFormat().SetPositionLayoutDir(
904 text::PositionLayoutDir::PositionInLayoutDirOfAnchor
);
906 // --> #i65798# - also for as-character anchored objects
907 // --> #i45952# - indicate that position
908 // attributes are set now.
909 static_cast<SwDrawFrameFormat
&>(GetFrameFormat()).PosAttrSet();
912 void SwAnchoredDrawObject::NotifyBackground( SwPageFrame
* _pPageFrame
,
913 const SwRect
& _rRect
,
916 ::Notify_Background( GetDrawObj(), _pPageFrame
, _rRect
, _eHint
, true );
919 /** method to assure that anchored object is registered at the correct
924 void SwAnchoredDrawObject::RegisterAtCorrectPage()
926 SwPageFrame
* pPageFrame( nullptr );
927 if ( GetVertPosOrientFrame() )
929 pPageFrame
= const_cast<SwPageFrame
*>(GetVertPosOrientFrame()->FindPageFrame());
931 if ( pPageFrame
&& GetPageFrame() != pPageFrame
)
933 RegisterAtPage(*pPageFrame
);
937 void SwAnchoredDrawObject::RegisterAtPage(SwPageFrame
& rPageFrame
)
939 assert(GetPageFrame() != &rPageFrame
);
942 GetPageFrame()->RemoveDrawObjFromPage( *this );
944 rPageFrame
.AppendDrawObjToPage( *this );
947 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */