1*f6e50924SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*f6e50924SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*f6e50924SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*f6e50924SAndrew Rist  * distributed with this work for additional information
6*f6e50924SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*f6e50924SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*f6e50924SAndrew Rist  * "License"); you may not use this file except in compliance
9*f6e50924SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*f6e50924SAndrew Rist  *
11*f6e50924SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*f6e50924SAndrew Rist  *
13*f6e50924SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*f6e50924SAndrew Rist  * software distributed under the License is distributed on an
15*f6e50924SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*f6e50924SAndrew Rist  * KIND, either express or implied.  See the License for the
17*f6e50924SAndrew Rist  * specific language governing permissions and limitations
18*f6e50924SAndrew Rist  * under the License.
19*f6e50924SAndrew Rist  *
20*f6e50924SAndrew Rist  *************************************************************/
21*f6e50924SAndrew Rist 
22*f6e50924SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svx.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "formfeaturedispatcher.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <comphelper/namedvaluecollection.hxx>
30cdf0e10cSrcweir #include <tools/diagnose_ex.h>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir //........................................................................
33cdf0e10cSrcweir namespace svx
34cdf0e10cSrcweir {
35cdf0e10cSrcweir //........................................................................
36cdf0e10cSrcweir 
37cdf0e10cSrcweir     using namespace ::com::sun::star::uno;
38cdf0e10cSrcweir     using namespace ::com::sun::star::lang;
39cdf0e10cSrcweir     using namespace ::com::sun::star::frame;
40cdf0e10cSrcweir     using namespace ::com::sun::star::beans;
41cdf0e10cSrcweir     using namespace ::com::sun::star::util;
42cdf0e10cSrcweir     using namespace ::com::sun::star::form::runtime;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir     //====================================================================
45cdf0e10cSrcweir     //= OSingleFeatureDispatcher
46cdf0e10cSrcweir     //====================================================================
47cdf0e10cSrcweir     //--------------------------------------------------------------------
OSingleFeatureDispatcher(const URL & _rFeatureURL,const sal_Int16 _nFormFeature,const Reference<XFormOperations> & _rxFormOperations,::osl::Mutex & _rMutex)48cdf0e10cSrcweir     OSingleFeatureDispatcher::OSingleFeatureDispatcher( const URL& _rFeatureURL, const sal_Int16 _nFormFeature,
49cdf0e10cSrcweir             const Reference< XFormOperations >& _rxFormOperations, ::osl::Mutex& _rMutex )
50cdf0e10cSrcweir         :m_rMutex( _rMutex )
51cdf0e10cSrcweir         ,m_aStatusListeners( _rMutex )
52cdf0e10cSrcweir         ,m_xFormOperations( _rxFormOperations )
53cdf0e10cSrcweir         ,m_aFeatureURL( _rFeatureURL )
54cdf0e10cSrcweir         ,m_nFormFeature( _nFormFeature )
55cdf0e10cSrcweir         ,m_bLastKnownEnabled( sal_False )
56cdf0e10cSrcweir         ,m_bDisposed( sal_False )
57cdf0e10cSrcweir     {
58cdf0e10cSrcweir     }
59cdf0e10cSrcweir 
60cdf0e10cSrcweir     //--------------------------------------------------------------------
dispose()61cdf0e10cSrcweir     void OSingleFeatureDispatcher::dispose()
62cdf0e10cSrcweir     {
63cdf0e10cSrcweir         {
64cdf0e10cSrcweir             ::osl::MutexGuard aGuard( m_rMutex );
65cdf0e10cSrcweir             if ( m_bDisposed )
66cdf0e10cSrcweir                 return;
67cdf0e10cSrcweir         }
68cdf0e10cSrcweir 
69cdf0e10cSrcweir         EventObject aDisposeEvent( *this );
70cdf0e10cSrcweir         m_aStatusListeners.disposeAndClear( aDisposeEvent );
71cdf0e10cSrcweir 
72cdf0e10cSrcweir         {
73cdf0e10cSrcweir             ::osl::MutexGuard aGuard( m_rMutex );
74cdf0e10cSrcweir             m_bDisposed = sal_True;
75cdf0e10cSrcweir         }
76cdf0e10cSrcweir     }
77cdf0e10cSrcweir 
78cdf0e10cSrcweir     //--------------------------------------------------------------------
getUnoState(FeatureStateEvent & _rState) const79cdf0e10cSrcweir     void OSingleFeatureDispatcher::getUnoState( FeatureStateEvent& /* [out] */ _rState ) const
80cdf0e10cSrcweir     {
81cdf0e10cSrcweir         _rState.Source = *const_cast< OSingleFeatureDispatcher* >( this );
82cdf0e10cSrcweir 
83cdf0e10cSrcweir         FeatureState aState( m_xFormOperations->getState( m_nFormFeature ) );
84cdf0e10cSrcweir 
85cdf0e10cSrcweir         _rState.FeatureURL = m_aFeatureURL;
86cdf0e10cSrcweir         _rState.IsEnabled = aState.Enabled;
87cdf0e10cSrcweir         _rState.Requery = sal_False;
88cdf0e10cSrcweir         _rState.State = aState.State;
89cdf0e10cSrcweir     }
90cdf0e10cSrcweir 
91cdf0e10cSrcweir     //--------------------------------------------------------------------
updateAllListeners()92cdf0e10cSrcweir     void OSingleFeatureDispatcher::updateAllListeners()
93cdf0e10cSrcweir     {
94cdf0e10cSrcweir         ::osl::ClearableMutexGuard aGuard( m_rMutex );
95cdf0e10cSrcweir 
96cdf0e10cSrcweir         FeatureStateEvent aUnoState;
97cdf0e10cSrcweir         getUnoState( aUnoState );
98cdf0e10cSrcweir 
99cdf0e10cSrcweir         if ( ( m_aLastKnownState == aUnoState.State ) && ( m_bLastKnownEnabled == aUnoState.IsEnabled ) )
100cdf0e10cSrcweir             return;
101cdf0e10cSrcweir 
102cdf0e10cSrcweir         m_aLastKnownState = aUnoState.State;
103cdf0e10cSrcweir         m_bLastKnownEnabled = aUnoState.IsEnabled;
104cdf0e10cSrcweir 
105cdf0e10cSrcweir         notifyStatus( NULL, aGuard );
106cdf0e10cSrcweir     }
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     //--------------------------------------------------------------------
notifyStatus(const Reference<XStatusListener> & _rxListener,::osl::ClearableMutexGuard & _rFreeForNotification)109cdf0e10cSrcweir     void OSingleFeatureDispatcher::notifyStatus( const Reference< XStatusListener >& _rxListener, ::osl::ClearableMutexGuard& _rFreeForNotification )
110cdf0e10cSrcweir     {
111cdf0e10cSrcweir         FeatureStateEvent aUnoState;
112cdf0e10cSrcweir         getUnoState( aUnoState );
113cdf0e10cSrcweir 
114cdf0e10cSrcweir         if ( _rxListener.is() )
115cdf0e10cSrcweir         {
116cdf0e10cSrcweir             try
117cdf0e10cSrcweir             {
118cdf0e10cSrcweir                 _rFreeForNotification.clear();
119cdf0e10cSrcweir                 _rxListener->statusChanged( aUnoState );
120cdf0e10cSrcweir             }
121cdf0e10cSrcweir             catch( const Exception& )
122cdf0e10cSrcweir             {
123cdf0e10cSrcweir                 OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught an exception!" );
124cdf0e10cSrcweir             }
125cdf0e10cSrcweir         }
126cdf0e10cSrcweir         else
127cdf0e10cSrcweir         {
128cdf0e10cSrcweir             ::cppu::OInterfaceIteratorHelper aIter( m_aStatusListeners );
129cdf0e10cSrcweir             _rFreeForNotification.clear();
130cdf0e10cSrcweir 
131cdf0e10cSrcweir             while ( aIter.hasMoreElements() )
132cdf0e10cSrcweir             {
133cdf0e10cSrcweir                 try
134cdf0e10cSrcweir                 {
135cdf0e10cSrcweir                     static_cast< XStatusListener* >( aIter.next() )->statusChanged( aUnoState );
136cdf0e10cSrcweir                 }
137cdf0e10cSrcweir                 catch( const DisposedException& )
138cdf0e10cSrcweir                 {
139cdf0e10cSrcweir                     OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught a DisposedException - removing the listener!" );
140cdf0e10cSrcweir                     aIter.remove( );
141cdf0e10cSrcweir                 }
142cdf0e10cSrcweir                 catch( const Exception& )
143cdf0e10cSrcweir                 {
144cdf0e10cSrcweir                     OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught a generic exception while notifying a single listener!" );
145cdf0e10cSrcweir                 }
146cdf0e10cSrcweir             }
147cdf0e10cSrcweir         }
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     //--------------------------------------------------------------------
dispatch(const URL & _rURL,const Sequence<PropertyValue> & _rArguments)151cdf0e10cSrcweir     void SAL_CALL OSingleFeatureDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException)
152cdf0e10cSrcweir     {
153cdf0e10cSrcweir         ::osl::ClearableMutexGuard aGuard( m_rMutex );
154cdf0e10cSrcweir         checkAlive();
155cdf0e10cSrcweir 
156cdf0e10cSrcweir         OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::dispatch: not responsible for this URL!" );
157cdf0e10cSrcweir         (void)_rURL;
158cdf0e10cSrcweir 
159cdf0e10cSrcweir         if ( !m_xFormOperations->isEnabled( m_nFormFeature ) )
160cdf0e10cSrcweir             return;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir         // release our mutex before executing the command
163cdf0e10cSrcweir         sal_Int16 nFormFeature( m_nFormFeature );
164cdf0e10cSrcweir         Reference< XFormOperations > xFormOperations( m_xFormOperations );
165cdf0e10cSrcweir         aGuard.clear();
166cdf0e10cSrcweir 
167cdf0e10cSrcweir         try
168cdf0e10cSrcweir         {
169cdf0e10cSrcweir             if ( !_rArguments.getLength() )
170cdf0e10cSrcweir             {
171cdf0e10cSrcweir                 xFormOperations->execute( nFormFeature );
172cdf0e10cSrcweir             }
173cdf0e10cSrcweir             else
174cdf0e10cSrcweir             {   // at the moment we only support one parameter
175cdf0e10cSrcweir                 ::comphelper::NamedValueCollection aArgs( _rArguments );
176cdf0e10cSrcweir                 xFormOperations->executeWithArguments( nFormFeature, aArgs.getNamedValues() );
177cdf0e10cSrcweir             }
178cdf0e10cSrcweir         }
179cdf0e10cSrcweir         catch( const RuntimeException& )
180cdf0e10cSrcweir         {
181cdf0e10cSrcweir             throw;
182cdf0e10cSrcweir         }
183cdf0e10cSrcweir         catch( const Exception& )
184cdf0e10cSrcweir         {
185cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
186cdf0e10cSrcweir         }
187cdf0e10cSrcweir     }
188cdf0e10cSrcweir 
189cdf0e10cSrcweir     //--------------------------------------------------------------------
addStatusListener(const Reference<XStatusListener> & _rxControl,const URL & _rURL)190cdf0e10cSrcweir     void SAL_CALL OSingleFeatureDispatcher::addStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException)
191cdf0e10cSrcweir     {
192cdf0e10cSrcweir         (void)_rURL;
193cdf0e10cSrcweir         OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::addStatusListener: unexpected URL!" );
194cdf0e10cSrcweir         OSL_ENSURE( _rxControl.is(), "OSingleFeatureDispatcher::addStatusListener: senseless call!" );
195cdf0e10cSrcweir         if ( !_rxControl.is() )
196cdf0e10cSrcweir             return;
197cdf0e10cSrcweir 
198cdf0e10cSrcweir         ::osl::ClearableMutexGuard aGuard( m_rMutex );
199cdf0e10cSrcweir         if ( m_bDisposed )
200cdf0e10cSrcweir         {
201cdf0e10cSrcweir             EventObject aDisposeEvent( *this );
202cdf0e10cSrcweir             aGuard.clear();
203cdf0e10cSrcweir             _rxControl->disposing( aDisposeEvent );
204cdf0e10cSrcweir             return;
205cdf0e10cSrcweir         }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir         m_aStatusListeners.addInterface( _rxControl );
208cdf0e10cSrcweir 
209cdf0e10cSrcweir         // initially update the status
210cdf0e10cSrcweir         notifyStatus( _rxControl, aGuard );
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir     //--------------------------------------------------------------------
removeStatusListener(const Reference<XStatusListener> & _rxControl,const URL & _rURL)214cdf0e10cSrcweir     void SAL_CALL OSingleFeatureDispatcher::removeStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException)
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         (void)_rURL;
217cdf0e10cSrcweir         OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::removeStatusListener: unexpected URL!" );
218cdf0e10cSrcweir         OSL_ENSURE( _rxControl.is(), "OSingleFeatureDispatcher::removeStatusListener: senseless call!" );
219cdf0e10cSrcweir         if ( !_rxControl.is() )
220cdf0e10cSrcweir             return;
221cdf0e10cSrcweir 
222cdf0e10cSrcweir         ::osl::MutexGuard aGuard( m_rMutex );
223cdf0e10cSrcweir         checkAlive();
224cdf0e10cSrcweir 
225cdf0e10cSrcweir         m_aStatusListeners.removeInterface( _rxControl );
226cdf0e10cSrcweir     }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     //--------------------------------------------------------------------
checkAlive() const229cdf0e10cSrcweir     void OSingleFeatureDispatcher::checkAlive() const SAL_THROW((DisposedException))
230cdf0e10cSrcweir     {
231cdf0e10cSrcweir         if ( m_bDisposed )
232cdf0e10cSrcweir             throw DisposedException( ::rtl::OUString(), *const_cast< OSingleFeatureDispatcher* >( this ) );
233cdf0e10cSrcweir     }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir //........................................................................
236cdf0e10cSrcweir }   // namespace svx
237cdf0e10cSrcweir //........................................................................
238