29#include <com/sun/star/lang/XServiceInfo.hpp>
30#include <com/sun/star/form/FormComponentType.hpp>
31#include <com/sun/star/xforms/XFormsUIHelper1.hpp>
32#include <com/sun/star/xsd/DataTypeClass.hpp>
33#include <com/sun/star/form/binding/XListEntrySink.hpp>
47 using namespace ::com::sun::star::form::binding;
58 OUString composeModelElementUIName( std::u16string_view _rModelName, std::u16string_view _rElementName )
60 OUString
a = OUString::Concat(
"[")
71 EFormsHelper::EFormsHelper( ::osl::Mutex& _rMutex,
const Reference< XPropertySet >& _rxControlModel,
const Reference< frame::XModel >& _rxContextDocument )
72 :m_xControlModel( _rxControlModel )
73 ,m_aPropertyListeners( _rMutex )
75 OSL_ENSURE( _rxControlModel.is(),
"EFormsHelper::EFormsHelper: invalid control model!" );
76 m_xBindableControl.set(_rxControlModel, css::uno::UNO_QUERY);
78 m_xDocument.set(_rxContextDocument, css::uno::UNO_QUERY);
79 OSL_ENSURE(
m_xDocument.is(),
"EFormsHelper::EFormsHelper: invalid document!" );
84 bool EFormsHelper::isEForm(
const Reference< frame::XModel >& _rxContextDocument )
88 Reference< xforms::XFormsSupplier > xDocument( _rxContextDocument, UNO_QUERY );
89 if ( !xDocument.is() )
92 return xDocument->getXForms().is();
102 bool EFormsHelper::canBindToDataType( sal_Int32 _nDataType )
const
104 if ( !m_xBindableControl.is() )
109 if ( ( DataTypeClass::hexBinary == _nDataType )
110 || ( DataTypeClass::base64Binary == _nDataType )
111 || ( DataTypeClass::QName == _nDataType )
112 || ( DataTypeClass::NOTATION == _nDataType )
120 sal_Int16 nControlType = FormComponentType::CONTROL;
121 OSL_VERIFY( m_xControlModel->getPropertyValue(
PROPERTY_CLASSID ) >>= nControlType );
124 sal_Int16
const nNumericCompatibleTypes[] = { DataTypeClass::DECIMAL, DataTypeClass::FLOAT, DataTypeClass::DOUBLE, 0 };
125 sal_Int16
const nDateCompatibleTypes[] = { DataTypeClass::DATE, 0 };
126 sal_Int16
const nTimeCompatibleTypes[] = { DataTypeClass::TIME, 0 };
127 sal_Int16
const nCheckboxCompatibleTypes[] = { DataTypeClass::BOOLEAN, DataTypeClass::STRING, DataTypeClass::anyURI, 0 };
128 sal_Int16
const nRadiobuttonCompatibleTypes[] = { DataTypeClass::STRING, DataTypeClass::anyURI, 0 };
129 sal_Int16
const nFormattedCompatibleTypes[] = { DataTypeClass::DECIMAL, DataTypeClass::FLOAT, DataTypeClass::DOUBLE, DataTypeClass::DATETIME, DataTypeClass::DATE, DataTypeClass::TIME, 0 };
131 sal_Int16
const * pCompatibleTypes =
nullptr;
132 switch ( nControlType )
134 case FormComponentType::SPINBUTTON:
135 case FormComponentType::NUMERICFIELD:
136 pCompatibleTypes = nNumericCompatibleTypes;
138 case FormComponentType::DATEFIELD:
139 pCompatibleTypes = nDateCompatibleTypes;
141 case FormComponentType::TIMEFIELD:
142 pCompatibleTypes = nTimeCompatibleTypes;
144 case FormComponentType::CHECKBOX:
145 pCompatibleTypes = nCheckboxCompatibleTypes;
147 case FormComponentType::RADIOBUTTON:
148 pCompatibleTypes = nRadiobuttonCompatibleTypes;
151 case FormComponentType::TEXTFIELD:
155 Reference< XServiceInfo > xSI( m_xControlModel, UNO_QUERY );
156 OSL_ENSURE( xSI.is(),
"EFormsHelper::canBindToDataType: a control model which has no service info?" );
161 pCompatibleTypes = nFormattedCompatibleTypes;
167 case FormComponentType::LISTBOX:
168 case FormComponentType::COMBOBOX:
173 if ( !bCan && pCompatibleTypes )
175 if ( _nDataType == -1 )
182 while ( *pCompatibleTypes && !bCan )
183 bCan = ( *pCompatibleTypes++ == _nDataType );
196 bool EFormsHelper::isListEntrySink()
const
201 Reference< XListEntrySink > xAsSink( m_xControlModel, UNO_QUERY );
212 void EFormsHelper::impl_switchBindingListening_throw(
bool _bDoListening,
const Reference< XPropertyChangeListener >& _rxListener )
214 Reference< XPropertySet > xBindingProps;
215 if ( m_xBindableControl.is() )
216 xBindingProps.set(m_xBindableControl->getValueBinding(), css::uno::UNO_QUERY);
217 if ( !xBindingProps.is() )
222 xBindingProps->addPropertyChangeListener( OUString(), _rxListener );
226 xBindingProps->removePropertyChangeListener( OUString(), _rxListener );
231 void EFormsHelper::registerBindingListener(
const Reference< XPropertyChangeListener >& _rxBindingListener )
233 if ( !_rxBindingListener.is() )
235 impl_toggleBindingPropertyListening_throw(
true, _rxBindingListener );
239 void EFormsHelper::impl_toggleBindingPropertyListening_throw(
bool _bDoListen,
const Reference< XPropertyChangeListener >& _rxConcreteListenerOrNull )
247 OSL_ENSURE( pTranslator,
"EFormsHelper::impl_toggleBindingPropertyListening_throw: invalid listener element in my container!" );
251 Reference< XPropertyChangeListener > xEventSourceTranslator( pTranslator );
252 if ( _rxConcreteListenerOrNull.is() )
254 if ( pTranslator->
getDelegator() == _rxConcreteListenerOrNull )
256 impl_switchBindingListening_throw(
false, xEventSourceTranslator );
257 m_aPropertyListeners.removeInterface( xEventSourceTranslator );
263 impl_switchBindingListening_throw(
false, xEventSourceTranslator );
269 if ( _rxConcreteListenerOrNull.is() )
271 Reference< XPropertyChangeListener > xEventSourceTranslator(
new PropertyEventTranslation( _rxConcreteListenerOrNull, m_xBindableControl ) );
272 m_aPropertyListeners.addInterface( xEventSourceTranslator );
273 impl_switchBindingListening_throw(
true, xEventSourceTranslator );
279 impl_switchBindingListening_throw(
true, aListenerIterator.
next() );
285 void EFormsHelper::revokeBindingListener(
const Reference< XPropertyChangeListener >& _rxBindingListener )
287 impl_toggleBindingPropertyListening_throw(
false, _rxBindingListener );
291 void EFormsHelper::getFormModelNames( std::vector< OUString >& _rModelNames )
const
298 _rModelNames.resize( 0 );
300 Reference< XNameContainer > xForms(
m_xDocument->getXForms() );
301 OSL_ENSURE( xForms.is(),
"EFormsHelper::getFormModelNames: invalid forms container!" );
304 const Sequence< OUString > aModelNames = xForms->getElementNames();
305 _rModelNames.resize( aModelNames.getLength() );
306 std::copy( aModelNames.begin(), aModelNames.end(), _rModelNames.begin() );
316 void EFormsHelper::getBindingNames(
const OUString& _rModelName, std::vector< OUString >& _rBindingNames )
const
318 _rBindingNames.resize( 0 );
321 Reference< xforms::XModel >
xModel( getFormModelByName( _rModelName ) );
324 Reference< XNameAccess > xBindings(
xModel->getBindings(), UNO_QUERY );
325 OSL_ENSURE( xBindings.is(),
"EFormsHelper::getBindingNames: invalid bindings container obtained from the model!" );
326 if ( xBindings.is() )
328 const Sequence< OUString > aNames = xBindings->getElementNames();
329 _rBindingNames.resize( aNames.getLength() );
330 std::copy( aNames.begin(), aNames.end(), _rBindingNames.begin() );
341 Reference< xforms::XModel > EFormsHelper::getFormModelByName(
const OUString& _rModelName )
const
343 Reference< xforms::XModel > xReturn;
346 Reference< XNameContainer > xForms(
m_xDocument->getXForms() );
347 OSL_ENSURE( xForms.is(),
"EFormsHelper::getFormModelByName: invalid forms container!" );
349 OSL_VERIFY( xForms->getByName( _rModelName ) >>= xReturn );
359 Reference< xforms::XModel > EFormsHelper::getCurrentFormModel()
const
361 Reference< xforms::XModel >
xModel;
364 Reference< XPropertySet > xBinding( getCurrentBinding() );
378 OUString EFormsHelper::getCurrentFormModelName()
const
383 Reference< xforms::XModel > xFormsModel( getCurrentFormModel() );
384 if ( xFormsModel.is() )
385 sModelName = xFormsModel->getID();
395 Reference< XPropertySet > EFormsHelper::getCurrentBinding()
const
397 Reference< XPropertySet > xBinding;
401 if ( m_xBindableControl.is() )
402 xBinding.set(m_xBindableControl->getValueBinding(), css::uno::UNO_QUERY);
413 OUString EFormsHelper::getCurrentBindingName()
const
415 OUString sBindingName;
418 Reference< XPropertySet > xBinding( getCurrentBinding() );
430 Reference< XListEntrySource > EFormsHelper::getCurrentListSourceBinding()
const
432 Reference< XListEntrySource > xReturn;
435 Reference< XListEntrySink > xAsSink( m_xControlModel, UNO_QUERY );
436 OSL_ENSURE( xAsSink.is(),
"EFormsHelper::getCurrentListSourceBinding: you should have used isListEntrySink before!" );
438 xReturn = xAsSink->getListEntrySource();
448 void EFormsHelper::setListSourceBinding(
const Reference< XListEntrySource >& _rxListSource )
452 Reference< XListEntrySink > xAsSink( m_xControlModel, UNO_QUERY );
453 OSL_ENSURE( xAsSink.is(),
"EFormsHelper::setListSourceBinding: you should have used isListEntrySink before!" );
455 xAsSink->setListEntrySource( _rxListSource );
464 void EFormsHelper::setBinding(
const Reference< css::beans::XPropertySet >& _rxBinding )
466 if ( !m_xBindableControl.is() )
471 Reference< XPropertySet > xOldBinding( m_xBindableControl->getValueBinding(), UNO_QUERY );
473 Reference< XValueBinding > xBinding( _rxBinding, UNO_QUERY );
474 OSL_ENSURE( xBinding.is() || !_rxBinding.is(),
"EFormsHelper::setBinding: invalid binding!" );
476 impl_toggleBindingPropertyListening_throw(
false,
nullptr );
477 m_xBindableControl->setValueBinding( xBinding );
478 impl_toggleBindingPropertyListening_throw(
true,
nullptr );
480 std::set< OUString > aSet;
481 firePropertyChanges( xOldBinding, _rxBinding, aSet );
490 Reference< XPropertySet > EFormsHelper::getOrCreateBindingForModel(
const OUString& _rTargetModel,
const OUString& _rBindingName )
const
492 OSL_ENSURE( !_rBindingName.isEmpty(),
"EFormsHelper::getOrCreateBindingForModel: invalid binding name!" );
493 return implGetOrCreateBinding( _rTargetModel, _rBindingName );
497 Reference< XPropertySet > EFormsHelper::implGetOrCreateBinding(
const OUString& _rTargetModel,
const OUString& _rBindingName )
const
499 OSL_ENSURE( !( _rTargetModel.isEmpty() && !_rBindingName.isEmpty() ),
"EFormsHelper::implGetOrCreateBinding: no model, but a binding name?" );
501 Reference< XPropertySet > xBinding;
504 OUString sTargetModel( _rTargetModel );
506 if ( sTargetModel.isEmpty() )
508 std::vector< OUString > aModelNames;
509 getFormModelNames( aModelNames );
510 if ( !aModelNames.empty() )
511 sTargetModel = *aModelNames.begin();
512 OSL_ENSURE( !sTargetModel.isEmpty(),
"EFormsHelper::implGetOrCreateBinding: unable to obtain a default model!" );
514 Reference< xforms::XModel >
xModel( getFormModelByName( sTargetModel ) );
515 Reference< XNameAccess > xBindingNames(
xModel.is() ?
xModel->getBindings() : Reference< XSet >(), UNO_QUERY );
516 if ( xBindingNames.is() )
519 if ( !_rBindingName.isEmpty() )
521 if ( xBindingNames->hasByName( _rBindingName ) )
522 OSL_VERIFY( xBindingNames->getByName( _rBindingName ) >>= xBinding );
525 xBinding =
xModel->createBinding( );
529 xModel->getBindings()->insert(
Any( xBinding ) );
535 xBinding =
xModel->createBinding( );
539 OUString sBaseName(
PcrRes(RID_STR_BINDING_NAME) +
" ");
541 sal_Int32 nNumber = 1;
544 sNewName = sBaseName + OUString::number( nNumber++ );
546 while ( xBindingNames->hasByName( sNewName ) );
547 Reference< XNamed > xName( xBinding, UNO_QUERY_THROW );
548 xName->setName( sNewName );
550 xModel->getBindings()->insert(
Any( xBinding ) );
567 struct PropertyBagInserter
575 void operator()(
const Property& _rProp )
582 Reference< XPropertySetInfo > collectPropertiesGetInfo(
const Reference< XPropertySet >& _rxProps,
PropertyBag& _rBag )
584 Reference< XPropertySetInfo > xInfo;
586 xInfo = _rxProps->getPropertySetInfo();
589 const Sequence< Property >
aProperties = xInfo->getProperties();
591 PropertyBagInserter( _rBag )
605 Reference< xforms::XFormsUIHelper1 > xHelper;
606 if ( _rxElement.is() )
608 OSL_ENSURE( xHelper.is(),
"EFormsHelper::getModelElementUIName: invalid element or model!" );
611 OUString sElementName = ( _eType == Submission ) ? xHelper->getSubmissionName( _rxElement,
true ) : xHelper->getBindingName( _rxElement,
true );
612 Reference< xforms::XModel >
xModel( xHelper, UNO_QUERY_THROW );
613 sUIName = composeModelElementUIName(
xModel->getID(), sElementName );
627 const MapStringToPropertySet& rMapUINameToElement( ( _eType == Submission ) ? m_aSubmissionUINames : m_aBindingUINames );
628 MapStringToPropertySet::const_iterator
pos = rMapUINameToElement.find( _rUIName );
629 OSL_ENSURE(
pos != rMapUINameToElement.end(),
"EFormsHelper::getModelElementFromUIName: didn't find it!" );
631 return (
pos != rMapUINameToElement.end() ) ?
pos->second : Reference< XPropertySet >();
635 void EFormsHelper::getAllElementUINames(
const ModelElementType _eType, std::vector< OUString >& _rElementNames,
bool _bPrepentEmptyEntry )
637 MapStringToPropertySet& rMapUINameToElement( ( _eType == Submission ) ? m_aSubmissionUINames : m_aBindingUINames );
638 rMapUINameToElement.clear();
639 _rElementNames.resize( 0 );
641 if ( _bPrepentEmptyEntry )
642 rMapUINameToElement[ OUString() ].clear();
647 std::vector< OUString > aModels;
648 getFormModelNames( aModels );
649 _rElementNames.reserve( aModels.size() * 2 );
652 for (
auto const& modelName : aModels)
654 Reference< xforms::XModel >
xModel = getFormModelByName(modelName);
655 OSL_ENSURE(
xModel.is(),
"EFormsHelper::getAllElementUINames: inconsistency in the models!" );
656 Reference< xforms::XFormsUIHelper1 > xHelper(
xModel, UNO_QUERY );
658 Reference< XIndexAccess > xElements;
660 xElements.set(( _eType == Submission ) ?
xModel->getSubmissions() :
xModel->getBindings(), css::uno::UNO_QUERY);
661 if ( !xElements.is() )
664 sal_Int32 nElementCount = xElements->getCount();
665 for ( sal_Int32
i = 0;
i < nElementCount; ++
i )
667 Reference< XPropertySet > xElement( xElements->getByIndex(
i ), UNO_QUERY );
668 OSL_ENSURE( xElement.is(),
"EFormsHelper::getAllElementUINames: empty element!" );
669 if ( !xElement.is() )
671#if OSL_DEBUG_LEVEL > 0
673 Reference< xforms::XModel > xElementsModel;
675 OSL_ENSURE( xElementsModel ==
xModel,
"EFormsHelper::getAllElementUINames: inconsistency in the model-element relationship!" );
676 if ( xElementsModel !=
xModel )
680 OUString sElementName = ( _eType == Submission ) ? xHelper->getSubmissionName( xElement,
true ) : xHelper->getBindingName( xElement,
true );
681 OUString sUIName = composeModelElementUIName( modelName, sElementName );
683 OSL_ENSURE( rMapUINameToElement.find( sUIName ) == rMapUINameToElement.end(),
"EFormsHelper::getAllElementUINames: duplicate name!" );
684 rMapUINameToElement.emplace( sUIName, xElement );
693 _rElementNames.resize( rMapUINameToElement.size() );
694 std::transform( rMapUINameToElement.begin(), rMapUINameToElement.end(), _rElementNames.begin(),
699 void EFormsHelper::firePropertyChange(
const OUString& _rName,
const Any& _rOldValue,
const Any& _rNewValue )
const
701 if ( m_aPropertyListeners.getLength() == 0 )
704 if ( _rOldValue == _rNewValue )
709 PropertyChangeEvent
aEvent;
711 aEvent.Source = m_xBindableControl.get();
712 aEvent.PropertyName = _rName;
713 aEvent.OldValue = _rOldValue;
714 aEvent.NewValue = _rNewValue;
716 const_cast< EFormsHelper*
>( this )->m_aPropertyListeners.notifyEach( &XPropertyChangeListener::propertyChange,
aEvent );
725 void EFormsHelper::firePropertyChanges(
const Reference< XPropertySet >& _rxOldProps,
const Reference< XPropertySet >& _rxNewProps, std::set< OUString >& _rFilter )
const
727 if ( m_aPropertyListeners.getLength() == 0 )
733 Reference< XPropertySetInfo > xOldInfo = collectPropertiesGetInfo( _rxOldProps,
aProperties );
734 Reference< XPropertySetInfo > xNewInfo = collectPropertiesGetInfo( _rxNewProps,
aProperties );
738 if ( _rFilter.find(
property.Name ) != _rFilter.end() )
742 if ( xOldInfo.is() && xOldInfo->hasPropertyByName(
property.Name ) )
743 aOldValue = _rxOldProps->getPropertyValue(
property.Name );
746 if ( xNewInfo.is() && xNewInfo->hasPropertyByName(
property.Name ) )
747 aNewValue = _rxNewProps->getPropertyValue(
property.Name );
749 firePropertyChange(
property.Name, aOldValue, aNewValue );
PropertiesInfo aProperties
bool hasMoreElements() const
css::uno::Reference< ListenerT > const & next()
const css::uno::Reference< css::beans::XPropertyChangeListener > & getDelegator() const
Reference< XOfficeDatabaseDocument > m_xDocument
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
a property handler for any virtual string properties
std::map< OUString, css::uno::Reference< css::beans::XPropertySet >, std::less< OUString > > MapStringToPropertySet
std::set< css::beans::Property, PropertyLessByName > PropertyBag
OUString PcrRes(TranslateId aId)
Reference< XModel > xModel