Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
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>
30 : : #include "iodlg.hxx"
31 : :
32 : : //.........................................................................
33 : : namespace svt
34 : : {
35 : : //.........................................................................
36 : :
37 : : #define PROPERTY_ID_HELPURL 1
38 : : #define PROPERTY_ID_WINDOW 2
39 : :
40 : : // using --------------------------------------------------------------
41 : :
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;
47 : :
48 : : //---------------------------------------------------------------------
49 : 0 : OCommonPicker::OCommonPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory )
50 : : :OCommonPicker_Base( m_aMutex )
51 : 0 : ,OPropertyContainer( GetBroadcastHelper() )
52 : : ,m_xORB( _rxFactory )
53 : : ,m_pDlg( NULL )
54 : : ,m_nCancelEvent( 0 )
55 : 0 : ,m_bExecuting( sal_False )
56 : : {
57 : : // the two properties we have
58 : : registerProperty(
59 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )), PROPERTY_ID_HELPURL,
60 : : PropertyAttribute::TRANSIENT,
61 : 0 : &m_sHelpURL, ::getCppuType( &m_sHelpURL )
62 : 0 : );
63 : :
64 : : registerProperty(
65 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Window" )), PROPERTY_ID_WINDOW,
66 : : PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY,
67 : 0 : &m_xWindow, ::getCppuType( &m_xWindow )
68 : 0 : );
69 : 0 : }
70 : :
71 : : //---------------------------------------------------------------------
72 : 0 : OCommonPicker::~OCommonPicker()
73 : : {
74 : 0 : if ( !GetBroadcastHelper().bDisposed )
75 : : {
76 : 0 : acquire();
77 : 0 : dispose();
78 : : }
79 : 0 : }
80 : :
81 : : //---------------------------------------------------------------------
82 : : // disambiguate XInterface
83 : : //---------------------------------------------------------------------
84 : 0 : IMPLEMENT_FORWARD_XINTERFACE2( OCommonPicker, OCommonPicker_Base, OPropertyContainer )
85 : :
86 : : //---------------------------------------------------------------------
87 : : // disambiguate XTypeProvider
88 : : //---------------------------------------------------------------------
89 : 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCommonPicker, OCommonPicker_Base, OPropertyContainer )
90 : :
91 : : //---------------------------------------------------------------------
92 : : // XComponent related methods
93 : : //---------------------------------------------------------------------
94 : 0 : void OCommonPicker::checkAlive() const SAL_THROW( (DisposedException) )
95 : : {
96 : 0 : if ( GetBroadcastHelper().bInDispose || GetBroadcastHelper().bDisposed )
97 : 0 : throw DisposedException();
98 : 0 : }
99 : :
100 : 0 : void OCommonPicker::prepareDialog()
101 : : {
102 : 0 : if ( !getDialog() )
103 : 0 : createPicker();
104 : :
105 : : // set the title
106 : 0 : if ( !m_aTitle.isEmpty() )
107 : 0 : getDialog()->SetText( m_aTitle );
108 : 0 : }
109 : :
110 : : //---------------------------------------------------------------------
111 : 0 : void SAL_CALL OCommonPicker::disposing()
112 : : {
113 : 0 : SolarMutexGuard aGuard;
114 : :
115 : 0 : stopWindowListening();
116 : :
117 : 0 : if ( m_nCancelEvent )
118 : 0 : Application::RemoveUserEvent( m_nCancelEvent );
119 : :
120 : : {
121 : 0 : ::osl::MutexGuard aOwnGuard( m_aMutex );
122 : 0 : if ( m_bExecuting && m_pDlg )
123 : 0 : m_pDlg->EndDialog( RET_CANCEL );
124 : : }
125 : :
126 : 0 : delete m_pDlg;
127 : 0 : m_pDlg = NULL;
128 : 0 : m_xWindow = NULL;
129 : 0 : m_xDialogParent = NULL;
130 : 0 : }
131 : :
132 : : //---------------------------------------------------------------------
133 : 0 : void OCommonPicker::stopWindowListening()
134 : : {
135 : 0 : disposeComponent( m_xWindowListenerAdapter );
136 : 0 : disposeComponent( m_xParentListenerAdapter );
137 : 0 : }
138 : :
139 : : //---------------------------------------------------------------------
140 : : // XEventListener
141 : : //---------------------------------------------------------------------
142 : 0 : void SAL_CALL OCommonPicker::disposing( const EventObject& _rSource ) throw (RuntimeException)
143 : : {
144 : 0 : SolarMutexGuard aGuard;
145 : 0 : sal_Bool bDialogDying = _rSource.Source == m_xWindow;
146 : 0 : sal_Bool bParentDying = _rSource.Source == m_xDialogParent;
147 : :
148 : 0 : if ( bDialogDying || bParentDying )
149 : : {
150 : 0 : stopWindowListening();
151 : :
152 : 0 : if ( !bDialogDying ) // it's the parent which is dying -> delete the dialog
153 : 0 : delete m_pDlg;
154 : :
155 : 0 : m_pDlg = NULL;
156 : 0 : m_xWindow = NULL;
157 : 0 : m_xDialogParent = NULL;
158 : : }
159 : : else
160 : : {
161 : : OSL_FAIL( "OCommonPicker::disposing: where did this come from?" );
162 : 0 : }
163 : 0 : }
164 : :
165 : : //---------------------------------------------------------------------
166 : : // property set related methods
167 : : //---------------------------------------------------------------------
168 : 0 : ::cppu::IPropertyArrayHelper* OCommonPicker::createArrayHelper( ) const
169 : : {
170 : 0 : Sequence< Property > aProps;
171 : 0 : describeProperties( aProps );
172 : 0 : return new cppu::OPropertyArrayHelper( aProps );
173 : : }
174 : :
175 : : //---------------------------------------------------------------------
176 : 0 : ::cppu::IPropertyArrayHelper& SAL_CALL OCommonPicker::getInfoHelper()
177 : : {
178 : 0 : return *const_cast< OCommonPicker* >( this )->getArrayHelper();
179 : : }
180 : :
181 : : //---------------------------------------------------------------------
182 : 0 : Reference< XPropertySetInfo > SAL_CALL OCommonPicker::getPropertySetInfo( ) throw(RuntimeException)
183 : : {
184 : 0 : return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
185 : : }
186 : :
187 : : //---------------------------------------------------------------------
188 : 0 : void SAL_CALL OCommonPicker::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception)
189 : : {
190 : 0 : OPropertyContainer::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
191 : :
192 : : // if the HelpURL changed, forward this to the dialog
193 : 0 : if ( PROPERTY_ID_HELPURL == _nHandle )
194 : 0 : if ( m_pDlg )
195 : 0 : OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False );
196 : 0 : }
197 : :
198 : :
199 : : //---------------------------------------------------------------------
200 : 0 : sal_Bool OCommonPicker::createPicker()
201 : : {
202 : 0 : SolarMutexGuard aGuard;
203 : :
204 : 0 : if ( !m_pDlg )
205 : : {
206 : 0 : m_pDlg = implCreateDialog( VCLUnoHelper::GetWindow( m_xDialogParent ) );
207 : : DBG_ASSERT( m_pDlg, "OCommonPicker::createPicker: invalid dialog returned!" );
208 : :
209 : 0 : if ( m_pDlg )
210 : : {
211 : : // synchronize the help id of the dialog with out help URL property
212 : 0 : if ( !m_sHelpURL.isEmpty() )
213 : : { // somebody already set the help URL while we had no dialog yet
214 : 0 : OControlAccess::setHelpURL( m_pDlg, m_sHelpURL, sal_False );
215 : : }
216 : : else
217 : : {
218 : 0 : m_sHelpURL = OControlAccess::getHelpURL( m_pDlg, sal_False );
219 : : }
220 : :
221 : 0 : m_xWindow = VCLUnoHelper::GetInterface( m_pDlg );
222 : :
223 : : // add as event listener to the window
224 : 0 : Reference< XComponent > xWindowComp( m_xWindow, UNO_QUERY );
225 : : OSL_ENSURE( xWindowComp.is(), "OCommonPicker::createFileDialog: invalid window component!" );
226 : 0 : if ( xWindowComp.is() )
227 : : {
228 : 0 : m_xWindowListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp );
229 : : // the adapter will add itself as listener, and forward notifications
230 : : }
231 : :
232 : : // _and_ add as event listener to the parent - in case the parent is destroyed
233 : : // before we are disposed, our disposal would access dead VCL windows then ....
234 : 0 : m_xDialogParent = VCLUnoHelper::GetInterface( m_pDlg->GetParent() );
235 : 0 : xWindowComp = xWindowComp.query( m_xDialogParent );
236 : : OSL_ENSURE( xWindowComp.is() || !m_pDlg->GetParent(), "OCommonPicker::createFileDialog: invalid window component (the parent this time)!" );
237 : 0 : if ( xWindowComp.is() )
238 : : {
239 : 0 : m_xParentListenerAdapter = new OWeakEventListenerAdapter( this, xWindowComp );
240 : : // the adapter will add itself as listener, and forward notifications
241 : 0 : }
242 : : }
243 : : }
244 : :
245 : 0 : return NULL != m_pDlg;
246 : : }
247 : :
248 : : //---------------------------------------------------------------------
249 : : // XControlAccess functions
250 : : //---------------------------------------------------------------------
251 : 0 : void SAL_CALL OCommonPicker::setControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty, const Any& aValue ) throw (IllegalArgumentException, RuntimeException)
252 : : {
253 : 0 : checkAlive();
254 : :
255 : 0 : SolarMutexGuard aGuard;
256 : 0 : if ( createPicker() )
257 : : {
258 : 0 : ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
259 : 0 : aAccess.setControlProperty( aControlName, aControlProperty, aValue );
260 : 0 : }
261 : 0 : }
262 : :
263 : : //---------------------------------------------------------------------
264 : 0 : Any SAL_CALL OCommonPicker::getControlProperty( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException)
265 : : {
266 : 0 : checkAlive();
267 : :
268 : 0 : SolarMutexGuard aGuard;
269 : 0 : if ( createPicker() )
270 : : {
271 : 0 : ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
272 : 0 : return aAccess.getControlProperty( aControlName, aControlProperty );
273 : : }
274 : :
275 : 0 : return Any();
276 : : }
277 : :
278 : : //---------------------------------------------------------------------
279 : : // XControlInformation functions
280 : : //---------------------------------------------------------------------
281 : 0 : Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControls( ) throw (RuntimeException)
282 : : {
283 : 0 : checkAlive();
284 : :
285 : 0 : SolarMutexGuard aGuard;
286 : 0 : if ( createPicker() )
287 : : {
288 : 0 : ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
289 : 0 : return aAccess.getSupportedControls( );
290 : : }
291 : :
292 : 0 : return Sequence< ::rtl::OUString >();
293 : : }
294 : :
295 : : //---------------------------------------------------------------------
296 : 0 : sal_Bool SAL_CALL OCommonPicker::isControlSupported( const ::rtl::OUString& aControlName ) throw (RuntimeException)
297 : : {
298 : 0 : checkAlive();
299 : :
300 : 0 : SolarMutexGuard aGuard;
301 : 0 : if ( createPicker() )
302 : : {
303 : 0 : ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
304 : 0 : return aAccess.isControlSupported( aControlName );
305 : : }
306 : :
307 : 0 : return sal_False;
308 : : }
309 : :
310 : : //---------------------------------------------------------------------
311 : 0 : Sequence< ::rtl::OUString > SAL_CALL OCommonPicker::getSupportedControlProperties( const ::rtl::OUString& aControlName ) throw (IllegalArgumentException, RuntimeException)
312 : : {
313 : 0 : checkAlive();
314 : :
315 : 0 : SolarMutexGuard aGuard;
316 : 0 : if ( createPicker() )
317 : : {
318 : 0 : ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
319 : 0 : return aAccess.getSupportedControlProperties( aControlName );
320 : : }
321 : :
322 : 0 : return Sequence< ::rtl::OUString >();
323 : : }
324 : :
325 : : //---------------------------------------------------------------------
326 : 0 : sal_Bool SAL_CALL OCommonPicker::isControlPropertySupported( const ::rtl::OUString& aControlName, const ::rtl::OUString& aControlProperty ) throw (IllegalArgumentException, RuntimeException)
327 : : {
328 : 0 : checkAlive();
329 : :
330 : 0 : SolarMutexGuard aGuard;
331 : 0 : if ( createPicker() )
332 : : {
333 : 0 : ::svt::OControlAccess aAccess( m_pDlg, m_pDlg->GetView() );
334 : 0 : return aAccess.isControlPropertySupported( aControlName, aControlProperty );
335 : : }
336 : :
337 : 0 : return sal_False;
338 : : }
339 : :
340 : : //---------------------------------------------------------------------
341 : : // XExecutableDialog functions
342 : : //---------------------------------------------------------------------
343 : 0 : void SAL_CALL OCommonPicker::setTitle( const rtl::OUString& _rTitle ) throw( RuntimeException )
344 : : {
345 : 0 : SolarMutexGuard aGuard;
346 : 0 : m_aTitle = _rTitle;
347 : 0 : }
348 : :
349 : : //---------------------------------------------------------------------
350 : 0 : sal_Int16 OCommonPicker::execute() throw (RuntimeException)
351 : : {
352 : 0 : SolarMutexGuard aGuard;
353 : :
354 : 0 : prepareDialog();
355 : :
356 : : {
357 : 0 : ::osl::MutexGuard aOwnGuard( m_aMutex );
358 : 0 : m_bExecuting = sal_True;
359 : : }
360 : 0 : sal_Int16 nResult = implExecutePicker();
361 : : {
362 : 0 : ::osl::MutexGuard aOwnGuard( m_aMutex );
363 : 0 : m_bExecuting = sal_False;
364 : : }
365 : :
366 : 0 : return nResult;
367 : : }
368 : :
369 : : //---------------------------------------------------------------------
370 : : // XCancellable functions
371 : : //---------------------------------------------------------------------
372 : 0 : void SAL_CALL OCommonPicker::cancel( ) throw (RuntimeException)
373 : : {
374 : : {
375 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
376 : 0 : if ( m_nCancelEvent )
377 : : // nothing to do - the event for cancelling the dialog is already on the way
378 : 0 : return;
379 : : }
380 : :
381 : : // The thread which executes our dialog has locked the solar mutex for
382 : : // sure. Cancelling the dialog should be done with a locked solar mutex, too.
383 : : // Thus we post ourself a message for cancelling the dialog. This way, the message
384 : : // is either handled in the thread which opened the dialog (which may even be
385 : : // this thread here), or, if no dialog is open, in the thread doing scheduling
386 : : // currently. Both is okay for us ....
387 : : //
388 : : // Note that we could do check if we are really executing the dialog currently.
389 : : // but the information would be potentially obsolete at the moment our event
390 : : // arrives, so we need to check it there, anyway ...
391 : 0 : m_nCancelEvent = Application::PostUserEvent( LINK( this, OCommonPicker, OnCancelPicker ) );
392 : : }
393 : :
394 : : //---------------------------------------------------------------------
395 : 0 : IMPL_LINK_NOARG(OCommonPicker, OnCancelPicker)
396 : : {
397 : : // By definition, the solar mutex is locked when we arrive here. Note that this
398 : : // is important, as for instance the consistency of m_pDlg depends on this mutex.
399 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
400 : 0 : m_nCancelEvent = 0;
401 : :
402 : 0 : if ( !m_bExecuting )
403 : : // nothing to do. This may be because the dialog was cancelled after our cancel method
404 : : // posted this async event, or because somebody called cancel without the dialog
405 : : // being executed at this time.
406 : 0 : return 0;
407 : :
408 : : OSL_ENSURE( getDialog(), "OCommonPicker::OnCancelPicker: executing, but no dialog!" );
409 : 0 : if ( getDialog() )
410 : 0 : getDialog()->EndDialog( RET_CANCEL );
411 : :
412 : 0 : return 0L;
413 : : }
414 : :
415 : : //------------------------------------------------------------------------------------
416 : : // XInitialization functions
417 : : //------------------------------------------------------------------------------------
418 : 0 : void SAL_CALL OCommonPicker::initialize( const Sequence< Any >& _rArguments )
419 : : throw ( Exception, RuntimeException )
420 : : {
421 : 0 : checkAlive();
422 : :
423 : 0 : ::rtl::OUString sSettingName;
424 : 0 : Any aSettingValue;
425 : :
426 : 0 : PropertyValue aPropArg;
427 : 0 : NamedValue aPairArg;
428 : :
429 : :
430 : 0 : const Any* pArguments = _rArguments.getConstArray();
431 : 0 : const Any* pArgumentsEnd = _rArguments.getConstArray() + _rArguments.getLength();
432 : 0 : for ( const Any* pArgument = pArguments;
433 : : pArgument != pArgumentsEnd;
434 : : ++pArgument
435 : : )
436 : : {
437 : 0 : if ( *pArgument >>= aPropArg )
438 : : {
439 : 0 : if ( aPropArg.Name.isEmpty())
440 : 0 : continue;
441 : :
442 : 0 : sSettingName = aPropArg.Name;
443 : 0 : aSettingValue = aPropArg.Value;
444 : : }
445 : 0 : else if ( *pArgument >>= aPairArg )
446 : : {
447 : 0 : if ( aPairArg.Name.isEmpty())
448 : 0 : continue;
449 : :
450 : 0 : sSettingName = aPairArg.Name;
451 : 0 : aSettingValue = aPairArg.Value;
452 : :
453 : :
454 : : }
455 : : else
456 : : {
457 : : OSL_FAIL(
458 : : ( ::rtl::OString( "OCommonPicker::initialize: unknown argument type at position " )
459 : : += ::rtl::OString::valueOf( (sal_Int32)( pArguments - _rArguments.getConstArray() ) )
460 : : ).getStr()
461 : : );
462 : 0 : continue;
463 : : }
464 : :
465 : : #ifdef DBG_UTIL
466 : : sal_Bool bKnownSetting =
467 : : #endif
468 : 0 : implHandleInitializationArgument( sSettingName, aSettingValue );
469 : : DBG_ASSERT( bKnownSetting,
470 : : ( ::rtl::OString( "OCommonPicker::initialize: unknown argument \"" )
471 : : += ::rtl::OString( sSettingName.getStr(), sSettingName.getLength(), osl_getThreadTextEncoding() )
472 : : += ::rtl::OString( "\"!" )
473 : : ).getStr()
474 : : );
475 : 0 : }
476 : 0 : }
477 : :
478 : : //---------------------------------------------------------------------
479 : 0 : sal_Bool OCommonPicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) )
480 : : {
481 : 0 : sal_Bool bKnown = sal_True;
482 : 0 : if ( _rName == "ParentWindow" )
483 : : {
484 : 0 : m_xDialogParent.clear();
485 : 0 : OSL_VERIFY( _rValue >>= m_xDialogParent );
486 : : OSL_ENSURE( VCLUnoHelper::GetWindow( m_xDialogParent ), "OCommonPicker::implHandleInitializationArgument: invalid parent window given!" );
487 : : }
488 : : else
489 : 0 : bKnown = sal_False;
490 : 0 : return bKnown;
491 : : }
492 : :
493 : : //.........................................................................
494 : : } // namespace svt
495 : : //.........................................................................
496 : :
497 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|