1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <formnavigation.hxx>
21 #include <urltransformer.hxx>
22 #include <controlfeatureinterception.hxx>
23 #include <frm_strings.hxx>
25 #include <com/sun/star/form/runtime/FormFeature.hpp>
27 #include <tools/debug.hxx>
28 #include <osl/diagnose.h>
35 using namespace ::com::sun::star::uno
;
36 using namespace ::com::sun::star::beans
;
37 using namespace ::com::sun::star::lang
;
38 using namespace ::com::sun::star::util
;
39 using namespace ::com::sun::star::frame
;
40 namespace FormFeature
= ::com::sun::star::form::runtime::FormFeature
;
42 OFormNavigationHelper::OFormNavigationHelper( const Reference
< XComponentContext
>& _rxORB
)
44 ,m_nConnectedFeatures( 0 )
46 m_pFeatureInterception
.reset( new ControlFeatureInterception( m_xORB
) );
50 OFormNavigationHelper::~OFormNavigationHelper()
55 void OFormNavigationHelper::dispose( )
57 m_pFeatureInterception
->dispose();
58 disconnectDispatchers();
62 void OFormNavigationHelper::interceptorsChanged( )
68 void OFormNavigationHelper::featureStateChanged( sal_Int16
/*_nFeatureId*/, bool /*_bEnabled*/ )
74 void OFormNavigationHelper::allFeatureStatesChanged( )
80 void SAL_CALL
OFormNavigationHelper::registerDispatchProviderInterceptor( const Reference
< XDispatchProviderInterceptor
>& _rxInterceptor
)
82 m_pFeatureInterception
->registerDispatchProviderInterceptor( _rxInterceptor
);
83 interceptorsChanged();
87 void SAL_CALL
OFormNavigationHelper::releaseDispatchProviderInterceptor( const Reference
< XDispatchProviderInterceptor
>& _rxInterceptor
)
89 m_pFeatureInterception
->releaseDispatchProviderInterceptor( _rxInterceptor
);
90 interceptorsChanged();
94 void SAL_CALL
OFormNavigationHelper::statusChanged( const FeatureStateEvent
& _rState
)
96 for (auto & feature
: m_aSupportedFeatures
)
98 if ( feature
.second
.aURL
.Main
== _rState
.FeatureURL
.Main
)
100 if ( ( feature
.second
.bCachedState
!= bool(_rState
.IsEnabled
) )
101 || ( feature
.second
.aCachedAdditionalState
!= _rState
.State
)
104 // change the cached state
105 feature
.second
.bCachedState
= _rState
.IsEnabled
;
106 feature
.second
.aCachedAdditionalState
= _rState
.State
;
107 // tell derivees what happened
108 featureStateChanged( feature
.first
, _rState
.IsEnabled
);
115 OSL_FAIL( "OFormNavigationHelper::statusChanged: huh? An invalid/unknown URL?" );
119 void SAL_CALL
OFormNavigationHelper::disposing( const EventObject
& _rSource
)
121 // was it one of our external dispatchers?
122 if ( !m_nConnectedFeatures
)
125 for (auto & feature
: m_aSupportedFeatures
)
127 if ( feature
.second
.xDispatcher
== _rSource
.Source
)
129 feature
.second
.xDispatcher
->removeStatusListener( static_cast< XStatusListener
* >( this ), feature
.second
.aURL
);
130 feature
.second
.xDispatcher
= nullptr;
131 feature
.second
.bCachedState
= false;
132 feature
.second
.aCachedAdditionalState
.clear();
133 --m_nConnectedFeatures
;
135 featureStateChanged( feature
.first
, false );
142 void OFormNavigationHelper::updateDispatches()
144 if ( !m_nConnectedFeatures
)
145 { // we don't have any dispatchers yet -> do the initial connect
146 connectDispatchers();
150 initializeSupportedFeatures();
152 m_nConnectedFeatures
= 0;
154 Reference
< XDispatch
> xNewDispatcher
;
155 Reference
< XDispatch
> xCurrentDispatcher
;
157 for (auto & feature
: m_aSupportedFeatures
)
159 xNewDispatcher
= queryDispatch( feature
.second
.aURL
);
160 xCurrentDispatcher
= feature
.second
.xDispatcher
;
161 if ( xNewDispatcher
!= xCurrentDispatcher
)
163 // the dispatcher for this particular URL changed
164 if ( xCurrentDispatcher
.is() )
165 xCurrentDispatcher
->removeStatusListener( static_cast< XStatusListener
* >( this ), feature
.second
.aURL
);
167 xCurrentDispatcher
= feature
.second
.xDispatcher
= xNewDispatcher
;
169 if ( xCurrentDispatcher
.is() )
170 xCurrentDispatcher
->addStatusListener( static_cast< XStatusListener
* >( this ), feature
.second
.aURL
);
173 if ( xCurrentDispatcher
.is() )
174 ++m_nConnectedFeatures
;
176 feature
.second
.bCachedState
= false;
179 // notify derivee that (potentially) all features changed their state
180 allFeatureStatesChanged( );
184 void OFormNavigationHelper::connectDispatchers()
186 if ( m_nConnectedFeatures
)
187 { // already connected -> just do an update
192 initializeSupportedFeatures();
194 m_nConnectedFeatures
= 0;
196 for (auto & feature
: m_aSupportedFeatures
)
198 feature
.second
.bCachedState
= false;
199 feature
.second
.aCachedAdditionalState
.clear();
200 feature
.second
.xDispatcher
= queryDispatch( feature
.second
.aURL
);
201 if ( feature
.second
.xDispatcher
.is() )
203 ++m_nConnectedFeatures
;
204 feature
.second
.xDispatcher
->addStatusListener( static_cast< XStatusListener
* >( this ), feature
.second
.aURL
);
208 // notify derivee that (potentially) all features changed their state
209 allFeatureStatesChanged( );
213 void OFormNavigationHelper::disconnectDispatchers()
215 if ( m_nConnectedFeatures
)
217 for (auto & feature
: m_aSupportedFeatures
)
219 if ( feature
.second
.xDispatcher
.is() )
220 feature
.second
.xDispatcher
->removeStatusListener( static_cast< XStatusListener
* >( this ), feature
.second
.aURL
);
222 feature
.second
.xDispatcher
= nullptr;
223 feature
.second
.bCachedState
= false;
224 feature
.second
.aCachedAdditionalState
.clear();
227 m_nConnectedFeatures
= 0;
230 // notify derivee that (potentially) all features changed their state
231 allFeatureStatesChanged( );
235 void OFormNavigationHelper::initializeSupportedFeatures( )
237 if ( !m_aSupportedFeatures
.empty() )
240 // ask the derivee which feature ids it wants us to support
241 ::std::vector
< sal_Int16
> aFeatureIds
;
242 getSupportedFeatures( aFeatureIds
);
244 OFormNavigationMapper
aUrlMapper( m_xORB
);
246 for (auto const& feature
: aFeatureIds
)
248 FeatureInfo aFeatureInfo
;
251 aUrlMapper
.getFeatureURL( feature
, aFeatureInfo
.aURL
);
252 DBG_ASSERT( bKnownId
, "OFormNavigationHelper::initializeSupportedFeatures: unknown feature id!" );
256 m_aSupportedFeatures
.emplace( feature
, aFeatureInfo
);
261 Reference
< XDispatch
> OFormNavigationHelper::queryDispatch( const URL
& _rURL
)
263 return m_pFeatureInterception
->queryDispatch( _rURL
);
267 void OFormNavigationHelper::dispatchWithArgument( sal_Int16 _nFeatureId
, const char* _pParamAsciiName
,
268 const Any
& _rParamValue
) const
270 FeatureMap::const_iterator aInfo
= m_aSupportedFeatures
.find( _nFeatureId
);
271 if ( m_aSupportedFeatures
.end() != aInfo
)
273 if ( aInfo
->second
.xDispatcher
.is() )
275 Sequence
< PropertyValue
> aArgs( 1 );
276 aArgs
[0].Name
= OUString::createFromAscii( _pParamAsciiName
);
277 aArgs
[0].Value
= _rParamValue
;
279 aInfo
->second
.xDispatcher
->dispatch( aInfo
->second
.aURL
, aArgs
);
285 void OFormNavigationHelper::dispatch( sal_Int16 _nFeatureId
) const
287 FeatureMap::const_iterator aInfo
= m_aSupportedFeatures
.find( _nFeatureId
);
288 if ( m_aSupportedFeatures
.end() != aInfo
)
290 if ( aInfo
->second
.xDispatcher
.is() )
292 Sequence
< PropertyValue
> aEmptyArgs
;
293 aInfo
->second
.xDispatcher
->dispatch( aInfo
->second
.aURL
, aEmptyArgs
);
299 bool OFormNavigationHelper::isEnabled( sal_Int16 _nFeatureId
) const
301 FeatureMap::const_iterator aInfo
= m_aSupportedFeatures
.find( _nFeatureId
);
302 if ( m_aSupportedFeatures
.end() != aInfo
)
303 return aInfo
->second
.bCachedState
;
309 bool OFormNavigationHelper::getBooleanState( sal_Int16 _nFeatureId
) const
313 FeatureMap::const_iterator aInfo
= m_aSupportedFeatures
.find( _nFeatureId
);
314 if ( m_aSupportedFeatures
.end() != aInfo
)
315 aInfo
->second
.aCachedAdditionalState
>>= bState
;
321 OUString
OFormNavigationHelper::getStringState( sal_Int16 _nFeatureId
) const
325 FeatureMap::const_iterator aInfo
= m_aSupportedFeatures
.find( _nFeatureId
);
326 if ( m_aSupportedFeatures
.end() != aInfo
)
327 aInfo
->second
.aCachedAdditionalState
>>= sState
;
333 sal_Int32
OFormNavigationHelper::getIntegerState( sal_Int16 _nFeatureId
) const
335 sal_Int32 nState
= 0;
337 FeatureMap::const_iterator aInfo
= m_aSupportedFeatures
.find( _nFeatureId
);
338 if ( m_aSupportedFeatures
.end() != aInfo
)
339 aInfo
->second
.aCachedAdditionalState
>>= nState
;
345 void OFormNavigationHelper::invalidateSupportedFeaturesSet()
347 disconnectDispatchers( );
348 // no supported features anymore:
350 m_aSupportedFeatures
.swap( aEmpty
);
353 OFormNavigationMapper::OFormNavigationMapper( const Reference
< XComponentContext
>& _rxORB
)
355 m_pUrlTransformer
.reset( new UrlTransformer( _rxORB
) );
359 OFormNavigationMapper::~OFormNavigationMapper( )
364 bool OFormNavigationMapper::getFeatureURL( sal_Int16 _nFeatureId
, URL
& /* [out] */ _rURL
)
366 // get the ascii version of the URL
367 const char* pAsciiURL
= getFeatureURLAscii( _nFeatureId
);
369 _rURL
= m_pUrlTransformer
->getStrictURLFromAscii( pAsciiURL
);
371 return ( pAsciiURL
!= nullptr );
379 const sal_Int16 nFormFeature
;
380 const char* pAsciiURL
;
382 FeatureURL( const sal_Int16 _nFormFeature
, const char* _pAsciiURL
)
383 :nFormFeature( _nFormFeature
)
384 ,pAsciiURL( _pAsciiURL
)
388 const FeatureURL
* lcl_getFeatureTable()
390 static const FeatureURL s_aFeatureURLs
[] =
392 FeatureURL( FormFeature::MoveAbsolute
, URL_FORM_POSITION
),
393 FeatureURL( FormFeature::TotalRecords
, URL_FORM_RECORDCOUNT
),
394 FeatureURL( FormFeature::MoveToFirst
, URL_RECORD_FIRST
),
395 FeatureURL( FormFeature::MoveToPrevious
, URL_RECORD_PREV
),
396 FeatureURL( FormFeature::MoveToNext
, URL_RECORD_NEXT
),
397 FeatureURL( FormFeature::MoveToLast
, URL_RECORD_LAST
),
398 FeatureURL( FormFeature::SaveRecordChanges
, URL_RECORD_SAVE
),
399 FeatureURL( FormFeature::UndoRecordChanges
, URL_RECORD_UNDO
),
400 FeatureURL( FormFeature::MoveToInsertRow
, URL_RECORD_NEW
),
401 FeatureURL( FormFeature::DeleteRecord
, URL_RECORD_DELETE
),
402 FeatureURL( FormFeature::ReloadForm
, URL_FORM_REFRESH
),
403 FeatureURL( FormFeature::RefreshCurrentControl
, URL_FORM_REFRESH_CURRENT_CONTROL
),
404 FeatureURL( FormFeature::SortAscending
, URL_FORM_SORT_UP
),
405 FeatureURL( FormFeature::SortDescending
, URL_FORM_SORT_DOWN
),
406 FeatureURL( FormFeature::InteractiveSort
, URL_FORM_SORT
),
407 FeatureURL( FormFeature::AutoFilter
, URL_FORM_AUTO_FILTER
),
408 FeatureURL( FormFeature::InteractiveFilter
, URL_FORM_FILTER
),
409 FeatureURL( FormFeature::ToggleApplyFilter
, URL_FORM_APPLY_FILTER
),
410 FeatureURL( FormFeature::RemoveFilterAndSort
, URL_FORM_REMOVE_FILTER
),
411 FeatureURL( 0, nullptr )
413 return s_aFeatureURLs
;
418 const char* OFormNavigationMapper::getFeatureURLAscii( sal_Int16 _nFeatureId
)
420 const FeatureURL
* pFeatures
= lcl_getFeatureTable();
421 while ( pFeatures
->pAsciiURL
)
423 if ( pFeatures
->nFormFeature
== _nFeatureId
)
424 return pFeatures
->pAsciiURL
;
431 sal_Int16
OFormNavigationMapper::getFeatureId( const OUString
& _rCompleteURL
)
433 const FeatureURL
* pFeatures
= lcl_getFeatureTable();
434 while ( pFeatures
->pAsciiURL
)
436 if ( _rCompleteURL
.equalsAscii( pFeatures
->pAsciiURL
) )
437 return pFeatures
->nFormFeature
;
447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */