| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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> |
| |
| #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_ENSURE(sal_False, "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_ENSURE(sal_False, "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 ) |
| ,m_nControlTypeinMSO(0) // 0 : default value is create from AOO |
| ,m_nObjIDinMSO(INVALID_OBJ_ID_IN_MSO) |
| // form controls are usually embedded into documents, not dialogs, and in documents |
| // the native look is ugly .... |
| // #i37342# / 2004-11-19 / frank.schoenheit@sun.com |
| { |
| 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_ENSURE( sal_False, "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; |
| m_nControlTypeinMSO = _pOriginal->m_nControlTypeinMSO; |
| m_nObjIDinMSO = _pOriginal->m_nObjIDinMSO; |
| |
| 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::createFromAscii( "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; |
| //added for exporting OCX control |
| case PROPERTY_ID_CONTROL_TYPE_IN_MSO: |
| aReturn <<= (sal_Int16)0; |
| break; |
| case PROPERTY_ID_OBJ_ID_IN_MSO: |
| aReturn <<= (sal_uInt16)INVALID_OBJ_ID_IN_MSO; |
| break; |
| default: |
| if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) |
| m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn ); |
| else |
| OSL_ENSURE( false, "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; |
| //added for exporting OCX control |
| case PROPERTY_ID_CONTROL_TYPE_IN_MSO: |
| _rValue <<= (sal_Int16)m_nControlTypeinMSO; |
| break; |
| case PROPERTY_ID_OBJ_ID_IN_MSO: |
| _rValue <<= (sal_uInt16)m_nObjIDinMSO; |
| 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; |
| //added for exporting OCX control |
| case PROPERTY_ID_CONTROL_TYPE_IN_MSO: |
| bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nControlTypeinMSO); |
| break; |
| case PROPERTY_ID_OBJ_ID_IN_MSO: |
| bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nObjIDinMSO); |
| break; |
| default: |
| if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) |
| bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue ); |
| else |
| OSL_ENSURE( false, "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; |
| //added for exporting OCX control |
| case PROPERTY_ID_CONTROL_TYPE_IN_MSO: |
| OSL_VERIFY( _rValue >>= m_nControlTypeinMSO ); |
| break; |
| case PROPERTY_ID_OBJ_ID_IN_MSO: |
| OSL_VERIFY( _rValue >>= m_nObjIDinMSO ); |
| break; |
| default: |
| if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) |
| m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue ); |
| else |
| OSL_ENSURE( false, "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" ); |
| break; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const |
| { |
| //BEGIN_DESCRIBE_BASE_PROPERTIES( 4 ) |
| BEGIN_DESCRIBE_BASE_PROPERTIES( 6 ) |
| 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); |
| DECL_PROP1 (CONTROL_TYPE_IN_MSO,sal_Int16, BOUND); |
| DECL_PROP1 (OBJ_ID_IN_MSO,sal_uInt16, 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::createFromAscii( "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 !!! |
| // FS - 68876 - 28.09.1999 |
| } |
| |
| //------------------------------------------------------------------------------ |
| 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: |
| DBG_ERROR( "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: |
| DBG_ERROR("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_ENSURE( sal_False, "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_ENSURE(sal_False, "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# / 2004-12-16 / frank.schoenheit@sun.com |
| 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 |
| // #72451# / 2000-01-31 / frank.schoenheit@sun.com |
| 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_ENSURE( sal_False, "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_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" ); |
| } |
| recheckValidity( false ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OBoundControlModel::onDisconnectedValidator( ) |
| { |
| try |
| { |
| Reference< XPropertySetInfo > xAggregatePropertyInfo; |
| if ( m_xAggregateSet.is() ) |
| xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo(); |
| if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) ) |
| m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) ); |
| } |
| catch( const Exception& ) |
| { |
| OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" ); |
| } |
| recheckValidity( false ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OBoundControlModel::onConnectedExternalValue( ) |
| { |
| 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_ENSURE( sal_False, "OBoundControlModel::reset: caught an SQL exception!" ); |
| } |
| // don't count the insert row as "invalid" |
| // @since #i24495# |
| // @date 2004-05-14 |
| // @author fs@openoffice.org |
| |
| 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&) |
| { |
| DBG_ERROR("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_ENSURE( sal_False, "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 |
| |
| if ( !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_ENSURE( sal_False, "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 ....................................................... |
| |