1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swbaslnk.cxx,v $
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>
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
52 #include <svx/linkmgr.hxx>
53 #include <svtools/soerr.hxx>
54 #include <fmtfsize.hxx>
55 #include <fmtanchr.hxx>
61 #include <swtable.hxx>
63 #include <swevent.hxx>
64 #include <swbaslnk.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#
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 ??
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
)
110 ASSERT(!this, "DataChanged ohne ContentNode" );
114 SwDoc
* pDoc
= pCntntNode
->GetDoc();
115 if( pDoc
->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged
)
117 bIgnoreDataChanged
= FALSE
;
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
))
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;
139 if( nEvent
&& 0 != ( pFmt
= pCntntNode
->GetFlyFmt() ))
141 SwCallMouseEvent aCallEvent
;
142 aCallEvent
.Set( EVENT_OBJECT_IMAGE
, pFmt
);
143 pDoc
->CallEvent( nEvent
, aCallEvent
);
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
);
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
);
175 Application::GetDefaultDevice()->PixelToLogic(
176 aGrf
.GetSizePixel(), aMapTwip
);
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() );
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
206 if( aGrfSz
.Height() && aGrfSz
.Width() &&
207 aSz
.Height() && aSz
.Width() &&
209 ((SwGrfNode
*)pCntntNode
)->SetTwipSize( aGrfSz
);
212 if ( bUpdate
&& !bGraphicArrived
&& !bGraphicPieceArrived
)
213 ((SwGrfNode
*)pCntntNode
)->SetTwipSize( Size(0,0) );
215 else if( pCntntNode
->IsOLENode() )
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
);
232 static BOOL bInNotifyLinks
= FALSE
;
233 if( bUpdate
&& !bDontNotify
&& (!bSwapIn
|| bGraphicArrived
) &&
236 BOOL bLockView
= FALSE
;
239 bLockView
= pSh
->IsViewLocked();
240 pSh
->LockView( TRUE
);
244 pESh
->StartAllAction();
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 &&
268 GRAPHIC_DEFAULT
== pGrfNd
->GetGrfObj().GetType()))
270 pBLink
->bIgnoreDataChanged
= FALSE
;
271 pBLink
->DataChanged( rMimeType
, rValue
);
272 pBLink
->bIgnoreDataChanged
= TRUE
;
274 pGrfNd
->SetGrafikArrived( ((SwGrfNode
*)pCntntNode
)->
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
;
292 pCntntNode
->Modify( &aMsgHint
, &aMsgHint
);
298 const BOOL bEndActionByVirDev
= pESh
->IsEndActionByVirDev();
299 pESh
->SetEndActionByVirDev( TRUE
);
300 pESh
->EndAllAction();
301 pESh
->SetEndActionByVirDev( bEndActionByVirDev
);
306 if( pSh
&& !bLockView
)
307 pSh
->LockView( FALSE
);
311 BOOL
SetGrfFlySize( const Size
& rGrfSz
, const Size
& rFrmSz
, SwGrfNode
* pGrfNd
)
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() )
324 if( pGrfNd
->IsChgTwipSize() &&
325 0 != (pFmt
= pGrfNd
->GetFlyFmt()) )
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();
337 //Hoehe und Breite uebernehmen
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
);
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();
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();
371 USHORT nBrowseWidth
=
372 pLayout
->GetBrowseWidthByTable( *pDoc
);
374 pLayout
->Resize( nBrowseWidth
, TRUE
, TRUE
,
375 bLastGrf
? HTMLTABLE_RESIZE_NOW
382 // SetTwipSize skaliert ggf. eine ImageMap neu und
383 // braucht dazu das Frame-Format
384 pGrfNd
->SetTwipSize( rGrfSz
);
393 BOOL
SwBaseLink::SwapIn( BOOL bWaitForData
, BOOL bNativFormat
)
399 if( !GetObj() && ( bNativFormat
|| ( !IsSynchron() && bWaitForData
) ))
406 #if OSL_DEBUG_LEVEL > 1
410 GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm
, 0, 0 );
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 )
423 // pTBIS = new TestBalloonInputStream();
424 // m_xInputStreamToLoadFrom = pTBIS;
431 // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
432 // GetObj()->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly);
434 String
aMimeType( SotExchange::GetFormatMimeType( GetContentType() ));
436 //!! ??? what have we here to do ????
437 //!! if( bNativFormat )
438 //!! aData.SetAspect( aData.GetAspect() | ASPECT_ICON );
441 GetObj()->GetData( aValue
, aMimeType
, !IsSynchron() && bWaitForData
);
443 if( bWaitForData
&& !GetObj() )
445 ASSERT( !this, "das SvxFileObject wurde in einem GetData geloescht!" );
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
)
461 SetSynchron( FALSE
);
468 // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
469 // if ( pTBIS && pTBIS->isTouched() )
471 // // --> OD 2005-04-11 #i46300# - determine correct URL for the graphic
473 // GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
474 // (m_pReReadThread = new ReReadThread(
475 // this, sGrfNm, bWaitForData, bNativFormat))->create();
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
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();
509 ASSERT( !this, "GetAnchor nicht ueberlagert" );
513 BOOL
SwBaseLink::IsRecursion( const SwBaseLink
* pChkLnk
) const
515 SwServerObjectRef
aRef( (SwServerObject
*)GetObj() );
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
);
526 BOOL
SwBaseLink::IsInRange( ULONG
, ULONG
, xub_StrLen
, xub_StrLen
) const
528 // Grafik oder OLE-Links nicht,
529 // Felder oder Sections haben eigene Ableitung!
533 SwBaseLink::~SwBaseLink()