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