Until now the 'local' StyleSheet got set, but that may not be the same as the original. It was/gets identified just by searching by name and type, not comparing content. What to do? We could... (a) the Style-Friendly way: - check if StyleSheet is identical - if not, create a new in-between StyleSheet hosting missing Items - if yes, use, done. (b) the pragmatic/practical way: - Just hard-attribute the Items that are detected as different similar to what BurnInStyleSheetAttributes does/did, but only for a view differing Items (b) is the most simple for now, but will lead to more hard attributes. The other possibilities will be better in the long term. For now, I will use (b). Note that there are more cases in that VERY complex and grown stuff emerging from SdDrawDocument::PasteBookmarkAsPage. More things will need to be fixed, see this as a 1st step. Needed to adapt postProcessAfterCloneToDifferentModel due to UT testTdf96206 failing, see comment there for details. That 1st implementation showed weaknesses with those Items critical and only on MasterPages, so decided to give up on that and implement ContentCompare to SdPage::Equals. That was easier than thought: No parameter needed, only used by InsertBookmarkAsPage_FindDuplicateLayouts::operator(). Thus, SdPage::Equals needs no change, just SdrObject::Equals. Due to still problems with Items corrected in Objects on MasterPages I will for now exclude this. Could now isolate remaining problems, these are defaults and/or PresObj things on MasterPages. Important is that I can completely correct all Items for all Objects in postProcessAfterCloneToDifferentModel. I can react to these false-positives in the ContentCompare in SdrObject::Equals. Signed-off-by: Armin Le Grand (collabora) <Armin.LeGrand@collabora.com> Change-Id: I10e17c8d6a893dbe92ab716182f07bafce1f3284 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/6595 Tested-by: Jenkins CPCI <releng@collaboraoffice.com> Reviewed-by: Armin Le Grand <armin.legrand@collabora.com> (cherry picked from commit 92ffaeac04c5c8586006b026f29ce12fba3674f1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211729 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2093 lines
69 KiB
C++
2093 lines
69 KiB
C++
/* -*- 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 <svx/svdoole2.hxx>
|
|
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/util/XModifyBroadcaster.hpp>
|
|
#include <com/sun/star/util/XModifiable.hpp>
|
|
#include <com/sun/star/embed/EmbedStates.hpp>
|
|
#include <com/sun/star/embed/EmbedMisc.hpp>
|
|
#include <com/sun/star/embed/Aspects.hpp>
|
|
#include <com/sun/star/embed/ObjectSaveVetoException.hpp>
|
|
#include <com/sun/star/embed/XEmbeddedObject.hpp>
|
|
#include <com/sun/star/embed/XEmbedPersist2.hpp>
|
|
#include <com/sun/star/embed/XInplaceClient.hpp>
|
|
#include <com/sun/star/embed/XInplaceObject.hpp>
|
|
#include <com/sun/star/embed/XLinkageSupport.hpp>
|
|
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
|
|
#include <com/sun/star/embed/XWindowSupplier.hpp>
|
|
#include <com/sun/star/document/XEventListener.hpp>
|
|
#include <com/sun/star/container/XChild.hpp>
|
|
#include <com/sun/star/document/XStorageBasedDocument.hpp>
|
|
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
|
|
|
|
#include <cppuhelper/exc_hlp.hxx>
|
|
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
|
|
|
#include <svtools/colorcfg.hxx>
|
|
#include <svtools/embedhlp.hxx>
|
|
|
|
#include <sfx2/objsh.hxx>
|
|
#include <sfx2/ipclient.hxx>
|
|
#include <sfx2/lnkbase.hxx>
|
|
#include <sfx2/linkmgr.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <tools/globname.hxx>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <comphelper/classids.hxx>
|
|
#include <comphelper/propertyvalue.hxx>
|
|
|
|
#include <sot/formats.hxx>
|
|
#include <cppuhelper/implbase.hxx>
|
|
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/unohelp.hxx>
|
|
|
|
#include <svx/svdmodel.hxx>
|
|
#include <svx/dialmgr.hxx>
|
|
#include <svx/strings.hrc>
|
|
#include <svx/svdetc.hxx>
|
|
#include <unomlstr.hxx>
|
|
#include <sdr/contact/viewcontactofsdrole2obj.hxx>
|
|
#include <svx/svdograf.hxx>
|
|
#include <sdr/properties/oleproperties.hxx>
|
|
#include <svx/unoshape.hxx>
|
|
#include <svx/xlineit0.hxx>
|
|
#include <svx/xlnclit.hxx>
|
|
#include <svx/xbtmpit.hxx>
|
|
#include <svx/xfillit0.hxx>
|
|
#include <svx/xflbmtit.hxx>
|
|
#include <svx/xflbstit.hxx>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
|
#include <editeng/outlobj.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
#include <rtl/ustrbuf.hxx>
|
|
#include <rtl/ref.hxx>
|
|
#include <bitmaps.hlst>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
static uno::Reference < beans::XPropertySet > lcl_getFrame_throw(const SdrOle2Obj* _pObject)
|
|
{
|
|
uno::Reference < beans::XPropertySet > xFrame;
|
|
if ( _pObject )
|
|
{
|
|
uno::Reference< frame::XController> xController = _pObject->GetParentXModel()->getCurrentController();
|
|
if ( xController.is() )
|
|
{
|
|
xFrame.set( xController->getFrame(),uno::UNO_QUERY_THROW);
|
|
}
|
|
} // if ( _pObject )
|
|
return xFrame;
|
|
}
|
|
|
|
namespace {
|
|
|
|
class SdrLightEmbeddedClient_Impl : public ::cppu::WeakImplHelper
|
|
< embed::XStateChangeListener
|
|
, document::XEventListener
|
|
, embed::XInplaceClient
|
|
, embed::XEmbeddedClient
|
|
, embed::XWindowSupplier
|
|
>
|
|
{
|
|
uno::Reference< awt::XWindow > m_xWindow;
|
|
SdrOle2Obj* mpObj;
|
|
|
|
double m_aScaleWidth { 0.0 };
|
|
double m_aScaleHeight { 0.0 };
|
|
|
|
|
|
public:
|
|
explicit SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj );
|
|
virtual ~SdrLightEmbeddedClient_Impl() override;
|
|
|
|
void SetSizeScale( double aScaleWidth, double aScaleHeight )
|
|
{
|
|
m_aScaleWidth = aScaleWidth;
|
|
m_aScaleHeight = aScaleHeight;
|
|
}
|
|
|
|
double GetScaleWidth() const { return m_aScaleWidth; }
|
|
double GetScaleHeight() const { return m_aScaleHeight; }
|
|
|
|
void setWindow(const uno::Reference< awt::XWindow >& _xWindow);
|
|
|
|
void disconnect();
|
|
private:
|
|
|
|
tools::Rectangle impl_getScaledRect_nothrow() const;
|
|
// XStateChangeListener
|
|
virtual void SAL_CALL changingState( const css::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
|
|
virtual void SAL_CALL stateChanged( const css::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
|
|
virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override;
|
|
|
|
// document::XEventListener
|
|
virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) override;
|
|
|
|
// XEmbeddedClient
|
|
virtual void SAL_CALL saveObject() override;
|
|
virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) override;
|
|
|
|
// XComponentSupplier
|
|
virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() override;
|
|
|
|
// XInplaceClient
|
|
virtual sal_Bool SAL_CALL canInplaceActivate() override;
|
|
virtual void SAL_CALL activatingInplace() override;
|
|
virtual void SAL_CALL activatingUI() override;
|
|
virtual void SAL_CALL deactivatedInplace() override;
|
|
virtual void SAL_CALL deactivatedUI() override;
|
|
virtual uno::Reference< css::frame::XLayoutManager > SAL_CALL getLayoutManager() override;
|
|
virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() override;
|
|
virtual awt::Rectangle SAL_CALL getPlacement() override;
|
|
virtual awt::Rectangle SAL_CALL getClipRectangle() override;
|
|
virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) override;
|
|
virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) override;
|
|
virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) override;
|
|
|
|
// XWindowSupplier
|
|
virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() override;
|
|
};
|
|
|
|
}
|
|
|
|
SdrLightEmbeddedClient_Impl::SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj )
|
|
: mpObj( pObj )
|
|
{
|
|
}
|
|
SdrLightEmbeddedClient_Impl::~SdrLightEmbeddedClient_Impl()
|
|
{
|
|
assert(!mpObj);
|
|
}
|
|
tools::Rectangle SdrLightEmbeddedClient_Impl::impl_getScaledRect_nothrow() const
|
|
{
|
|
tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
|
|
// apply scaling to object area and convert to pixels
|
|
aLogicRect.SetSize( Size( tools::Long( aLogicRect.GetWidth() * m_aScaleWidth),
|
|
tools::Long( aLogicRect.GetHeight() * m_aScaleHeight) ) );
|
|
return aLogicRect;
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::changingState( const css::lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ )
|
|
{
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::stateChanged( const css::lang::EventObject& /*aEvent*/, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if ( mpObj && nOldState == embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING )
|
|
{
|
|
mpObj->ObjectLoaded();
|
|
GetSdrGlobalData().GetOLEObjCache().InsertObj(mpObj);
|
|
}
|
|
else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING )
|
|
{
|
|
GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj);
|
|
}
|
|
}
|
|
|
|
void SdrLightEmbeddedClient_Impl::disconnect()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (!mpObj)
|
|
return;
|
|
GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj);
|
|
mpObj = nullptr;
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::disposing( const css::lang::EventObject& /*aEvent*/ )
|
|
{
|
|
disconnect();
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::notifyEvent( const document::EventObject& aEvent )
|
|
{
|
|
// TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
|
|
|
|
SolarMutexGuard aGuard;
|
|
|
|
// the code currently makes sense only in case there is no other client
|
|
if ( !(mpObj && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON && aEvent.EventName == "OnVisAreaChanged"
|
|
&& mpObj->GetObjRef().is() && mpObj->GetObjRef()->getClientSite() == uno::Reference< embed::XEmbeddedClient >( this )) )
|
|
return;
|
|
|
|
try
|
|
{
|
|
MapUnit aContainerMapUnit( MapUnit::Map100thMM );
|
|
uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY );
|
|
if ( xParentVis.is() )
|
|
aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
|
|
|
|
MapUnit aObjMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpObj->GetObjRef()->getMapUnit( mpObj->GetAspect() ) );
|
|
|
|
tools::Rectangle aVisArea;
|
|
awt::Size aSz;
|
|
try
|
|
{
|
|
aSz = mpObj->GetObjRef()->getVisualAreaSize( mpObj->GetAspect() );
|
|
}
|
|
catch( embed::NoVisualAreaSizeException& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION("svx.svdraw", "No visual area size!");
|
|
aSz.Width = 5000;
|
|
aSz.Height = 5000;
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION("svx.svdraw", "");
|
|
aSz.Width = 5000;
|
|
aSz.Height = 5000;
|
|
}
|
|
|
|
aVisArea.SetSize( Size( aSz.Width, aSz.Height ) );
|
|
aVisArea = OutputDevice::LogicToLogic(aVisArea, MapMode(aObjMapUnit), MapMode(aContainerMapUnit));
|
|
Size aScaledSize( static_cast< tools::Long >( m_aScaleWidth * aVisArea.GetWidth() ),
|
|
static_cast< tools::Long >( m_aScaleHeight * aVisArea.GetHeight() ) );
|
|
tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
|
|
|
|
// react to the change if the difference is bigger than one pixel
|
|
Size aPixelDiff =
|
|
Application::GetDefaultDevice()->LogicToPixel(
|
|
Size( aLogicRect.GetWidth() - aScaledSize.Width(),
|
|
aLogicRect.GetHeight() - aScaledSize.Height() ),
|
|
MapMode(aContainerMapUnit));
|
|
if( aPixelDiff.Width() || aPixelDiff.Height() )
|
|
{
|
|
mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aScaledSize ) );
|
|
mpObj->BroadcastObjectChange();
|
|
}
|
|
else
|
|
mpObj->ActionChanged();
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION("svx.svdraw", "");
|
|
}
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::saveObject()
|
|
{
|
|
// TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
|
|
uno::Reference< embed::XCommonEmbedPersist > xPersist;
|
|
uno::Reference< util::XModifiable > xModifiable;
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if ( !mpObj )
|
|
throw embed::ObjectSaveVetoException();
|
|
|
|
// the common persistence is supported by objects and links
|
|
xPersist.set( mpObj->GetObjRef(), uno::UNO_QUERY_THROW );
|
|
xModifiable.set( mpObj->GetParentXModel(), uno::UNO_QUERY );
|
|
}
|
|
|
|
xPersist->storeOwn();
|
|
|
|
if ( xModifiable.is() )
|
|
xModifiable->setModified( true );
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::visibilityChanged( sal_Bool /*bVisible*/ )
|
|
{
|
|
// nothing to do currently
|
|
// TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
|
|
if ( mpObj )
|
|
{
|
|
tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
|
|
Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() );
|
|
|
|
if( mpObj->IsChart() )
|
|
{
|
|
//charts never should be stretched see #i84323# for example
|
|
mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aLogicSize ) );
|
|
mpObj->BroadcastObjectChange();
|
|
} // if( mpObj->IsChart() )
|
|
}
|
|
}
|
|
|
|
uno::Reference< util::XCloseable > SAL_CALL SdrLightEmbeddedClient_Impl::getComponent()
|
|
{
|
|
uno::Reference< util::XCloseable > xResult;
|
|
|
|
SolarMutexGuard aGuard;
|
|
if ( mpObj )
|
|
xResult.set( mpObj->GetParentXModel(), uno::UNO_QUERY );
|
|
|
|
return xResult;
|
|
}
|
|
// XInplaceClient
|
|
|
|
sal_Bool SAL_CALL SdrLightEmbeddedClient_Impl::canInplaceActivate()
|
|
{
|
|
bool bRet = false;
|
|
SolarMutexGuard aGuard;
|
|
if ( mpObj )
|
|
{
|
|
uno::Reference< embed::XEmbeddedObject > xObject = mpObj->GetObjRef();
|
|
if ( !xObject.is() )
|
|
throw uno::RuntimeException();
|
|
// we don't want to switch directly from outplace to inplace mode
|
|
bRet = ( xObject->getCurrentState() != embed::EmbedStates::ACTIVE && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON );
|
|
} // if ( mpObj )
|
|
return bRet;
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::activatingInplace()
|
|
{
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::activatingUI()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj));
|
|
uno::Reference < frame::XFrame > xOwnFrame( xFrame,uno::UNO_QUERY);
|
|
uno::Reference < frame::XFramesSupplier > xParentFrame = xOwnFrame->getCreator();
|
|
if ( xParentFrame.is() )
|
|
xParentFrame->setActiveFrame( xOwnFrame );
|
|
|
|
OLEObjCache& rObjCache = GetSdrGlobalData().GetOLEObjCache();
|
|
const size_t nCount = rObjCache.size();
|
|
for(sal_Int32 i = nCount-1 ; i >= 0;--i)
|
|
{
|
|
SdrOle2Obj* pObj = rObjCache[i];
|
|
if ( pObj != mpObj )
|
|
{
|
|
// only deactivate ole objects which belongs to the same frame
|
|
if ( xFrame == lcl_getFrame_throw(pObj) )
|
|
{
|
|
const uno::Reference< embed::XEmbeddedObject >& xObject = pObj->GetObjRef();
|
|
try
|
|
{
|
|
if ( xObject->getStatus( pObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
|
|
xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
|
|
else
|
|
{
|
|
// the links should not stay in running state for long time because of locking
|
|
uno::Reference< embed::XLinkageSupport > xLink( xObject, uno::UNO_QUERY );
|
|
if ( xLink.is() && xLink->isLink() )
|
|
xObject->changeState( embed::EmbedStates::LOADED );
|
|
else
|
|
xObject->changeState( embed::EmbedStates::RUNNING );
|
|
}
|
|
}
|
|
catch (css::uno::Exception& )
|
|
{}
|
|
}
|
|
}
|
|
} // for(sal_Int32 i = nCount-1 ; i >= 0;--i)
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedInplace()
|
|
{
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedUI()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
css::uno::Reference< css::frame::XLayoutManager > xLayoutManager(getLayoutManager());
|
|
if ( xLayoutManager.is() )
|
|
{
|
|
static constexpr OUString aMenuBarURL = u"private:resource/menubar/menubar"_ustr;
|
|
if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
|
|
xLayoutManager->createElement( aMenuBarURL );
|
|
}
|
|
}
|
|
|
|
uno::Reference< css::frame::XLayoutManager > SAL_CALL SdrLightEmbeddedClient_Impl::getLayoutManager()
|
|
{
|
|
uno::Reference< css::frame::XLayoutManager > xMan;
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj));
|
|
try
|
|
{
|
|
xMan.set(xFrame->getPropertyValue(u"LayoutManager"_ustr),uno::UNO_QUERY);
|
|
}
|
|
catch ( uno::Exception& ex )
|
|
{
|
|
css::uno::Any anyEx = cppu::getCaughtException();
|
|
throw css::lang::WrappedTargetRuntimeException( ex.Message,
|
|
nullptr, anyEx );
|
|
}
|
|
|
|
return xMan;
|
|
}
|
|
|
|
uno::Reference< frame::XDispatchProvider > SAL_CALL SdrLightEmbeddedClient_Impl::getInplaceDispatchProvider()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return uno::Reference < frame::XDispatchProvider >( lcl_getFrame_throw(mpObj), uno::UNO_QUERY_THROW );
|
|
}
|
|
|
|
awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getPlacement()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ( !mpObj )
|
|
throw uno::RuntimeException();
|
|
|
|
tools::Rectangle aLogicRect = impl_getScaledRect_nothrow();
|
|
MapUnit aContainerMapUnit( MapUnit::Map100thMM );
|
|
uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY );
|
|
if ( xParentVis.is() )
|
|
aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
|
|
|
|
aLogicRect = Application::GetDefaultDevice()->LogicToPixel(aLogicRect, MapMode(aContainerMapUnit));
|
|
return vcl::unohelper::ConvertToAWTRect(aLogicRect);
|
|
}
|
|
|
|
awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getClipRectangle()
|
|
{
|
|
return getPlacement();
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ )
|
|
{
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::scrollObject( const awt::Size& /*aOffset*/ )
|
|
{
|
|
}
|
|
|
|
void SAL_CALL SdrLightEmbeddedClient_Impl::changedPlacement( const awt::Rectangle& aPosRect )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ( !mpObj )
|
|
throw uno::RuntimeException();
|
|
|
|
uno::Reference< embed::XInplaceObject > xInplace( mpObj->GetObjRef(), uno::UNO_QUERY_THROW );
|
|
|
|
// check if the change is at least one pixel in size
|
|
awt::Rectangle aOldRect = getPlacement();
|
|
tools::Rectangle aNewPixelRect = vcl::unohelper::ConvertToVCLRect(aPosRect);
|
|
tools::Rectangle aOldPixelRect = vcl::unohelper::ConvertToVCLRect(aOldRect);
|
|
if ( aOldPixelRect == aNewPixelRect )
|
|
// nothing has changed
|
|
return;
|
|
|
|
// new scaled object area
|
|
MapUnit aContainerMapUnit( MapUnit::Map100thMM );
|
|
uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY );
|
|
if ( xParentVis.is() )
|
|
aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
|
|
|
|
tools::Rectangle aNewLogicRect = Application::GetDefaultDevice()->PixelToLogic(aNewPixelRect, MapMode(aContainerMapUnit));
|
|
tools::Rectangle aLogicRect = impl_getScaledRect_nothrow();
|
|
|
|
if ( aNewLogicRect == aLogicRect )
|
|
return;
|
|
|
|
// the calculation of the object area has not changed the object size
|
|
// it should be done here then
|
|
//SfxBooleanFlagGuard aGuard( m_bResizeNoScale, true );
|
|
|
|
// new size of the object area without scaling
|
|
Size aNewObjSize( tools::Long( aNewLogicRect.GetWidth() / m_aScaleWidth ),
|
|
tools::Long( aNewLogicRect.GetHeight() / m_aScaleHeight ) );
|
|
|
|
// now remove scaling from new placement and keep this at the new object area
|
|
aNewLogicRect.SetSize( aNewObjSize );
|
|
// react to the change if the difference is bigger than one pixel
|
|
Size aPixelDiff =
|
|
Application::GetDefaultDevice()->LogicToPixel(
|
|
Size( aLogicRect.GetWidth() - aNewObjSize.Width(),
|
|
aLogicRect.GetHeight() - aNewObjSize.Height() ),
|
|
MapMode(aContainerMapUnit));
|
|
if( aPixelDiff.Width() || aPixelDiff.Height() )
|
|
{
|
|
mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aNewObjSize ) );
|
|
mpObj->BroadcastObjectChange();
|
|
}
|
|
else
|
|
mpObj->ActionChanged();
|
|
}
|
|
// XWindowSupplier
|
|
|
|
uno::Reference< awt::XWindow > SAL_CALL SdrLightEmbeddedClient_Impl::getWindow()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference< awt::XWindow > xCurrent = m_xWindow;
|
|
if ( !xCurrent.is() )
|
|
{
|
|
if ( !mpObj )
|
|
throw uno::RuntimeException();
|
|
uno::Reference< frame::XFrame> xFrame(lcl_getFrame_throw(mpObj),uno::UNO_QUERY_THROW);
|
|
xCurrent = xFrame->getComponentWindow();
|
|
} // if ( !xCurrent.is() )
|
|
return xCurrent;
|
|
}
|
|
void SdrLightEmbeddedClient_Impl::setWindow(const uno::Reference< awt::XWindow >& _xWindow)
|
|
{
|
|
m_xWindow = _xWindow;
|
|
}
|
|
|
|
SdrEmbedObjectLink::SdrEmbedObjectLink(SdrOle2Obj* pObject):
|
|
::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB ),
|
|
m_pObj(pObject)
|
|
{
|
|
SetSynchron( false );
|
|
}
|
|
|
|
SdrEmbedObjectLink::~SdrEmbedObjectLink()
|
|
{
|
|
}
|
|
|
|
::sfx2::SvBaseLink::UpdateResult SdrEmbedObjectLink::DataChanged(
|
|
const OUString& /*rMimeType*/, const css::uno::Any & /*rValue*/ )
|
|
{
|
|
// Deferred link: the object was not created during import because link
|
|
// updates were not yet allowed, complete the creation now.
|
|
if (m_pObj->CompleteDeferredLink())
|
|
{
|
|
m_pObj->GetNewReplacement();
|
|
m_pObj->SetChanged();
|
|
return SUCCESS;
|
|
}
|
|
|
|
if ( !m_pObj->UpdateLinkURL_Impl() )
|
|
{
|
|
// the link URL was not changed
|
|
uno::Reference< embed::XEmbeddedObject > xObject = m_pObj->GetObjRef();
|
|
OSL_ENSURE( xObject.is(), "The object must exist always!" );
|
|
if ( xObject.is() )
|
|
{
|
|
// let the object reload the link
|
|
// TODO/LATER: reload call could be used for this case
|
|
|
|
try
|
|
{
|
|
sal_Int32 nState = xObject->getCurrentState();
|
|
if ( nState != embed::EmbedStates::LOADED )
|
|
{
|
|
// in some cases the linked file probably is not locked so it could be changed
|
|
xObject->changeState( embed::EmbedStates::LOADED );
|
|
xObject->changeState( nState );
|
|
}
|
|
}
|
|
catch ( uno::Exception& )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pObj->GetNewReplacement();
|
|
m_pObj->SetChanged();
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
void SdrEmbedObjectLink::Closed()
|
|
{
|
|
m_pObj->BreakFileLink_Impl();
|
|
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:
|
|
svt::EmbeddedObjectRef mxObjRef;
|
|
|
|
std::optional<Graphic> moGraphic;
|
|
OUString maProgName;
|
|
OUString aPersistName; // name of object in persist
|
|
rtl::Reference<SdrLightEmbeddedClient_Impl> mxLightClient; // must be registered as client only using AddOwnLightClient() call
|
|
|
|
bool mbFrame:1; // Due to compatibility at SdrTextObj for now
|
|
bool mbSuppressSetVisAreaSize:1; // #i118524#
|
|
mutable bool mbTypeAsked:1;
|
|
mutable bool mbIsChart:1;
|
|
bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated loading if load of OLE2 fails
|
|
bool mbConnected:1;
|
|
bool mbIgnoreOLEObjectScale : 1 = false; // See SdXMLObjectShapeContext::createFastChildContext
|
|
|
|
sfx2::SvBaseLink* mpObjectLink;
|
|
OUString maLinkURL;
|
|
|
|
// Stored when a linked OLE object is deferred during import because
|
|
// link updates are not yet allowed, used to complete creation later.
|
|
css::uno::Sequence<css::beans::PropertyValue> maDeferredMediaDescriptor;
|
|
|
|
rtl::Reference<SvxUnoShapeModifyListener> mxModifyListener;
|
|
|
|
explicit SdrOle2ObjImpl( bool bFrame ) :
|
|
mbFrame(bFrame),
|
|
mbSuppressSetVisAreaSize(false),
|
|
mbTypeAsked(false),
|
|
mbIsChart(false),
|
|
mbLoadingOLEObjectFailed(false),
|
|
mbConnected(false),
|
|
mpObjectLink(nullptr)
|
|
{
|
|
mxObjRef.Lock();
|
|
}
|
|
|
|
SdrOle2ObjImpl( bool bFrame, const svt::EmbeddedObjectRef& rObjRef ) :
|
|
mxObjRef(rObjRef),
|
|
mbFrame(bFrame),
|
|
mbSuppressSetVisAreaSize(false),
|
|
mbTypeAsked(false),
|
|
mbIsChart(false),
|
|
mbLoadingOLEObjectFailed(false),
|
|
mbConnected(false),
|
|
mpObjectLink(nullptr)
|
|
{
|
|
mxObjRef.Lock();
|
|
}
|
|
|
|
~SdrOle2ObjImpl()
|
|
{
|
|
moGraphic.reset();
|
|
|
|
if (mxModifyListener.is())
|
|
{
|
|
mxModifyListener->invalidate();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Predicate determining whether the given OLE is an internal math
|
|
// object
|
|
static bool ImplIsMathObj( const uno::Reference < embed::XEmbeddedObject >& rObjRef )
|
|
{
|
|
if ( !rObjRef.is() )
|
|
return false;
|
|
|
|
SvGlobalName aClassName( rObjRef->getClassID() );
|
|
return aClassName == SvGlobalName(SO3_SM_CLASSID_30) ||
|
|
aClassName == SvGlobalName(SO3_SM_CLASSID_40) ||
|
|
aClassName == SvGlobalName(SO3_SM_CLASSID_50) ||
|
|
aClassName == SvGlobalName(SO3_SM_CLASSID_60) ||
|
|
aClassName == SvGlobalName(SO3_SM_CLASSID);
|
|
}
|
|
|
|
// BaseProperties section
|
|
|
|
std::unique_ptr<sdr::properties::BaseProperties> SdrOle2Obj::CreateObjectSpecificProperties()
|
|
{
|
|
return std::make_unique<sdr::properties::OleProperties>(*this);
|
|
}
|
|
|
|
// DrawContact section
|
|
|
|
std::unique_ptr<sdr::contact::ViewContact> SdrOle2Obj::CreateObjectSpecificViewContact()
|
|
{
|
|
return std::make_unique<sdr::contact::ViewContactOfSdrOle2Obj>(*this);
|
|
}
|
|
|
|
void SdrOle2Obj::Init()
|
|
{
|
|
// Stuff that was done from old SetModel:
|
|
// #i43086# #i85304 redo the change for charts for the above bugfix, as #i43086# does not occur anymore
|
|
// so maybe the ImpSetVisAreaSize call can be removed here completely
|
|
// Nevertheless I leave it in for other objects as I am not sure about the side effects when removing now
|
|
if(!getSdrModelFromSdrObject().isLocked() && !IsChart())
|
|
{
|
|
ImpSetVisAreaSize();
|
|
}
|
|
|
|
::comphelper::IEmbeddedHelper* pDestPers(getSdrModelFromSdrObject().GetPersist());
|
|
if(pDestPers && !IsEmptyPresObj())
|
|
{
|
|
// object wasn't connected, now it should be
|
|
Connect_Impl();
|
|
}
|
|
|
|
AddListeners_Impl();
|
|
}
|
|
|
|
SdrOle2Obj::SdrOle2Obj(
|
|
SdrModel& rSdrModel,
|
|
bool bFrame_)
|
|
: SdrRectObj(rSdrModel),
|
|
mpImpl(new SdrOle2ObjImpl(bFrame_))
|
|
{
|
|
Init();
|
|
}
|
|
|
|
SdrOle2Obj::SdrOle2Obj(SdrModel& rSdrModel, SdrOle2Obj const & rSource)
|
|
: SdrRectObj(rSdrModel, rSource),
|
|
mpImpl(new SdrOle2ObjImpl(/*bFrame*/false))
|
|
{
|
|
Init();
|
|
|
|
// Manually copying bClosedObj attribute
|
|
SetClosedObj( rSource.IsClosedObj() );
|
|
|
|
mpImpl->aPersistName = rSource.mpImpl->aPersistName;
|
|
mpImpl->maProgName = rSource.mpImpl->maProgName;
|
|
mpImpl->mbFrame = rSource.mpImpl->mbFrame;
|
|
|
|
if (rSource.mpImpl->moGraphic)
|
|
{
|
|
mpImpl->moGraphic.emplace(*rSource.mpImpl->moGraphic);
|
|
}
|
|
|
|
if( IsEmptyPresObj() )
|
|
return;
|
|
|
|
::comphelper::IEmbeddedHelper* pDestPers(getSdrModelFromSdrObject().GetPersist());
|
|
::comphelper::IEmbeddedHelper* pSrcPers(rSource.getSdrModelFromSdrObject().GetPersist());
|
|
if( !(pDestPers && pSrcPers) )
|
|
return;
|
|
|
|
DBG_ASSERT( !mpImpl->mxObjRef.is(), "Object already existing!" );
|
|
comphelper::EmbeddedObjectContainer& rContainer = pSrcPers->getEmbeddedObjectContainer();
|
|
uno::Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( mpImpl->aPersistName );
|
|
if ( xObj.is() )
|
|
{
|
|
OUString aTmp;
|
|
mpImpl->mxObjRef.Assign( pDestPers->getEmbeddedObjectContainer().CopyAndGetEmbeddedObject(
|
|
rContainer, xObj, aTmp, pSrcPers->getDocumentBaseURL(), pDestPers->getDocumentBaseURL()), rSource.GetAspect());
|
|
mpImpl->mbTypeAsked = false;
|
|
mpImpl->aPersistName = aTmp;
|
|
CheckFileLink_Impl();
|
|
}
|
|
|
|
Connect();
|
|
}
|
|
|
|
SdrOle2Obj::SdrOle2Obj(
|
|
SdrModel& rSdrModel,
|
|
const svt::EmbeddedObjectRef& rNewObjRef,
|
|
const OUString& rNewObjName,
|
|
const tools::Rectangle& rNewRect)
|
|
: SdrRectObj(rSdrModel, rNewRect),
|
|
mpImpl(new SdrOle2ObjImpl(false/*bFrame_*/, rNewObjRef))
|
|
{
|
|
osl_atomic_increment(&m_refCount);
|
|
|
|
mpImpl->aPersistName = rNewObjName;
|
|
|
|
if (mpImpl->mxObjRef.is() && (mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
|
|
m_bSizProt = true;
|
|
|
|
// For math objects, set closed state to transparent
|
|
SetClosedObj(!ImplIsMathObj( mpImpl->mxObjRef.GetObject() ));
|
|
|
|
Init();
|
|
|
|
osl_atomic_decrement(&m_refCount);
|
|
}
|
|
|
|
OUString SdrOle2Obj::GetStyleString()
|
|
{
|
|
OUString strStyle;
|
|
if (mpImpl->mxObjRef.is() && mpImpl->mxObjRef.IsChart())
|
|
{
|
|
strStyle = mpImpl->mxObjRef.GetChartType();
|
|
}
|
|
return strStyle;
|
|
}
|
|
|
|
SdrOle2Obj::~SdrOle2Obj()
|
|
{
|
|
if ( mpImpl->mbConnected )
|
|
Disconnect();
|
|
|
|
DisconnectFileLink_Impl();
|
|
|
|
if (mpImpl->mxLightClient)
|
|
{
|
|
mpImpl->mxLightClient->disconnect();
|
|
mpImpl->mxLightClient.clear();
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::SetAspect( sal_Int64 nAspect )
|
|
{
|
|
mpImpl->mxObjRef.SetViewAspect( nAspect );
|
|
}
|
|
|
|
const svt::EmbeddedObjectRef& SdrOle2Obj::getEmbeddedObjectRef() const
|
|
{
|
|
return mpImpl->mxObjRef;
|
|
}
|
|
|
|
sal_Int64 SdrOle2Obj::GetAspect() const
|
|
{
|
|
return mpImpl->mxObjRef.GetViewAspect();
|
|
}
|
|
|
|
bool SdrOle2Obj::isInplaceActive() const
|
|
{
|
|
return mpImpl->mxObjRef.is() && embed::EmbedStates::INPLACE_ACTIVE == mpImpl->mxObjRef->getCurrentState();
|
|
}
|
|
|
|
bool SdrOle2Obj::isUiActive() const
|
|
{
|
|
return mpImpl->mxObjRef.is() && embed::EmbedStates::UI_ACTIVE == mpImpl->mxObjRef->getCurrentState();
|
|
}
|
|
|
|
void SdrOle2Obj::SetGraphic(const Graphic& rGrf)
|
|
{
|
|
// only for setting a preview graphic
|
|
mpImpl->moGraphic.emplace(rGrf);
|
|
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
}
|
|
|
|
void SdrOle2Obj::ClearGraphic()
|
|
{
|
|
mpImpl->moGraphic.reset();
|
|
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
}
|
|
|
|
void SdrOle2Obj::SetProgName( const OUString& rName )
|
|
{
|
|
mpImpl->maProgName = rName;
|
|
}
|
|
|
|
const OUString& SdrOle2Obj::GetProgName() const
|
|
{
|
|
return mpImpl->maProgName;
|
|
}
|
|
|
|
bool SdrOle2Obj::IsEmpty() const
|
|
{
|
|
return !mpImpl->mxObjRef.is();
|
|
}
|
|
|
|
void SdrOle2Obj::Connect(SvxOle2Shape* pCreator)
|
|
{
|
|
if( IsEmptyPresObj() )
|
|
return;
|
|
|
|
if( mpImpl->mbConnected )
|
|
{
|
|
// currently there are situations where it seems to be unavoidable to have multiple connects
|
|
// changing this would need a larger code rewrite, so for now I remove the assertion
|
|
// OSL_FAIL("Connect() called on connected object!");
|
|
return;
|
|
}
|
|
|
|
Connect_Impl(pCreator);
|
|
AddListeners_Impl();
|
|
}
|
|
|
|
bool SdrOle2Obj::UpdateLinkURL_Impl()
|
|
{
|
|
bool bResult = false;
|
|
|
|
if ( mpImpl->mpObjectLink )
|
|
{
|
|
sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
|
|
|
|
if ( pLinkManager )
|
|
{
|
|
OUString aNewLinkURL;
|
|
sfx2::LinkManager::GetDisplayNames( mpImpl->mpObjectLink, nullptr, &aNewLinkURL );
|
|
if ( !aNewLinkURL.equalsIgnoreAsciiCase( mpImpl->maLinkURL ) )
|
|
{
|
|
GetObjRef_Impl();
|
|
uno::Reference<embed::XCommonEmbedPersist> xPersObj( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
|
|
OSL_ENSURE( xPersObj.is(), "The object must exist!" );
|
|
if ( xPersObj.is() )
|
|
{
|
|
try
|
|
{
|
|
sal_Int32 nCurState = mpImpl->mxObjRef->getCurrentState();
|
|
if ( nCurState != embed::EmbedStates::LOADED )
|
|
mpImpl->mxObjRef->changeState(embed::EmbedStates::LOADED);
|
|
|
|
// TODO/LATER: there should be possible to get current mediadescriptor settings from the object
|
|
uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
|
|
u"URL"_ustr, aNewLinkURL) };
|
|
xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() );
|
|
|
|
mpImpl->maLinkURL = aNewLinkURL;
|
|
bResult = true;
|
|
|
|
if ( nCurState != embed::EmbedStates::LOADED )
|
|
mpImpl->mxObjRef->changeState(nCurState);
|
|
}
|
|
catch( css::uno::Exception const & )
|
|
{
|
|
TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::UpdateLinkURL_Impl()" );
|
|
}
|
|
}
|
|
|
|
if ( !bResult )
|
|
{
|
|
// TODO/LATER: return the old name to the link manager, is it possible?
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
void SdrOle2Obj::BreakFileLink_Impl()
|
|
{
|
|
uno::Reference<document::XStorageBasedDocument> xDoc(getSdrModelFromSdrObject().getUnoModel(), uno::UNO_QUERY);
|
|
|
|
if ( !xDoc.is() )
|
|
return;
|
|
|
|
uno::Reference< embed::XStorage > xStorage = xDoc->getDocumentStorage();
|
|
if ( !xStorage.is() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
uno::Reference< embed::XLinkageSupport > xLinkSupport( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY_THROW );
|
|
xLinkSupport->breakLink( xStorage, mpImpl->aPersistName );
|
|
DisconnectFileLink_Impl();
|
|
mpImpl->maLinkURL.clear();
|
|
}
|
|
catch( css::uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::BreakFileLink_Impl()" );
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::DisconnectFileLink_Impl()
|
|
{
|
|
sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
|
|
|
|
if ( pLinkManager && mpImpl->mpObjectLink )
|
|
{
|
|
pLinkManager->Remove( mpImpl->mpObjectLink );
|
|
mpImpl->mpObjectLink = nullptr;
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::CheckFileLink_Impl()
|
|
{
|
|
if (!mpImpl->mxObjRef.GetObject().is() || mpImpl->mpObjectLink)
|
|
return;
|
|
|
|
try
|
|
{
|
|
uno::Reference<embed::XEmbeddedObject> xObject = mpImpl->mxObjRef.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
|
|
{
|
|
// 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(u"FrameURL"_ustr) >>= 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 )
|
|
{
|
|
SdrEmbedObjectLink* pEmbedObjectLink = nullptr;
|
|
if (!bIFrame)
|
|
{
|
|
pEmbedObjectLink = new SdrEmbedObjectLink(this);
|
|
mpImpl->mpObjectLink = pEmbedObjectLink;
|
|
}
|
|
else
|
|
mpImpl->mpObjectLink = new SdrIFrameLink(this);
|
|
mpImpl->maLinkURL = aLinkURL;
|
|
pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
|
|
if (pEmbedObjectLink)
|
|
pEmbedObjectLink->Connect();
|
|
}
|
|
}
|
|
}
|
|
catch (const css::uno::Exception&)
|
|
{
|
|
TOOLS_WARN_EXCEPTION("svx", "SdrOle2Obj::CheckFileLink_Impl()");
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::SetDeferredLink(const OUString& rLinkURL,
|
|
const uno::Sequence<beans::PropertyValue>& rMediaDescriptor)
|
|
{
|
|
if (mpImpl->mpObjectLink)
|
|
return;
|
|
|
|
mpImpl->maLinkURL = rLinkURL;
|
|
mpImpl->maDeferredMediaDescriptor = rMediaDescriptor;
|
|
|
|
sfx2::LinkManager* pLinkManager = getSdrModelFromSdrObject().GetLinkManager();
|
|
if (!pLinkManager)
|
|
return;
|
|
|
|
mpImpl->mpObjectLink = new SdrEmbedObjectLink(this);
|
|
pLinkManager->InsertFileLink(*mpImpl->mpObjectLink,
|
|
sfx2::SvBaseLinkObjectType::ClientOle, mpImpl->maLinkURL);
|
|
}
|
|
|
|
bool SdrOle2Obj::CompleteDeferredLink()
|
|
{
|
|
if (!mpImpl->maDeferredMediaDescriptor.hasElements())
|
|
return false;
|
|
|
|
// take ownership of the descriptor and clear it so we don't retry
|
|
uno::Sequence<beans::PropertyValue> aMediaDescriptor;
|
|
std::swap(aMediaDescriptor, mpImpl->maDeferredMediaDescriptor);
|
|
|
|
::comphelper::IEmbeddedHelper* pPersist = getSdrModelFromSdrObject().GetPersist();
|
|
if (!pPersist)
|
|
return false;
|
|
|
|
OUString aPersistName;
|
|
uno::Reference<embed::XEmbeddedObject> xObj =
|
|
pPersist->getEmbeddedObjectContainer().InsertEmbeddedLink(
|
|
aMediaDescriptor, aPersistName);
|
|
if (!xObj.is())
|
|
return false;
|
|
|
|
SyncObjVisualArea(xObj);
|
|
|
|
SetObjRef(xObj);
|
|
SetPersistName(aPersistName);
|
|
SetChanged();
|
|
return true;
|
|
}
|
|
|
|
void SdrOle2Obj::SyncObjVisualArea(const uno::Reference<embed::XEmbeddedObject>& xObj)
|
|
{
|
|
tools::Rectangle aRect = GetLogicRect();
|
|
if (aRect.GetWidth() == 101 && aRect.GetHeight() == 101)
|
|
{
|
|
// default size, take it from the OLE
|
|
try
|
|
{
|
|
awt::Size aSz = xObj->getVisualAreaSize(GetAspect());
|
|
aRect.SetSize(Size(aSz.Width, aSz.Height));
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
TOOLS_WARN_EXCEPTION("svx.svdraw", "");
|
|
}
|
|
SetLogicRect(aRect);
|
|
}
|
|
else
|
|
{
|
|
Size aSize = aRect.GetSize();
|
|
awt::Size aSz(aSize.Width(), aSize.Height());
|
|
try
|
|
{
|
|
xObj->setVisualAreaSize(GetAspect(), aSz);
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
TOOLS_WARN_EXCEPTION("svx.svdraw", "");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SdrOle2Obj::HasDeferredLink() const
|
|
{
|
|
return mpImpl->maDeferredMediaDescriptor.hasElements();
|
|
}
|
|
|
|
void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator)
|
|
{
|
|
if(mpImpl->aPersistName.isEmpty() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
::comphelper::IEmbeddedHelper* pPers(getSdrModelFromSdrObject().GetPersist());
|
|
|
|
if ( pPers )
|
|
{
|
|
comphelper::EmbeddedObjectContainer& rContainer = pPers->getEmbeddedObjectContainer();
|
|
|
|
if ( !rContainer.HasEmbeddedObject( mpImpl->aPersistName )
|
|
|| ( mpImpl->mxObjRef.is() && !rContainer.HasEmbeddedObject( mpImpl->mxObjRef.GetObject() ) ) )
|
|
{
|
|
// object not known to container document
|
|
// No object -> disaster!
|
|
DBG_ASSERT( mpImpl->mxObjRef.is(), "No object in connect!");
|
|
if ( mpImpl->mxObjRef.is() )
|
|
{
|
|
// object came from the outside, now add it to the container
|
|
OUString aTmp;
|
|
rContainer.InsertEmbeddedObject( mpImpl->mxObjRef.GetObject(), aTmp );
|
|
mpImpl->aPersistName = aTmp;
|
|
}
|
|
}
|
|
else if ( !mpImpl->mxObjRef.is() )
|
|
{
|
|
mpImpl->mxObjRef.Assign( rContainer.GetEmbeddedObject( mpImpl->aPersistName ), mpImpl->mxObjRef.GetViewAspect() );
|
|
mpImpl->mbTypeAsked = false;
|
|
}
|
|
|
|
if ( mpImpl->mxObjRef.GetObject().is() )
|
|
{
|
|
mpImpl->mxObjRef.AssignToContainer( &rContainer, mpImpl->aPersistName );
|
|
mpImpl->mbConnected = true;
|
|
mpImpl->mxObjRef.Lock();
|
|
}
|
|
}
|
|
|
|
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(u"FrameURL"_ustr, uno::Any(sFrameURL));
|
|
}
|
|
}
|
|
|
|
if ( mpImpl->mxObjRef.is() )
|
|
{
|
|
if ( !mpImpl->mxLightClient.is() )
|
|
mpImpl->mxLightClient = new SdrLightEmbeddedClient_Impl( this );
|
|
|
|
mpImpl->mxObjRef->addStateChangeListener( mpImpl->mxLightClient );
|
|
mpImpl->mxObjRef->addEventListener( mpImpl->mxLightClient );
|
|
|
|
if ( mpImpl->mxObjRef->getCurrentState() != embed::EmbedStates::LOADED )
|
|
GetSdrGlobalData().GetOLEObjCache().InsertObj(this);
|
|
|
|
CheckFileLink_Impl();
|
|
|
|
uno::Reference< container::XChild > xChild( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
|
|
if( xChild.is() )
|
|
{
|
|
uno::Reference< uno::XInterface > xParent( getSdrModelFromSdrObject().getUnoModel());
|
|
if( xParent.is())
|
|
xChild->setParent( getSdrModelFromSdrObject().getUnoModel() );
|
|
}
|
|
|
|
}
|
|
}
|
|
catch( css::uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::Connect_Impl()" );
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::ObjectLoaded()
|
|
{
|
|
AddListeners_Impl();
|
|
}
|
|
|
|
void SdrOle2Obj::AddListeners_Impl()
|
|
{
|
|
if( !(mpImpl->mxObjRef.is() && mpImpl->mxObjRef->getCurrentState() != embed::EmbedStates::LOADED) )
|
|
return;
|
|
|
|
// register modify listener
|
|
if (!mpImpl->mxModifyListener.is())
|
|
{
|
|
mpImpl->mxModifyListener = new SvxUnoShapeModifyListener(this);
|
|
}
|
|
|
|
uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY );
|
|
if (xBC.is())
|
|
{
|
|
xBC->addModifyListener( mpImpl->mxModifyListener );
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::Disconnect()
|
|
{
|
|
if( IsEmptyPresObj() )
|
|
return;
|
|
|
|
if( !mpImpl->mbConnected )
|
|
{
|
|
OSL_FAIL("Disconnect() called on disconnected object!");
|
|
return;
|
|
}
|
|
|
|
RemoveListeners_Impl();
|
|
Disconnect_Impl();
|
|
}
|
|
|
|
void SdrOle2Obj::RemoveListeners_Impl()
|
|
{
|
|
if ( !mpImpl->mxObjRef.is() || mpImpl->aPersistName.isEmpty() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
sal_Int32 nState = mpImpl->mxObjRef->getCurrentState();
|
|
if ( nState != embed::EmbedStates::LOADED )
|
|
{
|
|
uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY );
|
|
if (xBC.is() && mpImpl->mxModifyListener.is())
|
|
{
|
|
xBC->removeModifyListener( mpImpl->mxModifyListener );
|
|
}
|
|
}
|
|
}
|
|
catch( css::uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::RemoveListeners_Impl()" );
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::Disconnect_Impl()
|
|
{
|
|
try
|
|
{
|
|
if ( !mpImpl->aPersistName.isEmpty() )
|
|
{
|
|
if( getSdrModelFromSdrObject().IsInDestruction() )
|
|
{
|
|
// TODO/LATER: here we must assume that the destruction of the model is enough to make clear that we will not
|
|
// remove the object from the container, even if the DrawingObject itself is not destroyed (unfortunately this
|
|
// There is no real need to do the following removing of the object from the container
|
|
// in case the model has correct persistence, but in case of problems such a removing
|
|
// would make the behavior of the office more stable
|
|
|
|
comphelper::EmbeddedObjectContainer* pContainer = mpImpl->mxObjRef.GetContainer();
|
|
if ( pContainer )
|
|
{
|
|
pContainer->CloseEmbeddedObject( mpImpl->mxObjRef.GetObject() );
|
|
mpImpl->mxObjRef.AssignToContainer( nullptr, mpImpl->aPersistName );
|
|
}
|
|
|
|
// happens later than the destruction of the model, so we can't assert that).
|
|
//DBG_ASSERT( bInDestruction, "Model is destroyed, but not me?!" );
|
|
//TODO/LATER: should be make sure that the ObjectShell also forgets the object, because we will close it soon?
|
|
/*
|
|
uno::Reference < util::XCloseable > xClose( xObjRef, uno::UNO_QUERY );
|
|
if ( xClose.is() )
|
|
{
|
|
try
|
|
{
|
|
xClose->close( true );
|
|
}
|
|
catch ( util::CloseVetoException& )
|
|
{
|
|
// there's still someone who needs the object!
|
|
}
|
|
}
|
|
|
|
xObjRef = NULL;*/
|
|
}
|
|
else if ( mpImpl->mxObjRef.is() )
|
|
{
|
|
if ( getSdrModelFromSdrObject().getUnoModel().is() )
|
|
{
|
|
// remove object, but don't close it (that's up to someone else)
|
|
comphelper::EmbeddedObjectContainer* pContainer = mpImpl->mxObjRef.GetContainer();
|
|
if ( pContainer )
|
|
{
|
|
pContainer->RemoveEmbeddedObject( mpImpl->mxObjRef.GetObject() );
|
|
|
|
// TODO/LATER: mpImpl->aPersistName contains outdated information, to keep it updated
|
|
// it should be returned from RemoveEmbeddedObject call. Currently it is no problem,
|
|
// since no container is adjusted, actually the empty string could be provided as a name here
|
|
mpImpl->mxObjRef.AssignToContainer( nullptr, mpImpl->aPersistName );
|
|
}
|
|
|
|
DisconnectFileLink_Impl();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( mpImpl->mxObjRef.is() && mpImpl->mxLightClient.is() )
|
|
{
|
|
mpImpl->mxObjRef->removeStateChangeListener ( mpImpl->mxLightClient );
|
|
mpImpl->mxObjRef->removeEventListener( mpImpl->mxLightClient );
|
|
mpImpl->mxObjRef->setClientSite( nullptr );
|
|
|
|
GetSdrGlobalData().GetOLEObjCache().RemoveObj(this);
|
|
}
|
|
}
|
|
catch( css::uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::Disconnect_Impl()" );
|
|
}
|
|
|
|
mpImpl->mbConnected = false;
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrOle2Obj::createSdrGrafObjReplacement(bool bAddText) const
|
|
{
|
|
const Graphic* pOLEGraphic = GetGraphic();
|
|
|
|
if(pOLEGraphic)
|
|
{
|
|
// #i118485# allow creating a SdrGrafObj representation
|
|
rtl::Reference<SdrGrafObj> pClone = new SdrGrafObj(
|
|
getSdrModelFromSdrObject(),
|
|
*pOLEGraphic);
|
|
|
|
// copy transformation
|
|
basegfx::B2DHomMatrix aMatrix;
|
|
basegfx::B2DPolyPolygon aPolyPolygon;
|
|
|
|
TRGetBaseGeometry(aMatrix, aPolyPolygon);
|
|
pClone->TRSetBaseGeometry(aMatrix, aPolyPolygon);
|
|
|
|
// copy all attributes to support graphic styles for OLEs
|
|
pClone->SetStyleSheet(GetStyleSheet(), false);
|
|
pClone->SetMergedItemSet(GetMergedItemSet());
|
|
|
|
if(bAddText)
|
|
{
|
|
// #i118485# copy text (Caution! Model needed, as guaranteed in aw080)
|
|
OutlinerParaObject* pOPO = GetOutlinerParaObject();
|
|
|
|
if(pOPO)
|
|
{
|
|
pClone->NbcSetOutlinerParaObject(*pOPO);
|
|
}
|
|
}
|
|
|
|
return rtl::Reference<SdrObject>(pClone);
|
|
}
|
|
else
|
|
{
|
|
// #i100710# pOLEGraphic may be zero (no visualisation available),
|
|
// so we need to use the OLE replacement graphic
|
|
rtl::Reference<SdrRectObj> pClone = new SdrRectObj(
|
|
getSdrModelFromSdrObject(),
|
|
GetSnapRect());
|
|
|
|
// gray outline
|
|
pClone->SetMergedItem(XLineStyleItem(css::drawing::LineStyle_SOLID));
|
|
const svtools::ColorConfig aColorConfig;
|
|
const svtools::ColorConfigValue aColor(aColorConfig.GetColorValue(svtools::DOCBOUNDARIES));
|
|
pClone->SetMergedItem(XLineColorItem(OUString(), aColor.nColor));
|
|
|
|
// bitmap fill
|
|
pClone->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
|
|
pClone->SetMergedItem(XFillBitmapItem(OUString(), GetEmptyOLEReplacementGraphic()));
|
|
pClone->SetMergedItem(XFillBmpTileItem(false));
|
|
pClone->SetMergedItem(XFillBmpStretchItem(false));
|
|
|
|
return rtl::Reference<SdrObject>(pClone);
|
|
}
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrOle2Obj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
|
|
{
|
|
// #i118485# missing converter added
|
|
rtl::Reference<SdrObject> pRetval = createSdrGrafObjReplacement(true);
|
|
|
|
if(pRetval)
|
|
{
|
|
return pRetval->DoConvertToPolyObj(bBezier, bAddText);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void SdrOle2Obj::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage)
|
|
{
|
|
const bool bRemove(pNewPage == nullptr && pOldPage != nullptr);
|
|
const bool bInsert(pNewPage != nullptr && pOldPage == nullptr);
|
|
|
|
if (bRemove && mpImpl->mbConnected )
|
|
{
|
|
Disconnect();
|
|
}
|
|
|
|
// call parent
|
|
SdrRectObj::handlePageChange(pOldPage, pNewPage);
|
|
|
|
if (bInsert && !mpImpl->mbConnected )
|
|
{
|
|
Connect();
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::SetObjRef( const css::uno::Reference < css::embed::XEmbeddedObject >& rNewObjRef )
|
|
{
|
|
DBG_ASSERT( !rNewObjRef.is() || !mpImpl->mxObjRef.GetObject().is(), "SetObjRef called on already initialized object!");
|
|
if( rNewObjRef == mpImpl->mxObjRef.GetObject() )
|
|
return;
|
|
|
|
// the caller of the method is responsible to control the old object, it will not be closed here
|
|
// Otherwise WW8 import crashes because it transfers control to OLENode by this method
|
|
if ( mpImpl->mxObjRef.GetObject().is() )
|
|
mpImpl->mxObjRef.Lock( false );
|
|
|
|
// avoid removal of object in Disconnect! It is definitely a HACK to call SetObjRef(0)!
|
|
// This call will try to close the objects; so if anybody else wants to keep it, it must be locked by a CloseListener
|
|
mpImpl->mxObjRef.Clear();
|
|
|
|
if ( mpImpl->mbConnected )
|
|
Disconnect();
|
|
|
|
mpImpl->mxObjRef.Assign( rNewObjRef, GetAspect() );
|
|
mpImpl->mbTypeAsked = false;
|
|
|
|
if ( mpImpl->mxObjRef.is() )
|
|
{
|
|
mpImpl->moGraphic.reset();
|
|
|
|
if ( mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE )
|
|
SetResizeProtect(true);
|
|
|
|
// For math objects, set closed state to transparent
|
|
SetClosedObj(!ImplIsMathObj( rNewObjRef ));
|
|
|
|
Connect();
|
|
}
|
|
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
}
|
|
|
|
void SdrOle2Obj::SetClosedObj( bool bIsClosed )
|
|
{
|
|
// TODO/LATER: do we still need this hack?
|
|
// Allow changes to the closed state of OLE objects
|
|
m_bClosedObj = bIsClosed;
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrOle2Obj::getFullDragClone() const
|
|
{
|
|
// #i118485# use central replacement generator
|
|
return createSdrGrafObjReplacement(false);
|
|
}
|
|
|
|
void SdrOle2Obj::SetPersistName( const OUString& rPersistName, SvxOle2Shape* pCreator )
|
|
{
|
|
DBG_ASSERT( mpImpl->aPersistName.isEmpty(), "Persist name changed!");
|
|
|
|
mpImpl->aPersistName = rPersistName;
|
|
mpImpl->mbLoadingOLEObjectFailed = false;
|
|
|
|
Connect(pCreator);
|
|
SetChanged();
|
|
}
|
|
|
|
void SdrOle2Obj::AbandonObject()
|
|
{
|
|
mpImpl->aPersistName.clear();
|
|
mpImpl->mbLoadingOLEObjectFailed = false;
|
|
SetObjRef(nullptr);
|
|
}
|
|
|
|
const OUString& SdrOle2Obj::GetPersistName() const
|
|
{
|
|
return mpImpl->aPersistName;
|
|
}
|
|
|
|
void SdrOle2Obj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
|
|
{
|
|
// #i118485# Allowing much more attributes for OLEs
|
|
rInfo.bRotateFreeAllowed = true;
|
|
rInfo.bRotate90Allowed = true;
|
|
rInfo.bMirrorFreeAllowed = true;
|
|
rInfo.bMirror45Allowed = true;
|
|
rInfo.bMirror90Allowed = true;
|
|
rInfo.bTransparenceAllowed = true;
|
|
rInfo.bShearAllowed = true;
|
|
rInfo.bEdgeRadiusAllowed = false;
|
|
rInfo.bNoOrthoDesired = false;
|
|
rInfo.bCanConvToPath = true;
|
|
rInfo.bCanConvToPoly = true;
|
|
rInfo.bCanConvToPathLineToArea = false;
|
|
rInfo.bCanConvToPolyLineToArea = false;
|
|
rInfo.bCanConvToContour = true;
|
|
}
|
|
|
|
SdrObjKind SdrOle2Obj::GetObjIdentifier() const
|
|
{
|
|
return mpImpl->mbFrame ? SdrObjKind::OLEPluginFrame : SdrObjKind::OLE2;
|
|
}
|
|
|
|
OUString SdrOle2Obj::TakeObjNameSingul() const
|
|
{
|
|
OUStringBuffer sName(SvxResId(mpImpl->mbFrame ? STR_ObjNameSingulFrame : STR_ObjNameSingulOLE2));
|
|
|
|
const OUString aName(GetName());
|
|
|
|
if (!aName.isEmpty())
|
|
{
|
|
sName.append(" '" + aName + "\'");
|
|
}
|
|
|
|
return sName.makeStringAndClear();
|
|
}
|
|
|
|
OUString SdrOle2Obj::TakeObjNamePlural() const
|
|
{
|
|
return SvxResId(mpImpl->mbFrame ? STR_ObjNamePluralFrame : STR_ObjNamePluralOLE2);
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrOle2Obj::implCloneSdrObject(SdrModel& rTargetModel) const
|
|
{
|
|
return new SdrOle2Obj(rTargetModel, *this);
|
|
}
|
|
|
|
void SdrOle2Obj::ImpSetVisAreaSize()
|
|
{
|
|
// #i118524# do not again set VisAreaSize when the call comes from OLE client (e.g. ObjectAreaChanged)
|
|
if (mpImpl->mbSuppressSetVisAreaSize)
|
|
return;
|
|
|
|
// currently there is no need to recalculate scaling for iconified objects
|
|
// TODO/LATER: it might be needed in future when it is possible to change the icon
|
|
if ( GetAspect() == embed::Aspects::MSOLE_ICON )
|
|
return;
|
|
|
|
// the object area of an embedded object was changed, e.g. by user interaction an a selected object
|
|
GetObjRef();
|
|
if (!mpImpl->mxObjRef.is())
|
|
return;
|
|
|
|
sal_Int64 nMiscStatus = mpImpl->mxObjRef->getStatus( GetAspect() );
|
|
|
|
// the client is required to get access to scaling
|
|
SfxInPlaceClient* pClient(
|
|
SfxInPlaceClient::GetClient(
|
|
dynamic_cast<SfxObjectShell*>(
|
|
getSdrModelFromSdrObject().GetPersist()),
|
|
mpImpl->mxObjRef.GetObject()));
|
|
const bool bHasOwnClient(
|
|
mpImpl->mxLightClient.is() &&
|
|
mpImpl->mxObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->mxLightClient ) );
|
|
|
|
if ( pClient || bHasOwnClient )
|
|
{
|
|
// TODO: IMHO we need to do similar things when object is UIActive or OutplaceActive?!
|
|
if ( ((nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) &&
|
|
svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObjRef.GetObject() ))
|
|
|| mpImpl->mxObjRef->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
|
|
)
|
|
{
|
|
double fScaleWidth;
|
|
double fScaleHeight;
|
|
if ( pClient )
|
|
{
|
|
fScaleWidth = pClient->GetScaleWidth();
|
|
fScaleHeight = pClient->GetScaleHeight();
|
|
}
|
|
else
|
|
{
|
|
fScaleWidth = mpImpl->mxLightClient->GetScaleWidth();
|
|
fScaleHeight = mpImpl->mxLightClient->GetScaleHeight();
|
|
}
|
|
|
|
// The object wants to resize itself (f.e. Chart wants to recalculate the layout)
|
|
// or object is inplace active and so has a window that must be resized also
|
|
// In these cases the change in the object area size will be reflected in a change of the
|
|
// objects' visual area. The scaling will not change, but it might exist already and must
|
|
// be used in calculations
|
|
MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpImpl->mxObjRef->getMapUnit( GetAspect() ) );
|
|
Size aVisSize;
|
|
if (sal_Int32(fScaleWidth) != 0 && sal_Int32(fScaleHeight) != 0) // avoid div by zero
|
|
aVisSize = Size( static_cast<tools::Long>( getRectangle().GetWidth() / fScaleWidth ),
|
|
static_cast<tools::Long>( getRectangle().GetHeight() / fScaleHeight ) );
|
|
|
|
aVisSize = OutputDevice::LogicToLogic(
|
|
aVisSize,
|
|
MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
|
|
MapMode(aMapUnit));
|
|
awt::Size aSz;
|
|
aSz.Width = aVisSize.Width();
|
|
aSz.Height = aVisSize.Height();
|
|
mpImpl->mxObjRef->setVisualAreaSize( GetAspect(), aSz );
|
|
|
|
try
|
|
{
|
|
aSz = mpImpl->mxObjRef->getVisualAreaSize( GetAspect() );
|
|
}
|
|
catch( embed::NoVisualAreaSizeException& )
|
|
{}
|
|
|
|
tools::Rectangle aAcceptedVisArea;
|
|
aAcceptedVisArea.SetSize( Size( static_cast<tools::Long>( aSz.Width * fScaleWidth ),
|
|
static_cast<tools::Long>( aSz.Height * fScaleHeight ) ) );
|
|
if (aVisSize != aAcceptedVisArea.GetSize())
|
|
{
|
|
// server changed VisArea to its liking and the VisArea is different than the suggested one
|
|
// store the new value as given by the object
|
|
MapUnit aNewMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpImpl->mxObjRef->getMapUnit( GetAspect() ) );
|
|
auto aSize = OutputDevice::LogicToLogic(aAcceptedVisArea.GetSize(), MapMode(aNewMapUnit), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
|
|
setRectangleSize(aSize.Width(), aSize.Height());
|
|
}
|
|
|
|
// make the new object area known to the client
|
|
// compared to the "else" branch aRect might have been changed by the object and no additional scaling was applied
|
|
// WHY this -> OSL_ASSERT( pClient );
|
|
if( pClient )
|
|
pClient->SetObjArea(getRectangle());
|
|
|
|
// we need a new replacement image as the object has resized itself
|
|
|
|
//#i79578# don't request a new replacement image for charts to often
|
|
//a chart sends a modified call to the framework if it was changed
|
|
//thus the replacement update is already handled there
|
|
if( !IsChart() )
|
|
mpImpl->mxObjRef.UpdateReplacement();
|
|
}
|
|
else
|
|
{
|
|
// The object isn't active and does not want to resize itself so the changed object area size
|
|
// will be reflected in a changed object scaling
|
|
double aScaleWidth;
|
|
double aScaleHeight;
|
|
Size aObjAreaSize;
|
|
if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) )
|
|
{
|
|
if ( pClient )
|
|
{
|
|
tools::Rectangle aScaleRect(getRectangle().TopLeft(), aObjAreaSize);
|
|
pClient->SetObjAreaAndScale( aScaleRect, aScaleWidth, aScaleHeight);
|
|
}
|
|
else
|
|
{
|
|
mpImpl->mxLightClient->SetSizeScale( aScaleWidth, aScaleHeight );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( (nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) &&
|
|
svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObjRef.GetObject() ) )
|
|
{
|
|
//also handle not sfx based ole objects e.g. charts
|
|
//#i83860# resizing charts in impress distorts fonts
|
|
uno::Reference< embed::XVisualObject > xVisualObject( getXModel(), uno::UNO_QUERY );
|
|
if( xVisualObject.is() )
|
|
{
|
|
const MapUnit aMapUnit(
|
|
VCLUnoHelper::UnoEmbed2VCLMapUnit(
|
|
mpImpl->mxObjRef->getMapUnit(GetAspect())));
|
|
const Point aTL( getRectangle().TopLeft() );
|
|
const Point aBR( getRectangle().BottomRight() );
|
|
const Point aTL2(
|
|
OutputDevice::LogicToLogic(
|
|
aTL,
|
|
MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
|
|
MapMode(aMapUnit)));
|
|
const Point aBR2(
|
|
OutputDevice::LogicToLogic(
|
|
aBR,
|
|
MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
|
|
MapMode(aMapUnit)));
|
|
const tools::Rectangle aNewRect(
|
|
aTL2,
|
|
aBR2);
|
|
|
|
xVisualObject->setVisualAreaSize(
|
|
GetAspect(),
|
|
awt::Size(
|
|
aNewRect.GetWidth(),
|
|
aNewRect.GetHeight()));
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::NbcResize(const Point& rRef, double xFact, double yFact)
|
|
{
|
|
if(!getSdrModelFromSdrObject().isLocked())
|
|
{
|
|
GetObjRef();
|
|
|
|
if ( mpImpl->mxObjRef.is() && ( mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) )
|
|
{
|
|
// if the object needs recompose on resize
|
|
// the client site should be created before the resize will take place
|
|
// check whether there is no client site and create it if necessary
|
|
AddOwnLightClient();
|
|
}
|
|
}
|
|
|
|
SdrRectObj::NbcResize(rRef,xFact,yFact);
|
|
|
|
if( !getSdrModelFromSdrObject().isLocked() )
|
|
ImpSetVisAreaSize();
|
|
}
|
|
|
|
void SdrOle2Obj::SetGeoData(const SdrObjGeoData& rGeo)
|
|
{
|
|
SdrRectObj::SetGeoData(rGeo);
|
|
|
|
if( !getSdrModelFromSdrObject().isLocked() )
|
|
ImpSetVisAreaSize();
|
|
}
|
|
|
|
void SdrOle2Obj::NbcSetSnapRect(const tools::Rectangle& rRect)
|
|
{
|
|
SdrRectObj::NbcSetSnapRect(rRect);
|
|
|
|
if( !getSdrModelFromSdrObject().isLocked() )
|
|
ImpSetVisAreaSize();
|
|
|
|
if ( mpImpl->mxObjRef.is() && IsChart() )
|
|
{
|
|
//#i103460# charts do not necessarily have an own size within ODF files,
|
|
//for this case they need to use the size settings from the surrounding frame,
|
|
//which is made available with this method as there is no other way
|
|
mpImpl->mxObjRef.SetDefaultSizeForChart( Size( rRect.GetWidth(), rRect.GetHeight() ) );
|
|
}
|
|
}
|
|
|
|
void SdrOle2Obj::NbcSetLogicRect(const tools::Rectangle& rRect, bool bAdaptTextMinSize)
|
|
{
|
|
SdrRectObj::NbcSetLogicRect(rRect, bAdaptTextMinSize);
|
|
|
|
if( !getSdrModelFromSdrObject().isLocked() )
|
|
ImpSetVisAreaSize();
|
|
}
|
|
|
|
const Graphic* SdrOle2Obj::GetGraphic() const
|
|
{
|
|
if ( mpImpl->mxObjRef.is() )
|
|
return mpImpl->mxObjRef.GetGraphic();
|
|
return mpImpl->moGraphic ? &*mpImpl->moGraphic : nullptr;
|
|
}
|
|
|
|
void SdrOle2Obj::GetNewReplacement()
|
|
{
|
|
if ( mpImpl->mxObjRef.is() )
|
|
mpImpl->mxObjRef.UpdateReplacement();
|
|
}
|
|
|
|
Size SdrOle2Obj::GetOrigObjSize( MapMode const * pTargetMapMode ) const
|
|
{
|
|
return mpImpl->mxObjRef.GetSize( pTargetMapMode );
|
|
}
|
|
|
|
void SdrOle2Obj::setSuppressSetVisAreaSize( bool bNew )
|
|
{
|
|
mpImpl->mbSuppressSetVisAreaSize = bNew;
|
|
}
|
|
|
|
void SdrOle2Obj::NbcMove(const Size& rSize)
|
|
{
|
|
SdrRectObj::NbcMove(rSize);
|
|
|
|
if( !getSdrModelFromSdrObject().isLocked() )
|
|
ImpSetVisAreaSize();
|
|
}
|
|
|
|
bool SdrOle2Obj::CanUnloadRunningObj( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
|
|
{
|
|
uno::Reference<embed::XEmbedPersist2> xPersist(xObj, uno::UNO_QUERY);
|
|
if (xPersist.is())
|
|
{
|
|
if (!xPersist->isStored())
|
|
// It doesn't have persistent storage. We can't unload this.
|
|
return false;
|
|
}
|
|
|
|
bool bResult = false;
|
|
|
|
sal_Int32 nState = xObj->getCurrentState();
|
|
if ( nState == embed::EmbedStates::LOADED )
|
|
{
|
|
// the object is already unloaded
|
|
bResult = true;
|
|
}
|
|
else
|
|
{
|
|
uno::Reference < util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
|
|
if ( !xModifiable.is() )
|
|
bResult = true;
|
|
else
|
|
{
|
|
sal_Int64 nMiscStatus = xObj->getStatus( nAspect );
|
|
|
|
if ( embed::EmbedMisc::MS_EMBED_ALWAYSRUN != ( nMiscStatus & embed::EmbedMisc::MS_EMBED_ALWAYSRUN ) &&
|
|
embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY != ( nMiscStatus & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) &&
|
|
!( xModifiable.is() && xModifiable->isModified() ) &&
|
|
!( nState == embed::EmbedStates::INPLACE_ACTIVE || nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::ACTIVE ) )
|
|
{
|
|
bResult = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
bool SdrOle2Obj::Unload( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
|
|
{
|
|
bool bResult = false;
|
|
|
|
if ( CanUnloadRunningObj( xObj, nAspect ) )
|
|
{
|
|
try
|
|
{
|
|
xObj->changeState( embed::EmbedStates::LOADED );
|
|
bResult = true;
|
|
}
|
|
catch( css::uno::Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::Unload()" );
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
bool SdrOle2Obj::Unload()
|
|
{
|
|
if (!mpImpl->mxObjRef.is())
|
|
// Already unloaded.
|
|
return true;
|
|
|
|
return Unload(mpImpl->mxObjRef.GetObject(), GetAspect());
|
|
}
|
|
|
|
void SdrOle2Obj::GetObjRef_Impl()
|
|
{
|
|
if ( !mpImpl->mxObjRef.is() && !mpImpl->aPersistName.isEmpty() && getSdrModelFromSdrObject().GetPersist() )
|
|
{
|
|
// Only try loading if it did not went wrong up to now
|
|
if(!mpImpl->mbLoadingOLEObjectFailed)
|
|
{
|
|
mpImpl->mxObjRef.Assign(
|
|
getSdrModelFromSdrObject().GetPersist()->getEmbeddedObjectContainer().GetEmbeddedObject(mpImpl->aPersistName),
|
|
GetAspect());
|
|
mpImpl->mbTypeAsked = false;
|
|
CheckFileLink_Impl();
|
|
|
|
// If loading of OLE object failed, remember that to not invoke an endless
|
|
// loop trying to load it again and again.
|
|
if( mpImpl->mxObjRef.is() )
|
|
{
|
|
mpImpl->mbLoadingOLEObjectFailed = true;
|
|
}
|
|
|
|
// For math objects, set closed state to transparent
|
|
SetClosedObj(!ImplIsMathObj( mpImpl->mxObjRef.GetObject() ));
|
|
}
|
|
|
|
if ( mpImpl->mxObjRef.is() )
|
|
{
|
|
if( !IsEmptyPresObj() )
|
|
{
|
|
// remember modified status of model
|
|
const bool bWasChanged(getSdrModelFromSdrObject().IsChanged());
|
|
|
|
// perhaps preview not valid anymore
|
|
// This line changes the modified state of the model
|
|
ClearGraphic();
|
|
|
|
// if status was not set before, force it back
|
|
// to not set, so that SetGraphic(0) above does not
|
|
// set the modified state of the model.
|
|
if(!bWasChanged && getSdrModelFromSdrObject().IsChanged())
|
|
{
|
|
getSdrModelFromSdrObject().SetChanged( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( mpImpl->mxObjRef.is() )
|
|
Connect();
|
|
}
|
|
|
|
if ( mpImpl->mbConnected )
|
|
{
|
|
// move object to first position in cache
|
|
GetSdrGlobalData().GetOLEObjCache().InsertObj(this);
|
|
}
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > const & SdrOle2Obj::GetObjRef() const
|
|
{
|
|
const_cast<SdrOle2Obj*>(this)->GetObjRef_Impl();
|
|
return mpImpl->mxObjRef.GetObject();
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > const & SdrOle2Obj::GetObjRef_NoInit() const
|
|
{
|
|
return mpImpl->mxObjRef.GetObject();
|
|
}
|
|
|
|
uno::Reference< frame::XModel > SdrOle2Obj::getXModel() const
|
|
{
|
|
if (svt::EmbeddedObjectRef::TryRunningState(GetObjRef()))
|
|
return uno::Reference< frame::XModel >( mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY );
|
|
else
|
|
return uno::Reference< frame::XModel >();
|
|
}
|
|
|
|
bool SdrOle2Obj::IsChart() const
|
|
{
|
|
if (!mpImpl->mbTypeAsked)
|
|
{
|
|
mpImpl->mbIsChart = mpImpl->mxObjRef.IsChart();
|
|
mpImpl->mbTypeAsked = true;
|
|
}
|
|
return mpImpl->mbIsChart;
|
|
}
|
|
|
|
void SdrOle2Obj::SetGraphicToObj( const Graphic& aGraphic )
|
|
{
|
|
mpImpl->mxObjRef.SetGraphic( aGraphic, OUString() );
|
|
// if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
|
|
// graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback
|
|
if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
|
|
mpImpl->moGraphic.emplace(*pObjGraphic);
|
|
}
|
|
|
|
void SdrOle2Obj::SetGraphicToObj( const uno::Reference< io::XInputStream >& xGrStream, const OUString& aMediaType )
|
|
{
|
|
mpImpl->mxObjRef.SetGraphicStream( xGrStream, aMediaType );
|
|
// if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
|
|
// graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback
|
|
if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
|
|
mpImpl->moGraphic.emplace(*pObjGraphic);
|
|
}
|
|
|
|
bool SdrOle2Obj::IsCalc() const
|
|
{
|
|
if ( !mpImpl->mxObjRef.is() )
|
|
return false;
|
|
|
|
SvGlobalName aObjClsId( mpImpl->mxObjRef->getClassID() );
|
|
return SvGlobalName(SO3_SC_CLASSID_30) == aObjClsId
|
|
|| SvGlobalName(SO3_SC_CLASSID_40) == aObjClsId
|
|
|| SvGlobalName(SO3_SC_CLASSID_50) == aObjClsId
|
|
|| SvGlobalName(SO3_SC_CLASSID_60) == aObjClsId
|
|
|| SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_60) == aObjClsId
|
|
|| SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_8) == aObjClsId
|
|
|| SvGlobalName(SO3_SC_CLASSID) == aObjClsId;
|
|
}
|
|
|
|
const uno::Reference< frame::XModel > & SdrOle2Obj::GetParentXModel() const
|
|
{
|
|
return getSdrModelFromSdrObject().getUnoModel();
|
|
}
|
|
|
|
bool SdrOle2Obj::CalculateNewScaling( double& aScaleWidth, double& aScaleHeight, Size& aObjAreaSize )
|
|
{
|
|
// TODO/LEAN: to avoid rounding errors scaling always uses the VisArea.
|
|
// If we don't cache it for own objects also we must load the object here
|
|
if (!mpImpl->mxObjRef.is())
|
|
return false;
|
|
|
|
MapMode aMapMode(getSdrModelFromSdrObject().GetScaleUnit());
|
|
aObjAreaSize = mpImpl->mxObjRef.GetSize( &aMapMode );
|
|
|
|
Size aSize = getRectangle().GetSize();
|
|
if (!aObjAreaSize.Width() || !aObjAreaSize.Height())
|
|
{
|
|
// avoid invalid fractions
|
|
aScaleWidth = 1.0;
|
|
aScaleHeight = 1.0;
|
|
}
|
|
else
|
|
{
|
|
aScaleWidth = double(aSize.Width()) / aObjAreaSize.Width();
|
|
aScaleHeight = double(aSize.Height()) / aObjAreaSize.Height();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SdrOle2Obj::SetIgnoreOLEObjectScale(bool val) { mpImpl->mbIgnoreOLEObjectScale = val; }
|
|
|
|
bool SdrOle2Obj::AddOwnLightClient()
|
|
{
|
|
// The Own Light Client must be registered in object only using this method!
|
|
if ( !SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(getSdrModelFromSdrObject().GetPersist()), mpImpl->mxObjRef.GetObject() )
|
|
&& !( mpImpl->mxLightClient.is() && mpImpl->mxObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->mxLightClient ) ) )
|
|
{
|
|
Connect();
|
|
|
|
if (!mpImpl->mbIgnoreOLEObjectScale && mpImpl->mxObjRef.is() && mpImpl->mxLightClient.is())
|
|
{
|
|
double aScaleWidth;
|
|
double aScaleHeight;
|
|
Size aObjAreaSize;
|
|
if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) )
|
|
{
|
|
mpImpl->mxLightClient->SetSizeScale( aScaleWidth, aScaleHeight );
|
|
try {
|
|
mpImpl->mxObjRef->setClientSite( mpImpl->mxLightClient );
|
|
return true;
|
|
} catch( uno::Exception& )
|
|
{}
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Graphic SdrOle2Obj::GetEmptyOLEReplacementGraphic()
|
|
{
|
|
return Graphic(Bitmap(BMP_SVXOLEOBJ));
|
|
}
|
|
|
|
void SdrOle2Obj::SetWindow(const css::uno::Reference < css::awt::XWindow >& _xWindow)
|
|
{
|
|
if ( mpImpl->mxObjRef.is() && mpImpl->mxLightClient.is() )
|
|
{
|
|
mpImpl->mxLightClient->setWindow(_xWindow);
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|