Files
libreoffice/sw/source/core/docnode/swbaslnk.cxx

536 lines
17 KiB
C++
Raw Normal View History

2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 23:08:29 +00:00
*
* Copyright 2008 by Sun Microsystems, Inc.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:08:29 +00:00
*
* $RCSfile: swbaslnk.cxx,v $
* $Revision: 1.17 $
2000-09-18 23:08:29 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
2000-09-18 23:08:29 +00:00
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
2000-09-18 23:08:29 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
2000-09-18 23:08:29 +00:00
#include <hintids.hxx>
#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>
#ifndef _OSL_THREAD_HXX_
#include <osl/thread.hxx>
#endif
#include <salhelper/condition.hxx>
#include <comphelper/mediadescriptor.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/lnkbase.hxx>
#include <sfx2/linkmgr.hxx>
2000-09-18 23:08:29 +00:00
#include <sfx2/objsh.hxx>
#include <svx/boxitem.hxx>
#ifndef _SVX_SVXIDS_HRC
#include <svx/svxids.hrc> // fuer die EventIds
#endif
#include <svx/linkmgr.hxx>
#include <svtools/soerr.hxx>
2000-09-18 23:08:29 +00:00
#include <fmtfsize.hxx>
#include <fmtanchr.hxx>
#include <frmatr.hxx>
#include <frmfmt.hxx>
#include <doc.hxx>
#include <pam.hxx>
#include <editsh.hxx>
#include <swtable.hxx>
#include <docary.hxx>
#include <swevent.hxx>
#include <swbaslnk.hxx>
#include <swserv.hxx>
#include <ndgrf.hxx>
#include <ndole.hxx>
#include <hints.hxx>
#include <tabfrm.hxx>
#include <cntfrm.hxx>
2000-09-18 23:08:29 +00:00
#include <htmltbl.hxx>
using namespace com::sun::star;
BOOL SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd );
2000-09-18 23:08:29 +00:00
TYPEINIT1( SwBaseLink, ::sfx2::SvBaseLink );
2000-09-18 23:08:29 +00:00
SV_IMPL_REF( SwServerObject )
2000-09-18 23:08:29 +00:00
void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem )
{
//JP 4.7.2001: call fist all not SwNoTxtFrames, then the SwNoTxtFrames.
// The reason is, that in the SwNoTxtFrames the Graphic
// after a Paint will be swapped out! So all other "behind"
// them havent't a loaded Graphic. - #86501#
rGrfNd.LockModify();
SwClientIter aIter( rGrfNd );
for( int n = 0; n < 2; ++n )
{
SwClient * pLast = aIter.GoStart();
if( pLast ) // konnte zum Anfang gesprungen werden ??
{
do {
if( (0 == n) ^ ( 0 != pLast->ISA( SwCntntFrm )) )
pLast->Modify( &rItem, &rItem );
} while( 0 != ( pLast = aIter++ ));
}
}
rGrfNd.UnlockModify();
}
void SwBaseLink::DataChanged( const String& rMimeType,
const uno::Any & rValue )
2000-09-18 23:08:29 +00:00
{
if( !pCntntNode )
{
ASSERT(!this, "DataChanged ohne ContentNode" );
return ;
}
SwDoc* pDoc = pCntntNode->GetDoc();
if( pDoc->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged )
{
bIgnoreDataChanged = FALSE;
return ;
}
ULONG nFmt = SotExchange::GetFormatIdFromMimeType( rMimeType );
2000-09-18 23:08:29 +00:00
if( pCntntNode->IsNoTxtNode() &&
nFmt == SvxLinkManager::RegisterStatusInfoId() )
2000-09-18 23:08:29 +00:00
{
// nur eine Statusaenderung - Events bedienen ?
::rtl::OUString sState;
if( rValue.hasValue() && ( rValue >>= sState ))
2000-09-18 23:08:29 +00:00
{
USHORT nEvent = 0;
switch( sState.toInt32() )
2000-09-18 23:08:29 +00:00
{
case STATE_LOAD_OK: nEvent = SVX_EVENT_IMAGE_LOAD; break;
case STATE_LOAD_ERROR: nEvent = SVX_EVENT_IMAGE_ERROR; break;
case STATE_LOAD_ABORT: nEvent = SVX_EVENT_IMAGE_ABORT; break;
}
SwFrmFmt* pFmt;
if( nEvent && 0 != ( pFmt = pCntntNode->GetFlyFmt() ))
{
SwCallMouseEvent aCallEvent;
aCallEvent.Set( EVENT_OBJECT_IMAGE, pFmt );
pDoc->CallEvent( nEvent, aCallEvent );
}
}
return; // das wars!
}
BOOL bUpdate = FALSE;
BOOL bGraphicArrived = FALSE;
BOOL bGraphicPieceArrived = FALSE;
BOOL bDontNotify = FALSE;
Size aGrfSz, aFrmFmtSz;
2000-09-18 23:08:29 +00:00
if( pCntntNode->IsGrfNode() )
{
GraphicObject& rGrfObj = ((SwGrfNode*)pCntntNode)->GetGrfObj();
bDontNotify = ((SwGrfNode*)pCntntNode)->IsFrameInPaint();
bGraphicArrived = GetObj()->IsDataComplete();
bGraphicPieceArrived = GetObj()->IsPending();
((SwGrfNode*)pCntntNode)->SetGrafikArrived( bGraphicArrived );
2000-09-18 23:08:29 +00:00
Graphic aGrf;
if( SvxLinkManager::GetGraphicFromAny( rMimeType, rValue, aGrf ) &&
( GRAPHIC_DEFAULT != aGrf.GetType() ||
GRAPHIC_DEFAULT != rGrfObj.GetType() ) )
2000-09-18 23:08:29 +00:00
{
aGrfSz = ::GetGraphicSizeTwip( aGrf, 0 );
if( static_cast< const SwGrfNode * >( pCntntNode )->IsChgTwipSizeFromPixel() )
{
const MapMode aMapTwip( MAP_TWIP );
aFrmFmtSz =
Application::GetDefaultDevice()->PixelToLogic(
aGrf.GetSizePixel(), aMapTwip );
}
else
{
aFrmFmtSz = aGrfSz;
}
Size aSz( ((SwGrfNode*)pCntntNode)->GetTwipSize() );
2000-09-18 23:08:29 +00:00
if( bGraphicPieceArrived && GRAPHIC_DEFAULT != aGrf.GetType() &&
( !aSz.Width() || !aSz.Height() ) )
2000-09-18 23:08:29 +00:00
{
// wenn nur ein Teil ankommt, aber die Groesse nicht
// gesetzt ist, dann muss "unten" der Teil von
// bGraphicArrived durchlaufen werden!
// (ansonten wird die Grafik in deft. Size gepaintet)
bGraphicArrived = TRUE;
bGraphicPieceArrived = FALSE;
2000-09-18 23:08:29 +00:00
}
rGrfObj.SetGraphic( aGrf, rGrfObj.GetLink() );
bUpdate = TRUE;
2000-09-18 23:08:29 +00:00
// Bug 33999: damit der Node den Transparent-Status
// richtig gesetzt hat, ohne auf die Grafik
// zugreifen zu muessen (sonst erfolgt ein SwapIn!).
if( bGraphicArrived )
{
// Bug #34735#: immer mit der korrekten Grafik-Size
// arbeiten
if( aGrfSz.Height() && aGrfSz.Width() &&
aSz.Height() && aSz.Width() &&
aGrfSz != aSz )
((SwGrfNode*)pCntntNode)->SetTwipSize( aGrfSz );
2000-09-18 23:08:29 +00:00
}
}
if ( bUpdate && !bGraphicArrived && !bGraphicPieceArrived )
((SwGrfNode*)pCntntNode)->SetTwipSize( Size(0,0) );
}
else if( pCntntNode->IsOLENode() )
bUpdate = TRUE;
ViewShell *pSh = 0;
SwEditShell* pESh = pDoc->GetEditShell( &pSh );
if ( bUpdate && bGraphicPieceArrived && !(bSwapIn || bDontNotify) )
{
//Hint ohne Actions verschicken, loest direktes Paint aus.
if ( (!pSh || !pSh->ActionPend()) && (!pESh || !pESh->ActionPend()) )
{
SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
pCntntNode->Modify( &aMsgHint, &aMsgHint );
bUpdate = FALSE;
}
}
static BOOL bInNotifyLinks = FALSE;
if( bUpdate && !bDontNotify && (!bSwapIn || bGraphicArrived) &&
!bInNotifyLinks)
{
BOOL bLockView = FALSE;
if( pSh )
{
bLockView = pSh->IsViewLocked();
pSh->LockView( TRUE );
}
if( pESh )
pESh->StartAllAction();
else if( pSh )
pSh->StartAction();
SwMsgPoolItem aMsgHint( static_cast<USHORT>(
bGraphicArrived ? RES_GRAPHIC_ARRIVED : RES_UPDATE_ATTR ) );
2000-09-18 23:08:29 +00:00
if ( bGraphicArrived )
{
//Alle benachrichtigen, die am gleichen Link horchen.
bInNotifyLinks = TRUE;
const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
2000-09-18 23:08:29 +00:00
for( USHORT n = rLnks.Count(); n; )
{
::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
2000-09-18 23:08:29 +00:00
if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() &&
pLnk->ISA( SwBaseLink ) && pLnk->GetObj() == GetObj() )
{
SwBaseLink* pBLink = (SwBaseLink*)pLnk;
SwGrfNode* pGrfNd = (SwGrfNode*)pBLink->pCntntNode;
if( pBLink != this &&
( !bSwapIn ||
GRAPHIC_DEFAULT == pGrfNd->GetGrfObj().GetType()))
{
pBLink->bIgnoreDataChanged = FALSE;
pBLink->DataChanged( rMimeType, rValue );
2000-09-18 23:08:29 +00:00
pBLink->bIgnoreDataChanged = TRUE;
pGrfNd->SetGrafikArrived( ((SwGrfNode*)pCntntNode)->
IsGrafikArrived() );
// Fly der Grafik anpassen !
if( !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
::lcl_CallModify( *pGrfNd, aMsgHint );
2000-09-18 23:08:29 +00:00
}
else if( pBLink == this &&
!::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
2000-09-18 23:08:29 +00:00
// Fly der Grafik anpassen !
::lcl_CallModify( *pGrfNd, aMsgHint );
2000-09-18 23:08:29 +00:00
}
}
bInNotifyLinks = FALSE;
}
else
{
pCntntNode->Modify( &aMsgHint, &aMsgHint );
}
if( pESh )
{
const BOOL bEndActionByVirDev = pESh->IsEndActionByVirDev();
pESh->SetEndActionByVirDev( TRUE );
pESh->EndAllAction();
pESh->SetEndActionByVirDev( bEndActionByVirDev );
}
else if( pSh )
pSh->EndAction();
if( pSh && !bLockView )
pSh->LockView( FALSE );
}
}
BOOL SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd )
2000-09-18 23:08:29 +00:00
{
BOOL bRet = FALSE;
ViewShell *pSh;
CurrShell *pCurr = 0;
if ( pGrfNd->GetDoc()->GetEditShell( &pSh ) )
pCurr = new CurrShell( pSh );
Size aSz = pGrfNd->GetTwipSize();
if ( !(aSz.Width() && aSz.Height()) &&
rGrfSz.Width() && rGrfSz.Height() )
{
SwFrmFmt* pFmt;
if( pGrfNd->IsChgTwipSize() &&
0 != (pFmt = pGrfNd->GetFlyFmt()) )
{
Size aCalcSz( aSz );
if ( !aSz.Height() && aSz.Width() )
//passende Hoehe ausrechnen.
aCalcSz.Height() = rFrmSz.Height() *
aSz.Width() / rFrmSz.Width();
2000-09-18 23:08:29 +00:00
else if ( !aSz.Width() && aSz.Height() )
//passende Breite ausrechnen
aCalcSz.Width() = rFrmSz.Width() *
aSz.Height() / rFrmSz.Height();
2000-09-18 23:08:29 +00:00
else
//Hoehe und Breite uebernehmen
aCalcSz = rFrmSz;
2000-09-18 23:08:29 +00:00
const SvxBoxItem &rBox = pFmt->GetBox();
aCalcSz.Width() += rBox.CalcLineSpace(BOX_LINE_LEFT) +
rBox.CalcLineSpace(BOX_LINE_RIGHT);
aCalcSz.Height()+= rBox.CalcLineSpace(BOX_LINE_TOP) +
rBox.CalcLineSpace(BOX_LINE_BOTTOM);
const SwFmtFrmSize& rOldAttr = pFmt->GetFrmSize();
if( rOldAttr.GetSize() != aCalcSz )
{
SwFmtFrmSize aAttr( rOldAttr );
aAttr.SetSize( aCalcSz );
pFmt->SetFmtAttr( aAttr );
2000-09-18 23:08:29 +00:00
bRet = TRUE;
}
if( !aSz.Width() )
{
// Wenn die Grafik in einer Tabelle verankert ist, muess
// die Tabellen-Spalten neu berechnet werden
const SwDoc *pDoc = pGrfNd->GetDoc();
const SwPosition* pAPos = pFmt->GetAnchor().GetCntntAnchor();
SwNode *pANd;
SwTableNode *pTblNd;
if( pAPos &&
0 != (pANd = pDoc->GetNodes()[pAPos->nNode]) &&
0 != (pTblNd = pANd->FindTableNode()) )
{
BOOL bLastGrf = !pTblNd->GetTable().DecGrfsThatResize();
SwHTMLTableLayout *pLayout =
pTblNd->GetTable().GetHTMLTableLayout();
if( pLayout )
{
USHORT nBrowseWidth =
pLayout->GetBrowseWidthByTable( *pDoc );
if( nBrowseWidth )
pLayout->Resize( nBrowseWidth, TRUE, TRUE,
bLastGrf ? HTMLTABLE_RESIZE_NOW
: 500 );
}
}
}
}
// SetTwipSize skaliert ggf. eine ImageMap neu und
// braucht dazu das Frame-Format
pGrfNd->SetTwipSize( rGrfSz );
}
delete pCurr;
return bRet;
}
BOOL SwBaseLink::SwapIn( BOOL bWaitForData, BOOL bNativFormat )
2000-09-18 23:08:29 +00:00
{
bSwapIn = TRUE;
BOOL bRes;
2000-09-18 23:08:29 +00:00
if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) ))
{
AddNextRef();
_GetRealObject();
ReleaseRef();
}
#if OSL_DEBUG_LEVEL > 1
2000-09-18 23:08:29 +00:00
{
String sGrfNm;
if(GetLinkManager())
GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
2000-09-18 23:08:29 +00:00
int x = 0;
++x;
2000-09-18 23:08:29 +00:00
}
#endif
// --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
// TestBalloonInputStream* pTBIS = 0;
// if(!m_xInputStreamToLoadFrom.is()) {
// if ( !pCntntNode->IsGrfNode() ||
// static_cast<SwGrfNode*>(pCntntNode)->GetGrfObj().GetType()
// != GRAPHIC_DEFAULT )
// {
// pTBIS = new TestBalloonInputStream();
// m_xInputStreamToLoadFrom = pTBIS;
// }
// }
// <--
2000-09-18 23:08:29 +00:00
if( GetObj() )
{
// --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
// GetObj()->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly);
// <--
String aMimeType( SotExchange::GetFormatMimeType( GetContentType() ));
//!! ??? what have we here to do ????
//!! if( bNativFormat )
//!! aData.SetAspect( aData.GetAspect() | ASPECT_ICON );
uno::Any aValue;
GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData );
2000-09-18 23:08:29 +00:00
if( bWaitForData && !GetObj() )
{
ASSERT( !this, "das SvxFileObject wurde in einem GetData geloescht!" );
bRes = FALSE;
}
else if( 0 != ( bRes = aValue.hasValue() ) )
2000-09-18 23:08:29 +00:00
{
//JP 14.04.99: Bug 64820 - das Flag muss beim SwapIn natuerlich
// zurueckgesetzt werden. Die Daten sollen ja neu
// uebernommen werden
bIgnoreDataChanged = FALSE;
DataChanged( aMimeType, aValue );
2000-09-18 23:08:29 +00:00
}
}
else if( !IsSynchron() && bWaitForData )
{
SetSynchron( TRUE );
bRes = Update();
SetSynchron( FALSE );
}
else
bRes = Update();
bSwapIn = FALSE;
// --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293
// if ( pTBIS && pTBIS->isTouched() )
// {
// // --> OD 2005-04-11 #i46300# - determine correct URL for the graphic
// String sGrfNm;
// GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
// (m_pReReadThread = new ReReadThread(
// this, sGrfNm, bWaitForData, bNativFormat))->create();
// // <--
// }
// <--
2000-09-18 23:08:29 +00:00
return bRes;
}
void SwBaseLink::Closed()
{
if( pCntntNode && !pCntntNode->GetDoc()->IsInDtor() )
{
// wir heben die Verbindung auf
if( pCntntNode->IsGrfNode() )
((SwGrfNode*)pCntntNode)->ReleaseLink();
}
SvBaseLink::Closed();
}
const SwNode* SwBaseLink::GetAnchor() const
{
SwFrmFmt* pFmt;
if( pCntntNode && 0 != ( pFmt = pCntntNode->GetFlyFmt()) )
{
const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
const SwPosition* pAPos;
if( 0 != ( pAPos = rAnchor.GetCntntAnchor()) &&
( FLY_IN_CNTNT == rAnchor.GetAnchorId() ||
FLY_AUTO_CNTNT == rAnchor.GetAnchorId() ||
FLY_AT_FLY == rAnchor.GetAnchorId() ||
FLY_AT_CNTNT == rAnchor.GetAnchorId() ))
return &pAPos->nNode.GetNode();
return 0;
}
ASSERT( !this, "GetAnchor nicht ueberlagert" );
return 0;
}
BOOL SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const
{
SwServerObjectRef aRef( (SwServerObject*)GetObj() );
2000-09-18 23:08:29 +00:00
if( aRef.Is() )
{
// es ist ein ServerObject, also frage nach allen darin
// befindlichen Links, ob wir darin enthalten sind. Ansonsten
// handelt es sich um eine Rekursion.
return aRef->IsLinkInServer( pChkLnk );
}
return FALSE;
}
BOOL SwBaseLink::IsInRange( ULONG, ULONG, xub_StrLen, xub_StrLen ) const
{
// Grafik oder OLE-Links nicht,
// Felder oder Sections haben eigene Ableitung!
return FALSE;
}
SwBaseLink::~SwBaseLink()
{
}