diff options
Diffstat (limited to 'framework/source/services/frame.cxx')
-rw-r--r-- | framework/source/services/frame.cxx | 3305 |
1 files changed, 3305 insertions, 0 deletions
diff --git a/framework/source/services/frame.cxx b/framework/source/services/frame.cxx new file mode 100644 index 000000000000..e4d5655ca5f0 --- /dev/null +++ b/framework/source/services/frame.cxx @@ -0,0 +1,3305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <services/frame.hxx> +#include <dispatch/dispatchprovider.hxx> + +#include <dispatch/interceptionhelper.hxx> +#include <dispatch/closedispatcher.hxx> +#include <dispatch/windowcommanddispatch.hxx> +#include <loadenv/loadenv.hxx> +#include <helper/oframes.hxx> +#include <helper/statusindicatorfactory.hxx> +#include <framework/titlehelper.hxx> +#include <classes/droptargetlistener.hxx> +#include <classes/taskcreator.hxx> +#include <loadenv/targethelper.hxx> +#include <framework/framelistanalyzer.hxx> +#include <helper/dockingareadefaultacceptor.hxx> +#include <dispatch/dispatchinformationprovider.hxx> +#include <threadhelp/transactionguard.hxx> +#include <pattern/window.hxx> +#include <services.h> +#include <properties.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/task/XStatusIndicatorSupplier.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/awt/XDataTransferProviderAccess.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> + +#include <com/sun/star/frame/XTitleChangeBroadcaster.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <comphelper/sequenceashashmap.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/proptypehlp.hxx> +#include <rtl/ustrbuf.hxx> +#include <vcl/window.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/svapp.hxx> + +#include <toolkit/unohlp.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/moduleoptions.hxx> + +#ifdef ENABLE_ASSERTIONS + #ifndef _RTL_STRBUF_HXX_ + #include <rtl/strbuf.hxx> + #endif +#endif + +#include <vcl/menu.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +namespace framework{ + +//_________________________________________________________________________________________________________________ +// non exported const +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// non exported definitions +//_________________________________________________________________________________________________________________ + +css::uno::WeakReference< css::frame::XFrame > Frame::m_xCloserFrame = css::uno::WeakReference< css::frame::XFrame >(); + +//_________________________________________________________________________________________________________________ +// declarations +//_________________________________________________________________________________________________________________ + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_21 ( Frame , + OWeakObject , + DIRECT_INTERFACE(css::lang::XTypeProvider ), + DIRECT_INTERFACE(css::lang::XServiceInfo ), + DIRECT_INTERFACE(css::frame::XFramesSupplier ), + DIRECT_INTERFACE(css::frame::XFrame ), + DIRECT_INTERFACE(css::lang::XComponent ), + DIRECT_INTERFACE(css::task::XStatusIndicatorFactory ), + DIRECT_INTERFACE(css::frame::XDispatchProvider ), + DIRECT_INTERFACE(css::frame::XDispatchInformationProvider ), + DIRECT_INTERFACE(css::frame::XDispatchProviderInterception ), + DIRECT_INTERFACE(css::beans::XPropertySet ), + DIRECT_INTERFACE(css::beans::XPropertySetInfo ), + DIRECT_INTERFACE(css::awt::XWindowListener ), + DIRECT_INTERFACE(css::awt::XTopWindowListener ), + DIRECT_INTERFACE(css::awt::XFocusListener ), + DERIVED_INTERFACE(css::lang::XEventListener, css::awt::XWindowListener ), + DIRECT_INTERFACE(css::document::XActionLockable ), + DIRECT_INTERFACE(css::util::XCloseable ), + DIRECT_INTERFACE(css::util::XCloseBroadcaster ), + DIRECT_INTERFACE(css::frame::XComponentLoader ), + DIRECT_INTERFACE(css::frame::XTitle ), + DIRECT_INTERFACE(css::frame::XTitleChangeBroadcaster ) + ) + +DEFINE_XTYPEPROVIDER_20 ( Frame , + css::lang::XTypeProvider , + css::lang::XServiceInfo , + css::frame::XFramesSupplier , + css::frame::XFrame , + css::lang::XComponent , + css::task::XStatusIndicatorFactory , + css::beans::XPropertySet , + css::beans::XPropertySetInfo , + css::frame::XDispatchProvider , + css::frame::XDispatchInformationProvider , + css::frame::XDispatchProviderInterception , + css::awt::XWindowListener , + css::awt::XTopWindowListener , + css::awt::XFocusListener , + css::lang::XEventListener , + css::util::XCloseable , + css::util::XCloseBroadcaster , + css::frame::XComponentLoader , + css::frame::XTitle , + css::frame::XTitleChangeBroadcaster + ) + +DEFINE_XSERVICEINFO_MULTISERVICE ( Frame , + ::cppu::OWeakObject , + SERVICENAME_FRAME , + IMPLEMENTATIONNAME_FRAME + ) + +DEFINE_INIT_SERVICE ( Frame, + { + /*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! + */ + css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW); + + //------------------------------------------------------------------------------------------------------------- + // 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 ); + + //------------------------------------------------------------------------------------------------------------- + DispatchInformationProvider* pInfoHelper = new DispatchInformationProvider(m_xFactory, this); + m_xDispatchInfoHelper = css::uno::Reference< css::frame::XDispatchInformationProvider >( static_cast< ::cppu::OWeakObject* >(pInfoHelper), 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 ); + + //------------------------------------------------------------------------------------------------------------- + // 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_aChildFrameContainer ); + m_xFramesHelper = css::uno::Reference< css::frame::XFrames >( static_cast< ::cppu::OWeakObject* >(pFramesHelper), css::uno::UNO_QUERY ); + + //------------------------------------------------------------------------------------------------------------- + // Initialize a the drop target listener. + // We hold member as reference ... not as pointer too! + DropTargetListener* pDropListener = new DropTargetListener( m_xFactory, this ); + m_xDropTargetListener = css::uno::Reference< css::datatransfer::dnd::XDropTargetListener >( static_cast< ::cppu::OWeakObject* >(pDropListener), css::uno::UNO_QUERY ); + + // Safe impossible cases + // We can't work without these helpers! + LOG_ASSERT2( xDispatchProvider.is ()==sal_False, "Frame::impl_initService()", "Slowest slave for dispatch- and interception helper isn't valid. XDispatchProvider, XDispatch, XDispatchProviderInterception are not full supported!" ) + LOG_ASSERT2( m_xDispatchHelper.is ()==sal_False, "Frame::impl_initService()", "Interception helper isn't valid. XDispatchProvider, XDispatch, XDispatchProviderInterception are not full supported!" ) + LOG_ASSERT2( m_xFramesHelper.is ()==sal_False, "Frame::impl_initService()", "Frames helper isn't valid. XFrames, XIndexAccess and XElementAcces are not supported!" ) + LOG_ASSERT2( m_xDropTargetListener.is()==sal_False, "Frame::impl_initService()", "DropTarget helper isn't valid. Drag and drop without functionality!" ) + + //------------------------------------------------------------------------------------------------------------- + // establish notifies for changing of "disabled commands" configuration during runtime + m_aCommandOptions.EstablisFrameCallback(this); + + //------------------------------------------------------------------------------------------------------------- + // Create an initial layout manager + // Create layout manager and connect it to the newly created frame + m_xLayoutManager = css::uno::Reference< css::frame::XLayoutManager >(m_xFactory->createInstance(SERVICENAME_LAYOUTMANAGER), css::uno::UNO_QUERY); + + //------------------------------------------------------------------------------------------------------------- + // set information about all supported properties at the base class helper PropertySetHelper + impl_initializePropInfo(); + } + ) + +/*-****************************************************************************************************//** + @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 ASSERT in debug version or nothing in relaese version. +*//*-*****************************************************************************************************/ +Frame::Frame( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ) + : ThreadHelpBase ( &Application::GetSolarMutex() ) + , TransactionBase ( ) + , PropertySetHelper ( xFactory, + &m_aLock, + &m_aTransactionManager, + sal_False) // sal_False => dont release shared mutex on calling us! + , ::cppu::OWeakObject ( ) + // init member + , m_xFactory ( xFactory ) + , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) + , m_xParent ( ) + , m_xContainerWindow ( ) + , m_xComponentWindow ( ) + , m_xController ( ) + , m_eActiveState ( E_INACTIVE ) + , m_sName ( ) + , m_bIsFrameTop ( sal_True ) // I think we are top without a parent ... and there is no parent yet! + , m_bConnected ( sal_False ) // There exist no component inside of use => sal_False, we are not connected! + , m_nExternalLockCount ( 0 ) + , m_bSelfClose ( sal_False ) // Important! + , m_bIsHidden ( sal_True ) + , m_xTitleHelper ( ) + , m_pWindowCommandDispatch ( 0 ) + , m_aChildFrameContainer ( ) +{ + // Check incoming parameter to avoid against wrong initialization. + LOG_ASSERT2( implcp_ctor( xFactory ), "Frame::Frame()", "Invalid parameter detected!" ) + + /* Please have a look on "@attentions" of description before! */ +} + +/*-****************************************************************************************************//** + @short standard destructor + @descr This one do NOTHING! Use dispose() instaed of this. + + @seealso method dispose() + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +Frame::~Frame() +{ + LOG_ASSERT2( m_aTransactionManager.getWorkingMode()!=E_CLOSE, "Frame::~Frame()", "Who forgot to dispose this service?" ) +} + +/*-************************************************************************************************************//** + @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 Frame::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 ) +{ + { + // If the frame is closed the call might lead to crash even with target "_blank", + // so the DisposedException should be thrown in this case + // It still looks to be too dangerous to set the transaction for the whole loading process + // so the guard is used in scopes to let the standard check be used + + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + } + + 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(); + + return LoadEnv::loadComponentFromURL(xThis, xSMGR, sURL, sTargetFrameName, nSearchFlags, lArguments); +} + +/*-****************************************************************************************************//** + @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. + + @seealso class OFrames + + @param - + @return A reference to the helper which answer your queries. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::frame::XFrames > SAL_CALL Frame::getFrames() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + +/*TODO + This is a temp. HACK! + Our parent (a Task!) stand in close/dispose and set working mode to E_BEFOERECLOSE + and call dispose on us! We tra to get this xFramesHelper and are reject by an "already closed" pranet instance .... + => We use SOFTEXCEPTIONS here ... but we should make it right in further times .... + */ + + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + // Return access to all child frames to caller. + // Ouer childframe container is implemented in helper class OFrames and used as a reference m_xFramesHelper! + return m_xFramesHelper; +} + +/*-****************************************************************************************************//** + @short get the current active child frame + @descr It must be a frameto. Direct childs of a frame are frames only! No task or desktop is accepted. + We don't save this information directly in this class. We use ouer container-helper + to do that. + + @seealso class OFrameContainer + @seealso method setActiveFrame() + + @param - + @return A reference to ouer current active childframe, if anyone exist. + @return A null reference, if nobody is active. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::frame::XFrame > SAL_CALL Frame::getActiveFrame() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + // Return current active frame. + // This information is avaliable on the container. + return m_aChildFrameContainer.getActive(); +} + +/*-****************************************************************************************************//** + @short set the new active direct child frame + @descr It must be a frame to. Direct childs of frame are frames only! No task or desktop is accepted. + We don't save this information directly in this class. We use ouer container-helper + to do that. + + @seealso class OFrameContainer + @seealso method getActiveFrame() + + @param "xFrame", reference to new active child. It must be an already existing child! + @return - + + @onerror An assertion is thrown and element is ignored, if given frame is'nt already a child of us. +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameters. + LOG_ASSERT2( implcp_setActiveFrame( xFrame ), "Frame::setActiveFrame()", "Invalid parameter detected!" ) + // Look for rejected calls! + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + + // Copy neccessary member for threadsafe access! + // m_aChildFrameContainer is threadsafe himself and he live if we live!!! + // ...and our transaction is non breakable too ... + css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive(); + EActiveState eActiveState = m_eActiveState ; + + aWriteLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + // Don't work, if "new" active frame is'nt different from current one! + // (xFrame==NULL is allowed to UNSET it!) + if( xActiveChild != xFrame ) + { + // ... otherwise set new and deactivate old one. + m_aChildFrameContainer.setActive( xFrame ); + if ( + ( eActiveState != E_INACTIVE ) && + ( xActiveChild.is() == sal_True ) + ) + { + xActiveChild->deactivate(); + } + } + + if( xFrame.is() == sal_True ) + { + // If last active frame had focus ... + // ... reset state to ACTIVE and send right FrameActionEvent for focus lost. + if( eActiveState == E_FOCUS ) + { + aWriteLock.lock(); + eActiveState = E_ACTIVE ; + m_eActiveState = eActiveState; + aWriteLock.unlock(); + implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING ); + } + + // If last active frame was active ... + // but new one isn't it ... + // ... set it as active one. + if ( + ( eActiveState == E_ACTIVE ) && + ( xFrame->isActive() == sal_False ) + ) + { + xFrame->activate(); + } + } + else + // If this frame is active and has no active subframe anymore it is UI active too + if( eActiveState == E_ACTIVE ) + { + aWriteLock.lock(); + eActiveState = E_FOCUS ; + m_eActiveState = eActiveState; + aWriteLock.unlock(); + implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED ); + } +} + +/*-****************************************************************************************************//** + initialize new created layout manager +**/ +void lcl_enableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager >& xLayoutManager, + const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + // Provide container window to our layout manager implementation + xLayoutManager->attachFrame(xFrame); + + css::uno::Reference< css::frame::XFrameActionListener > xListen(xLayoutManager, css::uno::UNO_QUERY_THROW); + xFrame->addFrameActionListener(xListen); + + DockingAreaDefaultAcceptor* pAcceptor = new DockingAreaDefaultAcceptor(xFrame); + css::uno::Reference< css::ui::XDockingAreaAcceptor > xDockingAreaAcceptor( static_cast< ::cppu::OWeakObject* >(pAcceptor), css::uno::UNO_QUERY_THROW); + xLayoutManager->setDockingAreaAcceptor(xDockingAreaAcceptor); +} + +/*-****************************************************************************************************//** + deinitialize layout manager +**/ +void lcl_disableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager >& xLayoutManager, + const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + css::uno::Reference< css::frame::XFrameActionListener > xListen(xLayoutManager, css::uno::UNO_QUERY_THROW); + xFrame->removeFrameActionListener(xListen); + xLayoutManager->setDockingAreaAcceptor(css::uno::Reference< css::ui::XDockingAreaAcceptor >()); + xLayoutManager->attachFrame(css::uno::Reference< css::frame::XFrame >()); +} + +/*-****************************************************************************************************//** + @short initialize frame instance + @descr A frame needs a window. This method set a new one ... but should called one times only! + We use this window to listen for window events and forward it to our set component. + Its used as parent of component window too. + + @seealso method getContainerWindow() + @seealso method setComponent() + @seealso member m_xContainerWindow + + @param "xWindow", reference to new container window - must be valid! + @return - + + @onerror We do nothing. +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::initialize( const css::uno::Reference< css::awt::XWindow >& xWindow ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + if (!xWindow.is()) + throw css::uno::RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Frame::initialize() called without a valid container window reference.")), + static_cast< css::frame::XFrame* >(this)); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + + if ( m_xContainerWindow.is() ) + throw css::uno::RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Frame::initialized() is called more then once, which isnt usefull nor allowed.")), + static_cast< css::frame::XFrame* >(this)); + + // Look for rejected calls first! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + // Enable object for real working ... so follow impl methods don't must handle it special! (e.g. E_SOFTEXCEPTIONS for rejected calls) + m_aTransactionManager.setWorkingMode( E_WORK ); + + // This must be the first call of this method! + // We should initialize our object and open it for working. + // Set the new window. + LOG_ASSERT2( m_xContainerWindow.is()==sal_True, "Frame::initialize()", "Leak detected! This state should never occure ..." ) + m_xContainerWindow = xWindow; + + // if window is initially visible, we will never get a windowShowing event + Window* pWindow = VCLUnoHelper::GetWindow(xWindow); + if (pWindow && pWindow->IsVisible()) + m_bIsHidden = sal_False; + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory; + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager = m_xLayoutManager; + + // Release lock ... because we call some impl methods, which are threadsafe by himself. + // If we hold this lock - we will produce our own deadlock! + aWriteLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + if (xLayoutManager.is()) + lcl_enableLayoutManager(xLayoutManager, this); + + // create progress helper + css::uno::Reference< css::frame::XFrame > xThis (static_cast< css::frame::XFrame* >(this) , css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::task::XStatusIndicatorFactory > xIndicatorFactory(xSMGR->createInstance(IMPLEMENTATIONNAME_STATUSINDICATORFACTORY), css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::lang::XInitialization > xIndicatorInit (xIndicatorFactory , css::uno::UNO_QUERY_THROW); + css::uno::Sequence< css::uno::Any > lArgs(2); + css::beans::NamedValue aArg; + aArg.Name = STATUSINDICATORFACTORY_PROPNAME_FRAME; + aArg.Value <<= xThis; + lArgs[0] <<= aArg; + aArg.Name = STATUSINDICATORFACTORY_PROPNAME_ALLOWPARENTSHOW; + aArg.Value <<= sal_True; + lArgs[1] <<= aArg; + xIndicatorInit->initialize(lArgs); + + // SAFE -> ---------------------------------- + aWriteLock.lock(); + m_xIndicatorFactoryHelper = xIndicatorFactory; + aWriteLock.unlock(); + // <- SAFE ---------------------------------- + + // Start listening for events after setting it on helper class ... + // So superflous messages are filtered to NULL :-) + implts_startWindowListening(); + + impl_enablePropertySet(); + + m_pWindowCommandDispatch = new WindowCommandDispatch(xSMGR, this); + + // Initialize title functionality + TitleHelper* pTitleHelper = new TitleHelper(xSMGR); + m_xTitleHelper = css::uno::Reference< css::frame::XTitle >(static_cast< ::cppu::OWeakObject* >(pTitleHelper), css::uno::UNO_QUERY_THROW); + pTitleHelper->setOwner(xThis); +} + +/*-****************************************************************************************************//** + @short returns current set container window + @descr The ContainerWindow property is used as a container for the component + in this frame. So this object implements a container interface too. + The instantiation of the container window is done by the user of this class. + The frame is the owner of its container window. + + @seealso method initialize() + + @param - + @return A reference to current set containerwindow. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::awt::XWindow > SAL_CALL Frame::getContainerWindow() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + return m_xContainerWindow; +} + +/*-****************************************************************************************************//** + @short set parent frame + @descr We need a parent to support some functionality! e.g. findFrame() + By the way we use the chance to set an internal information about our top state. + So we must not check this information during every isTop() call. + We are top, if our parent is the desktop instance or we havent any parent. + + @seealso getCreator() + @seealso findFrame() + @seealso isTop() + @seealos m_bIsFrameTop + + @param xCreator + valid reference to our new owner frame, which should implement a supplier interface + + @threadsafe yes + @modified 08.05.2002 09:35, as96863 +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& xCreator ) throw( css::uno::RuntimeException ) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE { */ + WriteGuard aWriteLock( m_aLock ); + m_xParent = xCreator; + aWriteLock.unlock(); + /* } SAFE */ + + css::uno::Reference< css::frame::XDesktop > xIsDesktop( xCreator, css::uno::UNO_QUERY ); + m_bIsFrameTop = ( xIsDesktop.is() || ! xCreator.is() ); +} + +/*-****************************************************************************************************//** + @short returns current parent frame + @descr The Creator is the parent frame container. If it is NULL, the frame is the uppermost one. + + @seealso method setCreator() + + @param - + @return A reference to current set parent frame container. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL Frame::getCreator() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + return m_xParent; +} + +/*-****************************************************************************************************//** + @short returns current set name of frame + @descr This name is used to find target of findFrame() or queryDispatch() calls. + + @seealso method setName() + + @param - + @return Current set name of frame. + + @onerror An empty string is returned. +*//*-*****************************************************************************************************/ +::rtl::OUString SAL_CALL Frame::getName() throw( css::uno::RuntimeException ) +{ + /* SAFE { */ + ReadGuard aReadLock( m_aLock ); + return m_sName; + /* } SAFE */ +} + +/*-****************************************************************************************************//** + @short set new name for frame + @descr This name is used to find target of findFrame() or queryDispatch() calls. + + @attention Special names like "_blank", "_self" aren't allowed ... + "_beamer" or "_menubar" excepts this rule! + + @seealso method getName() + + @param "sName", new frame name. + @return - + + @onerror We do nothing. +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::setName( const ::rtl::OUString& sName ) throw( css::uno::RuntimeException ) +{ + /* SAFE { */ + WriteGuard aWriteLock( m_aLock ); + // Set new name ... but look for invalid special target names! + // They are not allowed to set. + if (TargetHelper::isValidNameForFrame(sName)) + m_sName = sName; + aWriteLock.unlock(); + /* } SAFE */ +} + +/*-****************************************************************************************************//** + @short search for frames + @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", "_blank" etc. The nSearchFlags are ignored + when comparing these names with sTargetFrameName, further steps are + controlled by the search flags. 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, for siblings + and as last for the parent frame. + If no frame with the given name is found until the top frames container, + a new top one is created, if this is allowed by a special + flag. The new frame also gets the desired name. + + @param sTargetFrameName + special names (_blank, _self) or real name of target frame + @param nSearchFlags + optional flags which regulate search for non special target frames + + @return A reference to found or may be new created frame. + @threadsafe yes + @modified 16.05.2002 11:08, as96863 +*//*-*****************************************************************************************************/ +css::uno::Reference< css::frame::XFrame > SAL_CALL Frame::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()! + ) + { + 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::frame::XFrame > xParent ( m_xParent, css::uno::UNO_QUERY ); + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory; + sal_Bool bIsTopFrame = m_bIsFrameTop; + sal_Bool bIsTopWindow = WindowHelper::isTopWindow(m_xContainerWindow); + aReadLock.unlock(); + /* } SAFE */ + + //----------------------------------------------------------------------------------------------------- + // I.I) "_blank" + // Not allowed for a normal frame - but for the desktop. + // Use helper class to do so. It use the desktop automaticly. + //----------------------------------------------------------------------------------------------------- + if ( sTargetFrameName==SPECIALTARGET_BLANK ) + { + TaskCreator aCreator(xFactory); + xTarget = aCreator.createTask(sTargetFrameName,sal_False); + } + + //----------------------------------------------------------------------------------------------------- + // I.II) "_parent" + // It doesn't matter if we have a valid parent or not. User ask for him and get it. + // An empty result is a valid result too. + //----------------------------------------------------------------------------------------------------- + else + if ( sTargetFrameName==SPECIALTARGET_PARENT ) + { + xTarget = xParent; + } + + //----------------------------------------------------------------------------------------------------- + // I.III) "_top" + // If we are not the top frame in this hierarchy, we must forward request to our parent. + // Otherwhise we must return ourself. + //----------------------------------------------------------------------------------------------------- + else + if ( sTargetFrameName==SPECIALTARGET_TOP ) + { + if (bIsTopFrame) + xTarget = this; + else + if (xParent.is()) // If we are not top - the parent MUST exist. But may it's better to check it again .-) + xTarget = xParent->findFrame(SPECIALTARGET_TOP,0); + } + + //----------------------------------------------------------------------------------------------------- + // I.IV) "_self", "" + // This mean this frame in every case. + //----------------------------------------------------------------------------------------------------- + else + if ( + ( sTargetFrameName==SPECIALTARGET_SELF ) || + ( sTargetFrameName.getLength()<1 ) + ) + { + xTarget = this; + } + + //----------------------------------------------------------------------------------------------------- + // I.V) "_beamer" + // This is a special sub frame of any task. We must return it if we found it on our direct childrens + // or create it there if it not already exists. + // Note: Such beamer exists for task(top) frames only! + //----------------------------------------------------------------------------------------------------- + else + if ( sTargetFrameName==SPECIALTARGET_BEAMER ) + { + // We are a task => search or create the beamer + if (bIsTopWindow) + { + xTarget = m_aChildFrameContainer.searchOnDirectChildrens(SPECIALTARGET_BEAMER); + if ( ! xTarget.is() ) + { + /* TODO + Creation not supported yet! + Wait for new layout manager service because we can't plug it + inside already opened document of this frame ... + */ + } + } + // We arent a task => forward request to our parent or ignore it. + else + if (xParent.is()) + xTarget = xParent->findFrame(SPECIALTARGET_BEAMER,0); + } + + 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. + //------------------------------------------------------------------------------------------------- + + // 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) 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_aChildFrameContainer.searchOnAllChildrens(sTargetFrameName); + } + + //------------------------------------------------------------------------------------------------- + // II.III) TASKS + // This is a special flag. It regulate search on this task tree only or allow search on + // all other ones (which are sibling trees of us) too. + // Upper search must stop at this frame if we are the topest one and the TASK flag isn't set + // or we can ignore it if we have no valid parent. + //------------------------------------------------------------------------------------------------- + if ( + ( bIsTopFrame && (nSearchFlags & css::frame::FrameSearchFlag::TASKS) ) || + ( ! bIsTopFrame ) + ) + { + //------------------------------------------------------------------------------------------------- + // II.III.I) SIBLINGS + // Search on all our direct siblings - means all childrens of our parent. + // Use this flag in combination with TASK. We must supress such upper search if + // user has not set it and if we are a top frame. + // Attention: Don't forward this request to our parent as a findFrame() call. + // In such case we must protect us against recursive calls. + // Use snapshot of our parent. But don't use queryFrames() of XFrames interface. + // Because it's return all siblings and all her childrens including our children too + // if we call it with the CHILDREN flag. We doesn't need that - we need the direct container + // items of our parent only to start searches there. So we must use the container interface + // XIndexAccess instead of XFrames. + //------------------------------------------------------------------------------------------------- + if ( + ( ! xTarget.is() ) && + (nSearchFlags & css::frame::FrameSearchFlag::SIBLINGS) && + ( xParent.is() ) // search on siblings is impossible without a parent + ) + { + css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY ); + if (xSupplier.is()) + { + css::uno::Reference< css::container::XIndexAccess > xContainer( xSupplier->getFrames(), css::uno::UNO_QUERY ); + if (xContainer.is()) + { + sal_Int32 nCount = xContainer->getCount(); + for( sal_Int32 i=0; i<nCount; ++i ) + { + css::uno::Reference< css::frame::XFrame > xSibling; + if ( + ( !(xContainer->getByIndex(i)>>=xSibling) ) || // control unpacking + ( ! xSibling.is() ) || // check for valid items + ( xSibling==static_cast< ::cppu::OWeakObject* >(this) ) // ignore ourself! (We are a part of this container too - but search on our children was already done.) + ) + { + continue; + } + + // Don't allow upper search here! Use rigth flags to regulate it. + // And allow deep search on children only - if it was allowed for us too. + sal_Int32 nRightFlags = css::frame::FrameSearchFlag::SELF; + if (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN) + nRightFlags |= css::frame::FrameSearchFlag::CHILDREN; + xTarget = xSibling->findFrame(sTargetFrameName, nRightFlags ); + // perform search be breaking further search if a result exist. + if (xTarget.is()) + break; + } + } + } + } + + //------------------------------------------------------------------------------------------------- + // II.III.II) PARENT + // Forward search to our parent (if he exists.) + // To prevent us against recursive and superflous calls (which can occure if we allow him + // to search on his childrens too) we must change used search flags. + //------------------------------------------------------------------------------------------------- + if ( + ( ! xTarget.is() ) && + (nSearchFlags & css::frame::FrameSearchFlag::PARENT) && + ( xParent.is() ) + ) + { + if (xParent->getName() == sTargetFrameName) + xTarget = xParent; + else + { + sal_Int32 nRightFlags = nSearchFlags; + nRightFlags &= ~css::frame::FrameSearchFlag::CHILDREN; + xTarget = xParent->findFrame(sTargetFrameName, nRightFlags); + } + } + } + + //------------------------------------------------------------------------------------------------- + // 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 Desktop instance automaticly as parent! + //------------------------------------------------------------------------------------------------- + if ( + ( ! xTarget.is() ) && + (nSearchFlags & css::frame::FrameSearchFlag::CREATE) + ) + { + TaskCreator aCreator(xFactory); + xTarget = aCreator.createTask(sTargetFrameName,sal_False); + } + } + + return xTarget; +} + +/*-****************************************************************************************************//** + @short - + @descr Returns sal_True, if this frame is a "top frame", otherwise sal_False. + The "m_bIsFrameTop" member must be set in the ctor or setCreator() method. + A top frame is a member of the top frame container or a member of the + task frame container. Both containers can create new frames if the findFrame() + method of their css::frame::XFrame interface is called with a frame name not yet known. + + @seealso ctor + @seealso method setCreator() + @seealso method findFrame() + + @param - + @return true, if is it a top frame ... false otherwise. + + @onerror No error should occure! +*//*-*****************************************************************************************************/ +sal_Bool SAL_CALL Frame::isTop() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + // This information is set in setCreator(). + // We are top, if ouer parent is a task or the desktop or if no parent exist! + return m_bIsFrameTop; +} + +/*-****************************************************************************************************//** + @short activate frame in hierarchy + @descr This feature is used to mark active pathes in our frame hierarchy. + You can be a listener for this event to react for it ... change some internal states or something else. + + @seealso method deactivate() + @seealso method isActivate() + @seealso enum EActiveState + @seealso listener mechanism + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::activate() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + + // Copy neccessary member and free the lock. + // It's not neccessary for m_aChildFrameContainer ... because + // he is threadsafe himself and live if we live. + // We use a registered transaction to prevent us against + // breaks during this operation! + css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive() ; + css::uno::Reference< css::frame::XFramesSupplier > xParent ( m_xParent, css::uno::UNO_QUERY ) ; + css::uno::Reference< css::frame::XFrame > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + css::uno::Reference< css::awt::XWindow > xComponentWindow( m_xComponentWindow, css::uno::UNO_QUERY ) ; + EActiveState eState = m_eActiveState ; + + aWriteLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + //_________________________________________________________________________________________________________ + // 1) If I'am not active before ... + if( eState == E_INACTIVE ) + { + // ... do it then. + aWriteLock.lock(); + eState = E_ACTIVE; + m_eActiveState = eState; + aWriteLock.unlock(); + // Deactivate sibling path and forward activation to parent ... if any parent exist! + if( xParent.is() == sal_True ) + { + // Everytime set THIS frame as active child of parent and activate it. + // We MUST have a valid path from bottom to top as active path! + // But we must deactivate the old active sibling path first. + + // Attention: Deactivation of an active path, deactivate the whole path ... from bottom to top! + // But we wish to deactivate founded sibling-tree only. + // [ see deactivate() / step 4) for further informations! ] + + xParent->setActiveFrame( xThis ); + + // Then we can activate from here to top. + // Attention: We are ACTIVE now. And the parent will call activate() at us! + // But we do nothing then! We are already activated. + xParent->activate(); + } + // Its neccessary to send event NOW - not before. + // Activation goes from bottom to top! + // Thats the reason to activate parent first and send event now. + implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_ACTIVATED ); + } + + //_________________________________________________________________________________________________________ + // 2) I was active before or current activated and there is a path from here to bottom, who CAN be active. + // But ouer direct child of path is not active yet. + // (It can be, if activation occur in the middle of a current path!) + // In these case we activate path to bottom to set focus on right frame! + if ( + ( eState == E_ACTIVE ) && + ( xActiveChild.is() == sal_True ) && + ( xActiveChild->isActive() == sal_False ) + ) + { + xActiveChild->activate(); + } + + //_________________________________________________________________________________________________________ + // 3) I was active before or current activated. But if I have no active child => I will get the focus! + if ( + ( eState == E_ACTIVE ) && + ( xActiveChild.is() == sal_False ) + ) + { + aWriteLock.lock(); + eState = E_FOCUS; + m_eActiveState = eState; + aWriteLock.unlock(); + implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED ); + } +} + +/*-****************************************************************************************************//** + @short deactivate frame in hierarchy + @descr This feature is used to deactive pathes in our frame hierarchy. + You can be a listener for this event to react for it ... change some internal states or something else. + + @seealso method activate() + @seealso method isActivate() + @seealso enum EActiveState + @seealso listener mechanism + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::deactivate() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + + // Copy neccessary member and free the lock. + css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive() ; + css::uno::Reference< css::frame::XFramesSupplier > xParent ( m_xParent, css::uno::UNO_QUERY ) ; + css::uno::Reference< css::frame::XFrame > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + EActiveState eState = m_eActiveState ; + + aWriteLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + // Work only, if there something to do! + if( eState != E_INACTIVE ) + { + //_____________________________________________________________________________________________________ + // 1) Deactivate all active childs. + if ( + ( xActiveChild.is() == sal_True ) && + ( xActiveChild->isActive() == sal_True ) + ) + { + xActiveChild->deactivate(); + } + + //_____________________________________________________________________________________________________ + // 2) If I have the focus - I will lost it now. + if( eState == E_FOCUS ) + { + // Set new state INACTIVE(!) and send message to all listener. + // Don't set ACTIVE as new state. This frame is deactivated for next time - due to activate(). + aWriteLock.lock(); + eState = E_ACTIVE; + m_eActiveState = eState ; + aWriteLock.unlock(); + implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING ); + } + + //_____________________________________________________________________________________________________ + // 3) If I'am active - I will be deactivated now. + if( eState == E_ACTIVE ) + { + // Set new state and send message to all listener. + aWriteLock.lock(); + eState = E_INACTIVE; + m_eActiveState = eState ; + aWriteLock.unlock(); + implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_DEACTIVATING ); + } + + //_____________________________________________________________________________________________________ + // 4) If there is a path from here to my parent ... + // ... I'am on the top or in the middle of deactivated subtree and action was started here. + // I must deactivate all frames from here to top, which are members of current path. + // Stop, if THESE frame not the active frame of ouer parent! + if ( + ( xParent.is() == sal_True ) && + ( xParent->getActiveFrame() == xThis ) + ) + { + // We MUST break the path - otherwise we will get the focus - not ouer parent! ... + // Attention: Ouer parent don't call us again - WE ARE NOT ACTIVE YET! + // [ see step 3 and condition "if ( m_eActiveState!=INACTIVE ) ..." in this method! ] + xParent->deactivate(); + } + } +} + +/*-****************************************************************************************************//** + @short returns active state + @descr Call it to get informations about current active state of this frame. + + @seealso method activate() + @seealso method deactivate() + @seealso enum EActiveState + + @param - + @return true if active, false otherwise. + + @onerror No error should occure. +*//*-*****************************************************************************************************/ +sal_Bool SAL_CALL Frame::isActive() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + return ( + ( m_eActiveState == E_ACTIVE ) || + ( m_eActiveState == E_FOCUS ) + ); +} + +/*-****************************************************************************************************//** + @short ??? + @descr - + + @seealso - + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::contextChanged() throw( css::uno::RuntimeException ) +{ + // Look for rejected calls! + // Sometimes called during closing object... => soft exceptions + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + // Impl-method is threadsafe himself! + // Send event to all listener for frame actions. + implts_sendFrameActionEvent( css::frame::FrameAction_CONTEXT_CHANGED ); +} + +/*-****************************************************************************************************//** + @short set new component inside the frame + @descr A frame is a container for a component. Use this method to set, change or realease it! + We accept null references! The xComponentWindow will be a child of our container window + and get all window events from us. + + @attention (a) A current set component can disagree with the suspend() request! + We don't set the new one and return with false then. + (b) It's possible to set: + (b1) a simple component here which supports the window only - no controller; + (b2) a full featured component which supports window and controller; + (b3) or both to NULL if outside code which to forget this component. + + @seealso method getComponentWindow() + @seealso method getController() + + @param xComponentWindow + valid reference to new component window which will be a child of internal container window + May <NULL/> for releasing. + @param xController + reference to new component controller + (may <NULL/> for relasing or setting of a simple component) + + @return <TRUE/> if operation was successful, <FALSE/> otherwise. + + @onerror We return <FALSE/>. + @threadsafe yes + @modified 06.05.2002 11:39, as96863 +*//*-*****************************************************************************************************/ +sal_Bool SAL_CALL Frame::setComponent( const css::uno::Reference< css::awt::XWindow >& xComponentWindow , + const css::uno::Reference< css::frame::XController >& xController ) throw( css::uno::RuntimeException ) +{ + //_____________________________________________________________________________________________________ + // Ignore this HACK of sfx2! + // He call us with an valid controller without a valid window ... Thats not allowed! + if ( xController.is() && ! xComponentWindow.is() ) + return sal_True; + + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + //_____________________________________________________________________________________________________ + // Get threadsafe some copies of used members. + /* SAFE { */ + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow; + css::uno::Reference< css::awt::XWindow > xOldComponentWindow = m_xComponentWindow; + css::uno::Reference< css::frame::XController > xOldController = m_xController; + Window* pOwnWindow = VCLUnoHelper::GetWindow( xContainerWindow ); + sal_Bool bHadFocus = pOwnWindow->HasChildPathFocus(); + sal_Bool bWasConnected = m_bConnected; + aReadLock.unlock(); + /* } SAFE */ + + //_____________________________________________________________________________________________________ + // stop listening on old window + // May it produce some trouble. + // But don't forget to listen on new window again ... or reactivate listening + // if we reject this setComponent() request and leave this method without changing the old window. + implts_stopWindowListening(); + + // Notify all listener, that this component (if current one exist) will be unloaded. + if (bWasConnected) + implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_DETACHING ); + + //_____________________________________________________________________________________________________ + // otherwhise release old component first + // Always release controller before releasing window, + // because controller may want to access its window! + // But check for real changes - may the new controller is the old one. + if ( + (xOldController.is() ) && + (xOldController != xController) + ) + { + /* ATTENTION + Don't suspend the old controller here. Because the outside caller must do that + by definition. We have to dispose it here only. + */ + + // Before we dispose this controller we should hide it inside this frame instance. + // We hold it alive for next calls by using xOldController! + /* SAFE {*/ + WriteGuard aWriteLock( m_aLock ); + m_xController = NULL; + aWriteLock.unlock(); + /* } SAFE */ + + css::uno::Reference< css::lang::XComponent > xDisposable( xOldController, css::uno::UNO_QUERY ); + if (xDisposable.is()) + { + try + { + xDisposable->dispose(); + } + catch(const css::lang::DisposedException&) + {} + } + xOldController = NULL; + } + + //_____________________________________________________________________________________________________ + // Now it's time to release the component window. + // If controller wasn't released successfully - this code line shouldn't be reached. + // Because in case of "suspend()==false" we return immediately with false ... + // see before + // Check for real changes too. + if ( + (xOldComponentWindow.is() ) && + (xOldComponentWindow != xComponentWindow) + ) + { + /* SAFE { */ + WriteGuard aWriteLock( m_aLock ); + m_xComponentWindow = NULL; + aWriteLock.unlock(); + /* } SAFE */ + + css::uno::Reference< css::lang::XComponent > xDisposable( xOldComponentWindow, css::uno::UNO_QUERY ); + if (xDisposable.is()) + { + try + { + xDisposable->dispose(); + } + catch(const css::lang::DisposedException&) + {} + } + xOldComponentWindow = NULL; + } + + //_____________________________________________________________________________________________________ + // Now it's time to set the new component ... + // By the way - find out our new "load state" - means if we have a valid component inside. + /* SAFE { */ + WriteGuard aWriteLock( m_aLock ); + m_xComponentWindow = xComponentWindow; + m_xController = xController ; + m_bConnected = (m_xComponentWindow.is() || m_xController.is()); + sal_Bool bIsConnected = m_bConnected; + aWriteLock.unlock(); + /* } SAFE */ + + //_____________________________________________________________________________________________________ + // notifies all interest listener, that current component was changed or a new one was loaded + if (bIsConnected && bWasConnected) + implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_REATTACHED ); + else + if (bIsConnected && !bWasConnected) + implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_ATTACHED ); + + //_____________________________________________________________________________________________________ + // A new component window doesn't know anything about current active/focus states. + // Set this information on it! + if ( + (bHadFocus ) && + (xComponentWindow.is()) + ) + { + xComponentWindow->setFocus(); + } + + // If it was a new component window - we must resize it to fill out + // our container window. + implts_resizeComponentWindow(); + // New component should change our current icon ... + implts_setIconOnWindow(); + // OK - start listening on new window again - or do nothing if it is an empty one. + implts_startWindowListening(); + + /* SAFE { */ + aWriteLock.lock(); + impl_checkMenuCloser(); + aWriteLock.unlock(); + /* } SAFE */ + + return sal_True; +} + +/*-****************************************************************************************************//** + @short returns current set component window + @descr Frames are used to display components. The actual displayed component is + held by the m_xComponentWindow property. If the component implements only a + XComponent interface, the communication between the frame and the + component is very restricted. Better integration is achievable through a + XController interface. + If the component wants other objects to be able to get information about its + ResourceDescriptor it has to implement a XModel interface. + This frame is the owner of the component window. + + @seealso method setComponent() + + @param - + @return css::uno::Reference to current set component window. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::awt::XWindow > SAL_CALL Frame::getComponentWindow() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Register transaction and reject wrong calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + return m_xComponentWindow; +} + +/*-****************************************************************************************************//** + @short returns current set controller + @descr Frames are used to display components. The actual displayed component is + held by the m_xComponentWindow property. If the component implements only a + XComponent interface, the communication between the frame and the + component is very restricted. Better integration is achievable through a + XController interface. + If the component wants other objects to be able to get information about its + ResourceDescriptor it has to implement a XModel interface. + This frame is the owner of the component window. + + @seealso method setComponent() + + @param - + @return css::uno::Reference to current set controller. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::frame::XController > SAL_CALL Frame::getController() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + return m_xController; +} + +/*-****************************************************************************************************//** + @short add/remove listener for activate/deactivate/contextChanged events + @descr - + + @seealso method activate() + @seealso method deactivate() + @seealso method contextChanged() + + @param "xListener" reference to your listener object + @return - + + @onerror Listener is ignored. +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_addFrameActionListener( xListener ), "Frame::addFrameActionListener()", "Invalid parameter detected." ) + // Listener container is threadsafe by himself ... but we must look for rejected calls! + // Our OMenuDispatch-helper (is a member of ODispatchProvider!) is create at startup of this frame BEFORE initialize! + // => soft exceptions! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XFrameActionListener >*)NULL ), xListener ); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_removeFrameActionListener( xListener ), "Frame::removeFrameActionListener()", "Invalid parameter detected." ) + // Listener container is threadsafe by himself ... but we must look for rejected calls after disposing! + // But we must work with E_SOFTEXCEPTIONS ... because sometimes we are called from our listeners + // during dispose! Our work mode is E_BEFORECLOSE then ... and E_HARDEXCEPTIONS whould throw a DisposedException. + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XFrameActionListener >*)NULL ), xListener ); +} + +/*-****************************************************************************************************//** + @short support two way mechanism to release a frame + @descr This method ask internal component (controller) if he accept this close request. + In case of <TRUE/> nothing will be happen (from point of caller of this close method). + In case of <FALSE/> a CloseVetoException is thrown. After such exception given parameter + <var>bDeliverOwnerShip</var> regulate which will be the new owner of this instance. + + @attention It's the replacement for XTask::close() which is marked as obsolete method. + + @param bDeliverOwnerShip + If parameter is set to <FALSE/> the original caller will be the owner after thrown + veto exception and must try to close this frame at later time again. Otherwhise the + source of throwed exception is the right one. May it will be the frame himself. + + @thrown CloseVetoException + if any internal things willn't be closed + + @threadsafe yes + @modified 06.05.2002 08:33, as96863 +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::close( sal_Bool bDeliverOwnerShip ) throw( css::util::CloseVetoException, + css::uno::RuntimeException ) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + // At the end of this method may we must dispose ourself ... + // and may nobody from outside hold a reference to us ... + // then it's a good idea to do that by ourself. + css::uno::Reference< css::uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) ); + + // Check any close listener before we look for currently running internal processes. + // Because if a listener disagree with this close() request - we hace time to finish this + // internal operations too ... + // Note: container is threadsafe himself. + css::lang::EventObject aSource (static_cast< ::cppu::OWeakObject*>(this)); + ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >*) NULL ) ); + if (pContainer!=NULL) + { + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + ((css::util::XCloseListener*)pIterator.next())->queryClosing( aSource, bDeliverOwnerShip ); + } + catch( css::uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + + // Ok - no listener disagreed with this close() request + // check if this frame is used for any load process currently + if (isActionLocked()) + { + if (bDeliverOwnerShip) + { + /* SAFE */ + WriteGuard aWriteLock( m_aLock ); + m_bSelfClose = sal_True; + aWriteLock.unlock(); + /* SAFE */ + } + + throw css::util::CloseVetoException(DECLARE_ASCII("Frame in use for loading document ..."),static_cast< ::cppu::OWeakObject*>(this)); + } + + if ( ! setComponent(NULL,NULL) ) + throw css::util::CloseVetoException(DECLARE_ASCII("Component couldn't be deattached ..."),static_cast< ::cppu::OWeakObject*>(this)); + + // If closing is allowed ... inform all istener and dispose this frame! + pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >*) NULL ) ); + if (pContainer!=NULL) + { + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + ((css::util::XCloseListener*)pIterator.next())->notifyClosing( aSource ); + } + catch( css::uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + + /* SAFE { */ + WriteGuard aWriteLock( m_aLock ); + m_bIsHidden = sal_True; + aWriteLock.unlock(); + /* } SAFE */ + impl_checkMenuCloser(); + + // Attention: We must release our own registered transaction here. Otherwhise following dispose() call + // wait for us too .... + aTransaction.stop(); + dispose(); +} + +/*-****************************************************************************************************//** + @short be a listener for close events! + @descr Adds/remove a CloseListener at this frame instance. If the close() method is called on + this object, the such listener are informed and can disagree with that by throwing + a CloseVetoException. + + @seealso Frame::close() + + @param xListener + reference to your listener object + + @onerror Listener is ignored. + + @threadsafe yes + @modified 06.05.2002 10:03, as96863 +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::addCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener ) throw (css::uno::RuntimeException) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + // We doesn't need any lock here ... + // Container lives if we live and is threadsafe by himself. + m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >* ) NULL ), xListener ); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::removeCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener ) throw (css::uno::RuntimeException) +{ + // Use soft exception mode - moslty this method is called during disposing of this frame ... + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + // We doesn't need any lock here ... + // Container lives if we live and is threadsafe by himself. + m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::util::XCloseListener >* ) NULL ), xListener ); +} + +//***************************************************************************************************************** +::rtl::OUString SAL_CALL Frame::getTitle() + throw (css::uno::RuntimeException) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + // SAFE -> + ReadGuard aReadLock(m_aLock); + css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW); + aReadLock.unlock(); + // <- SAFE + + return xTitle->getTitle(); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::setTitle( const ::rtl::OUString& sTitle ) + throw (css::uno::RuntimeException) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + // SAFE -> + ReadGuard aReadLock(m_aLock); + css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW); + aReadLock.unlock(); + // <- SAFE + + xTitle->setTitle(sTitle); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::addTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) + throw (css::uno::RuntimeException) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + // SAFE -> + ReadGuard aReadLock(m_aLock); + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW); + aReadLock.unlock(); + // <- SAFE + + xTitle->addTitleChangeListener(xListener); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::removeTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener ) + throw (css::uno::RuntimeException) +{ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + // SAFE -> + ReadGuard aReadLock(m_aLock); + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW); + aReadLock.unlock(); + // <- SAFE + + xTitle->removeTitleChangeListener(xListener); +} + +/*-****************************************************************************************************/ +void Frame::implts_forgetSubFrames() +{ + // SAFE -> + ReadGuard aReadLock(m_aLock); + css::uno::Reference< css::container::XIndexAccess > xContainer(m_xFramesHelper, css::uno::UNO_QUERY_THROW); + aReadLock.unlock(); + // <- SAFE + + sal_Int32 c = xContainer->getCount(); + sal_Int32 i = 0; + + for (i=0; i<c; ++i) + { + try + { + css::uno::Reference< css::frame::XFrame > xFrame; + xContainer->getByIndex(i) >>= xFrame; + if (xFrame.is()) + xFrame->setCreator(css::uno::Reference< css::frame::XFramesSupplier >()); + } + catch(const css::uno::Exception&) + { + // Ignore errors here. + // Nobody can guarantee a stable index in multi threaded environments .-) + } + } + + // SAFE -> + WriteGuard aWriteLock(m_aLock); + m_xFramesHelper.clear(); // clear uno reference + m_aChildFrameContainer.clear(); // clear container content + aWriteLock.unlock(); + // <- SAFE +} + +/*-****************************************************************************************************//** + @short destroy instance + @descr The owner of this object calles the dispose method if the object + should be destroyed. All other objects and components, that are registered + as an EventListener are forced to release their references to this object. + Furthermore this frame is removed from its parent frame container to release + this reference. The reference attributes are disposed and released also. + + @attention Look for globale description at beginning of file too! + (DisposedException, FairRWLock ..., initialize, dispose) + + @seealso method initialize() + @seealso baseclass FairRWLockBase! + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::dispose() throw( css::uno::RuntimeException ) +{ + // We should hold a reference to ourself ... + // because our owner dispose us and release our reference ... + // May be we will die before we could finish this method ... + css::uno::Reference< css::frame::XFrame > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + + LOG_DISPOSEEVENT( "Frame", sName ) + + // First operation should be ... "stopp all listening for window events on our container window". + // These events are superflous but can make trouble! + // We will die, die and die ... + implts_stopWindowListening(); + + delete m_pWindowCommandDispatch; + + // Send message to all listener and forget her references. + css::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + // set "end of live" for our property set helper + impl_disablePropertySet(); + + // interception/dispatch chain must be destructed explicitly + // Otherwhise some dispatches and/or interception objects wont die. + css::uno::Reference< css::lang::XEventListener > xDispatchHelper(m_xDispatchHelper, css::uno::UNO_QUERY_THROW); + xDispatchHelper->disposing(aEvent); + xDispatchHelper.clear(); + + // Disable this instance for further work. + // This will wait for all current running ones ... + // and reject all further requests! + m_aTransactionManager.setWorkingMode( E_BEFORECLOSE ); + + // Don't show any dialogs, errors or something else any more! + // If somewhere called dispose() whitout close() before - normaly no dialogs + // should exist. Otherwhise it's the problem of the outside caller. + // Note: + // (a) Do it after stopWindowListening(). May that force some active/deactive + // notifications which we doesn't need here realy. + // (b) Don't forget to save the old value of IsDialogCancelEnabled() to + // restore it afterwards. We cannot call EnableDialogCancel( sal_False ) + // as we would kill the headless mode! + sal_Bool bCancelDialogs( Application::IsDialogCancelEnabled() ); + Application::EnableDialogCancel( sal_True ); + + // We should be alone for ever and further dispose calls are rejected by lines before ... + // I hope it :-) + + // Free references of our frame tree. + // Force parent container to forget this frame too ... + // ( It's contained in m_xParent and so no css::lang::XEventListener for m_xParent! ) + // It's important to do that before we free some other internal structures. + // Because if our parent gets an activate and found us as last possible active frame + // he try to deactivate us ... and we run into some trouble (DisposedExceptions!). + if( m_xParent.is() == sal_True ) + { + m_xParent->getFrames()->remove( xThis ); + m_xParent = css::uno::Reference< css::frame::XFramesSupplier >(); + } + + /* } SAFE */ + // Forget our internal component and her window first. + // So we can release our container window later without problems. + // Because this container window is the parent of the component window ... + // Note: Dispose it hard - because suspending must be done inside close() call! + // But try to dispose the controller first befor you destroy the window. + // Because the window is used by the controller too ... + if (m_xController.is()) + { + css::uno::Reference< css::lang::XComponent > xDisposable( m_xController, css::uno::UNO_QUERY ); + if (xDisposable.is()) + xDisposable->dispose(); + } + + if (m_xComponentWindow.is()) + { + css::uno::Reference< css::lang::XComponent > xDisposable( m_xComponentWindow, css::uno::UNO_QUERY ); + if (xDisposable.is()) + xDisposable->dispose(); + } + + impl_checkMenuCloser(); + + impl_disposeContainerWindow( m_xContainerWindow ); + + /*ATTENTION + Clear container after successful removing from parent container ... + because our parent could be the desktop which stand in dispose too! + If we have already cleared our own container we lost our child before this could be + remove himself at this instance ... + Release m_xFramesHelper after that ... it's the same problem between parent and child! + "m_xParent->getFrames()->remove( xThis );" needs this helper ... + Otherwise we get a null reference and could finish removing successfuly. + => You see: Order of calling operations is important!!! + */ + implts_forgetSubFrames(); + + // Release some other references. + // This calls should be easy ... I hope it :-) + m_xDispatchHelper.clear(); + m_xFactory.clear(); + m_xDropTargetListener.clear(); + m_xDispatchRecorderSupplier.clear(); + m_xLayoutManager.clear(); + m_xIndicatorFactoryHelper.clear(); + + // It's important to set default values here! + // If may be later somewhere change the disposed-behaviour of this implementation + // and doesn't throw any DisposedExceptions we must guarantee best matching default values ... + m_eActiveState = E_INACTIVE; + m_sName = ::rtl::OUString(); + m_bIsFrameTop = sal_False; + m_bConnected = sal_False; + m_nExternalLockCount = 0; + m_bSelfClose = sal_False; + m_bIsHidden = sal_True; + + // Disable this instance for further working realy! + m_aTransactionManager.setWorkingMode( E_CLOSE ); + + // Don't forget it restore old value - + // otherwhise no dialogs can be shown anymore in other frames. + Application::EnableDialogCancel( bCancelDialogs ); +} + +/*-****************************************************************************************************//** + @short Be a listener for dispose events! + @descr Adds/remove an EventListener to this object. If the dispose method is called on + this object, the disposing method of the listener is called. + + @seealso - + + @param "xListener" reference to your listener object. + @return - + + @onerror Listener is ignored. +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_addEventListener( xListener ), "Frame::addEventListener()", "Invalid parameter detected." ) + // Look for rejected calls only! + // Container is threadsafe. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener ); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_removeEventListener( xListener ), "Frame::removeEventListener()", "Invalid parameter detected." ) + // Look for rejected calls only! + // Container is threadsafe. + // Use E_SOFTEXCEPTIONS to allow removing listeners during dispose call! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener ); +} + +/*-****************************************************************************************************//** + @short create new status indicator + @descr Use returned status indicator to show progresses and some text informations. + All created objects share the same dialog! Only the last one can show his information. + + @seealso class StatusIndicatorFactory + @seealso class StatusIndicator + + @param - + @return A reference to created object. + + @onerror We return a null reference. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::task::XStatusIndicator > SAL_CALL Frame::createStatusIndicator() throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA ----------------------------------------------------------------------------------------- */ + // Look for rejected calls! + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + // Make snapshot of neccessary member and define default return value. + css::uno::Reference< css::task::XStatusIndicator > xExternal(m_xIndicatorInterception.get(), css::uno::UNO_QUERY); + css::uno::Reference< css::task::XStatusIndicatorFactory > xFactory = m_xIndicatorFactoryHelper; + + aReadLock.unlock(); + /* UNSAFE AREA ----------------------------------------------------------------------------------------- */ + + // Was set from outside to intercept any progress activities! + if (xExternal.is()) + return xExternal; + + // Or use our own factory as fallback, to create such progress. + if (xFactory.is()) + return xFactory->createStatusIndicator(); + + return css::uno::Reference< css::task::XStatusIndicator >(); +} + +/*-****************************************************************************************************//** + @short search for target to load URL + @descr This method searches for a dispatch for the specified DispatchDescriptor. + The FrameSearchFlags and the FrameName of the DispatchDescriptor are + treated as described for findFrame. + + @seealso method findFrame() + @seealso method queryDispatches() + @seealso method set/getName() + @seealso class TargetFinder + + @param "aURL" , URL for loading + @param "sTargetFrameName" , name of target frame + @param "nSearchFlags" , additional flags to regulate search if sTargetFrameName isn't clear + @return css::uno::Reference to dispatch handler. + + @onerror A null reference is returned. +*//*-*****************************************************************************************************/ +css::uno::Reference< css::frame::XDispatch > SAL_CALL Frame::queryDispatch( const css::util::URL& aURL , + const ::rtl::OUString& sTargetFrameName, + sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException ) +{ + const char UNO_PROTOCOL[] = ".uno:"; + + // Don't check incoming parameter here! Our helper do it for us and it isn't a good idea to do it more then ones! + // But look for rejected 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 boost::unordered_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 ); + } +} + +/*-****************************************************************************************************//** + @short handle more then ones dispatches at same call + @descr Returns a sequence of dispatches. For details see the queryDispatch method. + For failed dispatches we return empty items in list! + + @seealso method queryDispatch() + + @param "lDescriptor" list of dispatch arguments for queryDispatch()! + @return List of dispatch references. Some elements can be NULL! + + @onerror An empty list is returned. +*//*-*****************************************************************************************************/ +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL Frame::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException ) +{ + // Don't check incoming parameter here! Our helper do it for us and it isn't a good idea to do it more then ones! + // But look for rejected calls! + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + // We use a helper to support these interface and an interceptor mechanism. + // Our helper is threadsafe by himself! + return m_xDispatchHelper->queryDispatches( lDescriptor ); +} + +/*-****************************************************************************************************//** + @short register/unregister interceptor for dispatch calls + @descr If you whish to handle some dispatches by himself ... you should be + an interceptor for it. Please see class OInterceptionHelper for further informations. + + @seealso class OInterceptionHelper + + @param "xInterceptor", reference to your interceptor implementation. + @return - + + @onerror Interceptor is ignored. +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor ) throw( css::uno::RuntimeException ) +{ + // We use a helper to support these interface and an interceptor mechanism. + // This helper is threadsafe himself and check incoming parameter too. + // I think we don't need any lock here! + // But we must look for rejected calls. + 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 Frame::releaseDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor ) throw( css::uno::RuntimeException ) +{ + // We use a helper to support these interface and an interceptor mechanism. + // This helper is threadsafe himself and check incoming parameter too. + // I think we don't need any lock here! + // But we must look for rejected calls ... + // Sometimes we are called during our dispose() method ... => soft exceptions! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY ); + xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor ); +} + +/*-****************************************************************************************************//** + @short provides information about all possible dispatch functions + inside the currnt frame environment +*//*-*****************************************************************************************************/ +css::uno::Sequence< sal_Int16 > SAL_CALL Frame::getSupportedCommandGroups() + throw(css::uno::RuntimeException) +{ + return m_xDispatchInfoHelper->getSupportedCommandGroups(); +} + +//***************************************************************************************************************** +css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL Frame::getConfigurableDispatchInformation(sal_Int16 nCommandGroup) + throw(css::uno::RuntimeException) +{ + return m_xDispatchInfoHelper->getConfigurableDispatchInformation(nCommandGroup); +} + +/*-****************************************************************************************************//** + @short notifications for window events + @descr We are a listener on our container window to forward it to our component window. + + @seealso method setComponent() + @seealso member m_xContainerWindow + @seealso member m_xComponentWindow + + @param "aEvent" describe source of detected event + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::windowResized( const css::awt::WindowEvent& +#if OSL_DEBUG_LEVEL > 0 +aEvent +#endif +) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_windowResized( aEvent ), "Frame::windowResized()", "Invalid parameter detected." ) + // Look for rejected calls. + // Part of dispose-mechanism => soft exceptions + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + // Impl-method is threadsafe! + // If we have a current component window - we must resize it! + implts_resizeComponentWindow(); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::focusGained( const css::awt::FocusEvent& +#if OSL_DEBUG_LEVEL > 0 +aEvent +#endif +) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_focusGained( aEvent ), "Frame::focusGained()", "Invalid parameter detected." ) + // Look for rejected calls. + // Part of dispose() mechanism ... => soft exceptions! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + // Make snapshot of member! + css::uno::Reference< css::awt::XWindow > xComponentWindow = m_xComponentWindow; + aReadLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + if( xComponentWindow.is() == sal_True ) + { + xComponentWindow->setFocus(); + } +} + +/*-****************************************************************************************************//** + @short notifications for window events + @descr We are a listener on our container window to forward it to our component window ... + but a XTopWindowListener we are only if we are a top frame! + + @seealso method setComponent() + @seealso member m_xContainerWindow + @seealso member m_xComponentWindow + + @param "aEvent" describe source of detected event + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::windowActivated( const css::lang::EventObject& +#if OSL_DEBUG_LEVEL > 0 +aEvent +#endif +) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_windowActivated( aEvent ), "Frame::windowActivated()", "Invalid parameter detected." ) + // Look for rejected calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + // Make snapshot of member! + EActiveState eState = m_eActiveState; + aReadLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Activate the new active path from here to top. + if( eState == E_INACTIVE ) + { + setActiveFrame( css::uno::Reference< css::frame::XFrame >() ); + activate(); + } +} + +//***************************************************************************************************************** +void SAL_CALL Frame::windowDeactivated( const css::lang::EventObject& +#if OSL_DEBUG_LEVEL > 0 +aEvent +#endif +) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_windowDeactivated( aEvent ), "Frame::windowDeactivated()", "Invalid parameter detected." ) + // Look for rejected calls. + // Sometimes called during dispose() => soft exceptions + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + + css::uno::Reference< css::frame::XFrame > xParent ( m_xParent, css::uno::UNO_QUERY ); + css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow; + EActiveState eActiveState = m_eActiveState ; + + aReadLock.unlock(); + + if( eActiveState != E_INACTIVE ) + { + // Deactivation is always done implicitely by activation of another frame. + // Only if no activation is done, deactivations have to be processed if the activated window + // is a parent window of the last active Window! + SolarMutexClearableGuard aSolarGuard; + Window* pFocusWindow = Application::GetFocusWindow(); + if ( + ( xContainerWindow.is() == sal_True ) && + ( xParent.is() == sal_True ) && + ( (css::uno::Reference< css::frame::XDesktop >( xParent, css::uno::UNO_QUERY )).is() == sal_False ) + ) + { + css::uno::Reference< css::awt::XWindow > xParentWindow = xParent->getContainerWindow() ; + Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); + //#i70261#: dialogs opend from an OLE object will cause a deactivate on the frame of the OLE object + // on Solaris/Linux at that time pFocusWindow is still NULL because the focus handling is different; right after + // the deactivation the focus will be set into the dialog! + // currently I see no case where a sub frame could get a deactivate with pFocusWindow being NULL permanently + // so for now this case is omitted from handled deactivations + if( pFocusWindow && pParentWindow->IsChild( pFocusWindow ) ) + { + css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY ); + if( xSupplier.is() == sal_True ) + { + aSolarGuard.clear(); + xSupplier->setActiveFrame( css::uno::Reference< css::frame::XFrame >() ); + } + } + } + } +} + +//***************************************************************************************************************** +void SAL_CALL Frame::windowClosing( const css::lang::EventObject& ) throw( css::uno::RuntimeException ) +{ + /* #i62088# + Some interceptor objects intercept our "internaly asynchronoues implemented" dispatch call. + And they close this frame directly (means synchronous then). + Means: Frame::windowClosing()->Frame::close() + In such situation its not a good idea to hold this transaction count alive .-) + */ + { + // Look for rejected calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + // deactivate this frame ... + deactivate(); + } + + // ... and try to close it + // But do it asynchron inside the main thread. + // VCL has no fun to do such things outside his main thread :-( + // Note: The used dispatch make it asynchronous for us .-) + + /*ATTENTION! + Don't try to suspend the controller here! Because it's done inside used dispatch(). + Otherwhise the dialog "would you save your changes?" will be shown more then once ... + */ + + /* SAFE */ + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory; + aReadLock.unlock(); + /* SAFE */ + + css::util::URL aURL; + aURL.Complete = DECLARE_ASCII(".uno:CloseFrame"); + css::uno::Reference< css::util::XURLTransformer > xParser(xFactory->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW); + xParser->parseStrict(aURL); + + css::uno::Reference< css::frame::XDispatch > xCloser = queryDispatch(aURL, SPECIALTARGET_SELF, 0); + if (xCloser.is()) + xCloser->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue >()); + + // Attention: If this dispatch works synchronous ... and full fill its job ... + // this line of code will never be reached ... + // Or if it will be reached it will be for sure that all your member are gone .-) +} + +/*-****************************************************************************************************//** + @short react for a show event for the internal container window + @descr Normaly we doesn't need this information realy. But we can use it to + implement the special feature "trigger first visible task". + + Algorithm: - first we have to check if we are a top (task) frame + It's not enough to be a top frame! Because we MUST have the desktop as parent. + But frames without a parent are top too. So it's not possible to check isTop() here! + We have to look for the type of our parent. + - if we are a task frame, then we have to check if we are the first one. + We use a static variable to do so. They will be reset to afterwards be shure + that further calls of this method doesn't do anything then. + - Then we have to trigger the right event string on the global job executor. + + @seealso css::task::JobExecutor + + @param aEvent + describes the source of this event + We are not interested on this information. We are interested on the visible state only. + + @threadsafe yes + @modified 31.07.2002 07:56, as96863 +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::windowShown( const css::lang::EventObject& ) throw(css::uno::RuntimeException) +{ + static sal_Bool bFirstVisibleTask = sal_True; + + /* SAFE { */ + ReadGuard aReadLock(m_aLock); + css::uno::Reference< css::frame::XDesktop > xDesktopCheck( m_xParent, css::uno::UNO_QUERY ); + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory; + m_bIsHidden = sal_False; + aReadLock.unlock(); + /* } SAFE */ + + impl_checkMenuCloser(); + + if (xDesktopCheck.is()) + { + /* STATIC SAFE { */ + WriteGuard aStaticWriteLock( LockHelper::getGlobalLock() ); + sal_Bool bMustBeTriggered = bFirstVisibleTask; + bFirstVisibleTask = sal_False; + aStaticWriteLock.unlock(); + /* } STATIC SAFE */ + + if (bMustBeTriggered) + { + css::uno::Reference< css::task::XJobExecutor > xExecutor( xFactory->createInstance( SERVICENAME_JOBEXECUTOR ), css::uno::UNO_QUERY ); + if (xExecutor.is()) + { + xExecutor->trigger( DECLARE_ASCII("onFirstVisibleTask") ); + } + } + } +} + +void SAL_CALL Frame::windowHidden( const css::lang::EventObject& ) throw(css::uno::RuntimeException) +{ + /* SAFE { */ + ReadGuard aReadLock(m_aLock); + m_bIsHidden = sal_True; + aReadLock.unlock(); + /* } SAFE */ + + impl_checkMenuCloser(); +} + +/*-****************************************************************************************************//** + @short called by dispose of our windows! + @descr This object is forced to release all references to the interfaces given + by the parameter source. We are a listener at our container window and + should listen for his diposing. + + @seealso XWindowListener + @seealso XTopWindowListener + @seealso XFocusListener + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void SAL_CALL Frame::disposing( const css::lang::EventObject& aEvent ) throw( css::uno::RuntimeException ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Check incoming parameter. + LOG_ASSERT2( implcp_disposing( aEvent ), "Frame::disposing()", "Invalid parameter detected." ) + // Look for rejected calls. + // May be we are called during releasing our windows in our in dispose call!? => soft exceptions + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + + if( aEvent.Source == m_xContainerWindow ) + { + // NECCESSARY: Impl-method is threadsafe by himself! + aWriteLock.unlock(); + implts_stopWindowListening(); + aWriteLock.lock(); + m_xContainerWindow = css::uno::Reference< css::awt::XWindow >(); + } +} + +/*-************************************************************************************************************//** + @interface com.sun.star.document.XActionLockable + @short implement locking of frame/task from outside + @descr Sometimes we have problems to decide if closing of task is allowed. Because; frame/task + could be used for pending loading jobs. So you can lock this object from outside and + prevent instance against closing during using! But - don't do it in a wrong or expensive manner. + Otherwise task couldn't die anymore!!! + + @seealso interface XActionLockable + @seeelso method BaseDispatcher::implts_loadIt() + @seeelso method Desktop::loadComponentFromURL() + + @param - + @return true if frame/task is locked + false otherwise + + @onerror - + @threadsafe yes +*//*-*************************************************************************************************************/ +sal_Bool SAL_CALL Frame::isActionLocked() throw( css::uno::RuntimeException ) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + ReadGuard aReadLock( m_aLock ); + return( m_nExternalLockCount!=0); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::addActionLock() throw( css::uno::RuntimeException ) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + ++m_nExternalLockCount; +} + +//***************************************************************************************************************** +void SAL_CALL Frame::removeActionLock() throw( css::uno::RuntimeException ) +{ + // Register no transaction here! Otherwhise we wait for ever inside possible + // implts_checkSuicide()/dispose() request ... + + /* SAFE AREA */{ + WriteGuard aWriteLock( m_aLock ); + LOG_ASSERT2( m_nExternalLockCount<=0, "Frame::removeActionLock()", "Frame isn't locked! Possible multithreading problem detected." ) + --m_nExternalLockCount; + }/* SAFE */ + + implts_checkSuicide(); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::setActionLocks( sal_Int16 nLock ) throw( css::uno::RuntimeException ) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + WriteGuard aWriteLock( m_aLock ); + // Attention: If somewhere called resetActionLocks() before and get e.g. 5 locks ... + // and tried to set these 5 ones here after his operations ... + // we can't ignore setted requests during these two calls! + // So we must add(!) these 5 locks here. + m_nExternalLockCount = m_nExternalLockCount + nLock; +} + +//***************************************************************************************************************** +sal_Int16 SAL_CALL Frame::resetActionLocks() throw( css::uno::RuntimeException ) +{ + // Register no transaction here! Otherwhise we wait for ever inside possible + // implts_checkSuicide()/dispose() request ... + + sal_Int16 nCurrentLocks = 0; + /* SAFE */{ + WriteGuard aWriteLock( m_aLock ); + nCurrentLocks = m_nExternalLockCount; + m_nExternalLockCount = 0; + }/* SAFE */ + + // Attention: + // external lock count is 0 here every time ... but if + // member m_bSelfClose is set to true too .... we call our own close()/dispose(). + // See close() for further informations + implts_checkSuicide(); + + return nCurrentLocks; +} + +//***************************************************************************************************************** +void Frame::impl_initializePropInfo() +{ + impl_setPropertyChangeBroadcaster(static_cast< css::frame::XFrame* >(this)); + + impl_addPropertyInfo( + css::beans::Property( + FRAME_PROPNAME_DISPATCHRECORDERSUPPLIER, + FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER, + ::getCppuType((const css::uno::Reference< css::frame::XDispatchRecorderSupplier >*)NULL), + css::beans::PropertyAttribute::TRANSIENT)); + + impl_addPropertyInfo( + css::beans::Property( + FRAME_PROPNAME_INDICATORINTERCEPTION, + FRAME_PROPHANDLE_INDICATORINTERCEPTION, + ::getCppuType((const css::uno::Reference< css::task::XStatusIndicator >*)NULL), + css::beans::PropertyAttribute::TRANSIENT)); + + impl_addPropertyInfo( + css::beans::Property( + FRAME_PROPNAME_ISHIDDEN, + FRAME_PROPHANDLE_ISHIDDEN, + ::getBooleanCppuType(), + css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY)); + + impl_addPropertyInfo( + css::beans::Property( + FRAME_PROPNAME_LAYOUTMANAGER, + FRAME_PROPHANDLE_LAYOUTMANAGER, + ::getCppuType((const css::uno::Reference< ::com::sun::star::frame::XLayoutManager >*)NULL), + css::beans::PropertyAttribute::TRANSIENT)); + + impl_addPropertyInfo( + css::beans::Property( + FRAME_PROPNAME_TITLE, + FRAME_PROPHANDLE_TITLE, + ::getCppuType((const ::rtl::OUString*)NULL), + css::beans::PropertyAttribute::TRANSIENT)); +} + +//***************************************************************************************************************** +void SAL_CALL Frame::impl_setPropertyValue(const ::rtl::OUString& /*sProperty*/, + sal_Int32 nHandle , + const css::uno::Any& aValue ) + +{ + static ::rtl::OUString MATERIALPROP_TITLE(RTL_CONSTASCII_USTRINGPARAM("title")); + + /* There is no need to lock any mutex here. Because we share the + solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-) + see ctor of PropertySetHelper for further informations. + */ + + /* Attention: You can use nHandle only, if you are sure that all supported + properties has an unique handle. That must be guaranteed + inside method impl_initializePropInfo()! + */ + switch (nHandle) + { + case FRAME_PROPHANDLE_TITLE : + { + ::rtl::OUString sExternalTitle; + aValue >>= sExternalTitle; + setTitle (sExternalTitle); + } + break; + + case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER : + aValue >>= m_xDispatchRecorderSupplier; + break; + + case FRAME_PROPHANDLE_LAYOUTMANAGER : + { + css::uno::Reference< css::frame::XLayoutManager > xOldLayoutManager = m_xLayoutManager; + css::uno::Reference< css::frame::XLayoutManager > xNewLayoutManager; + aValue >>= xNewLayoutManager; + + if (xOldLayoutManager != xNewLayoutManager) + { + m_xLayoutManager = xNewLayoutManager; + if (xOldLayoutManager.is()) + lcl_disableLayoutManager(xOldLayoutManager, this); + if (xNewLayoutManager.is()) + lcl_enableLayoutManager(xNewLayoutManager, this); + } + } + break; + + case FRAME_PROPHANDLE_INDICATORINTERCEPTION : + { + css::uno::Reference< css::task::XStatusIndicator > xProgress; + aValue >>= xProgress; + m_xIndicatorInterception = xProgress; + } + break; + + #ifdef ENABLE_WARNINGS + default : + LOG_WARNING( "Frame::setFastPropertyValue_NoBroadcast()", "Invalid handle detected!" ) + break; + #endif + } +} + +//***************************************************************************************************************** +css::uno::Any SAL_CALL Frame::impl_getPropertyValue(const ::rtl::OUString& /*sProperty*/, + sal_Int32 nHandle ) +{ + /* There is no need to lock any mutex here. Because we share the + solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-) + see ctor of PropertySetHelper for further informations. + */ + + /* Attention: You can use nHandle only, if you are sure that all supported + properties has an unique handle. That must be guaranteed + inside method impl_initializePropInfo()! + */ + css::uno::Any aValue; + switch (nHandle) + { + case FRAME_PROPHANDLE_TITLE : + aValue <<= getTitle (); + break; + + case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER : + aValue <<= m_xDispatchRecorderSupplier; + break; + + case FRAME_PROPHANDLE_ISHIDDEN : + aValue <<= m_bIsHidden; + break; + + case FRAME_PROPHANDLE_LAYOUTMANAGER : + aValue <<= m_xLayoutManager; + break; + + case FRAME_PROPHANDLE_INDICATORINTERCEPTION : + { + css::uno::Reference< css::task::XStatusIndicator > xProgress(m_xIndicatorInterception.get(), css::uno::UNO_QUERY); + aValue = css::uno::makeAny(xProgress); + } + break; + + #ifdef ENABLE_WARNINGS + default : + LOG_WARNING( "Frame::getFastPropertyValue()", "Invalid handle detected!" ) + break; + #endif + } + + return aValue; +} + +/*-****************************************************************************************************//** + @short dispose old container window and forget his reference + @descr Sometimes we must repair our "modal dialog parent mechanism" too! + + @seealso - + + @param "xWindow", reference to old container window to dispose it + @return An empty reference. + + @onerror - + @threadsafe NO! +*//*-*****************************************************************************************************/ +void Frame::impl_disposeContainerWindow( css::uno::Reference< css::awt::XWindow >& xWindow ) +{ + if( xWindow.is() == sal_True ) + { + xWindow->setVisible( sal_False ); + // All VclComponents are XComponents; so call dispose before discarding + // a css::uno::Reference< XVclComponent >, because this frame is the owner of the window + xWindow->dispose(); + xWindow = css::uno::Reference< css::awt::XWindow >(); + } +} + +/*-****************************************************************************************************//** + @short send frame action event to our listener + @descr This method is threadsafe AND can be called by our dispose method too! + + @seealso - + + @param "aAction", describe the event for sending + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void Frame::implts_sendFrameActionEvent( const css::frame::FrameAction& aAction ) +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Sometimes used by dispose() => soft exceptions! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + // Log informations about order of events to file! + // (only activated in debug version!) + LOG_FRAMEACTIONEVENT( "Frame", m_sName, aAction ) + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + // Send css::frame::FrameAction event to all listener. + // Get container for right listener. + // FOLLOW LINES ARE THREADSAFE!!! + // ( OInterfaceContainerHelper is synchronized with m_aListenerContainer! ) + ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XFrameActionListener >*) NULL ) ); + + if( pContainer != NULL ) + { + // Build action event. + css::frame::FrameActionEvent aFrameActionEvent( static_cast< ::cppu::OWeakObject* >(this), this, aAction ); + + // Get iterator for access to listener. + ::cppu::OInterfaceIteratorHelper aIterator( *pContainer ); + // Send message to all listener. + while( aIterator.hasMoreElements() == sal_True ) + { + try + { + ((css::frame::XFrameActionListener*)aIterator.next())->frameAction( aFrameActionEvent ); + } + catch( css::uno::RuntimeException& ) + { + aIterator.remove(); + } + } + } +} + +/*-****************************************************************************************************//** + @short helper to resize our component window + @descr A frame contains 2 windows - a container ~ and a component window. + This method resize inner component window to full size of outer container window. + This method is threadsafe AND can be called by our dispose method too! + + @seealso - + + @param - + @return - + + @onerror - +*//*-*****************************************************************************************************/ +void Frame::implts_resizeComponentWindow() +{ + // usually the LayoutManager does the resizing + // in case there is no LayoutManager resizing has to be done here + if ( !m_xLayoutManager.is() ) + { + css::uno::Reference< css::awt::XWindow > xComponentWindow( getComponentWindow() ); + if( xComponentWindow.is() == sal_True ) + { + css::uno::Reference< css::awt::XDevice > xDevice( getContainerWindow(), css::uno::UNO_QUERY ); + + // Convert relativ size to output size. + css::awt::Rectangle aRectangle = getContainerWindow()->getPosSize(); + css::awt::DeviceInfo aInfo = xDevice->getInfo(); + css::awt::Size aSize ( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset , + aRectangle.Height - aInfo.TopInset - aInfo.BottomInset ); + + // Resize our component window. + xComponentWindow->setPosSize( 0, 0, aSize.Width, aSize.Height, css::awt::PosSize::POSSIZE ); + } + } +} + +/*-****************************************************************************************************//** + @short helper to set icon on our container window (if it is a system window!) + @descr We use our internal set controller (if it exist) to specify which factory he represanted. + These information can be used to find right icon. But our controller can say it us directly + too ... we should ask his optional property set first ... + + @seealso method Window::SetIcon() + + @param - + @return - + + @onerror We do nothing. +*//*-*****************************************************************************************************/ +void Frame::implts_setIconOnWindow() +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Look for rejected calls. + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + // Make snapshot of neccessary members and release lock. + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::awt::XWindow > xContainerWindow( m_xContainerWindow, css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XController > xController ( m_xController , css::uno::UNO_QUERY ); + aReadLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + if( + ( xContainerWindow.is() == sal_True ) && + ( xController.is() == sal_True ) + ) + { + //------------------------------------------------------------------------------------------------------------- + // a) set default value to an invalid one. So we can start further searches for right icon id, if + // first steps failed! + // We must reset it to any fallback value - if no search step returns a valid result. + sal_Int32 nIcon = -1; + + //------------------------------------------------------------------------------------------------------------- + // b) try to find information on controller propertyset directly + // Don't forget to catch possible exceptions - because these property is an optional one! + css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY ); + if( xSet.is() == sal_True ) + { + try + { + xSet->getPropertyValue( DECLARE_ASCII("IconId") )>>= nIcon; + } + catch( css::beans::UnknownPropertyException& ) + { + } + } + + //------------------------------------------------------------------------------------------------------------- + // c) if b) failed ... analyze argument list of currently loaded document insde the frame to find the filter. + // He can be used to detect right factory - and these can be used to match factory to icon ... + if( nIcon == -1 ) + { + css::uno::Reference< css::frame::XModel > xModel = xController->getModel(); + if( xModel.is() == sal_True ) + { + SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByModel(xModel); + if (eFactory != SvtModuleOptions::E_UNKNOWN_FACTORY) + nIcon = SvtModuleOptions().GetFactoryIcon( eFactory ); + } + } + + //------------------------------------------------------------------------------------------------------------- + // d) if all steps failed - use fallback! + if( nIcon == -1 ) + { + nIcon = 0; + } + + //------------------------------------------------------------------------------------------------------------- + // e) set icon on container window now + // Don't forget SolarMutex! We use vcl directly :-( + // Check window pointer for right WorkWindow class too!!! + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + { + SolarMutexGuard aSolarGuard; + Window* pWindow = (VCLUnoHelper::GetWindow( xContainerWindow )); + if( + ( pWindow != NULL ) && + ( pWindow->GetType() == WINDOW_WORKWINDOW ) + ) + { + WorkWindow* pWorkWindow = (WorkWindow*)pWindow; + pWorkWindow->SetIcon( (sal_uInt16)nIcon ); + } + } + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + } +} + +/*-************************************************************************************************************//** + @short helper to start/stop listeneing for window events on container window + @descr If we get a new container window, we must set it on internal memeber ... + and stop listening at old one ... and start listening on new one! + But sometimes (in dispose() call!) it's neccessary to stop listeneing without starting + on new connections. So we split this functionality to make it easier at use. + + @seealso method initialize() + @seealso method dispose() + + @param - + @return - + + @onerror We do nothing! + @threadsafe yes +*//*-*************************************************************************************************************/ +void Frame::implts_startWindowListening() +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + // Make snapshot of neccessary member! + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow ; + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory ; + css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener; + css::uno::Reference< css::awt::XWindowListener > xWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + css::uno::Reference< css::awt::XFocusListener > xFocusListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + aReadLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + if( xContainerWindow.is() == sal_True ) + { + xContainerWindow->addWindowListener( xWindowListener); + xContainerWindow->addFocusListener ( xFocusListener ); + + css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY ); + if( xTopWindow.is() == sal_True ) + { + xTopWindow->addTopWindowListener( xTopWindowListener ); + + css::uno::Reference< css::awt::XDataTransferProviderAccess > xTransfer( xFactory->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY ); + if( xTransfer.is() == sal_True ) + { + css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xTransfer->getDropTarget( xContainerWindow ); + if( xDropTarget.is() == sal_True ) + { + xDropTarget->addDropTargetListener( xDragDropListener ); + xDropTarget->setActive( sal_True ); + } + } + } + } +} + +//***************************************************************************************************************** +void Frame::implts_stopWindowListening() +{ + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + // Sometimes used by dispose() => soft exceptions! + TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + // Make snapshot of neccessary member! + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow ; + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory ; + css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener; + css::uno::Reference< css::awt::XWindowListener > xWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + css::uno::Reference< css::awt::XFocusListener > xFocusListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); + aReadLock.unlock(); + /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ + + if( xContainerWindow.is() == sal_True ) + { + xContainerWindow->removeWindowListener( xWindowListener); + xContainerWindow->removeFocusListener ( xFocusListener ); + + css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY ); + if( xTopWindow.is() == sal_True ) + { + xTopWindow->removeTopWindowListener( xTopWindowListener ); + + css::uno::Reference< css::awt::XDataTransferProviderAccess > xTransfer( xFactory->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY ); + if( xTransfer.is() == sal_True ) + { + css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xTransfer->getDropTarget( xContainerWindow ); + if( xDropTarget.is() == sal_True ) + { + xDropTarget->removeDropTargetListener( xDragDropListener ); + xDropTarget->setActive( sal_False ); + } + } + } + } +} + +/*-****************************************************************************************************//** + @short helper to force breaked close() request again + @descr If we self disagree with a close() request, and detect that all external locks are gone ... + then we must try to close this frame again. + + @seealso XCloseable::close() + @seealso Frame::close() + @seealso Frame::removeActionLock() + @seealso Frame::resetActionLock() + @seealso m_bSelfClose + @seealso m_nExternalLockCount + + @threadsafe yes + @modified 06.05.2002 09:31, as96863 +*//*-*****************************************************************************************************/ +void Frame::implts_checkSuicide() +{ + /* SAFE */ + ReadGuard aReadLock(m_aLock); + // in case of lock==0 and safed state of previous close() request m_bSelfClose + // we must force close() again. Because we had disagreed with that before. + sal_Bool bSuicide = (m_nExternalLockCount==0 && m_bSelfClose); + m_bSelfClose = sal_False; + aReadLock.unlock(); + /* } SAFE */ + // force close and deliver owner ship to source of possible throwed veto exception + // Attention: Because this method isn't designed to throw such exception we must supress + // it for outside code! + try + { + if (bSuicide) + close(sal_True); + } + catch(const css::util::CloseVetoException&) + {} + catch(const css::lang::DisposedException&) + {} +} + +//_______________________________________________________________ + +/** little helper to enable/disable the menu closer at the menubar of the given frame. + + @param xFrame + we use its layout manager to set/reset a special callback. + Its existence regulate visibility of this closer item. + + @param bState + <TRUE/> enable; <FALSE/> disable this state + */ + +void Frame::impl_setCloser( /*IN*/ const css::uno::Reference< css::frame::XFrame >& xFrame , + /*IN*/ sal_Bool bState ) +{ + // Note: If start module isnt installed - no closer has to be shown! + if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) + return; + + try + { + css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + xFrameProps->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager; + css::uno::Reference< css::beans::XPropertySet > xLayoutProps(xLayoutManager, css::uno::UNO_QUERY_THROW); + xLayoutProps->setPropertyValue(LAYOUTMANAGER_PROPNAME_MENUBARCLOSER, css::uno::makeAny(bState)); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + {} +} + +//_______________________________________________________________ + +/** it checks, which of the top level task frames must have the special menu closer for + switching to the backing window mode. + + It analyze the current list of visible top level frames. Only the last real document + frame can have this symbol. Not the help frame nor the backing task itself. + Here we do anything related to this closer. We remove it from the old frame and set it + for the new one. + */ + +void Frame::impl_checkMenuCloser() +{ + /* SAFE { */ + ReadGuard aReadLock(m_aLock); + + // only top frames, which are part of our desktop hierarchy, can + // do so! By the way - we need the desktop instance to have acess + // to all other top level frames too. + css::uno::Reference< css::frame::XDesktop > xDesktop (m_xParent, css::uno::UNO_QUERY); + css::uno::Reference< css::frame::XFramesSupplier > xTaskSupplier(xDesktop , css::uno::UNO_QUERY); + if ( !xDesktop.is() || !xTaskSupplier.is() ) + return; + + aReadLock.unlock(); + /* } SAFE */ + + // analyze the list of current open tasks + // Suppress search for other views to the same model ... + // It's not needed here and can be very expensive. + FrameListAnalyzer aAnalyzer( + xTaskSupplier, + this, + FrameListAnalyzer::E_HIDDEN | FrameListAnalyzer::E_HELP | FrameListAnalyzer::E_BACKINGCOMPONENT); + + // specify the new frame, which must have this special state ... + css::uno::Reference< css::frame::XFrame > xNewCloserFrame; + + // ----------------------------- + // a) + // If there exist ate least one other frame - there are two frames currently open. + // But we can enable this closer only, if one of these two tasks includes the help module. + // The "other frame" couldn't be the help. Because then it wouldn't be part of this "other list". + // In such case it will be seperated to the reference aAnalyzer.m_xHelp! + // But we must check, if weself includes the help ... + // Check aAnalyzer.m_bReferenceIsHelp! + if ( + (aAnalyzer.m_lOtherVisibleFrames.getLength()==1) && + ( + (aAnalyzer.m_bReferenceIsHelp ) || + (aAnalyzer.m_bReferenceIsHidden) + ) + ) + { + // others[0] can't be the backing component! + // Because it's set at the special member aAnalyzer.m_xBackingComponent ... :-) + xNewCloserFrame = aAnalyzer.m_lOtherVisibleFrames[0]; + } + else + // ----------------------------- + // b) + // There is no other frame ... means no other document frame. The help module + // will be handled seperatly and must(!) be ignored here ... excepting weself includes the help. + if ( + (aAnalyzer.m_lOtherVisibleFrames.getLength()==0) && + (!aAnalyzer.m_bReferenceIsHelp ) && + (!aAnalyzer.m_bReferenceIsHidden ) && + (!aAnalyzer.m_bReferenceIsBacking ) + ) + { + xNewCloserFrame = this; + } + + // Look for neccessary actions ... + // Only if the closer state must be moved from one frame to another one + // or must be enabled/disabled at all. + /* STATIC SAFE { */ + WriteGuard aStaticWriteLock(LockHelper::getGlobalLock()); + css::uno::Reference< css::frame::XFrame > xCloserFrame (m_xCloserFrame.get(), css::uno::UNO_QUERY); + if (xCloserFrame!=xNewCloserFrame) + { + if (xCloserFrame.is()) + impl_setCloser(xCloserFrame, sal_False); + if (xNewCloserFrame.is()) + impl_setCloser(xNewCloserFrame, sal_True); + m_xCloserFrame = xNewCloserFrame; + } + aStaticWriteLock.unlock(); + /* } STATIC SAFE */ +} + +//_________________________________________________________________________________________________________________ +// 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 don't accept null pointer or references! +sal_Bool Frame::implcp_ctor( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ) +{ + return ( + ( &xFactory == NULL ) || + ( xFactory.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +// Its allowed to reset the active frame membervariable with a NULL-css::uno::Reference but not with a NULL-pointer! +// And we accept frames only! No tasks and desktops! +sal_Bool Frame::implcp_setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + return ( + ( &xFrame == NULL ) || + ( css::uno::Reference< css::frame::XDesktop >( xFrame, css::uno::UNO_QUERY ).is() == sal_True ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) +{ + return ( + ( &xListener == NULL ) || + ( xListener.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) +{ + return ( + ( &xListener == NULL ) || + ( xListener.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) +{ + return ( + ( &xListener == NULL ) || + ( xListener.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) +{ + return ( + ( &xListener == NULL ) || + ( xListener.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_windowResized( const css::awt::WindowEvent& aEvent ) +{ + return ( + ( &aEvent == NULL ) || + ( aEvent.Source.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_focusGained( const css::awt::FocusEvent& aEvent ) +{ + return ( + ( &aEvent == NULL ) || + ( aEvent.Source.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_windowActivated( const css::lang::EventObject& aEvent ) +{ + return ( + ( &aEvent == NULL ) || + ( aEvent.Source.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_windowDeactivated( const css::lang::EventObject& aEvent ) +{ + return ( + ( &aEvent == NULL ) || + ( aEvent.Source.is() == sal_False ) + ); +} + +//***************************************************************************************************************** +sal_Bool Frame::implcp_disposing( const css::lang::EventObject& aEvent ) +{ + return ( + ( &aEvent == NULL ) || + ( aEvent.Source.is() == sal_False ) + ); +} + +#endif // #ifdef ENABLE_ASSERTIONS + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |