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

Generated by: LCOV version 1.10