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