| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_fpicker.hxx" |
| |
| #include "commonpicker.hxx" |
| #include <com/sun/star/beans/PropertyAttribute.hpp> |
| #include <com/sun/star/beans/NamedValue.hpp> |
| #include <vcl/svapp.hxx> |
| #include <vos/mutex.hxx> |
| #include <toolkit/helper/vclunohelper.hxx> |
| #include <comphelper/weakeventlistener.hxx> |
| #include <comphelper/types.hxx> |
| #include <vcl/msgbox.hxx> |
| #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::createFromAscii( "HelpURL" ), PROPERTY_ID_HELPURL, |
| PropertyAttribute::TRANSIENT, |
| &m_sHelpURL, ::getCppuType( &m_sHelpURL ) |
| ); |
| |
| registerProperty( |
| ::rtl::OUString::createFromAscii( "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.getLength() > 0 ) |
| getDialog()->SetText( m_aTitle ); |
| } |
| |
| //--------------------------------------------------------------------- |
| void SAL_CALL OCommonPicker::disposing() |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| |
| 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) |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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 |
| { |
| DBG_ERROR( "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() |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| |
| 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.getLength() ) |
| { // 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(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| 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 ) |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| m_aTitle = _rTitle; |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_Int16 OCommonPicker::execute() throw (RuntimeException) |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| |
| 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( OCommonPicker, OnCancelPicker, void*, EMPTYARG ) |
| { |
| // 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.getLength() <= 0) |
| continue; |
| |
| sSettingName = aPropArg.Name; |
| aSettingValue = aPropArg.Value; |
| } |
| else if ( *pArgument >>= aPairArg ) |
| { |
| if ( aPairArg.Name.getLength() <= 0) |
| continue; |
| |
| sSettingName = aPairArg.Name; |
| aSettingValue = aPairArg.Value; |
| |
| |
| } |
| else |
| { |
| DBG_ERROR( |
| ( ::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.equalsAscii( "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 |
| //......................................................................... |
| |