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 .
21 #include <frmtool.hxx>
23 #include <fmtornt.hxx>
24 #include <rootfrm.hxx>
25 #include <flyfrms.hxx>
26 #include <dflyobj.hxx>
27 #include <IDocumentSettingAccess.hxx>
28 #include <IDocumentDrawModelAccess.hxx>
29 #include <osl/diagnose.h>
30 #include <o3tl/deleter.hxx>
32 SwFlyInContentFrame::SwFlyInContentFrame( SwFlyFrameFormat
*pFormat
, SwFrame
* pSib
, SwFrame
*pAnch
) :
33 SwFlyFrame( pFormat
, pSib
, pAnch
)
36 SwTwips nRel
= pFormat
->GetVertOrient().GetPos();
37 // OD 2004-05-27 #i26791# - member <aRelPos> moved to <SwAnchoredObject>
39 if( pAnch
&& pAnch
->IsVertical() )
43 SetCurrRelPos( aRelPos
);
46 void SwFlyInContentFrame::DestroyImpl()
48 if ( !GetFormat()->GetDoc()->IsInDtor() && GetAnchorFrame() )
50 SwRect
aTmp( GetObjRectWithSpaces() );
51 SwFlyInContentFrame::NotifyBackground( FindPageFrame(), aTmp
, PrepareHint::FlyFrameLeave
);
54 SwFlyFrame::DestroyImpl();
57 SwFlyInContentFrame::~SwFlyInContentFrame()
63 void SwFlyInContentFrame::SetRefPoint( const Point
& rPoint
,
64 const Point
& rRelAttr
,
65 const Point
& rRelPos
)
67 // OD 2004-05-27 #i26791# - member <aRelPos> moved to <SwAnchoredObject>
68 OSL_ENSURE( rPoint
!= m_aRef
|| rRelAttr
!= GetCurrRelPos(), "SetRefPoint: no change" );
69 std::unique_ptr
<SwFlyNotify
, o3tl::default_delete
<SwFlyNotify
>> xNotify
;
70 // No notify at a locked fly frame, if a fly frame is locked, there's
71 // already a SwFlyNotify object on the stack (MakeAll).
73 xNotify
.reset(new SwFlyNotify( this ));
75 SetCurrRelPos( rRelAttr
);
76 SwRectFnSet
aRectFnSet(GetAnchorFrame());
79 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
80 aRectFnSet
.SetPos( aFrm
, rPoint
+ rRelPos
);
84 InvalidateObjRectWithSpaces();
88 setFrameAreaPositionValid(false);
90 Calc(getRootFrame()->GetCurrShell()->GetOut());
95 void SwFlyInContentFrame::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
97 if (rHint
.GetId() == SfxHintId::SwAutoFormatUsedHint
)
99 // There's a FlyFrame, so use it
100 static_cast<const sw::AutoFormatUsedHint
&>(rHint
).SetUsed();
103 if (rHint
.GetId() == SfxHintId::SwFormatChange
)
105 SwFlyFrame::SwClientNotify(rMod
, rHint
);
107 AnchorFrame()->Prepare(PrepareHint::FlyFrameAttributesChanged
, GetFormat());
110 if (rHint
.GetId() == SfxHintId::SwAttrSetChange
)
112 auto pChangeHint
= static_cast<const sw::AttrSetChangeHint
*>(&rHint
);
113 std::pair
<std::unique_ptr
<SwAttrSetChg
>, std::unique_ptr
<SwAttrSetChg
>> aTweakedChgs
;
114 std::pair
<const SwAttrSetChg
*, const SwAttrSetChg
*> aSuperArgs(nullptr, nullptr);
115 const SwAttrSetChg
* pOldAttrSetChg
= pChangeHint
->m_pOld
;
116 const SwAttrSetChg
* pNewAttrSetChg
= pChangeHint
->m_pNew
;
119 && ((SfxItemState::SET
== pNewAttrSetChg
->GetChgSet()->GetItemState(RES_SURROUND
, false))
120 || (SfxItemState::SET
== pNewAttrSetChg
->GetChgSet()->GetItemState(RES_FRMMACRO
, false))))
122 aTweakedChgs
.second
= std::make_unique
<SwAttrSetChg
>(*pOldAttrSetChg
);
123 aTweakedChgs
.second
->ClearItem(RES_SURROUND
);
124 aTweakedChgs
.second
->ClearItem(RES_FRMMACRO
);
125 if(aTweakedChgs
.second
->Count())
127 aTweakedChgs
.first
= std::make_unique
<SwAttrSetChg
>(*pOldAttrSetChg
);
128 aTweakedChgs
.first
->ClearItem(RES_SURROUND
);
129 aTweakedChgs
.first
->ClearItem(RES_FRMMACRO
);
130 aSuperArgs
= std::pair
<const SwAttrSetChg
*, const SwAttrSetChg
*>(aTweakedChgs
.first
.get(), aTweakedChgs
.second
.get());
132 } else if (pNewAttrSetChg
&& pNewAttrSetChg
->GetChgSet()->Count())
133 aSuperArgs
= std::pair
<const SwAttrSetChg
*, const SwAttrSetChg
*>(pChangeHint
->m_pOld
, pChangeHint
->m_pNew
);
134 if(aSuperArgs
.second
)
136 SwFlyFrame::SwClientNotify(rMod
, sw::AttrSetChangeHint(aSuperArgs
.first
, aSuperArgs
.second
));
138 AnchorFrame()->Prepare(PrepareHint::FlyFrameAttributesChanged
, GetFormat());
142 if (rHint
.GetId() == SfxHintId::SwObjectDying
143 || rHint
.GetId() == SfxHintId::SwUpdateAttr
)
145 SwFlyFrame::SwClientNotify(rMod
, rHint
);
147 AnchorFrame()->Prepare(PrepareHint::FlyFrameAttributesChanged
, GetFormat());
150 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
152 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
153 std::pair
<const SfxPoolItem
*, const SfxPoolItem
*> aSuperArgs(nullptr, nullptr);
154 switch(pLegacy
->GetWhich())
160 aSuperArgs
= std::pair
<const SfxPoolItem
*, const SfxPoolItem
*>(pLegacy
->m_pOld
, pLegacy
->m_pNew
);
162 if(aSuperArgs
.second
)
164 SwFlyFrame::SwClientNotify(rMod
, sw::LegacyModifyHint(aSuperArgs
.first
, aSuperArgs
.second
));
166 AnchorFrame()->Prepare(PrepareHint::FlyFrameAttributesChanged
, GetFormat());
170 /// Here the content gets formatted initially.
171 void SwFlyInContentFrame::Format( vcl::RenderContext
* pRenderContext
, const SwBorderAttrs
*pAttrs
)
173 if ( !getFrameArea().Height() )
175 Lock(); //don't format the anchor on the crook.
176 SwContentFrame
*pContent
= ContainsContent();
178 { pContent
->Calc(pRenderContext
);
179 pContent
= pContent
->GetNextContentFrame();
183 SwFlyFrame::Format( pRenderContext
, pAttrs
);
186 /** Calculate object position
188 * @note: In contrast to other Frames, we only calculate the relative position
189 * here. The absolute position is only calculated using SetAbsPos.
191 void SwFlyInContentFrame::MakeObjPos()
193 if ( isFrameAreaPositionValid() )
196 setFrameAreaPositionValid(true);
197 SwFlyFrameFormat
*pFormat
= GetFormat();
198 const SwFormatVertOrient
&rVert
= pFormat
->GetVertOrient();
199 //Update the current values in the format if needed, during this we of
200 //course must not send any Modify.
201 const bool bVert
= GetAnchorFrame()->IsVertical();
202 SwTwips nOld
= rVert
.GetPos();
203 SwTwips nAct
= bVert
? -GetCurrRelPos().X() : GetCurrRelPos().Y();
206 SwFormatVertOrient
aVert( rVert
);
207 aVert
.SetPos( nAct
);
208 pFormat
->LockModify();
209 pFormat
->SetFormatAttr( aVert
);
210 pFormat
->UnlockModify();
214 void SwFlyInContentFrame::ActionOnInvalidation( const InvalidationType _nInvalid
)
216 if ( INVALID_POS
== _nInvalid
|| INVALID_ALL
== _nInvalid
)
217 AnchorFrame()->Prepare( PrepareHint::FlyFrameAttributesChanged
, GetFrameFormat() );
220 void SwFlyInContentFrame::NotifyBackground( SwPageFrame
*, const SwRect
& rRect
,
223 if ( eHint
== PrepareHint::FlyFrameAttributesChanged
)
224 AnchorFrame()->Prepare( PrepareHint::FlyFrameAttributesChanged
);
226 AnchorFrame()->Prepare( eHint
, static_cast<void const *>(&rRect
) );
229 Point
const & SwFlyInContentFrame::GetRelPos() const
231 Calc(getRootFrame()->GetCurrShell()->GetOut());
232 return GetCurrRelPos();
235 /// @see SwRowFrame::RegistFlys()
236 void SwFlyInContentFrame::RegistFlys()
238 SwPageFrame
*pPage
= FindPageFrame();
239 OSL_ENSURE( pPage
, "Register Flys without pages?" );
240 ::RegistFlys( pPage
, this );
243 void SwFlyInContentFrame::MakeAll(vcl::RenderContext
* /*pRenderContext*/)
245 // OD 2004-01-19 #110582#
246 if ( !GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
251 if ( !GetAnchorFrame() || IsLocked() || IsColLocked() || !FindPageFrame() )
254 Lock(); // The curtain falls
256 //does the notification in the DTor
257 const SwFlyNotify
aNotify( this );
258 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), this );
259 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
263 setFrameAreaSizeValid(false);
264 m_bHeightClipped
= m_bWidthClipped
= false;
267 while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() || !m_bValidContentPos
)
269 //Only stop, if the flag is set!!
270 if ( !isFrameAreaSizeValid() )
272 setFramePrintAreaValid(false);
275 if ( !isFramePrintAreaValid() )
277 MakePrtArea( rAttrs
);
278 m_bValidContentPos
= false;
281 if ( !isFrameAreaSizeValid() )
283 Format( getRootFrame()->GetCurrShell()->GetOut(), &rAttrs
);
286 if ( !isFrameAreaPositionValid() )
291 if ( !m_bValidContentPos
)
292 MakeContentPos( rAttrs
);
294 // re-activate clipping of as-character anchored Writer fly frames
295 // depending on compatibility option <ClipAsCharacterAnchoredWriterFlyFrames>
296 if ( isFrameAreaPositionValid() &&
297 isFrameAreaSizeValid() &&
298 GetFormat()->getIDocumentSettingAccess().get( DocumentSettingId::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME
) )
300 SwFrame
* pFrame
= AnchorFrame();
301 if ( getFrameArea().Left() == (pFrame
->getFrameArea().Left()+pFrame
->getFramePrintArea().Left()) &&
302 getFrameArea().Width() > pFrame
->getFramePrintArea().Width() )
304 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
305 aFrm
.Width( pFrame
->getFramePrintArea().Width() );
306 setFramePrintAreaValid(false);
307 m_bWidthClipped
= true;
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */