Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "formnavigation.hxx"
30 : : #include "urltransformer.hxx"
31 : : #include "controlfeatureinterception.hxx"
32 : : #include "frm_strings.hxx"
33 : :
34 : : #include <com/sun/star/form/runtime/FormFeature.hpp>
35 : :
36 : : #include <tools/debug.hxx>
37 : :
38 : :
39 : : //.........................................................................
40 : : namespace frm
41 : : {
42 : : //.........................................................................
43 : :
44 : : using namespace ::com::sun::star::uno;
45 : : using namespace ::com::sun::star::beans;
46 : : using namespace ::com::sun::star::lang;
47 : : using namespace ::com::sun::star::util;
48 : : using namespace ::com::sun::star::frame;
49 : : namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
50 : :
51 : : //==================================================================
52 : : //= OFormNavigationHelper
53 : : //==================================================================
54 : : DBG_NAME( OFormNavigationHelper )
55 : : //------------------------------------------------------------------
56 : 113 : OFormNavigationHelper::OFormNavigationHelper( const Reference< XMultiServiceFactory >& _rxORB )
57 : : :m_xORB( _rxORB )
58 [ + - ]: 113 : ,m_nConnectedFeatures( 0 )
59 : : {
60 : : DBG_CTOR( OFormNavigationHelper, NULL );
61 [ + - ][ + - ]: 113 : m_pFeatureInterception.reset( new ControlFeatureInterception( m_xORB ) );
62 : 113 : }
63 : :
64 : : //------------------------------------------------------------------
65 [ + - ]: 113 : OFormNavigationHelper::~OFormNavigationHelper()
66 : : {
67 : : DBG_DTOR( OFormNavigationHelper, NULL );
68 [ - + ]: 113 : }
69 : :
70 : : //------------------------------------------------------------------
71 : 149 : void SAL_CALL OFormNavigationHelper::dispose( ) throw( RuntimeException )
72 : : {
73 : 149 : m_pFeatureInterception->dispose();
74 : 149 : disconnectDispatchers();
75 : 149 : }
76 : :
77 : : //------------------------------------------------------------------
78 : 36 : void OFormNavigationHelper::interceptorsChanged( )
79 : : {
80 : 36 : updateDispatches();
81 : 36 : }
82 : :
83 : : //------------------------------------------------------------------
84 : 0 : void OFormNavigationHelper::featureStateChanged( sal_Int16 /*_nFeatureId*/, sal_Bool /*_bEnabled*/ )
85 : : {
86 : : // not interested in
87 : 0 : }
88 : :
89 : : //------------------------------------------------------------------
90 : 579 : void OFormNavigationHelper::allFeatureStatesChanged( )
91 : : {
92 : : // not interested in
93 : 579 : }
94 : :
95 : : //------------------------------------------------------------------
96 : 18 : void SAL_CALL OFormNavigationHelper::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
97 : : {
98 : 18 : m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor );
99 : 18 : interceptorsChanged();
100 : 18 : }
101 : :
102 : : //------------------------------------------------------------------
103 : 18 : void SAL_CALL OFormNavigationHelper::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
104 : : {
105 : 18 : m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor );
106 : 18 : interceptorsChanged();
107 : 18 : }
108 : :
109 : : //------------------------------------------------------------------
110 : 0 : void SAL_CALL OFormNavigationHelper::statusChanged( const FeatureStateEvent& _rState ) throw (RuntimeException)
111 : : {
112 [ # # ]: 0 : for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin();
113 : 0 : aFeature != m_aSupportedFeatures.end();
114 : : ++aFeature
115 : : )
116 : : {
117 [ # # ]: 0 : if ( aFeature->second.aURL.Main == _rState.FeatureURL.Main )
118 : : {
119 [ # # # # ]: 0 : if ( ( aFeature->second.bCachedState != _rState.IsEnabled )
[ # # ]
120 : 0 : || ( aFeature->second.aCachedAdditionalState != _rState.State )
121 : : )
122 : : {
123 : : // change the cached state
124 : 0 : aFeature->second.bCachedState = _rState.IsEnabled;
125 : 0 : aFeature->second.aCachedAdditionalState = _rState.State;
126 : : // tell derivees what happened
127 [ # # ]: 0 : featureStateChanged( aFeature->first, _rState.IsEnabled );
128 : : }
129 : 0 : return;
130 : : }
131 : : }
132 : :
133 : : // unreachable
134 : : OSL_FAIL( "OFormNavigationHelper::statusChanged: huh? An invalid/unknown URL?" );
135 : : }
136 : :
137 : : //------------------------------------------------------------------
138 : 259 : void SAL_CALL OFormNavigationHelper::disposing( const EventObject& _rSource ) throw (RuntimeException)
139 : : {
140 : : // was it one of our external dispatchers?
141 [ - + ]: 259 : if ( m_nConnectedFeatures )
142 : : {
143 [ # # ]: 0 : for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin();
144 : 0 : aFeature != m_aSupportedFeatures.end();
145 : : ++aFeature
146 : : )
147 : : {
148 [ # # ][ # # ]: 0 : if ( aFeature->second.xDispatcher == _rSource.Source )
149 : : {
150 [ # # ][ # # ]: 0 : aFeature->second.xDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL );
[ # # ]
151 [ # # ]: 0 : aFeature->second.xDispatcher = NULL;
152 : 0 : aFeature->second.bCachedState = sal_False;
153 : 0 : aFeature->second.aCachedAdditionalState.clear();
154 : 0 : --m_nConnectedFeatures;
155 : :
156 [ # # ]: 0 : featureStateChanged( aFeature->first, sal_False );
157 : 0 : break;
158 : : }
159 : : }
160 : : }
161 : 259 : }
162 : :
163 : : //------------------------------------------------------------------
164 : 36 : void OFormNavigationHelper::updateDispatches()
165 : : {
166 [ + - ]: 36 : if ( !m_nConnectedFeatures )
167 : : { // we don't have any dispatchers yet -> do the initial connect
168 [ + - ]: 36 : connectDispatchers();
169 : 36 : return;
170 : : }
171 : :
172 [ # # ]: 0 : initializeSupportedFeatures();
173 : :
174 : 0 : m_nConnectedFeatures = 0;
175 : :
176 : 0 : Reference< XDispatch > xNewDispatcher;
177 : 0 : Reference< XDispatch > xCurrentDispatcher;
178 : :
179 [ # # ]: 0 : for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin();
180 : 0 : aFeature != m_aSupportedFeatures.end();
181 : : ++aFeature
182 : : )
183 : : {
184 [ # # ][ # # ]: 0 : xNewDispatcher = queryDispatch( aFeature->second.aURL );
185 [ # # ]: 0 : xCurrentDispatcher = aFeature->second.xDispatcher;
186 [ # # ][ # # ]: 0 : if ( xNewDispatcher != xCurrentDispatcher )
187 : : {
188 : : // the dispatcher for this particular URL changed
189 [ # # ]: 0 : if ( xCurrentDispatcher.is() )
190 [ # # ][ # # ]: 0 : xCurrentDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL );
[ # # ]
191 : :
192 [ # # ][ # # ]: 0 : xCurrentDispatcher = aFeature->second.xDispatcher = xNewDispatcher;
193 : :
194 [ # # ]: 0 : if ( xCurrentDispatcher.is() )
195 [ # # ][ # # ]: 0 : xCurrentDispatcher->addStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL );
[ # # ]
196 : : }
197 : :
198 [ # # ]: 0 : if ( xCurrentDispatcher.is() )
199 : 0 : ++m_nConnectedFeatures;
200 : : else
201 : 0 : aFeature->second.bCachedState = sal_False;
202 : : }
203 : :
204 : : // notify derivee that (potentially) all features changed their state
205 [ # # ]: 36 : allFeatureStatesChanged( );
206 : : }
207 : :
208 : : //------------------------------------------------------------------
209 : 58 : void OFormNavigationHelper::connectDispatchers()
210 : : {
211 [ - + ]: 58 : if ( m_nConnectedFeatures )
212 : : { // already connected -> just do an update
213 : 0 : updateDispatches();
214 : 58 : return;
215 : : }
216 : :
217 : 58 : initializeSupportedFeatures();
218 : :
219 : 58 : m_nConnectedFeatures = 0;
220 : :
221 [ + + ]: 192 : for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin();
222 : 96 : aFeature != m_aSupportedFeatures.end();
223 : : ++aFeature
224 : : )
225 : : {
226 : 38 : aFeature->second.bCachedState = sal_False;
227 : 38 : aFeature->second.aCachedAdditionalState.clear();
228 [ + - ][ + - ]: 38 : aFeature->second.xDispatcher = queryDispatch( aFeature->second.aURL );
229 [ - + ]: 38 : if ( aFeature->second.xDispatcher.is() )
230 : : {
231 : 0 : ++m_nConnectedFeatures;
232 [ # # ][ # # ]: 0 : aFeature->second.xDispatcher->addStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL );
[ # # ]
233 : : }
234 : : }
235 : :
236 : : // notify derivee that (potentially) all features changed their state
237 : 58 : allFeatureStatesChanged( );
238 : : }
239 : :
240 : : //------------------------------------------------------------------
241 : 521 : void OFormNavigationHelper::disconnectDispatchers()
242 : : {
243 [ - + ]: 521 : if ( m_nConnectedFeatures )
244 : : {
245 [ # # ]: 0 : for ( FeatureMap::iterator aFeature = m_aSupportedFeatures.begin();
246 : 0 : aFeature != m_aSupportedFeatures.end();
247 : : ++aFeature
248 : : )
249 : : {
250 [ # # ]: 0 : if ( aFeature->second.xDispatcher.is() )
251 [ # # ][ # # ]: 0 : aFeature->second.xDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), aFeature->second.aURL );
[ # # ]
252 : :
253 [ # # ]: 0 : aFeature->second.xDispatcher = NULL;
254 : 0 : aFeature->second.bCachedState = sal_False;
255 : 0 : aFeature->second.aCachedAdditionalState.clear();
256 : : }
257 : :
258 : 0 : m_nConnectedFeatures = 0;
259 : : }
260 : :
261 : : // notify derivee that (potentially) all features changed their state
262 : 521 : allFeatureStatesChanged( );
263 : 521 : }
264 : :
265 : : //------------------------------------------------------------------
266 : 58 : void OFormNavigationHelper::initializeSupportedFeatures( )
267 : : {
268 [ + - ]: 58 : if ( m_aSupportedFeatures.empty() )
269 : : {
270 : : // ask the derivee which feature ids it wants us to support
271 [ + - ]: 58 : ::std::vector< sal_Int16 > aFeatureIds;
272 [ + - ]: 58 : getSupportedFeatures( aFeatureIds );
273 : :
274 [ + - ]: 58 : OFormNavigationMapper aUrlMapper( m_xORB );
275 : :
276 [ + - ]: 192 : for ( ::std::vector< sal_Int16 >::const_iterator aLoop = aFeatureIds.begin();
[ + - + - ]
[ + + ]
277 : 96 : aLoop != aFeatureIds.end();
278 : : ++aLoop
279 : : )
280 : : {
281 [ + - ]: 38 : FeatureInfo aFeatureInfo;
282 : :
283 : : bool bKnownId =
284 [ + - ][ + - ]: 38 : aUrlMapper.getFeatureURL( *aLoop, aFeatureInfo.aURL );
285 : : DBG_ASSERT( bKnownId, "OFormNavigationHelper::initializeSupportedFeatures: unknown feature id!" );
286 : :
287 [ + - ]: 38 : if ( bKnownId )
288 : : // add to our map
289 [ + - ][ + - ]: 38 : m_aSupportedFeatures.insert( FeatureMap::value_type( *aLoop, aFeatureInfo ) );
[ + - ][ + - ]
290 [ + - ][ + - ]: 96 : }
291 : : }
292 : 58 : }
293 : :
294 : : //------------------------------------------------------------------
295 : 38 : Reference< XDispatch > OFormNavigationHelper::queryDispatch( const URL& _rURL )
296 : : {
297 : 38 : return m_pFeatureInterception->queryDispatch( _rURL );
298 : : }
299 : :
300 : : //------------------------------------------------------------------
301 : 0 : void OFormNavigationHelper::dispatchWithArgument( sal_Int16 _nFeatureId, const sal_Char* _pParamAsciiName,
302 : : const Any& _rParamValue ) const
303 : : {
304 [ # # ]: 0 : FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId );
305 [ # # ]: 0 : if ( m_aSupportedFeatures.end() != aInfo )
306 : : {
307 [ # # ]: 0 : if ( aInfo->second.xDispatcher.is() )
308 : : {
309 [ # # ]: 0 : Sequence< PropertyValue > aArgs( 1 );
310 [ # # ]: 0 : aArgs[0].Name = ::rtl::OUString::createFromAscii( _pParamAsciiName );
311 [ # # ]: 0 : aArgs[0].Value = _rParamValue;
312 : :
313 [ # # ][ # # ]: 0 : aInfo->second.xDispatcher->dispatch( aInfo->second.aURL, aArgs );
[ # # ]
314 : : }
315 : : }
316 : 0 : }
317 : :
318 : : //------------------------------------------------------------------
319 : 0 : void OFormNavigationHelper::dispatch( sal_Int16 _nFeatureId ) const
320 : : {
321 [ # # ]: 0 : FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId );
322 [ # # ]: 0 : if ( m_aSupportedFeatures.end() != aInfo )
323 : : {
324 [ # # ]: 0 : if ( aInfo->second.xDispatcher.is() )
325 : : {
326 [ # # ]: 0 : Sequence< PropertyValue > aEmptyArgs;
327 [ # # ][ # # ]: 0 : aInfo->second.xDispatcher->dispatch( aInfo->second.aURL, aEmptyArgs );
[ # # ]
328 : : }
329 : : }
330 : 0 : }
331 : :
332 : : //------------------------------------------------------------------
333 : 798 : bool OFormNavigationHelper::isEnabled( sal_Int16 _nFeatureId ) const
334 : : {
335 [ + - ]: 798 : FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId );
336 [ + + ]: 798 : if ( m_aSupportedFeatures.end() != aInfo )
337 : 38 : return aInfo->second.bCachedState;
338 : :
339 : 798 : return false;
340 : : }
341 : :
342 : : //------------------------------------------------------------------
343 : 0 : bool OFormNavigationHelper::getBooleanState( sal_Int16 _nFeatureId ) const
344 : : {
345 : 0 : sal_Bool bState = sal_False;
346 : :
347 [ # # ]: 0 : FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId );
348 [ # # ]: 0 : if ( m_aSupportedFeatures.end() != aInfo )
349 : 0 : aInfo->second.aCachedAdditionalState >>= bState;
350 : :
351 : 0 : return (bool)bState;
352 : : }
353 : :
354 : : //------------------------------------------------------------------
355 : 0 : ::rtl::OUString OFormNavigationHelper::getStringState( sal_Int16 _nFeatureId ) const
356 : : {
357 : 0 : ::rtl::OUString sState;
358 : :
359 [ # # ]: 0 : FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId );
360 [ # # ]: 0 : if ( m_aSupportedFeatures.end() != aInfo )
361 : 0 : aInfo->second.aCachedAdditionalState >>= sState;
362 : :
363 : 0 : return sState;
364 : : }
365 : :
366 : : //------------------------------------------------------------------
367 : 0 : sal_Int32 OFormNavigationHelper::getIntegerState( sal_Int16 _nFeatureId ) const
368 : : {
369 : 0 : sal_Int32 nState = 0;
370 : :
371 [ # # ]: 0 : FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId );
372 [ # # ]: 0 : if ( m_aSupportedFeatures.end() != aInfo )
373 : 0 : aInfo->second.aCachedAdditionalState >>= nState;
374 : :
375 : 0 : return nState;
376 : : }
377 : :
378 : : //------------------------------------------------------------------
379 : 0 : void OFormNavigationHelper::invalidateSupportedFeaturesSet()
380 : : {
381 [ # # ]: 0 : disconnectDispatchers( );
382 : : // no supported features anymore:
383 [ # # ]: 0 : FeatureMap aEmpty;
384 [ # # ]: 0 : m_aSupportedFeatures.swap( aEmpty );
385 : 0 : }
386 : :
387 : : //==================================================================
388 : : //= OFormNavigationMapper
389 : : //==================================================================
390 : : //------------------------------------------------------------------
391 : 58 : OFormNavigationMapper::OFormNavigationMapper( const Reference< XMultiServiceFactory >& _rxORB )
392 : : {
393 [ + - ][ + - ]: 58 : m_pUrlTransformer.reset( new UrlTransformer( _rxORB ) );
394 : 58 : }
395 : :
396 : : //------------------------------------------------------------------
397 : 58 : OFormNavigationMapper::~OFormNavigationMapper( )
398 : : {
399 : 58 : }
400 : :
401 : : //------------------------------------------------------------------
402 : 38 : bool OFormNavigationMapper::getFeatureURL( sal_Int16 _nFeatureId, URL& /* [out] */ _rURL )
403 : : {
404 : : // get the ascii version of the URL
405 : 38 : const char* pAsciiURL = getFeatureURLAscii( _nFeatureId );
406 [ + - ]: 38 : if ( pAsciiURL )
407 : 38 : _rURL = m_pUrlTransformer->getStrictURLFromAscii( pAsciiURL );
408 : :
409 : 38 : return ( pAsciiURL != NULL );
410 : : }
411 : :
412 : : //------------------------------------------------------------------
413 : : namespace
414 : : {
415 : : struct FeatureURL
416 : : {
417 : : const sal_Int16 nFormFeature;
418 : : const sal_Char* pAsciiURL;
419 : :
420 : 40 : FeatureURL( const sal_Int16 _nFormFeature, const sal_Char* _pAsciiURL )
421 : : :nFormFeature( _nFormFeature )
422 : 40 : ,pAsciiURL( _pAsciiURL )
423 : : {
424 : 40 : }
425 : : };
426 : 38 : const FeatureURL* lcl_getFeatureTable()
427 : : {
428 : : static const FeatureURL s_aFeatureURLs[] =
429 : : {
430 : : FeatureURL( FormFeature::MoveAbsolute, URL_FORM_POSITION.ascii ),
431 : : FeatureURL( FormFeature::TotalRecords, URL_FORM_RECORDCOUNT.ascii ),
432 : : FeatureURL( FormFeature::MoveToFirst, URL_RECORD_FIRST.ascii ),
433 : : FeatureURL( FormFeature::MoveToPrevious, URL_RECORD_PREV.ascii ),
434 : : FeatureURL( FormFeature::MoveToNext, URL_RECORD_NEXT.ascii ),
435 : : FeatureURL( FormFeature::MoveToLast, URL_RECORD_LAST.ascii ),
436 : : FeatureURL( FormFeature::SaveRecordChanges, URL_RECORD_SAVE.ascii ),
437 : : FeatureURL( FormFeature::UndoRecordChanges, URL_RECORD_UNDO.ascii ),
438 : : FeatureURL( FormFeature::MoveToInsertRow, URL_RECORD_NEW.ascii ),
439 : : FeatureURL( FormFeature::DeleteRecord, URL_RECORD_DELETE.ascii ),
440 : : FeatureURL( FormFeature::ReloadForm, URL_FORM_REFRESH.ascii ),
441 : : FeatureURL( FormFeature::RefreshCurrentControl, URL_FORM_REFRESH_CURRENT_CONTROL.ascii ),
442 : : FeatureURL( FormFeature::SortAscending, URL_FORM_SORT_UP.ascii ),
443 : : FeatureURL( FormFeature::SortDescending, URL_FORM_SORT_DOWN.ascii ),
444 : : FeatureURL( FormFeature::InteractiveSort, URL_FORM_SORT.ascii ),
445 : : FeatureURL( FormFeature::AutoFilter, URL_FORM_AUTO_FILTER.ascii ),
446 : : FeatureURL( FormFeature::InteractiveFilter, URL_FORM_FILTER.ascii ),
447 : : FeatureURL( FormFeature::ToggleApplyFilter, URL_FORM_APPLY_FILTER.ascii ),
448 : : FeatureURL( FormFeature::RemoveFilterAndSort, URL_FORM_REMOVE_FILTER.ascii ),
449 : : FeatureURL( 0, NULL )
450 [ + + ][ + - ]: 38 : };
451 : 38 : return s_aFeatureURLs;
452 : : }
453 : : }
454 : :
455 : : //------------------------------------------------------------------
456 : 38 : const char* OFormNavigationMapper::getFeatureURLAscii( sal_Int16 _nFeatureId )
457 : : {
458 : 38 : const FeatureURL* pFeatures = lcl_getFeatureTable();
459 [ + - ]: 380 : while ( pFeatures->pAsciiURL )
460 : : {
461 [ + + ]: 380 : if ( pFeatures->nFormFeature == _nFeatureId )
462 : 38 : return pFeatures->pAsciiURL;
463 : 342 : ++pFeatures;
464 : : }
465 : 38 : return NULL;
466 : : }
467 : :
468 : : //------------------------------------------------------------------
469 : 0 : sal_Int16 OFormNavigationMapper::getFeatureId( const ::rtl::OUString& _rCompleteURL )
470 : : {
471 : 0 : const FeatureURL* pFeatures = lcl_getFeatureTable();
472 [ # # ]: 0 : while ( pFeatures->pAsciiURL )
473 : : {
474 [ # # ]: 0 : if ( _rCompleteURL.compareToAscii( pFeatures->pAsciiURL ) == 0 )
475 : 0 : return pFeatures->nFormFeature;
476 : 0 : ++pFeatures;
477 : : }
478 : 0 : return -1;
479 : : }
480 : :
481 : : //.........................................................................
482 : : } // namespace frm
483 : : //.........................................................................
484 : :
485 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|