LCOV - code coverage report
Current view: top level - sw/source/core/docnode - swbaslnk.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 124 218 56.9 %
Date: 2014-04-11 Functions: 9 15 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <svtools/soerr.hxx>
      33             : #include <fmtfsize.hxx>
      34             : #include <fmtanchr.hxx>
      35             : #include <frmatr.hxx>
      36             : #include <frmfmt.hxx>
      37             : #include <doc.hxx>
      38             : #include <pam.hxx>
      39             : #include <editsh.hxx>
      40             : #include <swtable.hxx>
      41             : #include <docary.hxx>
      42             : #include <swevent.hxx>
      43             : #include <swbaslnk.hxx>
      44             : #include <swserv.hxx>
      45             : #include <ndgrf.hxx>
      46             : #include <ndole.hxx>
      47             : #include <hints.hxx>
      48             : #include <tabfrm.hxx>
      49             : #include <cntfrm.hxx>
      50             : #include <htmltbl.hxx>
      51             : 
      52             : using namespace com::sun::star;
      53             : 
      54             : static bool SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd );
      55             : 
      56          24 : TYPEINIT1( SwBaseLink, ::sfx2::SvBaseLink );
      57             : 
      58           6 : static void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem )
      59             : {
      60             :     //call fist all not SwNoTxtFrames, then the SwNoTxtFrames.
      61             :     //              The reason is, that in the SwNoTxtFrames the Graphic
      62             :     //              after a Paint will be swapped out! So all other "behind"
      63             :     //              them havent't a loaded Graphic.
      64           6 :     rGrfNd.LockModify();
      65             : 
      66           6 :     SwClientIter aIter( rGrfNd );   // TODO
      67          18 :     for( int n = 0; n < 2; ++n )
      68             :     {
      69          12 :         SwClient * pLast = aIter.GoStart();
      70          12 :         if( pLast )     // Were we able to jump to the beginning?
      71             :         {
      72          12 :             do {
      73          12 :                 if( (0 == n) != pLast->ISA( SwCntntFrm ) )
      74           6 :                     pLast->ModifyNotification( &rItem, &rItem );
      75             :             } while( 0 != ( pLast = ++aIter ));
      76             :         }
      77             :     }
      78           6 :     rGrfNd.UnlockModify();
      79           6 : }
      80             : 
      81          20 : ::sfx2::SvBaseLink::UpdateResult SwBaseLink::DataChanged(
      82             :     const OUString& rMimeType, const uno::Any & rValue )
      83             : {
      84          20 :     if( !pCntntNode )
      85             :     {
      86             :         OSL_ENSURE(!this, "DataChanged without ContentNode" );
      87           0 :         return ERROR_GENERAL;
      88             :     }
      89             : 
      90          20 :     SwDoc* pDoc = pCntntNode->GetDoc();
      91          20 :     if( pDoc->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged )
      92             :     {
      93           0 :         bIgnoreDataChanged = false;
      94           0 :         return SUCCESS;
      95             :     }
      96             : 
      97          20 :     sal_uLong nFmt = SotExchange::GetFormatIdFromMimeType( rMimeType );
      98             : 
      99          40 :     if( pCntntNode->IsNoTxtNode() &&
     100          20 :         nFmt == sfx2::LinkManager::RegisterStatusInfoId() )
     101             :     {
     102             :         // Only a status change - serve Events?
     103           6 :         OUString sState;
     104           6 :         if( rValue.hasValue() && ( rValue >>= sState ))
     105             :         {
     106           6 :             sal_uInt16 nEvent = 0;
     107           6 :             switch( sState.toInt32() )
     108             :             {
     109           6 :             case sfx2::LinkManager::STATE_LOAD_OK:      nEvent = SVX_EVENT_IMAGE_LOAD;  break;
     110           0 :             case sfx2::LinkManager::STATE_LOAD_ERROR:   nEvent = SVX_EVENT_IMAGE_ERROR; break;
     111           0 :             case sfx2::LinkManager::STATE_LOAD_ABORT:   nEvent = SVX_EVENT_IMAGE_ABORT; break;
     112             :             }
     113             : 
     114             :             SwFrmFmt* pFmt;
     115           6 :             if( nEvent && 0 != ( pFmt = pCntntNode->GetFlyFmt() ))
     116             :             {
     117           6 :                 SwCallMouseEvent aCallEvent;
     118           6 :                 aCallEvent.Set( EVENT_OBJECT_IMAGE, pFmt );
     119           6 :                 pDoc->CallEvent( nEvent, aCallEvent );
     120             :             }
     121             :         }
     122           6 :         return SUCCESS; // That's it!
     123             :     }
     124             : 
     125          14 :     bool bUpdate = false;
     126          14 :     bool bGraphicArrived = false;
     127          14 :     bool bGraphicPieceArrived = false;
     128          14 :     bool bDontNotify = false;
     129          14 :     Size aGrfSz, aFrmFmtSz;
     130             : 
     131          14 :     if( pCntntNode->IsGrfNode() )
     132             :     {
     133          14 :         SwGrfNode* pSwGrfNode = dynamic_cast< SwGrfNode* >(pCntntNode);
     134             :         OSL_ENSURE(pSwGrfNode, "Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)");
     135          14 :         const GraphicObject& rGrfObj = pSwGrfNode->GetGrfObj();
     136             : 
     137          14 :         bDontNotify = pSwGrfNode->IsFrameInPaint();
     138             : 
     139          14 :         bGraphicArrived = GetObj()->IsDataComplete();
     140          14 :         bGraphicPieceArrived = GetObj()->IsPending();
     141          14 :         pSwGrfNode->SetGraphicArrived( bGraphicArrived );
     142             : 
     143          14 :         Graphic aGrf;
     144          42 :         if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGrf ) &&
     145          14 :             ( GRAPHIC_DEFAULT != aGrf.GetType() ||
     146           0 :               GRAPHIC_DEFAULT != rGrfObj.GetType() ) )
     147             :         {
     148          14 :             aGrfSz = ::GetGraphicSizeTwip( aGrf, 0 );
     149          14 :             if( pSwGrfNode->IsChgTwipSizeFromPixel() )
     150             :             {
     151           0 :                 const MapMode aMapTwip( MAP_TWIP );
     152             :                 aFrmFmtSz =
     153             :                     Application::GetDefaultDevice()->PixelToLogic(
     154           0 :                         aGrf.GetSizePixel(), aMapTwip );
     155             :             }
     156             :             else
     157             :             {
     158          14 :                 aFrmFmtSz = aGrfSz;
     159             :             }
     160          14 :             Size aSz( pSwGrfNode->GetTwipSize() );
     161             : 
     162          26 :             if( bGraphicPieceArrived && GRAPHIC_DEFAULT != aGrf.GetType() &&
     163           6 :                 ( !aSz.Width() || !aSz.Height() ) )
     164             :             {
     165             :                 // If only a part arrives, but the size is not set
     166             :                 // we need to go through bGraphicArrived down there.
     167             :                 // Or else the graphic is painted at its definitive size
     168           6 :                 bGraphicArrived = true;
     169           6 :                 bGraphicPieceArrived = false;
     170             :             }
     171             : 
     172          14 :             pSwGrfNode->SetGraphic(aGrf, rGrfObj.GetLink());
     173          14 :             bUpdate = true;
     174             : 
     175             :             // In order for the Node to have the right transparency status
     176             :             // without having to access the graphic.
     177             :             // Or else we cause a SwapIn.
     178          14 :             if( bGraphicArrived )
     179             :             {
     180             :                 // Always use the correct graphic size
     181          12 :                 if( aGrfSz.Height() && aGrfSz.Width() &&
     182           6 :                     aSz.Height() && aSz.Width() &&
     183           0 :                     aGrfSz != aSz )
     184           0 :                     pSwGrfNode->SetTwipSize( aGrfSz );
     185             :             }
     186             :         }
     187          14 :         if ( bUpdate && !bGraphicArrived && !bGraphicPieceArrived )
     188           8 :             pSwGrfNode->SetTwipSize( Size(0,0) );
     189             :     }
     190           0 :     else if( pCntntNode->IsOLENode() )
     191           0 :         bUpdate = true;
     192             : 
     193          14 :     SwViewShell *pSh = 0;
     194          14 :     SwEditShell* pESh = pDoc->GetEditShell( &pSh );
     195             : 
     196          14 :     if ( bUpdate && bGraphicPieceArrived && !(bSwapIn || bDontNotify) )
     197             :     {
     198             :         // Send hint without Actions; triggers direct paint
     199           0 :         if ( (!pSh || !pSh->ActionPend()) && (!pESh || !pESh->ActionPend()) )
     200             :         {
     201           0 :             SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
     202           0 :             pCntntNode->ModifyNotification( &aMsgHint, &aMsgHint );
     203           0 :             bUpdate = false;
     204             :         }
     205             :     }
     206             : 
     207             :     static bool bInNotifyLinks = false;
     208          24 :     if( bUpdate && !bDontNotify && (!bSwapIn || bGraphicArrived) &&
     209          10 :         !bInNotifyLinks)
     210             :     {
     211          10 :         bool bLockView = false;
     212          10 :         if( pSh )
     213             :         {
     214          10 :             bLockView = pSh->IsViewLocked();
     215          10 :             pSh->LockView( true );
     216             :         }
     217             : 
     218          10 :         if( pESh )
     219          10 :             pESh->StartAllAction();
     220           0 :         else if( pSh )
     221           0 :             pSh->StartAction();
     222             : 
     223             :         SwMsgPoolItem aMsgHint( static_cast<sal_uInt16>(
     224          10 :             bGraphicArrived ? RES_GRAPHIC_ARRIVED : RES_UPDATE_ATTR ) );
     225             : 
     226          10 :         if ( bGraphicArrived )
     227             :         {
     228             :             // Notify all who are listening at the same link
     229           6 :             bInNotifyLinks = true;
     230             : 
     231           6 :             const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
     232          18 :             for( sal_uInt16 n = rLnks.size(); n; )
     233             :             {
     234           6 :                 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
     235          18 :                 if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() &&
     236          18 :                     pLnk->ISA( SwBaseLink ) && pLnk->GetObj() == GetObj() )
     237             :                 {
     238           6 :                     SwBaseLink* pBLink = (SwBaseLink*)pLnk;
     239           6 :                     SwGrfNode* pGrfNd = (SwGrfNode*)pBLink->pCntntNode;
     240             : 
     241           6 :                     if( pBLink != this &&
     242           0 :                         ( !bSwapIn ||
     243           0 :                             GRAPHIC_DEFAULT == pGrfNd->GetGrfObj().GetType()))
     244             :                     {
     245           0 :                         pBLink->bIgnoreDataChanged = false;
     246           0 :                         pBLink->DataChanged( rMimeType, rValue );
     247           0 :                         pBLink->bIgnoreDataChanged = true;
     248             : 
     249             :                         pGrfNd->SetGraphicArrived( ((SwGrfNode*)pCntntNode)->
     250           0 :                                                     IsGraphicArrived() );
     251             : 
     252             :                         // Adjust the Fly's graphic
     253           0 :                         if( !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
     254           0 :                             ::lcl_CallModify( *pGrfNd, aMsgHint );
     255             :                     }
     256          12 :                     else if( pBLink == this &&
     257           6 :                             !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
     258             :                         // Adjust the Fly's graphic
     259           6 :                         ::lcl_CallModify( *pGrfNd, aMsgHint );
     260             :                 }
     261             :             }
     262             : 
     263           6 :             bInNotifyLinks = false;
     264             :         }
     265             :         else
     266             :         {
     267           4 :             pCntntNode->ModifyNotification( &aMsgHint, &aMsgHint );
     268             :         }
     269             : 
     270          10 :         if( pESh )
     271             :         {
     272          10 :             const bool bEndActionByVirDev = pESh->IsEndActionByVirDev();
     273          10 :             pESh->SetEndActionByVirDev( sal_True );
     274          10 :             pESh->EndAllAction();
     275          10 :             pESh->SetEndActionByVirDev( bEndActionByVirDev );
     276             :         }
     277           0 :         else if( pSh )
     278           0 :             pSh->EndAction();
     279             : 
     280          10 :         if( pSh && !bLockView )
     281          10 :             pSh->LockView( false );
     282             :     }
     283             : 
     284          14 :     return SUCCESS;
     285             : }
     286             : 
     287           6 : static bool SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd )
     288             : {
     289           6 :     bool bRet = false;
     290             :     SwViewShell *pSh;
     291           6 :     CurrShell *pCurr = 0;
     292           6 :     if ( pGrfNd->GetDoc()->GetEditShell( &pSh ) )
     293           6 :         pCurr = new CurrShell( pSh );
     294             : 
     295           6 :     Size aSz = pGrfNd->GetTwipSize();
     296          18 :     if ( !(aSz.Width() && aSz.Height()) &&
     297          12 :             rGrfSz.Width() && rGrfSz.Height() )
     298             :     {
     299             :         SwFrmFmt* pFmt;
     300           0 :         if( pGrfNd->IsChgTwipSize() &&
     301           0 :             0 != (pFmt = pGrfNd->GetFlyFmt()) )
     302             :         {
     303           0 :             Size aCalcSz( aSz );
     304           0 :             if ( !aSz.Height() && aSz.Width() )
     305             :                 // Calculate the right height
     306           0 :                 aCalcSz.Height() = rFrmSz.Height() *
     307           0 :                         aSz.Width() / rFrmSz.Width();
     308           0 :             else if ( !aSz.Width() && aSz.Height() )
     309             :                 // Calculate the right width
     310           0 :                 aCalcSz.Width() = rFrmSz.Width() *
     311           0 :                         aSz.Height() / rFrmSz.Height();
     312             :             else
     313             :                 // Take over height and width
     314           0 :                 aCalcSz = rFrmSz;
     315             : 
     316           0 :             const SvxBoxItem     &rBox = pFmt->GetBox();
     317           0 :             aCalcSz.Width() += rBox.CalcLineSpace(BOX_LINE_LEFT) +
     318           0 :                                rBox.CalcLineSpace(BOX_LINE_RIGHT);
     319           0 :             aCalcSz.Height()+= rBox.CalcLineSpace(BOX_LINE_TOP) +
     320           0 :                                rBox.CalcLineSpace(BOX_LINE_BOTTOM);
     321           0 :             const SwFmtFrmSize& rOldAttr = pFmt->GetFrmSize();
     322           0 :             if( rOldAttr.GetSize() != aCalcSz )
     323             :             {
     324           0 :                 SwFmtFrmSize aAttr( rOldAttr  );
     325           0 :                 aAttr.SetSize( aCalcSz );
     326           0 :                 pFmt->SetFmtAttr( aAttr );
     327           0 :                 bRet = true;
     328             :             }
     329             : 
     330           0 :             if( !aSz.Width() )
     331             :             {
     332             :                 // If the graphic is anchored in a table, we need to recalculate
     333             :                 // the table rows
     334           0 :                 const SwDoc *pDoc = pGrfNd->GetDoc();
     335           0 :                 const SwPosition* pAPos = pFmt->GetAnchor().GetCntntAnchor();
     336             :                 SwNode *pANd;
     337             :                 SwTableNode *pTblNd;
     338           0 :                 if( pAPos &&
     339           0 :                     0 != (pANd = & pAPos->nNode.GetNode()) &&
     340             :                     0 != (pTblNd = pANd->FindTableNode()) )
     341             :                 {
     342           0 :                     const bool bLastGrf = !pTblNd->GetTable().DecGrfsThatResize();
     343             :                     SwHTMLTableLayout *pLayout =
     344           0 :                         pTblNd->GetTable().GetHTMLTableLayout();
     345           0 :                     if( pLayout )
     346             :                     {
     347             :                         const sal_uInt16 nBrowseWidth =
     348           0 :                                     pLayout->GetBrowseWidthByTable( *pDoc );
     349           0 :                         if ( nBrowseWidth )
     350             :                         {
     351             :                             pLayout->Resize( nBrowseWidth, sal_True, sal_True,
     352             :                                              bLastGrf ? HTMLTABLE_RESIZE_NOW
     353           0 :                                                       : 500 );
     354             :                         }
     355             :                     }
     356             :                 }
     357             :             }
     358             :         }
     359             : 
     360             :         // SetTwipSize rescales an ImageMap if needed for which
     361             :         // it requires the Frame Format
     362           0 :         pGrfNd->SetTwipSize( rGrfSz );
     363             :     }
     364             : 
     365           6 :     delete pCurr;
     366             : 
     367           6 :     return bRet;
     368             : }
     369             : 
     370          16 : bool SwBaseLink::SwapIn( bool bWaitForData, bool bNativFormat )
     371             : {
     372          16 :     bSwapIn = true;
     373             : 
     374          16 :     if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) ))
     375             :     {
     376           0 :         AddNextRef();
     377           0 :         _GetRealObject();
     378           0 :         ReleaseRef();
     379             :     }
     380             : 
     381             : #if OSL_DEBUG_LEVEL > 1
     382             :     {
     383             :         OUString sGrfNm;
     384             :         if(GetLinkManager())
     385             :             GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
     386             :         int x = 0;
     387             :         ++x;
     388             :     }
     389             : #endif
     390             : 
     391          16 :     bool bRes = false;
     392             : 
     393          16 :     if( GetObj() )
     394             :     {
     395          12 :         OUString aMimeType( SotExchange::GetFormatMimeType( GetContentType() ));
     396          24 :         uno::Any aValue;
     397          12 :         (void)GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData );
     398             : 
     399          12 :         if( bWaitForData && !GetObj() )
     400             :         {
     401             :             OSL_ENSURE( !this, "The SvxFileObject was deleted in a GetData!" );
     402             :         }
     403             :         else
     404             :         {
     405          12 :             bRes = aValue.hasValue();
     406          12 :             if ( bRes )
     407             :             {
     408             :                 // The Flag needs to be reset on a SwapIn, because
     409             :                 // we want to reapply the data.
     410           4 :                 bIgnoreDataChanged = false;
     411           4 :                 DataChanged( aMimeType, aValue );
     412             :             }
     413          12 :         }
     414             :     }
     415           4 :     else if( !IsSynchron() && bWaitForData )
     416             :     {
     417           0 :         SetSynchron( true );
     418           0 :         bRes = Update();
     419           0 :         SetSynchron( false );
     420             :     }
     421             :     else
     422           4 :         bRes = Update();
     423             : 
     424          16 :     bSwapIn = false;
     425          16 :     return bRes;
     426             : }
     427             : 
     428           0 : void SwBaseLink::Closed()
     429             : {
     430           0 :     if( pCntntNode && !pCntntNode->GetDoc()->IsInDtor() )
     431             :     {
     432             :         // Delete the connection
     433           0 :         if( pCntntNode->IsGrfNode() )
     434           0 :             ((SwGrfNode*)pCntntNode)->ReleaseLink();
     435             :     }
     436           0 :     SvBaseLink::Closed();
     437           0 : }
     438             : 
     439           0 : const SwNode* SwBaseLink::GetAnchor() const
     440             : {
     441           0 :     if (pCntntNode)
     442             :     {
     443           0 :         SwFrmFmt *const pFmt = pCntntNode->GetFlyFmt();
     444           0 :         if (pFmt)
     445             :         {
     446           0 :             const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
     447           0 :             SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
     448           0 :             if (pAPos &&
     449           0 :                 ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
     450           0 :                  (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
     451           0 :                  (FLY_AT_FLY  == rAnchor.GetAnchorId()) ||
     452           0 :                  (FLY_AT_PARA == rAnchor.GetAnchorId())))
     453             :             {
     454           0 :                     return &pAPos->nNode.GetNode();
     455             :             }
     456           0 :             return 0;
     457             :         }
     458             :     }
     459             : 
     460             :     OSL_ENSURE( !this, "GetAnchor is not shadowed" );
     461           0 :     return 0;
     462             : }
     463             : 
     464           0 : bool SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const
     465             : {
     466           0 :     SwServerObjectRef aRef( (SwServerObject*)GetObj() );
     467           0 :     if( aRef.Is() )
     468             :     {
     469             :         // As it's a ServerObject, we query all contained Links
     470             :         // if we are contained in them. Else we have a recursion.
     471           0 :         return aRef->IsLinkInServer( pChkLnk );
     472             :     }
     473           0 :     return false;
     474             : }
     475             : 
     476           0 : bool SwBaseLink::IsInRange( sal_uLong, sal_uLong, sal_Int32, sal_Int32 ) const
     477             : {
     478             :     // Not Graphic or OLE Links
     479             :     // Fields or Sections have their own derivation!
     480           0 :     return false;
     481             : }
     482             : 
     483          13 : SwBaseLink::~SwBaseLink()
     484             : {
     485          13 : }
     486             : 
     487             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10