Files
odfstudio/svx/source/svdraw/svdoole2.cxx
T
Armin Le Grand (collabora) 5519a3d407 Correct StyleSheet handling when cloning to different Model II
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>
2026-10-05 08:52:54 +02:00

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: */