merged tag ooo/DEV300_m102
[LibreOffice.git] / fpicker / source / office / commonpicker.cxx
blob7fcab23e765753526cd67a7659d014d9c0ef2be8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
31 #include "commonpicker.hxx"
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/beans/NamedValue.hpp>
34 #include <vcl/svapp.hxx>
35 #include <vos/mutex.hxx>
36 #include <toolkit/helper/vclunohelper.hxx>
37 #include <comphelper/weakeventlistener.hxx>
38 #include <comphelper/types.hxx>
39 #include <vcl/msgbox.hxx>
40 #include "iodlg.hxx"
42 //.........................................................................
43 namespace svt
45 //.........................................................................
47 #define PROPERTY_ID_HELPURL 1
48 #define PROPERTY_ID_WINDOW 2
50 // using --------------------------------------------------------------
52 using namespace ::com::sun::star::lang;
53 using namespace ::com::sun::star::ui::dialogs;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::beans;
56 using namespace ::comphelper;
58 //---------------------------------------------------------------------
59 OCommonPicker::OCommonPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory )
60 :OCommonPicker_Base( m_aMutex )
61 ,OPropertyContainer( GetBroadcastHelper() )
62 ,m_xORB( _rxFactory )
63 ,m_pDlg( NULL )
64 ,m_nCancelEvent( 0 )
65 ,m_bExecuting( sal_False )
67 // the two properties we have
68 registerProperty(
69 ::rtl::OUString::createFromAscii( "HelpURL" ), PROPERTY_ID_HELPURL,
70 PropertyAttribute::TRANSIENT,
71 &m_sHelpURL, ::getCppuType( &m_sHelpURL )
74 registerProperty(
75 ::rtl::OUString::createFromAscii( "Window" ), PROPERTY_ID_WINDOW,
76 PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY,
77 &m_xWindow, ::getCppuType( &m_xWindow )
81 //---------------------------------------------------------------------
82 OCommonPicker::~OCommonPicker()
84 if ( !GetBroadcastHelper().bDisposed )
86 acquire();
87 dispose();
91 //---------------------------------------------------------------------
92 // disambiguate XInterface
93 //---------------------------------------------------------------------
94 IMPLEMENT_FORWARD_XINTERFACE2( OCommonPicker, OCommonPicker_Base, OPropertyContainer )
96 //---------------------------------------------------------------------
97 // disambiguate XTypeProvider
98 //---------------------------------------------------------------------
99 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCommonPicker, OCommonPicker_Base, OPropertyContainer )
101 //---------------------------------------------------------------------
102 // XComponent related methods
103 //---------------------------------------------------------------------
104 void OCommonPicker::checkAlive() const SAL_THROW( (DisposedException) )
106 if ( GetBroadcastHelper().bInDispose || GetBroadcastHelper().bDisposed )
107 throw DisposedException();
110 void OCommonPicker::prepareDialog()
112 if ( !getDialog() )
113 createPicker();
115 // set the title
116 if ( m_aTitle.getLength() > 0 )
117 getDialog()->SetText( m_aTitle );
120 //---------------------------------------------------------------------
121 void SAL_CALL OCommonPicker::disposing()
123 ::vos::OGuard aGuard( Application::GetSolarMutex() );
125 stopWindowListening();
127 if ( m_nCancelEvent )
128 Application::RemoveUserEvent( m_nCancelEvent );
131 ::osl::MutexGuard aOwnGuard( m_aMutex );
132 if ( m_bExecuting && m_pDlg )
133 m_pDlg->EndDialog( RET_CANCEL );
136 delete m_pDlg;
137 m_pDlg = NULL;
138 m_xWindow = NULL;
139 m_xDialogParent = NULL;
142 //---------------------------------------------------------------------
143 void OCommonPicker::stopWindowListening()
145 disposeComponent( m_xWindowListenerAdapter );
146 disposeComponent( m_xParentListenerAdapter );
149 //---------------------------------------------------------------------
150 // XEventListener
151 //---------------------------------------------------------------------
152 void SAL_CALL OCommonPicker::disposing( const EventObject& _rSource ) throw (RuntimeException)
154 ::vos::OGuard aGuard( Application::GetSolarMutex() );
155 sal_Bool bDialogDying = _rSource.Source == m_xWindow;
156 sal_Bool bParentDying = _rSource.Source == m_xDialogParent;
158 if ( bDialogDying || bParentDying )
160 stopWindowListening();
162 if ( !bDialogDying ) // it's the parent which is dying -> delete the dialog
163 delete m_pDlg;
165 m_pDlg = NULL;
166 m_xWindow = NULL;
167 m_xDialogParent = NULL;
169 else
171 DBG_ERROR( "OCommonPicker::disposing: where did this come from?" );
175 //---------------------------------------------------------------------
176 // property set related methods
177 //---------------------------------------------------------------------
178 ::cppu::IPropertyArrayHelper* OCommonPicker::createArrayHelper( ) const
180 Sequence< Property > aProps;
181 describeProperties( aProps );
182 return new cppu::OPropertyArrayHelper( aProps );
185 //---------------------------------------------------------------------
186 ::cppu::IPropertyArrayHelper& SAL_CALL OCommonPicker::getInfoHelper()
188 return *const_cast< OCommonPicker* >( this )->getArrayHelper();
191 //---------------------------------------------------------------------
192 Reference< XPropertySetInfo > SAL_CALL OCommonPicker::getPropertySetInfo( ) throw(RuntimeException)
194 return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
197 //---------------------------------------------------------------------
198 void SAL_CALL OCommonPicker::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception)
200 OPropertyContainer::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
202 // if the HelpURL changed, forward this to the dialog
203 if ( PROPERTY_ID_HELPURL == _nHandle )
204 if ( m_pDlg )
205 OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False );
209 //---------------------------------------------------------------------
210 sal_Bool OCommonPicker::createPicker()
212 ::vos::OGuard aGuard( Application::GetSolarMutex() );
214 if ( !m_pDlg )
216 m_pDlg = implCreateDialog( VCLUnoHelper::GetWindow( m_xDialogParent ) );
217 DBG_ASSERT( m_pDlg, "OCommonPicker::createPicker: invalid dialog returned!" );
219 if ( m_pDlg )
221 // synchronize the help id of the dialog with out help URL property
222 if ( m_sHelpURL.getLength() )
223 { // somebody already set the help URL while we had no dialog yet
224 OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False );
226 else
228 m_sHelpURL = OControlAccess::getHelpURL( m_pDlg, sal_False );
231 m_xWindow = VCLUnoHelper::GetInterface( m_pDlg );
233 // add as event listener to the window
234 Reference< XComponent > xWindowComp( m_xWindow, UNO_QUERY );
235 OSL_ENSURE( xWindowComp.is(), "OCommonPicker::createFileDialog: invalid window component!" );
236 if ( xWindowComp.is() )
238 m_xWindowListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp );
239 // the adapter will add itself as listener, and forward notifications
242 // _and_ add as event listener to the parent - in case the parent is destroyed
243 // before we are disposed, our disposal would access dead VCL windows then ....
244 m_xDialogParent = VCLUnoHelper::GetInterface( m_pDlg->GetParent() );
245 xWindowComp = xWindowComp.query( m_xDialogParent );
246 OSL_ENSURE( xWindowComp.is() || !m_pDlg->GetParent(), "OCommonPicker::createFileDialog: invalid window component (the parent this time)!" );
247 if ( xWindowComp.is() )
249 m_xParentListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp );
250 // the adapter will add itself as listener, and forward notifications
255 return NULL != m_pDlg;
258 //---------------------------------------------------------------------
259 // XControlAccess functions
260 //---------------------------------------------------------------------
261 void SAL_CALL OCommonPicker::setControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty, const Any& aValue ) throw (IllegalArgumentException, RuntimeException)
263 checkAlive();
265 ::vos::OGuard aGuard( Application::GetSolarMutex() );
266 if ( createPicker() )
268 ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
269 aAccess.setControlProperty( aControlName, aControlProperty, aValue );
273 //---------------------------------------------------------------------
274 Any SAL_CALL OCommonPicker::getControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException)
276 checkAlive();
278 ::vos::OGuard aGuard( Application::GetSolarMutex() );
279 if ( createPicker() )
281 ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
282 return aAccess.getControlProperty( aControlName, aControlProperty );
285 return Any();
288 //---------------------------------------------------------------------
289 // XControlInformation functions
290 //---------------------------------------------------------------------
291 Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControls( ) throw (RuntimeException)
293 checkAlive();
295 ::vos::OGuard aGuard( Application::GetSolarMutex() );
296 if ( createPicker() )
298 ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
299 return aAccess.getSupportedControls( );
302 return Sequence< ::rtl::OUString >();
305 //---------------------------------------------------------------------
306 sal_Bool SAL_CALL OCommonPicker::isControlSupported( const ::rtl::OUString& aControlName ) throw (RuntimeException)
308 checkAlive();
310 ::vos::OGuard aGuard( Application::GetSolarMutex() );
311 if ( createPicker() )
313 ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
314 return aAccess.isControlSupported( aControlName );
317 return sal_False;
320 //---------------------------------------------------------------------
321 Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControlProperties( const ::rtl::OUString& aControlName ) throw (IllegalArgumentException, RuntimeException)
323 checkAlive();
325 ::vos::OGuard aGuard( Application::GetSolarMutex() );
326 if ( createPicker() )
328 ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
329 return aAccess.getSupportedControlProperties( aControlName );
332 return Sequence< ::rtl::OUString >();
335 //---------------------------------------------------------------------
336 sal_Bool SAL_CALL OCommonPicker::isControlPropertySupported( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException)
338 checkAlive();
340 ::vos::OGuard aGuard( Application::GetSolarMutex() );
341 if ( createPicker() )
343 ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
344 return aAccess.isControlPropertySupported( aControlName, aControlProperty );
347 return sal_False;
350 //---------------------------------------------------------------------
351 // XExecutableDialog functions
352 //---------------------------------------------------------------------
353 void SAL_CALL OCommonPicker::setTitle( const rtl::OUString& _rTitle ) throw( RuntimeException )
355 ::vos::OGuard aGuard( Application::GetSolarMutex() );
356 m_aTitle = _rTitle;
359 //---------------------------------------------------------------------
360 sal_Int16 OCommonPicker::execute() throw (RuntimeException)
362 ::vos::OGuard aGuard( Application::GetSolarMutex() );
364 prepareDialog();
367 ::osl::MutexGuard aOwnGuard( m_aMutex );
368 m_bExecuting = sal_True;
370 sal_Int16 nResult = implExecutePicker();
372 ::osl::MutexGuard aOwnGuard( m_aMutex );
373 m_bExecuting = sal_False;
376 return nResult;
379 //---------------------------------------------------------------------
380 // XCancellable functions
381 //---------------------------------------------------------------------
382 void SAL_CALL OCommonPicker::cancel( ) throw (RuntimeException)
385 ::osl::MutexGuard aGuard( m_aMutex );
386 if ( m_nCancelEvent )
387 // nothing to do - the event for cancelling the dialog is already on the way
388 return;
391 // The thread which executes our dialog has locked the solar mutex for
392 // sure. Cancelling the dialog should be done with a locked solar mutex, too.
393 // Thus we post ourself a message for cancelling the dialog. This way, the message
394 // is either handled in the thread which opened the dialog (which may even be
395 // this thread here), or, if no dialog is open, in the thread doing scheduling
396 // currently. Both is okay for us ....
398 // Note that we could do check if we are really executing the dialog currently.
399 // but the information would be potentially obsolete at the moment our event
400 // arrives, so we need to check it there, anyway ...
401 m_nCancelEvent = Application::PostUserEvent( LINK( this, OCommonPicker, OnCancelPicker ) );
404 //---------------------------------------------------------------------
405 IMPL_LINK( OCommonPicker, OnCancelPicker, void*, EMPTYARG )
407 // By definition, the solar mutex is locked when we arrive here. Note that this
408 // is important, as for instance the consistency of m_pDlg depends on this mutex.
409 ::osl::MutexGuard aGuard( m_aMutex );
410 m_nCancelEvent = 0;
412 if ( !m_bExecuting )
413 // nothing to do. This may be because the dialog was cancelled after our cancel method
414 // posted this async event, or because somebody called cancel without the dialog
415 // being executed at this time.
416 return 0;
418 OSL_ENSURE( getDialog(), "OCommonPicker::OnCancelPicker: executing, but no dialog!" );
419 if ( getDialog() )
420 getDialog()->EndDialog( RET_CANCEL );
422 return 0L;
425 //------------------------------------------------------------------------------------
426 // XInitialization functions
427 //------------------------------------------------------------------------------------
428 void SAL_CALL OCommonPicker::initialize( const Sequence< Any >& _rArguments )
429 throw ( Exception, RuntimeException )
431 checkAlive();
433 ::rtl::OUString sSettingName;
434 Any aSettingValue;
436 PropertyValue aPropArg;
437 NamedValue aPairArg;
440 const Any* pArguments = _rArguments.getConstArray();
441 const Any* pArgumentsEnd = _rArguments.getConstArray() + _rArguments.getLength();
442 for ( const Any* pArgument = pArguments;
443 pArgument != pArgumentsEnd;
444 ++pArgument
447 if ( *pArgument >>= aPropArg )
449 if ( aPropArg.Name.getLength() <= 0)
450 continue;
452 sSettingName = aPropArg.Name;
453 aSettingValue = aPropArg.Value;
455 else if ( *pArgument >>= aPairArg )
457 if ( aPairArg.Name.getLength() <= 0)
458 continue;
460 sSettingName = aPairArg.Name;
461 aSettingValue = aPairArg.Value;
465 else
467 DBG_ERROR(
468 ( ::rtl::OString( "OCommonPicker::initialize: unknown argument type at position " )
469 += ::rtl::OString::valueOf( (sal_Int32)( pArguments - _rArguments.getConstArray() ) )
470 ).getStr()
472 continue;
475 #ifdef DBG_UTIL
476 sal_Bool bKnownSetting =
477 #endif
478 implHandleInitializationArgument( sSettingName, aSettingValue );
479 DBG_ASSERT( bKnownSetting,
480 ( ::rtl::OString( "OCommonPicker::initialize: unknown argument \"" )
481 += ::rtl::OString( sSettingName.getStr(), sSettingName.getLength(), osl_getThreadTextEncoding() )
482 += ::rtl::OString( "\"!" )
483 ).getStr()
488 //---------------------------------------------------------------------
489 sal_Bool OCommonPicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) )
491 sal_Bool bKnown = sal_True;
492 if ( _rName.equalsAscii( "ParentWindow" ) )
494 m_xDialogParent.clear();
495 OSL_VERIFY( _rValue >>= m_xDialogParent );
496 OSL_ENSURE( VCLUnoHelper::GetWindow( m_xDialogParent ), "OCommonPicker::implHandleInitializationArgument: invalid parent window given!" );
498 else
499 bKnown = sal_False;
500 return bKnown;
503 //.........................................................................
504 } // namespace svt
505 //.........................................................................