INTEGRATION: CWS frmvalidation (1.26.24); FILE MERGED

2004/03/24 07:24:54 fs 1.26.24.4: #100000#
2004/03/23 11:04:17 fs 1.26.24.3: RESYNC: (1.26-1.27); FILE MERGED
2004/03/12 11:28:41 fs 1.26.24.2: #i21506# moved some interfaces from css.form.binding to css.form.validation
2004/03/11 16:46:15 fs 1.26.24.1: mass checkin
- #i25106# core for validating form controls via external XValidator instances
- moved the services/interfaces related to binding form controls to external
  value suppliers into css.form.binding (out of drafts.css.form/component)
This commit is contained in:
Rüdiger Timm
2004-04-02 09:52:14 +00:00
parent f6506ac7a5
commit 60ccc0b7eb

View File

@@ -2,9 +2,9 @@
*
* $RCSfile: FormComponent.cxx,v $
*
* $Revision: 1.27 $
* $Revision: 1.28 $
*
* last change: $Author: obo $ $Date: 2004-03-19 11:52:54 $
* last change: $Author: rt $ $Date: 2004-04-02 10:52:14 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -95,6 +95,12 @@
#ifndef _COM_SUN_STAR_UTIL_XMODIFYBROADCASTER_HPP_
#include <com/sun/star/util/XModifyBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XVCLWINDOWPEER_HPP_
#include <com/sun/star/awt/XVclWindowPeer.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_FONTUNDERLINE_HPP_
#include <com/sun/star/awt/FontUnderline.hpp>
#endif
#ifndef _COMPHELPER_PROPERTY_HXX_
#include <comphelper/property.hxx>
@@ -115,6 +121,13 @@
#ifndef _COMPHELPER_BASIC_IO_HXX_
#include <comphelper/basicio.hxx>
#endif
#ifndef COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
#include <comphelper/listenernotification.hxx>
#endif
#ifndef _TOOLKIT_HELPER_EMPTYFONTDESCRIPTOR_HXX_
#include <toolkit/helper/emptyfontdescriptor.hxx>
#endif
#ifndef _FRM_RESOURCE_HXX_
#include "frm_resource.hxx"
@@ -128,20 +141,50 @@
namespace frm
{
//.........................................................................
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::form;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;
using namespace ::drafts::com::sun::star::form;
using namespace ::dbtools;
using namespace ::comphelper;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::form;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::form::binding;
using namespace ::com::sun::star::form::validation;
using namespace ::dbtools;
using namespace ::comphelper;
//====================================================================
//= OFormComponentListeners
//====================================================================
typedef ::comphelper::OListenerContainerBase < XFormComponentValidityListener
, EventObject
> OFormComponentListeners_Base;
class OFormComponentListeners : public OFormComponentListeners_Base
{
public:
OFormComponentListeners( ::osl::Mutex& _rMutex )
:OFormComponentListeners_Base( _rMutex )
{
}
protected:
virtual bool implNotify(
const Reference< XFormComponentValidityListener >& _rxListener,
const EventObject& _rEvent
) SAL_THROW( ( Exception ) );
};
//------------------------------------------------------------------------------
bool OFormComponentListeners::implNotify( const Reference< XFormComponentValidityListener >& _rxListener, const EventObject& _rEvent ) SAL_THROW( ( Exception ) )
{
_rxListener->componentValidityChanged( _rEvent );
return true; // continue calling listeners
}
//=========================================================================
//= base class for form layer controls
@@ -317,7 +360,7 @@ void SAL_CALL OControl::createPeer(const Reference<XToolkit>& Toolkit, const Ref
//------------------------------------------------------------------------------
Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException)
{
return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
}
//------------------------------------------------------------------------------
@@ -329,13 +372,13 @@ sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) thro
//------------------------------------------------------------------------------
Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException)
{
return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
}
//------------------------------------------------------------------------------
Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException)
{
return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
}
//------------------------------------------------------------------------------
@@ -365,6 +408,9 @@ DBG_NAME(frm_OBoundControl);
OBoundControl::OBoundControl(const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _sService)
:OControl(_rxFactory, _sService)
,m_bLocked(sal_False)
,m_bLastKnownValidity( sal_True )
,m_aOriginalFont( EmptyFontDescriptor() )
,m_nOriginalTextLineColor( 0 )
{
DBG_CTOR(frm_OBoundControl, NULL);
}
@@ -385,11 +431,13 @@ Sequence< Type> OBoundControl::_getTypes()
//------------------------------------------------------------------
Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException)
{
// ask the base class
Any aReturn(OControl::queryAggregation(_rType));
// ask our own interfaces
if (!aReturn.hasValue())
aReturn = OBoundControl_BASE::queryInterface(_rType);
// (do this first - we want to "overwrite" XPropertiesChangeListener)
Any aReturn( OBoundControl_BASE::queryInterface(_rType) );
// ask the base class
if ( !aReturn.hasValue() )
aReturn = OControl::queryAggregation( _rType );
return aReturn;
}
@@ -415,17 +463,203 @@ void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException)
void OBoundControl::_setLock(sal_Bool _bLock)
{
// try to set the text component to readonly
Reference<XWindowPeer> xPeer = getPeer();
Reference<com::sun::star::awt::XTextComponent> xText(xPeer, UNO_QUERY);
Reference< XWindowPeer > xPeer = getPeer();
Reference< XTextComponent > xText( xPeer, UNO_QUERY );
if (xText.is())
xText->setEditable(!_bLock);
if ( xText.is() )
xText->setEditable( !_bLock );
else
{
// disable the window
Reference<XWindow> xComp(xPeer, UNO_QUERY);
if (xComp.is())
xComp->setEnable(!_bLock);
Reference< XWindow > xComp( xPeer, UNO_QUERY );
if ( xComp.is() )
xComp->setEnable( !_bLock );
}
}
//--------------------------------------------------------------------
sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException)
{
implStartStopModelValidityListening( false );
sal_Bool bReturn = OControl::setModel( _rxModel );
implStartStopModelValidityListening( true );
implCheckValidity();
return bReturn;
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControl::componentValidityChanged( const EventObject& Source ) throw (RuntimeException)
{
implCheckValidity();
}
//--------------------------------------------------------------------
bool OBoundControl::implPropertyChanged( const ::rtl::OUString& _rPropertyName, const Any& _rValue )
{
// if the changed property is one of the properties which we use to indicate "invalidity" at the peer,
// we need to
// a) remember the value as "original value" (to restore when we're valid, again)
// b) ensure that our marking is forwarded to the peer, again (this is done by the caller, who
// may collect multiple changes)
bool bIsInvalidityIndicatorProperty = false;
if ( _rPropertyName == PROPERTY_HELPTEXT )
{
if ( !m_bLastKnownValidity && ( bIsInvalidityIndicatorProperty = true ) )
_rValue >>= m_sOriginalHelpText;
}
else if ( _rPropertyName == PROPERTY_FONT )
{
if ( !m_bLastKnownValidity && ( bIsInvalidityIndicatorProperty = true ) )
_rValue >>= m_aOriginalFont;
}
else if ( _rPropertyName == PROPERTY_TEXTLINECOLOR )
{
if ( !m_bLastKnownValidity && ( bIsInvalidityIndicatorProperty = true ) )
_rValue >>= m_nOriginalTextLineColor;
}
return bIsInvalidityIndicatorProperty;
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControl::propertiesChange( const Sequence< PropertyChangeEvent >& aEvent ) throw (RuntimeException)
{
// delegate to the aggregate
Reference< XPropertiesChangeListener > xAggregateListener;
if ( m_xAggregate.is() )
m_xAggregate->queryAggregation( ::getCppuType( &xAggregateListener ) ) >>= xAggregateListener;
if ( xAggregateListener.is() )
xAggregateListener->propertiesChange( aEvent );
// see if one of the changed properties is used by us to indicate invalidity
bool bValidityIndicatorPropertyChanged = false;
const PropertyChangeEvent* pEvent = aEvent.getConstArray();
const PropertyChangeEvent* pEventEnd = aEvent.getConstArray() + aEvent.getLength();
for ( ; pEvent != pEventEnd; ++pEvent )
bValidityIndicatorPropertyChanged |= implPropertyChanged( pEvent->PropertyName, pEvent->NewValue );
if ( bValidityIndicatorPropertyChanged )
implMarkInvalid( m_sLastKnownInvalidityExplanation );
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException)
{
// just disambiguate
OControl::disposing(Source);
}
//--------------------------------------------------------------------
void OBoundControl::disposing()
{
implStartStopModelValidityListening( false );
OControl::disposing();
}
//--------------------------------------------------------------------
void OBoundControl::implCheckValidity() SAL_THROW(())
{
try
{
// the validatable and the validator
Reference< XValidatableFormComponent > xValidatable( getModel(), UNO_QUERY );
Reference< XValidator > xValidator = xValidatable.is() ? xValidatable->getValidator() : Reference< XValidator >();
sal_Bool bIsCurrentlyValid = xValidatable.is() ? xValidatable->isValid() : sal_True;
::rtl::OUString sCurrentExplanation;
if ( !bIsCurrentlyValid && xValidator.is() )
sCurrentExplanation = xValidator->explainInvalid( xValidatable->getCurrentValue() );
if ( ( bIsCurrentlyValid == m_bLastKnownValidity ) && ( sCurrentExplanation == m_sLastKnownInvalidityExplanation ) )
// nothing to do
return;
if ( bIsCurrentlyValid )
implMarkValid( );
else
implMarkInvalid( sCurrentExplanation );
m_bLastKnownValidity = bIsCurrentlyValid;
m_sLastKnownInvalidityExplanation = sCurrentExplanation;
}
catch( const Exception& )
{
OSL_ENSURE( sal_False, "OBoundControl::implCheckValidity: caught an exception!" );
}
}
//--------------------------------------------------------------------
void OBoundControl::implMarkValid() SAL_THROW(( Exception ))
{
Reference< XVclWindowPeer > xPeer( getPeer(), UNO_QUERY );
if ( !xPeer.is() )
return;
// reset the help text
xPeer->setProperty( PROPERTY_HELPTEXT, makeAny( m_sOriginalHelpText ) );
m_sOriginalHelpText = ::rtl::OUString();
// reset the font
xPeer->setProperty( PROPERTY_FONT, makeAny( m_aOriginalFont ) );
m_aOriginalFont = EmptyFontDescriptor();
// reset the text line color
xPeer->setProperty( PROPERTY_TEXTLINECOLOR, makeAny( m_nOriginalTextLineColor ) );
m_nOriginalTextLineColor = 0;
}
//--------------------------------------------------------------------
void OBoundControl::implMarkInvalid( const ::rtl::OUString& _rExplanation ) SAL_THROW(( Exception ))
{
Reference< XVclWindowPeer > xPeer( getPeer(), UNO_QUERY );
if ( !xPeer.is() )
return;
if ( m_bLastKnownValidity )
{
// the last we know about validity is that our text/value was valid. So
// before doing anythiung, save the properties which we are going to modify
xPeer->getProperty( PROPERTY_HELPTEXT ) >>= m_sOriginalHelpText;
xPeer->getProperty( PROPERTY_FONT ) >>= m_aOriginalFont;
xPeer->getProperty( PROPERTY_TEXTLINECOLOR ) >>= m_nOriginalTextLineColor;
}
// set the invalidity explanation as help text
xPeer->setProperty( PROPERTY_HELPTEXT, makeAny( _rExplanation ) );
// modify the font
FontDescriptor aFont = EmptyFontDescriptor();
xPeer->getProperty( PROPERTY_FONT ) >>= aFont;
aFont.Underline = FontUnderline::WAVE;
xPeer->setProperty( PROPERTY_FONT, makeAny( aFont ) );
// modify the text line color (which is used for underlining)
xPeer->setProperty( PROPERTY_TEXTLINECOLOR, makeAny( (sal_Int32)0x00FF0000 ) );
}
//--------------------------------------------------------------------
void OBoundControl::implStartStopModelValidityListening( bool _bStart )
{
Reference< XValidatableFormComponent > xValidatable( getModel(), UNO_QUERY );
if ( xValidatable.is() )
if ( _bStart )
xValidatable->addFormComponentValidityListener( this );
else
xValidatable->removeFormComponentValidityListener( this );
Reference< XMultiPropertySet > xModelMultiProps( getModel(), UNO_QUERY );
if ( xModelMultiProps.is() )
{
Sequence< ::rtl::OUString > aNames( 3 );
aNames[ 0 ] = PROPERTY_HELPTEXT;
aNames[ 1 ] = PROPERTY_FONT;
aNames[ 2 ] = PROPERTY_TEXTLINECOLOR;
if ( _bStart )
xModelMultiProps->addPropertiesChangeListener( aNames, this );
else
xModelMultiProps->removePropertiesChangeListener( this );
}
}
@@ -946,6 +1180,16 @@ void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const A
}
}
//------------------------------------------------------------------------------
void OControlModel::fillProperties( Sequence< Property >& /* [out] */ _rProps, Sequence< Property >& /* [out] */ _rAggregateProps ) const
{
BEGIN_DESCRIBE_AGGREGATION_PROPERTIES( 3, m_xAggregateSet )
DECL_PROP2(CLASSID, sal_Int16, READONLY, TRANSIENT);
DECL_PROP1(NAME, ::rtl::OUString, BOUND);
DECL_PROP1(TAG, ::rtl::OUString, BOUND);
END_DESCRIBE_PROPERTIES()
}
//==================================================================
//= OBoundControlModel
//==================================================================
@@ -959,10 +1203,13 @@ Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (R
aReturn = OBoundControlModel_BASE1::queryInterface(_rType);
if ( !aReturn.hasValue() && m_bCommitable )
aReturn = OBoundControlModel_BASE2::queryInterface( _rType );
aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType );
if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
aReturn = OBoundControlModel_BASE3::queryInterface( _rType );
aReturn = OBoundControlModel_BINDING::queryInterface( _rType );
if ( !aReturn.hasValue() && m_bSupportsValidation )
aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType );
}
return aReturn;
@@ -970,25 +1217,26 @@ Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (R
//------------------------------------------------------------------
OBoundControlModel::OBoundControlModel(
const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory,
const ::rtl::OUString& _rUnoControlModelTypeName,
const ::rtl::OUString& _rDefault,
const sal_Bool _bCommitable,
const sal_Bool _bSupportExternalBinding)
const Reference< XMultiServiceFactory>& _rxFactory,
const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault,
const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation )
:OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False )
,OPropertyChangeListener( m_aMutex )
,m_aUpdateListeners(m_aMutex)
,m_aResetListeners(m_aMutex)
,m_pFormComponentListeners( new OFormComponentListeners( m_aMutex ) )
,m_bLoaded(sal_False)
,m_bRequired(sal_False)
,m_bCommitable(_bCommitable)
,m_bSupportsExternalBinding( _bSupportExternalBinding )
,m_bSupportsValidation( _bSupportsValidation )
,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
,m_bForwardValueChanges(sal_True)
,m_bLoadListening( sal_False )
,m_nValuePropertyAggregateHandle( -1 )
,m_pAggPropMultiplexer( NULL )
,m_bSettingAggregateState( sal_False )
,m_bIsCurrentValueValid( sal_True )
{
DBG_CTOR(frm_OBoundControlModel, NULL);
@@ -1003,15 +1251,19 @@ OBoundControlModel::OBoundControlModel(
,OPropertyChangeListener( m_aMutex )
,m_aUpdateListeners( m_aMutex )
,m_aResetListeners( m_aMutex )
,m_pFormComponentListeners( new OFormComponentListeners( m_aMutex ) )
,m_bLoaded( sal_False )
,m_bRequired( sal_False )
,m_bCommitable( _pOriginal->m_bCommitable )
,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
,m_bForwardValueChanges( sal_True )
,m_bLoadListening( sal_False )
,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
,m_pAggPropMultiplexer( NULL )
,m_bSettingAggregateState( sal_False )
,m_xValidator( _pOriginal->m_xValidator )
,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
{
DBG_CTOR(frm_OBoundControlModel, NULL);
@@ -1081,12 +1333,14 @@ void OBoundControlModel::implInitAggMultiplexer( )
void OBoundControlModel::implInitValuePropertyListening( ) const
{
// start listening for changes at the value property
// There are two pre-requisites for this to be done:
// There are three pre-requisites for this to be done:
// 1. We support external value bindings. In this case, the changes in the control value need to
// be propagated to the external binding immediately when they happen
// 2. We are not committable. In this case, changes in the control value need to be propagated
// 2. We support external validation. In this case, we need to listen for changes in the value
// property, since we need to revalidate then.
// 3. We are not committable. In this case, changes in the control value need to be propagated
// to the database column immediately when they happen.
if ( m_bSupportsExternalBinding || !m_bCommitable )
if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable )
{
OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() )
@@ -1157,10 +1411,13 @@ Sequence< Type > OBoundControlModel::_getTypes()
) );
if ( m_bCommitable )
appendSequence( aTypes, OBoundControlModel_BASE2::getTypes() );
appendSequence( aTypes, OBoundControlModel_COMMITTING::getTypes() );
if ( m_bSupportsExternalBinding )
appendSequence( aTypes, OBoundControlModel_BASE3::getTypes() );
appendSequence( aTypes, OBoundControlModel_BINDING::getTypes() );
if ( m_bSupportsValidation )
appendSequence( aTypes, OBoundControlModel_VALIDATION::getTypes() );
return aTypes;
}
@@ -1171,7 +1428,7 @@ void OBoundControlModel::disposing()
{
OControlModel::disposing();
osl::MutexGuard aGuard(m_aMutex);
::osl::ClearableMutexGuard aGuard(m_aMutex);
if ( m_pAggPropMultiplexer )
m_pAggPropMultiplexer->dispose();
@@ -1192,23 +1449,23 @@ void OBoundControlModel::disposing()
}
m_xCursor = NULL;
Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
if ( xComp.is() )
xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
// disconnect from our external value binding
if ( hasExternalValueBinding() )
disconnectExternalValueBinding();
Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
if ( xComp.is() )
xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
// dito for the validator
if ( hasValidator() )
disconnectValidator( );
}
//------------------------------------------------------------------------------
void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
if ( m_bSettingAggregateState )
// we caused this ourself
return;
::osl::ClearableMutexGuard aGuard( m_aMutex );
OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
"OBoundControlModel::_propertyChanged: where did this come from (1)?" );
@@ -1216,19 +1473,27 @@ void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) th
"OBoundControlModel::_propertyChanged: where did this come from (2)?" );
if ( _rEvt.PropertyName == m_sValuePropertyName )
{
if ( hasExternalValueBinding() )
{ // the control value changed, while we have an external value binding
// -> forward the value to it
transferControlValueToExternal( );
}
else if ( !m_bCommitable && m_xColumnUpdate.is() )
{ // the control value changed, while we have are bound to a database column,
// but not committable (which means changes in the control have to be reflected to
// the underlying database column immediately)
// -> forward the value to the database column
commitControlValueToDbColumn( false );
{ // our control value changed
if ( !m_bSettingAggregateState )
{ // not caused by ourself
if ( hasExternalValueBinding() )
{ // the control value changed, while we have an external value binding
// -> forward the value to it
transferControlValueToExternal( );
}
else if ( !m_bCommitable && m_xColumnUpdate.is() )
{ // the control value changed, while we have are bound to a database column,
// but not committable (which means changes in the control have to be reflected to
// the underlying database column immediately)
// -> forward the value to the database column
commitControlValueToDbColumn( false );
}
}
// validate the new value
if ( m_bSupportsValidation )
recheckValidity( true );
}
}
@@ -1294,7 +1559,7 @@ void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxPare
//------------------------------------------------------------------------------
void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
::osl::ClearableMutexGuard aGuard( m_aMutex );
if ( _rEvent.Source == m_xField )
{
resetField();
@@ -1311,9 +1576,14 @@ void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObj
OPropertySetHelper::fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False );
}
else if ( _rEvent.Source == m_xExternalBinding )
{
{ // *first* check for the external binding
disconnectExternalValueBinding( );
}
else if ( _rEvent.Source == m_xValidator )
{ // *then* check for the validator. Reason is that bindings may also act as validator at the same
// time, in this case, the validator is automatically revoked when the binding is revoked
disconnectValidator( );
}
else
OControlModel::disposing(_rEvent);
}
@@ -1388,10 +1658,10 @@ void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInp
nUsedFlag = _rxInStream->readLong();
if (nUsedFlag)
xPersist = _rxInStream->readObject();
m_xLabelControl = Reference<XPropertySet>(xPersist, UNO_QUERY);
Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
m_xLabelControl = m_xLabelControl.query( xPersist );
Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
if (xComp.is())
xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
// read any other new common properties here
@@ -1913,6 +2183,45 @@ void OBoundControlModel::setControlValue( const Any& _rValue )
m_bSettingAggregateState = sal_False;
}
//------------------------------------------------------------------------------
void OBoundControlModel::onConnectedValidator( )
{
try
{
// if we have an external validator, we do not want the control to force invalid
// inputs to the default value. Instead, invalid inputs should be translated
// to NaN (not a number)
Reference< XPropertySetInfo > xAggregatePropertyInfo;
if ( m_xAggregateSet.is() )
xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) );
}
catch( const Exception& )
{
OSL_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" );
}
recheckValidity( false );
}
//------------------------------------------------------------------------------
void OBoundControlModel::onDisconnectedValidator( )
{
try
{
Reference< XPropertySetInfo > xAggregatePropertyInfo;
if ( m_xAggregateSet.is() )
xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) );
}
catch( const Exception& )
{
OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" );
}
recheckValidity( false );
}
//------------------------------------------------------------------------------
void OBoundControlModel::onConnectedExternalValue( )
{
@@ -1972,7 +2281,7 @@ void OBoundControlModel::reset() throw (RuntimeException)
if (!bContinue)
return;
osl::ClearableMutexGuard aGuard(m_aMutex);
::osl::ClearableMutexGuard aGuard( m_aMutex );
sal_Bool bSimpleReset =
( !m_xColumn.is() // no connection to a database column
@@ -2046,10 +2355,16 @@ void OBoundControlModel::reset() throw (RuntimeException)
else
{
resetNoBroadcast();
// transfer to the external binding, if necessary
if ( hasExternalValueBinding() )
transferControlValueToExternal();
}
// revalidate, if necessary
if ( hasValidator() )
recheckValidity( true );
aGuard.clear();
cppu::OInterfaceIteratorHelper aIterDone(m_aResetListeners);
@@ -2110,6 +2425,19 @@ void OBoundControlModel::connectExternalValueBinding( const Reference< XValueBin
// propagate our new value
transferExternalValueToControl( );
// if the binding is also a validator, use it, too. This is a constraint of the
// com.sun.star.form.binding.ValidatableBindableFormComponent service
try
{
Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
if ( xAsValidator.is() )
setValidator( xAsValidator );
}
catch( const Exception& )
{
OSL_ENSURE( sal_False, "OBoundControlModel::connectExternalValueBinding: caught an exception while establishing the binding as validator!" );
}
}
//--------------------------------------------------------------------
@@ -2120,6 +2448,10 @@ void OBoundControlModel::disconnectExternalValueBinding( )
if ( xModifiable.is() )
xModifiable->removeModifyListener( this );
// if the binding also acts as our validator, disconnect the validator, too
if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
disconnectValidator( );
// no binding anymore
m_xExternalBinding.clear();
@@ -2147,10 +2479,9 @@ void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBindin
if ( _rxBinding.is() && !approveValueBinding( _rxBinding ) )
{
throw IncompatibleTypesException(
::rtl::OUString::createFromAscii( "The value types supported by the binding cannot be used for exchanging data with this control." ),
FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ),
*this
);
// TODO: localize this error message
}
// disconnect from the old binding
@@ -2251,11 +2582,23 @@ Any OBoundControlModel::translateExternalValueToControlValue( )
//------------------------------------------------------------------------------
Any OBoundControlModel::translateControlValueToExternalValue( )
{
return getControlValue( );
}
//------------------------------------------------------------------------------
Any OBoundControlModel::translateControlValueToValidatableValue( ) const
{
return getControlValue();
}
//------------------------------------------------------------------------------
Any OBoundControlModel::getControlValue( ) const
{
OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
"OBoundControlModel::translateControlValueToExternalValue: invalid aggregate !" );
"OBoundControlModel::getControlValue: invalid aggregate !" );
OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
"OBoundControlModel::translateControlValueToExternalValue: please override if you have own value property handling!" );
"OBoundControlModel::getControlValue: please override if you have own value property handling!" );
// determine the current control value
Any aControlValue;
@@ -2271,6 +2614,159 @@ Any OBoundControlModel::translateControlValueToExternalValue( )
return aControlValue;
}
//--------------------------------------------------------------------
void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
{
OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
m_xValidator = _rxValidator;
// add as value listener so we get notified when the value changes
if ( m_xValidator.is() )
{
try
{
m_xValidator->addValidityConstraintListener( this );
}
catch( const RuntimeException& )
{
}
}
onConnectedValidator( );
}
//--------------------------------------------------------------------
void OBoundControlModel::disconnectValidator( )
{
OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
// add as value listener so we get notified when the value changes
if ( m_xValidator.is() )
{
try
{
m_xValidator->removeValidityConstraintListener( this );
}
catch( const RuntimeException& )
{
}
}
m_xValidator.clear();
onDisconnectedValidator( );
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException)
{
::osl::ClearableMutexGuard aGuard( m_aMutex );
OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
// the interface for this method should not have been exposed if we do not
// support validation
if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
throw VetoException(
FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ),
*this
);
// disconnect from the old validator
if ( hasValidator() )
disconnectValidator( );
// connect to the new validator
if ( _rxValidator.is() )
connectValidator( _rxValidator );
}
//--------------------------------------------------------------------
Reference< XValidator > SAL_CALL OBoundControlModel::getValidator( ) throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
// the interface for this method should not have been exposed if we do not
// support validation
return m_xValidator;
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& Source ) throw (RuntimeException)
{
::osl::ClearableMutexGuard aGuard( m_aMutex );
OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
// the interface for this method should not have been exposed if we do not
// support validation
recheckValidity( false );
}
//--------------------------------------------------------------------
sal_Bool SAL_CALL OBoundControlModel::isValid( ) throw (RuntimeException)
{
return m_bIsCurrentValueValid;
}
//--------------------------------------------------------------------
Any SAL_CALL OBoundControlModel::getCurrentValue( ) throw (RuntimeException)
{
return translateControlValueToValidatableValue();
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException)
{
if ( !Listener.is() )
throw NullPointerException();
m_pFormComponentListeners->addListener( Listener );
}
//--------------------------------------------------------------------
void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException)
{
if ( !Listener.is() )
throw NullPointerException();
m_pFormComponentListeners->removeListener( Listener );
}
//--------------------------------------------------------------------
void OBoundControlModel::recheckValidity( bool _bForceNotification )
{
try
{
sal_Bool bIsCurrentlyValid = sal_True;
if ( hasValidator() )
bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
{
m_bIsCurrentValueValid = bIsCurrentlyValid;
// release our mutex for the notifications
MutexRelease aRelease( m_aMutex );
m_pFormComponentListeners->notify( EventObject( *this ) );
}
}
catch( const Exception& )
{
OSL_ENSURE( sal_False, "OBoundControlModel::recheckValidity: caught an exception!" );
}
}
//------------------------------------------------------------------------------
void OBoundControlModel::fillProperties( Sequence< Property >& /* [out] */ _rProps, Sequence< Property >& /* [out] */ _rAggregateProps ) const
{
BEGIN_DESCRIBE_PROPERTIES( 4, OControlModel )
DECL_PROP1 ( CONTROLSOURCE, ::rtl::OUString, BOUND );
DECL_IFACE_PROP3( BOUNDFIELD, XPropertySet, BOUND, READONLY, TRANSIENT );
DECL_IFACE_PROP2( CONTROLLABEL, XPropertySet, BOUND, MAYBEVOID );
DECL_PROP2 ( CONTROLSOURCEPROPERTY, ::rtl::OUString, READONLY, TRANSIENT );
END_DESCRIBE_PROPERTIES()
}
// -----------------------------------------------------------------------------
//.........................................................................