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

Generated by: LCOV version 1.11