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_svx.hxx" 26 27 #include "formfeaturedispatcher.hxx" 28 29 #include <comphelper/namedvaluecollection.hxx> 30 #include <tools/diagnose_ex.h> 31 32 //........................................................................ 33 namespace svx 34 { 35 //........................................................................ 36 37 using namespace ::com::sun::star::uno; 38 using namespace ::com::sun::star::lang; 39 using namespace ::com::sun::star::frame; 40 using namespace ::com::sun::star::beans; 41 using namespace ::com::sun::star::util; 42 using namespace ::com::sun::star::form::runtime; 43 44 //==================================================================== 45 //= OSingleFeatureDispatcher 46 //==================================================================== 47 //-------------------------------------------------------------------- OSingleFeatureDispatcher(const URL & _rFeatureURL,const sal_Int16 _nFormFeature,const Reference<XFormOperations> & _rxFormOperations,::osl::Mutex & _rMutex)48 OSingleFeatureDispatcher::OSingleFeatureDispatcher( const URL& _rFeatureURL, const sal_Int16 _nFormFeature, 49 const Reference< XFormOperations >& _rxFormOperations, ::osl::Mutex& _rMutex ) 50 :m_rMutex( _rMutex ) 51 ,m_aStatusListeners( _rMutex ) 52 ,m_xFormOperations( _rxFormOperations ) 53 ,m_aFeatureURL( _rFeatureURL ) 54 ,m_nFormFeature( _nFormFeature ) 55 ,m_bLastKnownEnabled( sal_False ) 56 ,m_bDisposed( sal_False ) 57 { 58 } 59 60 //-------------------------------------------------------------------- dispose()61 void OSingleFeatureDispatcher::dispose() 62 { 63 { 64 ::osl::MutexGuard aGuard( m_rMutex ); 65 if ( m_bDisposed ) 66 return; 67 } 68 69 EventObject aDisposeEvent( *this ); 70 m_aStatusListeners.disposeAndClear( aDisposeEvent ); 71 72 { 73 ::osl::MutexGuard aGuard( m_rMutex ); 74 m_bDisposed = sal_True; 75 } 76 } 77 78 //-------------------------------------------------------------------- getUnoState(FeatureStateEvent & _rState) const79 void OSingleFeatureDispatcher::getUnoState( FeatureStateEvent& /* [out] */ _rState ) const 80 { 81 _rState.Source = *const_cast< OSingleFeatureDispatcher* >( this ); 82 83 FeatureState aState( m_xFormOperations->getState( m_nFormFeature ) ); 84 85 _rState.FeatureURL = m_aFeatureURL; 86 _rState.IsEnabled = aState.Enabled; 87 _rState.Requery = sal_False; 88 _rState.State = aState.State; 89 } 90 91 //-------------------------------------------------------------------- updateAllListeners()92 void OSingleFeatureDispatcher::updateAllListeners() 93 { 94 ::osl::ClearableMutexGuard aGuard( m_rMutex ); 95 96 FeatureStateEvent aUnoState; 97 getUnoState( aUnoState ); 98 99 if ( ( m_aLastKnownState == aUnoState.State ) && ( m_bLastKnownEnabled == aUnoState.IsEnabled ) ) 100 return; 101 102 m_aLastKnownState = aUnoState.State; 103 m_bLastKnownEnabled = aUnoState.IsEnabled; 104 105 notifyStatus( NULL, aGuard ); 106 } 107 108 //-------------------------------------------------------------------- notifyStatus(const Reference<XStatusListener> & _rxListener,::osl::ClearableMutexGuard & _rFreeForNotification)109 void OSingleFeatureDispatcher::notifyStatus( const Reference< XStatusListener >& _rxListener, ::osl::ClearableMutexGuard& _rFreeForNotification ) 110 { 111 FeatureStateEvent aUnoState; 112 getUnoState( aUnoState ); 113 114 if ( _rxListener.is() ) 115 { 116 try 117 { 118 _rFreeForNotification.clear(); 119 _rxListener->statusChanged( aUnoState ); 120 } 121 catch( const Exception& ) 122 { 123 OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught an exception!" ); 124 } 125 } 126 else 127 { 128 ::cppu::OInterfaceIteratorHelper aIter( m_aStatusListeners ); 129 _rFreeForNotification.clear(); 130 131 while ( aIter.hasMoreElements() ) 132 { 133 try 134 { 135 static_cast< XStatusListener* >( aIter.next() )->statusChanged( aUnoState ); 136 } 137 catch( const DisposedException& ) 138 { 139 OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught a DisposedException - removing the listener!" ); 140 aIter.remove( ); 141 } 142 catch( const Exception& ) 143 { 144 OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught a generic exception while notifying a single listener!" ); 145 } 146 } 147 } 148 } 149 150 //-------------------------------------------------------------------- dispatch(const URL & _rURL,const Sequence<PropertyValue> & _rArguments)151 void SAL_CALL OSingleFeatureDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException) 152 { 153 ::osl::ClearableMutexGuard aGuard( m_rMutex ); 154 checkAlive(); 155 156 OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::dispatch: not responsible for this URL!" ); 157 (void)_rURL; 158 159 if ( !m_xFormOperations->isEnabled( m_nFormFeature ) ) 160 return; 161 162 // release our mutex before executing the command 163 sal_Int16 nFormFeature( m_nFormFeature ); 164 Reference< XFormOperations > xFormOperations( m_xFormOperations ); 165 aGuard.clear(); 166 167 try 168 { 169 if ( !_rArguments.getLength() ) 170 { 171 xFormOperations->execute( nFormFeature ); 172 } 173 else 174 { // at the moment we only support one parameter 175 ::comphelper::NamedValueCollection aArgs( _rArguments ); 176 xFormOperations->executeWithArguments( nFormFeature, aArgs.getNamedValues() ); 177 } 178 } 179 catch( const RuntimeException& ) 180 { 181 throw; 182 } 183 catch( const Exception& ) 184 { 185 DBG_UNHANDLED_EXCEPTION(); 186 } 187 } 188 189 //-------------------------------------------------------------------- addStatusListener(const Reference<XStatusListener> & _rxControl,const URL & _rURL)190 void SAL_CALL OSingleFeatureDispatcher::addStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException) 191 { 192 (void)_rURL; 193 OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::addStatusListener: unexpected URL!" ); 194 OSL_ENSURE( _rxControl.is(), "OSingleFeatureDispatcher::addStatusListener: senseless call!" ); 195 if ( !_rxControl.is() ) 196 return; 197 198 ::osl::ClearableMutexGuard aGuard( m_rMutex ); 199 if ( m_bDisposed ) 200 { 201 EventObject aDisposeEvent( *this ); 202 aGuard.clear(); 203 _rxControl->disposing( aDisposeEvent ); 204 return; 205 } 206 207 m_aStatusListeners.addInterface( _rxControl ); 208 209 // initially update the status 210 notifyStatus( _rxControl, aGuard ); 211 } 212 213 //-------------------------------------------------------------------- removeStatusListener(const Reference<XStatusListener> & _rxControl,const URL & _rURL)214 void SAL_CALL OSingleFeatureDispatcher::removeStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException) 215 { 216 (void)_rURL; 217 OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::removeStatusListener: unexpected URL!" ); 218 OSL_ENSURE( _rxControl.is(), "OSingleFeatureDispatcher::removeStatusListener: senseless call!" ); 219 if ( !_rxControl.is() ) 220 return; 221 222 ::osl::MutexGuard aGuard( m_rMutex ); 223 checkAlive(); 224 225 m_aStatusListeners.removeInterface( _rxControl ); 226 } 227 228 //-------------------------------------------------------------------- checkAlive() const229 void OSingleFeatureDispatcher::checkAlive() const SAL_THROW((DisposedException)) 230 { 231 if ( m_bDisposed ) 232 throw DisposedException( ::rtl::OUString(), *const_cast< OSingleFeatureDispatcher* >( this ) ); 233 } 234 235 //........................................................................ 236 } // namespace svx 237 //........................................................................ 238