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 <svl/itemiter.hxx>
23 #include <vcl/imap.hxx>
24 #include <tools/helpers.hxx>
25 #include <editeng/protitem.hxx>
26 #include <editeng/opaqitem.hxx>
27 #include <editeng/ulspitem.hxx>
28 #include <editeng/frmdiritem.hxx>
29 #include <fmtfsize.hxx>
30 #include <fmtclds.hxx>
31 #include <fmtcntnt.hxx>
33 #include <fmtsrnd.hxx>
34 #include <fmtornt.hxx>
35 #include <fmtcnct.hxx>
37 #include <tolayoutanchoredobjectposition.hxx>
38 #include <fmtfollowtextflow.hxx>
39 #include <sortedobjs.hxx>
40 #include <objectformatter.hxx>
42 #include <swtable.hxx>
43 #include <svx/svdoashp.hxx>
44 #include <svx/svdpage.hxx>
45 #include <layouter.hxx>
46 #include <pagefrm.hxx>
47 #include <rootfrm.hxx>
48 #include <viewimp.hxx>
49 #include <viewopt.hxx>
50 #include <dcontact.hxx>
51 #include <dflyobj.hxx>
54 #include <frmtool.hxx>
58 #include <notxtfrm.hxx>
59 #include <flyfrms.hxx>
60 #include <sectfrm.hxx>
61 #include <vcl/svapp.hxx>
63 #include <IDocumentDrawModelAccess.hxx>
64 #include <IDocumentSettingAccess.hxx>
65 #include <IDocumentLayoutAccess.hxx>
66 #include <textboxhelper.hxx>
68 #include <ndindex.hxx>
69 #include <basegfx/matrix/b2dhommatrixtools.hxx>
70 #include <osl/diagnose.h>
71 #include <o3tl/string_view.hxx>
76 #include <bodyfrm.hxx>
77 #include <FrameControlsManager.hxx>
79 #include <formatflysplit.hxx>
81 using namespace ::com::sun::star
;
85 /// Gets the bottom position which is a deadline for a split fly.
86 SwTwips
GetFlyAnchorBottom(SwFlyFrame
* pFly
, const SwFrame
& rAnchor
)
88 SwRectFnSet
aRectFnSet(pFly
);
90 const SwPageFrame
* pPage
= rAnchor
.FindPageFrame();
96 const SwFrame
* pBody
= pPage
->FindBodyCont();
102 const auto& rFrameFormat
= pFly
->GetFrameFormat();
103 const IDocumentSettingAccess
& rIDSA
= rFrameFormat
.getIDocumentSettingAccess();
104 // Allow overlap with bottom margin / footer only in case we're relative to the page frame.
105 bool bVertPageFrame
= rFrameFormat
.GetVertOrient().GetRelationOrient() == text::RelOrientation::PAGE_FRAME
;
106 bool bInBody
= rAnchor
.IsInDocBody();
107 bool bLegacy
= rIDSA
.get(DocumentSettingId::TAB_OVER_MARGIN
) && (bVertPageFrame
|| !bInBody
);
110 // Word <= 2010 style: the fly can overlap with the bottom margin / footer area in case the
111 // fly height fits the body height and the fly bottom fits the page.
112 // See if the fly height would fit at least the page height, ignoring the vertical offset.
113 SwTwips nFlyHeight
= aRectFnSet
.GetHeight(pFly
->getFrameArea());
114 SwTwips nPageHeight
= aRectFnSet
.GetHeight(pPage
->getFramePrintArea());
115 SwTwips nFlyTop
= aRectFnSet
.GetTop(pFly
->getFrameArea());
116 SwTwips nBodyTop
= aRectFnSet
.GetTop(pBody
->getFrameArea());
117 if (nFlyTop
< nBodyTop
)
119 // Fly frame overlaps with the top margin area, ignore that part of the fly frame for
120 // top/height purposes.
121 nFlyHeight
-= nBodyTop
- nFlyTop
;
124 if (nFlyHeight
<= nPageHeight
)
126 // Yes, it would fit: allow overlap if there is no problematic vertical offset.
127 SwTwips nDeadline
= aRectFnSet
.GetBottom(pPage
->getFrameArea());
128 SwTwips nBodyHeight
= aRectFnSet
.GetHeight(pBody
->getFramePrintArea());
129 if (nDeadline
- nFlyTop
> nBodyHeight
)
131 // If the fly would now grow to nDeadline then it would not fit the body height, so
133 nDeadline
= nFlyTop
+ nBodyHeight
;
139 // Word >= 2013 style: the fly has to stay inside the body frame.
140 return aRectFnSet
.GetPrtBottom(*pBody
);
144 static SwTwips
lcl_CalcAutoWidth( const SwLayoutFrame
& rFrame
);
146 SwFlyFrame::SwFlyFrame( SwFlyFrameFormat
*pFormat
, SwFrame
* pSib
, SwFrame
*pAnch
, bool bFollow
) :
147 SwLayoutFrame( pFormat
, pSib
),
149 m_pPrevLink( nullptr ),
150 m_pNextLink( nullptr ),
154 m_bAutoPosition( false ),
156 m_nAuthor( std::string::npos
),
157 m_bValidContentPos( false )
159 mnFrameType
= SwFrameType::Fly
;
161 m_bInvalid
= m_bNotifyBack
= true;
162 m_bLocked
= m_bMinHeight
=
163 m_bHeightClipped
= m_bWidthClipped
= m_bFormatHeightOnly
= false;
165 // Size setting: Fixed size is always the width
166 const SwFormatFrameSize
&rFrameSize
= pFormat
->GetFrameSize();
167 const SvxFrameDirection nDir
= pFormat
->GetFormatAttr( RES_FRAMEDIR
).GetValue();
168 if( SvxFrameDirection::Environment
== nDir
)
170 mbDerivedVert
= true;
175 mbInvalidVert
= false;
176 mbDerivedVert
= false;
177 mbDerivedR2L
= false;
178 if( SvxFrameDirection::Horizontal_LR_TB
== nDir
|| SvxFrameDirection::Horizontal_RL_TB
== nDir
)
185 const SwViewShell
*pSh
= getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
186 if( pSh
&& pSh
->GetViewOptions()->getBrowseMode() )
195 if ( SvxFrameDirection::Vertical_LR_TB
== nDir
)
197 else if (nDir
== SvxFrameDirection::Vertical_LR_BT
)
207 mbInvalidR2L
= false;
208 if( SvxFrameDirection::Horizontal_RL_TB
== nDir
)
209 mbRightToLeft
= true;
211 mbRightToLeft
= false;
215 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
216 aFrm
.Width( rFrameSize
.GetWidth() );
217 aFrm
.Height( rFrameSize
.GetHeightSizeType() == SwFrameSize::Variable
? MINFLY
: rFrameSize
.GetHeight() );
220 // Fixed or variable Height?
221 if ( rFrameSize
.GetHeightSizeType() == SwFrameSize::Minimum
)
223 else if ( rFrameSize
.GetHeightSizeType() == SwFrameSize::Fixed
)
226 // insert columns, if necessary
229 // First the Init, then the Content:
230 // This is due to the fact that the Content may have Objects/Frames,
231 // which are then registered
241 // Put it somewhere outside so that out document is not formatted unnecessarily often
242 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
243 aFrm
.Pos().setX(FAR_AWAY
);
244 aFrm
.Pos().setY(FAR_AWAY
);
247 void SwFlyFrame::Chain( SwFrame
* _pAnch
)
249 // Connect to chain neighbours.
250 // No problem, if a neighbor doesn't exist - the construction of the
251 // neighbor will make the connection
252 const SwFormatChain
& rChain
= GetFormat()->GetChain();
253 if ( !(rChain
.GetPrev() || rChain
.GetNext()) )
256 if ( rChain
.GetNext() )
258 SwFlyFrame
* pFollow
= FindChainNeighbour( *rChain
.GetNext(), _pAnch
);
261 OSL_ENSURE( !pFollow
->GetPrevLink(), "wrong chain detected" );
262 if ( !pFollow
->GetPrevLink() )
263 SwFlyFrame::ChainFrames( this, pFollow
);
266 if ( rChain
.GetPrev() )
268 SwFlyFrame
*pMaster
= FindChainNeighbour( *rChain
.GetPrev(), _pAnch
);
271 OSL_ENSURE( !pMaster
->GetNextLink(), "wrong chain detected" );
272 if ( !pMaster
->GetNextLink() )
273 SwFlyFrame::ChainFrames( pMaster
, this );
278 void SwFlyFrame::InsertCnt()
283 const SwFormatContent
& rContent
= GetFormat()->GetContent();
284 OSL_ENSURE( rContent
.GetContentIdx(), ":-( no content prepared." );
285 SwNodeOffset nIndex
= rContent
.GetContentIdx()->GetIndex();
286 // Lower() means SwColumnFrame; the Content then needs to be inserted into the (Column)BodyFrame
287 ::InsertCnt_( Lower() ? static_cast<SwLayoutFrame
*>(static_cast<SwLayoutFrame
*>(Lower())->Lower()) : static_cast<SwLayoutFrame
*>(this),
288 GetFormat()->GetDoc(), nIndex
);
290 // NoText always have a fixed height.
291 if ( Lower() && Lower()->IsNoTextFrame() )
294 m_bMinHeight
= false;
298 void SwFlyFrame::InsertColumns()
301 // Check, if column are allowed.
302 // Columns are not allowed for fly frames, which represent graphics or embedded objects.
303 const SwFormatContent
& rContent
= GetFormat()->GetContent();
304 OSL_ENSURE( rContent
.GetContentIdx(), "<SwFlyFrame::InsertColumns()> - no content prepared." );
305 SwNodeIndex
aFirstContent( *(rContent
.GetContentIdx()), 1 );
306 if ( aFirstContent
.GetNode().IsNoTextNode() )
311 const SwFormatCol
&rCol
= GetFormat()->GetCol();
312 if ( rCol
.GetNumCols() <= 1 )
315 // Start off PrtArea to be as large as Frame, so that we can put in the columns
316 // properly. It'll adjust later on.
318 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
319 aPrt
.Width( getFrameArea().Width() );
320 aPrt
.Height( getFrameArea().Height() );
323 const SwFormatCol aOld
; // ChgColumns() also needs an old value passed
324 ChgColumns( aOld
, rCol
);
327 void SwFlyFrame::DestroyImpl()
329 // Accessible objects for fly frames will be destroyed in this destructor.
330 // For frames bound as char or frames that don't have an anchor we have
331 // to do that ourselves. For any other frame the call RemoveFly at the
332 // anchor will do that.
333 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
334 if( IsAccessibleFrame() && GetFormat() && (IsFlyInContentFrame() || !GetAnchorFrame()) )
336 SwRootFrame
*pRootFrame
= getRootFrame();
337 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() )
339 SwViewShell
*pVSh
= pRootFrame
->GetCurrShell();
340 if( pVSh
&& pVSh
->Imp() )
342 // Lowers aren't disposed already, so we have to do a recursive
344 pVSh
->Imp()->DisposeAccessibleFrame( this, true );
350 if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() )
352 ClearTmpConsiderWrapInfluence(); // remove this from SwLayouter
358 if ( GetAnchorFrame() )
359 AnchorFrame()->RemoveFly( this );
364 SwLayoutFrame::DestroyImpl();
366 SwWrtShell
* pWrtSh
= dynamic_cast<SwWrtShell
*>(getRootFrame()->GetCurrShell());
367 UpdateUnfloatButton(pWrtSh
, false);
370 SwFlyFrame::~SwFlyFrame()
374 const IDocumentDrawModelAccess
& SwFlyFrame::getIDocumentDrawModelAccess()
376 return GetFormat()->getIDocumentDrawModelAccess();
379 void SwFlyFrame::Unchain()
382 UnchainFrames( GetPrevLink(), this );
384 UnchainFrames( this, GetNextLink() );
387 void SwFlyFrame::DeleteCnt()
389 SwFrame
* pFrame
= m_pLower
;
392 while ( pFrame
->GetDrawObjs() && pFrame
->GetDrawObjs()->size() )
394 SwAnchoredObject
*pAnchoredObj
= (*pFrame
->GetDrawObjs())[0];
395 if ( auto pFlyFrame
= pAnchoredObj
->DynCastFlyFrame() )
397 SwFrame::DestroyFrame(pFlyFrame
);
399 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pAnchoredObj
) != nullptr )
401 // consider 'virtual' drawing objects
402 SdrObject
* pObj
= pAnchoredObj
->DrawObj();
403 if ( auto pDrawVirtObj
= dynamic_cast<SwDrawVirtObj
*>( pObj
) )
405 pDrawVirtObj
->RemoveFromWriterLayout();
406 pDrawVirtObj
->RemoveFromDrawingPage();
410 SwDrawContact
* pContact
=
411 static_cast<SwDrawContact
*>(::GetUserCall( pObj
));
414 pContact
->DisconnectFromLayout();
420 pFrame
->RemoveFromLayout();
421 SwFrame::DestroyFrame(pFrame
);
428 void SwFlyFrame::InitDrawObj(SwFrame
const& rAnchorFrame
)
430 SetDrawObj(*SwFlyDrawContact::CreateNewRef(this, GetFormat(), rAnchorFrame
));
432 // Set the right Layer
433 IDocumentDrawModelAccess
& rIDDMA
= GetFormat()->getIDocumentDrawModelAccess();
434 SdrLayerID nHeavenId
= rIDDMA
.GetHeavenId();
435 SdrLayerID nHellId
= rIDDMA
.GetHellId();
436 GetVirtDrawObj()->SetLayer( GetFormat()->GetOpaque().GetValue()
441 static SwPosition
ResolveFlyAnchor(SwFrameFormat
const& rFlyFrame
)
443 SwFormatAnchor
const& rAnch(rFlyFrame
.GetAnchor());
444 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PAGE
)
445 { // arbitrarily pick last node
446 return SwPosition(rFlyFrame
.GetDoc()->GetNodes().GetEndOfContent(), SwNodeOffset(-1));
450 SwPosition
const*const pPos(rAnch
.GetContentAnchor());
452 if (SwFrameFormat
const*const pParent
= pPos
->GetNode().GetFlyFormat())
454 return ResolveFlyAnchor(*pParent
);
456 else if (pPos
->GetContentNode())
462 return SwPosition(*pPos
->GetNode().GetContentNode(), 0);
467 void SwFlyFrame::FinitDrawObj()
469 if(!GetVirtDrawObj() )
471 SwFormat
* pFormat
= GetFormat();
472 // Deregister from SdrPageViews if the Objects is still selected there.
473 if(!pFormat
->GetDoc()->IsInDtor())
475 SwViewShell
* p1St
= getRootFrame()->GetCurrShell();
478 for(SwViewShell
& rCurrentShell
: p1St
->GetRingContainer())
479 { // At the moment the Drawing can do just do an Unmark on everything,
480 // as the Object was already removed
481 if (rCurrentShell
.HasDrawView() &&
482 rCurrentShell
.Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount())
484 SwFlyFrame
const*const pOldSelFly
= ::GetFlyFromMarked(nullptr, &rCurrentShell
);
485 if (pOldSelFly
== this)
487 assert(rCurrentShell
.Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1);
488 if (SwFEShell
*const pFEShell
= dynamic_cast<SwFEShell
*>(&rCurrentShell
))
489 { // tdf#131679 move any cursor out of fly
490 rCurrentShell
.Imp()->GetDrawView()->UnmarkAll();
493 SwPaM
const temp(ResolveFlyAnchor(*pOldSelFly
->GetFormat()));
494 pFEShell
->SetSelection(temp
);
495 // could also call SetCursor() like SwFEShell::SelectObj()
496 // does, but that would access layout a bit much...
501 rCurrentShell
.Imp()->GetDrawView()->UnmarkAll();
509 SwVirtFlyDrawObj
* pVirtDrawObj
= GetVirtDrawObj();
510 // Else calls delete of the ContactObj
511 pVirtDrawObj
->SetUserCall(nullptr);
513 if ( pVirtDrawObj
->getSdrPageFromSdrObject() )
514 pVirtDrawObj
->getSdrPageFromSdrObject()->RemoveObject( pVirtDrawObj
->GetOrdNum() );
518 void SwFlyFrame::ChainFrames( SwFlyFrame
*pMaster
, SwFlyFrame
*pFollow
)
520 OSL_ENSURE( pMaster
&& pFollow
, "incomplete chain" );
521 OSL_ENSURE( !pMaster
->GetNextLink(), "link can not be changed" );
522 OSL_ENSURE( !pFollow
->GetPrevLink(), "link can not be changed" );
524 pMaster
->m_pNextLink
= pFollow
;
525 pFollow
->m_pPrevLink
= pMaster
;
527 if ( pMaster
->ContainsContent() )
529 // To get a text flow we need to invalidate
530 SwFrame
*pInva
= pMaster
->FindLastLower();
531 SwRectFnSet
aRectFnSet(pMaster
);
532 const tools::Long nBottom
= aRectFnSet
.GetPrtBottom(*pMaster
);
535 if( aRectFnSet
.BottomDist( pInva
->getFrameArea(), nBottom
) <= 0 )
537 pInva
->InvalidateSize();
539 pInva
= pInva
->FindPrev();
546 if ( pFollow
->ContainsContent() )
548 // There's only the content from the Masters left; the content from the Follow
549 // does not have any Frames left (should always be exactly one empty TextNode).
550 SwFrame
*pFrame
= pFollow
->ContainsContent();
551 OSL_ENSURE( !pFrame
->IsTabFrame() && !pFrame
->FindNext(), "follow in chain contains content" );
553 SwFrame::DestroyFrame(pFrame
);
556 // invalidate accessible relation set (accessibility wrapper)
557 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
558 SwViewShell
* pSh
= pMaster
->getRootFrame()->GetCurrShell();
561 SwRootFrame
* pLayout
= pMaster
->getRootFrame();
562 if( pLayout
&& pLayout
->IsAnyShellAccessible() )
563 pSh
->Imp()->InvalidateAccessibleRelationSet( pMaster
, pFollow
);
568 void SwFlyFrame::UnchainFrames( SwFlyFrame
*pMaster
, SwFlyFrame
*pFollow
)
570 pMaster
->m_pNextLink
= nullptr;
571 pFollow
->m_pPrevLink
= nullptr;
573 if ( pFollow
->ContainsContent() )
575 // The Master sucks up the content of the Follow
576 SwLayoutFrame
*pUpper
= pMaster
;
577 if ( pUpper
->Lower()->IsColumnFrame() )
579 pUpper
= static_cast<SwLayoutFrame
*>(pUpper
->GetLastLower());
580 pUpper
= static_cast<SwLayoutFrame
*>(pUpper
->Lower()); // The (Column)BodyFrame
581 OSL_ENSURE( pUpper
&& pUpper
->IsColBodyFrame(), "Missing ColumnBody" );
583 SwFlyFrame
*pFoll
= pFollow
;
586 SwFrame
*pTmp
= ::SaveContent( pFoll
);
588 ::RestoreContent( pTmp
, pUpper
, pMaster
->FindLastLower() );
589 pFoll
->SetCompletePaint();
590 pFoll
->InvalidateSize();
591 pFoll
= pFoll
->GetNextLink();
595 // The Follow needs his own content to be served
596 const SwFormatContent
&rContent
= pFollow
->GetFormat()->GetContent();
597 OSL_ENSURE( rContent
.GetContentIdx(), ":-( No content prepared." );
598 SwNodeOffset nIndex
= rContent
.GetContentIdx()->GetIndex();
599 // Lower() means SwColumnFrame: this one contains another SwBodyFrame
600 ::InsertCnt_( pFollow
->Lower() ? const_cast<SwLayoutFrame
*>(static_cast<const SwLayoutFrame
*>(static_cast<const SwLayoutFrame
*>(pFollow
->Lower())->Lower()))
601 : static_cast<SwLayoutFrame
*>(pFollow
),
602 pFollow
->GetFormat()->GetDoc(), ++nIndex
);
604 // invalidate accessible relation set (accessibility wrapper)
605 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
606 SwViewShell
* pSh
= pMaster
->getRootFrame()->GetCurrShell();
609 SwRootFrame
* pLayout
= pMaster
->getRootFrame();
610 if( pLayout
&& pLayout
->IsAnyShellAccessible() )
611 pSh
->Imp()->InvalidateAccessibleRelationSet( pMaster
, pFollow
);
616 SwFlyFrame
*SwFlyFrame::FindChainNeighbour( SwFrameFormat
const &rChain
, SwFrame
*pAnch
)
618 // We look for the Fly that's in the same Area.
619 // Areas can for now only be Head/Footer or Flys.
621 if ( !pAnch
) // If an Anchor was passed along, that one counts (ctor!)
622 pAnch
= AnchorFrame();
625 if ( pAnch
->IsInFly() )
626 pLay
= pAnch
->FindFlyFrame();
629 // FindFooterOrHeader is not appropriate here, as we may not have a
630 // connection to the Anchor yet.
631 pLay
= pAnch
->GetUpper();
632 while ( pLay
&& !(pLay
->GetType() & (SwFrameType::Header
|SwFrameType::Footer
)) )
633 pLay
= pLay
->GetUpper();
636 SwIterator
<SwFlyFrame
,SwFormat
> aIter( rChain
);
637 SwFlyFrame
*pFly
= aIter
.First();
642 if ( pFly
->GetAnchorFrame() )
644 if ( pFly
->GetAnchorFrame()->IsInFly() )
646 if ( pFly
->AnchorFrame()->FindFlyFrame() == pLay
)
649 else if ( pLay
== pFly
->FindFooterOrHeader() )
657 OSL_ENSURE( !aIter
.Next(), "chain with more than one instance" );
662 bool SwFlyFrame::IsFlySplitAllowed() const
664 if (!IsFlyAtContentFrame())
669 const IDocumentSettingAccess
& rIDSA
= GetFormat()->getIDocumentSettingAccess();
670 if (rIDSA
.get(DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES
))
675 if (FindFooterOrHeader())
677 // Adding a new page would not increase the header/footer area.
681 const SwFrame
* pFlyAnchor
= GetAnchorFrame();
682 if (pFlyAnchor
&& pFlyAnchor
->FindColFrame())
684 // No split in multi-column sections, so GetFlyAnchorBottom() can assume that our innermost
685 // body frame and the page's body frame is the same.
686 // This is also consistent with the Word behavior.
690 if (pFlyAnchor
&& pFlyAnchor
->IsInFootnote())
692 // No split in footnotes.
696 const SwFlyFrameFormat
* pFormat
= GetFormat();
697 const SwFormatVertOrient
& rVertOrient
= pFormat
->GetVertOrient();
698 if (rVertOrient
.GetVertOrient() == text::VertOrientation::BOTTOM
)
700 // We have to grow from bottom to top, and the fly split code assumes that we grow from top
701 // to bottom, so don't split for now.
702 if (rVertOrient
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
)
704 // Growing from the bottom of the body frame.
709 return pFormat
->GetFlySplit().GetValue();
712 SwFrame
*SwFlyFrame::FindLastLower()
714 SwFrame
*pRet
= ContainsAny();
715 if ( pRet
&& pRet
->IsInTab() )
716 pRet
= pRet
->FindTabFrame();
717 SwFrame
*pNxt
= pRet
;
718 while ( pNxt
&& IsAnLower( pNxt
) )
720 pNxt
= pNxt
->FindNext();
725 bool SwFlyFrame::FrameSizeChg( const SwFormatFrameSize
&rFrameSize
)
728 SwTwips nDiffHeight
= getFrameArea().Height();
729 if ( rFrameSize
.GetHeightSizeType() == SwFrameSize::Variable
)
730 mbFixSize
= m_bMinHeight
= false;
733 if ( rFrameSize
.GetHeightSizeType() == SwFrameSize::Fixed
)
736 m_bMinHeight
= false;
738 else if ( rFrameSize
.GetHeightSizeType() == SwFrameSize::Minimum
)
743 nDiffHeight
-= rFrameSize
.GetHeight();
745 // If the Fly contains columns, we already need to set the Fly
746 // and the Columns to the required value or else we run into problems.
749 if ( Lower()->IsColumnFrame() )
751 const SwRect
aOld( GetObjRectWithSpaces() );
752 const Size
aOldSz( getFramePrintArea().SSize() );
753 const SwTwips nDiffWidth
= getFrameArea().Width() - rFrameSize
.GetWidth();
756 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
757 aFrm
.Height( aFrm
.Height() - nDiffHeight
);
758 aFrm
.Width ( aFrm
.Width() - nDiffWidth
);
762 InvalidateObjRectWithSpaces();
765 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
766 aPrt
.Height( aPrt
.Height() - nDiffHeight
);
767 aPrt
.Width ( aPrt
.Width() - nDiffWidth
);
770 ChgLowersProp( aOldSz
);
771 ::Notify( this, FindPageFrame(), aOld
);
772 setFrameAreaPositionValid(false);
775 else if ( Lower()->IsNoTextFrame() )
778 m_bMinHeight
= false;
784 void SwFlyFrame::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
786 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
788 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
789 SwFlyFrameInvFlags eInvFlags
= SwFlyFrameInvFlags::NONE
;
790 if(pLegacy
->m_pNew
&& pLegacy
->m_pOld
&& RES_ATTRSET_CHG
== pLegacy
->m_pNew
->Which())
792 SfxItemIter
aNIter(*static_cast<const SwAttrSetChg
*>(pLegacy
->m_pNew
)->GetChgSet());
793 SfxItemIter
aOIter(*static_cast<const SwAttrSetChg
*>(pLegacy
->m_pOld
)->GetChgSet());
794 const SfxPoolItem
* pNItem
= aNIter
.GetCurItem();
795 const SfxPoolItem
* pOItem
= aOIter
.GetCurItem();
796 SwAttrSetChg
aOldSet(*static_cast<const SwAttrSetChg
*>(pLegacy
->m_pOld
));
797 SwAttrSetChg
aNewSet(*static_cast<const SwAttrSetChg
*>(pLegacy
->m_pNew
));
800 UpdateAttr_(pOItem
, pNItem
, eInvFlags
, &aOldSet
, &aNewSet
);
801 pNItem
= aNIter
.NextItem();
802 pOItem
= aOIter
.NextItem();
804 if(aOldSet
.Count() || aNewSet
.Count())
805 SwLayoutFrame::SwClientNotify(rMod
, sw::LegacyModifyHint(&aOldSet
, &aNewSet
));
808 UpdateAttr_(pLegacy
->m_pOld
, pLegacy
->m_pNew
, eInvFlags
);
810 if(eInvFlags
== SwFlyFrameInvFlags::NONE
)
814 if(eInvFlags
& SwFlyFrameInvFlags::InvalidatePos
)
818 InvalidateObjRectWithSpaces();
820 if(eInvFlags
& SwFlyFrameInvFlags::InvalidateSize
)
824 InvalidateObjRectWithSpaces();
826 if(eInvFlags
& SwFlyFrameInvFlags::InvalidatePrt
)
828 if(eInvFlags
& SwFlyFrameInvFlags::SetNotifyBack
)
830 if(eInvFlags
& SwFlyFrameInvFlags::SetCompletePaint
)
832 if((eInvFlags
& SwFlyFrameInvFlags::ClearContourCache
) && Lower() && Lower()->IsNoTextFrame())
833 ClrContourCache( GetVirtDrawObj() );
835 if(eInvFlags
& SwFlyFrameInvFlags::InvalidateBrowseWidth
&& nullptr != (pRoot
= getRootFrame()))
836 pRoot
->InvalidateBrowseWidth();
838 if(eInvFlags
& SwFlyFrameInvFlags::UpdateObjInSortedList
)
840 // update sorted object lists, the Writer fly frame is registered at.
841 UpdateObjInSortedList();
844 // #i87645# - reset flags for the layout process (only if something has been invalidated)
845 ResetLayoutProcessBools();
847 else if (rHint
.GetId() == SfxHintId::SwGetZOrder
)
849 auto pGetZOrdnerHint
= static_cast<const sw::GetZOrderHint
*>(&rHint
);
850 const auto& rFormat(dynamic_cast<const SwFrameFormat
&>(rMod
));
851 if (rFormat
.Which() == RES_FLYFRMFMT
&& rFormat
.getIDocumentLayoutAccess().GetCurrentViewShell()) // #i11176#
852 pGetZOrdnerHint
->m_rnZOrder
= GetVirtDrawObj()->GetOrdNum();
854 else if (rHint
.GetId() == SfxHintId::SwGetObjectConnected
)
856 auto pConnectedHint
= static_cast<const sw::GetObjectConnectedHint
*>(&rHint
);
857 const auto& rFormat(dynamic_cast<const SwFrameFormat
&>(rMod
));
858 if (!pConnectedHint
->m_risConnected
&& rFormat
.Which() == RES_FLYFRMFMT
&& (!pConnectedHint
->m_pRoot
|| pConnectedHint
->m_pRoot
== getRootFrame()))
859 pConnectedHint
->m_risConnected
= true;
863 void SwFlyFrame::UpdateAttr_( const SfxPoolItem
*pOld
, const SfxPoolItem
*pNew
,
864 SwFlyFrameInvFlags
&rInvFlags
,
865 SwAttrSetChg
*pOldSet
, SwAttrSetChg
*pNewSet
)
868 const sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
869 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
872 case RES_VERT_ORIENT
:
873 case RES_HORI_ORIENT
:
874 // #i18732# - consider new option 'follow text flow'
875 case RES_FOLLOW_TEXT_FLOW
:
877 // ATTENTION: Always also change Action in ChgRePos()!
878 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::SetNotifyBack
;
881 // #i28701# - consider new option 'wrap influence on position'
882 case RES_WRAP_INFLUENCE_ON_OBJPOS
:
884 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::SetNotifyBack
885 | SwFlyFrameInvFlags::UpdateObjInSortedList
;
890 //#i28701# - invalidate position on change of
892 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::ClearContourCache
;
893 // The background needs to be messaged and invalidated
894 const SwRect
aTmp( GetObjRectWithSpaces() );
895 NotifyBackground( FindPageFrame(), aTmp
, PrepareHint::FlyFrameAttributesChanged
);
897 // By changing the flow of frame-bound Frames, a vertical alignment
898 // can be activated/deactivated => MakeFlyPos
899 if( RndStdIds::FLY_AT_FLY
== GetFormat()->GetAnchor().GetAnchorId() )
900 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::SetNotifyBack
;
902 // Delete contour in the Node if necessary
903 if ( Lower() && Lower()->IsNoTextFrame() &&
904 !GetFormat()->GetSurround().IsContour() )
906 SwNoTextNode
*pNd
= static_cast<SwNoTextNode
*>(static_cast<SwNoTextFrame
*>(Lower())->GetNode());
907 if ( pNd
->HasContour() )
908 pNd
->SetContour( nullptr );
910 // #i28701# - perform reorder of object lists
911 // at anchor frame and at page frame.
912 rInvFlags
|= SwFlyFrameInvFlags::UpdateObjInSortedList
;
919 const SvxProtectItem
*pP
= static_cast<const SvxProtectItem
*>(pNew
);
920 GetVirtDrawObj()->SetMoveProtect( pP
->IsPosProtected() );
921 GetVirtDrawObj()->SetResizeProtect( pP
->IsSizeProtected() );
922 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
925 SwRootFrame
* pLayout
= getRootFrame();
926 if( pLayout
&& pLayout
->IsAnyShellAccessible() )
927 pSh
->Imp()->InvalidateAccessibleEditableState( true, this );
935 ChgColumns( *static_cast<const SwFormatCol
*>(pOld
), *static_cast<const SwFormatCol
*>(pNew
) );
936 const SwFormatFrameSize
&rNew
= GetFormat()->GetFrameSize();
937 if ( FrameSizeChg( rNew
) )
939 rInvFlags
|= SwFlyFrameInvFlags::InvalidateSize
| SwFlyFrameInvFlags::SetNotifyBack
940 | SwFlyFrameInvFlags::SetCompletePaint
;
948 const SwFormatFrameSize
&rNew
= GetFormat()->GetFrameSize();
949 if ( FrameSizeChg( rNew
) )
951 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::InvalidateSize
952 | SwFlyFrameInvFlags::InvalidatePrt
| SwFlyFrameInvFlags::SetNotifyBack
953 | SwFlyFrameInvFlags::SetCompletePaint
954 | SwFlyFrameInvFlags::InvalidateBrowseWidth
955 | SwFlyFrameInvFlags::ClearContourCache
;
956 if (pOld
&& RES_FMT_CHG
== nWhich
)
958 SwRect
aNew( GetObjRectWithSpaces() );
959 SwRect
aOld( getFrameArea() );
960 const SvxULSpaceItem
&rUL
= static_cast<const SwFormatChg
*>(pOld
)->pChangedFormat
->GetULSpace();
961 aOld
.Top( std::max( aOld
.Top() - tools::Long(rUL
.GetUpper()), tools::Long(0) ) );
962 aOld
.AddHeight(rUL
.GetLower() );
963 const SvxLRSpaceItem
&rLR
= static_cast<const SwFormatChg
*>(pOld
)->pChangedFormat
->GetLRSpace();
964 aOld
.Left ( std::max( aOld
.Left() - rLR
.GetLeft(), tools::Long(0) ) );
965 aOld
.AddWidth(rLR
.GetRight() );
967 NotifyBackground( FindPageFrame(), aNew
, PrepareHint::Clear
);
970 // When assigning a template we cannot rely on the old column
971 // attribute. As there need to be at least enough for ChgColumns,
972 // we need to create a temporary attribute.
974 if ( Lower() && Lower()->IsColumnFrame() )
977 SwFrame
*pTmp
= Lower();
980 pTmp
= pTmp
->GetNext();
982 aCol
.Init( nCol
, 0, 1000 );
984 ChgColumns( aCol
, GetFormat()->GetCol() );
987 SwFormatURL
aURL( GetFormat()->GetURL() );
989 SwFormatFrameSize
*pNewFormatFrameSize
= nullptr;
990 SwFormatChg
*pOldFormatChg
= nullptr;
991 if (nWhich
== RES_FRM_SIZE
)
992 pNewFormatFrameSize
= const_cast<SwFormatFrameSize
*>(static_cast<const SwFormatFrameSize
*>(pNew
));
993 else if (nWhich
== RES_FMT_CHG
)
994 pOldFormatChg
= const_cast<SwFormatChg
*>(static_cast<const SwFormatChg
*>(pOld
));
995 else if (nWhich
== RES_FLY_SPLIT
)
997 // If the fly frame has a table lower, invalidate that, so it joins its follow tab
998 // frames and re-splits according to the new fly split rule.
999 if (Lower() && Lower()->IsTabFrame())
1001 Lower()->InvalidateAll_();
1005 if (aURL
.GetMap() && (pNewFormatFrameSize
|| pOldFormatChg
))
1007 const SwFormatFrameSize
&rOld
= pNewFormatFrameSize
?
1008 *pNewFormatFrameSize
:
1009 pOldFormatChg
->pChangedFormat
->GetFrameSize();
1010 //#35091# Can be "times zero", when loading the template
1011 if ( rOld
.GetWidth() && rOld
.GetHeight() )
1014 Fraction
aScaleX( rOld
.GetWidth(), rNew
.GetWidth() );
1015 Fraction
aScaleY( rOld
.GetHeight(), rOld
.GetHeight() );
1016 aURL
.GetMap()->Scale( aScaleX
, aScaleY
);
1017 SwFrameFormat
*pFormat
= GetFormat();
1018 pFormat
->LockModify();
1019 pFormat
->SetFormatAttr( aURL
);
1020 pFormat
->UnlockModify();
1023 const SvxProtectItem
&rP
= GetFormat()->GetProtect();
1024 GetVirtDrawObj()->SetMoveProtect( rP
.IsPosProtected() );
1025 GetVirtDrawObj()->SetResizeProtect( rP
.IsSizeProtected() );
1028 pSh
->InvalidateWindows( getFrameArea() );
1029 const IDocumentDrawModelAccess
& rIDDMA
= GetFormat()->getIDocumentDrawModelAccess();
1030 const SdrLayerID nId
= GetFormat()->GetOpaque().GetValue() ?
1031 rIDDMA
.GetHeavenId() :
1033 GetVirtDrawObj()->SetLayer( nId
);
1037 // Delete contour in the Node if necessary
1038 if( Lower()->IsNoTextFrame() &&
1039 !GetFormat()->GetSurround().IsContour() )
1041 SwNoTextNode
*pNd
= static_cast<SwNoTextNode
*>(static_cast<SwNoTextFrame
*>(Lower())->GetNode());
1042 if ( pNd
->HasContour() )
1043 pNd
->SetContour( nullptr );
1045 else if( !Lower()->IsColumnFrame() )
1047 SwFrame
* pFrame
= GetLastLower();
1048 if( pFrame
->IsTextFrame() && static_cast<SwTextFrame
*>(pFrame
)->IsUndersized() )
1049 pFrame
->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
1053 // #i28701# - perform reorder of object lists
1054 // at anchor frame and at page frame.
1055 rInvFlags
|= SwFlyFrameInvFlags::UpdateObjInSortedList
;
1062 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::ClearContourCache
;
1063 if( pSh
&& pSh
->GetViewOptions()->getBrowseMode() )
1064 getRootFrame()->InvalidateBrowseWidth();
1065 SwRect
aNew( GetObjRectWithSpaces() );
1066 SwRect
aOld( getFrameArea() );
1069 if ( RES_UL_SPACE
== nWhich
)
1071 const SvxULSpaceItem
&rUL
= *static_cast<const SvxULSpaceItem
*>(pNew
);
1072 aOld
.Top( std::max( aOld
.Top() - tools::Long(rUL
.GetUpper()), tools::Long(0) ) );
1073 aOld
.AddHeight(rUL
.GetLower() );
1077 const SvxLRSpaceItem
&rLR
= *static_cast<const SvxLRSpaceItem
*>(pNew
);
1078 aOld
.Left ( std::max( aOld
.Left() - rLR
.GetLeft(), tools::Long(0) ) );
1079 aOld
.AddWidth(rLR
.GetRight() );
1083 NotifyBackground( FindPageFrame(), aNew
, PrepareHint::Clear
);
1087 case RES_TEXT_VERT_ADJUST
:
1089 InvalidateContentPos();
1090 rInvFlags
|= SwFlyFrameInvFlags::SetCompletePaint
;
1096 rInvFlags
|= SwFlyFrameInvFlags::InvalidatePos
| SwFlyFrameInvFlags::InvalidateSize
1097 | SwFlyFrameInvFlags::InvalidatePrt
| SwFlyFrameInvFlags::SetCompletePaint
;
1101 SetDerivedVert( false );
1102 SetDerivedR2L( false );
1110 pSh
->InvalidateWindows( getFrameArea() );
1112 const IDocumentDrawModelAccess
& rIDDMA
= GetFormat()->getIDocumentDrawModelAccess();
1113 const SdrLayerID nId
= static_cast<const SvxOpaqueItem
*>(pNew
)->GetValue() ?
1114 rIDDMA
.GetHeavenId() :
1116 GetVirtDrawObj()->SetLayer( nId
);
1117 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1120 SwRootFrame
* pLayout
= getRootFrame();
1121 if( pLayout
&& pLayout
->IsAnyShellAccessible() )
1123 pSh
->Imp()->DisposeAccessibleFrame( this );
1124 pSh
->Imp()->AddAccessibleFrame( this );
1128 // #i28701# - perform reorder of object lists
1129 // at anchor frame and at page frame.
1130 rInvFlags
|= SwFlyFrameInvFlags::UpdateObjInSortedList
;
1135 // The interface changes the frame size when interacting with text frames,
1136 // the Map, however, needs to be relative to FrameSize().
1137 if ( (!Lower() || !Lower()->IsNoTextFrame()) && pNew
&& pOld
&&
1138 static_cast<const SwFormatURL
*>(pNew
)->GetMap() && static_cast<const SwFormatURL
*>(pOld
)->GetMap() )
1140 const SwFormatFrameSize
&rSz
= GetFormat()->GetFrameSize();
1141 if ( rSz
.GetHeight() != getFrameArea().Height() ||
1142 rSz
.GetWidth() != getFrameArea().Width() )
1144 SwFormatURL
aURL( GetFormat()->GetURL() );
1145 Fraction
aScaleX( getFrameArea().Width(), rSz
.GetWidth() );
1146 Fraction
aScaleY( getFrameArea().Height(), rSz
.GetHeight() );
1147 aURL
.GetMap()->Scale( aScaleX
, aScaleY
);
1148 SwFrameFormat
*pFormat
= GetFormat();
1149 pFormat
->LockModify();
1150 pFormat
->SetFormatAttr( aURL
);
1151 pFormat
->UnlockModify();
1154 // No invalidation necessary
1160 const SwFormatChain
*pChain
= static_cast<const SwFormatChain
*>(pNew
);
1161 if ( pChain
->GetNext() )
1163 SwFlyFrame
*pFollow
= FindChainNeighbour( *pChain
->GetNext() );
1164 if ( GetNextLink() && pFollow
!= GetNextLink() )
1165 SwFlyFrame::UnchainFrames( this, GetNextLink());
1168 if ( pFollow
->GetPrevLink() &&
1169 pFollow
->GetPrevLink() != this )
1170 SwFlyFrame::UnchainFrames( pFollow
->GetPrevLink(),
1172 if ( !GetNextLink() )
1173 SwFlyFrame::ChainFrames( this, pFollow
);
1176 else if ( GetNextLink() )
1177 SwFlyFrame::UnchainFrames( this, GetNextLink() );
1178 if ( pChain
->GetPrev() )
1180 SwFlyFrame
*pMaster
= FindChainNeighbour( *pChain
->GetPrev() );
1181 if ( GetPrevLink() && pMaster
!= GetPrevLink() )
1182 SwFlyFrame::UnchainFrames( GetPrevLink(), this );
1185 if ( pMaster
->GetNextLink() &&
1186 pMaster
->GetNextLink() != this )
1187 SwFlyFrame::UnchainFrames( pMaster
,
1188 pMaster
->GetNextLink() );
1189 if ( !GetPrevLink() )
1190 SwFlyFrame::ChainFrames( pMaster
, this );
1193 else if ( GetPrevLink() )
1194 SwFlyFrame::UnchainFrames( GetPrevLink(), this );
1203 if ( pOldSet
|| pNewSet
)
1206 pOldSet
->ClearItem( nWhich
);
1208 pNewSet
->ClearItem( nWhich
);
1213 SwLayoutFrame::SwClientNotify(aMod
, sw::LegacyModifyHint(pOld
, pNew
));
1217 /// Gets information from the Modify
1218 bool SwFlyFrame::GetInfo( SfxPoolItem
& rInfo
) const
1220 if( RES_AUTOFMT_DOCNODE
== rInfo
.Which() )
1221 return false; // There's a FlyFrame, so use it
1222 return true; // Continue searching
1225 void SwFlyFrame::Invalidate_( SwPageFrame
const *pPage
)
1227 InvalidatePage( pPage
);
1228 m_bNotifyBack
= m_bInvalid
= true;
1231 if ( GetAnchorFrame() && nullptr != (pFrame
= AnchorFrame()->FindFlyFrame()) )
1233 // Very bad case: If the Fly is bound within another Fly which
1234 // contains columns, the Format should be from that one.
1235 if ( !pFrame
->IsLocked() && !pFrame
->IsColLocked() &&
1236 pFrame
->Lower() && pFrame
->Lower()->IsColumnFrame() )
1237 pFrame
->InvalidateSize();
1241 // if vertical position is oriented at a layout frame inside a ghost section,
1242 // assure that the position is invalidated and that the information about
1243 // the vertical position oriented frame is cleared
1244 if ( GetVertPosOrientFrame() && GetVertPosOrientFrame()->IsLayoutFrame() )
1246 const SwSectionFrame
* pSectFrame( GetVertPosOrientFrame()->FindSctFrame() );
1247 if ( pSectFrame
&& pSectFrame
->GetSection() == nullptr )
1250 ClearVertPosOrientFrame();
1255 /** Change the relative position
1257 * The position will be Fix automatically and the attribute is changed accordingly.
1259 void SwFlyFrame::ChgRelPos( const Point
&rNewPos
)
1261 if ( GetCurrRelPos() == rNewPos
)
1264 SwFrameFormat
*pFormat
= GetFormat();
1265 const bool bVert
= GetAnchorFrame()->IsVertical();
1266 const SwTwips nNewY
= bVert
? rNewPos
.X() : rNewPos
.Y();
1267 SwTwips nTmpY
= nNewY
== LONG_MAX
? 0 : nNewY
;
1270 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
> aSet( pFormat
->GetDoc()->GetAttrPool() );
1272 SwFormatVertOrient
aVert( pFormat
->GetVertOrient() );
1273 const SwTextFrame
*pAutoFrame
= nullptr;
1274 // #i34948# - handle also at-page and at-fly anchored
1275 // Writer fly frames
1276 const RndStdIds eAnchorType
= GetFrameFormat().GetAnchor().GetAnchorId();
1277 if ( eAnchorType
== RndStdIds::FLY_AT_PAGE
)
1279 aVert
.SetVertOrient( text::VertOrientation::NONE
);
1280 aVert
.SetRelationOrient( text::RelOrientation::PAGE_FRAME
);
1282 else if ( eAnchorType
== RndStdIds::FLY_AT_FLY
)
1284 aVert
.SetVertOrient( text::VertOrientation::NONE
);
1285 aVert
.SetRelationOrient( text::RelOrientation::FRAME
);
1287 else if ( IsFlyAtContentFrame() || text::VertOrientation::NONE
!= aVert
.GetVertOrient() )
1289 if( text::RelOrientation::CHAR
== aVert
.GetRelationOrient() && IsAutoPos() )
1291 if( LONG_MAX
!= nNewY
)
1293 aVert
.SetVertOrient( text::VertOrientation::NONE
);
1294 assert(GetAnchorFrame()->IsTextFrame());
1295 pAutoFrame
= static_cast<const SwTextFrame
*>(GetAnchorFrame());
1296 TextFrameIndex
const nOfs(pAutoFrame
->MapModelToViewPos(
1297 *pFormat
->GetAnchor().GetContentAnchor()));
1298 while( pAutoFrame
->GetFollow() &&
1299 pAutoFrame
->GetFollow()->GetOffset() <= nOfs
)
1301 if( pAutoFrame
== GetAnchorFrame() )
1302 nTmpY
+= pAutoFrame
->GetRelPos().Y();
1303 nTmpY
-= pAutoFrame
->GetUpper()->getFramePrintArea().Height();
1304 pAutoFrame
= pAutoFrame
->GetFollow();
1306 nTmpY
= static_cast<SwFlyAtContentFrame
*>(this)->GetRelCharY(pAutoFrame
)-nTmpY
;
1309 aVert
.SetVertOrient( text::VertOrientation::CHAR_BOTTOM
);
1313 aVert
.SetVertOrient( text::VertOrientation::NONE
);
1314 aVert
.SetRelationOrient( text::RelOrientation::FRAME
);
1317 aVert
.SetPos( nTmpY
);
1320 // For Flys in the Cnt, the horizontal orientation is of no interest,
1322 if ( !IsFlyInContentFrame() )
1324 const SwTwips nNewX
= bVert
? rNewPos
.Y() : rNewPos
.X();
1325 SwTwips nTmpX
= nNewX
== LONG_MAX
? 0 : nNewX
;
1326 SwFormatHoriOrient
aHori( pFormat
->GetHoriOrient() );
1327 // #i34948# - handle also at-page and at-fly anchored
1328 // Writer fly frames
1329 if ( eAnchorType
== RndStdIds::FLY_AT_PAGE
)
1331 aHori
.SetHoriOrient( text::HoriOrientation::NONE
);
1332 aHori
.SetRelationOrient( text::RelOrientation::PAGE_FRAME
);
1333 aHori
.SetPosToggle( false );
1335 else if ( eAnchorType
== RndStdIds::FLY_AT_FLY
)
1337 aHori
.SetHoriOrient( text::HoriOrientation::NONE
);
1338 aHori
.SetRelationOrient( text::RelOrientation::FRAME
);
1339 aHori
.SetPosToggle( false );
1341 else if ( IsFlyAtContentFrame() || text::HoriOrientation::NONE
!= aHori
.GetHoriOrient() )
1343 aHori
.SetHoriOrient( text::HoriOrientation::NONE
);
1344 if( text::RelOrientation::CHAR
== aHori
.GetRelationOrient() && IsAutoPos() )
1346 if( LONG_MAX
!= nNewX
)
1350 assert(GetAnchorFrame()->IsTextFrame());
1351 pAutoFrame
= static_cast<const SwTextFrame
*>(GetAnchorFrame());
1352 TextFrameIndex
const nOfs(pAutoFrame
->MapModelToViewPos(
1353 *pFormat
->GetAnchor().GetContentAnchor()));
1354 while( pAutoFrame
->GetFollow() &&
1355 pAutoFrame
->GetFollow()->GetOffset() <= nOfs
)
1356 pAutoFrame
= pAutoFrame
->GetFollow();
1358 nTmpX
-= static_cast<SwFlyAtContentFrame
*>(this)->GetRelCharX(pAutoFrame
);
1362 aHori
.SetRelationOrient( text::RelOrientation::FRAME
);
1363 aHori
.SetPosToggle( false );
1365 aHori
.SetPos( nTmpX
);
1368 SetCurrRelPos( rNewPos
);
1369 pFormat
->GetDoc()->SetAttr( aSet
, *pFormat
);
1373 /** "Formats" the Frame; Frame and PrtArea.
1375 * The FixSize is not inserted here.
1377 void SwFlyFrame::Format( vcl::RenderContext
* /*pRenderContext*/, const SwBorderAttrs
*pAttrs
)
1379 OSL_ENSURE( pAttrs
, "FlyFrame::Format, pAttrs is 0." );
1383 if ( !isFrameAreaSizeValid() )
1385 if ( getFrameArea().Top() == FAR_AWAY
&& getFrameArea().Left() == FAR_AWAY
)
1387 // Remove safety switch (see SwFrame::CTor)
1389 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1395 InvalidateObjRectWithSpaces();
1398 // Check column width and set it if needed
1399 if ( Lower() && Lower()->IsColumnFrame() )
1400 AdjustColumns( nullptr, false );
1402 setFrameAreaSizeValid(true);
1404 const SwTwips nUL
= pAttrs
->CalcTopLine() + pAttrs
->CalcBottomLine();
1405 const SwTwips nLR
= pAttrs
->CalcLeftLine() + pAttrs
->CalcRightLine();
1406 const SwFormatFrameSize
&rFrameSz
= GetFormat()->GetFrameSize();
1407 Size
aRelSize( CalcRel( rFrameSz
) );
1409 OSL_ENSURE( pAttrs
->GetSize().Height() != 0 || rFrameSz
.GetHeightPercent(), "FrameAttr height is 0." );
1410 OSL_ENSURE( pAttrs
->GetSize().Width() != 0 || rFrameSz
.GetWidthPercent(), "FrameAttr width is 0." );
1412 SwRectFnSet
aRectFnSet(this);
1415 tools::Long nMinHeight
= 0;
1417 nMinHeight
= aRectFnSet
.IsVert() ? aRelSize
.Width() : aRelSize
.Height();
1419 SwTwips nRemaining
= CalcContentHeight(pAttrs
, nMinHeight
, nUL
);
1420 if( IsMinHeight() && (nRemaining
+ nUL
) < nMinHeight
)
1421 nRemaining
= nMinHeight
- nUL
;
1422 // Because the Grow/Shrink of the Flys does not directly
1423 // set the size - only indirectly by triggering a Format()
1424 // via Invalidate() - the sizes need to be set here.
1425 // Notification is running along already.
1426 // As we already got a lot of zeros per attribute, we block them
1429 if ( nRemaining
< MINFLY
)
1430 nRemaining
= MINFLY
;
1432 const SwFrame
* pAnchor
= GetAnchorFrame();
1433 if (SwFrame
* pAnchorChar
= FindAnchorCharFrame())
1435 // If we find a follow of the anchor that is effectively the anchor of this fly,
1436 // then use that as the anchor for sizing purposes.
1437 pAnchor
= pAnchorChar
;
1439 if (pAnchor
&& IsFlySplitAllowed())
1441 // If the fly is allowed to be split, then limit its size to the upper of the
1443 SwTwips nDeadline
= GetFlyAnchorBottom(this, *pAnchor
);
1444 SwTwips nTop
= aRectFnSet
.GetTop(getFrameArea());
1445 SwTwips nBottom
= aRectFnSet
.GetTop(getFrameArea()) + nRemaining
;
1446 if (nBottom
> nDeadline
&& nDeadline
> nTop
)
1448 nRemaining
= nDeadline
- nTop
;
1453 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1454 aRectFnSet
.SetHeight( aPrt
, nRemaining
);
1457 nRemaining
-= aRectFnSet
.GetHeight(getFrameArea());
1460 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1461 aRectFnSet
.AddBottom( aFrm
, nRemaining
+ nUL
);
1465 if ( nRemaining
+ nUL
!= 0 )
1467 InvalidateObjRectWithSpaces();
1470 setFrameAreaSizeValid(true);
1472 if (SwFrameFormat
* pShapeFormat
= SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT
))
1474 // This fly is a textbox of a draw shape.
1475 SdrObject
* pShape
= pShapeFormat
->FindSdrObject();
1476 if (SdrObjCustomShape
* pCustomShape
= dynamic_cast<SdrObjCustomShape
*>( pShape
) )
1478 // The shape is a customshape: then inform it about the calculated fly size.
1479 Size
aSize(getFrameArea().Width(), getFrameArea().Height());
1480 pCustomShape
->SuggestTextFrameSize(aSize
);
1481 // Do the calculations normally done after touching editeng text of the shape.
1482 pCustomShape
->NbcSetOutlinerParaObjectForText(std::nullopt
, nullptr);
1488 // Fixed Frames do not Format itself
1489 setFrameAreaSizeValid(true);
1491 // Flys set their size using the attr
1492 SwTwips nNewSize
= aRectFnSet
.IsVert() ? aRelSize
.Width() : aRelSize
.Height();
1494 if( nNewSize
< MINFLY
)
1498 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1499 aRectFnSet
.SetHeight( aPrt
, nNewSize
);
1502 nNewSize
+= nUL
- aRectFnSet
.GetHeight(getFrameArea());
1505 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1506 aRectFnSet
.AddBottom( aFrm
, nNewSize
);
1510 if ( nNewSize
!= 0 )
1512 InvalidateObjRectWithSpaces();
1516 if ( !m_bFormatHeightOnly
)
1518 OSL_ENSURE( aRelSize
== CalcRel( rFrameSz
), "SwFlyFrame::Format CalcRel problem" );
1519 SwTwips nNewSize
= aRectFnSet
.IsVert() ? aRelSize
.Height() : aRelSize
.Width();
1521 if ( rFrameSz
.GetWidthSizeType() != SwFrameSize::Fixed
)
1523 // #i9046# Autowidth for fly frames
1524 const SwTwips nAutoWidth
= lcl_CalcAutoWidth( *this );
1527 if( SwFrameSize::Minimum
== rFrameSz
.GetWidthSizeType() )
1528 nNewSize
= std::max( nNewSize
- nLR
, nAutoWidth
);
1530 nNewSize
= nAutoWidth
;
1536 if( nNewSize
< MINFLY
)
1540 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1541 aRectFnSet
.SetWidth( aPrt
, nNewSize
);
1544 nNewSize
+= nLR
- aRectFnSet
.GetWidth(getFrameArea());
1547 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1548 aRectFnSet
.AddRight( aFrm
, nNewSize
);
1552 if ( nNewSize
!= 0 )
1554 InvalidateObjRectWithSpaces();
1561 // #i11760# - change parameter <bNoColl>: type <bool>;
1562 // add new parameter <bNoCalcFollow> with
1563 // new parameter <bNoCalcFollow> was used by method
1564 // <FormatWidthCols(..)> to avoid follow formatting
1565 // for text frames. But, unformatted follows causes
1566 // problems in method <SwContentFrame::WouldFit_(..)>,
1567 // which assumes that the follows are formatted.
1568 // Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
1569 void CalcContent( SwLayoutFrame
*pLay
, bool bNoColl
)
1571 vcl::RenderContext
* pRenderContext
= pLay
->getRootFrame()->GetCurrShell()->GetOut();
1572 SwSectionFrame
* pSect
;
1573 bool bCollect
= false;
1574 if( pLay
->IsSctFrame() )
1576 pSect
= static_cast<SwSectionFrame
*>(pLay
);
1577 if( pSect
->IsEndnAtEnd() && !bNoColl
)
1580 SwLayouter::CollectEndnotes( pLay
->GetFormat()->GetDoc(), pSect
);
1582 pSect
->CalcFootnoteContent();
1586 SwFrame
*pFrame
= pLay
->ContainsAny();
1591 if( pSect
->HasFollow() )
1592 pFrame
= pSect
->GetFollow()->ContainsAny();
1595 if( pSect
->IsEndnAtEnd() )
1598 pLay
->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->
1599 InsertEndnotes( pSect
);
1600 bool bLock
= pSect
->IsFootnoteLock();
1601 pSect
->SetFootnoteLock( true );
1602 pSect
->CalcFootnoteContent();
1603 pSect
->CalcFootnoteContent();
1604 pSect
->SetFootnoteLock( bLock
);
1608 pFrame
->InvalidatePos_();
1613 pFrame
->InvalidatePage();
1617 // local variables to avoid loops caused by anchored object positioning
1618 SwAnchoredObject
* pAgainObj1
= nullptr;
1619 SwAnchoredObject
* pAgainObj2
= nullptr;
1621 // FME 2007-08-30 #i81146# new loop control
1622 int nLoopControlRuns
= 0;
1623 // tdf#152106 loop control for multi-column sections
1624 int nLoopControlRunsInMultiCol
= 0;
1625 const int nLoopControlMax
= 20;
1626 const SwFrame
* pLoopControlCond
= nullptr;
1632 bool const wasFrameLowerOfLay(pLay
->IsAnLower(pFrame
));
1633 if( pFrame
->IsVertical() ?
1634 ( pFrame
->GetUpper()->getFramePrintArea().Height() != pFrame
->getFrameArea().Height() )
1635 : ( pFrame
->GetUpper()->getFramePrintArea().Width() != pFrame
->getFrameArea().Width() ) )
1637 pFrame
->Prepare( PrepareHint::FixSizeChanged
);
1638 pFrame
->InvalidateSize_();
1641 if ( pFrame
->IsTabFrame() )
1643 static_cast<SwTabFrame
*>(pFrame
)->m_bCalcLowers
= true;
1644 // #i18103# - lock move backward of follow table,
1645 // if no section content is formatted or follow table belongs
1646 // to the section, which content is formatted.
1647 if ( static_cast<SwTabFrame
*>(pFrame
)->IsFollow() &&
1648 ( !pSect
|| pSect
== pFrame
->FindSctFrame() ) )
1650 static_cast<SwTabFrame
*>(pFrame
)->m_bLockBackMove
= true;
1655 SwFrameDeleteGuard
aDeletePageGuard(pSect
? pSect
->FindPageFrame() : nullptr);
1656 SwFrameDeleteGuard
aDeleteGuard(pSect
);
1657 pFrame
->Calc(pRenderContext
);
1660 // #i11760# - reset control flag for follow format.
1661 if ( pFrame
->IsTextFrame() )
1663 static_cast<SwTextFrame
*>(pFrame
)->AllowFollowFormat();
1666 // The keep-attribute can cause the position
1667 // of the prev to be invalid:
1668 // Do not consider invalid previous frame
1669 // due to its keep-attribute, if current frame is a follow or is locked.
1670 // #i44049# - do not consider invalid previous
1671 // frame due to its keep-attribute, if it can't move forward.
1672 // #i57765# - do not consider invalid previous
1673 // frame, if current frame has a column/page break before attribute.
1674 SwFrame
* pTmpPrev
= pFrame
->FindPrev();
1675 SwFlowFrame
* pTmpPrevFlowFrame
= pTmpPrev
&& pTmpPrev
->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev
) : nullptr;
1676 SwFlowFrame
* pTmpFlowFrame
= pFrame
->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pFrame
) : nullptr;
1678 bool bPrevInvalid
= pTmpPrevFlowFrame
&& pTmpFlowFrame
&&
1679 !pTmpFlowFrame
->IsFollow() &&
1680 !StackHack::IsLocked() && // #i76382#
1681 !pTmpFlowFrame
->IsJoinLocked() &&
1682 !pTmpPrev
->isFrameAreaPositionValid() &&
1683 pLay
->IsAnLower( pTmpPrev
) &&
1684 pTmpPrevFlowFrame
->IsKeep(pTmpPrev
->GetAttrSet()->GetKeep(), pTmpPrev
->GetBreakItem()) &&
1685 pTmpPrevFlowFrame
->IsKeepFwdMoveAllowed();
1687 // format floating screen objects anchored to the frame.
1688 if ( !bPrevInvalid
&& pFrame
->GetDrawObjs() && pLay
->IsAnLower( pFrame
) )
1690 bool bAgain
= false;
1691 bool bRestartLayoutProcess
= false;
1692 size_t nCnt
= pFrame
->GetDrawObjs()->size();
1696 // pFrame can move to a different page in FormatObj()
1697 SwPageFrame
*const pPageFrame
= pFrame
->FindPageFrame();
1700 SwAnchoredObject
* pAnchoredObj
= (*pFrame
->GetDrawObjs())[i
];
1701 assert(pAnchoredObj
);
1703 // determine if anchored object has to be
1704 // formatted and, in case, format it
1705 if ( !pAnchoredObj
->PositionLocked() && pAnchoredObj
->IsFormatPossible() )
1707 // #i43737# - no invalidation of
1708 // anchored object needed - causes loops for as-character
1709 // anchored objects.
1710 //pAnchoredObj->InvalidateObjPos();
1711 SwRect
aRect( pAnchoredObj
->GetObjRect() );
1713 SwFrame
* pAnchorFrame
= pFrame
;
1714 SwPageFrame
* pAnchorPageFrame
= pPageFrame
;
1715 if (SwFlyFrame
* pFlyFrame
= pAnchoredObj
->DynCastFlyFrame())
1717 if (pFlyFrame
->IsFlySplitAllowed())
1719 // Split flys are at-para anchored, but the follow fly's anchor char
1720 // frame is not the master frame but can be also a follow of pFrame.
1721 SwTextFrame
* pAnchorCharFrame
= pFlyFrame
->FindAnchorCharFrame();
1722 if (pAnchorCharFrame
)
1724 // Found an anchor char frame, update the anchor frame and the
1725 // anchor page frame accordingly.
1726 pAnchorFrame
= pAnchorCharFrame
;
1727 pAnchorPageFrame
= pAnchorCharFrame
->FindPageFrame();
1732 if ( !SwObjectFormatter::FormatObj( *pAnchoredObj
, pAnchorFrame
, pAnchorPageFrame
) )
1734 bRestartLayoutProcess
= true;
1737 // #i3317# - restart layout process,
1738 // if the position of the anchored object is locked now.
1739 if ( pAnchoredObj
->PositionLocked() )
1741 bRestartLayoutProcess
= true;
1745 if ( aRect
!= pAnchoredObj
->GetObjRect() )
1748 if ( pAgainObj2
== pAnchoredObj
)
1750 OSL_FAIL( "::CalcContent(..) - loop detected, perform attribute changes to avoid the loop" );
1751 // Prevent oscillation
1752 SwFrameFormat
& rFormat
= pAnchoredObj
->GetFrameFormat();
1753 SwFormatSurround
aAttr( rFormat
.GetSurround() );
1754 if( css::text::WrapTextMode_THROUGH
!= aAttr
.GetSurround() )
1756 // When on auto position, we can only set it to
1758 if ((rFormat
.GetAnchor().GetAnchorId() ==
1759 RndStdIds::FLY_AT_CHAR
) &&
1760 (css::text::WrapTextMode_PARALLEL
==
1761 aAttr
.GetSurround()))
1763 aAttr
.SetSurround( css::text::WrapTextMode_THROUGH
);
1767 aAttr
.SetSurround( css::text::WrapTextMode_PARALLEL
);
1769 rFormat
.LockModify();
1770 rFormat
.SetFormatAttr( aAttr
);
1771 rFormat
.UnlockModify();
1776 if ( pAgainObj1
== pAnchoredObj
)
1777 pAgainObj2
= pAnchoredObj
;
1778 pAgainObj1
= pAnchoredObj
;
1782 if ( !pFrame
->GetDrawObjs() )
1784 if ( pFrame
->GetDrawObjs()->size() < nCnt
)
1787 // Do not increment index, in this case
1794 // #i28701# - restart layout process, if
1795 // requested by floating screen object formatting
1796 if (bRestartLayoutProcess
1797 // tdf#152106 loop control in multi-column sections to avoid of freezing
1798 && nLoopControlRunsInMultiCol
< nLoopControlMax
1799 // tdf#142080 if it was already on next page, and still is,
1800 // ignore restart, as restart could cause infinite loop
1801 && (wasFrameLowerOfLay
|| pLay
->IsAnLower(pFrame
)))
1803 bool bIsMultiColumn
= pSect
&& pSect
->GetSection() && pSect
->Lower() &&
1804 pSect
->Lower()->IsColumnFrame() && pSect
->Lower()->GetNext();
1805 if ( bIsMultiColumn
)
1806 ++nLoopControlRunsInMultiCol
;
1807 pFrame
= pLay
->ContainsAny();
1808 pAgainObj1
= nullptr;
1809 pAgainObj2
= nullptr;
1813 // #i28701# - format anchor frame after its objects
1814 // are formatted, if the wrapping style influence has to be considered.
1815 if ( pLay
->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) )
1817 pFrame
->Calc(pRenderContext
);
1822 pFrame
= pLay
->ContainsContent();
1823 if ( pFrame
&& pFrame
->IsInTab() )
1824 pFrame
= pFrame
->FindTabFrame();
1825 if( pFrame
&& pFrame
->IsInSct() )
1827 SwSectionFrame
* pTmp
= pFrame
->FindSctFrame();
1828 if( pTmp
!= pLay
&& pLay
->IsAnLower( pTmp
) )
1832 if ( pFrame
== pLoopControlCond
)
1836 nLoopControlRuns
= 0;
1837 pLoopControlCond
= pFrame
;
1840 if ( nLoopControlRuns
< nLoopControlMax
)
1843 OSL_FAIL( "LoopControl in CalcContent" );
1846 if ( pFrame
->IsTabFrame() )
1848 if (static_cast<SwTabFrame
*>(pFrame
)->m_bLockBackMove
)
1850 assert(static_cast<SwTabFrame
*>(pFrame
)->IsFollow());
1851 static_cast<SwTabFrame
*>(pFrame
)->m_bLockBackMove
= false;
1852 // tdf#150606 encourage it to move back in FormatLayout()
1853 if (static_cast<SwTabFrame
*>(pFrame
)->m_bWantBackMove
)
1855 static_cast<SwTabFrame
*>(pFrame
)->m_bWantBackMove
= false;
1856 pFrame
->InvalidatePos();
1861 pFrame
= bPrevInvalid
? pTmpPrev
: pFrame
->FindNext();
1862 if( !bPrevInvalid
&& pFrame
&& pFrame
->IsSctFrame() && pSect
)
1864 // Empty SectionFrames could be present here
1865 while( pFrame
&& pFrame
->IsSctFrame() && !static_cast<SwSectionFrame
*>(pFrame
)->GetSection() )
1866 pFrame
= pFrame
->FindNext();
1868 // If FindNext returns the Follow of the original Area, we want to
1869 // continue with this content as long as it flows back.
1870 if( pFrame
&& pFrame
->IsSctFrame() && ( pFrame
== pSect
->GetFollow() ||
1871 static_cast<SwSectionFrame
*>(pFrame
)->IsAnFollow( pSect
) ) )
1873 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1875 pFrame
->InvalidatePos_();
1878 // Stay in the pLay.
1879 // Except for SectionFrames with Follow: the first ContentFrame of the
1880 // Follow will be formatted, so that it gets a chance to move back
1881 // into the pLay. Continue as long as these Frames land in pLay.
1883 ( pLay
->IsAnLower( pFrame
) ||
1885 ( ( pSect
->HasFollow() &&
1886 ( pLay
->IsAnLower( pLast
) ||
1887 ( pLast
->IsInSct() &&
1888 pLast
->FindSctFrame()->IsAnFollow(pSect
) ) ) &&
1889 pSect
->GetFollow()->IsAnLower( pFrame
) ) ||
1890 ( pFrame
->IsInSct() &&
1891 pFrame
->FindSctFrame()->IsAnFollow( pSect
) ) ) ) ) );
1896 pLay
->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->InsertEndnotes(pSect
);
1897 pSect
->CalcFootnoteContent();
1899 if( pSect
->HasFollow() )
1901 SwSectionFrame
* pNxt
= pSect
->GetFollow();
1902 while( pNxt
&& !pNxt
->ContainsContent() )
1903 pNxt
= pNxt
->GetFollow();
1905 pNxt
->CalcFootnoteContent();
1909 pFrame
= pLay
->ContainsAny();
1920 void SwFlyFrame::MakeObjPos()
1922 if ( isFrameAreaPositionValid() )
1925 vcl::RenderContext
* pRenderContext
= getRootFrame()->GetCurrShell()->GetOut();
1926 setFrameAreaPositionValid(true);
1928 // use new class to position object
1929 GetAnchorFrame()->Calc(pRenderContext
);
1930 objectpositioning::SwToLayoutAnchoredObjectPosition
1931 aObjPositioning( *GetVirtDrawObj() );
1932 aObjPositioning
.CalcPosition();
1935 // update relative position
1936 SetCurrRelPos( aObjPositioning
.GetRelPos() );
1939 SwRectFnSet
aRectFnSet(GetAnchorFrame());
1940 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1941 aFrm
.Pos( aObjPositioning
.GetRelPos() );
1942 aFrm
.Pos() += aRectFnSet
.GetPos(GetAnchorFrame()->getFrameArea());
1946 InvalidateObjRectWithSpaces();
1949 void SwFlyFrame::MakePrtArea( const SwBorderAttrs
&rAttrs
)
1951 if ( !isFramePrintAreaValid() )
1953 setFramePrintAreaValid(true);
1955 // consider vertical layout
1956 SwRectFnSet
aRectFnSet(this);
1957 aRectFnSet
.SetXMargins( *this, rAttrs
.CalcLeftLine(),
1958 rAttrs
.CalcRightLine() );
1959 aRectFnSet
.SetYMargins( *this, rAttrs
.CalcTopLine(),
1960 rAttrs
.CalcBottomLine() );
1964 void SwFlyFrame::MakeContentPos( const SwBorderAttrs
&rAttrs
)
1966 if ( m_bValidContentPos
)
1969 m_bValidContentPos
= true;
1971 const SwTwips nUL
= rAttrs
.CalcTopLine() + rAttrs
.CalcBottomLine();
1972 Size
aRelSize( CalcRel( GetFormat()->GetFrameSize() ) );
1974 SwRectFnSet
aRectFnSet(this);
1975 tools::Long nMinHeight
= 0;
1977 nMinHeight
= aRectFnSet
.IsVert() ? aRelSize
.Width() : aRelSize
.Height();
1979 Point aNewContentPos
= getFramePrintArea().Pos();
1980 const SdrTextVertAdjust nAdjust
= GetFormat()->GetTextVertAdjust().GetValue();
1982 if( nAdjust
!= SDRTEXTVERTADJUST_TOP
)
1984 const SwTwips nContentHeight
= CalcContentHeight(&rAttrs
, nMinHeight
, nUL
);
1987 if( nContentHeight
!= 0)
1988 nDiff
= aRectFnSet
.GetHeight(getFramePrintArea()) - nContentHeight
;
1992 if( nAdjust
== SDRTEXTVERTADJUST_CENTER
)
1994 if( aRectFnSet
.IsVertL2R() )
1995 aNewContentPos
.setX(aNewContentPos
.getX() + nDiff
/2);
1996 else if( aRectFnSet
.IsVert() )
1997 aNewContentPos
.setX(aNewContentPos
.getX() - nDiff
/2);
1999 aNewContentPos
.setY(aNewContentPos
.getY() + nDiff
/2);
2001 else if( nAdjust
== SDRTEXTVERTADJUST_BOTTOM
)
2003 if( aRectFnSet
.IsVertL2R() )
2004 aNewContentPos
.setX(aNewContentPos
.getX() + nDiff
);
2005 else if( aRectFnSet
.IsVert() )
2006 aNewContentPos
.setX(aNewContentPos
.getX() - nDiff
);
2008 aNewContentPos
.setY(aNewContentPos
.getY() + nDiff
);
2012 if( aNewContentPos
!= ContentPos() )
2014 ContentPos() = aNewContentPos
;
2015 for( SwFrame
*pFrame
= Lower(); pFrame
; pFrame
= pFrame
->GetNext())
2017 pFrame
->InvalidatePos();
2023 void SwFlyFrame::InvalidateContentPos()
2025 m_bValidContentPos
= false;
2029 void SwFlyFrame::SelectionHasChanged(SwFEShell
* pShell
)
2031 SwWrtShell
* pWrtSh
= dynamic_cast< SwWrtShell
* >(pShell
);
2032 if (pWrtSh
== nullptr)
2035 UpdateUnfloatButton(pWrtSh
, IsShowUnfloatButton(pWrtSh
));
2038 bool SwFlyFrame::IsShowUnfloatButton(SwWrtShell
* pWrtSh
) const
2040 if (pWrtSh
== nullptr)
2043 // In read only mode we don't allow unfloat operation
2044 if (pWrtSh
->GetViewOptions()->IsReadonly())
2047 const SdrObject
*pObj
= GetFrameFormat().FindRealSdrObject();
2048 if (pObj
== nullptr)
2051 // SwFlyFrame itself can mean images, ole objects, etc, but we interested in actual text frames
2052 if (SwFEShell::GetObjCntType(*pObj
) != OBJCNT_FLY
)
2055 // We show the button only for the selected text frame
2056 SwDrawView
*pView
= pWrtSh
->Imp()->GetDrawView();
2057 if (pView
== nullptr)
2060 // Fly frame can be selected only alone
2061 if (pView
->GetMarkedObjectList().GetMarkCount() != 1)
2064 if(!pView
->IsObjMarked(pObj
))
2067 // A frame is a floating table if there is only one table (and maybe some whitespaces) inside it
2068 int nTableCount
= 0;
2069 const SwFrame
* pLower
= GetLower();
2070 const SwTabFrame
* pTable
= nullptr;
2073 if (pLower
->IsTabFrame())
2075 pTable
= static_cast<const SwTabFrame
*>(pLower
);
2077 if (nTableCount
> 1 || pTable
== nullptr)
2081 if (pLower
->IsTextFrame())
2083 const SwTextFrame
* pTextFrame
= static_cast<const SwTextFrame
*>(pLower
);
2084 if (!o3tl::trim(pTextFrame
->GetText()).empty())
2087 pLower
= pLower
->GetNext();
2090 if (nTableCount
!= 1 || pTable
== nullptr)
2093 // Show the unfold button only for multipage tables
2094 const SwBodyFrame
*pBody
= GetAnchorFrame()->FindBodyFrame();
2095 if (pBody
== nullptr)
2098 tools::Long nBodyHeight
= pBody
->getFrameArea().Height();
2099 tools::Long nTableHeight
= pTable
->getFrameArea().Height();
2100 tools::Long nFrameOffset
= std::abs(GetAnchorFrame()->getFrameArea().Top() - pBody
->getFrameArea().Top());
2102 return nBodyHeight
< nTableHeight
+ nFrameOffset
;
2105 void SwFlyFrame::ActiveUnfloatButton(SwWrtShell
* pWrtSh
)
2107 SwEditWin
& rEditWin
= pWrtSh
->GetView().GetEditWin();
2108 SwFrameControlsManager
& rMngr
= rEditWin
.GetFrameControlsManager();
2109 SwFrameControlPtr pControl
= rMngr
.GetControl(FrameControlType::FloatingTable
, this);
2110 if (pControl
&& pControl
->GetWindow())
2112 pControl
->GetWindow()->MouseButtonDown(MouseEvent());
2116 void SwFlyFrame::UpdateUnfloatButton(SwWrtShell
* pWrtSh
, bool bShow
) const
2118 if (pWrtSh
== nullptr)
2121 SwEditWin
& rEditWin
= pWrtSh
->GetView().GetEditWin();
2122 SwFrameControlsManager
& rMngr
= rEditWin
.GetFrameControlsManager();
2123 Point aTopRightPixel
= rEditWin
.LogicToPixel( getFrameArea().TopRight() );
2124 rMngr
.SetUnfloatTableButton(this, bShow
, aTopRightPixel
);
2127 SwFlyAtContentFrame
* SwFlyFrame::DynCastFlyAtContentFrame()
2129 return IsFlyAtContentFrame() ? static_cast<SwFlyAtContentFrame
*>(this) : nullptr;
2132 SwTwips
SwFlyFrame::Grow_( SwTwips nDist
, bool bTst
)
2134 SwRectFnSet
aRectFnSet(this);
2135 if ( Lower() && !IsColLocked() && !HasFixSize() )
2137 SwTwips nSize
= aRectFnSet
.GetHeight(getFrameArea());
2138 if( nSize
> 0 && nDist
> ( LONG_MAX
- nSize
) )
2139 nDist
= LONG_MAX
- nSize
;
2144 if ( Lower()->IsColumnFrame() )
2145 { // If it's a Column Frame, the Format takes control of the
2146 // resizing (due to the adjustment).
2149 // #i28701# - unlock position of Writer fly frame
2159 const SwRect
aOld( GetObjRectWithSpaces() );
2161 const bool bOldLock
= m_bLocked
;
2163 if ( IsFlyFreeFrame() )
2165 // #i37068# - no format of position here
2166 // and prevent move in method <CheckClip(..)>.
2167 // This is needed to prevent layout loop caused by nested
2168 // Writer fly frames - inner Writer fly frames format its
2169 // anchor, which grows/shrinks the outer Writer fly frame.
2170 // Note: position will be invalidated below.
2171 setFrameAreaPositionValid(true);
2174 // Suppress format of width for autowidth frame, because the
2175 // format of the width would call <SwTextFrame::CalcFitToContent()>
2176 // for the lower frame, which initiated this grow.
2177 const bool bOldFormatHeightOnly
= m_bFormatHeightOnly
;
2178 const SwFormatFrameSize
& rFrameSz
= GetFormat()->GetFrameSize();
2179 if ( rFrameSz
.GetWidthSizeType() != SwFrameSize::Fixed
)
2181 m_bFormatHeightOnly
= true;
2183 SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
2186 static_cast<SwFlyFreeFrame
*>(this)->SetNoMoveOnCheckClip( true );
2187 static_cast<SwFlyFreeFrame
*>(this)->SwFlyFreeFrame::MakeAll(pSh
->GetOut());
2188 static_cast<SwFlyFreeFrame
*>(this)->SetNoMoveOnCheckClip( false );
2191 if ( rFrameSz
.GetWidthSizeType() != SwFrameSize::Fixed
)
2193 m_bFormatHeightOnly
= bOldFormatHeightOnly
;
2197 MakeAll(getRootFrame()->GetCurrShell()->GetOut());
2202 SwRect
aNew(GetObjRectWithSpaces());
2203 if (IsFlySplitAllowed() && aNew
.Height() - aOld
.Height() < nDist
)
2205 // We are allowed to split and the actual growth is less than the requested growth.
2206 const SwFrame
* pAnchor
= GetAnchorFrame();
2207 if (SwFrame
* pAnchorChar
= FindAnchorCharFrame())
2209 pAnchor
= pAnchorChar
;
2213 SwTwips nDeadline
= GetFlyAnchorBottom(this, *pAnchor
);
2214 SwTwips nTop
= aRectFnSet
.GetTop(getFrameArea());
2215 SwTwips nBottom
= nTop
+ aRectFnSet
.GetHeight(getFrameArea());
2216 SwTwips nMaxGrow
= nDeadline
- nBottom
;
2217 if (nDist
> nMaxGrow
)
2219 // The requested growth is more than what we can provide, limit it.
2222 // Grow & invalidate the size.
2223 SwTwips nRemaining
= nDist
- (aNew
.Height() - aOld
.Height());
2225 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2226 aRectFnSet
.AddBottom(aFrm
, nRemaining
);
2228 InvalidateObjRectWithSpaces();
2230 // Margins are unchanged, so increase the print height similar to the frame
2232 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
2233 aRectFnSet
.AddBottom(aPrt
, nRemaining
);
2235 aNew
= GetObjRectWithSpaces();
2239 ::Notify( this, FindPageFrame(), aOld
);
2240 return aRectFnSet
.GetHeight(aNew
)-aRectFnSet
.GetHeight(aOld
);
2244 // We're in test mode. Don't promise infinite growth for split flys, rather limit the
2245 // max size to the bottom of the upper.
2246 const SwFrame
* pAnchor
= GetAnchorFrame();
2247 if (SwFrame
* pAnchorChar
= FindAnchorCharFrame())
2249 pAnchor
= pAnchorChar
;
2251 if (pAnchor
&& IsFlySplitAllowed())
2253 SwTwips nDeadline
= GetFlyAnchorBottom(this, *pAnchor
);
2254 SwTwips nTop
= aRectFnSet
.GetTop(getFrameArea());
2255 SwTwips nBottom
= nTop
+ aRectFnSet
.GetHeight(getFrameArea());
2256 // Calculate max grow and compare to the requested growth, adding to nDist may
2257 // overflow when it's LONG_MAX.
2258 SwTwips nMaxGrow
= nDeadline
- nBottom
;
2259 if (nDist
> nMaxGrow
)
2270 SwTwips
SwFlyFrame::Shrink_( SwTwips nDist
, bool bTst
)
2272 if( Lower() && !IsColLocked() && !HasFixSize() )
2274 SwRectFnSet
aRectFnSet(this);
2275 SwTwips nHeight
= aRectFnSet
.GetHeight(getFrameArea());
2276 if ( nDist
> nHeight
)
2279 SwTwips nVal
= nDist
;
2280 if ( IsMinHeight() )
2282 const SwFormatFrameSize
& rFormatSize
= GetFormat()->GetFrameSize();
2283 SwTwips nFormatHeight
= aRectFnSet
.IsVert() ? rFormatSize
.GetWidth() : rFormatSize
.GetHeight();
2285 nVal
= std::min( nDist
, nHeight
- nFormatHeight
);
2291 if ( Lower()->IsColumnFrame() )
2292 { // If it's a Column Frame, the Format takes control of the
2293 // resizing (due to the adjustment).
2296 SwRect
aOld( GetObjRectWithSpaces() );
2299 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2300 aRectFnSet
.SetHeight( aFrm
, nHeight
- nVal
);
2304 if ( nHeight
- nVal
!= 0 )
2306 InvalidateObjRectWithSpaces();
2309 nHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
2312 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
2313 aRectFnSet
.SetHeight( aPrt
, nHeight
- nVal
);
2318 ::Notify( this, FindPageFrame(), aOld
);
2320 if ( GetAnchorFrame()->IsInFly() )
2321 AnchorFrame()->FindFlyFrame()->Shrink( nDist
, bTst
);
2328 const SwRect
aOld( GetObjRectWithSpaces() );
2330 const bool bOldLocked
= m_bLocked
;
2332 if ( IsFlyFreeFrame() )
2334 // #i37068# - no format of position here
2335 // and prevent move in method <CheckClip(..)>.
2336 // This is needed to prevent layout loop caused by nested
2337 // Writer fly frames - inner Writer fly frames format its
2338 // anchor, which grows/shrinks the outer Writer fly frame.
2339 // Note: position will be invalidated below.
2340 setFrameAreaPositionValid(true);
2343 // Suppress format of width for autowidth frame, because the
2344 // format of the width would call <SwTextFrame::CalcFitToContent()>
2345 // for the lower frame, which initiated this shrink.
2346 const bool bOldFormatHeightOnly
= m_bFormatHeightOnly
;
2347 const SwFormatFrameSize
& rFrameSz
= GetFormat()->GetFrameSize();
2348 if ( rFrameSz
.GetWidthSizeType() != SwFrameSize::Fixed
)
2350 m_bFormatHeightOnly
= true;
2352 static_cast<SwFlyFreeFrame
*>(this)->SetNoMoveOnCheckClip( true );
2353 static_cast<SwFlyFreeFrame
*>(this)->SwFlyFreeFrame::MakeAll(getRootFrame()->GetCurrShell()->GetOut());
2354 static_cast<SwFlyFreeFrame
*>(this)->SetNoMoveOnCheckClip( false );
2356 if ( rFrameSz
.GetWidthSizeType() != SwFrameSize::Fixed
)
2358 m_bFormatHeightOnly
= bOldFormatHeightOnly
;
2362 MakeAll(getRootFrame()->GetCurrShell()->GetOut());
2367 const SwRect
aNew( GetObjRectWithSpaces() );
2370 ::Notify( this, FindPageFrame(), aOld
);
2371 if ( GetAnchorFrame()->IsInFly() )
2372 AnchorFrame()->FindFlyFrame()->Shrink( nDist
, bTst
);
2374 return aRectFnSet
.GetHeight(aOld
) -
2375 aRectFnSet
.GetHeight(aNew
);
2382 Size
SwFlyFrame::ChgSize( const Size
& aNewSize
)
2385 // If the fly frame anchored at-paragraph or at-character contains an OLE
2386 // object, assure that the new size fits into the current clipping area
2388 Size
aAdjustedNewSize( aNewSize
);
2390 if ( dynamic_cast<SwFlyAtContentFrame
*>(this) &&
2391 Lower() && dynamic_cast<SwNoTextFrame
*>(Lower()) &&
2392 static_cast<SwNoTextFrame
*>(Lower())->GetNode()->GetOLENode() )
2395 ::CalcClipRect( GetVirtDrawObj(), aClipRect
, false );
2396 if ( aAdjustedNewSize
.Width() > aClipRect
.Width() )
2398 aAdjustedNewSize
.setWidth( aClipRect
.Width() );
2400 if ( aAdjustedNewSize
.Height() > aClipRect
.Height() )
2402 aAdjustedNewSize
.setWidth( aClipRect
.Height() );
2407 if ( aAdjustedNewSize
!= getFrameArea().SSize() )
2409 SwFrameFormat
*pFormat
= GetFormat();
2410 SwFormatFrameSize
aSz( pFormat
->GetFrameSize() );
2411 aSz
.SetWidth( aAdjustedNewSize
.Width() );
2412 aSz
.SetHeight( aAdjustedNewSize
.Height() );
2413 // go via the Doc for UNDO
2414 pFormat
->GetDoc()->SetAttr( aSz
, *pFormat
);
2415 return aSz
.GetSize();
2418 return getFrameArea().SSize();
2421 bool SwFlyFrame::IsLowerOf( const SwLayoutFrame
* pUpperFrame
) const
2423 OSL_ENSURE( GetAnchorFrame(), "8-( Fly is lost in Space." );
2424 const SwFrame
* pFrame
= GetAnchorFrame();
2427 if ( pFrame
== pUpperFrame
)
2429 pFrame
= pFrame
->IsFlyFrame()
2430 ? static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame()
2431 : pFrame
->GetUpper();
2436 void SwFlyFrame::Cut()
2440 void SwFrame::AppendFly( SwFlyFrame
*pNew
)
2444 m_pDrawObjs
.reset(new SwSortedObjs());
2446 m_pDrawObjs
->Insert( *pNew
);
2447 pNew
->ChgAnchorFrame( this );
2449 // Register at the page
2450 // If there's none present, register via SwPageFrame::PreparePage
2451 SwPageFrame
* pPage
= FindPageFrame();
2452 if ( pPage
!= nullptr )
2454 pPage
->AppendFlyToPage( pNew
);
2458 void SwFrame::RemoveFly( SwFlyFrame
*pToRemove
)
2460 // Deregister from the page
2461 // Could already have happened, if the page was already destructed
2462 SwPageFrame
*pPage
= pToRemove
->FindPageFrame();
2463 if ( pPage
&& pPage
->GetSortedObjs() )
2465 pPage
->RemoveFlyFromPage( pToRemove
);
2468 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2471 if ( pToRemove
->IsAccessibleFrame() &&
2472 pToRemove
->GetFormat() &&
2473 !pToRemove
->IsFlyInContentFrame() )
2475 SwRootFrame
*pRootFrame
= getRootFrame();
2476 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() )
2478 SwViewShell
*pVSh
= pRootFrame
->GetCurrShell();
2479 if( pVSh
&& pVSh
->Imp() )
2481 pVSh
->Imp()->DisposeAccessibleFrame( pToRemove
);
2488 m_pDrawObjs
->Remove(*pToRemove
);
2489 if (!m_pDrawObjs
->size())
2491 m_pDrawObjs
.reset();
2494 pToRemove
->ChgAnchorFrame( nullptr );
2496 if ( !pToRemove
->IsFlyInContentFrame() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
2497 GetUpper()->InvalidateSize();
2500 void SwFrame::AppendDrawObj( SwAnchoredObject
& _rNewObj
)
2502 assert(!m_pDrawObjs
|| m_pDrawObjs
->is_sorted());
2504 if ( dynamic_cast<const SwAnchoredDrawObject
*>( &_rNewObj
) == nullptr )
2506 OSL_FAIL( "SwFrame::AppendDrawObj(..) - anchored object of unexpected type -> object not appended" );
2510 if ( dynamic_cast<const SwDrawVirtObj
*>(_rNewObj
.GetDrawObj()) == nullptr &&
2511 _rNewObj
.GetAnchorFrame() && _rNewObj
.GetAnchorFrame() != this )
2513 assert(!m_pDrawObjs
|| m_pDrawObjs
->is_sorted());
2514 // perform disconnect from layout, if 'master' drawing object is appended
2516 static_cast<SwDrawContact
*>(::GetUserCall( _rNewObj
.GetDrawObj() ))->
2517 DisconnectFromLayout( false );
2518 assert(!m_pDrawObjs
|| m_pDrawObjs
->is_sorted());
2521 if ( _rNewObj
.GetAnchorFrame() != this )
2525 m_pDrawObjs
.reset(new SwSortedObjs());
2527 m_pDrawObjs
->Insert(_rNewObj
);
2528 _rNewObj
.ChgAnchorFrame( this );
2532 // Assure the control objects and group objects containing controls are on the control layer
2533 if ( ::CheckControlLayer( _rNewObj
.DrawObj() ) )
2535 const IDocumentDrawModelAccess
& rIDDMA
= getIDocumentDrawModelAccess();
2536 const SdrLayerID
aCurrentLayer(_rNewObj
.DrawObj()->GetLayer());
2537 const SdrLayerID
aControlLayerID(rIDDMA
.GetControlsId());
2538 const SdrLayerID
aInvisibleControlLayerID(rIDDMA
.GetInvisibleControlsId());
2540 if(aCurrentLayer
!= aControlLayerID
&& aCurrentLayer
!= aInvisibleControlLayerID
)
2542 if ( aCurrentLayer
== rIDDMA
.GetInvisibleHellId() ||
2543 aCurrentLayer
== rIDDMA
.GetInvisibleHeavenId() )
2545 _rNewObj
.DrawObj()->SetLayer(aInvisibleControlLayerID
);
2549 _rNewObj
.DrawObj()->SetLayer(aControlLayerID
);
2551 //The layer is part of the key used to sort the obj, so update
2552 //its position if the layer changed.
2553 m_pDrawObjs
->Update(_rNewObj
);
2557 // no direct positioning needed, but invalidate the drawing object position
2558 _rNewObj
.InvalidateObjPos();
2560 // register at page frame
2561 SwPageFrame
* pPage
= FindPageFrame();
2564 pPage
->AppendDrawObjToPage( _rNewObj
);
2567 // Notify accessible layout.
2568 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2569 SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
2572 SwRootFrame
* pLayout
= getRootFrame();
2573 if( pLayout
&& pLayout
->IsAnyShellAccessible() )
2575 pSh
->Imp()->AddAccessibleObj( _rNewObj
.GetDrawObj() );
2580 assert(!m_pDrawObjs
|| m_pDrawObjs
->is_sorted());
2583 void SwFrame::RemoveDrawObj( SwAnchoredObject
& _rToRemoveObj
)
2585 // Notify accessible layout.
2586 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2587 SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
2590 SwRootFrame
* pLayout
= getRootFrame();
2591 if (pLayout
&& pLayout
->IsAnyShellAccessible())
2592 pSh
->Imp()->DisposeAccessibleObj(_rToRemoveObj
.GetDrawObj(), false);
2596 // deregister from page frame
2597 SwPageFrame
* pPage
= _rToRemoveObj
.GetPageFrame();
2598 if ( pPage
&& pPage
->GetSortedObjs() )
2599 pPage
->RemoveDrawObjFromPage( _rToRemoveObj
);
2601 m_pDrawObjs
->Remove(_rToRemoveObj
);
2602 if (!m_pDrawObjs
->size())
2604 m_pDrawObjs
.reset();
2606 _rToRemoveObj
.ChgAnchorFrame( nullptr );
2608 assert(!m_pDrawObjs
|| m_pDrawObjs
->is_sorted());
2611 void SwFrame::InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs
)
2613 if ( !GetDrawObjs() )
2616 // #i26945# - determine page the frame is on,
2617 // in order to check, if anchored object is registered at the same
2619 const SwPageFrame
* pPageFrame
= FindPageFrame();
2620 // #i28701# - re-factoring
2621 for (SwAnchoredObject
* pAnchoredObj
: *GetDrawObjs())
2623 if ( _bNoInvaOfAsCharAnchoredObjs
&&
2624 (pAnchoredObj
->GetFrameFormat().GetAnchor().GetAnchorId()
2625 == RndStdIds::FLY_AS_CHAR
) )
2629 // #i26945# - no invalidation, if anchored object
2630 // isn't registered at the same page and instead is registered at
2631 // the page, where its anchor character text frame is on.
2632 if ( pAnchoredObj
->GetPageFrame() &&
2633 pAnchoredObj
->GetPageFrame() != pPageFrame
)
2635 SwTextFrame
* pAnchorCharFrame
= pAnchoredObj
->FindAnchorCharFrame();
2636 if ( pAnchorCharFrame
&&
2637 pAnchoredObj
->GetPageFrame() == pAnchorCharFrame
->FindPageFrame() )
2641 // #115759# - unlock its position, if anchored
2642 // object isn't registered at the page, where its anchor
2643 // character text frame is on, respectively if it has no
2644 // anchor character text frame.
2647 pAnchoredObj
->UnlockPosition();
2650 // #i51474# - reset flag, that anchored object
2651 // has cleared environment, and unlock its position, if the anchored
2652 // object is registered at the same page as the anchor frame is on.
2653 if ( pAnchoredObj
->ClearedEnvironment() &&
2654 pAnchoredObj
->GetPageFrame() &&
2655 pAnchoredObj
->GetPageFrame() == pPageFrame
)
2657 pAnchoredObj
->UnlockPosition();
2658 pAnchoredObj
->SetClearedEnvironment( false );
2660 // distinguish between writer fly frames and drawing objects
2661 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
2663 pFly
->Invalidate_();
2664 pFly
->InvalidatePos_();
2668 pAnchoredObj
->InvalidateObjPos();
2670 } // end of loop on objects, which are connected to the frame
2673 // #i26945# - correct check, if anchored object is a lower
2674 // of the layout frame. E.g., anchor character text frame can be a follow text
2676 // #i44016# - add parameter <_bUnlockPosOfObjs> to
2677 // force an unlockposition call for the lower objects.
2678 void SwLayoutFrame::NotifyLowerObjs( const bool _bUnlockPosOfObjs
)
2680 // invalidate lower floating screen objects
2681 SwPageFrame
* pPageFrame
= FindPageFrame();
2682 if ( !(pPageFrame
&& pPageFrame
->GetSortedObjs()) )
2685 SwSortedObjs
& rObjs
= *(pPageFrame
->GetSortedObjs());
2686 for (SwAnchoredObject
* pObj
: rObjs
)
2688 // #i26945# - check if anchored object is a lower
2689 // of the layout frame is changed to check, if its anchor frame
2690 // is a lower of the layout frame.
2691 // Determine the anchor frame - usually it's the anchor frame,
2692 // for at-character/as-character anchored objects the anchor character
2693 // text frame is taken.
2694 const SwFrame
* pAnchorFrame
= pObj
->GetAnchorFrameContainingAnchPos();
2695 if ( auto pFly
= pObj
->DynCastFlyFrame() )
2697 if ( pFly
->getFrameArea().Left() == FAR_AWAY
)
2700 if ( pFly
->IsAnLower( this ) )
2703 // #i26945# - use <pAnchorFrame> to check, if
2704 // fly frame is lower of layout frame resp. if fly frame is
2705 // at a different page registered as its anchor frame is on.
2706 const bool bLow
= IsAnLower( pAnchorFrame
);
2707 if ( bLow
|| pAnchorFrame
->FindPageFrame() != pPageFrame
)
2709 pFly
->Invalidate_( pPageFrame
);
2710 if ( !bLow
|| pFly
->IsFlyAtContentFrame() )
2713 if ( _bUnlockPosOfObjs
)
2715 pFly
->UnlockPosition();
2717 pFly
->InvalidatePos_();
2720 pFly
->InvalidatePrt_();
2725 assert( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) &&
2726 "<SwLayoutFrame::NotifyFlys() - anchored object of unexpected type" );
2727 // tdf#156728 invalidate fly positioned dependent on header/footer size
2728 bool isPositionedByHF(false);
2729 if (IsHeaderFrame() || IsFooterFrame())
2731 auto const nO(pObj
->GetFrameFormat().GetVertOrient().GetRelationOrient());
2732 if (nO
== text::RelOrientation::PAGE_PRINT_AREA
2733 || nO
== text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
2734 || nO
== text::RelOrientation::PAGE_PRINT_AREA_TOP
)
2736 isPositionedByHF
= true;
2739 // #i26945# - use <pAnchorFrame> to check, if
2740 // fly frame is lower of layout frame resp. if fly frame is
2741 // at a different page registered as its anchor frame is on.
2742 if ( IsAnLower( pAnchorFrame
) ||
2744 pAnchorFrame
->FindPageFrame() != pPageFrame
)
2747 if ( _bUnlockPosOfObjs
)
2749 pObj
->UnlockPosition();
2751 pObj
->InvalidateObjPos();
2757 void SwFlyFrame::NotifyDrawObj()
2759 SwVirtFlyDrawObj
* pObj
= GetVirtDrawObj();
2761 pObj
->SetBoundAndSnapRectsDirty();
2763 pObj
->BroadcastObjectChange();
2765 if ( GetFormat()->GetSurround().IsContour() )
2767 ClrContourCache( pObj
);
2769 else if(IsFlyFreeFrame() && static_cast< const SwFlyFreeFrame
* >(this)->supportsAutoContour())
2771 // RotateFlyFrame3: Also need to clear when changes happen
2772 // Caution: isTransformableSwFrame is already reset when resetting rotation, so
2773 // *additionally* reset in SwFlyFreeFrame::MakeAll when no more rotation
2774 ClrContourCache( pObj
);
2778 Size
SwFlyFrame::CalcRel( const SwFormatFrameSize
&rSz
) const
2780 Size
aRet( rSz
.GetSize() );
2782 const SwFrame
*pRel
= IsFlyLayFrame() ? GetAnchorFrame() : GetAnchorFrame()->GetUpper();
2783 if( pRel
) // LAYER_IMPL
2785 tools::Long nRelWidth
= LONG_MAX
, nRelHeight
= LONG_MAX
;
2786 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2787 if ( ( pRel
->IsBodyFrame() || pRel
->IsPageFrame() ) &&
2788 pSh
&& pSh
->GetViewOptions()->getBrowseMode() &&
2789 pSh
->VisArea().HasArea() )
2791 nRelWidth
= pSh
->GetBrowseWidth();
2792 nRelHeight
= pSh
->VisArea().Height();
2793 Size aBorder
= pSh
->GetOut()->PixelToLogic( pSh
->GetBrowseBorder() );
2794 nRelWidth
= std::min( nRelWidth
, pRel
->getFramePrintArea().Width() );
2795 nRelHeight
-= 2*aBorder
.Height();
2796 nRelHeight
= std::min( nRelHeight
, pRel
->getFramePrintArea().Height() );
2799 // At the moment only the "== PAGE_FRAME" and "!= PAGE_FRAME" cases are handled.
2800 // When size is a relative to page size, ignore size of SwBodyFrame.
2801 if (rSz
.GetWidthPercentRelation() != text::RelOrientation::PAGE_FRAME
)
2802 nRelWidth
= std::min( nRelWidth
, pRel
->getFramePrintArea().Width() );
2803 else if ( pRel
->IsPageFrame() )
2804 nRelWidth
= std::min( nRelWidth
, pRel
->getFrameArea().Width() );
2806 if (rSz
.GetHeightPercentRelation() != text::RelOrientation::PAGE_FRAME
)
2807 nRelHeight
= std::min( nRelHeight
, pRel
->getFramePrintArea().Height() );
2808 else if ( pRel
->IsPageFrame() )
2809 nRelHeight
= std::min( nRelHeight
, pRel
->getFrameArea().Height() );
2811 if( !pRel
->IsPageFrame() )
2813 const SwPageFrame
* pPage
= FindPageFrame();
2816 if (rSz
.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME
)
2817 // Ignore margins of pPage.
2818 nRelWidth
= std::min( nRelWidth
, pPage
->getFrameArea().Width() );
2820 nRelWidth
= std::min( nRelWidth
, pPage
->getFramePrintArea().Width() );
2821 if (rSz
.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME
)
2822 // Ignore margins of pPage.
2823 nRelHeight
= std::min( nRelHeight
, pPage
->getFrameArea().Height() );
2825 nRelHeight
= std::min( nRelHeight
, pPage
->getFramePrintArea().Height() );
2829 if ( rSz
.GetWidthPercent() && rSz
.GetWidthPercent() != SwFormatFrameSize::SYNCED
)
2830 aRet
.setWidth( nRelWidth
* rSz
.GetWidthPercent() / 100 );
2831 if ( rSz
.GetHeightPercent() && rSz
.GetHeightPercent() != SwFormatFrameSize::SYNCED
)
2832 aRet
.setHeight( nRelHeight
* rSz
.GetHeightPercent() / 100 );
2834 if ( rSz
.GetHeight() && rSz
.GetWidthPercent() == SwFormatFrameSize::SYNCED
)
2836 aRet
.setWidth( aRet
.Width() * ( aRet
.Height()) );
2837 aRet
.setWidth( aRet
.Width() / ( rSz
.GetHeight()) );
2839 else if ( rSz
.GetWidth() && rSz
.GetHeightPercent() == SwFormatFrameSize::SYNCED
)
2841 aRet
.setHeight( aRet
.Height() * ( aRet
.Width()) );
2842 aRet
.setHeight( aRet
.Height() / ( rSz
.GetWidth()) );
2848 static SwTwips
lcl_CalcAutoWidth( const SwLayoutFrame
& rFrame
)
2852 const SwFrame
* pFrame
= rFrame
.Lower();
2854 // No autowidth defined for columned frames
2855 if ( !pFrame
|| pFrame
->IsColumnFrame() )
2858 int nParagraphCount
= 0;
2862 if ( pFrame
->IsSctFrame() )
2864 nMin
= lcl_CalcAutoWidth( *static_cast<const SwSectionFrame
*>(pFrame
) );
2866 if ( pFrame
->IsTextFrame() )
2868 nMin
= const_cast<SwTextFrame
*>(static_cast<const SwTextFrame
*>(pFrame
))->CalcFitToContent();
2869 auto const& rParaSet(static_cast<const SwTextFrame
*>(pFrame
)->GetTextNodeForParaProps()->GetSwAttrSet());
2870 SvxFirstLineIndentItem
const& rFirstLine(rParaSet
.GetFirstLineIndent());
2871 SvxTextLeftMarginItem
const& rLeftMargin(rParaSet
.GetTextLeftMargin());
2872 SvxRightMarginItem
const& rRightMargin(rParaSet
.GetRightMargin());
2873 if (!static_cast<const SwTextFrame
*>(pFrame
)->IsLocked())
2875 nMin
+= rRightMargin
.GetRight() + rLeftMargin
.GetTextLeft()
2876 + rFirstLine
.GetTextFirstLineOffset();
2879 else if ( pFrame
->IsTabFrame() )
2881 const SwFormatFrameSize
& rTableFormatSz
= static_cast<const SwTabFrame
*>(pFrame
)->GetTable()->GetFrameFormat()->GetFrameSize();
2882 if ( USHRT_MAX
== rTableFormatSz
.GetSize().Width() ||
2883 text::HoriOrientation::NONE
== static_cast<const SwTabFrame
*>(pFrame
)->GetFormat()->GetHoriOrient().GetHoriOrient() )
2885 const SwPageFrame
* pPage
= rFrame
.FindPageFrame();
2887 nMin
= pFrame
->GetUpper()->IsVertical() ?
2888 pPage
->getFramePrintArea().Height() :
2889 pPage
->getFramePrintArea().Width();
2893 nMin
= rTableFormatSz
.GetSize().Width();
2900 pFrame
= pFrame
->GetNext();
2903 // tdf#124423 In Microsoft compatibility mode: widen the frame to max (PrintArea of the frame it anchored to) if it contains at least 2 paragraphs,
2904 // or 1 paragraph wider than its parent area.
2905 if (rFrame
.GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::FRAME_AUTOWIDTH_WITH_MORE_PARA
))
2907 const SwFrame
* pFrameRect
= rFrame
.IsFlyFrame() ? static_cast<const SwFlyFrame
*>(&rFrame
)->GetAnchorFrame() : rFrame
.Lower()->FindPageFrame();
2908 SwTwips nParentWidth
= rFrame
.IsVertical() ? pFrameRect
->getFramePrintArea().Height() : pFrameRect
->getFramePrintArea().Width();
2909 if (nParagraphCount
> 1 || nRet
> nParentWidth
)
2911 return nParentWidth
;
2918 /// #i13147# - If called for paint and the <SwNoTextFrame> contains
2919 /// a graphic, load of intrinsic graphic has to be avoided.
2920 bool SwFlyFrame::GetContour( tools::PolyPolygon
& rContour
,
2921 const bool _bForPaint
) const
2923 vcl::RenderContext
* pRenderContext
= getRootFrame()->GetCurrShell()->GetOut();
2925 const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame());
2929 if(GetFormat()->GetSurround().IsContour())
2931 SwNoTextNode
*pNd
= const_cast<SwNoTextNode
*>(static_cast<const SwNoTextNode
*>(static_cast<const SwNoTextFrame
*>(Lower())->GetNode()));
2932 // #i13147# - determine <GraphicObject> instead of <Graphic>
2933 // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic
2934 // node and method is called for paint.
2935 std::unique_ptr
<GraphicObject
> xTmpGrfObj
;
2936 const GraphicObject
* pGrfObj
= nullptr;
2937 const SwGrfNode
* pGrfNd
= pNd
->GetGrfNode();
2938 if ( pGrfNd
&& _bForPaint
)
2940 pGrfObj
= &(pGrfNd
->GetGrfObj());
2944 xTmpGrfObj
.reset(new GraphicObject(pNd
->GetGraphic()));
2945 pGrfObj
= xTmpGrfObj
.get();
2947 assert(pGrfObj
&& "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>.");
2948 if (pGrfObj
->GetType() != GraphicType::NONE
)
2950 if( !pNd
->HasContour() )
2952 //#i13147# - no <CreateContour> for a graphic
2953 // during paint. Thus, return (value of <bRet> should be <false>).
2954 if ( pGrfNd
&& _bForPaint
)
2956 OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." );
2959 pNd
->CreateContour();
2961 pNd
->GetContour( rContour
);
2962 // The Node holds the Polygon matching the original size of the graphic
2963 // We need to include the scaling here
2966 Lower()->Calc(pRenderContext
);
2967 static_cast<const SwNoTextFrame
*>(Lower())->GetGrfArea( aClip
, &aOrig
);
2968 // #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
2969 // in order to avoid that graphic has to be loaded for contour scale.
2970 //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() );
2972 OutputDevice
* pOutDev
= Application::GetDefaultDevice();
2973 const MapMode
aDispMap( MapUnit::MapTwip
);
2974 const MapMode
aGrfMap( pGrfObj
->GetPrefMapMode() );
2975 const Size
aGrfSize( pGrfObj
->GetPrefSize() );
2978 bool bPixelMap
= aGrfMap
.GetMapUnit() == MapUnit::MapPixel
;
2981 aOrgSize
= pOutDev
->PixelToLogic( aGrfSize
, aDispMap
);
2983 aOrgSize
= OutputDevice::LogicToLogic( aGrfSize
, aGrfMap
, aDispMap
);
2985 if ( aOrgSize
.Width() && aOrgSize
.Height() )
2987 double fScaleX
= static_cast<double>(aOrig
.Width()) / aOrgSize
.Width();
2988 double fScaleY
= static_cast<double>(aOrig
.Height()) / aOrgSize
.Height();
2990 for ( sal_uInt16 j
= 0, nPolyCount
= rContour
.Count(); j
< nPolyCount
; j
++ )
2992 tools::Polygon
& rPoly
= rContour
[ j
];
2994 for ( sal_uInt16 i
= 0, nCount
= rPoly
.GetSize(); i
< nCount
; i
++ )
2997 aNewPoint
= pOutDev
->PixelToLogic( rPoly
[ i
], aDispMap
);
2999 aNewPoint
= OutputDevice::LogicToLogic( rPoly
[ i
], aGrfMap
, aDispMap
);
3001 rPoly
[ i
] = Point( FRound( aNewPoint
.getX() * fScaleX
), FRound( aNewPoint
.getY() * fScaleY
) );
3006 // destroy created <GraphicObject>.
3008 rContour
.Move( aOrig
.Left(), aOrig
.Top() );
3009 if( !aClip
.Width() )
3011 if( !aClip
.Height() )
3013 rContour
.Clip( aClip
.SVRect() );
3014 rContour
.Optimize(PolyOptimizeFlags::CLOSE
);
3018 else if (IsFlyFreeFrame())
3020 const SwFlyFreeFrame
* pSwFlyFreeFrame(static_cast< const SwFlyFreeFrame
* >(this));
3022 if(nullptr != pSwFlyFreeFrame
&&
3023 pSwFlyFreeFrame
->supportsAutoContour() &&
3024 // isTransformableSwFrame already used in supportsAutoContour(), but
3025 // better check twice when it may get changed there...
3026 pSwFlyFreeFrame
->isTransformableSwFrame())
3028 // RotateFlyFrame: use untransformed SwFrame to allow text floating around.
3029 // Will be transformed below
3030 const TransformableSwFrame
* pTransformableSwFrame(pSwFlyFreeFrame
->getTransformableSwFrame());
3031 const SwRect
aFrameArea(pTransformableSwFrame
->getUntransformedFrameArea());
3032 rContour
= tools::PolyPolygon(tools::Polygon(aFrameArea
.SVRect()));
3033 bRet
= (0 != rContour
.Count());
3037 if(bRet
&& 0 != rContour
.Count())
3039 if (IsFlyFreeFrame() &&
3040 static_cast< const SwFlyFreeFrame
* >(this)->isTransformableSwFrame())
3042 // Need to adapt contour to transformation
3043 basegfx::B2DVector aScale
, aTranslate
;
3044 double fRotate
, fShearX
;
3045 getFrameAreaTransformation().decompose(aScale
, aTranslate
, fRotate
, fShearX
);
3047 if(!basegfx::fTools::equalZero(fRotate
))
3049 basegfx::B2DPolyPolygon
aSource(rContour
.getB2DPolyPolygon());
3050 const basegfx::B2DPoint
aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
3051 const basegfx::B2DHomMatrix
aRotateAroundCenter(
3052 basegfx::utils::createRotateAroundPoint(
3056 aSource
.transform(aRotateAroundCenter
);
3057 rContour
= tools::PolyPolygon(aSource
);
3067 const SwVirtFlyDrawObj
* SwFlyFrame::GetVirtDrawObj() const
3069 return static_cast<const SwVirtFlyDrawObj
*>(GetDrawObj());
3071 SwVirtFlyDrawObj
* SwFlyFrame::GetVirtDrawObj()
3073 return static_cast<SwVirtFlyDrawObj
*>(DrawObj());
3076 // implementation of pure virtual method declared in
3077 // base class <SwAnchoredObject>
3079 void SwFlyFrame::InvalidateObjPos()
3083 InvalidateObjRectWithSpaces();
3086 SwFrameFormat
& SwFlyFrame::GetFrameFormat()
3088 OSL_ENSURE( GetFormat(),
3089 "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
3090 return *GetFormat();
3092 const SwFrameFormat
& SwFlyFrame::GetFrameFormat() const
3094 OSL_ENSURE( GetFormat(),
3095 "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
3096 return *GetFormat();
3099 SwRect
SwFlyFrame::GetObjRect() const
3101 return getFrameArea();
3105 // for Writer fly frames the bounding rectangle equals the object rectangles
3106 SwRect
SwFlyFrame::GetObjBoundRect() const
3108 return GetObjRect();
3112 bool SwFlyFrame::SetObjTop_( const SwTwips _nTop
)
3114 const bool bChanged( getFrameArea().Pos().getY() != _nTop
);
3115 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3116 aFrm
.Pos().setY(_nTop
);
3120 bool SwFlyFrame::SetObjLeft_( const SwTwips _nLeft
)
3122 const bool bChanged( getFrameArea().Pos().getX() != _nLeft
);
3123 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3124 aFrm
.Pos().setX(_nLeft
);
3129 /** method to assure that anchored object is registered at the correct
3132 OD 2004-07-02 #i28701#
3134 void SwFlyFrame::RegisterAtCorrectPage()
3136 // default behaviour is to do nothing.
3139 void SwFlyFrame::RegisterAtPage(SwPageFrame
&)
3141 // default behaviour is to do nothing.
3144 /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
3146 OD 2004-05-11 #i28701#
3148 bool SwFlyFrame::IsFormatPossible() const
3150 return SwAnchoredObject::IsFormatPossible() &&
3151 !IsLocked() && !IsColLocked();
3154 void SwFlyFrame::GetAnchoredObjects( std::vector
<SwAnchoredObject
*>& aVector
, const SwFormat
& rFormat
)
3156 SwIterator
<SwFlyFrame
,SwFormat
> aIter( rFormat
);
3157 for( SwFlyFrame
* pFlyFrame
= aIter
.First(); pFlyFrame
; pFlyFrame
= aIter
.Next() )
3158 aVector
.push_back( pFlyFrame
);
3161 const SwFlyFrameFormat
* SwFlyFrame::GetFormat() const
3163 return static_cast< const SwFlyFrameFormat
* >( GetDep() );
3166 SwFlyFrameFormat
* SwFlyFrame::GetFormat()
3168 return static_cast< SwFlyFrameFormat
* >( GetDep() );
3171 void SwFlyFrame::dumpAsXml(xmlTextWriterPtr writer
) const
3173 (void)xmlTextWriterStartElement(writer
, reinterpret_cast<const xmlChar
*>("fly"));
3174 dumpAsXmlAttributes(writer
);
3176 (void)xmlTextWriterStartElement(writer
, BAD_CAST("infos"));
3177 dumpInfosAsXml(writer
);
3178 (void)xmlTextWriterEndElement(writer
);
3179 const SwSortedObjs
* pAnchored
= GetDrawObjs();
3180 if (pAnchored
&& pAnchored
->size() > 0)
3182 (void)xmlTextWriterStartElement(writer
, BAD_CAST("anchored"));
3184 for (SwAnchoredObject
* pObject
: *pAnchored
)
3186 pObject
->dumpAsXml(writer
);
3189 (void)xmlTextWriterEndElement(writer
);
3191 dumpChildrenAsXml(writer
);
3193 SwAnchoredObject::dumpAsXml(writer
);
3195 (void)xmlTextWriterEndElement(writer
);
3198 void SwFlyFrame::Calc(vcl::RenderContext
* pRenderContext
) const
3200 if ( !m_bValidContentPos
)
3201 const_cast<SwFlyFrame
*>(this)->PrepareMake(pRenderContext
);
3203 SwLayoutFrame::Calc(pRenderContext
);
3206 SwTwips
SwFlyFrame::CalcContentHeight(const SwBorderAttrs
*pAttrs
, const SwTwips nMinHeight
, const SwTwips nUL
)
3208 SwRectFnSet
aRectFnSet(this);
3209 SwTwips nHeight
= 0;
3212 if ( Lower()->IsColumnFrame() )
3214 FormatWidthCols( *pAttrs
, nUL
, nMinHeight
);
3215 nHeight
= aRectFnSet
.GetHeight(Lower()->getFrameArea());
3219 SwFrame
*pFrame
= Lower();
3222 nHeight
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
3223 if( pFrame
->IsTextFrame() && static_cast<SwTextFrame
*>(pFrame
)->IsUndersized() )
3224 // This TextFrame would like to be a bit larger
3225 nHeight
+= static_cast<SwTextFrame
*>(pFrame
)->GetParHeight()
3226 - aRectFnSet
.GetHeight(pFrame
->getFramePrintArea());
3227 else if( pFrame
->IsSctFrame() && static_cast<SwSectionFrame
*>(pFrame
)->IsUndersized() )
3228 nHeight
+= static_cast<SwSectionFrame
*>(pFrame
)->Undersize();
3229 pFrame
= pFrame
->GetNext();
3232 if ( GetDrawObjs() )
3234 const size_t nCnt
= GetDrawObjs()->size();
3235 SwTwips nTop
= aRectFnSet
.GetTop(getFrameArea());
3236 SwTwips nBorder
= aRectFnSet
.GetHeight(getFrameArea()) -
3237 aRectFnSet
.GetHeight(getFramePrintArea());
3238 for ( size_t i
= 0; i
< nCnt
; ++i
)
3240 SwAnchoredObject
* pAnchoredObj
= (*GetDrawObjs())[i
];
3241 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
3243 // consider only Writer fly frames, which follow the text flow.
3244 if ( pFly
->IsFlyLayFrame() &&
3245 pFly
->getFrameArea().Top() != FAR_AWAY
&&
3246 pFly
->GetFormat()->GetFollowTextFlow().GetValue() )
3248 SwTwips nDist
= -aRectFnSet
.BottomDist( pFly
->getFrameArea(), nTop
);
3249 if( nDist
> nBorder
+ nHeight
)
3250 nHeight
= nDist
- nBorder
;
3259 const SwFormatAnchor
* SwFlyFrame::GetAnchorFromPoolItem(const SfxPoolItem
& rItem
)
3261 switch(rItem
.Which())
3263 case RES_ATTRSET_CHG
:
3264 return rItem
.StaticWhichCast(RES_ATTRSET_CHG
).GetChgSet()->GetItem(RES_ANCHOR
, false);
3266 return static_cast<const SwFormatAnchor
*>(&rItem
);
3272 const SwFlyFrame
* SwFlyFrame::DynCastFlyFrame() const
3277 SwFlyFrame
* SwFlyFrame::DynCastFlyFrame()
3282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */