LibreOffice Module sw (master)  1
swbaslnk.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 <vcl/svapp.hxx>
22 #include <vcl/outdev.hxx>
23 
24 #include <osl/thread.hxx>
25 #include <salhelper/condition.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/lnkbase.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <editeng/boxitem.hxx>
30 #include <svx/svxids.hrc>
31 #include <sfx2/linkmgr.hxx>
32 #include <sfx2/event.hxx>
33 #include <svtools/soerr.hxx>
34 #include <sot/exchange.hxx>
35 #include <fmtfsize.hxx>
36 #include <fmtanchr.hxx>
37 #include <frmatr.hxx>
38 #include <frmfmt.hxx>
39 #include <doc.hxx>
42 #include <pam.hxx>
43 #include <editsh.hxx>
44 #include <swtable.hxx>
45 #include <docary.hxx>
46 #include <swevent.hxx>
47 #include <swbaslnk.hxx>
48 #include <swserv.hxx>
49 #include <ndgrf.hxx>
50 #include <ndole.hxx>
51 #include <hints.hxx>
52 #include <tabfrm.hxx>
53 #include <cntfrm.hxx>
54 #include <htmltbl.hxx>
55 #include <calbck.hxx>
56 #include <dialoghelp.hxx>
57 #include <memory>
58 
59 using namespace com::sun::star;
60 
61 static bool SetGrfFlySize( const Size& rGrfSz, SwGrfNode* pGrfNd, const Size &rOrigGrfSize );
62 
63 
64 static void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem )
65 {
66  //call first all not SwNoTextFrames, then the SwNoTextFrames.
67  // The reason is, that in the SwNoTextFrames the Graphic
68  // after a Paint will be swapped out! So all other "behind"
69  // them haven't a loaded Graphic.
70  rGrfNd.LockModify();
71  {
72  SwIterator<SwClient,SwGrfNode> aIter(rGrfNd);
73  for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next())
74  if(dynamic_cast<const SwContentFrame*>( pLast) == nullptr)
75  pLast->ModifyNotification(&rItem, &rItem);
76  }
77  {
79  for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next())
80  pLast->ModifyNotification(&rItem, &rItem);
81  }
82  rGrfNd.UnlockModify();
83 }
84 
86  const OUString& rMimeType, const uno::Any & rValue )
87 {
88  if( !m_pContentNode )
89  {
90  OSL_ENSURE(false, "DataChanged without ContentNode" );
91  return ERROR_GENERAL;
92  }
93 
94  SwDoc* pDoc = m_pContentNode->GetDoc();
95  if( pDoc->IsInDtor() || ChkNoDataFlag() )
96  {
97  return SUCCESS;
98  }
99 
101 
102  if( m_pContentNode->IsNoTextNode() &&
104  {
105  // Only a status change - serve Events?
106  OUString sState;
107 
108  if( rValue.hasValue() && ( rValue >>= sState ))
109  {
110  SvMacroItemId nEvent = SvMacroItemId::NONE;
111  switch( sState.toInt32() )
112  {
113  case sfx2::LinkManager::STATE_LOAD_OK: nEvent = SvMacroItemId::OnImageLoadDone; break;
114  case sfx2::LinkManager::STATE_LOAD_ERROR: nEvent = SvMacroItemId::OnImageLoadError; break;
115  case sfx2::LinkManager::STATE_LOAD_ABORT: nEvent = SvMacroItemId::OnImageLoadCancel; break;
116  }
117 
118  SwFrameFormat* pFormat;
119  if( nEvent != SvMacroItemId::NONE && nullptr != ( pFormat = m_pContentNode->GetFlyFormat() ))
120  {
121  SwCallMouseEvent aCallEvent;
122  aCallEvent.Set( EVENT_OBJECT_IMAGE, pFormat );
123  pDoc->CallEvent( nEvent, aCallEvent );
124  }
125  }
126  return SUCCESS; // That's it!
127  }
128 
129  bool bUpdate = false;
130  bool bFrameInPaint = false;
131  Size aGrfSz, aOldSz;
132 
133  SwGrfNode* pSwGrfNode = nullptr;
134 
135  if (m_pContentNode->IsGrfNode())
136  {
137  pSwGrfNode = m_pContentNode->GetGrfNode();
138  assert(pSwGrfNode && "Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)");
139  aOldSz = pSwGrfNode->GetTwipSize();
140  const GraphicObject& rGrfObj = pSwGrfNode->GetGrfObj();
141 
142  bFrameInPaint = pSwGrfNode->IsFrameInPaint();
143 
144  Graphic aGrf;
145 
146  OUString sReferer;
147  SfxObjectShell * sh = pDoc->GetPersist();
148  if (sh != nullptr && sh->HasName())
149  {
150  sReferer = sh->GetMedium()->GetName();
151  }
152 
153  // tdf#124698 if any auth dialog is needed, find what the parent window should be
154  weld::Window* pDlgParent = GetFrameWeld(pDoc);
155 
156  if( sfx2::LinkManager::GetGraphicFromAny(rMimeType, rValue, sReferer, aGrf, pDlgParent) &&
157  ( GraphicType::Default != aGrf.GetType() ||
158  GraphicType::Default != rGrfObj.GetType() ) )
159  {
160  aGrfSz = ::GetGraphicSizeTwip( aGrf, nullptr );
161 
162  pSwGrfNode->SetGraphic(aGrf);
163  bUpdate = true;
164 
165  // Always use the correct graphic size
166  if( aGrfSz.Height() && aGrfSz.Width() &&
167  aOldSz.Height() && aOldSz.Width() &&
168  aGrfSz != aOldSz )
169  {
170  pSwGrfNode->SetTwipSize(aGrfSz);
171  aOldSz = aGrfSz;
172  }
173  }
174  }
175  else if( m_pContentNode->IsOLENode() )
176  bUpdate = true;
177 
178  if ( !bUpdate || bFrameInPaint )
179  return SUCCESS;
180 
181  if (pSwGrfNode)
182  {
183  if (!SetGrfFlySize(aGrfSz, pSwGrfNode, aOldSz))
184  {
186  lcl_CallModify(*pSwGrfNode, aMsgHint);
187  return SUCCESS;
188  }
189  }
190 
191  return SUCCESS;
192 }
193 
194 static bool SetGrfFlySize( const Size& rGrfSz, SwGrfNode* pGrfNd, const Size& rOrigGrfSize )
195 {
196  bool bRet = false;
198  std::unique_ptr<CurrShell> pCurr;
199  if ( pGrfNd->GetDoc()->GetEditShell() )
200  pCurr.reset(new CurrShell( pSh ));
201 
202  Size aSz = rOrigGrfSize;
203  if ( !(aSz.Width() && aSz.Height()) &&
204  rGrfSz.Width() && rGrfSz.Height() )
205  {
206  SwFrameFormat* pFormat = nullptr;
207  if (pGrfNd->IsChgTwipSize())
208  pFormat = pGrfNd->GetFlyFormat();
209  if (nullptr != pFormat)
210  {
211  Size aCalcSz( aSz );
212  if ( !aSz.Height() && aSz.Width() )
213  // Calculate the right height
214  aCalcSz.setHeight( rGrfSz.Height() *
215  aSz.Width() / rGrfSz.Width() );
216  else if ( !aSz.Width() && aSz.Height() )
217  // Calculate the right width
218  aCalcSz.setWidth( rGrfSz.Width() *
219  aSz.Height() / rGrfSz.Height() );
220  else
221  // Take over height and width
222  aCalcSz = rGrfSz;
223 
224  const SvxBoxItem &rBox = pFormat->GetBox();
225  aCalcSz.AdjustWidth(rBox.CalcLineSpace(SvxBoxItemLine::LEFT) +
226  rBox.CalcLineSpace(SvxBoxItemLine::RIGHT) );
227  aCalcSz.AdjustHeight(rBox.CalcLineSpace(SvxBoxItemLine::TOP) +
228  rBox.CalcLineSpace(SvxBoxItemLine::BOTTOM) );
229  const SwFormatFrameSize& rOldAttr = pFormat->GetFrameSize();
230  if( rOldAttr.GetSize() != aCalcSz )
231  {
232  SwFormatFrameSize aAttr( rOldAttr );
233  aAttr.SetSize( aCalcSz );
234  pFormat->SetFormatAttr( aAttr );
235  bRet = true;
236  }
237 
238  if( !aSz.Width() )
239  {
240  // If the graphic is anchored in a table, we need to recalculate
241  // the table rows
242  const SwDoc *pDoc = pGrfNd->GetDoc();
243  const SwPosition* pAPos = pFormat->GetAnchor().GetContentAnchor();
244  SwTableNode *pTableNd;
245  if (pAPos && nullptr != (pTableNd = pAPos->nNode.GetNode().FindTableNode()))
246  {
247  const bool bLastGrf = !pTableNd->GetTable().DecGrfsThatResize();
248  SwHTMLTableLayout *pLayout =
249  pTableNd->GetTable().GetHTMLTableLayout();
250  if( pLayout )
251  {
252  const sal_uInt16 nBrowseWidth =
253  pLayout->GetBrowseWidthByTable( *pDoc );
254  if ( nBrowseWidth )
255  {
256  pLayout->Resize( nBrowseWidth, true, true,
257  bLastGrf ? HTMLTABLE_RESIZE_NOW
258  : 500 );
259  }
260  }
261  }
262  }
263  }
264 
265  // SetTwipSize rescales an ImageMap if needed for which
266  // it requires the Frame Format
267  pGrfNd->SetTwipSize( rGrfSz );
268  }
269 
270  return bRet;
271 }
272 
273 bool SwBaseLink::SwapIn( bool bWaitForData, bool bNativFormat )
274 {
275  if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) ))
276  {
277  AddNextRef();
278  GetRealObject_();
279  ReleaseRef();
280  }
281 
282  bool bRes = false;
283 
284  if( GetObj() )
285  {
286  OUString aMimeType( SotExchange::GetFormatMimeType( GetContentType() ));
287  uno::Any aValue;
288  (void)GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData );
289 
290  if( bWaitForData && !GetObj() )
291  {
292  OSL_ENSURE( false, "The SvxFileObject was deleted in a GetData!" );
293  }
294  else
295  {
296  bRes = aValue.hasValue();
297  if ( bRes )
298  {
299  DataChanged( aMimeType, aValue );
300  }
301  }
302  }
303  else if( !IsSynchron() && bWaitForData )
304  {
305  SetSynchron( true );
306  bRes = Update();
307  SetSynchron( false );
308  }
309  else
310  bRes = Update();
311 
312  return bRes;
313 }
314 
316 {
317  if( m_pContentNode && !m_pContentNode->GetDoc()->IsInDtor() )
318  {
319  // Delete the connection
320  if( m_pContentNode->IsGrfNode() )
321  static_cast<SwGrfNode*>(m_pContentNode)->ReleaseLink();
322  }
323  SvBaseLink::Closed();
324 }
325 
327 {
328  if (m_pContentNode)
329  {
330  SwFrameFormat *const pFormat = m_pContentNode->GetFlyFormat();
331  if (pFormat)
332  {
333  const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
334  SwPosition const*const pAPos = rAnchor.GetContentAnchor();
335  if (pAPos &&
336  ((RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
337  (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
338  (RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId()) ||
339  (RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId())))
340  {
341  return &pAPos->nNode.GetNode();
342  }
343  return nullptr;
344  }
345  }
346 
347  OSL_ENSURE( false, "GetAnchor is not shadowed" );
348  return nullptr;
349 }
350 
351 bool SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const
352 {
353  tools::SvRef<SwServerObject> aRef( static_cast<SwServerObject*>(GetObj()) );
354  if( aRef.is() )
355  {
356  // As it's a ServerObject, we query all contained Links
357  // if we are contained in them. Else we have a recursion.
358  return aRef->IsLinkInServer( pChkLnk );
359  }
360  return false;
361 }
362 
364 {
365  // Not Graphic or OLE Links
366  // Fields or Sections have their own derivation!
367  return false;
368 }
369 
371 {
372 }
373 
374 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
bool is() const
bool hasValue()
Marks a position in the document model.
Definition: pam.hxx:35
bool IsLinkInServer(const SwBaseLink *) const
Definition: swserv.cxx:184
long AdjustWidth(long n)
long Height() const
SwNodeIndex nNode
Definition: pam.hxx:37
const OUString & GetName() const
sal_uIntPtr sal_uLong
bool IsFrameInPaint() const
Definition: ndgrf.hxx:104
Definition: doc.hxx:185
TElementType * Next()
Definition: calbck.hxx:376
SvMacroItemId
SwNode & GetNode() const
Definition: ndindex.hxx:118
long AdjustHeight(long n)
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
sal_uInt16 CallEvent(SvMacroItemId nEvent, const SwCallMouseEvent &rCallEvent, bool bChkPtr=false)
Definition: docbasic.cxx:130
#define RES_GRAPHIC_ARRIVED
Definition: hintids.hxx:298
const SwTable & GetTable() const
Definition: node.hxx:497
SotClipboardFormatId
static bool SetGrfFlySize(const Size &rGrfSz, SwGrfNode *pGrfNd, const Size &rOrigGrfSize)
Definition: swbaslnk.cxx:194
sal_uInt16 GetBrowseWidthByTable(const SwDoc &rDoc) const
Calculates available width by the table-frame or static GetBrowseWidth if no layout exists...
Definition: htmltbl.cxx:372
Style of a layout element.
Definition: frmfmt.hxx:57
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
void SetGraphic(const Graphic &rGraphic)
isolated only way to set GraphicObject to allow more actions when doing so
Definition: ndgrf.cxx:362
GraphicType GetType() const
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:323
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
TElementType * First()
Definition: calbck.hxx:345
FlyAnchors.
Definition: fmtanchr.hxx:34
bool IsChgTwipSize() const
Definition: ndgrf.hxx:98
SwDoc * GetDoc()
Definition: node.hxx:702
const char *const aMimeType[]
static void lcl_CallModify(SwGrfNode &rGrfNd, SfxPoolItem &rItem)
Definition: swbaslnk.cxx:64
void UnlockModify()
Definition: calbck.hxx:217
weld::Window * GetFrameWeld(SfxFrame *pFrame)
Definition: dialoghelp.cxx:20
void LockModify()
Definition: calbck.hxx:216
bool Resize(sal_uInt16 nAbsAvail, bool bRecalc=false, bool bForce=false, sal_uLong nDelay=0)
Recalculation of table widths for available width that has been passed.
Definition: htmltbl.cxx:1694
bool HasName() const
static OUString GetFormatMimeType(SotClipboardFormatId nFormat)
void SetTwipSize(const Size &rSz)
Definition: ndgrf.cxx:626
const GraphicObject & GetGrfObj(bool bWait=false) const
Definition: ndgrf.cxx:374
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:437
GraphicType GetType() const
virtual Size GetTwipSize() const override
Definition: ndgrf.cxx:428
void Set(SwCallEventObjectType eTyp, const SwFrameFormat *pFormat)
Definition: swevent.hxx:87
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:460
sal_uInt16 DecGrfsThatResize()
Definition: swtable.hxx:179
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
SwHTMLTableLayout * GetHTMLTableLayout()
Definition: swtable.hxx:174
SfxObjectShell * GetPersist() const
Definition: docnew.cxx:634
void SetSize(const Size &rSize)
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:351
sal_uInt16 CalcLineSpace(SvxBoxItemLine nLine, bool bEvenIfNoLine=false) const
bool IsInDtor() const
Definition: doc.hxx:398
SwGrfNode * GetGrfNode()
Definition: ndgrf.hxx:155
static bool GetGraphicFromAny(const OUString &rMimeType, const css::uno::Any &rValue, const OUString &rReferer, Graphic &rGrf, weld::Window *pParentWin)
static SotClipboardFormatId RegisterStatusInfoId()
void setWidth(long nWidth)
SwFrameFormat * GetFlyFormat() const
If node is in a fly return the respective format.
Definition: node.cxx:710
#define HTMLTABLE_RESIZE_NOW
Definition: htmltbl.hxx:36
const Size & GetSize() const
Size GetGraphicSizeTwip(const Graphic &rGraphic, vcl::RenderContext *pOutDev)
Definition: swtypes.cxx:49
Base class of the Writer document model elements.
Definition: node.hxx:79
void setHeight(long nHeight)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
SfxMedium * GetMedium() const