/************************************************************************* * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "controllerframe.hxx" #include "IController.hxx" /** === begin UNO includes === **/ #include #include #include #include #include #include /** === end UNO includes === **/ #include #include #include #include #include #include //........................................................................ namespace dbaui { //........................................................................ /** === begin UNO using === **/ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::XInterface; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::makeAny; using ::com::sun::star::frame::XFrame; using ::com::sun::star::frame::FrameAction; using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED; using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED; using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING; using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING; using ::com::sun::star::frame::XModel; using ::com::sun::star::frame::XController; using ::com::sun::star::frame::XController2; using ::com::sun::star::frame::XFramesSupplier; using ::com::sun::star::sdb::XOfficeDatabaseDocument; using ::com::sun::star::awt::XTopWindow; using ::com::sun::star::awt::XTopWindowListener; using ::com::sun::star::awt::XWindow2; using ::com::sun::star::lang::DisposedException; using ::com::sun::star::lang::EventObject; using ::com::sun::star::document::XDocumentEventBroadcaster; using ::com::sun::star::awt::XWindow; /** === end UNO using === **/ //==================================================================== //= FrameWindowActivationListener //==================================================================== typedef ::cppu::WeakImplHelper1 < XTopWindowListener > FrameWindowActivationListener_Base; class FrameWindowActivationListener : public FrameWindowActivationListener_Base { public: FrameWindowActivationListener( ControllerFrame_Data& _rData ); void dispose(); protected: ~FrameWindowActivationListener(); // XTopWindowListener virtual void SAL_CALL windowOpened( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL windowClosing( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL windowClosed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL windowMinimized( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL windowNormalized( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL windowActivated( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL windowDeactivated( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); // XEventListener virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); private: void impl_checkDisposed_throw() const; void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister ); private: ControllerFrame_Data* m_pData; }; //==================================================================== //= ControllerFrame_Data //==================================================================== struct ControllerFrame_Data { ControllerFrame_Data( IController& _rController ) :m_rController( _rController ) ,m_xFrame() ,m_xDocEventBroadcaster() ,m_pListener() ,m_bActive( false ) ,m_bIsTopLevelDocumentWindow( false ) { } IController& m_rController; Reference< XFrame > m_xFrame; Reference< XDocumentEventBroadcaster > m_xDocEventBroadcaster; ::rtl::Reference< FrameWindowActivationListener > m_pListener; bool m_bActive; bool m_bIsTopLevelDocumentWindow; }; //==================================================================== //= helper //==================================================================== //-------------------------------------------------------------------- static void lcl_setFrame_nothrow( ControllerFrame_Data& _rData, const Reference< XFrame >& _rxFrame ) { // release old listener if ( _rData.m_pListener.get() ) { _rData.m_pListener->dispose(); _rData.m_pListener = NULL; } // remember new frame _rData.m_xFrame = _rxFrame; // create new listener if ( _rData.m_xFrame.is() ) _rData.m_pListener = new FrameWindowActivationListener( _rData ); // at this point in time, we can assume the controller also has a model set, if it supports models try { Reference< XController > xController( _rData.m_rController.getXController(), UNO_SET_THROW ); Reference< XModel > xModel( xController->getModel() ); if ( xModel.is() ) _rData.m_xDocEventBroadcaster.set( xModel, UNO_QUERY ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } } //-------------------------------------------------------------------- static bool lcl_isActive_nothrow( const Reference< XFrame >& _rxFrame ) { bool bIsActive = false; try { if ( _rxFrame.is() ) { Reference< XWindow2 > xWindow( _rxFrame->getContainerWindow(), UNO_QUERY_THROW ); bIsActive = xWindow->isActive(); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } return bIsActive; } //-------------------------------------------------------------------- /** updates various global and local states with a new active component In particular, the following are updated * the global working document (aka Basic's ThisComponent in the application Basic), with our controller's model, or the controller itself if there is no such model. */ static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data& _rData ) { try { Reference< XController > xCompController( _rData.m_rController.getXController() ); OSL_ENSURE( xCompController.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" ); if ( !xCompController.is() ) return; if ( _rData.m_bActive && _rData.m_bIsTopLevelDocumentWindow ) { // set the "current component" at the SfxObjectShell Reference< XModel > xModel( xCompController->getModel() ); Reference< XInterface > xCurrentComponent; if ( xModel.is() ) xCurrentComponent = xModel; else xCurrentComponent = xCompController; SfxObjectShell::SetCurrentComponent( xCurrentComponent ); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } } //-------------------------------------------------------------------- /** broadcasts the OnFocus resp. OnUnfocus event */ static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data& _rData, bool _bActive ) { try { if ( _rData.m_xDocEventBroadcaster.is() ) { ::rtl::OUString sEventName( ::rtl::OUString::createFromAscii( _bActive ? "OnFocus" : "OnUnfocus" ) ); Reference< XController2 > xController( _rData.m_rController.getXController(), UNO_QUERY_THROW ); _rData.m_xDocEventBroadcaster->notifyDocumentEvent( sEventName, xController, Any() ); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } } //-------------------------------------------------------------------- static void lcl_updateActive_nothrow( ControllerFrame_Data& _rData, bool _bActive ) { if ( _rData.m_bActive == _bActive ) return; _rData.m_bActive = _bActive; lcl_updateActiveComponents_nothrow( _rData ); lcl_notifyFocusChange_nothrow( _rData, _bActive ); } //-------------------------------------------------------------------- FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data& _rData ) :m_pData( &_rData ) { impl_registerOnFrameContainerWindow_nothrow( true ); } //-------------------------------------------------------------------- FrameWindowActivationListener::~FrameWindowActivationListener() { } //-------------------------------------------------------------------- void FrameWindowActivationListener::dispose() { impl_registerOnFrameContainerWindow_nothrow( false ); m_pData = NULL; } //-------------------------------------------------------------------- void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister ) { OSL_ENSURE( m_pData && m_pData->m_xFrame.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" ); if ( !m_pData || !m_pData->m_xFrame.is() ) return; try { void ( SAL_CALL XTopWindow::*pListenerAction )( const Reference< XTopWindowListener >& ) = _bRegister ? &XTopWindow::addTopWindowListener : &XTopWindow::removeTopWindowListener; const Reference< XWindow > xContainerWindow( m_pData->m_xFrame->getContainerWindow(), UNO_SET_THROW ); if ( _bRegister ) { const Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ); ENSURE_OR_THROW( pContainerWindow, "no Window implementation for the frame's container window!" ); /*const Window* pContainerParentWindow = pContainerWindow->GetParent(); if ( pContainerParentWindow && ( pContainerParentWindow->GetType() == WINDOW_BORDERWINDOW ) ) pContainerParentWindow = pContainerParentWindow->GetParent(); m_pData->m_bIsTopLevelDocumentWindow = ( pContainerParentWindow == NULL );*/ m_pData->m_bIsTopLevelDocumentWindow = ( pContainerWindow->GetExtendedStyle() & WB_EXT_DOCUMENT ) != 0; } const Reference< XTopWindow > xFrameContainer( xContainerWindow, UNO_QUERY ); if ( xFrameContainer.is() ) (xFrameContainer.get()->*pListenerAction)( this ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } } //-------------------------------------------------------------------- void FrameWindowActivationListener::impl_checkDisposed_throw() const { if ( !m_pData ) throw DisposedException( ::rtl::OUString(), *const_cast< FrameWindowActivationListener* >( this ) ); } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowOpened( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowClosing( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowClosed( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowMinimized( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowNormalized( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowActivated( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { impl_checkDisposed_throw(); lcl_updateActive_nothrow( *m_pData, true ); } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::windowDeactivated( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { impl_checkDisposed_throw(); lcl_updateActive_nothrow( *m_pData, false ); } //-------------------------------------------------------------------- void SAL_CALL FrameWindowActivationListener::disposing( const EventObject& /*_rEvent*/ ) throw (RuntimeException) { dispose(); } //==================================================================== //= ControllerFrame //==================================================================== //-------------------------------------------------------------------- ControllerFrame::ControllerFrame( IController& _rController ) :m_pData( new ControllerFrame_Data( _rController ) ) { } //-------------------------------------------------------------------- ControllerFrame::~ControllerFrame() { } //-------------------------------------------------------------------- const Reference< XFrame >& ControllerFrame::attachFrame( const Reference< XFrame >& _rxFrame ) { // set new frame, including listener handling lcl_setFrame_nothrow( *m_pData, _rxFrame ); // determine whether we're active m_pData->m_bActive = lcl_isActive_nothrow( m_pData->m_xFrame ); // update active component if ( m_pData->m_bActive ) { lcl_updateActiveComponents_nothrow( *m_pData ); lcl_notifyFocusChange_nothrow( *m_pData, true ); } return m_pData->m_xFrame; } //-------------------------------------------------------------------- const Reference< XFrame >& ControllerFrame::getFrame() const { return m_pData->m_xFrame; } //-------------------------------------------------------------------- bool ControllerFrame::isActive() const { return m_pData->m_bActive; } //-------------------------------------------------------------------- void ControllerFrame::frameAction( FrameAction _eAction ) { bool bActive = m_pData->m_bActive; switch ( _eAction ) { case FrameAction_FRAME_ACTIVATED: case FrameAction_FRAME_UI_ACTIVATED: bActive = true; break; case FrameAction_FRAME_DEACTIVATING: case FrameAction_FRAME_UI_DEACTIVATING: bActive = false; break; default: break; } lcl_updateActive_nothrow( *m_pData, bActive ); } //........................................................................ } // namespace dbaui //........................................................................