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