summaryrefslogtreecommitdiffstats
path: root/embeddedobj/source/general
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--embeddedobj/source/general/docholder.cxx1278
-rw-r--r--embeddedobj/source/general/dummyobject.cxx638
-rw-r--r--embeddedobj/source/general/intercept.cxx312
-rw-r--r--embeddedobj/source/general/xcreator.cxx413
4 files changed, 2641 insertions, 0 deletions
diff --git a/embeddedobj/source/general/docholder.cxx b/embeddedobj/source/general/docholder.cxx
new file mode 100644
index 000000000..ee1a8dfa6
--- /dev/null
+++ b/embeddedobj/source/general/docholder.cxx
@@ -0,0 +1,1278 @@
+/* -*- 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 <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/frame/TaskCreator.hpp>
+#include <com/sun/star/frame/XTitle.hpp>
+#include <com/sun/star/frame/TerminationVetoException.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/XCloseBroadcaster.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/XControllerBorder.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/frame/XDispatchProviderInterception.hpp>
+#include <com/sun/star/awt/Toolkit.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+#include <com/sun/star/embed/XHatchWindow.hpp>
+#include <com/sun/star/embed/HatchWindowFactory.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/frame/XMenuBarMergingAcceptor.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/ui/XDockingAreaAcceptor.hpp>
+#include <com/sun/star/ui/XUIElementSettings.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/embed/StateChangeInProgressException.hpp>
+
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+#include <unotools/resmgr.hxx>
+#include <sfx2/strings.hrc>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+
+#include <docholder.hxx>
+#include <commonembobj.hxx>
+#include <intercept.hxx>
+
+#define HATCH_BORDER_WIDTH (((m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) && \
+ m_pEmbedObj->getCurrentState()!=embed::EmbedStates::UI_ACTIVE) ? 0 : 4 )
+
+using namespace ::com::sun::star;
+
+namespace {
+
+class IntCounterGuard
+{
+ sal_Int32& m_rFlag;
+public:
+ explicit IntCounterGuard(sal_Int32& rFlag)
+ : m_rFlag(rFlag)
+ {
+ ++m_rFlag;
+ }
+
+ ~IntCounterGuard()
+ {
+ if (m_rFlag)
+ --m_rFlag;
+ }
+};
+
+}
+
+static void InsertMenu_Impl( const uno::Reference< container::XIndexContainer >& xTargetMenu,
+ sal_Int32 nTargetIndex,
+ const uno::Reference< container::XIndexAccess >& xSourceMenu,
+ sal_Int32 nSourceIndex,
+ const OUString& aContModuleName,
+ const uno::Reference< frame::XDispatchProvider >& xSourceDisp )
+{
+ sal_Int32 nInd = 0;
+ OUString aModuleIdentPropName( "ModuleIdentifier" );
+ OUString aDispProvPropName( "DispatchProvider" );
+ bool bModuleNameSet = false;
+ bool bDispProvSet = false;
+
+ uno::Sequence< beans::PropertyValue > aSourceProps;
+ xSourceMenu->getByIndex( nSourceIndex ) >>= aSourceProps;
+ uno::Sequence< beans::PropertyValue > aTargetProps( aSourceProps.getLength() );
+ auto aTargetPropsRange = asNonConstRange(aTargetProps);
+ for ( nInd = 0; nInd < aSourceProps.getLength(); nInd++ )
+ {
+ aTargetPropsRange[nInd].Name = aSourceProps[nInd].Name;
+ if ( !aContModuleName.isEmpty() && aTargetProps[nInd].Name == aModuleIdentPropName )
+ {
+ aTargetPropsRange[nInd].Value <<= aContModuleName;
+ bModuleNameSet = true;
+ }
+ else if ( aTargetProps[nInd].Name == aDispProvPropName )
+ {
+ aTargetPropsRange[nInd].Value <<= xSourceDisp;
+ bDispProvSet = true;
+ }
+ else
+ aTargetPropsRange[nInd].Value = aSourceProps[nInd].Value;
+ }
+
+ if ( !bModuleNameSet && !aContModuleName.isEmpty() )
+ {
+ aTargetProps.realloc( ++nInd );
+ auto pTargetProps = aTargetProps.getArray();
+ pTargetProps[nInd-1].Name = aModuleIdentPropName;
+ pTargetProps[nInd-1].Value <<= aContModuleName;
+ }
+
+ if ( !bDispProvSet && xSourceDisp.is() )
+ {
+ aTargetProps.realloc( ++nInd );
+ auto pTargetProps = aTargetProps.getArray();
+ pTargetProps[nInd-1].Name = aDispProvPropName;
+ pTargetProps[nInd-1].Value <<= xSourceDisp;
+ }
+
+ xTargetMenu->insertByIndex( nTargetIndex, uno::Any( aTargetProps ) );
+}
+
+
+DocumentHolder::DocumentHolder( const uno::Reference< uno::XComponentContext >& xContext,
+ OCommonEmbeddedObject* pEmbObj )
+: m_pEmbedObj( pEmbObj ),
+ m_xContext( xContext ),
+ m_bReadOnly( false ),
+ m_bWaitForClose( false ),
+ m_bAllowClosing( false ),
+ m_bDesktopTerminated( false ),
+ m_nNoBorderResizeReact( 0 ),
+ m_nNoResizeReact( 0 )
+{
+ uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext );
+ osl_atomic_increment(&m_refCount);
+ try
+ {
+ xDesktop->addTerminateListener( this );
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+ osl_atomic_decrement(&m_refCount);
+
+ m_aOutplaceFrameProps = { uno::Any(beans::NamedValue{ "TopWindow", uno::Any(true) }),
+ uno::Any(beans::NamedValue{ "MakeVisible", uno::Any(false) }),
+ //TODO/LATER: should use parent document frame
+ uno::Any(beans::NamedValue{ "ParentFrame", uno::Any(xDesktop) }) };
+}
+
+
+DocumentHolder::~DocumentHolder()
+{
+ osl_atomic_increment(&m_refCount); // to allow deregistration as a listener
+
+ if( m_xFrame.is() )
+ CloseFrame();
+
+ if ( m_xComponent.is() )
+ {
+ try {
+ CloseDocument( true, false );
+ } catch( const uno::Exception& ) {}
+ }
+
+ if ( m_xInterceptor.is() )
+ {
+ m_xInterceptor->DisconnectDocHolder();
+ m_xInterceptor.clear();
+ }
+
+ if ( !m_bDesktopTerminated )
+ FreeOffice();
+}
+
+
+void DocumentHolder::CloseFrame()
+{
+ uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
+ if ( xCloseBroadcaster.is() )
+ xCloseBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
+
+ uno::Reference<util::XCloseable> xCloseable(
+ m_xFrame,uno::UNO_QUERY );
+ if( xCloseable.is() )
+ try {
+ xCloseable->close( true );
+ }
+ catch( const uno::Exception& ) {
+ }
+ else {
+ if( m_xFrame.is() )
+ m_xFrame->dispose();
+ }
+
+ if ( m_xHatchWindow.is() )
+ m_xHatchWindow->dispose();
+
+ m_xHatchWindow.clear();
+ m_xOwnWindow.clear();
+ m_xFrame.clear();
+}
+
+
+void DocumentHolder::FreeOffice()
+{
+ uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext );
+ xDesktop->removeTerminateListener( this );
+
+ // the following code is commented out since for now there is still no completely correct way to detect
+ // whether the office can be terminated, so it is better to have unnecessary process running than
+ // to lose any data
+
+// uno::Reference< frame::XFramesSupplier > xFramesSupplier( xDesktop, uno::UNO_QUERY );
+// if ( xFramesSupplier.is() )
+// {
+// uno::Reference< frame::XFrames > xFrames = xFramesSupplier->getFrames();
+// if ( xFrames.is() && !xFrames->hasElements() )
+// {
+// try
+// {
+// xDesktop->terminate();
+// }
+// catch( uno::Exception & )
+// {}
+// }
+// }
+}
+
+
+void DocumentHolder::CloseDocument( bool bDeliverOwnership, bool bWaitForClose )
+{
+ if ( m_xComponent.is() )
+ {
+ uno::Reference< document::XEventBroadcaster > xEventBroadcaster( m_xComponent, uno::UNO_QUERY );
+ if ( xEventBroadcaster.is() )
+ xEventBroadcaster->removeEventListener( static_cast<document::XEventListener*>(this) );
+ else
+ {
+ // the object does not support document::XEventBroadcaster interface
+ // use the workaround, register for modified events
+ uno::Reference< util::XModifyBroadcaster > xModifyBroadcaster( m_xComponent, uno::UNO_QUERY );
+ if ( xModifyBroadcaster.is() )
+ xModifyBroadcaster->removeModifyListener( static_cast<util::XModifyListener*>(this) );
+ }
+
+ m_bAllowClosing = true;
+ m_bWaitForClose = bWaitForClose;
+ m_xComponent->close( bDeliverOwnership );
+ }
+
+ m_xComponent = nullptr;
+}
+
+
+void DocumentHolder::PlaceFrame( const awt::Rectangle& aNewRect )
+{
+ OSL_ENSURE( m_xFrame.is() && m_xOwnWindow.is(),
+ "The object does not have windows required for inplace mode!" );
+
+ //TODO: may need mutex locking???
+ if ( !(m_xFrame.is() && m_xOwnWindow.is()) )
+ return;
+
+ // the frame can be replaced only in inplace mode
+ frame::BorderWidths aOldWidths;
+ IntCounterGuard aGuard( m_nNoBorderResizeReact );
+
+ do
+ {
+ aOldWidths = m_aBorderWidths;
+
+ awt::Rectangle aHatchRect = AddBorderToArea( aNewRect );
+
+ ResizeWindows_Impl( aHatchRect );
+
+ } while ( aOldWidths.Left != m_aBorderWidths.Left
+ || aOldWidths.Top != m_aBorderWidths.Top
+ || aOldWidths.Right != m_aBorderWidths.Right
+ || aOldWidths.Bottom != m_aBorderWidths.Bottom );
+
+ m_aObjRect = aNewRect;
+}
+
+
+void DocumentHolder::ResizeWindows_Impl( const awt::Rectangle& aHatchRect )
+{
+ OSL_ENSURE( m_xFrame.is() && m_xOwnWindow.is() /*&& m_xHatchWindow.is()*/,
+ "The object does not have windows required for inplace mode!" );
+ if ( m_xHatchWindow.is() )
+ {
+ m_xOwnWindow->setPosSize( HATCH_BORDER_WIDTH,
+ HATCH_BORDER_WIDTH,
+ aHatchRect.Width - 2*HATCH_BORDER_WIDTH,
+ aHatchRect.Height - 2*HATCH_BORDER_WIDTH,
+ awt::PosSize::POSSIZE );
+
+
+ m_xHatchWindow->setPosSize( aHatchRect.X,
+ aHatchRect.Y,
+ aHatchRect.Width,
+ aHatchRect.Height,
+ awt::PosSize::POSSIZE );
+ }
+ else
+ m_xOwnWindow->setPosSize( aHatchRect.X + HATCH_BORDER_WIDTH,
+ aHatchRect.Y + HATCH_BORDER_WIDTH,
+ aHatchRect.Width - 2*HATCH_BORDER_WIDTH,
+ aHatchRect.Height - 2*HATCH_BORDER_WIDTH,
+ awt::PosSize::POSSIZE );
+}
+
+
+bool DocumentHolder::SetFrameLMVisibility( const uno::Reference< frame::XFrame >& xFrame, bool bVisible )
+{
+ bool bResult = false;
+
+ try
+ {
+ uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY_THROW );
+ xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
+ if ( xLayoutManager.is() )
+ {
+ xLayoutManager->setVisible( bVisible );
+
+ // MBA: locking is done only on the container LM, because it is not about hiding windows, it's about
+ // giving up control over the component window (and stopping to listen for resize events of the container window)
+ if ( bVisible )
+ xLayoutManager->unlock();
+ else
+ xLayoutManager->lock();
+
+ bResult = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {}
+
+ return bResult;
+}
+
+
+bool DocumentHolder::ShowInplace( const uno::Reference< awt::XWindowPeer >& xParent,
+ const awt::Rectangle& aRectangleToShow,
+ const uno::Reference< frame::XDispatchProvider >& xContDisp )
+{
+ OSL_ENSURE( !m_xFrame.is(), "A frame exists already!" );
+
+ if ( !m_xFrame.is() )
+ {
+ uno::Reference < frame::XModel > xModel( GetComponent(), uno::UNO_QUERY );
+ awt::Rectangle aHatchRectangle = AddBorderToArea( aRectangleToShow );
+
+ awt::Rectangle aOwnRectangle( HATCH_BORDER_WIDTH,
+ HATCH_BORDER_WIDTH,
+ aHatchRectangle.Width - 2*HATCH_BORDER_WIDTH,
+ aHatchRectangle.Height - 2*HATCH_BORDER_WIDTH );
+ uno::Reference< awt::XWindow > xHWindow;
+ uno::Reference< awt::XWindowPeer > xMyParent( xParent );
+
+ if ( xModel.is() )
+ {
+
+ uno::Reference< embed::XHatchWindowFactory > xHatchFactory =
+ embed::HatchWindowFactory::create(m_xContext);
+
+ uno::Reference< embed::XHatchWindow > xHatchWindow =
+ xHatchFactory->createHatchWindowInstance( xParent,
+ aHatchRectangle,
+ awt::Size( HATCH_BORDER_WIDTH, HATCH_BORDER_WIDTH ) );
+
+ uno::Reference< awt::XWindowPeer > xHatchWinPeer( xHatchWindow, uno::UNO_QUERY );
+ xHWindow.set( xHatchWinPeer, uno::UNO_QUERY_THROW );
+
+ xHatchWindow->setController( uno::Reference< embed::XHatchWindowController >(
+ static_cast< embed::XHatchWindowController* >( this ) ) );
+
+ xMyParent = xHatchWinPeer;
+ }
+ else
+ {
+ aOwnRectangle.X += aHatchRectangle.X;
+ aOwnRectangle.Y += aHatchRectangle.Y;
+ }
+
+ awt::WindowDescriptor aOwnWinDescriptor( awt::WindowClass_TOP,
+ "dockingwindow",
+ xMyParent,
+ 0,
+ awt::Rectangle(),//aOwnRectangle,
+ awt::WindowAttribute::SHOW | awt::VclWindowPeerAttribute::CLIPCHILDREN );
+
+ uno::Reference< awt::XToolkit2 > xToolkit = awt::Toolkit::create(m_xContext);
+
+ uno::Reference< awt::XWindowPeer > xNewWinPeer = xToolkit->createWindow( aOwnWinDescriptor );
+ uno::Reference< awt::XWindow > xOwnWindow( xNewWinPeer, uno::UNO_QUERY_THROW );
+ uno::Reference< frame::XFrame > xContFrame( xContDisp, uno::UNO_QUERY );
+
+ // create a frame based on the specified window
+ uno::Reference< lang::XSingleServiceFactory > xFrameFact = frame::TaskCreator::create(m_xContext);
+
+ uno::Sequence< uno::Any > aArgs( xContFrame.is() ? 2 : 1 );
+ auto pArgs = aArgs.getArray();
+ beans::NamedValue aArg;
+
+ aArg.Name = "ContainerWindow";
+ aArg.Value <<= xOwnWindow;
+ pArgs[0] <<= aArg;
+
+ if ( xContFrame.is() )
+ {
+ aArg.Name = "ParentFrame";
+ aArg.Value <<= xContFrame;
+ pArgs[1] <<= aArg;
+ }
+
+ // the call will create, initialize the frame, and register it in the parent
+ m_xFrame.set( xFrameFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW );
+
+ m_xHatchWindow = xHWindow;
+ m_xOwnWindow = xOwnWindow;
+
+ if ( !SetFrameLMVisibility( m_xFrame, false ) )
+ {
+ OSL_FAIL( "Can't deactivate LayoutManager!" );
+ // TODO/LATER: error handling?
+ }
+
+ // m_bIsInplace = sal_True; TODO: ?
+
+ uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
+ if ( xCloseBroadcaster.is() )
+ xCloseBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
+
+ // TODO: some listeners to the frame and the window ( resize for example )
+ }
+
+ if ( !m_xComponent )
+ return false;
+
+ if ( !LoadDocToFrame( true ) )
+ {
+ CloseFrame();
+ return false;
+ }
+
+ uno::Reference< frame::XControllerBorder > xControllerBorder( m_xFrame->getController(), uno::UNO_QUERY );
+ if ( xControllerBorder.is() )
+ {
+ m_aBorderWidths = xControllerBorder->getBorder();
+ xControllerBorder->addBorderResizeListener( static_cast<frame::XBorderResizeListener*>(this) );
+ }
+
+ PlaceFrame( aRectangleToShow );
+
+ if ( m_xHatchWindow.is() )
+ m_xHatchWindow->setVisible( true );
+
+ return true;
+}
+
+
+uno::Reference< container::XIndexAccess > DocumentHolder::RetrieveOwnMenu_Impl()
+{
+ uno::Reference< container::XIndexAccess > xResult;
+
+ uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUIConfSupplier(
+ m_xComponent,
+ uno::UNO_QUERY );
+ uno::Reference< css::ui::XUIConfigurationManager > xUIConfigManager;
+ if( xUIConfSupplier.is())
+ {
+ xUIConfigManager.set(
+ xUIConfSupplier->getUIConfigurationManager(),
+ uno::UNO_SET_THROW );
+ }
+
+ try
+ {
+ if( xUIConfigManager.is())
+ {
+ xResult = xUIConfigManager->getSettings(
+ "private:resource/menubar/menubar",
+ false );
+ }
+ }
+ catch( const uno::Exception& )
+ {}
+
+ if ( !xResult.is() )
+ {
+ // no internal document configuration, use the one from the module
+ uno::Reference< frame::XModuleManager2 > xModuleMan = frame::ModuleManager::create(m_xContext);
+ OUString aModuleIdent =
+ xModuleMan->identify( uno::Reference< uno::XInterface >( m_xComponent, uno::UNO_QUERY ) );
+
+ if ( !aModuleIdent.isEmpty() )
+ {
+ uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModConfSupplier =
+ ui::theModuleUIConfigurationManagerSupplier::get(m_xContext);
+ uno::Reference< css::ui::XUIConfigurationManager > xModUIConfMan(
+ xModConfSupplier->getUIConfigurationManager( aModuleIdent ),
+ uno::UNO_SET_THROW );
+ xResult = xModUIConfMan->getSettings(
+ "private:resource/menubar/menubar",
+ false );
+ }
+ }
+
+ if ( !xResult.is() )
+ throw uno::RuntimeException();
+
+ return xResult;
+}
+
+
+void DocumentHolder::FindConnectPoints(
+ const uno::Reference< container::XIndexAccess >& xMenu,
+ sal_Int32 nConnectPoints[2] )
+{
+ nConnectPoints[0] = -1;
+ nConnectPoints[1] = -1;
+ for ( sal_Int32 nInd = 0; nInd < xMenu->getCount(); nInd++ )
+ {
+ uno::Sequence< beans::PropertyValue > aProps;
+ xMenu->getByIndex( nInd ) >>= aProps;
+ OUString aCommand;
+ for ( beans::PropertyValue const & prop : std::as_const(aProps) )
+ if ( prop.Name == "CommandURL" )
+ {
+ prop.Value >>= aCommand;
+ break;
+ }
+
+ if ( aCommand.isEmpty() )
+ throw uno::RuntimeException();
+
+ if ( aCommand == ".uno:PickList" )
+ nConnectPoints[0] = nInd;
+ else if ( aCommand == ".uno:WindowList" )
+ nConnectPoints[1] = nInd;
+ }
+}
+
+
+uno::Reference< container::XIndexAccess > DocumentHolder::MergeMenusForInplace(
+ const uno::Reference< container::XIndexAccess >& xContMenu,
+ const uno::Reference< frame::XDispatchProvider >& xContDisp,
+ const OUString& aContModuleName,
+ const uno::Reference< container::XIndexAccess >& xOwnMenu,
+ const uno::Reference< frame::XDispatchProvider >& xOwnDisp )
+{
+ // TODO/LATER: use dispatch providers on merge
+
+ sal_Int32 nContPoints[2];
+ sal_Int32 nOwnPoints[2];
+
+ uno::Reference< lang::XSingleComponentFactory > xIndAccessFact( xContMenu, uno::UNO_QUERY_THROW );
+
+ uno::Reference< container::XIndexContainer > xMergedMenu(
+ xIndAccessFact->createInstanceWithContext(
+ comphelper::getProcessComponentContext() ),
+ uno::UNO_QUERY_THROW );
+
+ FindConnectPoints( xContMenu, nContPoints );
+ FindConnectPoints( xOwnMenu, nOwnPoints );
+
+ for ( sal_Int32 nInd = 0; nInd < xOwnMenu->getCount(); nInd++ )
+ {
+ if ( nOwnPoints[0] == nInd )
+ {
+ if ( nContPoints[0] >= 0 && nContPoints[0] < xContMenu->getCount() )
+ {
+ InsertMenu_Impl( xMergedMenu, nInd, xContMenu, nContPoints[0], aContModuleName, xContDisp );
+ }
+ }
+ else if ( nOwnPoints[1] == nInd )
+ {
+ if ( nContPoints[1] >= 0 && nContPoints[1] < xContMenu->getCount() )
+ {
+ InsertMenu_Impl( xMergedMenu, nInd, xContMenu, nContPoints[1], aContModuleName, xContDisp );
+ }
+ }
+ else
+ InsertMenu_Impl( xMergedMenu, nInd, xOwnMenu, nInd, OUString(), xOwnDisp );
+ }
+
+ return uno::Reference< container::XIndexAccess >( xMergedMenu, uno::UNO_QUERY_THROW );
+}
+
+
+bool DocumentHolder::MergeMenus_Impl( const uno::Reference< css::frame::XLayoutManager >& xOwnLM,
+ const uno::Reference< css::frame::XLayoutManager >& xContLM,
+ const uno::Reference< frame::XDispatchProvider >& xContDisp,
+ const OUString& aContModuleName )
+{
+ bool bMenuMerged = false;
+ try
+ {
+ uno::Reference< css::ui::XUIElementSettings > xUISettings(
+ xContLM->getElement( "private:resource/menubar/menubar" ),
+ uno::UNO_QUERY_THROW );
+ uno::Reference< container::XIndexAccess > xContMenu = xUISettings->getSettings( true );
+ if ( !xContMenu.is() )
+ throw uno::RuntimeException();
+
+ uno::Reference< container::XIndexAccess > xOwnMenu = RetrieveOwnMenu_Impl();
+ uno::Reference< frame::XDispatchProvider > xOwnDisp( m_xFrame, uno::UNO_QUERY_THROW );
+
+ uno::Reference< container::XIndexAccess > xMergedMenu = MergeMenusForInplace( xContMenu, xContDisp, aContModuleName, xOwnMenu, xOwnDisp );
+ uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM,
+ uno::UNO_QUERY_THROW );
+ bMenuMerged = xMerge->setMergedMenuBar( xMergedMenu );
+ }
+ catch( const uno::Exception& )
+ {}
+
+ return bMenuMerged;
+}
+
+bool DocumentHolder::ShowUI( const uno::Reference< css::frame::XLayoutManager >& xContainerLM,
+ const uno::Reference< frame::XDispatchProvider >& xContainerDP,
+ const OUString& aContModuleName )
+{
+ bool bResult = false;
+ if ( xContainerLM.is() )
+ {
+ // the LM of the embedded frame and its current DockingAreaAcceptor
+ uno::Reference< css::frame::XLayoutManager > xOwnLM;
+ uno::Reference< css::ui::XDockingAreaAcceptor > xDocAreaAcc;
+
+ try
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
+ xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
+ xDocAreaAcc = xContainerLM->getDockingAreaAcceptor();
+ }
+ catch( const uno::Exception& ){}
+
+ if ( xOwnLM.is() && xDocAreaAcc.is() )
+ {
+ // make sure that lock state of LM is correct even if an exception is thrown in between
+ bool bUnlockContainerLM = false;
+ bool bLockOwnLM = false;
+ try
+ {
+ // take over the control over the containers window
+ // as long as the LM is invisible and locked an empty tool space will be used on resizing
+ xOwnLM->setDockingAreaAcceptor( xDocAreaAcc );
+
+ // try to merge menus; don't do anything else if it fails
+ if ( MergeMenus_Impl( xOwnLM, xContainerLM, xContainerDP, aContModuleName ) )
+ {
+ // make sure that the container LM does not control the size of the containers window anymore
+ // this must be done after merging menus as we won't get the container menu otherwise
+ xContainerLM->setDockingAreaAcceptor( uno::Reference < ui::XDockingAreaAcceptor >() );
+
+ uno::Reference< lang::XServiceInfo> xServiceInfo(m_xComponent, uno::UNO_QUERY);
+ if (!xServiceInfo.is() || !xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
+ {
+ // prevent further changes at this LM
+ xContainerLM->setVisible(false);
+ xContainerLM->lock();
+ bUnlockContainerLM = true;
+ }
+
+ // by unlocking the LM each layout change will now resize the containers window; pending layouts will be processed now
+ xOwnLM->setVisible( true );
+
+ uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
+ if ( xSupp.is() )
+ xSupp->setActiveFrame( m_xFrame );
+
+ xOwnLM->unlock();
+ bLockOwnLM = true;
+ bResult = true;
+
+ // TODO/LATER: The following action should be done only if the window is not hidden
+ // otherwise the activation must fail, unfortunately currently it is not possible
+ // to detect whether the window is hidden using UNO API
+ m_xOwnWindow->setFocus();
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ // activation failed; reestablish old state
+ try
+ {
+ uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
+ if ( xSupp.is() )
+ xSupp->setActiveFrame( nullptr );
+
+ // remove control about containers window from own LM
+ if (bLockOwnLM)
+ xOwnLM->lock();
+ xOwnLM->setVisible( false );
+ xOwnLM->setDockingAreaAcceptor( uno::Reference< css::ui::XDockingAreaAcceptor >() );
+
+ // unmerge menu
+ uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM, uno::UNO_QUERY_THROW );
+ xMerge->removeMergedMenuBar();
+ }
+ catch( const uno::Exception& ) {}
+
+ try
+ {
+ // reestablish control of containers window
+ xContainerLM->setDockingAreaAcceptor( xDocAreaAcc );
+ xContainerLM->setVisible( true );
+ if (bUnlockContainerLM)
+ xContainerLM->unlock();
+ }
+ catch( const uno::Exception& ) {}
+ }
+ }
+ }
+
+ return bResult;
+}
+
+
+bool DocumentHolder::HideUI( const uno::Reference< css::frame::XLayoutManager >& xContainerLM )
+{
+ bool bResult = false;
+
+ if ( xContainerLM.is() )
+ {
+ uno::Reference< css::frame::XLayoutManager > xOwnLM;
+
+ try {
+ uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
+ xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
+ } catch( const uno::Exception& )
+ {}
+
+ if ( xOwnLM.is() )
+ {
+ try {
+ uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
+ if ( xSupp.is() )
+ xSupp->setActiveFrame( nullptr );
+
+ uno::Reference< css::ui::XDockingAreaAcceptor > xDocAreaAcc = xOwnLM->getDockingAreaAcceptor();
+
+ xOwnLM->setDockingAreaAcceptor( uno::Reference < ui::XDockingAreaAcceptor >() );
+ xOwnLM->lock();
+ xOwnLM->setVisible( false );
+
+ uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM, uno::UNO_QUERY_THROW );
+ xMerge->removeMergedMenuBar();
+
+ xContainerLM->setDockingAreaAcceptor( xDocAreaAcc );
+ uno::Reference< lang::XServiceInfo> xServiceInfo(m_xComponent, uno::UNO_QUERY);
+ if (!xServiceInfo.is() || !xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
+ {
+ xContainerLM->setVisible(true);
+ xContainerLM->unlock();
+ }
+
+ xContainerLM->doLayout();
+ bResult = true;
+ }
+ catch( const uno::Exception& )
+ {
+ SetFrameLMVisibility( m_xFrame, true );
+ }
+ }
+ }
+
+ return bResult;
+}
+
+
+uno::Reference< frame::XFrame > const & DocumentHolder::GetDocFrame()
+{
+ // the frame for outplace activation
+ if ( !m_xFrame.is() )
+ {
+ uno::Reference< lang::XSingleServiceFactory > xFrameFact = frame::TaskCreator::create(m_xContext);
+
+ m_xFrame.set(xFrameFact->createInstanceWithArguments( m_aOutplaceFrameProps ), uno::UNO_QUERY_THROW);
+
+ uno::Reference< frame::XDispatchProviderInterception > xInterception( m_xFrame, uno::UNO_QUERY );
+ if ( xInterception.is() )
+ {
+ if ( m_xInterceptor.is() )
+ {
+ m_xInterceptor->DisconnectDocHolder();
+ m_xInterceptor.clear();
+ }
+
+ m_xInterceptor = new Interceptor( this );
+
+ xInterception->registerDispatchProviderInterceptor( m_xInterceptor );
+
+ // register interceptor from outside
+ if ( m_xOutplaceInterceptor.is() )
+ xInterception->registerDispatchProviderInterceptor( m_xOutplaceInterceptor );
+ }
+
+ uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
+ if ( xCloseBroadcaster.is() )
+ xCloseBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
+ }
+
+ if ( m_xComponent.is() )
+ {
+ uno::Reference< css::frame::XLayoutManager > xOwnLM;
+ try {
+ uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
+ xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
+ } catch( const uno::Exception& )
+ {}
+
+ if ( xOwnLM.is() )
+ xOwnLM->lock();
+
+ // TODO/LATER: get it for the real aspect
+ awt::Size aSize;
+ LoadDocToFrame(false);
+
+ if ( xOwnLM.is() )
+ {
+ xOwnLM->unlock();
+ xOwnLM->lock();
+ }
+
+ GetExtent(embed::Aspects::MSOLE_CONTENT, &aSize);
+ SetExtent(embed::Aspects::MSOLE_CONTENT, aSize);
+
+ if ( xOwnLM.is() )
+ xOwnLM->unlock();
+ }
+
+ try
+ {
+ uno::Reference< awt::XWindow > xHWindow = m_xFrame->getContainerWindow();
+
+ if( xHWindow.is() )
+ {
+ sal_Int32 nDisplay = Application::GetDisplayBuiltInScreen();
+
+ tools::Rectangle aWorkRect = Application::GetScreenPosSizePixel( nDisplay );
+ awt::Rectangle aWindowRect = xHWindow->getPosSize();
+
+ if (( aWindowRect.Width < aWorkRect.GetWidth()) && ( aWindowRect.Height < aWorkRect.GetHeight() ))
+ {
+ int OffsetX = ( aWorkRect.GetWidth() - aWindowRect.Width ) / 2 + aWorkRect.Left();
+ int OffsetY = ( aWorkRect.GetHeight() - aWindowRect.Height ) /2 + aWorkRect.Top();
+ xHWindow->setPosSize( OffsetX, OffsetY, aWindowRect.Width, aWindowRect.Height, awt::PosSize::POS );
+ }
+ else
+ {
+ xHWindow->setPosSize( aWorkRect.Left(), aWorkRect.Top(), aWorkRect.GetWidth(), aWorkRect.GetHeight(), awt::PosSize::POSSIZE );
+ }
+
+ xHWindow->setVisible( true );
+ }
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+
+ return m_xFrame;
+}
+
+
+void DocumentHolder::SetComponent( const uno::Reference< util::XCloseable >& xDoc, bool bReadOnly )
+{
+ if ( m_xComponent.is() )
+ {
+ // May be should be improved
+ try {
+ CloseDocument( true, false );
+ } catch( const uno::Exception& )
+ {}
+ }
+
+ m_xComponent = xDoc;
+
+ m_bReadOnly = bReadOnly;
+ m_bAllowClosing = false;
+
+ if ( m_xComponent.is() )
+ m_xComponent->addCloseListener( static_cast<util::XCloseListener*>(this) );
+
+ uno::Reference< document::XEventBroadcaster > xEventBroadcaster( m_xComponent, uno::UNO_QUERY );
+ if ( xEventBroadcaster.is() )
+ xEventBroadcaster->addEventListener( static_cast<document::XEventListener*>(this) );
+ else
+ {
+ // the object does not support document::XEventBroadcaster interface
+ // use the workaround, register for modified events
+ uno::Reference< util::XModifyBroadcaster > xModifyBroadcaster( m_xComponent, uno::UNO_QUERY );
+ if ( xModifyBroadcaster.is() )
+ xModifyBroadcaster->addModifyListener( static_cast<util::XModifyListener*>(this) );
+ }
+
+ if ( m_xFrame.is() )
+ LoadDocToFrame(false);
+}
+
+
+bool DocumentHolder::LoadDocToFrame( bool bInPlace )
+{
+ if ( !m_xFrame || !m_xComponent )
+ return true;
+
+ uno::Reference < frame::XModel > xDoc( m_xComponent, uno::UNO_QUERY );
+ if ( xDoc.is() )
+ {
+ // load new document into the frame
+ uno::Reference< frame::XComponentLoader > xComponentLoader( m_xFrame, uno::UNO_QUERY_THROW );
+
+ ::comphelper::NamedValueCollection aArgs;
+ aArgs.put( "Model", m_xComponent );
+ aArgs.put( "ReadOnly", m_bReadOnly );
+
+ // set document title to show in the title bar
+ css::uno::Reference< css::frame::XTitle > xModelTitle( xDoc, css::uno::UNO_QUERY );
+ if( xModelTitle.is() && m_pEmbedObj && !m_pEmbedObj->getContainerName().isEmpty() )
+ {
+ std::locale aResLoc = Translate::Create("sfx");
+ OUString sEmbedded = Translate::get(STR_EMBEDDED_TITLE, aResLoc);
+ xModelTitle->setTitle( m_pEmbedObj->getContainerName() + sEmbedded );
+ m_aContainerName = m_pEmbedObj->getContainerName();
+ // TODO: get real m_aDocumentNamePart
+ m_aDocumentNamePart = sEmbedded;
+ }
+
+ if ( bInPlace )
+ aArgs.put( "PluginMode", sal_Int16(1) );
+ OUString sUrl;
+ uno::Reference< lang::XServiceInfo> xServiceInfo(xDoc,uno::UNO_QUERY);
+ if ( xServiceInfo.is()
+ && xServiceInfo->supportsService("com.sun.star.report.ReportDefinition") )
+ {
+ sUrl = ".component:DB/ReportDesign";
+ }
+ else if( xServiceInfo.is()
+ && xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
+ sUrl = "private:factory/schart";
+ else
+ sUrl = "private:object";
+
+ xComponentLoader->loadComponentFromURL( sUrl,
+ "_self",
+ 0,
+ aArgs.getPropertyValues() );
+
+ return true;
+ }
+ else
+ {
+ uno::Reference < frame::XSynchronousFrameLoader > xLoader( m_xComponent, uno::UNO_QUERY );
+ if ( xLoader.is() )
+ return xLoader->load( uno::Sequence < beans::PropertyValue >(), m_xFrame );
+ else
+ return false;
+ }
+
+ return true;
+}
+
+
+void DocumentHolder::Show()
+{
+ if( m_xFrame.is() )
+ {
+ m_xFrame->activate();
+ uno::Reference<awt::XTopWindow> xTopWindow( m_xFrame->getContainerWindow(), uno::UNO_QUERY );
+ if( xTopWindow.is() )
+ xTopWindow->toFront();
+ }
+ else
+ GetDocFrame();
+}
+
+
+bool DocumentHolder::SetExtent( sal_Int64 nAspect, const awt::Size& aSize )
+{
+ uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
+ if ( xDocVis.is() )
+ {
+ try
+ {
+ xDocVis->setVisualAreaSize( nAspect, aSize );
+ return true;
+ }
+ catch( const uno::Exception& )
+ {
+ // TODO: Error handling
+ }
+ }
+
+ return false;
+}
+
+
+bool DocumentHolder::GetExtent( sal_Int64 nAspect, awt::Size *pSize )
+{
+ uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
+ if ( pSize && xDocVis.is() )
+ {
+ try
+ {
+ *pSize = xDocVis->getVisualAreaSize( nAspect );
+ return true;
+ }
+ catch( const uno::Exception& )
+ {
+ // TODO: Error handling
+ }
+ }
+
+ return false;
+}
+
+
+sal_Int32 DocumentHolder::GetMapUnit( sal_Int64 nAspect )
+{
+ uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
+ if ( xDocVis.is() )
+ {
+ try
+ {
+ return xDocVis->getMapUnit( nAspect );
+ }
+ catch( const uno::Exception& )
+ {
+ // TODO: Error handling
+ }
+ }
+
+ return 0;
+}
+
+
+awt::Rectangle DocumentHolder::CalculateBorderedArea( const awt::Rectangle& aRect )
+{
+ return awt::Rectangle( aRect.X + m_aBorderWidths.Left + HATCH_BORDER_WIDTH,
+ aRect.Y + m_aBorderWidths.Top + HATCH_BORDER_WIDTH,
+ aRect.Width - m_aBorderWidths.Left - m_aBorderWidths.Right - 2*HATCH_BORDER_WIDTH,
+ aRect.Height - m_aBorderWidths.Top - m_aBorderWidths.Bottom - 2*HATCH_BORDER_WIDTH );
+}
+
+
+awt::Rectangle DocumentHolder::AddBorderToArea( const awt::Rectangle& aRect )
+{
+ return awt::Rectangle( aRect.X - m_aBorderWidths.Left - HATCH_BORDER_WIDTH,
+ aRect.Y - m_aBorderWidths.Top - HATCH_BORDER_WIDTH,
+ aRect.Width + m_aBorderWidths.Left + m_aBorderWidths.Right + 2*HATCH_BORDER_WIDTH,
+ aRect.Height + m_aBorderWidths.Top + m_aBorderWidths.Bottom + 2*HATCH_BORDER_WIDTH );
+}
+
+
+void SAL_CALL DocumentHolder::disposing( const css::lang::EventObject& aSource )
+{
+ if ( m_xComponent.is() && m_xComponent == aSource.Source )
+ {
+ m_xComponent = nullptr;
+ if ( m_bWaitForClose )
+ {
+ m_bWaitForClose = false;
+ FreeOffice();
+ }
+ }
+
+ if( m_xFrame.is() && m_xFrame == aSource.Source )
+ {
+ m_xHatchWindow.clear();
+ m_xOwnWindow.clear();
+ m_xFrame.clear();
+ }
+}
+
+
+void SAL_CALL DocumentHolder::queryClosing( const lang::EventObject& aSource, sal_Bool /*bGetsOwnership*/ )
+{
+ if ( m_xComponent.is() && m_xComponent == aSource.Source && !m_bAllowClosing )
+ throw util::CloseVetoException("To close an embedded document, close the document holder (document definition), not the document itself.", static_cast< ::cppu::OWeakObject*>(this));
+}
+
+
+void SAL_CALL DocumentHolder::notifyClosing( const lang::EventObject& aSource )
+{
+ if ( m_xComponent.is() && m_xComponent == aSource.Source )
+ {
+ m_xComponent = nullptr;
+ if ( m_bWaitForClose )
+ {
+ m_bWaitForClose = false;
+ FreeOffice();
+ }
+ }
+
+ if( m_xFrame.is() && m_xFrame == aSource.Source )
+ {
+ m_xHatchWindow.clear();
+ m_xOwnWindow.clear();
+ m_xFrame.clear();
+ }
+}
+
+
+void SAL_CALL DocumentHolder::queryTermination( const lang::EventObject& )
+{
+ if ( m_bWaitForClose )
+ throw frame::TerminationVetoException();
+}
+
+
+void SAL_CALL DocumentHolder::notifyTermination( const lang::EventObject& aSource )
+{
+ OSL_ENSURE( !m_xComponent.is(), "Just a disaster..." );
+
+ uno::Reference< frame::XDesktop > xDesktop( aSource.Source, uno::UNO_QUERY );
+ m_bDesktopTerminated = true;
+ if ( xDesktop.is() )
+ xDesktop->removeTerminateListener( static_cast<frame::XTerminateListener*>(this) );
+}
+
+
+void SAL_CALL DocumentHolder::modified( const lang::EventObject& aEvent )
+{
+ // if the component does not support document::XEventBroadcaster
+ // the modify notifications are used as workaround, but only for running state
+ if( aEvent.Source == m_xComponent && m_pEmbedObj && m_pEmbedObj->getCurrentState() == embed::EmbedStates::RUNNING )
+ m_pEmbedObj->PostEvent_Impl( "OnVisAreaChanged" );
+}
+
+
+void SAL_CALL DocumentHolder::notifyEvent( const document::EventObject& Event )
+{
+ if( m_pEmbedObj && Event.Source == m_xComponent )
+ {
+ // for now the ignored events are not forwarded, but sent by the object itself
+ if ( !Event.EventName.startsWith( "OnSave" )
+ && !Event.EventName.startsWith( "OnSaveDone" )
+ && !Event.EventName.startsWith( "OnSaveAs" )
+ && !Event.EventName.startsWith( "OnSaveAsDone" )
+ && !( Event.EventName.startsWith( "OnVisAreaChanged" ) && m_nNoResizeReact ) )
+ m_pEmbedObj->PostEvent_Impl( Event.EventName );
+ }
+}
+
+
+void SAL_CALL DocumentHolder::borderWidthsChanged( const uno::Reference< uno::XInterface >& aObject,
+ const frame::BorderWidths& aNewSize )
+{
+ // TODO: may require mutex introduction ???
+ if ( m_pEmbedObj && m_xFrame.is() && aObject == m_xFrame->getController() )
+ {
+ if ( m_aBorderWidths.Left != aNewSize.Left
+ || m_aBorderWidths.Right != aNewSize.Right
+ || m_aBorderWidths.Top != aNewSize.Top
+ || m_aBorderWidths.Bottom != aNewSize.Bottom )
+ {
+ m_aBorderWidths = aNewSize;
+ if ( !m_nNoBorderResizeReact )
+ PlaceFrame( m_aObjRect );
+ }
+ }
+}
+
+
+void SAL_CALL DocumentHolder::requestPositioning( const awt::Rectangle& aRect )
+{
+ // TODO: may require mutex introduction ???
+ if ( m_pEmbedObj )
+ {
+ // borders should not be counted
+ awt::Rectangle aObjRect = CalculateBorderedArea( aRect );
+ IntCounterGuard aGuard( m_nNoResizeReact );
+ m_pEmbedObj->requestPositioning( aObjRect );
+ }
+}
+
+
+awt::Rectangle SAL_CALL DocumentHolder::calcAdjustedRectangle( const awt::Rectangle& aRect )
+{
+ // Solar mutex should be locked already since this is a call from HatchWindow with focus
+ awt::Rectangle aResult( aRect );
+
+ if ( m_xFrame.is() )
+ {
+ // borders should not be counted
+ uno::Reference< frame::XControllerBorder > xControllerBorder( m_xFrame->getController(), uno::UNO_QUERY );
+ if ( xControllerBorder.is() )
+ {
+ awt::Rectangle aObjRect = CalculateBorderedArea( aRect );
+ aObjRect = xControllerBorder->queryBorderedArea( aObjRect );
+ aResult = AddBorderToArea( aObjRect );
+ }
+ }
+
+ awt::Rectangle aMinRectangle = AddBorderToArea( awt::Rectangle() );
+ if ( aResult.Width < aMinRectangle.Width + 2 )
+ aResult.Width = aMinRectangle.Width + 2;
+ if ( aResult.Height < aMinRectangle.Height + 2 )
+ aResult.Height = aMinRectangle.Height + 2;
+
+ return aResult;
+}
+
+void SAL_CALL DocumentHolder::activated( )
+{
+ if ( !(m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) )
+ return;
+
+ if ( m_pEmbedObj->getCurrentState() != embed::EmbedStates::UI_ACTIVE &&
+ !(m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_NOUIACTIVATE) )
+ {
+ try
+ {
+ m_pEmbedObj->changeState( embed::EmbedStates::UI_ACTIVE );
+ }
+ catch ( const css::embed::StateChangeInProgressException& )
+ {
+ // must catch this exception because focus is grabbed while UI activation in doVerb()
+ }
+ catch ( const css::uno::Exception& )
+ {
+ // no outgoing exceptions specified here
+ }
+ }
+ else
+ {
+ uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
+ if ( xSupp.is() )
+ xSupp->setActiveFrame( m_xFrame );
+ }
+}
+
+void DocumentHolder::ResizeHatchWindow()
+{
+ awt::Rectangle aHatchRect = AddBorderToArea( m_aObjRect );
+ ResizeWindows_Impl( aHatchRect );
+ uno::Reference< embed::XHatchWindow > xHatchWindow( m_xHatchWindow, uno::UNO_QUERY );
+ xHatchWindow->setHatchBorderSize( awt::Size( HATCH_BORDER_WIDTH, HATCH_BORDER_WIDTH ) );
+}
+
+void SAL_CALL DocumentHolder::deactivated( )
+{
+ // deactivation is too unspecific to be useful; usually we only trigger code from activation
+ // so UIDeactivation is actively triggered by the container
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/general/dummyobject.cxx b/embeddedobj/source/general/dummyobject.cxx
new file mode 100644
index 000000000..4d2af144a
--- /dev/null
+++ b/embeddedobj/source/general/dummyobject.cxx
@@ -0,0 +1,638 @@
+/* -*- 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 <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/embed/UnreachableStateException.hpp>
+#include <com/sun/star/embed/WrongStateException.hpp>
+#include <com/sun/star/embed/XEmbeddedClient.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/EmbedMapUnits.hpp>
+#include <com/sun/star/embed/EntryInitModes.hpp>
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <comphelper/multicontainer2.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <dummyobject.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+void ODummyEmbeddedObject::CheckInit_WrongState()
+{
+ if ( m_bDisposed )
+ throw lang::DisposedException();
+
+ if ( m_nObjectState == -1 )
+ throw embed::WrongStateException( "The object has no persistence!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+}
+
+void ODummyEmbeddedObject::CheckInit_Runtime()
+{
+ if ( m_bDisposed )
+ throw lang::DisposedException();
+
+ if ( m_nObjectState == -1 )
+ throw uno::RuntimeException( "The object has no persistence!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+}
+void ODummyEmbeddedObject::PostEvent_Impl( const OUString& aEventName )
+{
+ if ( !m_pInterfaceContainer )
+ return;
+
+ comphelper::OInterfaceContainerHelper2* pIC = m_pInterfaceContainer->getContainer(
+ cppu::UnoType<document::XEventListener>::get());
+ if( !pIC )
+ return;
+
+ document::EventObject aEvent;
+ aEvent.EventName = aEventName;
+ aEvent.Source.set( static_cast< ::cppu::OWeakObject* >( this ) );
+ // For now all the events are sent as object events
+ // aEvent.Source = ( xSource.is() ? xSource
+ // : uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ) );
+ comphelper::OInterfaceIteratorHelper2 aIt( *pIC );
+ while( aIt.hasMoreElements() )
+ {
+ try
+ {
+ static_cast<document::XEventListener *>(aIt.next())->notifyEvent( aEvent );
+ }
+ catch( const uno::RuntimeException& )
+ {
+ aIt.remove();
+ }
+
+ // the listener could dispose the object.
+ if ( m_bDisposed )
+ return;
+ }
+}
+
+
+ODummyEmbeddedObject::~ODummyEmbeddedObject()
+{
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::changeState( sal_Int32 nNewState )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( nNewState == embed::EmbedStates::LOADED )
+ return;
+
+ throw embed::UnreachableStateException();
+}
+
+
+uno::Sequence< sal_Int32 > SAL_CALL ODummyEmbeddedObject::getReachableStates()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ return { embed::EmbedStates::LOADED };
+}
+
+
+sal_Int32 SAL_CALL ODummyEmbeddedObject::getCurrentState()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ return m_nObjectState;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::doVerb( sal_Int32 )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ // no supported verbs
+}
+
+
+uno::Sequence< embed::VerbDescriptor > SAL_CALL ODummyEmbeddedObject::getSupportedVerbs()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ return uno::Sequence< embed::VerbDescriptor >();
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::setClientSite(
+ const uno::Reference< embed::XEmbeddedClient >& xClient )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ m_xClientSite = xClient;
+}
+
+
+uno::Reference< embed::XEmbeddedClient > SAL_CALL ODummyEmbeddedObject::getClientSite()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ return m_xClientSite;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::update()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::setUpdateMode( sal_Int32 )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+}
+
+
+sal_Int64 SAL_CALL ODummyEmbeddedObject::getStatus( sal_Int64 )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ return 0;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::setContainerName( const OUString& )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_Runtime();
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::setVisualAreaSize( sal_Int64 nAspect, const awt::Size& aSize )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!" );
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ // no representation can be retrieved
+ throw embed::WrongStateException( "Illegal call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ m_nCachedAspect = nAspect;
+ m_aCachedSize = aSize;
+ m_bHasCachedSize = true;
+}
+
+
+awt::Size SAL_CALL ODummyEmbeddedObject::getVisualAreaSize( sal_Int64 nAspect )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!" );
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ // no representation can be retrieved
+ throw embed::WrongStateException( "Illegal call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ if ( !m_bHasCachedSize || m_nCachedAspect != nAspect )
+ throw embed::NoVisualAreaSizeException(
+ "No size available!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ return m_aCachedSize;
+}
+
+
+sal_Int32 SAL_CALL ODummyEmbeddedObject::getMapUnit( sal_Int64 nAspect )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_Runtime();
+
+ OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!" );
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ // no representation can be retrieved
+ throw embed::WrongStateException( "Illegal call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ return embed::EmbedMapUnits::ONE_100TH_MM;
+}
+
+
+embed::VisualRepresentation SAL_CALL ODummyEmbeddedObject::getPreferredVisualRepresentation( sal_Int64 )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ // no representation can be retrieved
+ throw embed::WrongStateException( "Illegal call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::setPersistentEntry(
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ sal_Int32 nEntryConnectionMode,
+ const uno::Sequence< beans::PropertyValue >& /* lArguments */,
+ const uno::Sequence< beans::PropertyValue >& /* lObjArgs */ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bDisposed )
+ throw lang::DisposedException(); // TODO
+
+ if ( !xStorage.is() )
+ throw lang::IllegalArgumentException( "No parent storage is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1 );
+
+ if ( sEntName.isEmpty() )
+ throw lang::IllegalArgumentException( "Empty element name is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 2 );
+
+ if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
+ && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
+ {
+ throw embed::WrongStateException(
+ "Can't change persistent representation of activated object!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+ }
+
+ if ( m_bWaitSaveCompleted )
+ {
+ if ( nEntryConnectionMode != embed::EntryInitModes::NO_INIT )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ saveCompleted( m_xParentStorage != xStorage || m_aEntryName != sEntName );
+
+ }
+
+ if ( nEntryConnectionMode != embed::EntryInitModes::DEFAULT_INIT
+ && nEntryConnectionMode != embed::EntryInitModes::NO_INIT )
+ throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 3 );
+
+ if ( !xStorage->hasByName( sEntName ) )
+ throw lang::IllegalArgumentException( "Wrong entry is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 2 );
+
+ m_xParentStorage = xStorage;
+ m_aEntryName = sEntName;
+ m_nObjectState = embed::EmbedStates::LOADED;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ const uno::Sequence< beans::PropertyValue >& /* lArguments */,
+ const uno::Sequence< beans::PropertyValue >& /* lObjArgs */ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ const uno::Sequence< beans::PropertyValue >& /* lArguments */,
+ const uno::Sequence< beans::PropertyValue >& /* lObjArgs */ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ PostEvent_Impl( "OnSaveAs" );
+
+ m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
+
+ m_bWaitSaveCompleted = true;
+ m_xNewParentStorage = xStorage;
+ m_aNewEntryName = sEntName;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::saveCompleted( sal_Bool bUseNew )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ // it is allowed to call saveCompleted( false ) for nonstored objects
+ if ( !m_bWaitSaveCompleted && !bUseNew )
+ return;
+
+ OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!" );
+ if ( !m_bWaitSaveCompleted )
+ throw io::IOException(); // TODO: illegal call
+
+ OSL_ENSURE( m_xNewParentStorage.is() , "Internal object information is broken!" );
+ if ( !m_xNewParentStorage.is() )
+ throw uno::RuntimeException(); // TODO: broken internal information
+
+ if ( bUseNew )
+ {
+ m_xParentStorage = m_xNewParentStorage;
+ m_aEntryName = m_aNewEntryName;
+
+ PostEvent_Impl( "OnSaveAsDone" );
+ }
+
+ m_xNewParentStorage.clear();
+ m_aNewEntryName.clear();
+ m_bWaitSaveCompleted = false;
+}
+
+
+sal_Bool SAL_CALL ODummyEmbeddedObject::hasEntry()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ if ( !m_aEntryName.isEmpty() )
+ return true;
+
+ return false;
+}
+
+
+OUString SAL_CALL ODummyEmbeddedObject::getEntryName()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ return m_aEntryName;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::storeOwn()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ // the object can not be activated or changed
+}
+
+
+sal_Bool SAL_CALL ODummyEmbeddedObject::isReadonly()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ // this object can not be changed
+ return true;
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::reload(
+ const uno::Sequence< beans::PropertyValue >& /* lArguments */,
+ const uno::Sequence< beans::PropertyValue >& /* lObjArgs */ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_WrongState();
+
+ if ( m_bWaitSaveCompleted )
+ throw embed::WrongStateException(
+ "The object waits for saveCompleted() call!",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ // nothing to reload
+}
+
+
+uno::Sequence< sal_Int8 > SAL_CALL ODummyEmbeddedObject::getClassID()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_Runtime();
+
+ // currently the class ID is empty
+ // TODO/LATER: should a special class ID be used in this case?
+ return uno::Sequence< sal_Int8 >();
+}
+
+
+OUString SAL_CALL ODummyEmbeddedObject::getClassName()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bDisposed )
+ throw lang::DisposedException(); // TODO
+
+ return OUString();
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::setClassInfo(
+ const uno::Sequence< sal_Int8 >& /*aClassID*/, const OUString& /*aClassName*/ )
+{
+ throw lang::NoSupportException();
+}
+
+
+uno::Reference< util::XCloseable > SAL_CALL ODummyEmbeddedObject::getComponent()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ CheckInit_Runtime();
+
+ return uno::Reference< util::XCloseable >();
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::addStateChangeListener( const uno::Reference< embed::XStateChangeListener >& xListener )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bDisposed )
+ return;
+
+ if ( !m_pInterfaceContainer )
+ m_pInterfaceContainer.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex ));
+
+ m_pInterfaceContainer->addInterface( cppu::UnoType<embed::XStateChangeListener>::get(),
+ xListener );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::removeStateChangeListener(
+ const uno::Reference< embed::XStateChangeListener >& xListener )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_pInterfaceContainer )
+ m_pInterfaceContainer->removeInterface( cppu::UnoType<embed::XStateChangeListener>::get(),
+ xListener );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::close( sal_Bool bDeliverOwnership )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bDisposed )
+ throw lang::DisposedException(); // TODO
+
+ uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
+ lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
+
+ if ( m_pInterfaceContainer )
+ {
+ comphelper::OInterfaceContainerHelper2* pContainer =
+ m_pInterfaceContainer->getContainer( cppu::UnoType<util::XCloseListener>::get());
+ if ( pContainer != nullptr )
+ {
+ comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ static_cast<util::XCloseListener*>(pIterator.next())->queryClosing( aSource, bDeliverOwnership );
+ }
+ catch( const uno::RuntimeException& )
+ {
+ pIterator.remove();
+ }
+ }
+ }
+
+ pContainer = m_pInterfaceContainer->getContainer(
+ cppu::UnoType<util::XCloseListener>::get());
+ if ( pContainer != nullptr )
+ {
+ comphelper::OInterfaceIteratorHelper2 pCloseIterator(*pContainer);
+ while (pCloseIterator.hasMoreElements())
+ {
+ try
+ {
+ static_cast<util::XCloseListener*>(pCloseIterator.next())->notifyClosing( aSource );
+ }
+ catch( const uno::RuntimeException& )
+ {
+ pCloseIterator.remove();
+ }
+ }
+ }
+
+ m_pInterfaceContainer->disposeAndClear( aSource );
+ }
+
+ m_bDisposed = true; // the object is disposed now for outside
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::addCloseListener( const uno::Reference< util::XCloseListener >& xListener )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bDisposed )
+ return;
+
+ if ( !m_pInterfaceContainer )
+ m_pInterfaceContainer.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex ));
+
+ m_pInterfaceContainer->addInterface( cppu::UnoType<util::XCloseListener>::get(), xListener );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_pInterfaceContainer )
+ m_pInterfaceContainer->removeInterface( cppu::UnoType<util::XCloseListener>::get(),
+ xListener );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::addEventListener( const uno::Reference< document::XEventListener >& xListener )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bDisposed )
+ return;
+
+ if ( !m_pInterfaceContainer )
+ m_pInterfaceContainer.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex ));
+
+ m_pInterfaceContainer->addInterface( cppu::UnoType<document::XEventListener>::get(), xListener );
+}
+
+
+void SAL_CALL ODummyEmbeddedObject::removeEventListener( const uno::Reference< document::XEventListener >& xListener )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_pInterfaceContainer )
+ m_pInterfaceContainer->removeInterface( cppu::UnoType<document::XEventListener>::get(),
+ xListener );
+}
+
+OUString SAL_CALL ODummyEmbeddedObject::getImplementationName()
+{
+ return "com.sun.star.comp.embed.ODummyEmbeddedObject";
+}
+
+sal_Bool SAL_CALL ODummyEmbeddedObject::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ODummyEmbeddedObject::getSupportedServiceNames()
+{
+ return { "com.sun.star.comp.embed.ODummyEmbeddedObject" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/general/intercept.cxx b/embeddedobj/source/general/intercept.cxx
new file mode 100644
index 000000000..58a7ed49b
--- /dev/null
+++ b/embeddedobj/source/general/intercept.cxx
@@ -0,0 +1,312 @@
+/* -*- 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 <com/sun/star/embed/EmbedStates.hpp>
+#include <comphelper/multiinterfacecontainer3.hxx>
+
+#include <intercept.hxx>
+#include <docholder.hxx>
+#include <commonembobj.hxx>
+
+using namespace ::com::sun::star;
+
+constexpr OUStringLiteral IU0 = u".uno:Save";
+constexpr OUStringLiteral IU1 = u".uno:SaveAll";
+constexpr OUStringLiteral IU2 = u".uno:CloseDoc";
+constexpr OUStringLiteral IU3 = u".uno:CloseWin";
+constexpr OUStringLiteral IU4 = u".uno:CloseFrame";
+constexpr OUStringLiteral IU5 = u".uno:SaveAs";
+const uno::Sequence< OUString > Interceptor::m_aInterceptedURL{ IU0, IU1, IU2, IU3, IU4, IU5 };
+
+class StatusChangeListenerContainer
+ : public comphelper::OMultiTypeInterfaceContainerHelperVar3<frame::XStatusListener, OUString>
+{
+public:
+ explicit StatusChangeListenerContainer(osl::Mutex& aMutex)
+ : comphelper::OMultiTypeInterfaceContainerHelperVar3<frame::XStatusListener, OUString>(aMutex)
+ {
+ }
+};
+
+void Interceptor::DisconnectDocHolder()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+ m_pDocHolder = nullptr;
+}
+
+Interceptor::Interceptor( DocumentHolder* pDocHolder )
+ : m_pDocHolder( pDocHolder )
+{
+}
+
+Interceptor::~Interceptor()
+{
+}
+
+//XDispatch
+void SAL_CALL
+Interceptor::dispatch(
+ const util::URL& URL,
+ const uno::Sequence<
+ beans::PropertyValue >& Arguments )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ if( !m_pDocHolder )
+ return;
+
+ if(URL.Complete == m_aInterceptedURL[0])
+ m_pDocHolder->GetEmbedObject()->SaveObject_Impl();
+ else if(URL.Complete == m_aInterceptedURL[2] ||
+ URL.Complete == m_aInterceptedURL[3] ||
+ URL.Complete == m_aInterceptedURL[4])
+ {
+ try {
+ m_pDocHolder->GetEmbedObject()->changeState( embed::EmbedStates::RUNNING );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ else if ( URL.Complete == m_aInterceptedURL[5] )
+ {
+ uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
+ sal_Int32 nInd = 0;
+
+ while( nInd < aNewArgs.getLength() )
+ {
+ if ( aNewArgs[nInd].Name == "SaveTo" )
+ {
+ aNewArgs.getArray()[nInd].Value <<= true;
+ break;
+ }
+ nInd++;
+ }
+
+ if ( nInd == aNewArgs.getLength() )
+ {
+ aNewArgs.realloc( nInd + 1 );
+ auto pNewArgs = aNewArgs.getArray();
+ pNewArgs[nInd].Name = "SaveTo";
+ pNewArgs[nInd].Value <<= true;
+ }
+
+ uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
+ URL, "_self", 0 );
+ if ( xDispatch.is() )
+ xDispatch->dispatch( URL, aNewArgs );
+ }
+}
+
+void SAL_CALL
+Interceptor::addStatusListener(
+ const uno::Reference<
+ frame::XStatusListener >& Control,
+ const util::URL& URL )
+{
+ if(!Control.is())
+ return;
+
+ if(URL.Complete == m_aInterceptedURL[0])
+ { // Save
+ frame::FeatureStateEvent aStateEvent;
+ aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
+ aStateEvent.FeatureDescriptor = "Update";
+ aStateEvent.IsEnabled = true;
+ aStateEvent.Requery = false;
+ aStateEvent.State <<= "($1) " + m_pDocHolder->GetTitle();
+ Control->statusChanged(aStateEvent);
+
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ if(!m_pStatCL)
+ m_pStatCL.reset(new StatusChangeListenerContainer(m_aMutex));
+ }
+
+ m_pStatCL->addInterface(URL.Complete,Control);
+ return;
+ }
+
+ sal_Int32 i = 2;
+ if(URL.Complete == m_aInterceptedURL[i] ||
+ URL.Complete == m_aInterceptedURL[++i] ||
+ URL.Complete == m_aInterceptedURL[++i] )
+ { // Close and return
+ frame::FeatureStateEvent aStateEvent;
+ aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
+ aStateEvent.FeatureDescriptor = "Close and Return";
+ aStateEvent.IsEnabled = true;
+ aStateEvent.Requery = false;
+ aStateEvent.State <<= "($2)" + m_pDocHolder->GetContainerName();
+ Control->statusChanged(aStateEvent);
+
+
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ if(!m_pStatCL)
+ m_pStatCL.reset(new StatusChangeListenerContainer(m_aMutex));
+ }
+
+ m_pStatCL->addInterface(URL.Complete,Control);
+ return;
+ }
+
+ if(URL.Complete != m_aInterceptedURL[5])
+ return;
+
+// SaveAs
+ frame::FeatureStateEvent aStateEvent;
+ aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
+ aStateEvent.FeatureDescriptor = "SaveCopyTo";
+ aStateEvent.IsEnabled = true;
+ aStateEvent.Requery = false;
+ aStateEvent.State <<= OUString("($3)");
+ Control->statusChanged(aStateEvent);
+
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ if(!m_pStatCL)
+ m_pStatCL.reset(new StatusChangeListenerContainer(m_aMutex));
+ }
+
+ m_pStatCL->addInterface(URL.Complete,Control);
+ return;
+
+}
+
+
+void SAL_CALL
+Interceptor::removeStatusListener(
+ const uno::Reference<
+ frame::XStatusListener >& Control,
+ const util::URL& URL )
+{
+ if(!(Control.is() && m_pStatCL))
+ return;
+ else {
+ m_pStatCL->removeInterface(URL.Complete,Control);
+ return;
+ }
+}
+
+
+//XInterceptorInfo
+uno::Sequence< OUString >
+SAL_CALL
+Interceptor::getInterceptedURLs( )
+{
+ // now implemented as update
+
+ return m_aInterceptedURL;
+}
+
+
+// XDispatchProvider
+
+uno::Reference< frame::XDispatch > SAL_CALL
+Interceptor::queryDispatch(
+ const util::URL& URL,
+ const OUString& TargetFrameName,
+ sal_Int32 SearchFlags )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ if(URL.Complete == m_aInterceptedURL[0])
+ return static_cast<frame::XDispatch*>(this);
+ else if(URL.Complete == m_aInterceptedURL[1])
+ return nullptr ;
+ else if(URL.Complete == m_aInterceptedURL[2])
+ return static_cast<frame::XDispatch*>(this);
+ else if(URL.Complete == m_aInterceptedURL[3])
+ return static_cast<frame::XDispatch*>(this);
+ else if(URL.Complete == m_aInterceptedURL[4])
+ return static_cast<frame::XDispatch*>(this);
+ else if(URL.Complete == m_aInterceptedURL[5])
+ return static_cast<frame::XDispatch*>(this);
+ else {
+ if(m_xSlaveDispatchProvider.is())
+ return m_xSlaveDispatchProvider->queryDispatch(
+ URL,TargetFrameName,SearchFlags);
+ else
+ return uno::Reference<frame::XDispatch>(nullptr);
+ }
+}
+
+uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
+Interceptor::queryDispatches(
+ const uno::Sequence<frame::DispatchDescriptor >& Requests )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ typedef uno::Sequence<uno::Reference<frame::XDispatch>> DispatchSeq;
+ DispatchSeq aRet = m_xSlaveDispatchProvider.is()
+ ? m_xSlaveDispatchProvider->queryDispatches(Requests)
+ : DispatchSeq(Requests.getLength());
+
+ auto aRetRange = asNonConstRange(aRet);
+ for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
+ if(m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete)
+ aRetRange[i] = static_cast<frame::XDispatch*>(this);
+ else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
+ aRetRange[i] = nullptr;
+ else if(m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete)
+ aRetRange[i] = static_cast<frame::XDispatch*>(this);
+ else if(m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete)
+ aRetRange[i] = static_cast<frame::XDispatch*>(this);
+ else if(m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete)
+ aRetRange[i] = static_cast<frame::XDispatch*>(this);
+ else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
+ aRetRange[i] = static_cast<frame::XDispatch*>(this);
+
+ return aRet;
+}
+
+
+//XDispatchProviderInterceptor
+
+uno::Reference< frame::XDispatchProvider > SAL_CALL
+Interceptor::getSlaveDispatchProvider( )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_xSlaveDispatchProvider;
+}
+
+void SAL_CALL
+Interceptor::setSlaveDispatchProvider(
+ const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xSlaveDispatchProvider = NewDispatchProvider;
+}
+
+
+uno::Reference< frame::XDispatchProvider > SAL_CALL
+Interceptor::getMasterDispatchProvider( )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_xMasterDispatchProvider;
+}
+
+
+void SAL_CALL
+Interceptor::setMasterDispatchProvider(
+ const uno::Reference< frame::XDispatchProvider >& NewSupplier )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xMasterDispatchProvider = NewSupplier;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/general/xcreator.cxx b/embeddedobj/source/general/xcreator.cxx
new file mode 100644
index 000000000..c4a8635e4
--- /dev/null
+++ b/embeddedobj/source/general/xcreator.cxx
@@ -0,0 +1,413 @@
+/* -*- 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 <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/EntryInitModes.hpp>
+#include <com/sun/star/embed/XEmbedObjectFactory.hpp>
+#include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
+#include <com/sun/star/embed/OLEEmbeddedObjectFactory.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <comphelper/documentconstants.hxx>
+#include <officecfg/Office/Common.hxx>
+
+#include <xcreator.hxx>
+#include <dummyobject.hxx>
+
+
+using namespace ::com::sun::star;
+
+uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitNew(
+ const uno::Sequence< sal_Int8 >& aClassID,
+ const OUString& aClassName,
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ const uno::Sequence< beans::PropertyValue >& lObjArgs )
+{
+ if ( !xStorage.is() )
+ throw lang::IllegalArgumentException( "No parent storage is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 3 );
+
+ if ( sEntName.isEmpty() )
+ throw lang::IllegalArgumentException( "Empty element name is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 4 );
+
+ OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID );
+ if ( aEmbedFactory.isEmpty() )
+ {
+ // use system fallback
+ // TODO: in future users factories can be tested
+ aEmbedFactory = "com.sun.star.embed.OLEEmbeddedObjectFactory";
+ }
+
+ uno::Reference < uno::XInterface > xFact( m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext) );
+ uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY );
+ if ( xEmbCreator.is() )
+ return xEmbCreator->createInstanceInitNew( aClassID, aClassName, xStorage, sEntName, lObjArgs );
+
+ uno::Reference < embed::XEmbedObjectFactory > xEmbFact( xFact, uno::UNO_QUERY_THROW );
+ return xEmbFact->createInstanceUserInit( aClassID, aClassName, xStorage, sEntName, embed::EntryInitModes::TRUNCATE_INIT, uno::Sequence < beans::PropertyValue >(), lObjArgs);
+}
+
+
+uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitFromEntry(
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ const uno::Sequence< beans::PropertyValue >& aMedDescr,
+ const uno::Sequence< beans::PropertyValue >& lObjArgs )
+{
+ if ( !xStorage.is() )
+ throw lang::IllegalArgumentException( "No parent storage is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1 );
+
+ if ( sEntName.isEmpty() )
+ throw lang::IllegalArgumentException( "Empty element name is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 2 );
+
+ uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY_THROW );
+
+ // detect entry existence
+ if ( !xNameAccess->hasByName( sEntName ) )
+ throw container::NoSuchElementException();
+
+ OUString aMediaType;
+ OUString aEmbedFactory;
+ if ( xStorage->isStorageElement( sEntName ) )
+ {
+ // the object must be based on storage
+ uno::Reference< embed::XStorage > xSubStorage =
+ xStorage->openStorageElement( sEntName, embed::ElementModes::READ );
+
+ uno::Reference< beans::XPropertySet > xPropSet( xSubStorage, uno::UNO_QUERY_THROW );
+
+ try {
+ uno::Any aAny = xPropSet->getPropertyValue("MediaType");
+ aAny >>= aMediaType;
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+
+ try {
+ if ( xSubStorage.is() )
+ xSubStorage->dispose();
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+ }
+ else
+ {
+ // the object must be based on stream
+ // it means for now that this is an OLE object
+
+ // the object will be created as embedded object
+ // after it is loaded it can detect that it is a link
+
+ uno::Reference< io::XStream > xSubStream =
+ xStorage->openStreamElement( sEntName, embed::ElementModes::READ );
+
+ uno::Reference< beans::XPropertySet > xPropSet( xSubStream, uno::UNO_QUERY_THROW );
+
+ try {
+ uno::Any aAny = xPropSet->getPropertyValue("MediaType");
+ aAny >>= aMediaType;
+ if ( aMediaType == "application/vnd.sun.star.oleobject" )
+ aEmbedFactory = "com.sun.star.embed.OLEEmbeddedObjectFactory";
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+
+ try {
+ uno::Reference< lang::XComponent > xComp( xSubStream, uno::UNO_QUERY );
+ if ( xComp.is() )
+ xComp->dispose();
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+ }
+
+ OSL_ENSURE( !aMediaType.isEmpty(), "No media type is specified for the object!" );
+ if ( !aMediaType.isEmpty() && aEmbedFactory.isEmpty() )
+ {
+ aEmbedFactory = m_aConfigHelper.GetFactoryNameByMediaType( aMediaType );
+
+ // If no factory is found, fall back to the FileFormatVersion=6200 filter, Base only has that.
+ if (aEmbedFactory.isEmpty() && aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII)
+ aEmbedFactory = m_aConfigHelper.GetFactoryNameByMediaType(MIMETYPE_VND_SUN_XML_BASE_ASCII);
+ }
+
+ if ( !aEmbedFactory.isEmpty() )
+ {
+ uno::Reference< uno::XInterface > xFact = m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext);
+
+ uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY );
+ if ( xEmbCreator.is() )
+ return xEmbCreator->createInstanceInitFromEntry( xStorage, sEntName, aMedDescr, lObjArgs );
+
+ uno::Reference < embed::XEmbedObjectFactory > xEmbFact( xFact, uno::UNO_QUERY );
+ if ( xEmbFact.is() )
+ return xEmbFact->createInstanceUserInit( uno::Sequence< sal_Int8 >(), OUString(), xStorage, sEntName, embed::EntryInitModes::DEFAULT_INIT, aMedDescr, lObjArgs);
+ }
+
+ // the default object should be created, it will allow to store the contents on the next saving
+ uno::Reference< uno::XInterface > xResult( static_cast< cppu::OWeakObject* >( new ODummyEmbeddedObject() ) );
+ uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY_THROW );
+ xPersist->setPersistentEntry( xStorage, sEntName, embed::EntryInitModes::DEFAULT_INIT, aMedDescr, lObjArgs );
+ return xResult;
+}
+
+/**
+ * Decides if rFilter should be used to load data into a doc model or real OLE embedding should
+ * happen. Empty return value means the later.
+ */
+static OUString HandleFilter(const OUString& rFilter)
+{
+ OUString aRet = rFilter;
+
+ if (!officecfg::Office::Common::Filter::Microsoft::Import::WinWordToWriter::get())
+ {
+ if (rFilter == "MS Word 97" || rFilter == "MS Word 2007 XML")
+ {
+ aRet.clear();
+ }
+ }
+
+ if (!officecfg::Office::Common::Filter::Microsoft::Import::ExcelToCalc::get())
+ {
+ if (rFilter == "MS Excel 97" || rFilter == "Calc MS Excel 2007 XML")
+ {
+ aRet.clear();
+ }
+ }
+ if (!officecfg::Office::Common::Filter::Microsoft::Import::PowerPointToImpress::get())
+ {
+ if (rFilter == "MS PowerPoint 97" || rFilter == "Impress MS PowerPoint 2007 XML")
+ {
+ aRet.clear();
+ }
+ }
+ if (!officecfg::Office::Common::Filter::Microsoft::Import::VisioToDraw::get())
+ {
+ if (rFilter == "Visio Document")
+ {
+ aRet.clear();
+ }
+ }
+ if (!officecfg::Office::Common::Filter::Adobe::Import::PDFToDraw::get())
+ {
+ if (rFilter == "draw_pdf_import")
+ {
+ aRet.clear();
+ }
+ }
+
+ return aRet;
+}
+
+uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitFromMediaDescriptor(
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ const uno::Sequence< beans::PropertyValue >& aMediaDescr,
+ const uno::Sequence< beans::PropertyValue >& lObjArgs )
+{
+ // TODO: use lObjArgs
+
+ if ( !xStorage.is() )
+ throw lang::IllegalArgumentException( "No parent storage is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 1 );
+
+ if ( sEntName.isEmpty() )
+ throw lang::IllegalArgumentException( "Empty element name is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 2 );
+
+ uno::Reference< uno::XInterface > xResult;
+ uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr );
+
+ // check if there is FilterName
+ OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, false );
+
+ aFilterName = HandleFilter(aFilterName);
+
+ if ( !aFilterName.isEmpty() )
+ {
+ // the object can be loaded by one of the office application
+ uno::Reference< embed::XEmbeddedObjectCreator > xOOoEmbCreator =
+ embed::OOoEmbeddedObjectFactory::create( m_xContext );
+
+ xResult = xOOoEmbCreator->createInstanceInitFromMediaDescriptor( xStorage,
+ sEntName,
+ aTempMedDescr,
+ lObjArgs );
+ }
+ else
+ {
+ // must be an OLE object
+
+ // TODO: in future, when more object types are possible this place seems
+ // to be a weak one, probably configuration must provide a type detection service
+ // for every factory, so any file could go through services until it is recognized
+ // or there is no more services
+ // Or for example the typename can be used to detect object type if typedetection
+ // was also extended.
+
+ uno::Reference< embed::XEmbeddedObjectCreator > xOleEmbCreator =
+ embed::OLEEmbeddedObjectFactory::create( m_xContext );
+
+ xResult = xOleEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aTempMedDescr, lObjArgs );
+ }
+
+ return xResult;
+}
+
+
+uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceUserInit(
+ const uno::Sequence< sal_Int8 >& aClassID,
+ const OUString& sClassName,
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ sal_Int32 nEntryConnectionMode,
+ const uno::Sequence< beans::PropertyValue >& aArgs,
+ const uno::Sequence< beans::PropertyValue >& aObjectArgs )
+{
+ if ( !xStorage.is() )
+ throw lang::IllegalArgumentException( "No parent storage is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 3 );
+
+ if ( sEntName.isEmpty() )
+ throw lang::IllegalArgumentException( "Empty element name is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 4 );
+
+ OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID );
+ uno::Reference< embed::XEmbedObjectFactory > xEmbFactory(
+ m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext),
+ uno::UNO_QUERY_THROW );
+
+ return xEmbFactory->createInstanceUserInit( aClassID,
+ sClassName,
+ xStorage,
+ sEntName,
+ nEntryConnectionMode,
+ aArgs,
+ aObjectArgs );
+}
+
+
+uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceLink(
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& sEntName,
+ const uno::Sequence< beans::PropertyValue >& aMediaDescr,
+ const uno::Sequence< beans::PropertyValue >& lObjArgs )
+{
+ uno::Reference< uno::XInterface > xResult;
+
+ uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr );
+
+ // check if there is URL, URL must exist
+ OUString aURL;
+ for ( beans::PropertyValue const & prop : std::as_const(aTempMedDescr) )
+ if ( prop.Name == "URL" )
+ prop.Value >>= aURL;
+
+ if ( aURL.isEmpty() )
+ throw lang::IllegalArgumentException( "No URL for the link is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 3 );
+
+ OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, false );
+
+ if ( !aFilterName.isEmpty() )
+ {
+ // the object can be loaded by one of the office application
+ uno::Reference< embed::XEmbeddedObjectCreator > xOOoLinkCreator =
+ embed::OOoEmbeddedObjectFactory::create( m_xContext );
+
+ xResult = xOOoLinkCreator->createInstanceLink( xStorage,
+ sEntName,
+ aTempMedDescr,
+ lObjArgs );
+ }
+ else
+ {
+ // must be an OLE link
+
+ // TODO: in future, when more object types are possible this place seems
+ // to be a weak one, probably configuration must provide a type detection service
+ // for every factory, so any file could go through services until it is recognized
+ // or there is no more services
+ // Or for example the typename can be used to detect object type if typedetection
+ // was also extended.
+
+ if ( !xStorage.is() )
+ throw lang::IllegalArgumentException( "No parent storage is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 3 );
+
+ if ( sEntName.isEmpty() )
+ throw lang::IllegalArgumentException( "Empty element name is provided!",
+ static_cast< ::cppu::OWeakObject* >(this),
+ 4 );
+
+ uno::Reference< embed::XEmbeddedObjectCreator > xLinkCreator =
+ embed::OLEEmbeddedObjectFactory::create( m_xContext);
+
+ xResult = xLinkCreator->createInstanceLink( xStorage, sEntName, aTempMedDescr, lObjArgs );
+ }
+
+ return xResult;
+}
+
+OUString SAL_CALL UNOEmbeddedObjectCreator::getImplementationName()
+{
+ return "com.sun.star.comp.embed.EmbeddedObjectCreator";
+}
+
+sal_Bool SAL_CALL UNOEmbeddedObjectCreator::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL UNOEmbeddedObjectCreator::getSupportedServiceNames()
+{
+ return { "com.sun.star.embed.EmbeddedObjectCreator", "com.sun.star.comp.embed.EmbeddedObjectCreator" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+embeddedobj_UNOEmbeddedObjectCreator_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new UNOEmbeddedObjectCreator(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */