1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svtools.hxx" 26 27 #include "svtools/genericunodialog.hxx" 28 29 #include <com/sun/star/beans/NamedValue.hpp> 30 #include <com/sun/star/ucb/AlreadyInitializedException.hpp> 31 32 #include <toolkit/awt/vclxwindow.hxx> 33 #include <comphelper/extract.hxx> 34 #include <cppuhelper/typeprovider.hxx> 35 #include <comphelper/property.hxx> 36 #include <osl/diagnose.h> 37 #include <tools/diagnose_ex.h> 38 #include <vcl/msgbox.hxx> 39 #include <vos/mutex.hxx> 40 #include <vcl/svapp.hxx> 41 42 using namespace ::comphelper; 43 using namespace ::com::sun::star::uno; 44 using namespace ::com::sun::star::lang; 45 using namespace ::com::sun::star::beans; 46 using namespace ::com::sun::star::ucb; 47 48 //......................................................................... 49 namespace svt 50 { 51 //......................................................................... 52 53 //========================================================================= 54 //------------------------------------------------------------------------- 55 OGenericUnoDialog::OGenericUnoDialog(const Reference< XMultiServiceFactory >& _rxORB) 56 :OPropertyContainer(GetBroadcastHelper()) 57 ,m_pDialog(NULL) 58 ,m_bExecuting(sal_False) 59 ,m_bCanceled(sal_False) 60 ,m_bTitleAmbiguous(sal_True) 61 ,m_bInitialized( false ) 62 ,m_bNeedInitialization( false ) 63 ,m_aContext( _rxORB ) 64 { 65 registerProperty(::rtl::OUString::createFromAscii(UNODIALOG_PROPERTY_TITLE), UNODIALOG_PROPERTY_ID_TITLE, PropertyAttribute::TRANSIENT, 66 &m_sTitle, getCppuType(&m_sTitle)); 67 registerProperty(::rtl::OUString::createFromAscii(UNODIALOG_PROPERTY_PARENT), UNODIALOG_PROPERTY_ID_PARENT, PropertyAttribute::TRANSIENT, 68 &m_xParent, getCppuType(&m_xParent)); 69 } 70 71 //------------------------------------------------------------------------- 72 OGenericUnoDialog::OGenericUnoDialog(const Reference< XComponentContext >& _rxContext) 73 :OPropertyContainer(GetBroadcastHelper()) 74 ,m_pDialog(NULL) 75 ,m_bExecuting(sal_False) 76 ,m_bCanceled(sal_False) 77 ,m_bTitleAmbiguous(sal_True) 78 ,m_bInitialized( false ) 79 ,m_bNeedInitialization( false ) 80 ,m_aContext(_rxContext) 81 { 82 registerProperty(::rtl::OUString::createFromAscii(UNODIALOG_PROPERTY_TITLE), UNODIALOG_PROPERTY_ID_TITLE, PropertyAttribute::TRANSIENT, 83 &m_sTitle, getCppuType(&m_sTitle)); 84 registerProperty(::rtl::OUString::createFromAscii(UNODIALOG_PROPERTY_PARENT), UNODIALOG_PROPERTY_ID_PARENT, PropertyAttribute::TRANSIENT, 85 &m_xParent, getCppuType(&m_xParent)); 86 } 87 88 //------------------------------------------------------------------------- 89 OGenericUnoDialog::~OGenericUnoDialog() 90 { 91 if ( m_pDialog ) 92 { 93 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 94 ::osl::MutexGuard aGuard( m_aMutex ); 95 if ( m_pDialog ) 96 destroyDialog(); 97 } 98 } 99 100 //------------------------------------------------------------------------- 101 Any SAL_CALL OGenericUnoDialog::queryInterface(const Type& _rType) throw (RuntimeException) 102 { 103 Any aReturn = OGenericUnoDialogBase::queryInterface(_rType); 104 105 if (!aReturn.hasValue()) 106 aReturn = ::cppu::queryInterface(_rType 107 ,static_cast<XPropertySet*>(this) 108 ,static_cast<XMultiPropertySet*>(this) 109 ,static_cast<XFastPropertySet*>(this) 110 ); 111 112 return aReturn; 113 } 114 115 //------------------------------------------------------------------------- 116 Sequence<Type> SAL_CALL OGenericUnoDialog::getTypes( ) throw(RuntimeException) 117 { 118 return ::comphelper::concatSequences( 119 OGenericUnoDialogBase::getTypes(), 120 ::comphelper::OPropertyContainer::getTypes() 121 ); 122 } 123 124 //------------------------------------------------------------------------- 125 Sequence<sal_Int8> SAL_CALL OGenericUnoDialog::getImplementationId( ) throw(RuntimeException) 126 { 127 static ::cppu::OImplementationId aId; 128 return aId.getImplementationId(); 129 } 130 131 //------------------------------------------------------------------------- 132 sal_Bool SAL_CALL OGenericUnoDialog::supportsService(const ::rtl::OUString& ServiceName) throw(RuntimeException) 133 { 134 Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames()); 135 const ::rtl::OUString* pArray = aSupported.getConstArray(); 136 for (sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray) 137 if (pArray->equals(ServiceName)) 138 return sal_True; 139 return sal_False; 140 } 141 142 //------------------------------------------------------------------------- 143 void OGenericUnoDialog::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw(Exception) 144 { 145 // TODO : need some handling if we're currently executing ... 146 147 OPropertyContainer::setFastPropertyValue_NoBroadcast(nHandle, rValue); 148 149 if (UNODIALOG_PROPERTY_ID_TITLE == nHandle) 150 { 151 // from now on m_sTitle is valid 152 m_bTitleAmbiguous = sal_False; 153 154 if (m_pDialog) 155 m_pDialog->SetText(String(m_sTitle)); 156 } 157 } 158 159 //------------------------------------------------------------------------- 160 sal_Bool OGenericUnoDialog::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) throw(IllegalArgumentException) 161 { 162 switch (nHandle) 163 { 164 case UNODIALOG_PROPERTY_ID_PARENT: 165 { 166 Reference<starawt::XWindow> xNew; 167 ::cppu::extractInterface(xNew, rValue); 168 if (xNew != m_xParent) 169 { 170 rConvertedValue <<= xNew; 171 rOldValue <<= m_xParent; 172 return sal_True; 173 } 174 return sal_False; 175 } 176 } 177 return OPropertyContainer::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); 178 } 179 180 //------------------------------------------------------------------------- 181 void SAL_CALL OGenericUnoDialog::setTitle( const ::rtl::OUString& _rTitle ) throw(RuntimeException) 182 { 183 UnoDialogEntryGuard aGuard( *this ); 184 185 try 186 { 187 setPropertyValue(::rtl::OUString::createFromAscii(UNODIALOG_PROPERTY_TITLE), makeAny(_rTitle)); 188 } 189 catch(RuntimeException&) 190 { 191 // allowed to pass 192 throw; 193 } 194 catch( const Exception& ) 195 { 196 DBG_UNHANDLED_EXCEPTION(); 197 // not allowed to pass 198 } 199 } 200 201 //------------------------------------------------------------------------- 202 bool OGenericUnoDialog::impl_ensureDialog_lck() 203 { 204 if ( m_pDialog ) 205 return true; 206 207 // get the parameters for the dialog from the current settings 208 209 // the parent window 210 Window* pParent = NULL; 211 VCLXWindow* pImplementation = VCLXWindow::GetImplementation(m_xParent); 212 if (pImplementation) 213 pParent = pImplementation->GetWindow(); 214 215 // the title 216 String sTitle = m_sTitle; 217 218 Dialog* pDialog = createDialog( pParent ); 219 OSL_ENSURE( pDialog, "OGenericUnoDialog::impl_ensureDialog_lck: createDialog returned nonsense!" ); 220 if ( !pDialog ) 221 return false; 222 223 // do some initialisations 224 if ( !m_bTitleAmbiguous ) 225 pDialog->SetText( sTitle ); 226 227 // be notified when the dialog is killed by somebody else 228 // #i65958# / 2006-07-07 / frank.schoenheit@sun.com 229 pDialog->AddEventListener( LINK( this, OGenericUnoDialog, OnDialogDying ) ); 230 231 m_pDialog = pDialog; 232 233 return true; 234 } 235 236 //------------------------------------------------------------------------- 237 sal_Int16 SAL_CALL OGenericUnoDialog::execute( ) throw(RuntimeException) 238 { 239 // both creation and execution of the dialog must be guarded with the SolarMutex, so be generous here 240 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 241 242 Dialog* pDialogToExecute = NULL; 243 // create the dialog, if neccessary 244 { 245 UnoDialogEntryGuard aGuard( *this ); 246 247 if (m_bExecuting) 248 throw RuntimeException( 249 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "already executing the dialog (recursive call)" ) ), 250 *this 251 ); 252 253 m_bCanceled = sal_False; 254 m_bExecuting = sal_True; 255 256 if ( !impl_ensureDialog_lck() ) 257 return 0; 258 259 pDialogToExecute = m_pDialog; 260 } 261 262 // start execution 263 sal_Int16 nReturn(0); 264 if ( pDialogToExecute ) 265 nReturn = pDialogToExecute->Execute(); 266 267 { 268 ::osl::MutexGuard aExecutionGuard(m_aExecutionMutex); 269 if (m_bCanceled) 270 nReturn = RET_CANCEL; 271 } 272 273 { 274 ::osl::MutexGuard aGuard(m_aMutex); 275 276 // get the settings of the dialog 277 executedDialog( nReturn ); 278 279 m_bExecuting = sal_False; 280 } 281 282 // outta here 283 return nReturn; 284 } 285 286 #ifdef AWT_DIALOG 287 //------------------------------------------------------------------------- 288 void SAL_CALL OGenericUnoDialog::endExecute( ) throw(RuntimeException) 289 { 290 UnoDialogEntryGuard aGuard( *this ); 291 if (!m_bExecuting) 292 throw RuntimeException(); 293 294 { 295 ::osl::MutexGuard aExecutionGuard(m_aExecutionMutex); 296 OSL_ENSURE(m_pDialog, "OGenericUnoDialog::endExecute : executing which dialog ?"); 297 // m_bExecuting is true but we have no dialog ? 298 if (!m_pDialog) 299 throw RuntimeException(); 300 301 if (!m_pDialog->IsInExecute()) 302 // we tighly missed it ... another thread finished the execution of the dialog, 303 // but did not manage it to reset m_bExecuting, it currently tries to acquire 304 // m_aMutex or m_aExecutionMutex 305 // => nothing to do 306 return; 307 308 m_pDialog->EndDialog(RET_CANCEL); 309 m_bCanceled = sal_True; 310 } 311 } 312 #endif 313 314 //------------------------------------------------------------------------- 315 void OGenericUnoDialog::implInitialize(const Any& _rValue) 316 { 317 try 318 { 319 PropertyValue aProperty; 320 NamedValue aValue; 321 if ( _rValue >>= aProperty ) 322 { 323 setPropertyValue( aProperty.Name, aProperty.Value ); 324 } 325 else if ( _rValue >>= aValue ) 326 { 327 setPropertyValue( aValue.Name, aValue.Value ); 328 } 329 } 330 catch(const Exception&) 331 { 332 DBG_UNHANDLED_EXCEPTION(); 333 } 334 } 335 336 //------------------------------------------------------------------------- 337 void SAL_CALL OGenericUnoDialog::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException) 338 { 339 ::osl::MutexGuard aGuard( m_aMutex ); 340 if ( m_bInitialized ) 341 throw AlreadyInitializedException( ::rtl::OUString(), *this ); 342 343 const Any* pArguments = aArguments.getConstArray(); 344 for (sal_Int32 i=0; i<aArguments.getLength(); ++i, ++pArguments) 345 implInitialize(*pArguments); 346 347 m_bInitialized = true; 348 } 349 350 //------------------------------------------------------------------------- 351 void OGenericUnoDialog::destroyDialog() 352 { 353 delete m_pDialog; 354 m_pDialog = NULL; 355 } 356 357 //------------------------------------------------------------------------- 358 IMPL_LINK( OGenericUnoDialog, OnDialogDying, VclWindowEvent*, _pEvent ) 359 { 360 OSL_ENSURE( _pEvent->GetWindow() == m_pDialog, "OGenericUnoDialog::OnDialogDying: where does this come from?" ); 361 if ( _pEvent->GetId() == VCLEVENT_OBJECT_DYING ) 362 m_pDialog = NULL; 363 return 0L; 364 } 365 366 //......................................................................... 367 } // namespace svt 368 //......................................................................... 369 370