diff options
Diffstat (limited to 'forms/source/component/FormComponent.cxx')
-rw-r--r-- | forms/source/component/FormComponent.cxx | 3070 |
1 files changed, 0 insertions, 3070 deletions
diff --git a/forms/source/component/FormComponent.cxx b/forms/source/component/FormComponent.cxx deleted file mode 100644 index d57723920..000000000 --- a/forms/source/component/FormComponent.cxx +++ /dev/null @@ -1,3070 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_forms.hxx" - -#include "componenttools.hxx" -#include "FormComponent.hxx" -#include "frm_resource.hrc" -#include "frm_resource.hxx" -#include "property.hrc" -#include "services.hxx" - -/** === begin UNO includes === **/ -#include <com/sun/star/awt/XTextComponent.hpp> -#include <com/sun/star/awt/XVclWindowPeer.hpp> -#include <com/sun/star/awt/XWindow.hpp> -#include <com/sun/star/form/XForm.hpp> -#include <com/sun/star/form/XLoadable.hpp> -#include <com/sun/star/io/XMarkableStream.hpp> -#include <com/sun/star/lang/DisposedException.hpp> -#include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp> -#include <com/sun/star/sdb/XRowSetSupplier.hpp> -#include <com/sun/star/sdbc/ColumnValue.hpp> -#include <com/sun/star/sdbc/DataType.hpp> -#include <com/sun/star/util/XModifyBroadcaster.hpp> -/** === end UNO includes === **/ - -#include <comphelper/basicio.hxx> -#include <comphelper/guarding.hxx> -#include <comphelper/listenernotification.hxx> -#include <comphelper/property.hxx> -#include <connectivity/dbtools.hxx> -#include <cppuhelper/queryinterface.hxx> -#include <rtl/logfile.hxx> -#include <toolkit/helper/emptyfontdescriptor.hxx> -#include <tools/debug.hxx> -#include <tools/diagnose_ex.h> - -#include <functional> -#include <algorithm> - - -//... namespace frm ....................................................... -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 ::com::sun::star::form::binding; - using namespace ::com::sun::star::form::validation; - using namespace ::dbtools; - using namespace ::comphelper; - - //========================================================================= - //= FieldChangeNotifier - //========================================================================= - //------------------------------------------------------------------------- - void ControlModelLock::impl_notifyAll_nothrow() - { - m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() ); - } - - //------------------------------------------------------------------------- - void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue ) - { - sal_Int32 nOldLength = m_aHandles.getLength(); - if ( ( nOldLength != m_aOldValues.getLength() ) - || ( nOldLength != m_aNewValues.getLength() ) - ) - throw RuntimeException( ::rtl::OUString(), m_rModel ); - - m_aHandles.realloc( nOldLength + 1 ); - m_aHandles[ nOldLength ] = _nHandle; - m_aOldValues.realloc( nOldLength + 1 ); - m_aOldValues[ nOldLength ] = _rOldValue; - m_aNewValues.realloc( nOldLength + 1 ); - m_aNewValues[ nOldLength ] = _rNewValue; - } - - //========================================================================= - //= FieldChangeNotifier - //========================================================================= - //------------------------------------------------------------------------- - class FieldChangeNotifier - { - public: - FieldChangeNotifier( ControlModelLock& _rLock ) - :m_rLock( _rLock ) - ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) ) - { - m_xOldField = m_rModel.getField(); - } - - ~FieldChangeNotifier() - { - Reference< XPropertySet > xNewField( m_rModel.getField() ); - if ( m_xOldField != xNewField ) - m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) ); - } - - private: - ControlModelLock& m_rLock; - OBoundControlModel& m_rModel; - Reference< XPropertySet > m_xOldField; - }; - -//============================================================================= -//= base class for form layer controls -//============================================================================= -DBG_NAME(frm_OControl) -//------------------------------------------------------------------------------ -OControl::OControl( const Reference< XMultiServiceFactory >& _rxFactory, const rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator ) - :OComponentHelper(m_aMutex) - ,m_aContext( _rxFactory ) -{ - DBG_CTOR(frm_OControl, NULL); - // VCL-Control aggregieren - // bei Aggregation den Refcount um eins erhoehen da im setDelegator - // das Aggregat selbst den Refcount erhoeht - increment( m_refCount ); - { - m_xAggregate = m_xAggregate.query( _rxFactory->createInstance( _rAggregateService ) ); - m_xControl = m_xControl.query( m_xAggregate ); - } - decrement( m_refCount ); - - if ( _bSetDelegator ) - doSetDelegator(); -} - -//------------------------------------------------------------------------------ -OControl::~OControl() -{ - DBG_DTOR(frm_OControl, NULL); - doResetDelegator(); -} - -//------------------------------------------------------------------------------ -void OControl::doResetDelegator() -{ - if ( m_xAggregate.is() ) - m_xAggregate->setDelegator( NULL ); -} - -//------------------------------------------------------------------------------ -void OControl::doSetDelegator() -{ - increment( m_refCount ); - if ( m_xAggregate.is() ) - { // those brackets are important for some compilers, don't remove! - // (they ensure that the temporary object created in the line below - // is destroyed *before* the refcount-decrement) - m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); - } - decrement( m_refCount ); -} - -// UNO Anbindung -//------------------------------------------------------------------------------ -Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException) -{ - // ask the base class - Any aReturn( OComponentHelper::queryAggregation(_rType) ); - // ask our own interfaces - if (!aReturn.hasValue()) - { - aReturn = OControl_BASE::queryInterface(_rType); - // ask our aggregate - if (!aReturn.hasValue() && m_xAggregate.is()) - aReturn = m_xAggregate->queryAggregation(_rType); - } - - return aReturn; -} - -//------------------------------------------------------------------------------ -Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException) -{ - return OImplementationIds::getImplementationId(getTypes()); -} - -//------------------------------------------------------------------------------ -Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException) -{ - TypeBag aTypes( _getTypes() ); - - Reference< XTypeProvider > xProv; - if ( query_aggregation( m_xAggregate, xProv ) ) - aTypes.addTypes( xProv->getTypes() ); - - return aTypes.getTypes(); -} - -//------------------------------------------------------------------------------ -Sequence<Type> OControl::_getTypes() -{ - return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes(); -} - -//------------------------------------------------------------------------------ -void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ ) -{ - // nothing to do here -} - -// OComponentHelper -//------------------------------------------------------------------------------ -void OControl::disposing() -{ - OComponentHelper::disposing(); - - m_aWindowStateGuard.attach( NULL, NULL ); - - Reference< XComponent > xComp; - if (query_aggregation(m_xAggregate, xComp)) - xComp->dispose(); -} - -// XServiceInfo -//------------------------------------------------------------------------------ -sal_Bool SAL_CALL OControl::supportsService(const rtl::OUString& _rsServiceName) throw ( RuntimeException) -{ - Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); - const rtl::OUString* pSupported = aSupported.getConstArray(); - for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) - if (pSupported->equals(_rsServiceName)) - return sal_True; - return sal_False; -} - -//------------------------------------------------------------------------------ -Sequence< ::rtl::OUString > OControl::getAggregateServiceNames() -{ - Sequence< ::rtl::OUString > aAggServices; - Reference< XServiceInfo > xInfo; - if ( query_aggregation( m_xAggregate, xInfo ) ) - aAggServices = xInfo->getSupportedServiceNames(); - return aAggServices; -} - -//------------------------------------------------------------------------------ -Sequence<rtl::OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException) -{ - return ::comphelper::concatSequences( - getAggregateServiceNames(), - getSupportedServiceNames_Static() - ); -} - -//------------------------------------------------------------------------------ -Sequence< ::rtl::OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException ) -{ - // no own supported service names - return Sequence< ::rtl::OUString >(); -} - -// XEventListener -//------------------------------------------------------------------------------ -void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException) -{ - Reference< XInterface > xAggAsIface; - query_aggregation(m_xAggregate, xAggAsIface); - - // does the disposing come from the aggregate ? - if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY)) - { // no -> forward it - Reference<com::sun::star::lang::XEventListener> xListener; - if (query_aggregation(m_xAggregate, xListener)) - xListener->disposing(_rEvent); - } -} - -// XControl -//------------------------------------------------------------------------------ -void SAL_CALL OControl::setContext(const Reference< XInterface >& Context) throw (RuntimeException) -{ - if (m_xControl.is()) - m_xControl->setContext(Context); -} - -//------------------------------------------------------------------------------ -Reference< XInterface > SAL_CALL OControl::getContext() throw (RuntimeException) -{ - return m_xControl.is() ? m_xControl->getContext() : Reference< XInterface >(); -} - -//------------------------------------------------------------------------------ -void OControl::impl_resetStateGuard_nothrow() -{ - Reference< XWindow2 > xWindow; - Reference< XControlModel > xModel; - try - { - xWindow.set( getPeer(), UNO_QUERY ); - xModel.set( getModel(), UNO_QUERY ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - m_aWindowStateGuard.attach( xWindow, xModel ); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException) -{ - if ( m_xControl.is() ) - { - m_xControl->createPeer( _rxToolkit, _rxParent ); - - initFormControlPeer( getPeer() ); - - impl_resetStateGuard_nothrow(); - } -} - -//------------------------------------------------------------------------------ -Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException) -{ - return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>(); -} - -//------------------------------------------------------------------------------ -sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException) -{ - if ( !m_xControl.is() ) - return sal_False; - - sal_Bool bSuccess = m_xControl->setModel( Model ); - impl_resetStateGuard_nothrow(); - return bSuccess; -} - -//------------------------------------------------------------------------------ -Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException) -{ - 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>(); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException) -{ - if (m_xControl.is()) - m_xControl->setDesignMode(bOn); -} - -//------------------------------------------------------------------------------ -sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException) -{ - return m_xControl.is() ? m_xControl->isDesignMode() : sal_True; -} - -//------------------------------------------------------------------------------ -sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException) -{ - return m_xControl.is() ? m_xControl->isTransparent() : sal_True; -} - -//================================================================== -//= OBoundControl -//================================================================== -DBG_NAME(frm_OBoundControl); -//------------------------------------------------------------------ -OBoundControl::OBoundControl( const Reference< XMultiServiceFactory >& _rxFactory, - const ::rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator ) - :OControl( _rxFactory, _rAggregateService, _bSetDelegator ) - ,m_bLocked(sal_False) - ,m_aOriginalFont( EmptyFontDescriptor() ) - ,m_nOriginalTextLineColor( 0 ) -{ - DBG_CTOR(frm_OBoundControl, NULL); -} - -//------------------------------------------------------------------ -OBoundControl::~OBoundControl() -{ - DBG_DTOR(frm_OBoundControl, NULL); -} -// ----------------------------------------------------------------------------- -Sequence< Type> OBoundControl::_getTypes() -{ - return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes(); -} -//------------------------------------------------------------------ -Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException) -{ - Any aReturn; - - // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types - if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) ) - aReturn = OControl::queryAggregation( _rType ); - - // ask our own interfaces - // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener) - if ( !aReturn.hasValue() ) - aReturn = OBoundControl_BASE::queryInterface( _rType ); - - // ask the base class - if ( !aReturn.hasValue() ) - aReturn = OControl::queryAggregation( _rType ); - - return aReturn; -} - -//------------------------------------------------------------------ -sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException) -{ - return m_bLocked; -} - -//------------------------------------------------------------------ -void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException) -{ - if (m_bLocked == _bLock) - return; - - osl::MutexGuard aGuard(m_aMutex); - _setLock(_bLock); - m_bLocked = _bLock; -} - -//------------------------------------------------------------------ -void OBoundControl::_setLock(sal_Bool _bLock) -{ - // try to set the text component to readonly - Reference< XWindowPeer > xPeer = getPeer(); - Reference< XTextComponent > xText( xPeer, UNO_QUERY ); - - if ( xText.is() ) - xText->setEditable( !_bLock ); - else - { - // disable the window - Reference< XWindow > xComp( xPeer, UNO_QUERY ); - if ( xComp.is() ) - xComp->setEnable( !_bLock ); - } -} - -//-------------------------------------------------------------------- -sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException) -{ - return OControl::setModel( _rxModel ); -} - -//-------------------------------------------------------------------- -void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException) -{ - // just disambiguate - OControl::disposing(Source); -} - -//-------------------------------------------------------------------- -void OBoundControl::disposing() -{ - OControl::disposing(); -} - -//================================================================== -//= OControlModel -//================================================================== -DBG_NAME(OControlModel) -//------------------------------------------------------------------ -Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException) -{ - return OImplementationIds::getImplementationId(getTypes()); -} - -//------------------------------------------------------------------ -Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException) -{ - TypeBag aTypes( _getTypes() ); - - Reference< XTypeProvider > xProv; - if ( query_aggregation( m_xAggregate, xProv ) ) - aTypes.addTypes( xProv->getTypes() ); - - return aTypes.getTypes(); -} - -//------------------------------------------------------------------------------ -Sequence<Type> OControlModel::_getTypes() -{ - return TypeBag( OComponentHelper::getTypes(), - OPropertySetAggregationHelper::getTypes(), - OControlModel_BASE::getTypes() - ).getTypes(); -} - -//------------------------------------------------------------------ -Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) -{ - // base class 1 - Any aReturn(OComponentHelper::queryAggregation(_rType)); - - // base class 2 - if (!aReturn.hasValue()) - { - aReturn = OControlModel_BASE::queryInterface(_rType); - - // our own interfaces - if (!aReturn.hasValue()) - { - aReturn = OPropertySetAggregationHelper::queryInterface(_rType); - // our aggregate - if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL)))) - aReturn = m_xAggregate->queryAggregation(_rType); - } - } - return aReturn; -} - -//------------------------------------------------------------------------------ -void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream) -{ - ::rtl::OUString sHelpText; - ::comphelper::operator>>( _rxInStream, sHelpText); - try - { - if (m_xAggregateSet.is()) - m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText)); - } - catch(const Exception&) - { - OSL_FAIL("OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!"); - } -} - -//------------------------------------------------------------------------------ -void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream) -{ - ::rtl::OUString sHelpText; - try - { - if (m_xAggregateSet.is()) - m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText; - } - catch(const Exception&) - { - OSL_FAIL("OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!"); - } - ::comphelper::operator<<( _rxOutStream, sHelpText); -} - -//------------------------------------------------------------------ -OControlModel::OControlModel( - const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory, - const ::rtl::OUString& _rUnoControlModelTypeName, - const ::rtl::OUString& rDefault, const sal_Bool _bSetDelegator) - :OComponentHelper(m_aMutex) - ,OPropertySetAggregationHelper(OComponentHelper::rBHelper) - ,m_aContext( _rxFactory ) - ,m_lockCount( 0 ) - ,m_aPropertyBagHelper( *this ) - ,m_nTabIndex(FRM_DEFAULT_TABINDEX) - ,m_nClassId(FormComponentType::CONTROL) - ,m_bNativeLook( sal_False ) - // form controls are usually embedded into documents, not dialogs, and in documents - // the native look is ugly .... - // #i37342# -{ - DBG_CTOR(OControlModel, NULL); - if (_rUnoControlModelTypeName.getLength()) // the is a model we have to aggregate - { - increment(m_refCount); - - { - m_xAggregate = Reference<XAggregation>(_rxFactory->createInstance(_rUnoControlModelTypeName), UNO_QUERY); - setAggregation(m_xAggregate); - - if ( m_xAggregateSet.is() ) - { - try - { - if ( rDefault.getLength() ) - m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) ); - } - catch( const Exception& ) - { - OSL_FAIL( "OControlModel::OControlModel: caught an exception!" ); - } - } - } - - if (_bSetDelegator) - doSetDelegator(); - - // Refcount wieder bei NULL - decrement(m_refCount); - } -} - -//------------------------------------------------------------------ -OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator ) - :OComponentHelper( m_aMutex ) - ,OPropertySetAggregationHelper( OComponentHelper::rBHelper ) - ,m_aContext( _rxFactory ) - ,m_lockCount( 0 ) - ,m_aPropertyBagHelper( *this ) - ,m_nTabIndex( FRM_DEFAULT_TABINDEX ) - ,m_nClassId( FormComponentType::CONTROL ) -{ - DBG_CTOR( OControlModel, NULL ); - DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" ); - - // copy members - m_aName = _pOriginal->m_aName; - m_aTag = _pOriginal->m_aTag; - m_nTabIndex = _pOriginal->m_nTabIndex; - m_nClassId = _pOriginal->m_nClassId; - m_bNativeLook = _pOriginal->m_bNativeLook; - - if ( _bCloneAggregate ) - { - // temporarily increment refcount because of temporary references to ourself in the following - increment( m_refCount ); - - { - // transfer the (only, at the very moment!) ref count - m_xAggregate = createAggregateClone( _pOriginal ); - - // set aggregation (retrieve other direct interfaces of the aggregate) - setAggregation( m_xAggregate ); - } - - // set the delegator, if allowed by our derived class - if ( _bSetDelegator ) - doSetDelegator(); - - // decrement ref count - decrement( m_refCount ); - } -} - -//------------------------------------------------------------------ -OControlModel::~OControlModel() -{ - // release the aggregate - doResetDelegator( ); - - DBG_DTOR(OControlModel, NULL); -} - -//------------------------------------------------------------------ -void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ ) -{ - // nothing to do in this base class -} - -//------------------------------------------------------------------------------ -void OControlModel::doResetDelegator() -{ - if (m_xAggregate.is()) - m_xAggregate->setDelegator(NULL); -} - -//------------------------------------------------------------------------------ -void OControlModel::doSetDelegator() -{ - increment(m_refCount); - if (m_xAggregate.is()) - { - m_xAggregate->setDelegator(static_cast<XWeak*>(this)); - } - decrement(m_refCount); -} - -// XChild -//------------------------------------------------------------------------------ -Reference< XInterface > SAL_CALL OControlModel::getParent() throw(RuntimeException) -{ - return m_xParent; -} - -//------------------------------------------------------------------------------ -void SAL_CALL OControlModel::setParent(const Reference< XInterface >& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException) -{ - osl::MutexGuard aGuard(m_aMutex); - - Reference<XComponent> xComp(m_xParent, UNO_QUERY); - if (xComp.is()) - xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this)); - - m_xParent = _rxParent; - xComp = xComp.query( m_xParent ); - - if ( xComp.is() ) - xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this)); -} - -// XNamed -//------------------------------------------------------------------------------ -::rtl::OUString SAL_CALL OControlModel::getName() throw(RuntimeException) -{ - ::rtl::OUString aReturn; - OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn; - return aReturn; -} - -//------------------------------------------------------------------------------ -void SAL_CALL OControlModel::setName(const ::rtl::OUString& _rName) throw(RuntimeException) -{ - setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName)); -} - -// XServiceInfo -//------------------------------------------------------------------------------ -sal_Bool SAL_CALL OControlModel::supportsService(const rtl::OUString& _rServiceName) throw ( RuntimeException) -{ - Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); - const rtl::OUString* pSupported = aSupported.getConstArray(); - for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) - if (pSupported->equals(_rServiceName)) - return sal_True; - return sal_False; -} - -//------------------------------------------------------------------------------ -Sequence< ::rtl::OUString > OControlModel::getAggregateServiceNames() -{ - Sequence< ::rtl::OUString > aAggServices; - Reference< XServiceInfo > xInfo; - if ( query_aggregation( m_xAggregate, xInfo ) ) - aAggServices = xInfo->getSupportedServiceNames(); - return aAggServices; -} - -//------------------------------------------------------------------------------ -Sequence<rtl::OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException) -{ - return ::comphelper::concatSequences( - getAggregateServiceNames(), - getSupportedServiceNames_Static() - ); -} - -//------------------------------------------------------------------------------ -Sequence< ::rtl::OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException ) -{ - Sequence< ::rtl::OUString > aServiceNames( 2 ); - aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT; - aServiceNames[ 1 ] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.FormControlModel") ); - return aServiceNames; -} - -// XEventListener -//------------------------------------------------------------------------------ -void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException) -{ - // release the parent - if (_rSource.Source == m_xParent) - { - osl::MutexGuard aGuard(m_aMutex); - m_xParent = NULL; - } - else - { - Reference<com::sun::star::lang::XEventListener> xEvtLst; - if (query_aggregation(m_xAggregate, xEvtLst)) - { - osl::MutexGuard aGuard(m_aMutex); - xEvtLst->disposing(_rSource); - } - } -} - -// OComponentHelper -//----------------------------------------------------------------------------- -void OControlModel::disposing() -{ - OPropertySetAggregationHelper::disposing(); - - Reference<com::sun::star::lang::XComponent> xComp; - if (query_aggregation(m_xAggregate, xComp)) - xComp->dispose(); - - setParent(Reference<XFormComponent>()); - - m_aPropertyBagHelper.dispose(); -} - -//------------------------------------------------------------------------------ -void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const -{ - Reference< XPersistObject > xPersist; - if ( query_aggregation( m_xAggregate, xPersist ) ) - xPersist->write( _rxOutStream ); -} - -//------------------------------------------------------------------------------ -void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream ) -{ - Reference< XPersistObject > xPersist; - if ( query_aggregation( m_xAggregate, xPersist ) ) - xPersist->read( _rxInStream ); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) - throw(stario::IOException, RuntimeException) -{ - osl::MutexGuard aGuard(m_aMutex); - - // 1. Schreiben des UnoControls - Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY); - if ( !xMark.is() ) - { - throw IOException( - FRM_RES_STRING( RID_STR_INVALIDSTREAM ), - static_cast< ::cppu::OWeakObject* >( this ) - ); - } - - sal_Int32 nMark = xMark->createMark(); - sal_Int32 nLen = 0; - - _rxOutStream->writeLong(nLen); - - writeAggregate( _rxOutStream ); - - // feststellen der Laenge - nLen = xMark->offsetToMark(nMark) - 4; - xMark->jumpToMark(nMark); - _rxOutStream->writeLong(nLen); - xMark->jumpToFurthest(); - xMark->deleteMark(nMark); - - // 2. Schreiben einer VersionsNummer - _rxOutStream->writeShort(0x0003); - - // 3. Schreiben der allgemeinen Properties - ::comphelper::operator<<( _rxOutStream, m_aName); - _rxOutStream->writeShort(m_nTabIndex); - ::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version - - // !!! IMPORTANT NOTE !!! - // don't write any new members here : this wouldn't be compatible with older versions, as OControlModel - // is a base class which is called in derived classes "read" method. So if you increment the version - // and write new stuff, older office versions will read this in the _derived_ classes, which may result - // in anything from data loss to crash. - // !!! EOIN !!! -} - -//------------------------------------------------------------------------------ -void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException) -{ - osl::MutexGuard aGuard(m_aMutex); - - Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY); - if ( !xMark.is() ) - { - throw IOException( - FRM_RES_STRING( RID_STR_INVALIDSTREAM ), - static_cast< ::cppu::OWeakObject* >( this ) - ); - } - - // 1. Lesen des UnoControls - sal_Int32 nLen = InStream->readLong(); - if (nLen) - { - sal_Int32 nMark = xMark->createMark(); - - try - { - readAggregate( InStream ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - - xMark->jumpToMark(nMark); - InStream->skipBytes(nLen); - xMark->deleteMark(nMark); - } - - // 2. Lesen des Versionsnummer - sal_uInt16 nVersion = InStream->readShort(); - - // 3. Lesen der allgemeinen Properties - ::comphelper::operator>>( InStream, m_aName); - m_nTabIndex = InStream->readShort(); - - if (nVersion > 0x0002) - ::comphelper::operator>>( InStream, m_aTag); - - // we had a version where we wrote the help text - if (nVersion == 0x0004) - readHelpTextCompatibly(InStream); - - DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !"); - // 4 was the version where we wrote the help text - // later versions shouldn't exist (see write for a detailed comment) -} - -//------------------------------------------------------------------------------ -PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle ) -{ - // simply compare the current and the default value - Any aCurrentValue = getPropertyDefaultByHandle( _nHandle ); - Any aDefaultValue; getFastPropertyValue( aDefaultValue, _nHandle ); - - sal_Bool bEqual = uno_type_equalData( - const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(), - const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(), - reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), - reinterpret_cast< uno_ReleaseFunc >(cpp_release) - ); - return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; -} - -//------------------------------------------------------------------------------ -void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle) -{ - Any aDefault = getPropertyDefaultByHandle( _nHandle ); - - Any aConvertedValue, aOldValue; - if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) ) - { - setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue ); - // TODO: fire the property change - } -} - -//------------------------------------------------------------------------------ -Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const -{ - Any aReturn; - switch ( _nHandle ) - { - case PROPERTY_ID_NAME: - case PROPERTY_ID_TAG: - aReturn <<= ::rtl::OUString(); - break; - - case PROPERTY_ID_CLASSID: - aReturn <<= (sal_Int16)FormComponentType::CONTROL; - break; - - case PROPERTY_ID_TABINDEX: - aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX; - break; - - case PROPERTY_ID_NATIVE_LOOK: - aReturn <<= (sal_Bool)sal_True; - break; - - default: - if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) - m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn ); - else - OSL_FAIL( "OControlModel::convertFastPropertyValue: unknown handle!" ); - } - return aReturn; -} - -//------------------------------------------------------------------------------ -void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const -{ - switch ( _nHandle ) - { - case PROPERTY_ID_NAME: - _rValue <<= m_aName; - break; - case PROPERTY_ID_TAG: - _rValue <<= m_aTag; - break; - case PROPERTY_ID_CLASSID: - _rValue <<= m_nClassId; - break; - case PROPERTY_ID_TABINDEX: - _rValue <<= m_nTabIndex; - break; - case PROPERTY_ID_NATIVE_LOOK: - _rValue <<= (sal_Bool)m_bNativeLook; - break; - default: - if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) - m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue ); - else - OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle ); - break; - } -} - -//------------------------------------------------------------------------------ -sal_Bool OControlModel::convertFastPropertyValue( - Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) - throw (com::sun::star::lang::IllegalArgumentException) -{ - sal_Bool bModified(sal_False); - switch (_nHandle) - { - case PROPERTY_ID_NAME: - bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName); - break; - case PROPERTY_ID_TAG: - bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag); - break; - case PROPERTY_ID_TABINDEX: - bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex); - break; - case PROPERTY_ID_NATIVE_LOOK: - bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook); - break; - default: - if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) - bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue ); - else - OSL_FAIL( "OControlModel::convertFastPropertyValue: unknown handle!" ); - break; - } - return bModified; -} - -//------------------------------------------------------------------------------ -void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) - throw (Exception) -{ - switch (_nHandle) - { - case PROPERTY_ID_NAME: - DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL), - "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); - _rValue >>= m_aName; - break; - case PROPERTY_ID_TAG: - DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL), - "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); - _rValue >>= m_aTag; - break; - case PROPERTY_ID_TABINDEX: - DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL), - "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); - _rValue >>= m_nTabIndex; - break; - case PROPERTY_ID_NATIVE_LOOK: - OSL_VERIFY( _rValue >>= m_bNativeLook ); - break; - default: - if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) - m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue ); - else - OSL_FAIL( "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" ); - break; - } -} - -//------------------------------------------------------------------------------ -void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const -{ - BEGIN_DESCRIBE_BASE_PROPERTIES( 4 ) - DECL_PROP2 (CLASSID, sal_Int16, READONLY, TRANSIENT); - DECL_PROP1 (NAME, ::rtl::OUString, BOUND); - DECL_BOOL_PROP2 (NATIVE_LOOK, BOUND, TRANSIENT); - DECL_PROP1 (TAG, ::rtl::OUString, BOUND); - END_DESCRIBE_PROPERTIES() -} - -//------------------------------------------------------------------------------ -void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const -{ - if ( m_xAggregateSet.is() ) - { - Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() ); - if ( xPSI.is() ) - _rAggregateProps = xPSI->getProperties(); - } -} - -//------------------------------------------------------------------------------ -::osl::Mutex& OControlModel::getMutex() -{ - return m_aMutex; -} - -//------------------------------------------------------------------------------ -void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const -{ - describeFixedProperties( _out_rFixedProperties ); - describeAggregateProperties( _out_rAggregateProperties ); -} - -//------------------------------------------------------------------------------ -Reference< XMultiPropertySet > OControlModel::getPropertiesInterface() -{ - return Reference< XMultiPropertySet >( *this, UNO_QUERY ); -} - -//------------------------------------------------------------------------------ -Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException) -{ - return createPropertySetInfo( getInfoHelper() ); -} - -//------------------------------------------------------------------------------ -::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper() -{ - return m_aPropertyBagHelper.getInfoHelper(); -} - -//-------------------------------------------------------------------- -void SAL_CALL OControlModel::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) -{ - m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue ); -} - -//-------------------------------------------------------------------- -void SAL_CALL OControlModel::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) -{ - m_aPropertyBagHelper.removeProperty( _rName ); -} - -//-------------------------------------------------------------------- -Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException) -{ - return m_aPropertyBagHelper.getPropertyValues(); -} - -//-------------------------------------------------------------------- -void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) -{ - m_aPropertyBagHelper.setPropertyValues( _rProps ); -} - -//-------------------------------------------------------------------- -void OControlModel::lockInstance( LockAccess ) -{ - m_aMutex.acquire(); - osl_incrementInterlockedCount( &m_lockCount ); -} - -//-------------------------------------------------------------------- -oslInterlockedCount OControlModel::unlockInstance( LockAccess ) -{ - OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" ); - oslInterlockedCount lockCount = osl_decrementInterlockedCount( &m_lockCount ); - m_aMutex.release(); - return lockCount; -} - -//-------------------------------------------------------------------- -void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues, - const Sequence< Any >& _rNewValues, LockAccess ) -{ - OPropertySetHelper::fire( - const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(), - _rNewValues.getConstArray(), - _rOldValues.getConstArray(), - _rHandles.getLength(), - sal_False - ); -} - -//================================================================== -//= OBoundControlModel -//================================================================== -DBG_NAME(frm_OBoundControlModel); -//------------------------------------------------------------------ -Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException) -{ - Any aReturn( OControlModel::queryAggregation(_rType) ); - if (!aReturn.hasValue()) - { - aReturn = OBoundControlModel_BASE1::queryInterface(_rType); - - if ( !aReturn.hasValue() && m_bCommitable ) - aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType ); - - if ( !aReturn.hasValue() && m_bSupportsExternalBinding ) - aReturn = OBoundControlModel_BINDING::queryInterface( _rType ); - - if ( !aReturn.hasValue() && m_bSupportsValidation ) - aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType ); - } - - return aReturn; -} - -//------------------------------------------------------------------ -OBoundControlModel::OBoundControlModel( - 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_xField() - ,m_xAmbientForm() - ,m_nValuePropertyAggregateHandle( -1 ) - ,m_nFieldType( DataType::OTHER ) - ,m_bValuePropertyMayBeVoid( false ) - ,m_aResetHelper( *this, m_aMutex ) - ,m_aUpdateListeners(m_aMutex) - ,m_aFormComponentListeners( m_aMutex ) - ,m_bInputRequired( sal_True ) - ,m_pAggPropMultiplexer( NULL ) - ,m_bFormListening( false ) - ,m_bLoaded(sal_False) - ,m_bRequired(sal_False) - ,m_bCommitable(_bCommitable) - ,m_bSupportsExternalBinding( _bSupportExternalBinding ) - ,m_bSupportsValidation( _bSupportsValidation ) - ,m_bForwardValueChanges(sal_True) - ,m_bTransferingValue( sal_False ) - ,m_bIsCurrentValueValid( sal_True ) - ,m_bBindingControlsRO( sal_False ) - ,m_bBindingControlsEnable( sal_False ) - ,m_eControlValueChangeInstigator( eOther ) - ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT) -{ - DBG_CTOR(frm_OBoundControlModel, NULL); - - // start property listening at the aggregate - implInitAggMultiplexer( ); -} - -//------------------------------------------------------------------ -OBoundControlModel::OBoundControlModel( - const OBoundControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory ) - :OControlModel( _pOriginal, _rxFactory, sal_True, sal_False ) - ,OPropertyChangeListener( m_aMutex ) - ,m_xField() - ,m_xAmbientForm() - ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle ) - ,m_nFieldType( DataType::OTHER ) - ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid ) - ,m_aResetHelper( *this, m_aMutex ) - ,m_aUpdateListeners( m_aMutex ) - ,m_aFormComponentListeners( m_aMutex ) - ,m_xValidator( _pOriginal->m_xValidator ) - ,m_bInputRequired( sal_True ) - ,m_pAggPropMultiplexer( NULL ) - ,m_bFormListening( false ) - ,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_bTransferingValue( sal_False ) - ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid ) - ,m_bBindingControlsRO( sal_False ) - ,m_bBindingControlsEnable( sal_False ) - ,m_eControlValueChangeInstigator( eOther ) -{ - DBG_CTOR(frm_OBoundControlModel, NULL); - - // start property listening at the aggregate - implInitAggMultiplexer( ); - - m_aLabelServiceName = _pOriginal->m_aLabelServiceName; - m_sValuePropertyName = _pOriginal->m_sValuePropertyName; - m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle; - m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid; - m_aValuePropertyType = _pOriginal->m_aValuePropertyType; - m_aControlSource = _pOriginal->m_aControlSource; - m_bInputRequired = _pOriginal->m_bInputRequired; - // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transfered. - // (the former should be clear - a clone of the object we're only referencing does not make sense) - // (the second would violate the restriction for label controls that they're part of the - // same form component hierarchy - we ourself are no part, yet, so we can't have a label control) - - // start listening for changes at the value property - implInitValuePropertyListening( ); -} - -//------------------------------------------------------------------ -OBoundControlModel::~OBoundControlModel() -{ - if ( !OComponentHelper::rBHelper.bDisposed ) - { - acquire(); - dispose(); - } - - doResetDelegator( ); - - OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" ); - if ( m_pAggPropMultiplexer ) - { - m_pAggPropMultiplexer->dispose(); - m_pAggPropMultiplexer->release(); - m_pAggPropMultiplexer = NULL; - } - - DBG_DTOR(frm_OBoundControlModel, NULL); -} - -//------------------------------------------------------------------ -void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal ) -{ - const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal ); - // the value binding can be handled as if somebody called setValueBinding here - // By definition, bindings can be share between bindables - if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() ) - { - try - { - setValueBinding( pBoundOriginal->m_xExternalBinding ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - } -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::implInitAggMultiplexer( ) -{ - increment( m_refCount ); - if ( m_xAggregateSet.is() ) - { - m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, sal_False ); - m_pAggPropMultiplexer->acquire(); - } - decrement( m_refCount ); - - doSetDelegator(); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::implInitValuePropertyListening( ) const -{ - // start listening for changes at the value property - // 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 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_bSupportsValidation || !m_bCommitable ) - { - OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" ); - if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() ) - m_pAggPropMultiplexer->addProperty( m_sValuePropertyName ); - } -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::initOwnValueProperty( const ::rtl::OUString& i_rValuePropertyName ) -{ - OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle, - "OBoundControlModel::initOwnValueProperty: value property is already initialized!" ); - OSL_ENSURE( i_rValuePropertyName.getLength(), "OBoundControlModel::initOwnValueProperty: invalid property name!" ); - m_sValuePropertyName = i_rValuePropertyName; -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::initValueProperty( const ::rtl::OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle ) -{ - OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle, - "OBoundControlModel::initValueProperty: value property is already initialized!" ); - OSL_ENSURE( _rValuePropertyName.getLength(), "OBoundControlModel::initValueProperty: invalid property name!" ); - OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" ); - - m_sValuePropertyName = _rValuePropertyName; - m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle ); - OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" ); - - if ( m_nValuePropertyAggregateHandle != -1 ) - { - Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW ); - Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName ); - m_aValuePropertyType = aValuePropDesc.Type; - m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0; - } - - // start listening for changes at the value property - implInitValuePropertyListening( ); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::suspendValueListening( ) -{ - OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::suspendValueListening: don't have a value property!" ); - OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" ); - - if ( m_pAggPropMultiplexer ) - m_pAggPropMultiplexer->lock(); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::resumeValueListening( ) -{ - OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::resumeValueListening: don't have a value property!" ); - OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" ); - OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" ); - - if ( m_pAggPropMultiplexer ) - m_pAggPropMultiplexer->unlock(); -} - -//----------------------------------------------------------------------------- -Sequence< Type > OBoundControlModel::_getTypes() -{ - TypeBag aTypes( - OControlModel::_getTypes(), - OBoundControlModel_BASE1::getTypes() - ); - - if ( m_bCommitable ) - aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() ); - - if ( m_bSupportsExternalBinding ) - aTypes.addTypes( OBoundControlModel_BINDING::getTypes() ); - - if ( m_bSupportsValidation ) - aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() ); - - return aTypes.getTypes(); -} - -// OComponentHelper -//----------------------------------------------------------------------------- -void OBoundControlModel::disposing() -{ - OControlModel::disposing(); - - ::osl::ClearableMutexGuard aGuard(m_aMutex); - - if ( m_pAggPropMultiplexer ) - m_pAggPropMultiplexer->dispose(); - - // notify all our listeners - com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) ); - m_aUpdateListeners.disposeAndClear( aEvt ); - m_aResetHelper.disposing(); - - // disconnect from our database column - // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify? - // The only more thing which it does is calling onDisconnectedDbColumn - could this - // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*. - if ( hasField() ) - { - getField()->removePropertyChangeListener( PROPERTY_VALUE, this ); - resetField(); - } - 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(); - - // dito for the validator - if ( hasValidator() ) - disconnectValidator( ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::onValuePropertyChange( ControlModelLock& i_rControLock ) -{ - if ( hasExternalValueBinding() ) - { // the control value changed, while we have an external value binding - // -> forward the value to it - if ( m_eControlValueChangeInstigator != eExternalBinding ) - transferControlValueToExternal( i_rControLock ); - } - else if ( !m_bCommitable && m_xColumnUpdate.is() ) - { // the control value changed, while we 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 - if ( m_eControlValueChangeInstigator != eDbColumnBinding ) - commitControlValueToDbColumn( false ); - } - - // validate the new value - if ( m_bSupportsValidation ) - recheckValidity( true ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException ) -{ - ControlModelLock aLock( *this ); - - OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName, - "OBoundControlModel::_propertyChanged: where did this come from (1)?" ); - OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(), - "OBoundControlModel::_propertyChanged: where did this come from (2)?" ); - - if ( _rEvt.PropertyName == m_sValuePropertyName ) - { - onValuePropertyChange( aLock ); - } -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName ) -{ - OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" ); - OSL_ENSURE( _rPropertyName.getLength(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" ); - - if ( m_pAggPropMultiplexer && _rPropertyName.getLength() ) - { - m_pAggPropMultiplexer->addProperty( _rPropertyName ); - } -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::doFormListening( const bool _bStart ) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" ); - - if ( isFormListening() == _bStart ) - return; - - if ( m_xAmbientForm.is() ) - _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this ); - - Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY ); - if ( getParent().is() && !xParentLoadable.is() ) - { - // if our parent does not directly support the XLoadable interface, then it might support the - // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes - // broadcasted by the latter. - Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY ); - if ( xRowSetBroadcaster.is() ) - _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this ); - } - - m_bFormListening = _bStart && m_xAmbientForm.is(); -} - -// XChild -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException) -{ - ControlModelLock aLock( *this ); - FieldChangeNotifier aBoundFieldNotifier( aLock ); - - if ( getParent() == _rxParent ) - return; - - // disconnect from database column (which is controlled by parent, directly or indirectly) - if ( hasField() ) - impl_disconnectDatabaseColumn_noNotify(); - - // log off old listeners - if ( isFormListening() ) - doFormListening( false ); - - // actually set the new parent - OControlModel::setParent( _rxParent ); - - // a new parent means a new ambient form - impl_determineAmbientForm_nothrow(); - - if ( !hasExternalValueBinding() ) - { - // log on new listeners - doFormListening( true ); - - // re-connect to database column of the new parent - if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) - impl_connectDatabaseColumn_noNotify( false ); - } -} - -// XEventListener -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException) -{ - ControlModelLock aLock( *this ); - - if ( _rEvent.Source == getField() ) - { - resetField(); - } - else if ( _rEvent.Source == m_xLabelControl ) - { - Reference<XPropertySet> xOldValue = m_xLabelControl; - m_xLabelControl = NULL; - - // fire a propertyChanged (when we leave aLock's scope) - aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) ); - } - 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); -} - -// XServiceInfo -//------------------------------------------------------------------------------ -StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException) -{ - return ::comphelper::concatSequences( - getAggregateServiceNames(), - getSupportedServiceNames_Static() - ); -} - -//------------------------------------------------------------------------------ -Sequence< ::rtl::OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException ) -{ - Sequence< ::rtl::OUString > aOwnServiceNames( 1 ); - aOwnServiceNames[ 0 ] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.DataAwareControlModel") ); - - return ::comphelper::concatSequences( - OControlModel::getSupportedServiceNames_Static(), - aOwnServiceNames - ); -} - -// XPersist -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream ) throw(stario::IOException, RuntimeException) -{ - OControlModel::write(_rxOutStream); - - osl::MutexGuard aGuard(m_aMutex); - - // Version - _rxOutStream->writeShort(0x0002); - - // Controlsource - ::comphelper::operator<<( _rxOutStream, m_aControlSource); - - // !!! IMPORTANT NOTE !!! - // don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel - // is a base class which is called in derived classes "read" method. So if you increment the version - // and write new stuff, older office versions will read this in the _derived_ classes, which may result - // in anything from data loss to crash. - // (use writeCommonProperties instead, this is called in derived classes write-method) - // !!! EOIN !!! -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::defaultCommonProperties() -{ - Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); - if (xComp.is()) - xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); - m_xLabelControl = NULL; -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream) -{ - sal_Int32 nLen = _rxInStream->readLong(); - - Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY); - DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !"); - sal_Int32 nMark = xMark->createMark(); - - // read the reference to the label control - Reference<stario::XPersistObject> xPersist; - sal_Int32 nUsedFlag; - nUsedFlag = _rxInStream->readLong(); - if (nUsedFlag) - xPersist = _rxInStream->readObject(); - 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))); - - // read any other new common properties here - - // skip the remaining bytes - xMark->jumpToMark(nMark); - _rxInStream->skipBytes(nLen); - xMark->deleteMark(nMark); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream) -{ - Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY); - DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !"); - sal_Int32 nMark = xMark->createMark(); - - // a placeholder where we will write the overall length (later in this method) - sal_Int32 nLen = 0; - _rxOutStream->writeLong(nLen); - - // write the reference to the label control - Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY); - sal_Int32 nUsedFlag = 0; - if (xPersist.is()) - nUsedFlag = 1; - _rxOutStream->writeLong(nUsedFlag); - if (xPersist.is()) - _rxOutStream->writeObject(xPersist); - - // write any other new common properties here - - // write the correct length at the beginning of the block - nLen = xMark->offsetToMark(nMark) - sizeof(nLen); - xMark->jumpToMark(nMark); - _rxOutStream->writeLong(nLen); - xMark->jumpToFurthest(); - xMark->deleteMark(nMark); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream ) throw(stario::IOException, RuntimeException) -{ - OControlModel::read(_rxInStream); - - osl::MutexGuard aGuard(m_aMutex); - sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion; - ::comphelper::operator>>( _rxInStream, m_aControlSource); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const -{ - switch (nHandle) - { - case PROPERTY_ID_INPUT_REQUIRED: - rValue <<= m_bInputRequired; - break; - case PROPERTY_ID_CONTROLSOURCEPROPERTY: - rValue <<= m_sValuePropertyName; - break; - case PROPERTY_ID_CONTROLSOURCE: - rValue <<= m_aControlSource; - break; - case PROPERTY_ID_BOUNDFIELD: - rValue <<= getField(); - break; - case PROPERTY_ID_CONTROLLABEL: - if (!m_xLabelControl.is()) - rValue.clear(); - else - rValue <<= m_xLabelControl; - break; - default: - OControlModel::getFastPropertyValue(rValue, nHandle); - } -} - -//------------------------------------------------------------------------------ -sal_Bool OBoundControlModel::convertFastPropertyValue( - Any& _rConvertedValue, Any& _rOldValue, - sal_Int32 _nHandle, - const Any& _rValue) - throw (com::sun::star::lang::IllegalArgumentException) -{ - sal_Bool bModified(sal_False); - switch (_nHandle) - { - case PROPERTY_ID_INPUT_REQUIRED: - bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired ); - break; - case PROPERTY_ID_CONTROLSOURCE: - bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource); - break; - case PROPERTY_ID_BOUNDFIELD: - OSL_FAIL( "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" ); - throw com::sun::star::lang::IllegalArgumentException(); - case PROPERTY_ID_CONTROLLABEL: - if (!_rValue.hasValue()) - { // property set to void - _rConvertedValue = Any(); - getFastPropertyValue(_rOldValue, _nHandle); - bModified = m_xLabelControl.is(); - } - else - { - bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl); - if (!m_xLabelControl.is()) - // an empty interface is interpreted as VOID - _rOldValue.clear(); - } - break; - default: - bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); - } - return bModified; -} - -//------------------------------------------------------------------------------ -Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const -{ - Any aDefault; - switch ( _nHandle ) - { - case PROPERTY_ID_INPUT_REQUIRED: - aDefault <<= sal_Bool( sal_True ); - break; - - case PROPERTY_ID_CONTROLSOURCE: - aDefault <<= ::rtl::OUString(); - break; - - case PROPERTY_ID_CONTROLLABEL: - aDefault <<= Reference< XPropertySet >(); - break; - } - return aDefault; -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) -{ - switch (nHandle) - { - case PROPERTY_ID_INPUT_REQUIRED: - OSL_VERIFY( rValue >>= m_bInputRequired ); - break; - case PROPERTY_ID_CONTROLSOURCE: - OSL_VERIFY( rValue >>= m_aControlSource ); - break; - case PROPERTY_ID_BOUNDFIELD: - OSL_FAIL("OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !"); - throw com::sun::star::lang::IllegalArgumentException(); - case PROPERTY_ID_CONTROLLABEL: - { - if ( rValue.hasValue() && ( rValue.getValueTypeClass() != TypeClass_INTERFACE ) ) - throw com::sun::star::lang::IllegalArgumentException(); - - Reference< XInterface > xNewValue( rValue, UNO_QUERY ); - if ( !xNewValue.is() ) - { // set property to "void" - Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY ); - if ( xComp.is() ) - xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) ); - m_xLabelControl = NULL; - break; - } - - Reference< XControlModel > xAsModel ( xNewValue, UNO_QUERY ); - Reference< XServiceInfo > xAsServiceInfo ( xAsModel, UNO_QUERY ); - Reference< XPropertySet > xAsPropSet ( xAsServiceInfo, UNO_QUERY ); - Reference< XChild > xAsChild ( xAsPropSet, UNO_QUERY ); - if ( !xAsChild.is() || !xAsServiceInfo->supportsService( m_aLabelServiceName ) ) - { - throw com::sun::star::lang::IllegalArgumentException(); - } - - // check if weself and the given model have a common anchestor (up to the forms collection) - Reference<XChild> xCont; - query_interface(static_cast<XWeak*>(this), xCont); - Reference< XInterface > xMyTopLevel = xCont->getParent(); - while (xMyTopLevel.is()) - { - Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY); - if (!xAsForm.is()) - // found my root - break; - - Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY); - xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >(); - } - Reference< XInterface > xNewTopLevel = xAsChild->getParent(); - while (xNewTopLevel.is()) - { - Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY); - if (!xAsForm.is()) - break; - - Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY); - xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >(); - } - if (xNewTopLevel != xMyTopLevel) - { - // the both objects don't belong to the same forms collection -> not acceptable - throw com::sun::star::lang::IllegalArgumentException(); - } - - m_xLabelControl = xAsPropSet; - Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); - if (xComp.is()) - xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); - } - break; - default: - OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue ); - } -} - -// XPropertyChangeListener -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException) -{ - // if the DBColumn value changed, transfer it to the control - if ( evt.PropertyName.equals( PROPERTY_VALUE ) ) - { - OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database colum?" ); - osl::MutexGuard aGuard(m_aMutex); - if ( m_bForwardValueChanges && m_xColumn.is() ) - transferDbValueToControl(); - } - else - { - OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" ); - - // our binding has properties which can control properties of ourself - ::rtl::OUString sBindingControlledProperty; - bool bForwardToLabelControl = false; - if ( evt.PropertyName.equals( PROPERTY_READONLY ) ) - { - sBindingControlledProperty = PROPERTY_READONLY; - } - else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) ) - { - sBindingControlledProperty = PROPERTY_ENABLED; - bForwardToLabelControl = true; - } - else - return; - - try - { - setPropertyValue( sBindingControlledProperty, evt.NewValue ); - if ( bForwardToLabelControl && m_xLabelControl.is() ) - m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue ); - } - catch( const Exception& ) - { - OSL_FAIL( "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!" ); - } - } -} - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException) -{ - ControlModelLock aLock( *this ); - FieldChangeNotifier aBoundFieldNotifier( aLock ); - - // disconnect from database column (which is controlled by parent, directly or indirectly) - if ( hasField() ) - impl_disconnectDatabaseColumn_noNotify(); - - // log off old listeners - if ( isFormListening() ) - doFormListening( false ); - - // determine the new ambient form - impl_determineAmbientForm_nothrow(); - - // log on new listeners - doFormListening( true ); - - // re-connect to database column if needed and possible - if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) - impl_connectDatabaseColumn_noNotify( false ); -} - -// XBoundComponent -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException) -{ - m_aUpdateListeners.addInterface(_rxListener); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException) -{ - m_aUpdateListeners.removeInterface(_rxListener); -} - -//------------------------------------------------------------------------------ -sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException) -{ - ControlModelLock aLock( *this ); - - OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " ); - if ( hasExternalValueBinding() ) - { - // in most cases, no action is required: For most derivees, we know the value property of - // our control (see initValueProperty), and when an external binding is active, we - // instantly forward all changes in this property to the external binding. - if ( !m_sValuePropertyName.getLength() ) - // but for those derivees which did not use this feature, we need an - // explicit transfer - transferControlValueToExternal( aLock ); - return sal_True; - } - - OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" ); - // we reach this only if we're not working with an external binding - - if ( !hasField() ) - return sal_True; - - ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners ); - EventObject aEvent; - aEvent.Source = static_cast< XWeak* >( this ); - sal_Bool bSuccess = sal_True; - - aLock.release(); - // >>>>>>>> ----- UNSAFE ----- >>>>>>>> - while (aIter.hasMoreElements() && bSuccess) - bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent ); - // <<<<<<<< ----- UNSAFE ----- <<<<<<<< - aLock.acquire(); - - if ( bSuccess ) - { - try - { - if ( m_xColumnUpdate.is() ) - bSuccess = commitControlValueToDbColumn( sal_False ); - } - catch(Exception&) - { - bSuccess = sal_False; - } - } - - if ( bSuccess ) - { - aLock.release(); - m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent ); - } - - return bSuccess; -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::resetField() -{ - m_xColumnUpdate.clear(); - m_xColumn.clear(); - m_xField.clear(); - m_nFieldType = DataType::OTHER; -} - -//------------------------------------------------------------------------------ -sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" ); - - // wenn eine Verbindung zur Datenbank existiert - if (rForm.is() && getConnection(rForm).is()) - { - // Feld bestimmen und PropertyChangeListener - m_xCursor = rForm; - Reference<XPropertySet> xFieldCandidate; - - if (m_xCursor.is()) - { - Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY); - DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !"); - if (xColumnsSupplier.is()) - { - Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY); - if (xColumns.is() && xColumns->hasByName(m_aControlSource)) - { - OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate ); - } - } - } - - try - { - sal_Int32 nFieldType = DataType::OTHER; - if ( xFieldCandidate.is() ) - { - xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType; - if ( approveDbColumnType( nFieldType ) ) - impl_setField_noNotify( xFieldCandidate ); - } - else - impl_setField_noNotify( NULL ); - - if ( m_xField.is() ) - { - if( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) ) - { - m_nFieldType = nFieldType; - - // an wertaenderungen horchen - m_xField->addPropertyChangeListener( PROPERTY_VALUE, this ); - m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY ); - m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY ); - - sal_Int32 nNullableFlag = ColumnValue::NO_NULLS; - m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag; - m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag); - // we're optimistic : in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability .... - } - else - { - OSL_FAIL("OBoundControlModel::connectToField: property NAME not supported!"); - impl_setField_noNotify( NULL ); - } - } - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - resetField(); - } - } - return hasField(); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet ) -{ - // but only if the rowset if posisitioned on a valid record - if ( hasField() && _rxRowSet.is() ) - { - if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() ) - transferDbValueToControl(); - else - // reset the field if the row set is empty - // #i30661# - resetNoBroadcast(); - } -} - -//------------------------------------------------------------------------------ -sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" ); - - if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY) - || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER) - || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT) - || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY) - || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/ - || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL)) - return sal_False; - - return sal_True; -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::impl_determineAmbientForm_nothrow() -{ - Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() ); - - m_xAmbientForm.set( xParent, UNO_QUERY ); - if ( !m_xAmbientForm.is() ) - { - Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY ); - if ( xSupRowSet.is() ) - m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY ); - } -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload ) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" ); - - // consistency checks - DBG_ASSERT( !( hasField() && !_bFromReload ), - "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" ); - (void)_bFromReload; - - Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY ); - OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" ); - if ( !xRowSet.is() ) - return; - - if ( !hasField() ) - { - // connect to the column - connectToField( xRowSet ); - } - - // now that we're connected (more or less, even if we did not find a column), - // we definately want to forward any potentially occuring value changes - m_bForwardValueChanges = sal_True; - - // let derived classes react on this new connection - m_bLoaded = sal_True; - onConnectedDbColumn( xRowSet ); - - // initially transfer the db column value to the control, if we successfully connected to a database column - if ( hasField() ) - initFromField( xRowSet ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify() -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" ); - - // let derived classes react on this - onDisconnectedDbColumn(); - - if ( hasField() ) - { - getField()->removePropertyChangeListener( PROPERTY_VALUE, this ); - resetField(); - } - - m_xCursor = NULL; - m_bLoaded = sal_False; -} - -//============================================================================== -// XLoadListener -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException) -{ - ControlModelLock aLock( *this ); - FieldChangeNotifier aBoundFieldNotifier( aLock ); - - OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" ); - (void)_rEvent; - - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" ); - if ( hasExternalValueBinding() ) - return; - - impl_connectDatabaseColumn_noNotify( false ); -} - - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" ); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" ); - if ( hasExternalValueBinding() ) - return; - - osl::MutexGuard aGuard(m_aMutex); - m_bForwardValueChanges = sal_False; -} - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException) -{ - ControlModelLock aLock( *this ); - FieldChangeNotifier aBoundFieldNotifier( aLock ); - - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" ); - if ( hasExternalValueBinding() ) - return; - - impl_disconnectDatabaseColumn_noNotify(); -} - -//------------------------------------------------------------------------------ -void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException) -{ - ControlModelLock aLock( *this ); - FieldChangeNotifier aBoundFieldNotifier( aLock ); - - OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" ); - (void)_rEvent; - - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" ); - if ( hasExternalValueBinding() ) - return; - - impl_connectDatabaseColumn_noNotify( true ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator ) -{ - m_eControlValueChangeInstigator = _eInstigator; - doSetControlValue( _rValue ); - m_eControlValueChangeInstigator = eOther; -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::doSetControlValue( const Any& _rValue ) -{ - OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(), - "OBoundControlModel::doSetControlValue: invalid aggregate !" ); - OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ), - "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" ); - - try - { - // release our mutex once (it's acquired in one of the the calling methods), as setting aggregate properties - // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with - // our own mutex locked - MutexRelease aRelease( m_aMutex ); - if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() ) - { - m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue ); - } - else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() ) - { - m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue ); - } - } - catch( const Exception& ) - { - OSL_FAIL( "OBoundControlModel::doSetControlValue: caught an exception!" ); - } -} - -//------------------------------------------------------------------------------ -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_FAIL( "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_FAIL( "OBoundControlModel::onDisconnectedValidator: caught an exception!" ); - } - recheckValidity( false ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::onConnectedExternalValue( ) -{ - calculateExternalValueType(); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::onDisconnectedExternalValue( ) -{ -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ ) -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::onDisconnectedDbColumn() -{ - OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" ); -} - -// XReset -//----------------------------------------------------------------------------- -Any OBoundControlModel::getDefaultForReset() const -{ - return Any(); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::resetNoBroadcast() -{ - setControlValue( getDefaultForReset(), eOther ); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException) -{ - m_aResetHelper.addResetListener( l ); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException) -{ - m_aResetHelper.removeResetListener( l ); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::reset() throw (RuntimeException) -{ - if ( !m_aResetHelper.approveReset() ) - return; - - ControlModelLock aLock( *this ); - - // on a new record? - sal_Bool bIsNewRecord = sal_False; - Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY ); - if ( xSet.is() ) - { - try - { - xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord; - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - } - - // cursor on an invalid row? - sal_Bool bInvalidCursorPosition = sal_True; - try - { - bInvalidCursorPosition = m_xCursor.is() - && ( m_xCursor->isAfterLast() - || m_xCursor->isBeforeFirst() - ) - && !bIsNewRecord; - } - catch( const SQLException& ) - { - OSL_FAIL( "OBoundControlModel::reset: caught an SQL exception!" ); - } - // #i24495# - don't count the insert row as "invalid" - - sal_Bool bSimpleReset = - ( !m_xColumn.is() // no connection to a database column - || ( m_xCursor.is() // OR we have an improperly positioned cursor - && bInvalidCursorPosition - ) - || hasExternalValueBinding() // OR we have an external value binding - ); - - if ( !bSimpleReset ) - { - // The default values will be set if and only if the current value of the field which we're bound - // to is NULL. - // Else, the current field value should be refreshed - // This behaviour is not completely ... "matured": What should happen if the field as well as the - // control have a default value? - - sal_Bool bIsNull = sal_True; - // we have to access the field content at least once to get a reliable result by XColumn::wasNull - try - { - // normally, we'd do a getString here. However, this is extremely expensive in the case - // of binary fields. Unfortunately, getString is the only method which is guaranteed - // to *always* succeed, all other getXXX methods may fail if the column is asked for a - // non-convertible type - sal_Int32 nFieldType = DataType::OBJECT; - getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType; - if ( ( nFieldType == DataType::BINARY ) - || ( nFieldType == DataType::VARBINARY ) - || ( nFieldType == DataType::LONGVARBINARY ) - || ( nFieldType == DataType::OBJECT ) - /*|| ( nFieldType == DataType::CLOB )*/ - ) - m_xColumn->getBinaryStream(); - else if ( nFieldType == DataType::BLOB ) - m_xColumn->getBlob(); - else - m_xColumn->getString(); - - bIsNull = m_xColumn->wasNull(); - } - catch(Exception&) - { - OSL_FAIL("OBoundControlModel::reset: this should have succeeded in all cases!"); - } - - sal_Bool bNeedValueTransfer = sal_True; - - if ( bIsNull ) - { - if ( bIsNewRecord ) - { - // reset the control to it's default - resetNoBroadcast(); - // and immediately commit the changes to the DB column, to keep consistency - commitControlValueToDbColumn( sal_True ); - - bNeedValueTransfer = sal_False; - } - } - - if ( bNeedValueTransfer ) - transferDbValueToControl(); - } - else - { - resetNoBroadcast(); - - // transfer to the external binding, if necessary - if ( hasExternalValueBinding() ) - transferControlValueToExternal( aLock ); - } - - // revalidate, if necessary - if ( hasValidator() ) - recheckValidity( true ); - - aLock.release(); - - m_aResetHelper.notifyResetted(); -} - -// ----------------------------------------------------------------------------- -void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField ) -{ - DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" ); - m_xField = _rxField; -} - -//-------------------------------------------------------------------- -sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding ) -{ - if ( !_rxBinding.is() ) - return sal_False; - - Sequence< Type > aTypeCandidates; - { - // SYNCHRONIZED --> - ::osl::MutexGuard aGuard( m_aMutex ); - aTypeCandidates = getSupportedBindingTypes(); - // <-- SYNCHRONIZED - } - - for ( const Type* pType = aTypeCandidates.getConstArray(); - pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength(); - ++pType - ) - { - if ( _rxBinding->supportsType( *pType ) ) - return sal_True; - } - - return sal_False; -} - -//-------------------------------------------------------------------- -void OBoundControlModel::connectExternalValueBinding( - const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock ) -{ - OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" ); - OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" ); - - // if we're connected to a database column, suspend this - if ( hasField() ) - impl_disconnectDatabaseColumn_noNotify(); - - // suspend listening for load-related events at out ambient form. - // This is because an external value binding overrules a possible database binding. - if ( isFormListening() ) - doFormListening( false ); - - // remember this new binding - m_xExternalBinding = _rxBinding; - - // tell the derivee - onConnectedExternalValue(); - - try - { - // add as value listener so we get notified when the value changes - Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY ); - if ( xModifiable.is() ) - xModifiable->addModifyListener( this ); - - // add as property change listener for some (possibly present) properties we're - // interested in - Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY ); - Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() ); - if ( xBindingPropsInfo.is() ) - { - if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) ) - { - xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this ); - m_bBindingControlsRO = sal_True; - } - if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) ) - { - xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this ); - m_bBindingControlsEnable = sal_True; - } - } - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - - // propagate our new value - transferExternalValueToControl( _rInstanceLock ); - - // if the binding is also a validator, use it, too. This is a constraint of the - // com.sun.star.form.binding.ValidatableBindableFormComponent service - if ( m_bSupportsValidation ) - { - try - { - Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY ); - if ( xAsValidator.is() ) - setValidator( xAsValidator ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - } -} - -//-------------------------------------------------------------------- -void OBoundControlModel::disconnectExternalValueBinding( ) -{ - try - { - // not listening at the binding anymore - Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY ); - if ( xModifiable.is() ) - xModifiable->removeModifyListener( this ); - - // remove as property change listener - Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY ); - if ( m_bBindingControlsRO ) - xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this ); - if ( m_bBindingControlsEnable ) - xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this ); - } - catch( const Exception& ) - { - OSL_FAIL( "OBoundControlModel::disconnectExternalValueBinding: caught an exception!" ); - } - - // 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(); - - // be a load listener at our form, again. This was suspended while we had - // an external value binding in place. - doFormListening( true ); - - // re-connect to database column of the new parent - if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) - impl_connectDatabaseColumn_noNotify( false ); - - // tell the derivee - onDisconnectedExternalValue(); -} - -//-------------------------------------------------------------------- -void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException) -{ - OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" ); - // the interface for this method should not have been exposed if we do not - // support binding to external data - // allow reset - if ( _rxBinding.is() && !impl_approveValueBinding_nolock( _rxBinding ) ) - { - throw IncompatibleTypesException( - FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ), - *this - ); - } - - ControlModelLock aLock( *this ); - - // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding - // might trigger a change in our BoundField. - FieldChangeNotifier aBoundFieldNotifier( aLock ); - - // disconnect from the old binding - if ( hasExternalValueBinding() ) - disconnectExternalValueBinding( ); - - // connect to the new binding - if ( _rxBinding.is() ) - connectExternalValueBinding( _rxBinding, aLock ); -} - -//-------------------------------------------------------------------- -Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding( ) throw (RuntimeException) -{ - ::osl::MutexGuard aGuard( m_aMutex ); - OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" ); - // the interface for this method should not have been exposed if we do not - // support binding to external data - - return m_xExternalBinding; -} - -//-------------------------------------------------------------------- -void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException ) -{ - ControlModelLock aLock( *this ); - - OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" ); - if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() ) - { - transferExternalValueToControl( aLock ); - } -} - -//-------------------------------------------------------------------- -void OBoundControlModel::transferDbValueToControl( ) -{ - try - { - setControlValue( translateDbColumnToControlValue(), eDbColumnBinding ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock ) -{ - Reference< XValueBinding > xExternalBinding( m_xExternalBinding ); - Type aValueExchangeType( getExternalValueType() ); - - _rInstanceLock.release(); - // >>>>>>>> ----- UNSAFE ----- >>>>>>>> - Any aExternalValue; - try - { - aExternalValue = xExternalBinding->getValue( aValueExchangeType ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - // <<<<<<<< ----- UNSAFE ----- <<<<<<<< - _rInstanceLock.acquire(); - - setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding ); -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock ) -{ - OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(), - "OBoundControlModel::transferControlValueToExternal: precondition not met!" ); - - if ( m_xExternalBinding.is() ) - { - Any aExternalValue( translateControlValueToExternalValue() ); - m_bTransferingValue = sal_True; - - _rInstanceLock.release(); - // >>>>>>>> ----- UNSAFE ----- >>>>>>>> - try - { - m_xExternalBinding->setValue( aExternalValue ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - // <<<<<<<< ----- UNSAFE ----- <<<<<<<< - _rInstanceLock.acquire(); - - m_bTransferingValue = sal_False; - } -} - -// ----------------------------------------------------------------------------- -Sequence< Type > OBoundControlModel::getSupportedBindingTypes() -{ - return Sequence< Type >( &m_aValuePropertyType, 1 ); -} - -//----------------------------------------------------------------------------- -void OBoundControlModel::calculateExternalValueType() -{ - m_aExternalValueType = Type(); - if ( !m_xExternalBinding.is() ) - return; - - Sequence< Type > aTypeCandidates( getSupportedBindingTypes() ); - for ( const Type* pTypeCandidate = aTypeCandidates.getConstArray(); - pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength(); - ++pTypeCandidate - ) - { - if ( m_xExternalBinding->supportsType( *pTypeCandidate ) ) - { - m_aExternalValueType = *pTypeCandidate; - break; - } - } -} - -//----------------------------------------------------------------------------- -Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const -{ - OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(), - "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" ); - - Any aControlValue( _rExternalValue ); - - // if the external value is VOID, and our value property is not allowed to be VOID, - // then default-construct a value - if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid ) - aControlValue.setValue( NULL, m_aValuePropertyType ); - - // outta here - return aControlValue; -} - -//------------------------------------------------------------------------------ -Any OBoundControlModel::translateControlValueToExternalValue( ) const -{ - return getControlValue( ); -} - -//------------------------------------------------------------------------------ -Any OBoundControlModel::translateControlValueToValidatableValue( ) const -{ - OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" ); - if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() ) - return translateControlValueToExternalValue(); - return getControlValue(); -} - -//------------------------------------------------------------------------------ -Any OBoundControlModel::getControlValue( ) const -{ - OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(), - "OBoundControlModel::getControlValue: invalid aggregate !" ); - OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ), - "OBoundControlModel::getControlValue: please override if you have own value property handling!" ); - - // determine the current control value - Any aControlValue; - if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() ) - { - aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle ); - } - else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() ) - { - aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName ); - } - - 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 - - // early out if the validator does not change - if( _rxValidator == m_xValidator ) - return; - - 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; -} - -//-------------------------------------------------------------------- -::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const -{ - if ( hasValidator() ) - return translateControlValueToValidatableValue(); - return getControlValue(); -} - -//-------------------------------------------------------------------- -Any SAL_CALL OBoundControlModel::getCurrentValue( ) throw (RuntimeException) -{ - ::osl::MutexGuard aGuard( m_aMutex ); - return getCurrentFormComponentValue(); -} - -//-------------------------------------------------------------------- -void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException) -{ - if ( Listener.is() ) - m_aFormComponentListeners.addInterface( Listener ); -} - -//-------------------------------------------------------------------- -void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException) -{ - if ( Listener.is() ) - m_aFormComponentListeners.removeInterface( 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_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) ); - } - } - catch( const Exception& ) - { - OSL_FAIL( "OBoundControlModel::recheckValidity: caught an exception!" ); - } -} - -//------------------------------------------------------------------------------ -void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const -{ - BEGIN_DESCRIBE_PROPERTIES( 5, 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 ); - DECL_BOOL_PROP1 ( INPUT_REQUIRED, BOUND ); - END_DESCRIBE_PROPERTIES() -} - -// ----------------------------------------------------------------------------- - -//......................................................................... -} -//... namespace frm ....................................................... - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |