summaryrefslogtreecommitdiff
path: root/framework/source/services/desktop.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/services/desktop.cxx')
-rw-r--r--framework/source/services/desktop.cxx2038
1 files changed, 2038 insertions, 0 deletions
diff --git a/framework/source/services/desktop.cxx b/framework/source/services/desktop.cxx
new file mode 100644
index 000000000000..3c89661af599
--- /dev/null
+++ b/framework/source/services/desktop.cxx
@@ -0,0 +1,2038 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <loadenv/loadenv.hxx>
+
+#ifndef __FRAMEWORK_LOADENV_TARGETHELPER_HXX_
+#include <loadenv/targethelper.hxx>
+#endif
+
+#ifndef __FRAMEWORK_DESKTOP_HXX_
+#include <services/desktop.hxx>
+#endif
+#include <helper/ocomponentaccess.hxx>
+#include <dispatch/dispatchprovider.hxx>
+
+#ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_
+#include <dispatch/interceptionhelper.hxx>
+#endif
+#include <classes/taskcreator.hxx>
+#include <threadhelp/transactionguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <threadhelp/readguard.hxx>
+#include <services.h>
+#include <general.h>
+#include <properties.h>
+
+#include <classes/resource.hrc>
+#include <classes/fwkresid.hxx>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/awt/XToolkit.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/task/XInteractionAbort.hpp>
+#include <com/sun/star/task/XInteractionApprove.hpp>
+#include <com/sun/star/document/XInteractionFilterSelect.hpp>
+#include <com/sun/star/document/AmbigousFilterRequest.hpp>
+#include <com/sun/star/task/ErrorCodeRequest.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/frame/XNotifyingDispatch.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <com/sun/star/frame/XTerminateListener2.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/proptypehlp.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/logfile.hxx>
+#include <vcl/svapp.hxx>
+
+#ifndef __RSC
+#include <tools/errinf.hxx>
+#endif
+#include <comphelper/extract.hxx>
+
+#include <fwkdllapi.h>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+DEFINE_XINTERFACE_15 ( Desktop ,
+ OWeakObject ,
+ DIRECT_INTERFACE( css::lang::XTypeProvider ),
+ DIRECT_INTERFACE( css::lang::XServiceInfo ),
+ DIRECT_INTERFACE( css::frame::XDesktop ),
+ DIRECT_INTERFACE( css::frame::XComponentLoader ),
+ DIRECT_INTERFACE( css::frame::XTasksSupplier ),
+ DIRECT_INTERFACE( css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE( css::frame::XDispatchProviderInterception),
+ DIRECT_INTERFACE( css::frame::XFramesSupplier ),
+ DIRECT_INTERFACE( css::frame::XFrame ),
+ DIRECT_INTERFACE( css::lang::XComponent ),
+ DIRECT_INTERFACE( css::frame::XDispatchResultListener ),
+ DIRECT_INTERFACE( css::lang::XEventListener ),
+ DIRECT_INTERFACE( css::task::XInteractionHandler ),
+ DIRECT_INTERFACE( css::beans::XPropertySet ),
+ DIRECT_INTERFACE( css::frame::XUntitledNumbers )
+ )
+
+DEFINE_XTYPEPROVIDER_15 ( Desktop ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XDesktop ,
+ css::frame::XComponentLoader ,
+ css::frame::XTasksSupplier ,
+ css::frame::XDispatchProvider ,
+ css::frame::XDispatchProviderInterception ,
+ css::frame::XFramesSupplier ,
+ css::frame::XFrame ,
+ css::lang::XComponent ,
+ css::frame::XDispatchResultListener ,
+ css::lang::XEventListener ,
+ css::task::XInteractionHandler ,
+ css::beans::XPropertySet ,
+ css::frame::XUntitledNumbers
+ )
+
+DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( Desktop ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_DESKTOP ,
+ IMPLEMENTATIONNAME_DESKTOP
+ )
+
+DEFINE_INIT_SERVICE ( Desktop,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess.
+ // We hold member as reference ... not as pointer too!
+ // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that.
+ // But look on dispose() for right order of deinitialization.
+ OFrames* pFramesHelper = new OFrames( m_xFactory, this, &m_aChildTaskContainer );
+ m_xFramesHelper = css::uno::Reference< css::frame::XFrames >( static_cast< ::cppu::OWeakObject* >(pFramesHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new dispatchhelper-object to handle dispatches.
+ // We use these helper as slave for our interceptor helper ... not directly!
+ // But he is event listener on THIS instance!
+ DispatchProvider* pDispatchHelper = new DispatchProvider( m_xFactory, this );
+ css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( static_cast< ::cppu::OWeakObject* >(pDispatchHelper), css::uno::UNO_QUERY );
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism.
+ // Set created dispatch provider as slowest slave of it.
+ // Hold interception helper by reference only - not by pointer!
+ // So it's easiear to destroy it.
+ InterceptionHelper* pInterceptionHelper = new InterceptionHelper( this, xDispatchProvider );
+ m_xDispatchHelper = css::uno::Reference< css::frame::XDispatchProvider >( static_cast< ::cppu::OWeakObject* >(pInterceptionHelper), css::uno::UNO_QUERY );
+
+ ::rtl::OUStringBuffer sUntitledPrefix (256);
+ sUntitledPrefix.append (::rtl::OUString( String( FwkResId( STR_UNTITLED_DOCUMENT ))));
+ sUntitledPrefix.appendAscii (" ");
+
+ ::comphelper::NumberedCollection* pNumbers = new ::comphelper::NumberedCollection ();
+ m_xTitleNumberGenerator = css::uno::Reference< css::frame::XUntitledNumbers >(static_cast< ::cppu::OWeakObject* >(pNumbers), css::uno::UNO_QUERY_THROW);
+ pNumbers->setOwner ( static_cast< ::cppu::OWeakObject* >(this) );
+ pNumbers->setUntitledPrefix ( sUntitledPrefix.makeStringAndClear () );
+
+ // Safe impossible cases
+ // We can't work without this helper!
+ LOG_ASSERT2( m_xFramesHelper.is ()==sal_False, "Desktop::Desktop()", "Frames helper is not valid. XFrames, XIndexAccess and XElementAcces are not supported!\n")
+ LOG_ASSERT2( m_xDispatchHelper.is()==sal_False, "Desktop::Desktop()", "Dispatch helper is not valid. XDispatch will not work correctly!\n" )
+
+ // Enable object for real working!
+ // Otherwise all calls will be rejected ...
+ m_aTransactionManager.setWorkingMode( E_WORK );
+ }
+ )
+
+/*-************************************************************************************************************//**
+ @short standard constructor to create instance by factory
+ @descr This constructor initialize a new instance of this class by valid factory,
+ and will be set valid values on his member and baseclasses.
+
+ @attention a) Don't use your own reference during an UNO-Service-ctor! There is no guarantee, that you
+ will get over this. (e.g. using of your reference as parameter to initialize some member)
+ Do such things in DEFINE_INIT_SERVICE() method, which is called automaticly after your ctor!!!
+ b) Baseclass OBroadcastHelper is a typedef in namespace cppu!
+ The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
+ If we write it without a namespace or expand the typedef to OBrodcastHelperVar<...> -> it will be OK!?
+ I don't know why! (other compiler not tested .. but it works!)
+
+ @seealso method DEFINE_INIT_SERVICE()
+
+ @param "xFactory" is the multi service manager, which create this instance.
+ The value must be different from NULL!
+ @return -
+
+ @onerror We throw an ASSERT in debug version or do nothing in relaese version.
+*//*-*************************************************************************************************************/
+Desktop::Desktop( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ // Attention: Don't change order of initialization!
+ // ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
+ // We must garant right initialization and a valid value of this to initialize other baseclasses!
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , TransactionBase ( )
+ , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType > ( m_aLock.getShareableOslMutex() )
+ , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) )
+ , ::cppu::OWeakObject ( )
+ // Init member
+ #ifdef ENABLE_ASSERTIONS
+ , m_bIsTerminated ( sal_False ) // see dispose() for further informations!
+ #endif
+ , m_xFactory ( xFactory )
+ , m_aChildTaskContainer ( )
+ , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
+ , m_xFramesHelper ( )
+ , m_xDispatchHelper ( )
+ , m_eLoadState ( E_NOTSET )
+ , m_xLastFrame ( )
+ , m_aInteractionRequest ( )
+ , m_bSuspendQuickstartVeto( sal_False )
+ , m_aCommandOptions ( )
+ , m_sName ( )
+ , m_sTitle ( )
+ , m_xDispatchRecorderSupplier( )
+ , m_xPipeTerminator ( )
+ , m_xQuickLauncher ( )
+ , m_xSWThreadManager ( )
+ , m_xSfxTerminator ( )
+ , m_xTitleNumberGenerator ( )
+{
+ // Safe impossible cases
+ // We don't accept all incoming parameter.
+ LOG_ASSERT2( implcp_ctor( xFactory ), "Desktop::Desktop()", "Invalid parameter detected!")
+}
+
+/*-************************************************************************************************************//**
+ @short standard destructor
+ @descr This one do NOTHING! Use dispose() instaed of this.
+
+ @seealso method dispose()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+Desktop::~Desktop()
+{
+ LOG_ASSERT2( m_bIsTerminated ==sal_False, "Desktop::~Desktop()", "Who forgot to terminate the desktop service?" )
+ LOG_ASSERT2( m_aTransactionManager.getWorkingMode()!=E_CLOSE , "Desktop::~Desktop()", "Who forgot to dispose this service?" )
+}
+
+//=============================================================================
+sal_Bool SAL_CALL Desktop::terminate()
+ throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ SYNCHRONIZED_START
+ ReadGuard aReadLock( m_aLock );
+
+ css::uno::Reference< css::frame::XTerminateListener > xPipeTerminator = m_xPipeTerminator;
+ css::uno::Reference< css::frame::XTerminateListener > xQuickLauncher = m_xQuickLauncher;
+ css::uno::Reference< css::frame::XTerminateListener > xSWThreadManager = m_xSWThreadManager;
+ css::uno::Reference< css::frame::XTerminateListener > xSfxTerminator = m_xSfxTerminator;
+
+ css::lang::EventObject aEvent ( static_cast< ::cppu::OWeakObject* >(this) );
+ ::sal_Bool bAskQuickStart = !m_bSuspendQuickstartVeto ;
+
+ aReadLock.unlock();
+ SYNCHRONIZED_END
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Ask normal terminate listener. They could stop terminate without closing any open document.
+ Desktop::TTerminateListenerList lCalledTerminationListener;
+ ::sal_Bool bVeto = sal_False;
+ impl_sendQueryTerminationEvent(lCalledTerminationListener, bVeto);
+ if ( bVeto )
+ {
+ impl_sendCancelTerminationEvent(lCalledTerminationListener);
+ return sal_False;
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // try to close all open frames.
+ // Allow using of any UI ... because Desktop.terminate() was designed as UI functionality in the past.
+ ::sal_Bool bAllowUI = sal_True;
+ ::sal_Bool bFramesClosed = impl_closeFrames(bAllowUI);
+ if ( ! bFramesClosed )
+ {
+ impl_sendCancelTerminationEvent(lCalledTerminationListener);
+ return sal_False;
+ }
+
+ //-------------------------------------------------------------------------------------------------------------
+ // Normal listener had no problem ...
+ // all frames was closed ...
+ // now it's time to ask our specialized listener.
+ // They are handled these way because they wish to hinder the office on termination
+ // but they wish also closing of all frames.
+
+ // Note further:
+ // We shouldn't ask quicklauncher in case it was allowed from outside only.
+ // This is special trick to "ignore existing quick starter" for debug purposes.
+
+ // Attention:
+ // Order of alled listener is important !
+ // some of them are harmless .-)
+ // But some of them can be dangerous. E.g. it would be dangerous if we close our pipe
+ // and dont terminate in real because another listener throws a veto exception .-)
+
+ ::sal_Bool bTerminate = sal_False;
+ try
+ {
+ if(
+ ( bAskQuickStart ) &&
+ ( xQuickLauncher.is() )
+ )
+ {
+ xQuickLauncher->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xQuickLauncher );
+ }
+
+ if ( xSWThreadManager.is() )
+ {
+ xSWThreadManager->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xSWThreadManager );
+ }
+
+ if ( xPipeTerminator.is() )
+ {
+ xPipeTerminator->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xPipeTerminator );
+ }
+
+ if ( xSfxTerminator.is() )
+ {
+ xSfxTerminator->queryTermination( aEvent );
+ lCalledTerminationListener.push_back( xSfxTerminator );
+ }
+
+ bTerminate = sal_True;
+ }
+ catch(const css::frame::TerminationVetoException&)
+ {
+ bTerminate = sal_False;
+ }
+
+ if ( ! bTerminate )
+ impl_sendCancelTerminationEvent(lCalledTerminationListener);
+ else
+ {
+ #ifdef ENABLE_ASSERTIONS
+ // "Protect" us against dispose before terminate calls!
+ // see dispose() for further informations.
+ /* SAFE AREA --------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+ m_bIsTerminated = sal_True;
+ aWriteLock.unlock();
+ /* UNSAFE AREA ------------------------------------------------------------------------------------- */
+ #endif
+
+ impl_sendNotifyTerminationEvent();
+
+ if(
+ ( bAskQuickStart ) &&
+ ( xQuickLauncher.is() )
+ )
+ {
+ xQuickLauncher->notifyTermination( aEvent );
+ }
+
+ if ( xSWThreadManager.is() )
+ xSWThreadManager->notifyTermination( aEvent );
+
+ if ( xPipeTerminator.is() )
+ xPipeTerminator->notifyTermination( aEvent );
+
+ // Must be realy the last listener to be called.
+ // Because it shutdown the whole process asynchronous !
+ if ( xSfxTerminator.is() )
+ xSfxTerminator->notifyTermination( aEvent );
+ }
+
+ return bTerminate;
+}
+
+
+//=============================================================================
+void SAL_CALL Desktop::addTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener )
+ throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ ::rtl::OUString sImplementationName = xInfo->getImplementationName();
+
+ // SYCNHRONIZED ->
+ WriteGuard aWriteLock( m_aLock );
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) )
+ {
+ m_xSfxTerminator = xListener;
+ return;
+ }
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) )
+ {
+ m_xPipeTerminator = xListener;
+ return;
+ }
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) )
+ {
+ m_xQuickLauncher = xListener;
+ return;
+ }
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) )
+ {
+ m_xSWThreadManager = xListener;
+ return;
+ }
+
+ aWriteLock.unlock();
+ // <- SYCNHRONIZED
+ }
+
+ // No lock required ... container is threadsafe by itself.
+ m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener );
+}
+
+//=============================================================================
+void SAL_CALL Desktop::removeTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener )
+ throw( css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ ::rtl::OUString sImplementationName = xInfo->getImplementationName();
+
+ // SYCNHRONIZED ->
+ WriteGuard aWriteLock( m_aLock );
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) )
+ {
+ m_xSfxTerminator.clear();
+ return;
+ }
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) )
+ {
+ m_xPipeTerminator.clear();
+ return;
+ }
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) )
+ {
+ m_xQuickLauncher.clear();
+ return;
+ }
+
+ if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) )
+ {
+ m_xSWThreadManager.clear();
+ return;
+ }
+
+ aWriteLock.unlock();
+ // <- SYCNHRONIZED
+ }
+
+ // No lock required ... container is threadsafe by itself.
+ m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener );
+}
+
+/*-************************************************************************************************************//**
+ @interface XDesktop
+ @short get access to create enumerations of all current components
+ @descr You will be the owner of the returned object and must delete it if you don't use it again.
+
+ @seealso class TasksAccess
+ @seealso class TasksEnumeration
+
+ @param -
+ @return A reference to an XEnumerationAccess-object.
+
+ @onerror We return a null-reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getComponents() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // We use a helper class OComponentAccess to have access on all child components.
+ // Create it on demand and return it as a reference.
+ OComponentAccess* pAccess = new OComponentAccess( this );
+ css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pAccess), css::uno::UNO_QUERY );
+ return xAccess;
+}
+
+/*-************************************************************************************************************//**
+ @interface XDesktop
+ @short return the current active component
+ @descr The most current component is the window, model or the controller of the current active frame.
+
+ @seealso method getCurrentFrame()
+ @seealso method impl_getFrameComponent()
+
+ @param -
+ @return A reference to the component.
+
+ @onerror We return a null-reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::getCurrentComponent() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Set return value if method failed.
+ css::uno::Reference< css::lang::XComponent > xComponent;
+
+ // Get reference to current frame ...
+ // ... get component of this frame ... (It can be the window, the model or the controller.)
+ // ... and return the result.
+ css::uno::Reference< css::frame::XFrame > xCurrentFrame = getCurrentFrame();
+ if( xCurrentFrame.is() == sal_True )
+ {
+ xComponent = impl_getFrameComponent( xCurrentFrame );
+ }
+ return xComponent;
+}
+
+/*-************************************************************************************************************//**
+ @interface XDesktop
+ @short return the current active frame in hierarchy
+ @descr There can be more then one different active pathes in our frame hierarchy. But only one of them
+ could be the most active frame (normal he has the focus).
+ Don't mix it with getActiveFrame()! That will return our current active frame, which must be
+ a direct child of us and should be a part(!) of an active path.
+
+ @seealso method getActiveFrame()
+
+ @param -
+ @return A valid reference, if there is an active frame.
+ A null reference , otherwise.
+
+ @onerror We return a null reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getCurrentFrame() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Start search with ouer direct active frame (if it exist!).
+ // Search on his children for other active frames too.
+ // Stop if no one could be found and return last of found ones.
+ css::uno::Reference< css::frame::XFramesSupplier > xLast = css::uno::Reference< css::frame::XFramesSupplier >( getActiveFrame(), css::uno::UNO_QUERY );
+ if( xLast.is() == sal_True )
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xNext = css::uno::Reference< css::frame::XFramesSupplier >( xLast->getActiveFrame(), css::uno::UNO_QUERY );
+ while( xNext.is() == sal_True )
+ {
+ xLast = xNext;
+ xNext = css::uno::Reference< css::frame::XFramesSupplier >( xNext->getActiveFrame(), css::uno::UNO_QUERY );
+ }
+ }
+ return css::uno::Reference< css::frame::XFrame >( xLast, css::uno::UNO_QUERY );
+}
+
+/*-************************************************************************************************************//**
+ @interface XComponentLoader
+ @short try to load given URL into a task
+ @descr You can give us some informations about the content, which you will load into a frame.
+ We search or create this target for you, make a type detection of given URL and try to load it.
+ As result of this operation we return the new created component or nothing, if loading failed.
+
+ @seealso -
+
+ @param "sURL" , URL, which represant the content
+ @param "sTargetFrameName" , name of target frame or special value like "_self", "_blank" ...
+ @param "nSearchFlags" , optional arguments for frame search, if target isn't a special one
+ @param "lArguments" , optional arguments for loading
+ @return A valid component reference, if loading was successfully.
+ A null reference otherwise.
+
+ @onerror We return a null reference.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::loadComponentFromURL( const ::rtl::OUString& sURL ,
+ const ::rtl::OUString& sTargetFrameName,
+ sal_Int32 nSearchFlags ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::io::IOException ,
+ css::lang::IllegalArgumentException ,
+ css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::Desktop::loadComponentFromURL" );
+
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XComponentLoader > xThis(static_cast< css::frame::XComponentLoader* >(this), css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory;
+ aReadLock.unlock();
+
+ RTL_LOGFILE_PRODUCT_CONTEXT( aLog2, "PERFORMANCE - Desktop::loadComponentFromURL()" );
+ return LoadEnv::loadComponentFromURL(xThis, xSMGR, sURL, sTargetFrameName, nSearchFlags, lArguments);
+}
+
+/*-************************************************************************************************************//**
+ @interface XTasksSupplier
+ @short get access to create enumerations of ouer taskchilds
+ @descr Direct childs of desktop are tasks everytime.
+ Call these method to could create enumerations of it.
+
+But; Don't forget - you will be the owner of returned object and must release it!
+ We use a helper class to implement the access interface. They hold a weakreference to us.
+ It can be, that the desktop is dead - but not your tasksaccess-object! Then they will do nothing!
+ You can't create enumerations then.
+
+ @attention Normaly we don't need any lock here. We don't work on internal member!
+
+ @seealso class TasksAccess
+
+ @param -
+ @return A reference to an accessobject, which can create enumerations of ouer childtasks.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getTasks() throw( css::uno::RuntimeException )
+{
+ LOG_WARNING("Desktop::getTasks()", "Use of obsolete interface XTaskSupplier")
+ return NULL;
+ /*
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ OTasksAccess* pTasksAccess = new OTasksAccess( this, &m_aChildTaskContainer );
+ css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pTasksAccess), css::uno::UNO_QUERY );
+ return xAccess;
+ */
+}
+
+/*-************************************************************************************************************//**
+ @interface XTasksSupplier
+ @short return current active task of ouer direct childs
+ @descr Desktop childs are tasks only ! If we have an active path from desktop
+ as top to any frame on bottom, we must have an active direct child. His reference is returned here.
+
+ @attention a) Do not confuse it with getCurrentFrame()! The current frame don't must one of ouer direct childs.
+ It can be every frame in subtree and must have the focus (Is the last one of an active path!).
+ b) We don't need any lock here. Our container is threadsafe himself and live, if we live!
+
+ @seealso method getCurrentFrame()
+
+ @param -
+ @return A reference to ouer current active taskchild.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XTask > SAL_CALL Desktop::getActiveTask() throw( css::uno::RuntimeException )
+{
+ /*
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return css::uno::Reference< css::frame::XTask >( m_aChildTaskContainer.getActive(), css::uno::UNO_QUERY );
+ */
+ LOG_WARNING("Desktop::getActiveTask()", "Use of obsolete interface XTaskSupplier")
+ return NULL;
+}
+
+/*-************************************************************************************************************//**
+ @interface XDispatchProvider
+ @short search a dispatcher for given URL
+ @descr We use a helper implementation (class DispatchProvider) to do so.
+ So we don't must implement this algorithm twice!
+
+ @attention We don't need any lock here. Our helper is threadsafe himself and live, if we live!
+
+ @seealso class DispatchProvider
+
+ @param "aURL" , URL to dispatch
+ @param "sTargetFrameName" , name of target frame, who should dispatch these URL
+ @param "nSearchFlags" , flags to regulate the search
+ @param "lQueries" , list of queryDispatch() calls!
+ @return A reference or list of founded dispatch objects for these URL.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL Desktop::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ const char UNO_PROTOCOL[] = ".uno:";
+
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Remove uno and cmd protocol part as we want to support both of them. We store only the command part
+ // in our hash map. All other protocols are stored with the protocol part.
+ String aCommand( aURL.Main );
+ if ( aURL.Protocol.equalsIgnoreAsciiCaseAsciiL( UNO_PROTOCOL, sizeof( UNO_PROTOCOL )-1 ))
+ aCommand = aURL.Path;
+
+ // Make hash_map lookup if the current URL is in the disabled list
+ if ( m_aCommandOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aCommand ) )
+ return css::uno::Reference< css::frame::XDispatch >();
+ else
+ {
+ // We use a helper to support these interface and an interceptor mechanism.
+ // Our helper is threadsafe by himself!
+ return m_xDispatchHelper->queryDispatch( aURL, sTargetFrameName, nSearchFlags );
+ }
+}
+
+//*****************************************************************************************************************
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL Desktop::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lQueries ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return m_xDispatchHelper->queryDispatches( lQueries );
+}
+
+/*-************************************************************************************************************//**
+ @interface XDipsatchProviderInterception
+ @short supports registration/deregistration of interception objects, which
+ are interested on special dispatches.
+
+ @descr Its realy provided by an internal helper, which is used inside the dispatch api too.
+ @param xInterceptor
+ the interceptor object, which wish to be (de)registered.
+
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
+ throw( css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
+ xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::releaseDispatchProviderInterceptor ( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
+ throw( css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
+ xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor );
+}
+
+/*-************************************************************************************************************//**
+ @interface XFramesSupplier
+ @short return access to append or remove childs on desktop
+ @descr We don't implement these interface directly. We use a helper class to do this.
+ If you wish to add or delete childs to/from the container, call these method to get
+ a reference to the helper.
+
+ @attention Helper is threadsafe himself. So we don't need any lock here.
+
+ @seealso class OFrames
+
+ @param -
+ @return A reference to the helper.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XFrames > SAL_CALL Desktop::getFrames() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return m_xFramesHelper;
+}
+
+/*-************************************************************************************************************//**
+ @interface XFramesSupplier
+ @short set/get the current active child frame
+ @descr It must be a task. Direct childs of desktop are tasks only! No frames are accepted.
+ We don't save this information directly in this class. We use ouer container-helper
+ to do that.
+
+ @attention Helper is threadsafe himself. So we don't need any lock here.
+
+ @seealso class OFrameContainer
+
+ @param "xFrame", new active frame (must be valid!)
+ @return A reference to ouer current active childtask, if anyone exist.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Get old active frame first.
+ // If nothing will change - do nothing!
+ // Otherwise set new active frame ...
+ // and deactivate last frame.
+ // It's neccessary for our FrameActionEvent listener on a frame!
+ css::uno::Reference< css::frame::XFrame > xLastActiveChild = m_aChildTaskContainer.getActive();
+ if( xLastActiveChild != xFrame )
+ {
+ m_aChildTaskContainer.setActive( xFrame );
+ if( xLastActiveChild.is() == sal_True )
+ {
+ xLastActiveChild->deactivate();
+ }
+ }
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getActiveFrame() throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ return m_aChildTaskContainer.getActive();
+}
+
+/*-************************************************************************************************************//**
+ @interface XFrame
+ @short non implemented methods!
+ @descr Some method make no sense for our desktop! He has no window or parent or ...
+ So we should implement it empty and warn programmer, if he use it!
+
+ @seealso -
+
+ @param -
+ @return -
+
+ @onerror -
+ @threadsafe -
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::initialize( const css::uno::Reference< css::awt::XWindow >& ) throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getContainerWindow() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::awt::XWindow >();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& /*xCreator*/ ) throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL Desktop::getCreator() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::frame::XFramesSupplier >();
+}
+
+//*****************************************************************************************************************
+::rtl::OUString SAL_CALL Desktop::getName() throw( css::uno::RuntimeException )
+{
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ return m_sName;
+ /* } SAFE */
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::setName( const ::rtl::OUString& sName ) throw( css::uno::RuntimeException )
+{
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ m_sName = sName;
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//*****************************************************************************************************************
+sal_Bool SAL_CALL Desktop::isTop() throw( css::uno::RuntimeException )
+{
+ return sal_True;
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::activate() throw( css::uno::RuntimeException )
+{
+ // Desktop is activae always ... but sometimes our frames try to activate
+ // the complete path from bottom to top ... And our desktop is the topest frame :-(
+ // So - please don't show any assertions here. Do nothing!
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::deactivate() throw( css::uno::RuntimeException )
+{
+ // Desktop is activae always ... but sometimes our frames try to deactivate
+ // the complete path from bottom to top ... And our desktop is the topest frame :-(
+ // So - please don't show any assertions here. Do nothing!
+}
+
+//*****************************************************************************************************************
+sal_Bool SAL_CALL Desktop::isActive() throw( css::uno::RuntimeException )
+{
+ return sal_True;
+}
+
+//*****************************************************************************************************************
+sal_Bool SAL_CALL Desktop::setComponent( const css::uno::Reference< css::awt::XWindow >& /*xComponentWindow*/ ,
+ const css::uno::Reference< css::frame::XController >& /*xController*/ ) throw( css::uno::RuntimeException )
+{
+ return sal_False;
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getComponentWindow() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::awt::XWindow >();
+}
+
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XController > SAL_CALL Desktop::getController() throw( css::uno::RuntimeException )
+{
+ return css::uno::Reference< css::frame::XController >();
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::contextChanged() throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+// css::frame::XFrame
+//*****************************************************************************************************************
+void SAL_CALL Desktop::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException )
+{
+}
+
+/*-************************************************************************************************************//**
+ @interface XFrame
+ @short try to find a frame with special parameters
+ @descr This method searches for a frame with the specified name.
+ Frames may contain other frames (e.g. a frameset) and may
+ be contained in other frames. This hierarchie ist searched by
+ this method.
+ First some special names are taken into account, i.e. "",
+ "_self", "_top", "_parent" etc. The FrameSearchFlags are ignored
+ when comparing these names with aTargetFrameName, further steps are
+ controlled by the FrameSearchFlags. If allowed, the name of the frame
+ itself is compared with the desired one, then ( again if allowed )
+ the method findFrame is called for all children of the frame.
+ If no Frame with the given name is found until the top frames container,
+ a new top Frame is created, if this is allowed by a special
+ FrameSearchFlag. The new Frame also gets the desired name.
+ We use a helper to get right search direction and react in a right manner.
+
+ @seealso class TargetFinder
+
+ @param "sTargetFrameName" , name of searched frame
+ @param "nSearchFlags" , flags to regulate search
+ @return A reference to an existing frame in hierarchy, if it exist.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::findFrame( const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XFrame > xTarget;
+
+ //-----------------------------------------------------------------------------------------------------
+ // 0) Ignore wrong parameter!
+ // We doesn't support search for following special targets.
+ // If we reject this requests - we mustnt check for such names
+ // in following code again and again. If we do not so -wrong
+ // search results can occure!
+ //-----------------------------------------------------------------------------------------------------
+ if (
+ (sTargetFrameName==SPECIALTARGET_DEFAULT ) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_HELPAGENT) || // valid for dispatches - not for findFrame()!
+ (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition
+ (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only -
+ // and they exist more then ones. We have no idea which our sub tasks is the right one
+ )
+ {
+ return NULL;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I) check for special defined targets first which must be handled exclusive.
+ // force using of "if() else if() ..."
+ //-----------------------------------------------------------------------------------------------------
+
+ // get threadsafe some neccessary member which are neccessary for following functionality
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.I) "_blank"
+ // create a new task as child of this desktop instance
+ // Note: Used helper TaskCreator use us automaticly ...
+ //-----------------------------------------------------------------------------------------------------
+ if ( sTargetFrameName==SPECIALTARGET_BLANK )
+ {
+ TaskCreator aCreator(xFactory);
+ xTarget = aCreator.createTask(sTargetFrameName,sal_False);
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.II) "_top"
+ // We are top by definition
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if ( sTargetFrameName==SPECIALTARGET_TOP )
+ {
+ xTarget = this;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.III) "_self", ""
+ // This mean this "frame" in every case.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (
+ ( sTargetFrameName==SPECIALTARGET_SELF ) ||
+ ( sTargetFrameName.getLength()<1 )
+ )
+ {
+ xTarget = this;
+ }
+
+ else
+ {
+ //-------------------------------------------------------------------------------------------------
+ // II) otherwhise use optional given search flags
+ // force using of combinations of such flags. means no "else" part of use if() statements.
+ // But we ust break further searches if target was already found.
+ // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
+ // TASK and CREATE are handled special.
+ // But note: Such flags are not valid for the desktop - especialy SIBLINGS or PARENT.
+ //-------------------------------------------------------------------------------------------------
+
+ // get threadsafe some neccessary member which are neccessary for following functionality
+ /* SAFE { */
+ aReadLock.lock();
+ ::rtl::OUString sOwnName = m_sName;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ //-------------------------------------------------------------------------------------------------
+ // II.I) SELF
+ // Check for right name. If it's the searched one return ourself - otherwhise
+ // ignore this flag.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ (nSearchFlags & css::frame::FrameSearchFlag::SELF) &&
+ (sOwnName == sTargetFrameName )
+ )
+ {
+ xTarget = this;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.II) TASKS
+ // This is a special flag. Normaly it regulate search inside tasks and forbid access to parent trees.
+ // But the desktop exists outside such task trees. They are our sub trees. So the desktop implement
+ // a special feature: We use it to start search on our direct childrens only. That means we supress
+ // search on ALL child frames. May that can be usefull to get access on opened document tasks
+ // only without filter out all non realy required sub frames ...
+ // Used helper method on our container doesn't create any frame - its a search only.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::TASKS)
+ )
+ {
+ xTarget = m_aChildTaskContainer.searchOnDirectChildrens(sTargetFrameName);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.III) CHILDREN
+ // Search on all children for the given target name.
+ // An empty name value can't occure here - because it must be already handled as "_self"
+ // before. Used helper function of container doesn't create any frame.
+ // It makes a deep search only.
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
+ )
+ {
+ xTarget = m_aChildTaskContainer.searchOnAllChildrens(sTargetFrameName);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // II.IV) CREATE
+ // If we haven't found any valid target frame by using normal flags - but user allowed us to create
+ // a new one ... we should do that. Used TaskCreator use us automaticly as parent!
+ //-------------------------------------------------------------------------------------------------
+ if (
+ ( ! xTarget.is() ) &&
+ (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
+ )
+ {
+ TaskCreator aCreator(xFactory);
+ xTarget = aCreator.createTask(sTargetFrameName,sal_False);
+ }
+ }
+
+ return xTarget;
+}
+
+//=============================================================================
+void SAL_CALL Desktop::dispose()
+ throw( css::uno::RuntimeException )
+{
+ // Safe impossible cases
+ // It's an programming error if dispose is called before terminate!
+ LOG_ASSERT2( m_bIsTerminated==sal_False, "Desktop::dispose()", "It's not allowed to dispose the desktop before terminate() is called!" )
+
+ SYNCHRONIZED_START
+ WriteGuard aWriteLock( m_aLock );
+
+ // Look for multiple calls of this method!
+ // If somewhere call dispose() twice - he will be stopped here realy!!!
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Now - we are alone and its the first call of this method ...
+ // otherwise call before had thrown a DisposedException / hopefully .-)
+ // But we dont use the transaction object created before ... we reset it immediatly ...
+ // two lines of code ... for what ?
+ // The answer: We wished to synchronize concurrent dispose() calls -> OK
+ // But next line will wait for all currently running transaction (even if they
+ // are running within the same thread!) So we would block ourself there if aTransaction
+ // will stay registered .-)
+ aTransaction.stop();
+
+ // Disable this instance for further work.
+ // This will wait for all current running transactions ...
+ // and reject all new incoming requests!
+ m_aTransactionManager.setWorkingMode( E_BEFORECLOSE );
+
+ aWriteLock.unlock();
+ SYNCHRONIZED_END
+
+ // Following lines of code can be called outside a synchronized block ...
+ // Because our transaction manager will block all new requests to this object.
+ // So nobody can use us any longer.
+ // Exception: Only removing of listener will work ... and this code cant be dangerous.
+
+ // First we has to kill all listener connections.
+ // They might rely on our member and can hinder us on releasing them.
+ css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
+ css::lang::EventObject aEvent( xThis );
+ m_aListenerContainer.disposeAndClear( aEvent );
+
+ // Clear our child task container and forget all task references hardly.
+ // Normaly all open document was already closed by our terminate() function before ...
+ // New opened frames will have a problem now .-)
+ m_aChildTaskContainer.clear();
+
+ // Dispose our helper too.
+ css::uno::Reference< css::lang::XEventListener > xFramesHelper( m_xFramesHelper, css::uno::UNO_QUERY );
+ if( xFramesHelper.is() )
+ xFramesHelper->disposing( aEvent );
+
+ // At least clean up other member references.
+ m_xDispatchHelper.clear();
+ m_xFramesHelper.clear();
+ m_xLastFrame.clear();
+ m_xFactory.clear();
+
+ m_xPipeTerminator.clear();
+ m_xQuickLauncher.clear();
+ m_xSWThreadManager.clear();
+ m_xSfxTerminator.clear();
+
+ // From this point nothing will work further on this object ...
+ // excepting our dtor() .-)
+ m_aTransactionManager.setWorkingMode( E_CLOSE );
+}
+
+/*-************************************************************************************************************//**
+ @interface XComponent
+ @short add/remove listener for dispose events
+ @descr Add an event listener to this object, if you whish to get informations
+ about our dieing!
+ You must releas ethis listener reference during your own disposing() method.
+
+ @attention Our container is threadsafe himeslf. So we doesn't need any lock here.
+
+ @seealso -
+
+ @param "xListener", reference to valid listener. We don't accept invalid values!
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Safe impossible cases
+ // Method not defined for all incoming parameter.
+ LOG_ASSERT2( implcp_addEventListener( xListener ), "Desktop::addEventListener()", "Invalid parameter detected!" )
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener );
+}
+
+//*****************************************************************************************************************
+void SAL_CALL Desktop::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Safe impossible cases
+ // Method not defined for all incoming parameter.
+ LOG_ASSERT2( implcp_removeEventListener( xListener ), "Desktop::removeEventListener()", "Invalid parameter detected!" )
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
+
+ m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener );
+}
+
+/*-************************************************************************************************************//**
+ @interface XDispatchResultListener
+ @short callback for dispatches
+ @descr To support our method "loadComponentFromURL()" we are listener on temp. created dispatcher.
+ They call us back in this method "statusChanged()". As source of given state event, they give us a
+ reference to the target frame, in which dispatch was loaded! So we can use it to return his component
+ to caller! If no target exist ... ??!!
+
+ @seealso method loadComponentFromURL()
+
+ @param "aEvent", state event which (hopefully) valid informations
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::dispatchFinished( const css::frame::DispatchResultEvent& aEvent ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ /* SAFE AREA ------------------------------------------------------------------------------------------- */
+ WriteGuard aWriteLock( m_aLock );
+ if( m_eLoadState != E_INTERACTION )
+ {
+ m_xLastFrame = css::uno::Reference< css::frame::XFrame >();
+ m_eLoadState = E_FAILED ;
+ if( aEvent.State == css::frame::DispatchResultState::SUCCESS )
+ {
+ css::uno::Reference < css::frame::XFrame > xFrame;
+ if ( aEvent.Result >>= m_xLastFrame )
+ m_eLoadState = E_SUCCESSFUL;
+ }
+ }
+ /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
+}
+
+/*-************************************************************************************************************//**
+ @interface XEventListener
+ @short not implemented!
+ @descr We are a status listener ... and so we must be an event listener too ... But we doesn't need it realy!
+ We are a temp. listener only and our lifetime isn't smaller then of our temp. used dispatcher.
+
+ @seealso method loadComponentFromURL()
+
+ @param -
+ @return -
+
+ @onerror -
+ @threadsafe -
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::disposing( const css::lang::EventObject& ) throw( css::uno::RuntimeException )
+{
+ LOG_ERROR( "Desktop::disposing()", "Algorithm error! Normaly desktop is temp. listener ... not all the time. So this method shouldn't be called." )
+}
+
+/*-************************************************************************************************************//**
+ @interface XInteractionHandler
+ @short callback for loadComponentFromURL for detected exceptions during load proccess
+ @descr In this case we must cancel loading and throw these detected exception again as result
+ of our own called method.
+
+ @attention a)
+ Normal loop in loadComponentFromURL() breaks on setted member m_eLoadState during callback statusChanged().
+ But these interaction feature implements second way to do so! So we must look on different callbacks
+ for same operation ... and live with it.
+ b)
+ Search for given continuations too. If any XInteractionAbort exist ... use it to abort further operations
+ for currently running operation!
+
+ @seealso method loadComponentFromURL()
+ @seealso member m_eLoadState
+
+ @param "xRequest", request for interaction - normal a wrapped target exception from bottom services
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::handle( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) throw( css::uno::RuntimeException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Don't check incoming request!
+ // If somewhere starts interaction without right parameter - he maked something wrong.
+ // loadComponentFromURL() waits for thjese event - otherwise it yield for ever!
+
+ // get packed request and work on it first
+ // Attention: Don't set it on internal member BEFORE interaction is finished - because
+ // "loadComponentFromURL()" yield tills this member is changed. If we do it before
+ // interaction finish we can't guarantee right functionality. May be we cancel load process to erliear ...
+ css::uno::Any aRequest = xRequest->getRequest();
+
+ // extract continuations from request
+ css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations();
+ css::uno::Reference< css::task::XInteractionAbort > xAbort ;
+ css::uno::Reference< css::task::XInteractionApprove > xApprove ;
+ css::uno::Reference< css::document::XInteractionFilterSelect > xFilterSelect ;
+ sal_Bool bAbort = sal_False;
+
+ sal_Int32 nCount=lContinuations.getLength();
+ for( sal_Int32 nStep=0; nStep<nCount; ++nStep )
+ {
+ if( ! xAbort.is() )
+ xAbort = css::uno::Reference< css::task::XInteractionAbort >( lContinuations[nStep], css::uno::UNO_QUERY );
+
+ if( ! xApprove.is() )
+ xApprove = css::uno::Reference< css::task::XInteractionApprove >( lContinuations[nStep], css::uno::UNO_QUERY );
+
+ if( ! xFilterSelect.is() )
+ xFilterSelect = css::uno::Reference< css::document::XInteractionFilterSelect >( lContinuations[nStep], css::uno::UNO_QUERY );
+ }
+
+ // differ between abortable interactions (error, unknown filter ...)
+ // and other ones (ambigous but not unknown filter ...)
+ css::task::ErrorCodeRequest aErrorCodeRequest ;
+ css::document::AmbigousFilterRequest aAmbigousFilterRequest;
+ if( aRequest >>= aAmbigousFilterRequest )
+ {
+ if( xFilterSelect.is() )
+ {
+ xFilterSelect->setFilter( aAmbigousFilterRequest.SelectedFilter ); // user selected filter wins!
+ xFilterSelect->select();
+ }
+ }
+ else
+ if( aRequest >>= aErrorCodeRequest )
+ {
+ sal_Bool bWarning = ((aErrorCodeRequest.ErrCode & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK);
+ if (xApprove.is() && bWarning)
+ xApprove->select();
+ else
+ if (xAbort.is())
+ {
+ xAbort->select();
+ bAbort = sal_True;
+ }
+ }
+ else
+ if( xAbort.is() )
+ {
+ xAbort->select();
+ bAbort = sal_True;
+ }
+
+ /* SAFE AREA ------------------------------------------------------------------------------------------- */
+ // Ok now it's time to break yield loop of loadComponentFromURL().
+ // But only for realy aborted requests!
+ // For example warnings will be approved and we wait for any success story ...
+ if (bAbort)
+ {
+ WriteGuard aWriteLock( m_aLock );
+ m_eLoadState = E_INTERACTION;
+ m_aInteractionRequest = aRequest ;
+ aWriteLock.unlock();
+ }
+ /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
+}
+
+//-----------------------------------------------------------------------------
+::sal_Int32 SAL_CALL Desktop::leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent )
+ throw (css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ return m_xTitleNumberGenerator->leaseNumber (xComponent);
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL Desktop::releaseNumber( ::sal_Int32 nNumber )
+ throw (css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ m_xTitleNumberGenerator->releaseNumber (nNumber);
+}
+
+//-----------------------------------------------------------------------------
+void SAL_CALL Desktop::releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent )
+ throw (css::lang::IllegalArgumentException,
+ css::uno::RuntimeException )
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ m_xTitleNumberGenerator->releaseNumberForComponent (xComponent);
+}
+
+//-----------------------------------------------------------------------------
+::rtl::OUString SAL_CALL Desktop::getUntitledPrefix()
+ throw (css::uno::RuntimeException)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+ return m_xTitleNumberGenerator->getUntitledPrefix ();
+}
+
+/*-************************************************************************************************************//**
+ @short try to convert a property value
+ @descr This method is called from helperclass "OPropertySetHelper".
+ Don't use this directly!
+ You must try to convert the value of given DESKTOP_PROPHANDLE and
+ return results of this operation. This will be used to ask vetoable
+ listener. If no listener has a veto, we will change value realy!
+ ( in method setFastPropertyValue_NoBroadcast(...) )
+
+ @attention Methods of OPropertySethelper are safed by using our shared osl mutex! (see ctor!)
+ So we must use different locks to make our implementation threadsafe.
+
+ @seealso class OPropertySetHelper
+ @seealso method setFastPropertyValue_NoBroadcast()
+
+ @param "aConvertedValue" new converted value of property
+ @param "aOldValue" old value of property
+ @param "nHandle" handle of property
+ @param "aValue" new value of property
+ @return sal_True if value will be changed, sal_FALSE otherway
+
+ @onerror IllegalArgumentException, if you call this with an invalid argument
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+sal_Bool SAL_CALL Desktop::convertFastPropertyValue( css::uno::Any& aConvertedValue ,
+ css::uno::Any& aOldValue ,
+ sal_Int32 nHandle ,
+ const css::uno::Any& aValue ) throw( css::lang::IllegalArgumentException )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Initialize state with sal_False !!!
+ // (Handle can be invalid)
+ sal_Bool bReturn = sal_False;
+
+ switch( nHandle )
+ {
+ case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO:
+ bReturn = PropHelper::willPropertyBeChanged(
+ css::uno::makeAny(m_bSuspendQuickstartVeto),
+ aValue,
+ aOldValue,
+ aConvertedValue);
+ break;
+ case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
+ bReturn = PropHelper::willPropertyBeChanged(
+ css::uno::makeAny(m_xDispatchRecorderSupplier),
+ aValue,
+ aOldValue,
+ aConvertedValue);
+ break;
+ case DESKTOP_PROPHANDLE_TITLE :
+ bReturn = PropHelper::willPropertyBeChanged(
+ css::uno::makeAny(m_sTitle),
+ aValue,
+ aOldValue,
+ aConvertedValue);
+ break;
+ }
+
+ // Return state of operation.
+ return bReturn ;
+}
+
+/*-************************************************************************************************************//**
+ @short set value of a transient property
+ @descr This method is calling from helperclass "OPropertySetHelper".
+ Don't use this directly!
+ Handle and value are valid everyway! You must set the new value only.
+ After this, baseclass send messages to all listener automaticly.
+
+ @seealso class OPropertySetHelper
+
+ @param "nHandle" handle of property to change
+ @param "aValue" new value of property
+ @return -
+
+ @onerror An exception is thrown.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle ,
+ const css::uno::Any& aValue ) throw( css::uno::Exception )
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ switch( nHandle )
+ {
+ case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: aValue >>= m_bSuspendQuickstartVeto;
+ break;
+ case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER: aValue >>= m_xDispatchRecorderSupplier;
+ break;
+ case DESKTOP_PROPHANDLE_TITLE: aValue >>= m_sTitle;
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short get value of a transient property
+ @descr This method is calling from helperclass "OPropertySetHelper".
+ Don't use this directly!
+
+ @attention We don't need any mutex or lock here ... We use threadsafe container or methods here only!
+
+ @seealso class OPropertySetHelper
+
+ @param "nHandle" handle of property to change
+ @param "aValue" current value of property
+ @return -
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Desktop::getFastPropertyValue( css::uno::Any& aValue ,
+ sal_Int32 nHandle ) const
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ switch( nHandle )
+ {
+ case DESKTOP_PROPHANDLE_ACTIVEFRAME : aValue <<= m_aChildTaskContainer.getActive();
+ break;
+ case DESKTOP_PROPHANDLE_ISPLUGGED : aValue <<= sal_False;
+ break;
+ case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: aValue <<= m_bSuspendQuickstartVeto;
+ break;
+ case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER: aValue <<= m_xDispatchRecorderSupplier;
+ break;
+ case DESKTOP_PROPHANDLE_TITLE: aValue <<= m_sTitle;
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short return structure and information about transient properties
+ @descr This method is calling from helperclass "OPropertySetHelper".
+ Don't use this directly!
+
+ @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
+ Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
+ So we could have two different mutex/lock mechanism at the same object.
+
+ @seealso class OPropertySetHelper
+
+ @param -
+ @return structure with property-informations
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+::cppu::IPropertyArrayHelper& SAL_CALL Desktop::getInfoHelper()
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Optimize this method !
+ // We initialize a static variable only one time. And we don't must use a mutex at every call!
+ // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL!
+ static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL;
+
+ if( pInfoHelper == NULL )
+ {
+ // Ready for multithreading
+ ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
+ // Control this pointer again, another instance can be faster then these!
+ if( pInfoHelper == NULL )
+ {
+ // Define static member to give structure of properties to baseclass "OPropertySetHelper".
+ // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable.
+ // "sal_True" say: Table is sorted by name.
+ static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True );
+ pInfoHelper = &aInfoHelper;
+ }
+ }
+
+ return(*pInfoHelper);
+}
+
+/*-************************************************************************************************************//**
+ @short return propertysetinfo
+ @descr You can call this method to get information about transient properties
+ of this object.
+
+ @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
+ Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
+ So we could have two different mutex/lock mechanism at the same object.
+
+ @seealso class OPropertySetHelper
+ @seealso interface XPropertySet
+ @seealso interface XMultiPropertySet
+
+ @param -
+ @return reference to object with information [XPropertySetInfo]
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL Desktop::getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException)
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Optimize this method !
+ // We initialize a static variable only one time. And we don't must use a mutex at every call!
+ // For the first call; pInfo is NULL - for the second call pInfo is different from NULL!
+ static css::uno::Reference< css::beans::XPropertySetInfo >* pInfo = NULL;
+
+ if( pInfo == NULL )
+ {
+ // Ready for multithreading
+ ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
+ // Control this pointer again, another instance can be faster then these!
+ if( pInfo == NULL )
+ {
+ // Create structure of propertysetinfo for baseclass "OPropertySetHelper".
+ // (Use method "getInfoHelper()".)
+ static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ pInfo = &xInfo;
+ }
+ }
+
+ return (*pInfo);
+}
+
+/*-************************************************************************************************************//**
+ @short return current component of current frame
+ @descr The desktop himself has no component. But every frame in subtree.
+ If somewhere call getCurrentComponent() at this class, we try to find the right frame and
+ then we try to become his component. It can be a VCL-component, the model or the controller
+ of founded frame.
+
+ @attention We don't work on internal member ... so we doesn't need any lock here.
+
+ @seealso method getCurrentComponent();
+
+ @param "xFrame", reference to valid frame in hierarchy. Method is not defined for invalid values.
+ But we don't check these. Its an IMPL-method and caller must use it right!
+ @return A reference to found component.
+
+ @onerror A null reference is returned.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+css::uno::Reference< css::lang::XComponent > Desktop::impl_getFrameComponent( const css::uno::Reference< css::frame::XFrame >& xFrame ) const
+{
+ /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
+ // Register transaction and reject wrong calls.
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ // Set default return value, if method failed.
+ css::uno::Reference< css::lang::XComponent > xComponent;
+ // Does no controller exists?
+ css::uno::Reference< css::frame::XController > xController = xFrame->getController();
+ if( xController.is() == sal_False )
+ {
+ // Controller not exist - use the VCL-component.
+ xComponent = css::uno::Reference< css::lang::XComponent >( xFrame->getComponentWindow(), css::uno::UNO_QUERY );
+ }
+ else
+ {
+ // Does no model exists?
+ css::uno::Reference< css::frame::XModel > xModel( xController->getModel(), css::uno::UNO_QUERY );
+ if( xModel.is() == sal_True )
+ {
+ // Model exist - use the model as component.
+ xComponent = css::uno::Reference< css::lang::XComponent >( xModel, css::uno::UNO_QUERY );
+ }
+ else
+ {
+ // Model not exist - use the controller as component.
+ xComponent = css::uno::Reference< css::lang::XComponent >( xController, css::uno::UNO_QUERY );
+ }
+ }
+
+ return xComponent;
+}
+
+/*-************************************************************************************************************//**
+ @short create table with information about properties
+ @descr We use a helper class to support properties. These class need some information about this.
+ These method create a new static description table with name, type, r/w-flags and so on ...
+
+ @seealso class OPropertySetHelper
+ @seealso method getInfoHelper()
+
+ @param -
+ @return Static table with information about properties.
+
+ @onerror -
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+const css::uno::Sequence< css::beans::Property > Desktop::impl_getStaticPropertyDescriptor()
+{
+ // Create a new static property array to initialize sequence!
+ // Table of all predefined properties of this class. Its used from OPropertySetHelper-class!
+ // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!!
+ // It's necessary for methods of OPropertySetHelper.
+ // ATTENTION:
+ // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!!
+
+ static const css::beans::Property pProperties[] =
+ {
+ css::beans::Property( DESKTOP_PROPNAME_ACTIVEFRAME , DESKTOP_PROPHANDLE_ACTIVEFRAME , ::getCppuType((const css::uno::Reference< css::lang::XComponent >*)NULL) , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ css::beans::Property( DESKTOP_PROPNAME_DISPATCHRECORDERSUPPLIER , DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER, ::getCppuType((const css::uno::Reference< css::frame::XDispatchRecorderSupplier >*)NULL), css::beans::PropertyAttribute::TRANSIENT ),
+ css::beans::Property( DESKTOP_PROPNAME_ISPLUGGED , DESKTOP_PROPHANDLE_ISPLUGGED , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
+ css::beans::Property( DESKTOP_PROPNAME_SUSPENDQUICKSTARTVETO , DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT ),
+ css::beans::Property( DESKTOP_PROPNAME_TITLE , DESKTOP_PROPHANDLE_TITLE , ::getCppuType((const ::rtl::OUString*)NULL) , css::beans::PropertyAttribute::TRANSIENT ),
+ };
+ // Use it to initialize sequence!
+ static const css::uno::Sequence< css::beans::Property > lPropertyDescriptor( pProperties, DESKTOP_PROPCOUNT );
+ // Return static "PropertyDescriptor"
+ return lPropertyDescriptor;
+}
+
+//=============================================================================
+void Desktop::impl_sendQueryTerminationEvent(Desktop::TTerminateListenerList& lCalledListener,
+ ::sal_Bool& bVeto )
+{
+ bVeto = sal_False;
+
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) );
+ if ( ! pContainer )
+ return;
+
+ css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
+
+ ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
+ while ( aIterator.hasMoreElements() )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY);
+ if ( ! xListener.is() )
+ continue;
+ xListener->queryTermination( aEvent );
+ lCalledListener.push_back(xListener);
+ }
+ catch( const css::frame::TerminationVetoException& )
+ {
+ // first veto will stop notification loop.
+ bVeto = sal_True;
+ return;
+ }
+ catch( const css::uno::Exception& )
+ {
+ // clean up container.
+ // E.g. dead remote listener objects can make trouble otherwise.
+ // Iterator implementation allows removing objects during it's used !
+ aIterator.remove();
+ }
+ }
+}
+
+//=============================================================================
+void Desktop::impl_sendCancelTerminationEvent(const Desktop::TTerminateListenerList& lCalledListener)
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
+ Desktop::TTerminateListenerList::const_iterator pIt;
+ for ( pIt = lCalledListener.begin();
+ pIt != lCalledListener.end ();
+ ++pIt )
+ {
+ try
+ {
+ // Note: cancelTermination() is a new and optional interface method !
+ css::uno::Reference< css::frame::XTerminateListener > xListener = *pIt;
+ css::uno::Reference< css::frame::XTerminateListener2 > xListenerGeneration2(xListener, css::uno::UNO_QUERY);
+ if ( ! xListenerGeneration2.is() )
+ continue;
+ xListenerGeneration2->cancelTermination( aEvent );
+ }
+ catch( const css::uno::Exception& )
+ {}
+ }
+}
+
+//=============================================================================
+void Desktop::impl_sendNotifyTerminationEvent()
+{
+ TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
+
+ ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) );
+ if ( ! pContainer )
+ return;
+
+ css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
+
+ ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
+ while ( aIterator.hasMoreElements() )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY);
+ if ( ! xListener.is() )
+ continue;
+ xListener->notifyTermination( aEvent );
+ }
+ catch( const css::uno::Exception& )
+ {
+ // clean up container.
+ // E.g. dead remote listener objects can make trouble otherwise.
+ // Iterator implementation allows removing objects during it's used !
+ aIterator.remove();
+ }
+ }
+}
+
+//=============================================================================
+::sal_Bool Desktop::impl_closeFrames(::sal_Bool bAllowUI)
+{
+ SYNCHRONIZED_START
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Sequence< css::uno::Reference< css::frame::XFrame > > lFrames = m_aChildTaskContainer.getAllElements();
+ aReadLock.unlock();
+ SYNCHRONIZED_END
+
+ ::sal_Int32 c = lFrames.getLength();
+ ::sal_Int32 i = 0;
+ ::sal_Int32 nNonClosedFrames = 0;
+
+ for( i=0; i<c; ++i )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XFrame > xFrame = lFrames[i];
+
+ // XController.suspend() will show an UI ...
+ // Use it in case it was allowed from outside only.
+ sal_Bool bSuspended = sal_False;
+ css::uno::Reference< css::frame::XController > xController( xFrame->getController(), css::uno::UNO_QUERY );
+ if (
+ ( bAllowUI ) &&
+ ( xController.is() )
+ )
+ {
+ bSuspended = xController->suspend( sal_True );
+ if ( ! bSuspended )
+ {
+ ++nNonClosedFrames;
+ continue;
+ }
+ }
+
+ // Try to close frame (in case no UI was allowed without calling XController->suspend() before!)
+ // But don't deliver ownership to any other one!
+ // This method can be called again.
+ css::uno::Reference< css::util::XCloseable > xClose( xFrame, css::uno::UNO_QUERY );
+ if ( xClose.is() )
+ {
+ try
+ {
+ xClose->close(sal_False);
+ }
+ catch(const css::util::CloseVetoException&)
+ {
+ // Any internal process of this frame disagree with our request.
+ // Safe this state but dont break these loop. Other frames has to be closed!
+ ++nNonClosedFrames;
+
+ // Reactivate controller.
+ // It can happen that XController.suspend() returned true ... but a registered close listener
+ // throwed these veto exception. Then the controller has to be reactivated. Otherwise
+ // these document doesnt work any more.
+ if (
+ (bSuspended ) &&
+ (xController.is())
+ )
+ xController->suspend(sal_False);
+ }
+
+ // If interface XClosable interface exists and was used ...
+ // it's not allowed to use XComponent->dispose() also !
+ continue;
+ }
+
+ // XClosable not supported ?
+ // Then we have to dispose these frame hardly.
+ css::uno::Reference< css::lang::XComponent > xDispose( xFrame, css::uno::UNO_QUERY );
+ if ( xDispose.is() )
+ xDispose->dispose();
+
+ // Don't remove these frame from our child container!
+ // A frame do it by itself inside close()/dispose() method.
+ }
+ catch(const css::lang::DisposedException&)
+ {
+ // Dispose frames are closed frames.
+ // So we can count it here .-)
+ }
+ }
+
+ return (nNonClosedFrames < 1);
+}
+
+//_________________________________________________________________________________________________________________
+// debug methods
+//_________________________________________________________________________________________________________________
+
+/*-----------------------------------------------------------------------------------------------------------------
+ The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
+ we return "sal_True". (otherwise sal_False) This mechanism is used to throw an ASSERT!
+-----------------------------------------------------------------------------------------------------------------*/
+
+#ifdef ENABLE_ASSERTIONS
+
+//*****************************************************************************************************************
+// We work with valid servicemanager only.
+sal_Bool Desktop::implcp_ctor( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+{
+ return(
+ ( &xFactory == NULL ) ||
+ ( xFactory.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+// We work with valid listener only.
+sal_Bool Desktop::implcp_addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
+{
+ return(
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+//*****************************************************************************************************************
+// We work with valid listener only.
+sal_Bool Desktop::implcp_removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
+{
+ return(
+ ( &xListener == NULL ) ||
+ ( xListener.is() == sal_False )
+ );
+}
+
+#endif // #ifdef ENABLE_ASSERTIONS
+
+} // namespace framework