LibreOffice Module sw (master)  1
atrflyin.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <hintids.hxx>
21 #include <doc.hxx>
22 #include <IDocumentUndoRedo.hxx>
24 #include <pam.hxx>
25 #include <flyfrm.hxx>
26 #include <ndtxt.hxx>
27 #include <frmfmt.hxx>
28 #include <fmtflcnt.hxx>
29 #include <txtflcnt.hxx>
30 #include <fmtanchr.hxx>
31 #include <txtfrm.hxx>
32 #include <flyfrms.hxx>
33 #include <objectformatter.hxx>
34 #include <calbck.hxx>
35 #include <dcontact.hxx>
36 #include <textboxhelper.hxx>
37 #include <osl/diagnose.h>
38 
41  m_pTextAttr( nullptr ),
42  m_pFormat( pFrameFormat )
43 {
44 }
45 
46 bool SwFormatFlyCnt::operator==( const SfxPoolItem& rAttr ) const
47 {
48  assert(SfxPoolItem::operator==(rAttr));
49  return( m_pTextAttr && static_cast<const SwFormatFlyCnt&>(rAttr).m_pTextAttr &&
50  m_pTextAttr->GetStart() == static_cast<const SwFormatFlyCnt&>(rAttr).m_pTextAttr->GetStart() &&
51  m_pFormat == static_cast<const SwFormatFlyCnt&>(rAttr).GetFrameFormat() );
52 }
53 
55 {
56  return new SwFormatFlyCnt( m_pFormat );
57 }
58 
59 SwTextFlyCnt::SwTextFlyCnt( SwFormatFlyCnt& rAttr, sal_Int32 nStartPos )
60  : SwTextAttr( rAttr, nStartPos )
61 {
62  rAttr.m_pTextAttr = this;
63  SetHasDummyChar(true);
64 }
65 
93 {
94  SwFrameFormat* pFormat = GetFlyCnt().GetFrameFormat();
95  assert(pFormat);
96  // The FlyFrameFormat must be copied - CopyLayoutFormat
97  // (DocumentLayoutManager.cxx) creates the FlyFrameFormat and copies the
98  // content.
99 
100  // disable undo while copying attribute
101  ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
102  SwFormatAnchor aAnchor( pFormat->GetAnchor() );
103  if ((RndStdIds::FLY_AT_PAGE != aAnchor.GetAnchorId()) &&
104  (&rDoc != pFormat->GetDoc())) // different documents?
105  {
106  // JP 03.06.96: ensure that the copied anchor points to valid content!
107  // setting it to the correct position is done later.
108  SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfExtras(), +2 );
109  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
110  if( !pCNd )
111  pCNd = rDoc.GetNodes().GoNext( &aIdx );
112 
113  SwPosition pos = *aAnchor.GetContentAnchor();
114  pos.nNode = aIdx;
115  if (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId())
116  {
117  pos.nContent.Assign( pCNd, 0 );
118  }
119  else
120  {
121  pos.nContent.Assign( nullptr, 0 );
122  assert(false);
123  }
124  aAnchor.SetAnchor( &pos );
125  }
126 
127  SwFrameFormat* pNew = rDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, false, false );
128  const_cast<SwFormatFlyCnt&>(GetFlyCnt()).SetFlyFormat( pNew );
129 }
130 
137 {
138  // for Undo, the new anchor must be known already!
139 
140  SwDoc& rDoc = const_cast<SwDoc&>(pNode->GetDoc());
141 
142  SwIndex aIdx( const_cast<SwTextNode*>(pNode), GetStart() );
143  SwPosition aPos( *pNode->StartOfSectionNode(), aIdx );
144  SwFrameFormat* pFormat = GetFlyCnt().GetFrameFormat();
145  SwFormatAnchor aAnchor( pFormat->GetAnchor() );
146  SwNode *const pOldNode(aAnchor.GetContentAnchor()
147  ? &aAnchor.GetContentAnchor()->nNode.GetNode()
148  : nullptr);
149 
150  if (!pOldNode || !pOldNode->GetNodes().IsDocNodes() ||
151  pOldNode != static_cast<SwNode const *>(pNode))
152  {
153  aPos.nNode = *pNode;
154  }
155  else
156  {
157  aPos.nNode = *pOldNode;
158  }
159 
160  aAnchor.SetType( RndStdIds::FLY_AS_CHAR ); // default!
161  aAnchor.SetAnchor( &aPos );
162 
163  // in case of anchor change, delete all FlyFrames
164  // JP 25.04.95: if the Frames can be moved within SplitNode, they don't
165  // need to be deleted
166  if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
167  && RES_DRAWFRMFMT != pFormat->Which() )
168  pFormat->DelFrames();
169 
170  // copy into a different document?
171  if( &rDoc != pFormat->GetDoc() )
172  {
173  // disable undo while copying attribute
174  ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
175  SwFrameFormat* pNew = rDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, false, false );
176 
177  ::sw::UndoGuard const undoGuardFormat(
178  pFormat->GetDoc()->GetIDocumentUndoRedo());
179  pFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pFormat );
180  const_cast<SwFormatFlyCnt&>(GetFlyCnt()).SetFlyFormat( pNew );
181  }
182  else if( pNode->GetpSwpHints() &&
183  pNode->GetpSwpHints()->IsInSplitNode() &&
184  RES_DRAWFRMFMT != pFormat->Which() )
185  {
186  pFormat->LockModify();
187  pFormat->SetFormatAttr( aAnchor ); // only set the anchor
188  // tdf#91228 must notify the anchor nodes despite LockModify
189  assert(pOldNode);
190  pOldNode->RemoveAnchoredFly(pFormat);
191  aPos.nNode.GetNode().AddAnchoredFly(pFormat);
192  pFormat->UnlockModify();
193  }
194  else
195  {
196  assert(!pFormat->IsModifyLocked()); // need to notify anchor node
197  if (RES_DRAWFRMFMT == pFormat->Which())
198  {
199  if (SdrObject const*const pObj = pFormat->FindSdrObject())
200  { // tdf#123259 disconnect with *old* anchor position
201  static_cast<SwDrawContact*>(::GetUserCall(pObj))->DisconnectFromLayout(false);
202  }
203  }
204  pFormat->SetFormatAttr( aAnchor ); // only set the anchor
205 
206  // If the draw format has a TextBox, then set its anchor as well.
207  if (SwFrameFormat* pTextBox
209  {
210  SwFormatAnchor aTextBoxAnchor(pTextBox->GetAnchor());
211  aTextBoxAnchor.SetAnchor(aAnchor.GetContentAnchor());
212 
213  // SwFlyAtContentFrame::SwClientNotify() assumes the anchor has a matching layout frame, which
214  // may not be the case when we're in the process of a node split, so block
215  // notifications.
216  bool bIsInSplitNode = pNode->GetpSwpHints() && pNode->GetpSwpHints()->IsInSplitNode();
217  if (bIsInSplitNode)
218  {
219  pTextBox->LockModify();
220  }
221  else
222  {
223  // Otherwise delete fly frames on anchor change.
224  pTextBox->DelFrames();
225  }
226 
227  pTextBox->SetFormatAttr(aTextBoxAnchor);
228 
229  if (bIsInSplitNode)
230  {
231  pOldNode->RemoveAnchoredFly(pTextBox);
232  aPos.nNode.GetNode().AddAnchoredFly(pTextBox);
233  pTextBox->UnlockModify();
234  }
235  else
236  {
237  pTextBox->MakeFrames();
238  }
239  }
240  }
241 
242  // The node may have several SwTextFrames - for every SwTextFrame a
243  // SwFlyInContentFrame is created.
244 }
245 
246 
252 {
253  SwFrameFormat* pFrameFormat = GetFlyCnt().GetFrameFormat();
254  if( RES_DRAWFRMFMT == pFrameFormat->Which() )
255  {
256  OSL_ENSURE( false, "SwTextFlyCnt::GetFlyFrame_: DrawInCnt-under construction!" );
257  return nullptr;
258  }
259 
260  SwIterator<SwFlyFrame,SwFormat> aIter( *GetFlyCnt().m_pFormat );
261  assert(pCurrFrame->IsTextFrame());
262  SwFrame* pFrame = aIter.First();
263  if ( pFrame )
264  {
265  SwTextFrame *pFirst = const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCurrFrame));
266  while ( pFirst->IsFollow() )
267  pFirst = pFirst->FindMaster();
268  do
269  {
270  SwTextFrame *pTmp = pFirst;
271  do
272  { if( static_cast<SwFlyFrame*>(pFrame)->GetAnchorFrame() == static_cast<SwFrame*>(pTmp) )
273  {
274  if ( pTmp != pCurrFrame )
275  {
276  pTmp->RemoveFly( static_cast<SwFlyFrame*>(pFrame) );
277  const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCurrFrame))->AppendFly( static_cast<SwFlyFrame*>(pFrame) );
278  }
279  return static_cast<SwFlyInContentFrame*>(pFrame);
280  }
281  pTmp = pTmp->GetFollow();
282  } while ( pTmp );
283 
284  pFrame = aIter.Next();
285 
286  } while( pFrame );
287  }
288 
289  // We did not find a matching FlyFrame, so create a new one.
290  // AppendFly() triggers a reformat of pCurrentFrame. However, the
291  // recursion is blocked by the lock mechanism in SwTextFrame::Format().
292  SwFrame* pCurrentFrame = const_cast<SwFrame*>(pCurrFrame);
293  SwFlyInContentFrame *pFly = new SwFlyInContentFrame(static_cast<SwFlyFrameFormat*>(pFrameFormat), pCurrentFrame, pCurrentFrame);
294  pCurrentFrame->AppendFly(pFly);
295  pFly->RegistFlys();
296 
297  // We must ensure that the content of the FlyInCnt is fully formatted
298  // right after construction.
299  // #i26945# - Use new object formatter to format Writer
300  // fly frame and its content.
301  SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrame*>(pCurrFrame),
302  pCurrFrame->FindPageFrame() );
303 
304  return pFly;
305 }
306 
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetAnchor(const SwTextNode *pNode)
SetAnchor() is called by SwTextNode::InsertHint() and sets the anchor position in the SwFlyFrameForma...
Definition: atrflyin.cxx:136
Base class of the Writer layout elements.
Definition: frame.hxx:315
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
bool IsFollow() const
Definition: flowfrm.hxx:166
Marks a position in the document model.
Definition: pam.hxx:35
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:223
void SetHasDummyChar(const bool bFlag)
Definition: txatbase.hxx:76
SwNodeIndex nNode
Definition: pam.hxx:37
SwFlyInContentFrame * GetFlyFrame_(const SwFrame *pCurrFrame)
GetFlyFrame_() is called during text formatting by SwTextFormatter and searches for the SwFlyFrame fo...
Definition: atrflyin.cxx:251
Definition: doc.hxx:188
TElementType * Next()
Definition: calbck.hxx:365
virtual SwFrameFormat * CopyLayoutFormat(const SwFrameFormat &rSrc, const SwFormatAnchor &rNewAnchor, bool bSetTextFlyAtt, bool bMakeFrames)=0
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(57)
SwFormatFlyCnt(SwFrameFormat *pFrameFormat)
Definition: atrflyin.cxx:39
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
SwContact * GetUserCall(const SdrObject *pObj)
Returns the UserCall if applicable from the group object.
Definition: dcontact.cxx:171
virtual bool operator==(const SfxPoolItem &) const override
"Pure virtual methods" of SfxPoolItem.
Definition: atrflyin.cxx:46
virtual SwFormatFlyCnt * Clone(SfxItemPool *pPool=nullptr) const override
Definition: atrflyin.cxx:54
void CopyFlyFormat(SwDoc &rDoc)
An overview of how a new SwTextFlyCnt is created: MakeTextAttr() is called e.g.
Definition: atrflyin.cxx:92
SwFrameFormat * m_pFormat
My Fly/DrawFrame-format.
Definition: fmtflcnt.hxx:36
void AppendFly(SwFlyFrame *pNew)
Definition: fly.cxx:2180
constexpr TypedWhichId< SwDrawFrameFormat > RES_DRAWFRMFMT(159)
SwIndex nContent
Definition: pam.hxx:38
size_t pos
A wrapper around SfxPoolItem to store the start position of (usually) a text portion, with an optional end.
Definition: txatbase.hxx:41
bool IsTextFrame() const
Definition: frame.hxx:1235
sal_Int32 GetStart() const
Definition: txatbase.hxx:86
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:855
static SwFrameFormat * getOtherTextBoxFormat(const SwFrameFormat *pFormat, sal_uInt16 nType, SdrObject *pObject=nullptr)
If we have an associated TextFrame, then return that.
SwTextFlyCnt(SwFormatFlyCnt &rAttr, sal_Int32 nStart)
Definition: atrflyin.cxx:59
SwTextFlyCnt * m_pTextAttr
Definition: fmtflcnt.hxx:35
Style of a layout element.
Definition: frmfmt.hxx:59
bool IsInSplitNode() const
Definition: ndhints.hxx:206
void RemoveFly(SwFlyFrame *pToRemove)
Definition: fly.cxx:2198
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:132
SwDoc & GetDoc()
Definition: node.hxx:212
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
SwPageFrame * FindPageFrame()
Definition: frame.hxx:681
TElementType * First()
Definition: calbck.hxx:357
SwContentNode * GetContentNode()
Definition: node.hxx:616
FlyAnchors.
Definition: fmtanchr.hxx:34
void DelFrames(SwRootFrame const *pLayout)
Method deletes all views of document for the node.
Definition: node.cxx:1409
Marks a character position inside a document model node.
Definition: index.hxx:33
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:123
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:738
static bool FormatObj(SwAnchoredObject &_rAnchoredObj, SwFrame *_pAnchorFrame=nullptr, const SwPageFrame *_pPageFrame=nullptr)
method to format a given floating screen object
SwNodes & GetNodes()
Definition: doc.hxx:409
Format of a fly content.
Definition: fmtflcnt.hxx:32
SwFrameFormat * GetFrameFormat() const
Definition: fmtflcnt.hxx:45
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:161
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1293
void SetAnchor(const SwPosition *pPos)
Definition: atrfrm.cxx:1584
const SwFormatFlyCnt & GetFlyCnt() const
Definition: txatbase.hxx:210
Base class of the Writer document model elements.
Definition: node.hxx:80