diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/core/docnode/swbaslnk.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/docnode/swbaslnk.cxx')
-rw-r--r-- | sw/source/core/docnode/swbaslnk.cxx | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/sw/source/core/docnode/swbaslnk.cxx b/sw/source/core/docnode/swbaslnk.cxx new file mode 100644 index 000000000..8b7832937 --- /dev/null +++ b/sw/source/core/docnode/swbaslnk.cxx @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <hintids.hxx> +#include <vcl/svapp.hxx> + +#include <sfx2/docfile.hxx> +#include <sfx2/lnkbase.hxx> +#include <sfx2/objsh.hxx> +#include <editeng/boxitem.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/event.hxx> +#include <sot/exchange.hxx> +#include <fmtfsize.hxx> +#include <fmtanchr.hxx> +#include <frmatr.hxx> +#include <frmfmt.hxx> +#include <doc.hxx> +#include <DocumentLinksAdministrationManager.hxx> +#include <IDocumentLayoutAccess.hxx> +#include <pam.hxx> +#include <swtable.hxx> +#include <swevent.hxx> +#include <swbaslnk.hxx> +#include <swserv.hxx> +#include <viewsh.hxx> +#include <ndgrf.hxx> +#include <hints.hxx> +#include <cntfrm.hxx> +#include <htmltbl.hxx> +#include <calbck.hxx> +#include <dialoghelp.hxx> +#include <memory> + +using namespace com::sun::star; + +static bool SetGrfFlySize( const Size& rGrfSz, SwGrfNode* pGrfNd, const Size &rOrigGrfSize ); + + +static void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem ) +{ + //call first all not SwNoTextFrames, then the SwNoTextFrames. + // The reason is, that in the SwNoTextFrames the Graphic + // after a Paint will be swapped out! So all other "behind" + // them haven't a loaded Graphic. + rGrfNd.LockModify(); + { + SwIterator<SwClient,SwGrfNode> aIter(rGrfNd); + for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next()) + if(dynamic_cast<const SwContentFrame*>( pLast) == nullptr) + pLast->ModifyNotification(&rItem, &rItem); + } + { + SwIterator<SwContentFrame,SwGrfNode> aIter(rGrfNd); + for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next()) + pLast->ModifyNotification(&rItem, &rItem); + } + rGrfNd.UnlockModify(); +} + +::sfx2::SvBaseLink::UpdateResult SwBaseLink::DataChanged( + const OUString& rMimeType, const uno::Any & rValue ) +{ + if( !m_pContentNode ) + { + OSL_ENSURE(false, "DataChanged without ContentNode" ); + return ERROR_GENERAL; + } + + SwDoc* pDoc = m_pContentNode->GetDoc(); + if( pDoc->IsInDtor() || ChkNoDataFlag() ) + { + return SUCCESS; + } + + SotClipboardFormatId nFormat = SotExchange::GetFormatIdFromMimeType( rMimeType ); + + if( m_pContentNode->IsNoTextNode() && + nFormat == sfx2::LinkManager::RegisterStatusInfoId() ) + { + // Only a status change - serve Events? + OUString sState; + + if( rValue.hasValue() && ( rValue >>= sState )) + { + SvMacroItemId nEvent = SvMacroItemId::NONE; + switch( sState.toInt32() ) + { + case sfx2::LinkManager::STATE_LOAD_OK: nEvent = SvMacroItemId::OnImageLoadDone; break; + case sfx2::LinkManager::STATE_LOAD_ERROR: nEvent = SvMacroItemId::OnImageLoadError; break; + case sfx2::LinkManager::STATE_LOAD_ABORT: nEvent = SvMacroItemId::OnImageLoadCancel; break; + } + + SwFrameFormat* pFormat; + if( nEvent != SvMacroItemId::NONE && nullptr != ( pFormat = m_pContentNode->GetFlyFormat() )) + { + SwCallMouseEvent aCallEvent; + aCallEvent.Set( EVENT_OBJECT_IMAGE, pFormat ); + pDoc->CallEvent( nEvent, aCallEvent ); + } + } + return SUCCESS; // That's it! + } + + bool bUpdate = false; + bool bFrameInPaint = false; + Size aGrfSz, aOldSz; + + SwGrfNode* pSwGrfNode = nullptr; + + if (m_pContentNode->IsGrfNode()) + { + pSwGrfNode = m_pContentNode->GetGrfNode(); + assert(pSwGrfNode && "Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)"); + aOldSz = pSwGrfNode->GetTwipSize(); + const GraphicObject& rGrfObj = pSwGrfNode->GetGrfObj(); + + bFrameInPaint = pSwGrfNode->IsFrameInPaint(); + + Graphic aGrf; + + // tdf#124698 if any auth dialog is needed, find what the parent window should be + weld::Window* pDlgParent = GetFrameWeld(pDoc); + + if (pDoc->getIDocumentLinksAdministration().GetLinkManager().GetGraphicFromAny(rMimeType, rValue, aGrf, pDlgParent) && + ( GraphicType::Default != aGrf.GetType() || + GraphicType::Default != rGrfObj.GetType() ) ) + { + aGrfSz = ::GetGraphicSizeTwip( aGrf, nullptr ); + + pSwGrfNode->SetGraphic(aGrf); + bUpdate = true; + + // Always use the correct graphic size + if( aGrfSz.Height() && aGrfSz.Width() && + aOldSz.Height() && aOldSz.Width() && + aGrfSz != aOldSz ) + { + pSwGrfNode->SetTwipSize(aGrfSz); + aOldSz = aGrfSz; + } + } + } + else if( m_pContentNode->IsOLENode() ) + bUpdate = true; + + if ( !bUpdate || bFrameInPaint ) + return SUCCESS; + + if (pSwGrfNode) + { + if (!SetGrfFlySize(aGrfSz, pSwGrfNode, aOldSz)) + { + SwMsgPoolItem aMsgHint(RES_GRAPHIC_ARRIVED); + lcl_CallModify(*pSwGrfNode, aMsgHint); + return SUCCESS; + } + } + + return SUCCESS; +} + +static bool SetGrfFlySize( const Size& rGrfSz, SwGrfNode* pGrfNd, const Size& rOrigGrfSize ) +{ + bool bRet = false; + SwViewShell *pSh = pGrfNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell(); + std::unique_ptr<CurrShell> pCurr; + if ( pGrfNd->GetDoc()->GetEditShell() ) + pCurr.reset(new CurrShell( pSh )); + + Size aSz = rOrigGrfSize; + if ( !(aSz.Width() && aSz.Height()) && + rGrfSz.Width() && rGrfSz.Height() ) + { + SwFrameFormat* pFormat = nullptr; + if (pGrfNd->IsChgTwipSize()) + pFormat = pGrfNd->GetFlyFormat(); + if (nullptr != pFormat) + { + Size aCalcSz( aSz ); + if ( !aSz.Height() && aSz.Width() ) + // Calculate the right height + aCalcSz.setHeight( rGrfSz.Height() * + aSz.Width() / rGrfSz.Width() ); + else if ( !aSz.Width() && aSz.Height() ) + // Calculate the right width + aCalcSz.setWidth( rGrfSz.Width() * + aSz.Height() / rGrfSz.Height() ); + else + // Take over height and width + aCalcSz = rGrfSz; + + const SvxBoxItem &rBox = pFormat->GetBox(); + aCalcSz.AdjustWidth(rBox.CalcLineSpace(SvxBoxItemLine::LEFT) + + rBox.CalcLineSpace(SvxBoxItemLine::RIGHT) ); + aCalcSz.AdjustHeight(rBox.CalcLineSpace(SvxBoxItemLine::TOP) + + rBox.CalcLineSpace(SvxBoxItemLine::BOTTOM) ); + const SwFormatFrameSize& rOldAttr = pFormat->GetFrameSize(); + if( rOldAttr.GetSize() != aCalcSz ) + { + SwFormatFrameSize aAttr( rOldAttr ); + aAttr.SetSize( aCalcSz ); + pFormat->SetFormatAttr( aAttr ); + bRet = true; + } + + if( !aSz.Width() ) + { + // If the graphic is anchored in a table, we need to recalculate + // the table rows + const SwDoc *pDoc = pGrfNd->GetDoc(); + const SwPosition* pAPos = pFormat->GetAnchor().GetContentAnchor(); + SwTableNode *pTableNd; + if (pAPos && nullptr != (pTableNd = pAPos->nNode.GetNode().FindTableNode())) + { + const bool bLastGrf = !pTableNd->GetTable().DecGrfsThatResize(); + SwHTMLTableLayout *pLayout = + pTableNd->GetTable().GetHTMLTableLayout(); + if( pLayout ) + { + const sal_uInt16 nBrowseWidth = + pLayout->GetBrowseWidthByTable( *pDoc ); + if ( nBrowseWidth ) + { + pLayout->Resize( nBrowseWidth, true, true, + bLastGrf ? HTMLTABLE_RESIZE_NOW + : 500 ); + } + } + } + } + } + + // SetTwipSize rescales an ImageMap if needed for which + // it requires the Frame Format + pGrfNd->SetTwipSize( rGrfSz ); + } + + return bRet; +} + +bool SwBaseLink::SwapIn( bool bWaitForData, bool bNativFormat ) +{ + if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) )) + { + AddNextRef(); + GetRealObject_(); + ReleaseRef(); + } + + bool bRes = false; + + if( GetObj() ) + { + OUString aMimeType( SotExchange::GetFormatMimeType( GetContentType() )); + uno::Any aValue; + (void)GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData ); + + if( bWaitForData && !GetObj() ) + { + OSL_ENSURE( false, "The SvxFileObject was deleted in a GetData!" ); + } + else + { + bRes = aValue.hasValue(); + if ( bRes ) + { + DataChanged( aMimeType, aValue ); + } + } + } + else if( !IsSynchron() && bWaitForData ) + { + SetSynchron( true ); + bRes = Update(); + SetSynchron( false ); + } + else + bRes = Update(); + + return bRes; +} + +void SwBaseLink::Closed() +{ + if( m_pContentNode && !m_pContentNode->GetDoc()->IsInDtor() ) + { + // Delete the connection + if( m_pContentNode->IsGrfNode() ) + static_cast<SwGrfNode*>(m_pContentNode)->ReleaseLink(); + } + SvBaseLink::Closed(); +} + +const SwNode* SwBaseLink::GetAnchor() const +{ + if (m_pContentNode) + { + SwFrameFormat *const pFormat = m_pContentNode->GetFlyFormat(); + if (pFormat) + { + const SwFormatAnchor& rAnchor = pFormat->GetAnchor(); + SwPosition const*const pAPos = rAnchor.GetContentAnchor(); + if (pAPos && + ((RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) || + (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()) || + (RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId()) || + (RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()))) + { + return &pAPos->nNode.GetNode(); + } + return nullptr; + } + } + + OSL_ENSURE( false, "GetAnchor is not shadowed" ); + return nullptr; +} + +bool SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const +{ + tools::SvRef<SwServerObject> aRef( static_cast<SwServerObject*>(GetObj()) ); + if( aRef.is() ) + { + // As it's a ServerObject, we query all contained Links + // if we are contained in them. Else we have a recursion. + return aRef->IsLinkInServer( pChkLnk ); + } + return false; +} + +bool SwBaseLink::IsInRange( sal_uLong, sal_uLong ) const +{ + // Not Graphic or OLE Links + // Fields or Sections have their own derivation! + return false; +} + +SwBaseLink::~SwBaseLink() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |