/* -*- 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "commonpicker.hxx" #include #include #include #include #include #include #include #include #include "iodlg.hxx" //......................................................................... namespace svt { //......................................................................... #define PROPERTY_ID_HELPURL 1 #define PROPERTY_ID_WINDOW 2 // using -------------------------------------------------------------- using namespace ::com::sun::star::lang; using namespace ::com::sun::star::ui::dialogs; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::comphelper; //--------------------------------------------------------------------- OCommonPicker::OCommonPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ) :OCommonPicker_Base( m_aMutex ) ,OPropertyContainer( GetBroadcastHelper() ) ,m_xORB( _rxFactory ) ,m_pDlg( NULL ) ,m_nCancelEvent( 0 ) ,m_bExecuting( sal_False ) { // the two properties we have registerProperty( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )), PROPERTY_ID_HELPURL, PropertyAttribute::TRANSIENT, &m_sHelpURL, ::getCppuType( &m_sHelpURL ) ); registerProperty( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Window" )), PROPERTY_ID_WINDOW, PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY, &m_xWindow, ::getCppuType( &m_xWindow ) ); } //--------------------------------------------------------------------- OCommonPicker::~OCommonPicker() { if ( !GetBroadcastHelper().bDisposed ) { acquire(); dispose(); } } //--------------------------------------------------------------------- // disambiguate XInterface //--------------------------------------------------------------------- IMPLEMENT_FORWARD_XINTERFACE2( OCommonPicker, OCommonPicker_Base, OPropertyContainer ) //--------------------------------------------------------------------- // disambiguate XTypeProvider //--------------------------------------------------------------------- IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCommonPicker, OCommonPicker_Base, OPropertyContainer ) //--------------------------------------------------------------------- // XComponent related methods //--------------------------------------------------------------------- void OCommonPicker::checkAlive() const SAL_THROW( (DisposedException) ) { if ( GetBroadcastHelper().bInDispose || GetBroadcastHelper().bDisposed ) throw DisposedException(); } void OCommonPicker::prepareDialog() { if ( !getDialog() ) createPicker(); // set the title if ( !m_aTitle.isEmpty() ) getDialog()->SetText( m_aTitle ); } //--------------------------------------------------------------------- void SAL_CALL OCommonPicker::disposing() { SolarMutexGuard aGuard; stopWindowListening(); if ( m_nCancelEvent ) Application::RemoveUserEvent( m_nCancelEvent ); { ::osl::MutexGuard aOwnGuard( m_aMutex ); if ( m_bExecuting && m_pDlg ) m_pDlg->EndDialog( RET_CANCEL ); } delete m_pDlg; m_pDlg = NULL; m_xWindow = NULL; m_xDialogParent = NULL; } //--------------------------------------------------------------------- void OCommonPicker::stopWindowListening() { disposeComponent( m_xWindowListenerAdapter ); disposeComponent( m_xParentListenerAdapter ); } //--------------------------------------------------------------------- // XEventListener //--------------------------------------------------------------------- void SAL_CALL OCommonPicker::disposing( const EventObject& _rSource ) throw (RuntimeException) { SolarMutexGuard aGuard; sal_Bool bDialogDying = _rSource.Source == m_xWindow; sal_Bool bParentDying = _rSource.Source == m_xDialogParent; if ( bDialogDying || bParentDying ) { stopWindowListening(); if ( !bDialogDying ) // it's the parent which is dying -> delete the dialog delete m_pDlg; m_pDlg = NULL; m_xWindow = NULL; m_xDialogParent = NULL; } else { OSL_FAIL( "OCommonPicker::disposing: where did this come from?" ); } } //--------------------------------------------------------------------- // property set related methods //--------------------------------------------------------------------- ::cppu::IPropertyArrayHelper* OCommonPicker::createArrayHelper( ) const { Sequence< Property > aProps; describeProperties( aProps ); return new cppu::OPropertyArrayHelper( aProps ); } //--------------------------------------------------------------------- ::cppu::IPropertyArrayHelper& SAL_CALL OCommonPicker::getInfoHelper() { return *const_cast< OCommonPicker* >( this )->getArrayHelper(); } //--------------------------------------------------------------------- Reference< XPropertySetInfo > SAL_CALL OCommonPicker::getPropertySetInfo( ) throw(RuntimeException) { return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); } //--------------------------------------------------------------------- void SAL_CALL OCommonPicker::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) { OPropertyContainer::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); // if the HelpURL changed, forward this to the dialog if ( PROPERTY_ID_HELPURL == _nHandle ) if ( m_pDlg ) OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False ); } //--------------------------------------------------------------------- sal_Bool OCommonPicker::createPicker() { SolarMutexGuard aGuard; if ( !m_pDlg ) { m_pDlg = implCreateDialog( VCLUnoHelper::GetWindow( m_xDialogParent ) ); DBG_ASSERT( m_pDlg, "OCommonPicker::createPicker: invalid dialog returned!" ); if ( m_pDlg ) { // synchronize the help id of the dialog with out help URL property if ( !m_sHelpURL.isEmpty() ) { // somebody already set the help URL while we had no dialog yet OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False ); } else { m_sHelpURL = OControlAccess::getHelpURL( m_pDlg, sal_False ); } m_xWindow = VCLUnoHelper::GetInterface( m_pDlg ); // add as event listener to the window Reference< XComponent > xWindowComp( m_xWindow, UNO_QUERY ); OSL_ENSURE( xWindowComp.is(), "OCommonPicker::createFileDialog: invalid window component!" ); if ( xWindowComp.is() ) { m_xWindowListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp ); // the adapter will add itself as listener, and forward notifications } // _and_ add as event listener to the parent - in case the parent is destroyed // before we are disposed, our disposal would access dead VCL windows then .... m_xDialogParent = VCLUnoHelper::GetInterface( m_pDlg->GetParent() ); xWindowComp = xWindowComp.query( m_xDialogParent ); OSL_ENSURE( xWindowComp.is() || !m_pDlg->GetParent(), "OCommonPicker::createFileDialog: invalid window component (the parent this time)!" ); if ( xWindowComp.is() ) { m_xParentListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp ); // the adapter will add itself as listener, and forward notifications } } } return NULL != m_pDlg; } //--------------------------------------------------------------------- // XControlAccess functions //--------------------------------------------------------------------- void SAL_CALL OCommonPicker::setControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty, const Any& aValue ) throw (IllegalArgumentException, RuntimeException) { checkAlive(); SolarMutexGuard aGuard; if ( createPicker() ) { ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); aAccess.setControlProperty( aControlName, aControlProperty, aValue ); } } //--------------------------------------------------------------------- Any SAL_CALL OCommonPicker::getControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException) { checkAlive(); SolarMutexGuard aGuard; if ( createPicker() ) { ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); return aAccess.getControlProperty( aControlName, aControlProperty ); } return Any(); } //--------------------------------------------------------------------- // XControlInformation functions //--------------------------------------------------------------------- Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControls( ) throw (RuntimeException) { checkAlive(); SolarMutexGuard aGuard; if ( createPicker() ) { ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); return aAccess.getSupportedControls( ); } return Sequence< ::rtl::OUString >(); } //--------------------------------------------------------------------- sal_Bool SAL_CALL OCommonPicker::isControlSupported( const ::rtl::OUString& aControlName ) throw (RuntimeException) { checkAlive(); SolarMutexGuard aGuard; if ( createPicker() ) { ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); return aAccess.isControlSupported( aControlName ); } return sal_False; } //--------------------------------------------------------------------- Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControlProperties( const ::rtl::OUString& aControlName ) throw (IllegalArgumentException, RuntimeException) { checkAlive(); SolarMutexGuard aGuard; if ( createPicker() ) { ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); return aAccess.getSupportedControlProperties( aControlName ); } return Sequence< ::rtl::OUString >(); } //--------------------------------------------------------------------- sal_Bool SAL_CALL OCommonPicker::isControlPropertySupported( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException) { checkAlive(); SolarMutexGuard aGuard; if ( createPicker() ) { ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() ); return aAccess.isControlPropertySupported( aControlName, aControlProperty ); } return sal_False; } //--------------------------------------------------------------------- // XExecutableDialog functions //--------------------------------------------------------------------- void SAL_CALL OCommonPicker::setTitle( const rtl::OUString& _rTitle ) throw( RuntimeException ) { SolarMutexGuard aGuard; m_aTitle = _rTitle; } //--------------------------------------------------------------------- sal_Int16 OCommonPicker::execute() throw (RuntimeException) { SolarMutexGuard aGuard; prepareDialog(); { ::osl::MutexGuard aOwnGuard( m_aMutex ); m_bExecuting = sal_True; } sal_Int16 nResult = implExecutePicker(); { ::osl::MutexGuard aOwnGuard( m_aMutex ); m_bExecuting = sal_False; } return nResult; } //--------------------------------------------------------------------- // XCancellable functions //--------------------------------------------------------------------- void SAL_CALL OCommonPicker::cancel( ) throw (RuntimeException) { { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_nCancelEvent ) // nothing to do - the event for cancelling the dialog is already on the way return; } // The thread which executes our dialog has locked the solar mutex for // sure. Cancelling the dialog should be done with a locked solar mutex, too. // Thus we post ourself a message for cancelling the dialog. This way, the message // is either handled in the thread which opened the dialog (which may even be // this thread here), or, if no dialog is open, in the thread doing scheduling // currently. Both is okay for us .... // // Note that we could do check if we are really executing the dialog currently. // but the information would be potentially obsolete at the moment our event // arrives, so we need to check it there, anyway ... m_nCancelEvent = Application::PostUserEvent( LINK( this, OCommonPicker, OnCancelPicker ) ); } //--------------------------------------------------------------------- IMPL_LINK_NOARG(OCommonPicker, OnCancelPicker) { // By definition, the solar mutex is locked when we arrive here. Note that this // is important, as for instance the consistency of m_pDlg depends on this mutex. ::osl::MutexGuard aGuard( m_aMutex ); m_nCancelEvent = 0; if ( !m_bExecuting ) // nothing to do. This may be because the dialog was cancelled after our cancel method // posted this async event, or because somebody called cancel without the dialog // being executed at this time. return 0; OSL_ENSURE( getDialog(), "OCommonPicker::OnCancelPicker: executing, but no dialog!" ); if ( getDialog() ) getDialog()->EndDialog( RET_CANCEL ); return 0L; } //------------------------------------------------------------------------------------ // XInitialization functions //------------------------------------------------------------------------------------ void SAL_CALL OCommonPicker::initialize( const Sequence< Any >& _rArguments ) throw ( Exception, RuntimeException ) { checkAlive(); ::rtl::OUString sSettingName; Any aSettingValue; PropertyValue aPropArg; NamedValue aPairArg; const Any* pArguments = _rArguments.getConstArray(); const Any* pArgumentsEnd = _rArguments.getConstArray() + _rArguments.getLength(); for ( const Any* pArgument = pArguments; pArgument != pArgumentsEnd; ++pArgument ) { if ( *pArgument >>= aPropArg ) { if ( aPropArg.Name.isEmpty()) continue; sSettingName = aPropArg.Name; aSettingValue = aPropArg.Value; } else if ( *pArgument >>= aPairArg ) { if ( aPairArg.Name.isEmpty()) continue; sSettingName = aPairArg.Name; aSettingValue = aPairArg.Value; } else { OSL_FAIL( ( ::rtl::OString( "OCommonPicker::initialize: unknown argument type at position " ) += ::rtl::OString::valueOf( (sal_Int32)( pArguments - _rArguments.getConstArray() ) ) ).getStr() ); continue; } #ifdef DBG_UTIL sal_Bool bKnownSetting = #endif implHandleInitializationArgument( sSettingName, aSettingValue ); DBG_ASSERT( bKnownSetting, ( ::rtl::OString( "OCommonPicker::initialize: unknown argument \"" ) += ::rtl::OString( sSettingName.getStr(), sSettingName.getLength(), osl_getThreadTextEncoding() ) += ::rtl::OString( "\"!" ) ).getStr() ); } } //--------------------------------------------------------------------- sal_Bool OCommonPicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) ) { sal_Bool bKnown = sal_True; if ( _rName == "ParentWindow" ) { m_xDialogParent.clear(); OSL_VERIFY( _rValue >>= m_xDialogParent ); OSL_ENSURE( VCLUnoHelper::GetWindow( m_xDialogParent ), "OCommonPicker::implHandleInitializationArgument: invalid parent window given!" ); } else bKnown = sal_False; return bKnown; } //......................................................................... } // namespace svt //......................................................................... /* vim:set shiftwidth=4 softtabstop=4 expandtab: */