| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 |