Update ooo320-m1
[ooovba.git] / sw / source / core / docnode / swbaslnk.cxx
blob01711b931dfadb63ee046d2eb9f595e1aebb6162
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swbaslnk.cxx,v $
10 * $Revision: 1.17 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/outdev.hxx>
39 #ifndef _OSL_THREAD_HXX_
40 #include <osl/thread.hxx>
41 #endif
42 #include <salhelper/condition.hxx>
43 #include <comphelper/mediadescriptor.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <sfx2/lnkbase.hxx>
46 #include <sfx2/linkmgr.hxx>
47 #include <sfx2/objsh.hxx>
48 #include <svx/boxitem.hxx>
49 #ifndef _SVX_SVXIDS_HRC
50 #include <svx/svxids.hrc> // fuer die EventIds
51 #endif
52 #include <svx/linkmgr.hxx>
53 #include <svtools/soerr.hxx>
54 #include <fmtfsize.hxx>
55 #include <fmtanchr.hxx>
56 #include <frmatr.hxx>
57 #include <frmfmt.hxx>
58 #include <doc.hxx>
59 #include <pam.hxx>
60 #include <editsh.hxx>
61 #include <swtable.hxx>
62 #include <docary.hxx>
63 #include <swevent.hxx>
64 #include <swbaslnk.hxx>
65 #include <swserv.hxx>
66 #include <ndgrf.hxx>
67 #include <ndole.hxx>
68 #include <hints.hxx>
69 #include <tabfrm.hxx>
70 #include <cntfrm.hxx>
71 #include <htmltbl.hxx>
73 using namespace com::sun::star;
75 BOOL SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd );
77 TYPEINIT1( SwBaseLink, ::sfx2::SvBaseLink );
79 SV_IMPL_REF( SwServerObject )
81 void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem )
83 //JP 4.7.2001: call fist all not SwNoTxtFrames, then the SwNoTxtFrames.
84 // The reason is, that in the SwNoTxtFrames the Graphic
85 // after a Paint will be swapped out! So all other "behind"
86 // them havent't a loaded Graphic. - #86501#
87 rGrfNd.LockModify();
89 SwClientIter aIter( rGrfNd );
90 for( int n = 0; n < 2; ++n )
92 SwClient * pLast = aIter.GoStart();
93 if( pLast ) // konnte zum Anfang gesprungen werden ??
95 do {
96 if( (0 == n) ^ ( 0 != pLast->ISA( SwCntntFrm )) )
97 pLast->Modify( &rItem, &rItem );
98 } while( 0 != ( pLast = aIter++ ));
101 rGrfNd.UnlockModify();
105 void SwBaseLink::DataChanged( const String& rMimeType,
106 const uno::Any & rValue )
108 if( !pCntntNode )
110 ASSERT(!this, "DataChanged ohne ContentNode" );
111 return ;
114 SwDoc* pDoc = pCntntNode->GetDoc();
115 if( pDoc->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged )
117 bIgnoreDataChanged = FALSE;
118 return ;
121 ULONG nFmt = SotExchange::GetFormatIdFromMimeType( rMimeType );
123 if( pCntntNode->IsNoTxtNode() &&
124 nFmt == SvxLinkManager::RegisterStatusInfoId() )
126 // nur eine Statusaenderung - Events bedienen ?
127 ::rtl::OUString sState;
128 if( rValue.hasValue() && ( rValue >>= sState ))
130 USHORT nEvent = 0;
131 switch( sState.toInt32() )
133 case STATE_LOAD_OK: nEvent = SVX_EVENT_IMAGE_LOAD; break;
134 case STATE_LOAD_ERROR: nEvent = SVX_EVENT_IMAGE_ERROR; break;
135 case STATE_LOAD_ABORT: nEvent = SVX_EVENT_IMAGE_ABORT; break;
138 SwFrmFmt* pFmt;
139 if( nEvent && 0 != ( pFmt = pCntntNode->GetFlyFmt() ))
141 SwCallMouseEvent aCallEvent;
142 aCallEvent.Set( EVENT_OBJECT_IMAGE, pFmt );
143 pDoc->CallEvent( nEvent, aCallEvent );
146 return; // das wars!
149 BOOL bUpdate = FALSE;
150 BOOL bGraphicArrived = FALSE;
151 BOOL bGraphicPieceArrived = FALSE;
152 BOOL bDontNotify = FALSE;
153 Size aGrfSz, aFrmFmtSz;
155 if( pCntntNode->IsGrfNode() )
157 GraphicObject& rGrfObj = ((SwGrfNode*)pCntntNode)->GetGrfObj();
159 bDontNotify = ((SwGrfNode*)pCntntNode)->IsFrameInPaint();
161 bGraphicArrived = GetObj()->IsDataComplete();
162 bGraphicPieceArrived = GetObj()->IsPending();
163 ((SwGrfNode*)pCntntNode)->SetGrafikArrived( bGraphicArrived );
165 Graphic aGrf;
166 if( SvxLinkManager::GetGraphicFromAny( rMimeType, rValue, aGrf ) &&
167 ( GRAPHIC_DEFAULT != aGrf.GetType() ||
168 GRAPHIC_DEFAULT != rGrfObj.GetType() ) )
170 aGrfSz = ::GetGraphicSizeTwip( aGrf, 0 );
171 if( static_cast< const SwGrfNode * >( pCntntNode )->IsChgTwipSizeFromPixel() )
173 const MapMode aMapTwip( MAP_TWIP );
174 aFrmFmtSz =
175 Application::GetDefaultDevice()->PixelToLogic(
176 aGrf.GetSizePixel(), aMapTwip );
179 else
181 aFrmFmtSz = aGrfSz;
183 Size aSz( ((SwGrfNode*)pCntntNode)->GetTwipSize() );
185 if( bGraphicPieceArrived && GRAPHIC_DEFAULT != aGrf.GetType() &&
186 ( !aSz.Width() || !aSz.Height() ) )
188 // wenn nur ein Teil ankommt, aber die Groesse nicht
189 // gesetzt ist, dann muss "unten" der Teil von
190 // bGraphicArrived durchlaufen werden!
191 // (ansonten wird die Grafik in deft. Size gepaintet)
192 bGraphicArrived = TRUE;
193 bGraphicPieceArrived = FALSE;
196 rGrfObj.SetGraphic( aGrf, rGrfObj.GetLink() );
197 bUpdate = TRUE;
199 // Bug 33999: damit der Node den Transparent-Status
200 // richtig gesetzt hat, ohne auf die Grafik
201 // zugreifen zu muessen (sonst erfolgt ein SwapIn!).
202 if( bGraphicArrived )
204 // Bug #34735#: immer mit der korrekten Grafik-Size
205 // arbeiten
206 if( aGrfSz.Height() && aGrfSz.Width() &&
207 aSz.Height() && aSz.Width() &&
208 aGrfSz != aSz )
209 ((SwGrfNode*)pCntntNode)->SetTwipSize( aGrfSz );
212 if ( bUpdate && !bGraphicArrived && !bGraphicPieceArrived )
213 ((SwGrfNode*)pCntntNode)->SetTwipSize( Size(0,0) );
215 else if( pCntntNode->IsOLENode() )
216 bUpdate = TRUE;
218 ViewShell *pSh = 0;
219 SwEditShell* pESh = pDoc->GetEditShell( &pSh );
221 if ( bUpdate && bGraphicPieceArrived && !(bSwapIn || bDontNotify) )
223 //Hint ohne Actions verschicken, loest direktes Paint aus.
224 if ( (!pSh || !pSh->ActionPend()) && (!pESh || !pESh->ActionPend()) )
226 SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
227 pCntntNode->Modify( &aMsgHint, &aMsgHint );
228 bUpdate = FALSE;
232 static BOOL bInNotifyLinks = FALSE;
233 if( bUpdate && !bDontNotify && (!bSwapIn || bGraphicArrived) &&
234 !bInNotifyLinks)
236 BOOL bLockView = FALSE;
237 if( pSh )
239 bLockView = pSh->IsViewLocked();
240 pSh->LockView( TRUE );
243 if( pESh )
244 pESh->StartAllAction();
245 else if( pSh )
246 pSh->StartAction();
248 SwMsgPoolItem aMsgHint( static_cast<USHORT>(
249 bGraphicArrived ? RES_GRAPHIC_ARRIVED : RES_UPDATE_ATTR ) );
251 if ( bGraphicArrived )
253 //Alle benachrichtigen, die am gleichen Link horchen.
254 bInNotifyLinks = TRUE;
256 const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
257 for( USHORT n = rLnks.Count(); n; )
259 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
260 if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() &&
261 pLnk->ISA( SwBaseLink ) && pLnk->GetObj() == GetObj() )
263 SwBaseLink* pBLink = (SwBaseLink*)pLnk;
264 SwGrfNode* pGrfNd = (SwGrfNode*)pBLink->pCntntNode;
266 if( pBLink != this &&
267 ( !bSwapIn ||
268 GRAPHIC_DEFAULT == pGrfNd->GetGrfObj().GetType()))
270 pBLink->bIgnoreDataChanged = FALSE;
271 pBLink->DataChanged( rMimeType, rValue );
272 pBLink->bIgnoreDataChanged = TRUE;
274 pGrfNd->SetGrafikArrived( ((SwGrfNode*)pCntntNode)->
275 IsGrafikArrived() );
277 // Fly der Grafik anpassen !
278 if( !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
279 ::lcl_CallModify( *pGrfNd, aMsgHint );
281 else if( pBLink == this &&
282 !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
283 // Fly der Grafik anpassen !
284 ::lcl_CallModify( *pGrfNd, aMsgHint );
288 bInNotifyLinks = FALSE;
290 else
292 pCntntNode->Modify( &aMsgHint, &aMsgHint );
296 if( pESh )
298 const BOOL bEndActionByVirDev = pESh->IsEndActionByVirDev();
299 pESh->SetEndActionByVirDev( TRUE );
300 pESh->EndAllAction();
301 pESh->SetEndActionByVirDev( bEndActionByVirDev );
303 else if( pSh )
304 pSh->EndAction();
306 if( pSh && !bLockView )
307 pSh->LockView( FALSE );
311 BOOL SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd )
313 BOOL bRet = FALSE;
314 ViewShell *pSh;
315 CurrShell *pCurr = 0;
316 if ( pGrfNd->GetDoc()->GetEditShell( &pSh ) )
317 pCurr = new CurrShell( pSh );
319 Size aSz = pGrfNd->GetTwipSize();
320 if ( !(aSz.Width() && aSz.Height()) &&
321 rGrfSz.Width() && rGrfSz.Height() )
323 SwFrmFmt* pFmt;
324 if( pGrfNd->IsChgTwipSize() &&
325 0 != (pFmt = pGrfNd->GetFlyFmt()) )
327 Size aCalcSz( aSz );
328 if ( !aSz.Height() && aSz.Width() )
329 //passende Hoehe ausrechnen.
330 aCalcSz.Height() = rFrmSz.Height() *
331 aSz.Width() / rFrmSz.Width();
332 else if ( !aSz.Width() && aSz.Height() )
333 //passende Breite ausrechnen
334 aCalcSz.Width() = rFrmSz.Width() *
335 aSz.Height() / rFrmSz.Height();
336 else
337 //Hoehe und Breite uebernehmen
338 aCalcSz = rFrmSz;
340 const SvxBoxItem &rBox = pFmt->GetBox();
341 aCalcSz.Width() += rBox.CalcLineSpace(BOX_LINE_LEFT) +
342 rBox.CalcLineSpace(BOX_LINE_RIGHT);
343 aCalcSz.Height()+= rBox.CalcLineSpace(BOX_LINE_TOP) +
344 rBox.CalcLineSpace(BOX_LINE_BOTTOM);
345 const SwFmtFrmSize& rOldAttr = pFmt->GetFrmSize();
346 if( rOldAttr.GetSize() != aCalcSz )
348 SwFmtFrmSize aAttr( rOldAttr );
349 aAttr.SetSize( aCalcSz );
350 pFmt->SetFmtAttr( aAttr );
351 bRet = TRUE;
354 if( !aSz.Width() )
356 // Wenn die Grafik in einer Tabelle verankert ist, muess
357 // die Tabellen-Spalten neu berechnet werden
358 const SwDoc *pDoc = pGrfNd->GetDoc();
359 const SwPosition* pAPos = pFmt->GetAnchor().GetCntntAnchor();
360 SwNode *pANd;
361 SwTableNode *pTblNd;
362 if( pAPos &&
363 0 != (pANd = pDoc->GetNodes()[pAPos->nNode]) &&
364 0 != (pTblNd = pANd->FindTableNode()) )
366 BOOL bLastGrf = !pTblNd->GetTable().DecGrfsThatResize();
367 SwHTMLTableLayout *pLayout =
368 pTblNd->GetTable().GetHTMLTableLayout();
369 if( pLayout )
371 USHORT nBrowseWidth =
372 pLayout->GetBrowseWidthByTable( *pDoc );
373 if( nBrowseWidth )
374 pLayout->Resize( nBrowseWidth, TRUE, TRUE,
375 bLastGrf ? HTMLTABLE_RESIZE_NOW
376 : 500 );
382 // SetTwipSize skaliert ggf. eine ImageMap neu und
383 // braucht dazu das Frame-Format
384 pGrfNd->SetTwipSize( rGrfSz );
387 delete pCurr;
389 return bRet;
393 BOOL SwBaseLink::SwapIn( BOOL bWaitForData, BOOL bNativFormat )
395 bSwapIn = TRUE;
397 BOOL bRes;
399 if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) ))
401 AddNextRef();
402 _GetRealObject();
403 ReleaseRef();
406 #if OSL_DEBUG_LEVEL > 1
408 String sGrfNm;
409 if(GetLinkManager())
410 GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
411 int x = 0;
412 ++x;
414 #endif
416 // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
417 // TestBalloonInputStream* pTBIS = 0;
418 // if(!m_xInputStreamToLoadFrom.is()) {
419 // if ( !pCntntNode->IsGrfNode() ||
420 // static_cast<SwGrfNode*>(pCntntNode)->GetGrfObj().GetType()
421 // != GRAPHIC_DEFAULT )
422 // {
423 // pTBIS = new TestBalloonInputStream();
424 // m_xInputStreamToLoadFrom = pTBIS;
425 // }
426 // }
427 // <--
429 if( GetObj() )
431 // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
432 // GetObj()->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly);
433 // <--
434 String aMimeType( SotExchange::GetFormatMimeType( GetContentType() ));
436 //!! ??? what have we here to do ????
437 //!! if( bNativFormat )
438 //!! aData.SetAspect( aData.GetAspect() | ASPECT_ICON );
440 uno::Any aValue;
441 GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData );
443 if( bWaitForData && !GetObj() )
445 ASSERT( !this, "das SvxFileObject wurde in einem GetData geloescht!" );
446 bRes = FALSE;
448 else if( 0 != ( bRes = aValue.hasValue() ) )
450 //JP 14.04.99: Bug 64820 - das Flag muss beim SwapIn natuerlich
451 // zurueckgesetzt werden. Die Daten sollen ja neu
452 // uebernommen werden
453 bIgnoreDataChanged = FALSE;
454 DataChanged( aMimeType, aValue );
457 else if( !IsSynchron() && bWaitForData )
459 SetSynchron( TRUE );
460 bRes = Update();
461 SetSynchron( FALSE );
463 else
464 bRes = Update();
466 bSwapIn = FALSE;
468 // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
469 // if ( pTBIS && pTBIS->isTouched() )
470 // {
471 // // --> OD 2005-04-11 #i46300# - determine correct URL for the graphic
472 // String sGrfNm;
473 // GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
474 // (m_pReReadThread = new ReReadThread(
475 // this, sGrfNm, bWaitForData, bNativFormat))->create();
476 // // <--
477 // }
478 // <--
479 return bRes;
482 void SwBaseLink::Closed()
484 if( pCntntNode && !pCntntNode->GetDoc()->IsInDtor() )
486 // wir heben die Verbindung auf
487 if( pCntntNode->IsGrfNode() )
488 ((SwGrfNode*)pCntntNode)->ReleaseLink();
490 SvBaseLink::Closed();
493 const SwNode* SwBaseLink::GetAnchor() const
495 SwFrmFmt* pFmt;
496 if( pCntntNode && 0 != ( pFmt = pCntntNode->GetFlyFmt()) )
498 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
499 const SwPosition* pAPos;
500 if( 0 != ( pAPos = rAnchor.GetCntntAnchor()) &&
501 ( FLY_IN_CNTNT == rAnchor.GetAnchorId() ||
502 FLY_AUTO_CNTNT == rAnchor.GetAnchorId() ||
503 FLY_AT_FLY == rAnchor.GetAnchorId() ||
504 FLY_AT_CNTNT == rAnchor.GetAnchorId() ))
505 return &pAPos->nNode.GetNode();
506 return 0;
509 ASSERT( !this, "GetAnchor nicht ueberlagert" );
510 return 0;
513 BOOL SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const
515 SwServerObjectRef aRef( (SwServerObject*)GetObj() );
516 if( aRef.Is() )
518 // es ist ein ServerObject, also frage nach allen darin
519 // befindlichen Links, ob wir darin enthalten sind. Ansonsten
520 // handelt es sich um eine Rekursion.
521 return aRef->IsLinkInServer( pChkLnk );
523 return FALSE;
526 BOOL SwBaseLink::IsInRange( ULONG, ULONG, xub_StrLen, xub_StrLen ) const
528 // Grafik oder OLE-Links nicht,
529 // Felder oder Sections haben eigene Ableitung!
530 return FALSE;
533 SwBaseLink::~SwBaseLink()