/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 .
*/ #include <componenttools.hxx> #include <FormComponent.hxx> #include <strings.hrc> #include <frm_resource.hxx> #include <property.hxx> #include <services.hxx>
// base class for form layer controls
OControl::OControl( const Reference< XComponentContext >& _rxContext, const OUString& _rAggregateService, constbool _bSetDelegator )
:OComponentHelper(m_aMutex)
,m_xContext( _rxContext )
{ // Aggregate VCL Control // Increment the RefCount for aggregates, because the aggregate by itself increments the RefCount in the setDelegator
osl_atomic_increment( &m_refCount );
{
m_xAggregate.set(_rxContext->getServiceManager()->createInstanceWithContext(_rAggregateService, _rxContext), css::uno::UNO_QUERY);
m_xControl.set(m_xAggregate, css::uno::UNO_QUERY);
}
osl_atomic_decrement( &m_refCount );
void OControl::doSetDelegator()
{
osl_atomic_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 ) );
}
osl_atomic_decrement( &m_refCount );
}
// UNO Binding
Any SAL_CALL OControl::queryAggregation( const Type& _rType )
{ // 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);
}
// does the disposing come from the aggregate? if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY))
{ // no -> forward it if (auto xListener = query_aggregation<css::lang::XEventListener>(m_xAggregate))
xListener->disposing(_rEvent);
}
}
Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType)
{
Any aReturn;
// XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types if ( _rType.equals( cppu::UnoType<XTypeProvider>::get() ) )
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 );
Any SAL_CALL OControlModel::queryAggregation(const Type& _rType)
{ // 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(cppu::UnoType<XCloneable>::get()))
aReturn = m_xAggregate->queryAggregation(_rType);
}
} return aReturn;
}
void OControlModel::readHelpTextCompatibly(const css::uno::Reference< css::io::XObjectInputStream >& _rxInStream)
{
OUString sHelpText;
::comphelper::operator>>( _rxInStream, sHelpText); try
{ if (m_xAggregateSet.is())
m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, Any(sHelpText));
} catch(const Exception&)
{
DBG_UNHANDLED_EXCEPTION("forms.component");
SAL_WARN("forms.component", "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
}
}
void OControlModel::writeHelpTextCompatibly(const css::uno::Reference< css::io::XObjectOutputStream >& _rxOutStream)
{
OUString sHelpText; try
{ if (m_xAggregateSet.is())
m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
} catch(const Exception&)
{
DBG_UNHANDLED_EXCEPTION("forms.component");
SAL_WARN("forms.component", "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
}
::comphelper::operator<<( _rxOutStream, sHelpText);
}
OControlModel::OControlModel( const Reference<XComponentContext>& _rxContext, const OUString& _rUnoControlModelTypeName, const OUString& rDefault, constbool _bSetDelegator)
:OComponentHelper(m_aMutex)
,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
,m_xContext( _rxContext )
,m_lockCount( 0 )
,m_aPropertyBagHelper( *this )
,m_nTabIndex(FRM_DEFAULT_TABINDEX)
,m_nClassId(FormComponentType::CONTROL)
,m_bNativeLook( false )
,m_bStandardTheme( false )
,m_bGenerateVbEvents( 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#
{ if (_rUnoControlModelTypeName.isEmpty()) // the is a model we have to aggregate return;
// temporarily increment refcount because of temporary references to ourself in the following
osl_atomic_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();
// 2. writing a version number
_rxOutStream->writeShort(0x0003);
// 3. writing the general properties
::comphelper::operator<<( _rxOutStream, m_aName);
_rxOutStream->writeShort(m_nTabIndex);
::comphelper::operator<<( _rxOutStream, m_aTag); // 3rd 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!
}
// 2. reading the version number
sal_uInt16 nVersion = InStream->readShort();
// 3. reading the general 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 );
OBoundControlModel::OBoundControlModel( const OBoundControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory )
:OControlModel( _pOriginal, _rxFactory, true, false )
,OPropertyChangeListener()
,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( false )
,m_bFormListening( false )
,m_bLoaded( false )
,m_bRequired( false )
,m_bCommitable( _pOriginal->m_bCommitable )
,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
,m_bForwardValueChanges( true )
,m_bTransferringValue( false )
,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
,m_bBindingControlsRO( false )
,m_bBindingControlsEnable( false )
,m_eControlValueChangeInstigator( eOther )
{ // 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 transferred. // (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 = nullptr;
}
}
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()) ) return;
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.isEmpty() )
m_pAggPropMultiplexer->addProperty( m_sValuePropertyName );
}
}
// start listening for changes at the value property
implInitValuePropertyListening( );
}
void OBoundControlModel::suspendValueListening( )
{
OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "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.isEmpty(), "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();
}
if ( m_pAggPropMultiplexer )
m_pAggPropMultiplexer->dispose();
// notify all our listeners
css::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 = nullptr;
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(); // ditto 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 );
}
elseif ( !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 )
{
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::doFormListening( constbool _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 );
}
// XChild void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent)
{
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 );
}
}
elseif ( _rEvent.Source == m_xExternalBinding )
{ // *first* check for the external binding
disconnectExternalValueBinding( );
}
elseif ( _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( );
}
// XPersist void SAL_CALL OBoundControlModel::write( const Reference<css::io::XObjectOutputStream>& _rxOutStream )
{
OControlModel::write(_rxOutStream);
osl::MutexGuard aGuard(m_aMutex); // Version
_rxOutStream->writeShort(0x0002); // Controlsource
::comphelper::operator<<( _rxOutStream, m_aControlSource); // !!! IMPORTANT NOTE !!! // don't write any new members here: this wouldn't be compatible with older versions, as OBoundControlModel // is a base class which is called in derived classes "read" method. So if you increment the version // and write new stuff, older office versions will read this in the _derived_ classes, which may result // in anything from data loss to crash. // (use writeCommonProperties instead, this is called in derived classes write-method) // !!! EOIN !!!
}
void OBoundControlModel::readCommonProperties(const Reference<css::io::XObjectInputStream>& _rxInStream)
{
sal_Int32 nLen = _rxInStream->readLong();
Reference<css::io::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<css::io::XPersistObject> xPersist;
sal_Int32 nUsedFlag;
nUsedFlag = _rxInStream->readLong(); if (nUsedFlag)
xPersist = _rxInStream->readObject();
m_xLabelControl.set(xPersist, css::uno::UNO_QUERY);
Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY ); if (xComp.is())
xComp->addEventListener(static_cast<css::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<css::io::XObjectOutputStream>& _rxOutStream)
{
Reference<css::io::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<css::io::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 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)
{ bool bModified(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:
SAL_WARN("forms.component", "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" ); throw css::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();
}
// Check if we and the given model have a common ancestor (up to the forms collection)
Reference<XChild> xCont(this);
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 >();
}
if (xNewTopLevel != xMyTopLevel)
{ // the both objects don't belong to the same forms collection -> not acceptable throw css::lang::IllegalArgumentException();
}
m_xLabelControl = std::move(xAsPropSet);
Reference<css::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); if (xComp.is())
xComp->addEventListener(static_cast<css::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
}
// XPropertyChangeListener void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt )
{ // if the DBColumn value changed, transfer it to the control if ( evt.PropertyName == PROPERTY_VALUE )
{
OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database column?" );
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
OUString sBindingControlledProperty; bool bForwardToLabelControl = false; if ( evt.PropertyName == PROPERTY_READONLY )
{
sBindingControlledProperty = PROPERTY_READONLY;
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("forms.component");
SAL_WARN("forms.component", "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!");
}
}
}
void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ )
{
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 );
}
sal_Bool SAL_CALL OBoundControlModel::commit()
{
ControlModelLock aLock( *this );
OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not committable!) " ); 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.isEmpty() ) // but for those derivees which did not use this feature, we need an // explicit transfer
transferControlValueToExternal( aLock ); returntrue;
}
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.30 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.