1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "commonpicker.hxx"
22 #include <com/sun/star/beans/PropertyAttribute.hpp>
23 #include <com/sun/star/beans/NamedValue.hpp>
24 #include <vcl/svapp.hxx>
25 #include <osl/mutex.hxx>
26 #include <toolkit/helper/vclunohelper.hxx>
27 #include <comphelper/weakeventlistener.hxx>
28 #include <comphelper/types.hxx>
29 #include <vcl/msgbox.hxx>
37 #define PROPERTY_ID_HELPURL 1
38 #define PROPERTY_ID_WINDOW 2
40 // using --------------------------------------------------------------
42 using namespace ::com::sun::star::lang
;
43 using namespace ::com::sun::star::ui::dialogs
;
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::comphelper
;
49 OCommonPicker::OCommonPicker()
50 :OCommonPicker_Base( m_aMutex
)
51 ,OPropertyContainer( GetBroadcastHelper() )
53 ,m_nCancelEvent( nullptr )
54 ,m_bExecuting( false )
56 // the two properties we have
58 "HelpURL", PROPERTY_ID_HELPURL
,
59 PropertyAttribute::TRANSIENT
,
60 &m_sHelpURL
, cppu::UnoType
<decltype(m_sHelpURL
)>::get()
64 "Window", PROPERTY_ID_WINDOW
,
65 PropertyAttribute::TRANSIENT
| PropertyAttribute::READONLY
,
66 &m_xWindow
, cppu::UnoType
<decltype(m_xWindow
)>::get()
71 OCommonPicker::~OCommonPicker()
73 if ( !GetBroadcastHelper().bDisposed
)
81 // disambiguate XInterface
83 IMPLEMENT_FORWARD_XINTERFACE2( OCommonPicker
, OCommonPicker_Base
, OPropertyContainer
)
86 // disambiguate XTypeProvider
88 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCommonPicker
, OCommonPicker_Base
, OPropertyContainer
)
91 // XComponent related methods
93 void OCommonPicker::checkAlive() const
95 if ( GetBroadcastHelper().bInDispose
|| GetBroadcastHelper().bDisposed
)
96 throw DisposedException();
99 void OCommonPicker::prepareDialog()
104 if ( !m_aTitle
.isEmpty() )
105 m_pDlg
->SetText( m_aTitle
);
110 void SAL_CALL
OCommonPicker::disposing()
112 SolarMutexGuard aGuard
;
114 stopWindowListening();
116 if ( m_nCancelEvent
)
117 Application::RemoveUserEvent( m_nCancelEvent
);
120 ::osl::MutexGuard
aOwnGuard( m_aMutex
);
121 if ( m_bExecuting
&& m_pDlg
)
125 m_pDlg
.disposeAndClear();
127 m_xDialogParent
= nullptr;
131 void OCommonPicker::stopWindowListening()
133 disposeComponent( m_xWindowListenerAdapter
);
134 disposeComponent( m_xParentListenerAdapter
);
140 void SAL_CALL
OCommonPicker::disposing( const EventObject
& _rSource
) throw (RuntimeException
, std::exception
)
142 SolarMutexGuard aGuard
;
143 bool bDialogDying
= _rSource
.Source
== m_xWindow
;
144 bool bParentDying
= _rSource
.Source
== m_xDialogParent
;
146 if ( bDialogDying
|| bParentDying
)
148 stopWindowListening();
150 if ( !bDialogDying
) // it's the parent which is dying -> delete the dialog
151 m_pDlg
.disposeAndClear();
156 m_xDialogParent
= nullptr;
160 OSL_FAIL( "OCommonPicker::disposing: where did this come from?" );
165 // property set related methods
167 ::cppu::IPropertyArrayHelper
* OCommonPicker::createArrayHelper( ) const
169 Sequence
< Property
> aProps
;
170 describeProperties( aProps
);
171 return new cppu::OPropertyArrayHelper( aProps
);
175 ::cppu::IPropertyArrayHelper
& SAL_CALL
OCommonPicker::getInfoHelper()
177 return *getArrayHelper();
181 Reference
< XPropertySetInfo
> SAL_CALL
OCommonPicker::getPropertySetInfo( ) throw(RuntimeException
, std::exception
)
183 return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
187 void SAL_CALL
OCommonPicker::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
) throw (Exception
, std::exception
)
189 OPropertyContainer::setFastPropertyValue_NoBroadcast( _nHandle
, _rValue
);
191 // if the HelpURL changed, forward this to the dialog
192 if ( PROPERTY_ID_HELPURL
== _nHandle
)
194 OControlAccess::setHelpURL( m_pDlg
, m_sHelpURL
, false );
198 bool OCommonPicker::createPicker()
202 m_pDlg
.reset( implCreateDialog( VCLUnoHelper::GetWindow( m_xDialogParent
) ) );
203 SAL_WARN_IF( !m_pDlg
, "fpicker.office", "OCommonPicker::createPicker: invalid dialog returned!" );
207 // synchronize the help id of the dialog with out help URL property
208 if ( !m_sHelpURL
.isEmpty() )
209 { // somebody already set the help URL while we had no dialog yet
210 OControlAccess::setHelpURL( m_pDlg
, m_sHelpURL
, false );
214 m_sHelpURL
= OControlAccess::getHelpURL( m_pDlg
, false );
217 m_xWindow
= VCLUnoHelper::GetInterface( m_pDlg
);
219 // add as event listener to the window
220 Reference
< XComponent
> xWindowComp( m_xWindow
, UNO_QUERY
);
221 OSL_ENSURE( xWindowComp
.is(), "OCommonPicker::createFileDialog: invalid window component!" );
222 if ( xWindowComp
.is() )
224 m_xWindowListenerAdapter
= new OWeakEventListenerAdapter( this, xWindowComp
);
225 // the adapter will add itself as listener, and forward notifications
228 // _and_ add as event listener to the parent - in case the parent is destroyed
229 // before we are disposed, our disposal would access dead VCL windows then ....
230 m_xDialogParent
= VCLUnoHelper::GetInterface( m_pDlg
->GetParent() );
231 xWindowComp
.set(m_xDialogParent
, css::uno::UNO_QUERY
);
232 OSL_ENSURE( xWindowComp
.is() || !m_pDlg
->GetParent(), "OCommonPicker::createFileDialog: invalid window component (the parent this time)!" );
233 if ( xWindowComp
.is() )
235 m_xParentListenerAdapter
= new OWeakEventListenerAdapter( this, xWindowComp
);
236 // the adapter will add itself as listener, and forward notifications
241 return nullptr != m_pDlg
;
245 // XControlAccess functions
247 void SAL_CALL
OCommonPicker::setControlProperty( const OUString
& aControlName
, const OUString
& aControlProperty
, const Any
& aValue
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
251 SolarMutexGuard aGuard
;
252 if ( createPicker() )
254 ::svt::OControlAccess
aAccess( m_pDlg
, m_pDlg
->GetView() );
255 aAccess
.setControlProperty( aControlName
, aControlProperty
, aValue
);
260 Any SAL_CALL
OCommonPicker::getControlProperty( const OUString
& aControlName
, const OUString
& aControlProperty
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
264 SolarMutexGuard aGuard
;
265 if ( createPicker() )
267 ::svt::OControlAccess
aAccess( m_pDlg
, m_pDlg
->GetView() );
268 return aAccess
.getControlProperty( aControlName
, aControlProperty
);
275 // XControlInformation functions
277 Sequence
< OUString
> SAL_CALL
OCommonPicker::getSupportedControls( ) throw (RuntimeException
, std::exception
)
281 SolarMutexGuard aGuard
;
282 if ( createPicker() )
284 ::svt::OControlAccess
aAccess( m_pDlg
, m_pDlg
->GetView() );
285 return aAccess
.getSupportedControls( );
288 return Sequence
< OUString
>();
292 sal_Bool SAL_CALL
OCommonPicker::isControlSupported( const OUString
& aControlName
) throw (RuntimeException
, std::exception
)
296 SolarMutexGuard aGuard
;
297 if ( createPicker() )
299 return svt::OControlAccess::isControlSupported( aControlName
);
306 Sequence
< OUString
> SAL_CALL
OCommonPicker::getSupportedControlProperties( const OUString
& aControlName
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
310 SolarMutexGuard aGuard
;
311 if ( createPicker() )
313 ::svt::OControlAccess
aAccess( m_pDlg
, m_pDlg
->GetView() );
314 return aAccess
.getSupportedControlProperties( aControlName
);
317 return Sequence
< OUString
>();
321 sal_Bool SAL_CALL
OCommonPicker::isControlPropertySupported( const OUString
& aControlName
, const OUString
& aControlProperty
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
325 SolarMutexGuard aGuard
;
326 if ( createPicker() )
328 ::svt::OControlAccess
aAccess( m_pDlg
, m_pDlg
->GetView() );
329 return aAccess
.isControlPropertySupported( aControlName
, aControlProperty
);
336 // XExecutableDialog functions
338 void SAL_CALL
OCommonPicker::setTitle( const OUString
& _rTitle
) throw( RuntimeException
, std::exception
)
340 SolarMutexGuard aGuard
;
345 sal_Int16
OCommonPicker::execute() throw (RuntimeException
, std::exception
)
347 SolarMutexGuard aGuard
;
352 ::osl::MutexGuard
aOwnGuard( m_aMutex
);
355 sal_Int16 nResult
= implExecutePicker();
357 ::osl::MutexGuard
aOwnGuard( m_aMutex
);
358 m_bExecuting
= false;
365 // XCancellable functions
367 void SAL_CALL
OCommonPicker::cancel( ) throw (RuntimeException
, std::exception
)
370 ::osl::MutexGuard
aGuard( m_aMutex
);
371 if ( m_nCancelEvent
)
372 // nothing to do - the event for cancelling the dialog is already on the way
376 // The thread which executes our dialog has locked the solar mutex for
377 // sure. Cancelling the dialog should be done with a locked solar mutex, too.
378 // Thus we post ourself a message for cancelling the dialog. This way, the message
379 // is either handled in the thread which opened the dialog (which may even be
380 // this thread here), or, if no dialog is open, in the thread doing scheduling
381 // currently. Both is okay for us ....
383 // Note that we could do check if we are really executing the dialog currently.
384 // but the information would be potentially obsolete at the moment our event
385 // arrives, so we need to check it there, anyway ...
386 m_nCancelEvent
= Application::PostUserEvent( LINK( this, OCommonPicker
, OnCancelPicker
) );
390 IMPL_LINK_NOARG(OCommonPicker
, OnCancelPicker
, void*, void)
392 // By definition, the solar mutex is locked when we arrive here. Note that this
393 // is important, as for instance the consistency of m_pDlg depends on this mutex.
394 ::osl::MutexGuard
aGuard( m_aMutex
);
395 m_nCancelEvent
= nullptr;
398 // nothing to do. This may be because the dialog was canceled after our cancel method
399 // posted this async event, or because somebody called cancel without the dialog
400 // being executed at this time.
403 OSL_ENSURE( getDialog(), "OCommonPicker::OnCancelPicker: executing, but no dialog!" );
405 getDialog()->EndDialog();
409 // XInitialization functions
411 void SAL_CALL
OCommonPicker::initialize( const Sequence
< Any
>& _rArguments
)
412 throw ( Exception
, RuntimeException
, std::exception
)
416 OUString sSettingName
;
419 PropertyValue aPropArg
;
423 const Any
* pArguments
= _rArguments
.getConstArray();
424 const Any
* pArgumentsEnd
= _rArguments
.getConstArray() + _rArguments
.getLength();
425 for ( const Any
* pArgument
= pArguments
;
426 pArgument
!= pArgumentsEnd
;
430 if ( *pArgument
>>= aPropArg
)
432 if ( aPropArg
.Name
.isEmpty())
435 sSettingName
= aPropArg
.Name
;
436 aSettingValue
= aPropArg
.Value
;
438 else if ( *pArgument
>>= aPairArg
)
440 if ( aPairArg
.Name
.isEmpty())
443 sSettingName
= aPairArg
.Name
;
444 aSettingValue
= aPairArg
.Value
;
452 "OCommonPicker::initialize: unknown argument type at position "
453 + OString::number(pArguments
- _rArguments
.getConstArray())).getStr());
458 implHandleInitializationArgument( sSettingName
, aSettingValue
);
459 DBG_ASSERT( bKnownSetting
,
461 "OCommonPicker::initialize: unknown argument \""
462 + OString(sSettingName
.getStr(), sSettingName
.getLength(), osl_getThreadTextEncoding())
468 bool OCommonPicker::implHandleInitializationArgument( const OUString
& _rName
, const Any
& _rValue
)
471 if ( _rName
== "ParentWindow" )
473 m_xDialogParent
.clear();
474 OSL_VERIFY( _rValue
>>= m_xDialogParent
);
475 OSL_ENSURE( VCLUnoHelper::GetWindow( m_xDialogParent
), "OCommonPicker::implHandleInitializationArgument: invalid parent window given!" );
486 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */