diff options
-rw-r--r-- | embeddedobj/source/commonembedding/embedobj.cxx | 60 | ||||
-rw-r--r-- | embeddedobj/source/commonembedding/specialobject.cxx | 9 | ||||
-rw-r--r-- | embeddedobj/source/inc/commonembobj.hxx | 3 | ||||
-rw-r--r-- | embeddedobj/source/inc/specialobject.hxx | 6 | ||||
-rw-r--r-- | include/svx/svdoole2.hxx | 17 | ||||
-rw-r--r-- | include/svx/unoshape.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/docshell/documentlinkmgr.cxx | 9 | ||||
-rw-r--r-- | sfx2/source/doc/iframe.cxx | 55 | ||||
-rw-r--r-- | svx/source/svdraw/svdoole2.cxx | 104 | ||||
-rw-r--r-- | svx/source/unodraw/shapeimpl.hxx | 5 | ||||
-rw-r--r-- | svx/source/unodraw/unoshap4.cxx | 23 | ||||
-rw-r--r-- | sw/inc/ndole.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/ole/ndole.cxx | 89 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.cxx | 29 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.hxx | 2 |
15 files changed, 331 insertions, 86 deletions
diff --git a/embeddedobj/source/commonembedding/embedobj.cxx b/embeddedobj/source/commonembedding/embedobj.cxx index 14e7246b7b42..f3fed14d191d 100644 --- a/embeddedobj/source/commonembedding/embedobj.cxx +++ b/embeddedobj/source/commonembedding/embedobj.cxx @@ -155,6 +155,37 @@ void OCommonEmbeddedObject::StateChangeNotification_Impl( bool bBeforeChange, sa } } +void OCommonEmbeddedObject::SetInplaceActiveState() +{ + if ( !m_xClientSite.is() ) + throw embed::WrongStateException( "client site not set, yet", *this ); + + uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, uno::UNO_QUERY ); + if ( !xInplaceClient.is() || !xInplaceClient->canInplaceActivate() ) + throw embed::WrongStateException(); //TODO: can't activate inplace + xInplaceClient->activatingInplace(); + + uno::Reference< embed::XWindowSupplier > xClientWindowSupplier( xInplaceClient, uno::UNO_QUERY_THROW ); + + m_xClientWindow = xClientWindowSupplier->getWindow(); + m_aOwnRectangle = xInplaceClient->getPlacement(); + m_aClipRectangle = xInplaceClient->getClipRectangle(); + awt::Rectangle aRectangleToShow = GetRectangleInterception( m_aOwnRectangle, m_aClipRectangle ); + + // create own window based on the client window + // place and resize the window according to the rectangles + uno::Reference< awt::XWindowPeer > xClientWindowPeer( m_xClientWindow, uno::UNO_QUERY_THROW ); + + // dispatch provider may not be provided + uno::Reference< frame::XDispatchProvider > xContainerDP = xInplaceClient->getInplaceDispatchProvider(); + bool bOk = m_xDocHolder->ShowInplace( xClientWindowPeer, aRectangleToShow, xContainerDP ); + m_nObjectState = embed::EmbedStates::INPLACE_ACTIVE; + if ( !bOk ) + { + SwitchStateTo_Impl( embed::EmbedStates::RUNNING ); + throw embed::WrongStateException(); //TODO: can't activate inplace + } +} void OCommonEmbeddedObject::SwitchStateTo_Impl( sal_Int32 nNextState ) { @@ -229,34 +260,7 @@ void OCommonEmbeddedObject::SwitchStateTo_Impl( sal_Int32 nNextState ) { if ( nNextState == embed::EmbedStates::INPLACE_ACTIVE ) { - if ( !m_xClientSite.is() ) - throw embed::WrongStateException( "client site not set, yet", *this ); - - uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, uno::UNO_QUERY ); - if ( !xInplaceClient.is() || !xInplaceClient->canInplaceActivate() ) - throw embed::WrongStateException(); //TODO: can't activate inplace - xInplaceClient->activatingInplace(); - - uno::Reference< embed::XWindowSupplier > xClientWindowSupplier( xInplaceClient, uno::UNO_QUERY_THROW ); - - m_xClientWindow = xClientWindowSupplier->getWindow(); - m_aOwnRectangle = xInplaceClient->getPlacement(); - m_aClipRectangle = xInplaceClient->getClipRectangle(); - awt::Rectangle aRectangleToShow = GetRectangleInterception( m_aOwnRectangle, m_aClipRectangle ); - - // create own window based on the client window - // place and resize the window according to the rectangles - uno::Reference< awt::XWindowPeer > xClientWindowPeer( m_xClientWindow, uno::UNO_QUERY_THROW ); - - // dispatch provider may not be provided - uno::Reference< frame::XDispatchProvider > xContainerDP = xInplaceClient->getInplaceDispatchProvider(); - bool bOk = m_xDocHolder->ShowInplace( xClientWindowPeer, aRectangleToShow, xContainerDP ); - m_nObjectState = nNextState; - if ( !bOk ) - { - SwitchStateTo_Impl( embed::EmbedStates::RUNNING ); - throw embed::WrongStateException(); //TODO: can't activate inplace - } + SetInplaceActiveState(); } else if ( nNextState == embed::EmbedStates::ACTIVE ) { diff --git a/embeddedobj/source/commonembedding/specialobject.cxx b/embeddedobj/source/commonembedding/specialobject.cxx index 7b4a27ead172..faf76d91bbc8 100644 --- a/embeddedobj/source/commonembedding/specialobject.cxx +++ b/embeddedobj/source/commonembedding/specialobject.cxx @@ -59,6 +59,7 @@ uno::Any SAL_CALL OSpecialEmbeddedObject::queryInterface( const uno::Type& rType aReturn = ::cppu::queryInterface( rType, static_cast< embed::XEmbeddedObject* >( this ), static_cast< embed::XInplaceObject* >( this ), + static_cast< embed::XCommonEmbedPersist* >( static_cast< embed::XEmbedPersist* >( this ) ), static_cast< embed::XVisualObject* >( this ), static_cast< embed::XClassifiedObject* >( this ), static_cast< embed::XComponentSupplier* >( this ), @@ -172,4 +173,12 @@ void SAL_CALL OSpecialEmbeddedObject::doVerb( sal_Int32 nVerbID ) OCommonEmbeddedObject::doVerb( nVerbID ); } +void SAL_CALL OSpecialEmbeddedObject::reload( + const uno::Sequence< beans::PropertyValue >&, + const uno::Sequence< beans::PropertyValue >&) +{ + // Allow IFrames to reload their content + SetInplaceActiveState(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/embeddedobj/source/inc/commonembobj.hxx b/embeddedobj/source/inc/commonembobj.hxx index 868bcc296631..7176009bcc11 100644 --- a/embeddedobj/source/inc/commonembobj.hxx +++ b/embeddedobj/source/inc/commonembobj.hxx @@ -231,6 +231,9 @@ private: const css::uno::Sequence< css::beans::PropertyValue >& lArguments, const css::uno::Sequence< css::beans::PropertyValue >& lObjArgs ); +protected: + void SetInplaceActiveState(); + public: OCommonEmbeddedObject( const css::uno::Reference< css::uno::XComponentContext >& rxContext, diff --git a/embeddedobj/source/inc/specialobject.hxx b/embeddedobj/source/inc/specialobject.hxx index 32ad61a7a582..ce5c01b35ae7 100644 --- a/embeddedobj/source/inc/specialobject.hxx +++ b/embeddedobj/source/inc/specialobject.hxx @@ -48,6 +48,12 @@ public: virtual void SAL_CALL changeState( sal_Int32 nNewState ) override; virtual void SAL_CALL doVerb( sal_Int32 nVerbID ) override; + +// XCommonEmbedPersist + + virtual void SAL_CALL reload( + const css::uno::Sequence< css::beans::PropertyValue >& lArguments, + const css::uno::Sequence< css::beans::PropertyValue >& lObjArgs ) override; }; #endif diff --git a/include/svx/svdoole2.hxx b/include/svx/svdoole2.hxx index a897b797694d..2fc34ecedc3f 100644 --- a/include/svx/svdoole2.hxx +++ b/include/svx/svdoole2.hxx @@ -42,6 +42,7 @@ namespace frame { class XModel; } namespace svt { class EmbeddedObjectRef; } class SdrOle2ObjImpl; +class SvxOle2Shape; class SVX_DLLPUBLIC SdrOle2Obj : public SdrRectObj { @@ -49,7 +50,7 @@ private: std::unique_ptr<SdrOle2ObjImpl> mpImpl; private: - SVX_DLLPRIVATE void Connect_Impl(); + SVX_DLLPRIVATE void Connect_Impl(SvxOle2Shape* pCreator = nullptr); SVX_DLLPRIVATE void Disconnect_Impl(); SVX_DLLPRIVATE void AddListeners_Impl(); SVX_DLLPRIVATE void RemoveListeners_Impl(); @@ -105,7 +106,7 @@ public: // OLE object has got a separate PersistName member now; // !!! use ::SetPersistName( ... ) only, if you know what you do !!! const OUString& GetPersistName() const; - void SetPersistName( const OUString& rPersistName ); + void SetPersistName( const OUString& rPersistName, SvxOle2Shape* pCreator = nullptr ); // One can add an application name to a SdrOle2Obj, which can be queried for // later on (SD needs this for presentation objects). @@ -153,7 +154,7 @@ public: sal_Int64 nAspect ); static bool Unload( const css::uno::Reference< css::embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ); bool Unload(); - void Connect(); + void Connect(SvxOle2Shape* pCreator = nullptr); void Disconnect(); void ObjectLoaded(); @@ -200,6 +201,16 @@ public: void Connect() { GetRealObject(); } }; +class SVXCORE_DLLPUBLIC SdrIFrameLink final : public sfx2::SvBaseLink +{ + SdrOle2Obj* m_pObject; + +public: + explicit SdrIFrameLink(SdrOle2Obj* pObject); + virtual ::sfx2::SvBaseLink::UpdateResult DataChanged( + const OUString& rMimeType, const css::uno::Any & rValue ) override; +}; + #endif // INCLUDED_SVX_SVDOOLE2_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/unoshape.hxx b/include/svx/unoshape.hxx index 60917bf7d893..6bbbe5b56502 100644 --- a/include/svx/unoshape.hxx +++ b/include/svx/unoshape.hxx @@ -605,6 +605,8 @@ public: bool createObject( const SvGlobalName &aClassName ); void createLink( const OUString& aLinkURL ); + + virtual OUString GetAndClearInitialFrameURL(); }; diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx index 7452f87d3ce7..7b4bdb698a80 100644 --- a/sc/source/ui/docshell/documentlinkmgr.cxx +++ b/sc/source/ui/docshell/documentlinkmgr.cxx @@ -142,7 +142,7 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, boo sfx2::SvBaseLink* pBase = rLink.get(); if (bDde && dynamic_cast<ScDdeLink*>(pBase)) return true; - if (bOle && dynamic_cast<SdrEmbedObjectLink*>(pBase)) + if (bOle && (dynamic_cast<SdrEmbedObjectLink*>(pBase) || dynamic_cast<SdrIFrameLink*>(pBase))) return true; if (bWebService && dynamic_cast<ScWebServiceLink*>(pBase)) return true; @@ -173,6 +173,13 @@ bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(weld::Window* pWin) continue; } + SdrIFrameLink* pIFrameLink = dynamic_cast<SdrIFrameLink*>(pBase); + if (pIFrameLink) + { + pIFrameLink->Update(); + continue; + } + ScWebServiceLink* pWebserviceLink = dynamic_cast<ScWebServiceLink*>(pBase); if (pWebserviceLink) { diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx index b5deacd4f468..0911f08f71d5 100644 --- a/sfx2/source/doc/iframe.cxx +++ b/sfx2/source/doc/iframe.cxx @@ -176,31 +176,46 @@ sal_Bool SAL_CALL IFrameObject::load( return false; } + bool bUpdateAllowed(true); + if (pDoc) + { + // perhaps should only check for file targets, but lets default to making it strong + // unless there is a known need to distinguish + comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pDoc->getEmbeddedObjectContainer(); + bUpdateAllowed = rEmbeddedObjectContainer.getUserAllowsLinkUpdate(); + } + if (!bUpdateAllowed) + return false; + OUString sReferer; if (pDoc && pDoc->HasName()) sReferer = pDoc->GetMedium()->GetName(); - DBG_ASSERT( !mxFrame.is(), "Frame already existing!" ); - VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); - VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( pParent, maFrmDescr.IsFrameBorderOn() ); - pWin->SetSizePixel( pParent->GetOutputSizePixel() ); - pWin->SetBackground(); - pWin->Show(); - - uno::Reference < awt::XWindow > xWindow( pWin->GetComponentInterface(), uno::UNO_QUERY ); - xFrame->setComponent( xWindow, uno::Reference < frame::XController >() ); + uno::Reference<css::awt::XWindow> xParentWindow(xFrame->getContainerWindow()); - // we must destroy the IFrame before the parent is destroyed - xWindow->addEventListener( this ); - - mxFrame = frame::Frame::create( mxContext ); - uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), uno::UNO_QUERY ); - mxFrame->initialize( xWin ); - mxFrame->setName( maFrmDescr.GetName() ); - - uno::Reference < frame::XFramesSupplier > xFramesSupplier( xFrame, uno::UNO_QUERY ); - if ( xFramesSupplier.is() ) - mxFrame->setCreator( xFramesSupplier ); + if (!mxFrame.is()) + { + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(xParentWindow); + VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( pParent, maFrmDescr.IsFrameBorderOn() ); + pWin->SetSizePixel( pParent->GetOutputSizePixel() ); + pWin->SetBackground(); + pWin->Show(); + + uno::Reference < awt::XWindow > xWindow( pWin->GetComponentInterface(), uno::UNO_QUERY ); + xFrame->setComponent( xWindow, uno::Reference < frame::XController >() ); + + // we must destroy the IFrame before the parent is destroyed + xWindow->addEventListener( this ); + + mxFrame = frame::Frame::create( mxContext ); + uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), uno::UNO_QUERY ); + mxFrame->initialize( xWin ); + mxFrame->setName( maFrmDescr.GetName() ); + + uno::Reference < frame::XFramesSupplier > xFramesSupplier( xFrame, uno::UNO_QUERY ); + if ( xFramesSupplier.is() ) + mxFrame->setCreator( xFramesSupplier ); + } uno::Sequence < beans::PropertyValue > aProps{ comphelper::makePropertyValue("PluginMode", sal_Int16(2)), diff --git a/svx/source/svdraw/svdoole2.cxx b/svx/source/svdraw/svdoole2.cxx index 0b8fac18ca8f..f401cccf7095 100644 --- a/svx/source/svdraw/svdoole2.cxx +++ b/svx/source/svdraw/svdoole2.cxx @@ -75,6 +75,7 @@ #include <sdr/contact/viewcontactofsdrole2obj.hxx> #include <svx/svdograf.hxx> #include <sdr/properties/oleproperties.hxx> +#include <svx/unoshape.hxx> #include <svx/xlnclit.hxx> #include <svx/xbtmpit.hxx> #include <svx/xflbmtit.hxx> @@ -594,6 +595,35 @@ void SdrEmbedObjectLink::Closed() SvBaseLink::Closed(); } +SdrIFrameLink::SdrIFrameLink(SdrOle2Obj* pObject) + : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB) + , m_pObject(pObject) +{ + SetSynchron( false ); +} + +::sfx2::SvBaseLink::UpdateResult SdrIFrameLink::DataChanged( + const OUString&, const uno::Any& ) +{ + uno::Reference<embed::XEmbeddedObject> xObject = m_pObject->GetObjRef(); + uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, uno::UNO_QUERY); + if (xPersObj.is()) + { + // let the IFrameObject reload the link + try + { + xPersObj->reload(uno::Sequence<beans::PropertyValue>(), uno::Sequence<beans::PropertyValue>()); + } + catch (const uno::Exception&) + { + } + + m_pObject->SetChanged(); + } + + return SUCCESS; +} + class SdrOle2ObjImpl { public: @@ -611,7 +641,7 @@ public: bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated loading if load of OLE2 fails bool mbConnected:1; - SdrEmbedObjectLink* mpObjectLink; + sfx2::SvBaseLink* mpObjectLink; OUString maLinkURL; rtl::Reference<SvxUnoShapeModifyListener> mxModifyListener; @@ -811,7 +841,7 @@ bool SdrOle2Obj::IsEmpty() const return !mpImpl->mxObjRef.is(); } -void SdrOle2Obj::Connect() +void SdrOle2Obj::Connect(SvxOle2Shape* pCreator) { if( IsEmptyPresObj() ) return; @@ -824,7 +854,7 @@ void SdrOle2Obj::Connect() return; } - Connect_Impl(); + Connect_Impl(pCreator); AddListeners_Impl(); } @@ -925,24 +955,51 @@ void SdrOle2Obj::CheckFileLink_Impl() { try { - uno::Reference< embed::XLinkageSupport > xLinkSupport( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY ); + uno::Reference<embed::XEmbeddedObject> xObject = mpImpl->mxObjRef.GetObject(); + if (!xObject) + return; - if ( xLinkSupport.is() && xLinkSupport->isLink() ) - { - OUString aLinkURL = xLinkSupport->getLinkURL(); + bool bIFrame = false; - if ( !aLinkURL.isEmpty() ) + OUString aLinkURL; + uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, uno::UNO_QUERY); + if (xLinkSupport) + { + if (xLinkSupport->isLink()) + aLinkURL = xLinkSupport->getLinkURL(); + } + else + { + // get IFrame (Floating Frames) listed and updatable from the + // manage links dialog + SvGlobalName aClassId(xObject->getClassID()); + if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID)) { - // this is a file link so the model link manager should handle it - sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager()); + uno::Reference<beans::XPropertySet> xSet(xObject->getComponent(), uno::UNO_QUERY); + if (xSet.is()) + xSet->getPropertyValue("FrameURL") >>= aLinkURL; + bIFrame = true; + } + } + + if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it + { + sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager()); - if ( pLinkManager ) + if ( pLinkManager ) + { + SdrEmbedObjectLink* pEmbedObjectLink = nullptr; + if (!bIFrame) { - mpImpl->mpObjectLink = new SdrEmbedObjectLink( this ); - mpImpl->maLinkURL = aLinkURL; - pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL ); - mpImpl->mpObjectLink->Connect(); + pEmbedObjectLink = new SdrEmbedObjectLink(this); + mpImpl->mpObjectLink = pEmbedObjectLink; } + else + mpImpl->mpObjectLink = new SdrIFrameLink(this); + mpImpl->maLinkURL = aLinkURL; + pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL ); + if (pEmbedObjectLink) + pEmbedObjectLink->Connect(); } } } @@ -953,7 +1010,7 @@ void SdrOle2Obj::CheckFileLink_Impl() } } -void SdrOle2Obj::Connect_Impl() +void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator) { if(!mpImpl->aPersistName.isEmpty() ) { @@ -993,6 +1050,17 @@ void SdrOle2Obj::Connect_Impl() } } + if (pCreator) + { + OUString sFrameURL(pCreator->GetAndClearInitialFrameURL()); + if (!sFrameURL.isEmpty() && svt::EmbeddedObjectRef::TryRunningState(mpImpl->mxObjRef.GetObject())) + { + uno::Reference<beans::XPropertySet> xSet(mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY); + if (xSet.is()) + xSet->setPropertyValue("FrameURL", uno::Any(sFrameURL)); + } + } + if ( mpImpl->mxObjRef.is() ) { if ( !mpImpl->mxLightClient.is() ) @@ -1312,14 +1380,14 @@ SdrObject* SdrOle2Obj::getFullDragClone() const return createSdrGrafObjReplacement(false); } -void SdrOle2Obj::SetPersistName( const OUString& rPersistName ) +void SdrOle2Obj::SetPersistName( const OUString& rPersistName, SvxOle2Shape* pCreator ) { DBG_ASSERT( mpImpl->aPersistName.isEmpty(), "Persist name changed!"); mpImpl->aPersistName = rPersistName; mpImpl->mbLoadingOLEObjectFailed = false; - Connect(); + Connect(pCreator); SetChanged(); } diff --git a/svx/source/unodraw/shapeimpl.hxx b/svx/source/unodraw/shapeimpl.hxx index 9b0a713184fa..23a886036f32 100644 --- a/svx/source/unodraw/shapeimpl.hxx +++ b/svx/source/unodraw/shapeimpl.hxx @@ -62,8 +62,11 @@ public: virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override; }; + class SvxFrameShape : public SvxOle2Shape { +private: + OUString m_sInitialFrameURL; protected: // override these for special property handling in subcasses. Return true if property is handled virtual bool setPropertyValueImpl( const OUString& rName, const SfxItemPropertySimpleEntry* pProperty, const css::uno::Any& rValue ) override; @@ -80,6 +83,8 @@ public: virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override; virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override; + + virtual OUString GetAndClearInitialFrameURL() override; }; diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx index c05baca128cc..dd9400d3741c 100644 --- a/svx/source/unodraw/unoshap4.cxx +++ b/svx/source/unodraw/unoshap4.cxx @@ -179,7 +179,7 @@ bool SvxOle2Shape::setPropertyValueImpl( const OUString& rName, const SfxItemPro #else pOle = static_cast<SdrOle2Obj*>(GetSdrObject()); #endif - pOle->SetPersistName( aPersistName ); + pOle->SetPersistName( aPersistName, this ); return true; } break; @@ -500,10 +500,11 @@ void SvxOle2Shape::createLink( const OUString& aLinkURL ) void SvxOle2Shape::resetModifiedState() { - ::comphelper::IEmbeddedHelper* pPersist = GetSdrObject()->getSdrModelFromSdrObject().GetPersist(); + SdrObject* pObject = GetSdrObject(); + ::comphelper::IEmbeddedHelper* pPersist = pObject ? pObject->getSdrModelFromSdrObject().GetPersist() : nullptr; if( pPersist && !pPersist->isEnableSetModified() ) { - SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >(pObject); if( pOle && !pOle->IsEmpty() ) { uno::Reference < util::XModifiable > xMod( pOle->GetObjRef(), uno::UNO_QUERY ); @@ -553,6 +554,11 @@ const SvGlobalName SvxOle2Shape::GetClassName_Impl(OUString& rHexCLSID) return aClassName; } +OUString SvxOle2Shape::GetAndClearInitialFrameURL() +{ + return OUString(); +} + SvxAppletShape::SvxAppletShape(SdrObject* pObject) : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_APPLET), getSvxMapProvider().GetPropertySet(SVXMAP_APPLET, SdrObject::GetGlobalDrawObjectItemPool()) ) { @@ -706,8 +712,19 @@ SvxFrameShape::~SvxFrameShape() throw() { } +OUString SvxFrameShape::GetAndClearInitialFrameURL() +{ + OUString sRet(m_sInitialFrameURL); + m_sInitialFrameURL.clear(); + return sRet; +} + void SvxFrameShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) { + uno::Reference<beans::XPropertySet> xSet(static_cast<OWeakObject *>(this), uno::UNO_QUERY); + if (xSet) + xSet->getPropertyValue("FrameURL") >>= m_sInitialFrameURL; + SvxShape::Create( pNewObj, pNewPage ); const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID ); createObject(aIFrameClassId); diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx index 21896f6f99c0..b996540e70b5 100644 --- a/sw/inc/ndole.hxx +++ b/sw/inc/ndole.hxx @@ -28,7 +28,7 @@ class SwGrfFormatColl; class SwDoc; class SwOLENode; class SwOLEListener_Impl; -class SwEmbedObjectLink; +namespace sfx2 { class SvBaseLink; } class DeflateData; class SW_DLLPUBLIC SwOLEObj @@ -88,7 +88,7 @@ class SW_DLLPUBLIC SwOLENode: public SwNoTextNode bool mbOLESizeInvalid; /**< Should be considered at SwDoc::PrtOLENotify (e.g. copied). Is not persistent. */ - SwEmbedObjectLink* mpObjectLink; + sfx2::SvBaseLink* mpObjectLink; OUString maLinkURL; SwOLENode( const SwNodeIndex &rWhere, diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx index ee11c90fc626..e79f59ba9bc5 100644 --- a/sw/source/core/ole/ndole.cxx +++ b/sw/source/core/ole/ndole.cxx @@ -144,6 +144,8 @@ void SAL_CALL SwOLEListener_Impl::disposing( const lang::EventObject& ) // TODO/LATER: actually SwEmbedObjectLink should be used here, but because different objects are used to control // embedded object different link objects with the same functionality had to be implemented +namespace { + class SwEmbedObjectLink : public sfx2::SvBaseLink { SwOLENode* pOleNode; @@ -206,6 +208,44 @@ void SwEmbedObjectLink::Closed() SvBaseLink::Closed(); } +class SwIFrameLink : public sfx2::SvBaseLink +{ + SwOLENode* m_pOleNode; + +public: + explicit SwIFrameLink(SwOLENode* pNode) + : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB) + , m_pOleNode(pNode) + { + SetSynchron( false ); + } + + ::sfx2::SvBaseLink::UpdateResult DataChanged( + const OUString&, const uno::Any& ) + { + uno::Reference<embed::XEmbeddedObject> xObject = m_pOleNode->GetOLEObj().GetOleRef(); + uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, uno::UNO_QUERY); + if (xPersObj.is()) + { + // let the IFrameObject reload the link + try + { + xPersObj->reload(uno::Sequence<beans::PropertyValue>(), uno::Sequence<beans::PropertyValue>()); + } + catch (const uno::Exception&) + { + } + + m_pOleNode->SetChanged(); + } + + return SUCCESS; + } + +}; + +} + SwOLENode::SwOLENode( const SwNodeIndex &rWhere, const svt::EmbeddedObjectRef& xObj, SwGrfFormatColl *pGrfColl, @@ -591,18 +631,49 @@ void SwOLENode::CheckFileLink_Impl() { try { - uno::Reference< embed::XLinkageSupport > xLinkSupport( maOLEObj.m_xOLERef.GetObject(), uno::UNO_QUERY_THROW ); - if ( xLinkSupport->isLink() ) + uno::Reference<embed::XEmbeddedObject> xObject = maOLEObj.m_xOLERef.GetObject(); + if (!xObject) + return; + + bool bIFrame = false; + + OUString aLinkURL; + uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, uno::UNO_QUERY); + if (xLinkSupport) + { + if (xLinkSupport->isLink()) + aLinkURL = xLinkSupport->getLinkURL(); + } + else { - const OUString aLinkURL = xLinkSupport->getLinkURL(); - if ( !aLinkURL.isEmpty() ) + // get IFrame (Floating Frames) listed and updatable from the + // manage links dialog + SvGlobalName aClassId(xObject->getClassID()); + if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID)) + { + uno::Reference<beans::XPropertySet> xSet(xObject->getComponent(), uno::UNO_QUERY); + if (xSet.is()) + xSet->getPropertyValue("FrameURL") >>= aLinkURL; + bIFrame = true; + } + } + + if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it + { + SwEmbedObjectLink* pEmbedObjectLink = nullptr; + if (!bIFrame) + { + pEmbedObjectLink = new SwEmbedObjectLink(this); + mpObjectLink = pEmbedObjectLink; + } + else { - // this is a file link so the model link manager should handle it - mpObjectLink = new SwEmbedObjectLink( this ); - maLinkURL = aLinkURL; - GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL ); - mpObjectLink->Connect(); + mpObjectLink = new SwIFrameLink(this); } + maLinkURL = aLinkURL; + GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL ); + if (pEmbedObjectLink) + pEmbedObjectLink->Connect(); } } catch( uno::Exception& ) diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 81aa648837e9..12f0b9af142a 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -3231,9 +3231,35 @@ SdXMLFloatingFrameShapeContext::~SdXMLFloatingFrameShapeContext() { } +uno::Reference<drawing::XShape> SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape() const +{ + uno::Reference<lang::XMultiServiceFactory> xServiceFact(GetImport().GetModel(), uno::UNO_QUERY); + if (!xServiceFact.is()) + return nullptr; + uno::Reference<drawing::XShape> xShape( + xServiceFact->createInstance("com.sun.star.drawing.FrameShape"), uno::UNO_QUERY); + return xShape; +} + void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< css::xml::sax::XAttributeList >& ) { - AddShape("com.sun.star.drawing.FrameShape"); + uno::Reference<drawing::XShape> xShape(SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape()); + + uno::Reference< beans::XPropertySet > xProps(xShape, uno::UNO_QUERY); + // set FrameURL before AddShape, we have to do it again later because it + // gets cleared when the SdrOle2Obj is attached to the XShape. But we want + // FrameURL to exist when AddShape triggers SetPersistName which itself + // triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to + // know what URL will end up being used. So bodge this by setting FrameURL + // to the temp pre-SdrOle2Obj attached properties and we can smuggle it + // eventually into SdrOle2Obj::SetPersistName at the right point after + // PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called + // in order to inform the link manager that this is an IFrame that links to + // a URL + if (xProps && !maHref.isEmpty()) + xProps->setPropertyValue("FrameURL", Any(maHref)); + + AddShape(xShape); if( mxShape.is() ) { @@ -3242,7 +3268,6 @@ void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< cs // set pos, size, shear and rotate SetTransformation(); - uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY ); if( xProps.is() ) { if( !maFrameName.isEmpty() ) diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx index 6066a72f7889..4229495641e2 100644 --- a/xmloff/source/draw/ximpshap.hxx +++ b/xmloff/source/draw/ximpshap.hxx @@ -521,6 +521,8 @@ private: OUString maFrameName; OUString maHref; + css::uno::Reference<css::drawing::XShape> CreateFloatingFrameShape() const; + public: SdXMLFloatingFrameShapeContext( SvXMLImport& rImport, sal_uInt16 nPrfx, |