LCOV - code coverage report
Current view: top level - forms/source/component - FormComponent.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1015 1293 78.5 %
Date: 2014-04-11 Functions: 158 178 88.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : #include "componenttools.hxx"
      20             : #include "FormComponent.hxx"
      21             : #include "frm_resource.hrc"
      22             : #include "frm_resource.hxx"
      23             : #include "property.hrc"
      24             : #include "services.hxx"
      25             : 
      26             : #include <com/sun/star/awt/XTextComponent.hpp>
      27             : #include <com/sun/star/awt/XVclWindowPeer.hpp>
      28             : #include <com/sun/star/awt/XWindow.hpp>
      29             : #include <com/sun/star/form/XForm.hpp>
      30             : #include <com/sun/star/form/XLoadable.hpp>
      31             : #include <com/sun/star/io/XMarkableStream.hpp>
      32             : #include <com/sun/star/lang/DisposedException.hpp>
      33             : #include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp>
      34             : #include <com/sun/star/sdb/XRowSetSupplier.hpp>
      35             : #include <com/sun/star/sdbc/ColumnValue.hpp>
      36             : #include <com/sun/star/sdbc/DataType.hpp>
      37             : #include <com/sun/star/util/XModifyBroadcaster.hpp>
      38             : 
      39             : #include <comphelper/basicio.hxx>
      40             : #include <comphelper/guarding.hxx>
      41             : #include <comphelper/listenernotification.hxx>
      42             : #include <comphelper/property.hxx>
      43             : #include <connectivity/dbtools.hxx>
      44             : #include <cppuhelper/queryinterface.hxx>
      45             : #include <cppuhelper/supportsservice.hxx>
      46             : #include <toolkit/helper/emptyfontdescriptor.hxx>
      47             : #include <tools/debug.hxx>
      48             : #include <tools/diagnose_ex.h>
      49             : 
      50             : #include <functional>
      51             : #include <algorithm>
      52             : 
      53             : namespace frm
      54             : {
      55             : using namespace ::com::sun::star::uno;
      56             : using namespace ::com::sun::star::sdb;
      57             : using namespace ::com::sun::star::sdbc;
      58             : using namespace ::com::sun::star::sdbcx;
      59             : using namespace ::com::sun::star::beans;
      60             : using namespace ::com::sun::star::container;
      61             : using namespace ::com::sun::star::form;
      62             : using namespace ::com::sun::star::awt;
      63             : using namespace ::com::sun::star::io;
      64             : using namespace ::com::sun::star::lang;
      65             : using namespace ::com::sun::star::util;
      66             : using namespace ::com::sun::star::form::binding;
      67             : using namespace ::com::sun::star::form::validation;
      68             : using namespace ::dbtools;
      69             : using namespace ::comphelper;
      70             : 
      71             : // FieldChangeNotifier
      72        1231 : void ControlModelLock::impl_notifyAll_nothrow()
      73             : {
      74        1231 :     m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() );
      75        1231 : }
      76             : 
      77          31 : void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue )
      78             : {
      79          31 :     sal_Int32 nOldLength = m_aHandles.getLength();
      80          62 :     if  (   ( nOldLength != m_aOldValues.getLength() )
      81          31 :         ||  ( nOldLength != m_aNewValues.getLength() )
      82             :         )
      83           0 :         throw RuntimeException( OUString(), m_rModel );
      84             : 
      85          31 :     m_aHandles.realloc( nOldLength + 1 );
      86          31 :     m_aHandles[ nOldLength ] = _nHandle;
      87          31 :     m_aOldValues.realloc( nOldLength + 1 );
      88          31 :     m_aOldValues[ nOldLength ] = _rOldValue;
      89          31 :     m_aNewValues.realloc( nOldLength + 1 );
      90          31 :     m_aNewValues[ nOldLength ] = _rNewValue;
      91          31 : }
      92             : 
      93             : class FieldChangeNotifier
      94             : {
      95             : public:
      96         654 :     FieldChangeNotifier( ControlModelLock& _rLock )
      97             :         :m_rLock( _rLock )
      98         654 :         ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) )
      99             :     {
     100         654 :         m_xOldField = m_rModel.getField();
     101         654 :     }
     102             : 
     103         654 :     ~FieldChangeNotifier()
     104         654 :     {
     105         654 :         Reference< XPropertySet > xNewField( m_rModel.getField() );
     106         654 :         if ( m_xOldField != xNewField )
     107          31 :             m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) );
     108         654 :     }
     109             : 
     110             : private:
     111             :     ControlModelLock&           m_rLock;
     112             :     OBoundControlModel&         m_rModel;
     113             :     Reference< XPropertySet >   m_xOldField;
     114             : };
     115             : 
     116             : // base class for form layer controls
     117         319 : OControl::OControl( const Reference< XComponentContext >& _rxContext, const OUString& _rAggregateService, const sal_Bool _bSetDelegator )
     118             :             :OComponentHelper(m_aMutex)
     119         319 :             ,m_xContext( _rxContext )
     120             : {
     121             :     // aggregate VCL-Control
     122             :     // bei Aggregation den Refcount um eins erhoehen da im setDelegator
     123             :     // das Aggregat selbst den Refcount erhoeht
     124         319 :     increment( m_refCount );
     125             :     {
     126         319 :         m_xAggregate = m_xAggregate.query( _rxContext->getServiceManager()->createInstanceWithContext(_rAggregateService, _rxContext) );
     127         319 :         m_xControl = m_xControl.query( m_xAggregate );
     128             :     }
     129         319 :     decrement( m_refCount );
     130             : 
     131         319 :     if ( _bSetDelegator )
     132         301 :         doSetDelegator();
     133         319 : }
     134             : 
     135         550 : OControl::~OControl()
     136             : {
     137         275 :     doResetDelegator();
     138         275 : }
     139             : 
     140         280 : void OControl::doResetDelegator()
     141             : {
     142         280 :     if ( m_xAggregate.is() )
     143         280 :         m_xAggregate->setDelegator( NULL );
     144         280 : }
     145             : 
     146         319 : void OControl::doSetDelegator()
     147             : {
     148         319 :     increment( m_refCount );
     149         319 :     if ( m_xAggregate.is() )
     150             :     {   // those brackets are important for some compilers, don't remove!
     151             :         // (they ensure that the temporary object created in the line below
     152             :         // is destroyed *before* the refcount-decrement)
     153         319 :         m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
     154             :     }
     155         319 :     decrement( m_refCount );
     156         319 : }
     157             : 
     158             : // UNO Anbindung
     159       13530 : Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException, std::exception)
     160             : {
     161             :     // ask the base class
     162       13530 :     Any aReturn( OComponentHelper::queryAggregation(_rType) );
     163             :     // ask our own interfaces
     164       13530 :     if (!aReturn.hasValue())
     165             :     {
     166       12742 :         aReturn = OControl_BASE::queryInterface(_rType);
     167             :         // ask our aggregate
     168       12742 :         if (!aReturn.hasValue() && m_xAggregate.is())
     169        7333 :             aReturn = m_xAggregate->queryAggregation(_rType);
     170             :     }
     171             : 
     172       13530 :     return aReturn;
     173             : }
     174             : 
     175           0 : Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException, std::exception)
     176             : {
     177           0 :     return css::uno::Sequence<sal_Int8>();
     178             : }
     179             : 
     180         132 : Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException, std::exception)
     181             : {
     182         132 :     TypeBag aTypes( _getTypes() );
     183             : 
     184         264 :     Reference< XTypeProvider > xProv;
     185         132 :     if ( query_aggregation( m_xAggregate, xProv ) )
     186         132 :         aTypes.addTypes( xProv->getTypes() );
     187             : 
     188         264 :     return aTypes.getTypes();
     189             : }
     190             : 
     191          74 : Sequence<Type> OControl::_getTypes()
     192             : {
     193          74 :     return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes();
     194             : }
     195             : 
     196         429 : void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ )
     197             : {
     198             :     // nothing to do here
     199         429 : }
     200             : 
     201             : // OComponentHelper
     202         277 : void OControl::disposing()
     203             : {
     204         277 :     OComponentHelper::disposing();
     205             : 
     206         277 :     m_aWindowStateGuard.attach( NULL, NULL );
     207             : 
     208         277 :     Reference< XComponent > xComp;
     209         277 :     if (query_aggregation(m_xAggregate, xComp))
     210         277 :         xComp->dispose();
     211         277 : }
     212             : 
     213             : // XServiceInfo
     214           0 : sal_Bool SAL_CALL OControl::supportsService(const OUString& _rsServiceName) throw ( RuntimeException, std::exception)
     215             : {
     216           0 :     return cppu::supportsService(this, _rsServiceName);
     217             : }
     218             : 
     219           0 : Sequence< OUString > OControl::getAggregateServiceNames()
     220             : {
     221           0 :     Sequence< OUString > aAggServices;
     222           0 :     Reference< XServiceInfo > xInfo;
     223           0 :     if ( query_aggregation( m_xAggregate, xInfo ) )
     224           0 :         aAggServices = xInfo->getSupportedServiceNames();
     225             : 
     226           0 :     return aAggServices;
     227             : }
     228             : 
     229           0 : Sequence<OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException, std::exception)
     230             : {
     231             :     return ::comphelper::concatSequences(
     232             :         getAggregateServiceNames(),
     233             :         getSupportedServiceNames_Static()
     234           0 :    );
     235             : }
     236             : 
     237           0 : Sequence< OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException )
     238             : {
     239             :     // no own supported service names
     240           0 :     return Sequence< OUString >();
     241             : }
     242             : 
     243             : // XEventListener
     244         815 : void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException, std::exception)
     245             : {
     246         815 :     Reference< XInterface > xAggAsIface;
     247         815 :     query_aggregation(m_xAggregate, xAggAsIface);
     248             : 
     249             :     // does the disposing come from the aggregate?
     250         815 :     if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY))
     251             :     {   // no -> forward it
     252         589 :                 Reference<com::sun::star::lang::XEventListener> xListener;
     253         589 :         if (query_aggregation(m_xAggregate, xListener))
     254         589 :             xListener->disposing(_rEvent);
     255         815 :     }
     256         815 : }
     257             : 
     258             : // XControl
     259         362 : void SAL_CALL OControl::setContext(const Reference< XInterface >& Context) throw (RuntimeException, std::exception)
     260             : {
     261         362 :     if (m_xControl.is())
     262         362 :         m_xControl->setContext(Context);
     263         362 : }
     264             : 
     265          13 : Reference< XInterface > SAL_CALL OControl::getContext() throw (RuntimeException, std::exception)
     266             : {
     267          13 :     return m_xControl.is() ? m_xControl->getContext() : Reference< XInterface >();
     268             : }
     269             : 
     270         611 : void OControl::impl_resetStateGuard_nothrow()
     271             : {
     272         611 :     Reference< XWindow2 > xWindow;
     273        1222 :     Reference< XControlModel > xModel;
     274             :     try
     275             :     {
     276         611 :         xWindow.set( getPeer(), UNO_QUERY );
     277         611 :         xModel.set( getModel(), UNO_QUERY );
     278             :     }
     279           0 :     catch( const Exception& )
     280             :     {
     281             :         DBG_UNHANDLED_EXCEPTION();
     282             :     }
     283        1222 :     m_aWindowStateGuard.attach( xWindow, xModel );
     284         611 : }
     285             : 
     286         327 : void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException, std::exception)
     287             : {
     288         327 :     if ( m_xControl.is() )
     289             :     {
     290         327 :         m_xControl->createPeer( _rxToolkit, _rxParent );
     291         327 :         initFormControlPeer( getPeer() );
     292         327 :         impl_resetStateGuard_nothrow();
     293             :     }
     294         327 : }
     295             : 
     296        3734 : Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException, std::exception)
     297             : {
     298        3734 :     return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
     299             : }
     300             : 
     301         284 : sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException, std::exception)
     302             : {
     303         284 :     if ( !m_xControl.is() )
     304           0 :         return sal_False;
     305             : 
     306         284 :     sal_Bool bSuccess = m_xControl->setModel( Model );
     307         284 :     impl_resetStateGuard_nothrow();
     308         284 :     return bSuccess;
     309             : }
     310             : 
     311        1930 : Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException, std::exception)
     312             : {
     313        1930 :     return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
     314             : }
     315             : 
     316          13 : Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException, std::exception)
     317             : {
     318          13 :     return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
     319             : }
     320             : 
     321         199 : void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException, std::exception)
     322             : {
     323         199 :     if (m_xControl.is())
     324         199 :         m_xControl->setDesignMode(bOn);
     325         199 : }
     326             : 
     327       11117 : sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException, std::exception)
     328             : {
     329       11117 :     return m_xControl.is() ? m_xControl->isDesignMode() : sal_True;
     330             : }
     331             : 
     332          13 : sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException, std::exception)
     333             : {
     334          13 :     return m_xControl.is() ? m_xControl->isTransparent() : sal_True;
     335             : }
     336             : 
     337             : // OBoundControl
     338         169 : OBoundControl::OBoundControl( const Reference< XComponentContext >& _rxContext,
     339             :             const OUString& _rAggregateService, const sal_Bool _bSetDelegator )
     340             :     :OControl( _rxContext, _rAggregateService, _bSetDelegator )
     341             :     ,m_bLocked(sal_False)
     342             :     ,m_aOriginalFont( EmptyFontDescriptor() )
     343         169 :     ,m_nOriginalTextLineColor( 0 )
     344             : {
     345         169 : }
     346             : 
     347         133 : OBoundControl::~OBoundControl()
     348             : {
     349         133 : }
     350             : 
     351          70 : Sequence< Type> OBoundControl::_getTypes()
     352             : {
     353          70 :     return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes();
     354             : }
     355             : 
     356       11483 : Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException, std::exception)
     357             : {
     358       11483 :     Any aReturn;
     359             : 
     360             :     // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types
     361       11483 :     if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) )
     362          35 :         aReturn = OControl::queryAggregation( _rType );
     363             : 
     364             :     // ask our own interfaces
     365             :     // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener)
     366       11483 :     if ( !aReturn.hasValue() )
     367       11448 :         aReturn = OBoundControl_BASE::queryInterface( _rType );
     368             : 
     369             :     // ask the base class
     370       11483 :     if ( !aReturn.hasValue() )
     371       10168 :         aReturn = OControl::queryAggregation( _rType );
     372             : 
     373       11483 :     return aReturn;
     374             : }
     375             : 
     376          22 : sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException, std::exception)
     377             : {
     378          22 :     return m_bLocked;
     379             : }
     380             : 
     381          22 : void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException, std::exception)
     382             : {
     383          22 :     if (m_bLocked == _bLock)
     384          22 :         return;
     385             : 
     386          22 :     osl::MutexGuard aGuard(m_aMutex);
     387          22 :     _setLock(_bLock);
     388          22 :     m_bLocked = _bLock;
     389             : }
     390             : 
     391          22 : void OBoundControl::_setLock(sal_Bool _bLock)
     392             : {
     393             :     // try to set the text component to readonly
     394          22 :     Reference< XWindowPeer > xPeer = getPeer();
     395          44 :     Reference< XTextComponent > xText( xPeer, UNO_QUERY );
     396             : 
     397          22 :     if ( xText.is() )
     398          16 :         xText->setEditable( !_bLock );
     399             :     else
     400             :     {
     401             :         // disable the window
     402           6 :         Reference< XWindow > xComp( xPeer, UNO_QUERY );
     403           6 :         if ( xComp.is() )
     404           6 :             xComp->setEnable( !_bLock );
     405          22 :     }
     406          22 : }
     407             : 
     408         137 : sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException, std::exception)
     409             : {
     410         137 :     return OControl::setModel( _rxModel );
     411             : }
     412             : 
     413         342 : void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException, std::exception)
     414             : {
     415             :     // just disambiguate
     416         342 :     OControl::disposing(Source);
     417         342 : }
     418             : 
     419         135 : void OBoundControl::disposing()
     420             : {
     421         135 :     OControl::disposing();
     422         135 : }
     423             : 
     424             : // OControlModel
     425          32 : Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException, std::exception)
     426             : {
     427          32 :     return css::uno::Sequence<sal_Int8>();
     428             : }
     429             : 
     430          86 : Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException, std::exception)
     431             : {
     432          86 :     TypeBag aTypes( _getTypes() );
     433             : 
     434         172 :     Reference< XTypeProvider > xProv;
     435             : 
     436          86 :     if ( query_aggregation( m_xAggregate, xProv ) )
     437          86 :         aTypes.addTypes( xProv->getTypes() );
     438             : 
     439         172 :     return aTypes.getTypes();
     440             : }
     441             : 
     442          86 : Sequence<Type> OControlModel::_getTypes()
     443             : {
     444             :     return TypeBag( OComponentHelper::getTypes(),
     445             :         OPropertySetAggregationHelper::getTypes(),
     446             :         OControlModel_BASE::getTypes()
     447          86 :     ).getTypes();
     448             : }
     449             : 
     450      106361 : Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
     451             : {
     452             :     // base class 1
     453      106361 :     Any aReturn(OComponentHelper::queryAggregation(_rType));
     454             : 
     455             :     // base class 2
     456      106361 :     if (!aReturn.hasValue())
     457             :     {
     458       78933 :         aReturn = OControlModel_BASE::queryInterface(_rType);
     459             : 
     460             :         // our own interfaces
     461       78933 :         if (!aReturn.hasValue())
     462             :         {
     463       74515 :             aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
     464             :             // our aggregate
     465       74515 :             if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL))))
     466       43462 :                 aReturn = m_xAggregate->queryAggregation(_rType);
     467             :         }
     468             :     }
     469      106361 :     return aReturn;
     470             : }
     471             : 
     472          18 : void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream)
     473             : {
     474          18 :     OUString sHelpText;
     475          18 :     ::comphelper::operator>>( _rxInStream, sHelpText);
     476             :     try
     477             :     {
     478          18 :         if (m_xAggregateSet.is())
     479          18 :             m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText));
     480             :     }
     481           0 :     catch(const Exception&)
     482             :     {
     483             :         SAL_WARN("forms.component", "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
     484             :         DBG_UNHANDLED_EXCEPTION();
     485          18 :     }
     486          18 : }
     487             : 
     488          18 : void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream)
     489             : {
     490          18 :     OUString sHelpText;
     491             :     try
     492             :     {
     493          18 :         if (m_xAggregateSet.is())
     494          18 :             m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
     495             :     }
     496           0 :     catch(const Exception&)
     497             :     {
     498             :         SAL_WARN("forms.component", "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
     499             :         DBG_UNHANDLED_EXCEPTION();
     500             :     }
     501          18 :     ::comphelper::operator<<( _rxOutStream, sHelpText);
     502          18 : }
     503             : 
     504         544 : OControlModel::OControlModel(
     505             :             const Reference<XComponentContext>& _rxContext,
     506             :             const OUString& _rUnoControlModelTypeName,
     507             :             const OUString& rDefault, const sal_Bool _bSetDelegator)
     508             :     :OComponentHelper(m_aMutex)
     509             :     ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
     510             :     ,m_xContext( _rxContext )
     511             :     ,m_lockCount( 0 )
     512             :     ,m_aPropertyBagHelper( *this )
     513             :     ,m_nTabIndex(FRM_DEFAULT_TABINDEX)
     514             :     ,m_nClassId(FormComponentType::CONTROL)
     515             :     ,m_bNativeLook( sal_False )
     516             :     ,m_bGenerateVbEvents( sal_False )
     517             :     ,m_nControlTypeinMSO(0) // 0 : default value is create from AOO
     518         544 :     ,m_nObjIDinMSO(INVALID_OBJ_ID_IN_MSO)
     519             :     // form controls are usually embedded into documents, not dialogs, and in documents
     520             :     // the native look is ugly...
     521             :     // #i37342#
     522             : {
     523         544 :     if (!_rUnoControlModelTypeName.isEmpty())  // the is a model we have to aggregate
     524             :     {
     525         411 :         increment(m_refCount);
     526             :         {
     527         411 :             m_xAggregate = Reference<XAggregation>(m_xContext->getServiceManager()->createInstanceWithContext(_rUnoControlModelTypeName, m_xContext), UNO_QUERY);
     528         411 :             setAggregation(m_xAggregate);
     529             : 
     530         411 :             if ( m_xAggregateSet.is() )
     531             :             {
     532             :                 try
     533             :                 {
     534         411 :                     if ( !rDefault.isEmpty() )
     535         344 :                         m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) );
     536             :                 }
     537           0 :                 catch( const Exception& )
     538             :                 {
     539             :                     SAL_WARN("forms.component",  "OControlModel::OControlModel: caught an exception!");
     540             :                     DBG_UNHANDLED_EXCEPTION();
     541             :                 }
     542             :             }
     543             :         }
     544         411 :         if (_bSetDelegator)
     545         143 :             doSetDelegator();
     546             : 
     547             :         // Refcount is at NULL again
     548         411 :         decrement(m_refCount);
     549             :     }
     550         544 : }
     551             : 
     552          22 : OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator )
     553             :     :OComponentHelper( m_aMutex )
     554             :     ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
     555             :     ,m_xContext( _rxFactory )
     556             :     ,m_lockCount( 0 )
     557             :     ,m_aPropertyBagHelper( *this )
     558             :     ,m_nTabIndex( FRM_DEFAULT_TABINDEX )
     559          22 :     ,m_nClassId( FormComponentType::CONTROL )
     560             : {
     561             :     DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" );
     562             : 
     563             :     // copy members
     564          22 :     m_aName = _pOriginal->m_aName;
     565          22 :     m_aTag = _pOriginal->m_aTag;
     566          22 :     m_nTabIndex = _pOriginal->m_nTabIndex;
     567          22 :     m_nClassId = _pOriginal->m_nClassId;
     568          22 :     m_bNativeLook = _pOriginal->m_bNativeLook;
     569          22 :     m_bGenerateVbEvents = _pOriginal->m_bGenerateVbEvents;
     570          22 :     m_nControlTypeinMSO = _pOriginal->m_nControlTypeinMSO;
     571          22 :     m_nObjIDinMSO = _pOriginal->m_nObjIDinMSO;
     572             : 
     573          22 :     if ( _bCloneAggregate )
     574             :     {
     575             :         // temporarily increment refcount because of temporary references to ourself in the following
     576          20 :         increment( m_refCount );
     577             :         {
     578             :             // transfer the (only, at the very moment!) ref count
     579          20 :             m_xAggregate = createAggregateClone( _pOriginal );
     580             : 
     581             :             // set aggregation (retrieve other direct interfaces of the aggregate)
     582          20 :             setAggregation( m_xAggregate );
     583             :         }
     584             : 
     585             :         // set the delegator, if allowed by our derived class
     586          20 :         if ( _bSetDelegator )
     587           5 :             doSetDelegator();
     588             : 
     589             :         // decrement ref count
     590          20 :         decrement( m_refCount );
     591             :     }
     592          22 : }
     593             : 
     594        1062 : OControlModel::~OControlModel()
     595             : {
     596             :     // release the aggregate
     597         531 :     doResetDelegator( );
     598         531 : }
     599             : 
     600           7 : void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ )
     601             : {
     602             :     // nothing to do in this base class
     603           7 : }
     604             : 
     605         795 : void OControlModel::doResetDelegator()
     606             : {
     607         795 :     if (m_xAggregate.is())
     608         766 :         m_xAggregate->setDelegator(NULL);
     609         795 : }
     610             : 
     611         537 : void OControlModel::doSetDelegator()
     612             : {
     613         537 :     increment(m_refCount);
     614         537 :     if (m_xAggregate.is())
     615             :     {
     616         535 :         m_xAggregate->setDelegator(static_cast<XWeak*>(this));
     617             :     }
     618         537 :     decrement(m_refCount);
     619         537 : }
     620             : 
     621             : // XChild
     622        4311 : Reference< XInterface > SAL_CALL OControlModel::getParent() throw(RuntimeException, std::exception)
     623             : {
     624        4311 :     return m_xParent;
     625             : }
     626             : 
     627         866 : void SAL_CALL OControlModel::setParent(const Reference< XInterface >& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException, std::exception)
     628             : {
     629         866 :     osl::MutexGuard aGuard(m_aMutex);
     630             : 
     631        1732 :     Reference<XComponent> xComp(m_xParent, UNO_QUERY);
     632         866 :     if (xComp.is())
     633         255 :         xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this));
     634             : 
     635         866 :     m_xParent = _rxParent;
     636         866 :     xComp = xComp.query( m_xParent );
     637             : 
     638         866 :     if ( xComp.is() )
     639        1231 :         xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this));
     640         866 : }
     641             : 
     642             : // XNamed
     643         188 : OUString SAL_CALL OControlModel::getName() throw(RuntimeException, std::exception)
     644             : {
     645         188 :     OUString aReturn;
     646         188 :     OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn;
     647         188 :     return aReturn;
     648             : }
     649             : 
     650          38 : void SAL_CALL OControlModel::setName(const OUString& _rName) throw(RuntimeException, std::exception)
     651             : {
     652          38 :         setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName));
     653          38 : }
     654             : 
     655             : // XServiceInfo
     656         279 : sal_Bool SAL_CALL OControlModel::supportsService(const OUString& _rServiceName) throw ( RuntimeException, std::exception)
     657             : {
     658         279 :     return cppu::supportsService(this, _rServiceName);
     659             : }
     660             : 
     661         322 : Sequence< OUString > OControlModel::getAggregateServiceNames()
     662             : {
     663         322 :     Sequence< OUString > aAggServices;
     664         644 :     Reference< XServiceInfo > xInfo;
     665         322 :     if ( query_aggregation( m_xAggregate, xInfo ) )
     666         317 :         aAggServices = xInfo->getSupportedServiceNames();
     667         644 :     return aAggServices;
     668             : }
     669             : 
     670          19 : Sequence<OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException, std::exception)
     671             : {
     672             :     return ::comphelper::concatSequences(
     673             :         getAggregateServiceNames(),
     674             :         getSupportedServiceNames_Static()
     675          19 :     );
     676             : }
     677             : 
     678         395 : Sequence< OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
     679             : {
     680         395 :     Sequence< OUString > aServiceNames( 2 );
     681         395 :     aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT;
     682         395 :     aServiceNames[ 1 ] = "com.sun.star.form.FormControlModel";
     683         395 :     return aServiceNames;
     684             : }
     685             : 
     686             : // XEventListener
     687         263 : void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException, std::exception)
     688             : {
     689             :     // release the parent
     690         263 :     if (_rSource.Source == m_xParent)
     691             :     {
     692         106 :         osl::MutexGuard aGuard(m_aMutex);
     693         106 :         m_xParent = NULL;
     694             :     }
     695             :     else
     696             :     {
     697         157 :         Reference<com::sun::star::lang::XEventListener> xEvtLst;
     698         157 :         if (query_aggregation(m_xAggregate, xEvtLst))
     699             :         {
     700          46 :             osl::MutexGuard aGuard(m_aMutex);
     701          46 :             xEvtLst->disposing(_rSource);
     702         157 :         }
     703             :     }
     704         263 : }
     705             : 
     706             : // OComponentHelper
     707         534 : void OControlModel::disposing()
     708             : {
     709         534 :     OPropertySetAggregationHelper::disposing();
     710             : 
     711         534 :     Reference<com::sun::star::lang::XComponent> xComp;
     712         534 :     if (query_aggregation(m_xAggregate, xComp))
     713         407 :         xComp->dispose();
     714             : 
     715         534 :     setParent(Reference<XFormComponent>());
     716             : 
     717         534 :     m_aPropertyBagHelper.dispose();
     718         534 : }
     719             : 
     720          19 : void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
     721             : {
     722          19 :     Reference< XPersistObject > xPersist;
     723          19 :     if ( query_aggregation( m_xAggregate, xPersist ) )
     724          16 :         xPersist->write( _rxOutStream );
     725          19 : }
     726             : 
     727          16 : void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
     728             : {
     729          16 :     Reference< XPersistObject > xPersist;
     730          16 :     if ( query_aggregation( m_xAggregate, xPersist ) )
     731          16 :         xPersist->read( _rxInStream );
     732          16 : }
     733             : 
     734          21 : void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream)
     735             :                         throw(stario::IOException, RuntimeException, std::exception)
     736             : {
     737          21 :     osl::MutexGuard aGuard(m_aMutex);
     738             : 
     739             :     // 1. writing the UnoControls
     740          42 :     Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
     741          21 :     if ( !xMark.is() )
     742             :     {
     743             :         throw IOException(
     744             :             FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
     745             :             static_cast< ::cppu::OWeakObject* >( this )
     746           0 :         );
     747             :     }
     748             : 
     749          21 :     sal_Int32 nMark = xMark->createMark();
     750          21 :     sal_Int32 nLen = 0;
     751             : 
     752          21 :     _rxOutStream->writeLong(nLen);
     753             : 
     754          21 :     writeAggregate( _rxOutStream );
     755             : 
     756             :     // determining the length
     757          21 :     nLen = xMark->offsetToMark(nMark) - 4;
     758          21 :     xMark->jumpToMark(nMark);
     759          21 :     _rxOutStream->writeLong(nLen);
     760          21 :     xMark->jumpToFurthest();
     761          21 :     xMark->deleteMark(nMark);
     762             : 
     763             :     // 2. wrting a version number
     764          21 :     _rxOutStream->writeShort(0x0003);
     765             : 
     766             :     // 3. Schreiben der allgemeinen Properties
     767          21 :     ::comphelper::operator<<( _rxOutStream, m_aName);
     768          21 :     _rxOutStream->writeShort(m_nTabIndex);
     769          42 :     ::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version
     770             : 
     771             :     // IMPORTANT NOTE!
     772             :     // don't write any new members here : this wouldn't be compatible with older versions, as OControlModel
     773             :     // is a base class which is called in derived classes "read" method. So if you increment the version
     774             :     // and write new stuff, older office versions will read this in the _derived_ classes, which may result
     775             :     // in anything from data loss to crash.
     776             :     // EOIN!
     777          21 : }
     778             : 
     779          21 : void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException, std::exception)
     780             : {
     781          21 :     osl::MutexGuard aGuard(m_aMutex);
     782             : 
     783          42 :     Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY);
     784          21 :     if ( !xMark.is() )
     785             :     {
     786             :         throw IOException(
     787             :             FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
     788             :             static_cast< ::cppu::OWeakObject* >( this )
     789           0 :         );
     790             :     }
     791             : 
     792             :     // 1. reading the UnoControls
     793          21 :     sal_Int32 nLen = InStream->readLong();
     794          21 :     if (nLen)
     795             :     {
     796          18 :         sal_Int32 nMark = xMark->createMark();
     797             : 
     798             :         try
     799             :         {
     800          18 :             readAggregate( InStream );
     801             :         }
     802             : 
     803           0 :         catch( const Exception& )
     804             :         {
     805             :             DBG_UNHANDLED_EXCEPTION();
     806             :         }
     807             : 
     808          18 :         xMark->jumpToMark(nMark);
     809          18 :         InStream->skipBytes(nLen);
     810          18 :         xMark->deleteMark(nMark);
     811             :     }
     812             : 
     813             :     // 2. reading the version number
     814          21 :     sal_uInt16 nVersion = InStream->readShort();
     815             : 
     816             :     // 3. reading the general properties
     817          21 :     ::comphelper::operator>>( InStream, m_aName);
     818          21 :     m_nTabIndex  = InStream->readShort();
     819             : 
     820          21 :     if (nVersion > 0x0002)
     821          21 :         ::comphelper::operator>>( InStream, m_aTag);
     822             : 
     823             :     // we had a version where we wrote the help text
     824          21 :     if (nVersion == 0x0004)
     825           0 :         readHelpTextCompatibly(InStream);
     826             : 
     827          21 :     DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !");
     828             :     // 4 was the version where we wrote the help text
     829             :     // later versions shouldn't exist (see write for a detailed comment)
     830          21 : }
     831             : 
     832           8 : PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle )
     833             : {
     834             :     // simply compare the current and the default value
     835           8 :     Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
     836          16 :     Any aDefaultValue;  getFastPropertyValue( aDefaultValue, _nHandle );
     837             : 
     838             :     sal_Bool bEqual = uno_type_equalData(
     839          16 :             const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
     840          16 :             const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
     841             :             reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
     842             :             reinterpret_cast< uno_ReleaseFunc >(cpp_release)
     843          24 :         );
     844          16 :     return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
     845             : }
     846             : 
     847           3 : void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle)
     848             : {
     849           3 :     Any aDefault = getPropertyDefaultByHandle( _nHandle );
     850             : 
     851           6 :     Any aConvertedValue, aOldValue;
     852           3 :     if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) )
     853             :     {
     854           0 :         setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue );
     855             :         // TODO: fire the property change
     856           3 :     }
     857           3 : }
     858             : 
     859           0 : Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
     860             : {
     861           0 :     Any aReturn;
     862           0 :     switch ( _nHandle )
     863             :     {
     864             :         case PROPERTY_ID_NAME:
     865             :         case PROPERTY_ID_TAG:
     866           0 :             aReturn <<= OUString();
     867           0 :             break;
     868             :         case PROPERTY_ID_CLASSID:
     869           0 :             aReturn <<= (sal_Int16)FormComponentType::CONTROL;
     870           0 :             break;
     871             :         case PROPERTY_ID_TABINDEX:
     872           0 :             aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX;
     873           0 :             break;
     874             :         case PROPERTY_ID_NATIVE_LOOK:
     875           0 :             aReturn <<= (sal_Bool)sal_True;
     876           0 :             break;
     877             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     878           0 :             aReturn <<= (sal_Bool)sal_False;
     879           0 :             break;
     880             :         // added for exporting OCX control
     881             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
     882           0 :             aReturn <<= (sal_Int16)0;
     883           0 :             break;
     884             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
     885           0 :             aReturn <<= (sal_uInt16)INVALID_OBJ_ID_IN_MSO;
     886           0 :             break;
     887             :         default:
     888           0 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
     889           0 :                 m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn );
     890             :             else
     891             :                 SAL_WARN("forms.component",  "OControlModel::convertFastPropertyValue: unknown handle " << _nHandle);
     892             :     }
     893           0 :     return aReturn;
     894             : }
     895             : 
     896       57343 : void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
     897             : {
     898       57343 :     switch ( _nHandle )
     899             :     {
     900             :         case PROPERTY_ID_NAME:
     901        4646 :             _rValue <<= m_aName;
     902        4646 :             break;
     903             :         case PROPERTY_ID_TAG:
     904        1414 :             _rValue <<= m_aTag;
     905        1414 :             break;
     906             :         case PROPERTY_ID_CLASSID:
     907        1797 :             _rValue <<= m_nClassId;
     908        1797 :             break;
     909             :         case PROPERTY_ID_TABINDEX:
     910        2519 :             _rValue <<= m_nTabIndex;
     911        2519 :             break;
     912             :         case PROPERTY_ID_NATIVE_LOOK:
     913        1278 :             _rValue <<= (sal_Bool)m_bNativeLook;
     914        1278 :             break;
     915             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     916         879 :             _rValue <<= (sal_Bool)m_bGenerateVbEvents;
     917             :         // added for exporting OCX control
     918             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
     919        2154 :             _rValue <<= (sal_Int16)m_nControlTypeinMSO;
     920        2154 :             break;
     921             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
     922        1278 :             _rValue <<= (sal_uInt16)m_nObjIDinMSO;
     923        1278 :             break;
     924             :         default:
     925       42257 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
     926           0 :                 m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue );
     927             :             else
     928       42257 :                 OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle );
     929       42257 :             break;
     930             :     }
     931       57343 : }
     932             : 
     933        5142 : sal_Bool OControlModel::convertFastPropertyValue(
     934             :                         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
     935             :                         throw (com::sun::star::lang::IllegalArgumentException)
     936             : {
     937        5142 :     sal_Bool bModified(sal_False);
     938        5142 :     switch (_nHandle)
     939             :     {
     940             :         case PROPERTY_ID_NAME:
     941        1251 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName);
     942        1250 :             break;
     943             :         case PROPERTY_ID_TAG:
     944         796 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag);
     945         796 :             break;
     946             :         case PROPERTY_ID_TABINDEX:
     947         753 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex);
     948         753 :             break;
     949             :         case PROPERTY_ID_NATIVE_LOOK:
     950         730 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook);
     951         730 :             break;
     952             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     953          90 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bGenerateVbEvents);
     954          90 :             break;
     955             :         // added for exporting OCX control
     956             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
     957         763 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nControlTypeinMSO);
     958         763 :             break;
     959             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
     960         759 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nObjIDinMSO);
     961         759 :             break;
     962             :         default:
     963           0 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
     964           0 :                 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
     965             :             else
     966             :                 SAL_WARN("forms.component",  "OControlModel::convertFastPropertyValue: unknown handle " << _nHandle);
     967           0 :             break;
     968             :     }
     969        5141 :     return bModified;
     970             : }
     971             : 
     972        1537 : void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
     973             :                         throw (Exception, std::exception)
     974             : {
     975        1537 :     switch (_nHandle)
     976             :     {
     977             :         case PROPERTY_ID_NAME:
     978             :             DBG_ASSERT(_rValue.getValueType() == getCppuType((const OUString*)NULL),
     979             :                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
     980         613 :             _rValue >>= m_aName;
     981         613 :             break;
     982             :         case PROPERTY_ID_TAG:
     983             :             DBG_ASSERT(_rValue.getValueType() == getCppuType((const OUString*)NULL),
     984             :                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
     985         191 :             _rValue >>= m_aTag;
     986         191 :             break;
     987             :         case PROPERTY_ID_TABINDEX:
     988             :             DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL),
     989             :                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
     990         178 :             _rValue >>= m_nTabIndex;
     991         178 :             break;
     992             :         case PROPERTY_ID_NATIVE_LOOK:
     993         143 :             OSL_VERIFY( _rValue >>= m_bNativeLook );
     994         143 :             break;
     995             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     996          64 :             OSL_VERIFY( _rValue >>= m_bGenerateVbEvents );
     997          64 :             break;
     998             :         // added for exporting OCX control
     999             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
    1000         176 :             OSL_VERIFY( _rValue >>= m_nControlTypeinMSO );
    1001         176 :             break;
    1002             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
    1003         172 :             OSL_VERIFY( _rValue >>= m_nObjIDinMSO );
    1004         172 :             break;
    1005             :         default:
    1006           0 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
    1007           0 :                 m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue );
    1008             :             else
    1009             :                 SAL_WARN("forms.component",  "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle " << _nHandle );
    1010           0 :             break;
    1011             :     }
    1012        1537 : }
    1013             : 
    1014         559 : void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
    1015             : {
    1016         559 :     BEGIN_DESCRIBE_BASE_PROPERTIES( 7 )
    1017         559 :         DECL_PROP2      (CLASSID,     sal_Int16,        READONLY, TRANSIENT);
    1018         559 :         DECL_PROP1      (NAME,        OUString,  BOUND);
    1019         559 :         DECL_BOOL_PROP2 (NATIVE_LOOK,                   BOUND, TRANSIENT);
    1020         559 :         DECL_PROP1      (TAG,         OUString,  BOUND);
    1021         559 :         DECL_PROP1      (GENERATEVBAEVENTS,         sal_Bool,  TRANSIENT);
    1022         559 :         DECL_PROP1      (CONTROL_TYPE_IN_MSO,sal_Int16,     BOUND);
    1023         559 :         DECL_PROP1      (OBJ_ID_IN_MSO,sal_uInt16,      BOUND);
    1024             :     END_DESCRIBE_PROPERTIES()
    1025         559 : }
    1026             : 
    1027         580 : void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const
    1028             : {
    1029         580 :     if ( m_xAggregateSet.is() )
    1030             :     {
    1031         547 :         Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() );
    1032         547 :         if ( xPSI.is() )
    1033         547 :             _rAggregateProps = xPSI->getProperties();
    1034             :     }
    1035         580 : }
    1036             : 
    1037         789 : ::osl::Mutex& OControlModel::getMutex()
    1038             : {
    1039         789 :     return m_aMutex;
    1040             : }
    1041             : 
    1042         580 : void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const
    1043             : {
    1044         580 :     describeFixedProperties( _out_rFixedProperties );
    1045         580 :     describeAggregateProperties( _out_rAggregateProperties );
    1046         580 : }
    1047             : 
    1048         152 : Reference< XMultiPropertySet > OControlModel::getPropertiesInterface()
    1049             : {
    1050         152 :     return Reference< XMultiPropertySet >( *this, UNO_QUERY );
    1051             : }
    1052             : 
    1053       20781 : Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException, std::exception)
    1054             : {
    1055       20781 :     return createPropertySetInfo( getInfoHelper() );
    1056             : }
    1057             : 
    1058      170924 : ::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper()
    1059             : {
    1060      170924 :     return m_aPropertyBagHelper.getInfoHelper();
    1061             : }
    1062             : 
    1063          76 : void SAL_CALL OControlModel::addProperty( const OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
    1064             : {
    1065          76 :     m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
    1066          19 : }
    1067             : 
    1068          57 : void SAL_CALL OControlModel::removeProperty( const OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException, std::exception)
    1069             : {
    1070          57 :     m_aPropertyBagHelper.removeProperty( _rName );
    1071          19 : }
    1072             : 
    1073          19 : Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException, std::exception)
    1074             : {
    1075          19 :     return m_aPropertyBagHelper.getPropertyValues();
    1076             : }
    1077             : 
    1078          57 : void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
    1079             : {
    1080          57 :     m_aPropertyBagHelper.setPropertyValues( _rProps );
    1081          19 : }
    1082             : 
    1083        1257 : void OControlModel::lockInstance( LockAccess )
    1084             : {
    1085        1257 :     m_aMutex.acquire();
    1086        1257 :     osl_atomic_increment( &m_lockCount );
    1087        1257 : }
    1088             : 
    1089        1257 : oslInterlockedCount OControlModel::unlockInstance( LockAccess )
    1090             : {
    1091             :     OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" );
    1092        1257 :     oslInterlockedCount lockCount = osl_atomic_decrement( &m_lockCount );
    1093        1257 :     m_aMutex.release();
    1094        1257 :     return lockCount;
    1095             : }
    1096             : 
    1097        1231 : void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues,
    1098             :                                         const Sequence< Any >& _rNewValues, LockAccess )
    1099             : {
    1100             :     OPropertySetHelper::fire(
    1101             :         const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(),
    1102             :         _rNewValues.getConstArray(),
    1103             :         _rOldValues.getConstArray(),
    1104             :         _rHandles.getLength(),
    1105             :         sal_False
    1106        1231 :     );
    1107        1231 : }
    1108             : 
    1109             : // OBoundControlModel
    1110       78373 : Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException, std::exception)
    1111             : {
    1112       78373 :     Any aReturn( OControlModel::queryAggregation(_rType) );
    1113       78373 :     if (!aReturn.hasValue())
    1114             :     {
    1115        2553 :         aReturn = OBoundControlModel_BASE1::queryInterface(_rType);
    1116             : 
    1117        2553 :         if ( !aReturn.hasValue() && m_bCommitable )
    1118        1954 :             aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType );
    1119             : 
    1120        2553 :         if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
    1121        2116 :             aReturn = OBoundControlModel_BINDING::queryInterface( _rType );
    1122             : 
    1123        2553 :         if ( !aReturn.hasValue() && m_bSupportsValidation )
    1124        1983 :             aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType );
    1125             :     }
    1126       78373 :     return aReturn;
    1127             : }
    1128             : 
    1129         268 : OBoundControlModel::OBoundControlModel(
    1130             :         const Reference< XComponentContext>& _rxFactory,
    1131             :         const OUString& _rUnoControlModelTypeName, const OUString& _rDefault,
    1132             :         const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation )
    1133             :     :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False )
    1134             :     ,OPropertyChangeListener( m_aMutex )
    1135             :     ,m_xField()
    1136             :     ,m_xAmbientForm()
    1137             :     ,m_nValuePropertyAggregateHandle( -1 )
    1138             :     ,m_nFieldType( DataType::OTHER )
    1139             :     ,m_bValuePropertyMayBeVoid( false )
    1140             :     ,m_aResetHelper( *this, m_aMutex )
    1141             :     ,m_aUpdateListeners(m_aMutex)
    1142             :     ,m_aFormComponentListeners( m_aMutex )
    1143             :     ,m_bInputRequired( sal_True )
    1144             :     ,m_pAggPropMultiplexer( NULL )
    1145             :     ,m_bFormListening( false )
    1146             :     ,m_bLoaded(sal_False)
    1147             :     ,m_bRequired(sal_False)
    1148             :     ,m_bCommitable(_bCommitable)
    1149             :     ,m_bSupportsExternalBinding( _bSupportExternalBinding )
    1150             :     ,m_bSupportsValidation( _bSupportsValidation )
    1151             :     ,m_bForwardValueChanges(sal_True)
    1152             :     ,m_bTransferingValue( sal_False )
    1153             :     ,m_bIsCurrentValueValid( sal_True )
    1154             :     ,m_bBindingControlsRO( sal_False )
    1155             :     ,m_bBindingControlsEnable( sal_False )
    1156             :     ,m_eControlValueChangeInstigator( eOther )
    1157         268 :     ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
    1158             : {
    1159             :     // start property listening at the aggregate
    1160         268 :     implInitAggMultiplexer( );
    1161         268 : }
    1162             : 
    1163          15 : OBoundControlModel::OBoundControlModel(
    1164             :         const OBoundControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory )
    1165             :     :OControlModel( _pOriginal, _rxFactory, sal_True, sal_False )
    1166             :     ,OPropertyChangeListener( m_aMutex )
    1167             :     ,m_xField()
    1168             :     ,m_xAmbientForm()
    1169             :     ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
    1170             :     ,m_nFieldType( DataType::OTHER )
    1171             :     ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid )
    1172             :     ,m_aResetHelper( *this, m_aMutex )
    1173             :     ,m_aUpdateListeners( m_aMutex )
    1174             :     ,m_aFormComponentListeners( m_aMutex )
    1175             :     ,m_xValidator( _pOriginal->m_xValidator )
    1176             :     ,m_bInputRequired( sal_True )
    1177             :     ,m_pAggPropMultiplexer( NULL )
    1178             :     ,m_bFormListening( false )
    1179             :     ,m_bLoaded( sal_False )
    1180             :     ,m_bRequired( sal_False )
    1181             :     ,m_bCommitable( _pOriginal->m_bCommitable )
    1182             :     ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
    1183             :     ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
    1184             :     ,m_bForwardValueChanges( sal_True )
    1185             :     ,m_bTransferingValue( sal_False )
    1186             :     ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
    1187             :     ,m_bBindingControlsRO( sal_False )
    1188             :     ,m_bBindingControlsEnable( sal_False )
    1189          15 :     ,m_eControlValueChangeInstigator( eOther )
    1190             : {
    1191             :     // start property listening at the aggregate
    1192          15 :     implInitAggMultiplexer( );
    1193          15 :     m_aLabelServiceName = _pOriginal->m_aLabelServiceName;
    1194          15 :     m_sValuePropertyName = _pOriginal->m_sValuePropertyName;
    1195          15 :     m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle;
    1196          15 :     m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid;
    1197          15 :     m_aValuePropertyType = _pOriginal->m_aValuePropertyType;
    1198          15 :     m_aControlSource = _pOriginal->m_aControlSource;
    1199          15 :     m_bInputRequired = _pOriginal->m_bInputRequired;
    1200             :     // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transferred.
    1201             :     // (the former should be clear - a clone of the object we're only referencing does not make sense)
    1202             :     // (the second would violate the restriction for label controls that they're part of the
    1203             :     // same form component hierarchy - we ourself are no part, yet, so we can't have a label control)
    1204             :     // start listening for changes at the value property
    1205          15 :     implInitValuePropertyListening( );
    1206          15 : }
    1207             : 
    1208         528 : OBoundControlModel::~OBoundControlModel()
    1209             : {
    1210         264 :     if ( !OComponentHelper::rBHelper.bDisposed )
    1211             :     {
    1212           0 :         acquire();
    1213           0 :         dispose();
    1214             :     }
    1215             : 
    1216         264 :     doResetDelegator( );
    1217             :     OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" );
    1218         264 :     if ( m_pAggPropMultiplexer )
    1219             :     {
    1220         264 :         m_pAggPropMultiplexer->dispose();
    1221         264 :         m_pAggPropMultiplexer->release();
    1222         264 :         m_pAggPropMultiplexer = NULL;
    1223             :     }
    1224         264 : }
    1225             : 
    1226          15 : void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal )
    1227             : {
    1228          15 :     const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal );
    1229             :     // the value binding can be handled as if somebody called setValueBinding here
    1230             :     // By definition, bindings can be share between bindables
    1231          15 :     if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() )
    1232             :     {
    1233             :         try
    1234             :         {
    1235           0 :             setValueBinding( pBoundOriginal->m_xExternalBinding );
    1236             :         }
    1237             : 
    1238           0 :         catch( const Exception& )
    1239             :         {
    1240             :             DBG_UNHANDLED_EXCEPTION();
    1241             :         }
    1242             : 
    1243             :     }
    1244          15 : }
    1245             : 
    1246         283 : void OBoundControlModel::implInitAggMultiplexer( )
    1247             : {
    1248         283 :     increment( m_refCount );
    1249         283 :     if ( m_xAggregateSet.is() )
    1250             :     {
    1251         283 :         m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, false );
    1252         283 :         m_pAggPropMultiplexer->acquire();
    1253             :     }
    1254             : 
    1255         283 :     decrement( m_refCount );
    1256         283 :     doSetDelegator();
    1257         283 : }
    1258             : 
    1259         274 : void OBoundControlModel::implInitValuePropertyListening( ) const
    1260             : {
    1261             :     // start listening for changes at the value property
    1262             :     // There are three pre-requisites for this to be done:
    1263             :     // 1. We support external value bindings. In this case, the changes in the control value need to
    1264             :     //    be propagated to the external binding immediately when they happen
    1265             :     // 2. We support external validation. In this case, we need to listen for changes in the value
    1266             :     //    property, since we need to revalidate then.
    1267             :     // 3. We are not committable. In this case, changes in the control value need to be propagated
    1268             :     //    to the database column immediately when they happen.
    1269         274 :     if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable )
    1270             :     {
    1271             :         OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
    1272         264 :         if ( m_pAggPropMultiplexer && !m_sValuePropertyName.isEmpty() )
    1273         264 :             m_pAggPropMultiplexer->addProperty( m_sValuePropertyName );
    1274             :     }
    1275         274 : }
    1276             : 
    1277           9 : void OBoundControlModel::initOwnValueProperty( const OUString& i_rValuePropertyName )
    1278             : {
    1279             :     OSL_PRECOND( m_sValuePropertyName.isEmpty() && -1 == m_nValuePropertyAggregateHandle,
    1280             :         "OBoundControlModel::initOwnValueProperty: value property is already initialized!" );
    1281             :     OSL_ENSURE( !i_rValuePropertyName.isEmpty(), "OBoundControlModel::initOwnValueProperty: invalid property name!" );
    1282           9 :     m_sValuePropertyName = i_rValuePropertyName;
    1283           9 : }
    1284             : 
    1285         259 : void OBoundControlModel::initValueProperty( const OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle )
    1286             : {
    1287             :     OSL_PRECOND( m_sValuePropertyName.isEmpty() && -1 == m_nValuePropertyAggregateHandle,
    1288             :         "OBoundControlModel::initValueProperty: value property is already initialized!" );
    1289             :     OSL_ENSURE( !_rValuePropertyName.isEmpty(), "OBoundControlModel::initValueProperty: invalid property name!" );
    1290             :     OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" );
    1291             : 
    1292         259 :     m_sValuePropertyName = _rValuePropertyName;
    1293         259 :     m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle );
    1294             :     OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" );
    1295             : 
    1296         259 :     if ( m_nValuePropertyAggregateHandle != -1 )
    1297             :     {
    1298         259 :         Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW );
    1299         518 :         Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName );
    1300         259 :         m_aValuePropertyType = aValuePropDesc.Type;
    1301         518 :         m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0;
    1302             :     }
    1303             : 
    1304             :     // start listening for changes at the value property
    1305         259 :     implInitValuePropertyListening( );
    1306         259 : }
    1307             : 
    1308          20 : void OBoundControlModel::suspendValueListening( )
    1309             : {
    1310             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "OBoundControlModel::suspendValueListening: don't have a value property!" );
    1311             :     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" );
    1312             : 
    1313          20 : if ( m_pAggPropMultiplexer )
    1314          20 :         m_pAggPropMultiplexer->lock();
    1315          20 : }
    1316             : 
    1317          20 : void OBoundControlModel::resumeValueListening( )
    1318             : {
    1319             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "OBoundControlModel::resumeValueListening: don't have a value property!" );
    1320             :     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" );
    1321             :     OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" );
    1322          20 :     if ( m_pAggPropMultiplexer )
    1323          20 :         m_pAggPropMultiplexer->unlock();
    1324          20 : }
    1325             : 
    1326          64 : Sequence< Type > OBoundControlModel::_getTypes()
    1327             : {
    1328             :     TypeBag aTypes(
    1329             :         OControlModel::_getTypes(),
    1330             :         OBoundControlModel_BASE1::getTypes()
    1331          64 :     );
    1332             : 
    1333          64 :     if ( m_bCommitable )
    1334          44 :         aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() );
    1335             : 
    1336          64 :     if ( m_bSupportsExternalBinding )
    1337          64 :         aTypes.addTypes( OBoundControlModel_BINDING::getTypes() );
    1338             : 
    1339          64 :     if ( m_bSupportsValidation )
    1340          64 :         aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() );
    1341          64 :     return aTypes.getTypes();
    1342             : }
    1343             : 
    1344             : // OComponentHelper
    1345         267 : void OBoundControlModel::disposing()
    1346             : {
    1347         267 :     OControlModel::disposing();
    1348             : 
    1349         267 :     ::osl::ClearableMutexGuard aGuard(m_aMutex);
    1350             : 
    1351         267 :     if ( m_pAggPropMultiplexer )
    1352         267 :         m_pAggPropMultiplexer->dispose();
    1353             : 
    1354             :     // notify all our listeners
    1355         534 :     com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) );
    1356         267 :     m_aUpdateListeners.disposeAndClear( aEvt );
    1357         267 :     m_aResetHelper.disposing();
    1358             : 
    1359             :     // disconnect from our database column
    1360             :     // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify?
    1361             :     // The only more thing which it does is calling onDisconnectedDbColumn - could this
    1362             :     // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*.
    1363         267 :     if ( hasField() )
    1364             :     {
    1365           0 :         getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
    1366           0 :         resetField();
    1367             :     }
    1368             : 
    1369         267 :     m_xCursor = NULL;
    1370         534 :     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
    1371         267 :     if ( xComp.is() )
    1372           0 :         xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
    1373             :     // disconnect from our external value binding
    1374         267 :     if ( hasExternalValueBinding() )
    1375           9 :         disconnectExternalValueBinding();
    1376             :     // dito for the validator
    1377         267 :     if ( hasValidator() )
    1378         285 :         disconnectValidator( );
    1379         267 : }
    1380             : 
    1381         308 : void OBoundControlModel::onValuePropertyChange( ControlModelLock& i_rControLock )
    1382             : {
    1383         308 :     if ( hasExternalValueBinding() )
    1384             :     {
    1385             :         // the control value changed, while we have an external value binding
    1386             :         // -> forward the value to it
    1387           4 :         if ( m_eControlValueChangeInstigator != eExternalBinding )
    1388           0 :             transferControlValueToExternal( i_rControLock );
    1389             :     }
    1390             : 
    1391         304 :     else if ( !m_bCommitable && m_xColumnUpdate.is() )
    1392             :     {
    1393             :         // the control value changed, while we are  bound to a database column,
    1394             :         // but not committable (which means changes in the control have to be reflected to
    1395             :         // the underlying database column immediately)
    1396             :         // -> forward the value to the database column
    1397           0 :         if ( m_eControlValueChangeInstigator != eDbColumnBinding )
    1398           0 :             commitControlValueToDbColumn( false );
    1399             :     }
    1400             : 
    1401             :     // validate the new value
    1402         308 :     if ( m_bSupportsValidation )
    1403         281 :         recheckValidity( true );
    1404         308 : }
    1405             : 
    1406         303 : void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException )
    1407             : {
    1408         303 :     ControlModelLock aLock( *this );
    1409             :     OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
    1410             :         "OBoundControlModel::_propertyChanged: where did this come from (1)?" );
    1411             :     OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(),
    1412             :         "OBoundControlModel::_propertyChanged: where did this come from (2)?" );
    1413         303 :     if ( _rEvt.PropertyName == m_sValuePropertyName )
    1414             :     {
    1415         303 :         onValuePropertyChange( aLock );
    1416         303 :     }
    1417         303 : }
    1418             : 
    1419          62 : void OBoundControlModel::startAggregatePropertyListening( const OUString& _rPropertyName )
    1420             : {
    1421             :     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" );
    1422             :     OSL_ENSURE( !_rPropertyName.isEmpty(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" );
    1423          62 :     if ( m_pAggPropMultiplexer && !_rPropertyName.isEmpty() )
    1424             :     {
    1425          62 :         m_pAggPropMultiplexer->addProperty( _rPropertyName );
    1426             :     }
    1427          62 : }
    1428             : 
    1429         496 : void OBoundControlModel::doFormListening( const bool _bStart )
    1430             : {
    1431             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" );
    1432         496 :     if ( isFormListening() == _bStart )
    1433         496 :         return;
    1434         496 :     if ( m_xAmbientForm.is() )
    1435         353 :         _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this );
    1436         496 :     Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY );
    1437         496 :     if ( getParent().is() && !xParentLoadable.is() )
    1438             :     {
    1439             :         // if our parent does not directly support the XLoadable interface, then it might support the
    1440             :         // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes
    1441             :         // broadcasted by the latter.
    1442          81 :         Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY );
    1443          81 :         if ( xRowSetBroadcaster.is() )
    1444          81 :             _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this );
    1445             :     }
    1446             : 
    1447         496 :     m_bFormListening = _bStart && m_xAmbientForm.is();
    1448             : }
    1449             : 
    1450             : // XChild
    1451         596 : void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException, std::exception)
    1452             : {
    1453         596 :     ControlModelLock aLock( *this );
    1454         925 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    1455         596 :     if ( getParent() == _rxParent )
    1456         863 :         return;
    1457             :     // disconnect from database column (which is controlled by parent, directly or indirectly)
    1458         329 :     if ( hasField() )
    1459           0 :         impl_disconnectDatabaseColumn_noNotify();
    1460             :     // log off old listeners
    1461         329 :     if ( isFormListening() )
    1462         121 :         doFormListening( false );
    1463             :     // actually set the new parent
    1464         329 :     OControlModel::setParent( _rxParent );
    1465             :     // a new parent means a new ambient form
    1466         329 :     impl_determineAmbientForm_nothrow();
    1467         329 :     if ( !hasExternalValueBinding() )
    1468             :     {
    1469             :         // log on new listeners
    1470         321 :         doFormListening( true );
    1471             :         // re-connect to database column of the new parent
    1472         321 :         if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
    1473          31 :             impl_connectDatabaseColumn_noNotify( false );
    1474         329 :     }
    1475             : }
    1476             : 
    1477             : // XEventListener
    1478         195 : void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException, std::exception)
    1479             : {
    1480         195 :     ControlModelLock aLock( *this );
    1481         195 :     if ( _rEvent.Source == getField() )
    1482             :     {
    1483          31 :         resetField();
    1484             :     }
    1485             : 
    1486         164 :     else if ( _rEvent.Source == m_xLabelControl )
    1487             :     {
    1488           0 :         Reference<XPropertySet> xOldValue = m_xLabelControl;
    1489           0 :         m_xLabelControl = NULL;
    1490             :         // fire a propertyChanged (when we leave aLock's scope)
    1491           0 :         aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) );
    1492             :     }
    1493             : 
    1494         164 :     else if ( _rEvent.Source == m_xExternalBinding )
    1495             :     {   // *first* check for the external binding
    1496           0 :         disconnectExternalValueBinding( );
    1497             :     }
    1498             : 
    1499         164 :     else if ( _rEvent.Source == m_xValidator )
    1500             :     {   // *then* check for the validator. Reason is that bindings may also act as validator at the same
    1501             :         // time, in this case, the validator is automatically revoked when the binding is revoked
    1502           0 :         disconnectValidator( );
    1503             :     }
    1504             : 
    1505             :     else
    1506         164 :         OControlModel::disposing(_rEvent);
    1507         195 : }
    1508             : 
    1509             : // XServiceInfo
    1510         240 : StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException, std::exception)
    1511             : {
    1512             :     return ::comphelper::concatSequences(
    1513             :         getAggregateServiceNames(),
    1514             :         getSupportedServiceNames_Static()
    1515         240 :     );
    1516             : }
    1517             : 
    1518         240 : Sequence< OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
    1519             : {
    1520         240 :     Sequence< OUString > aOwnServiceNames( 1 );
    1521         240 :     aOwnServiceNames[ 0 ] = "com.sun.star.form.DataAwareControlModel";
    1522             :     return ::comphelper::concatSequences(
    1523             :         OControlModel::getSupportedServiceNames_Static(),
    1524             :         aOwnServiceNames
    1525         240 :     );
    1526             : }
    1527             : 
    1528             : // XPersist
    1529          15 : void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream ) throw(stario::IOException, RuntimeException, std::exception)
    1530             : {
    1531          15 :     OControlModel::write(_rxOutStream);
    1532          15 :     osl::MutexGuard aGuard(m_aMutex);
    1533             :     // Version
    1534          15 :     _rxOutStream->writeShort(0x0002);
    1535             :     // Controlsource
    1536          15 :     ::comphelper::operator<<( _rxOutStream, m_aControlSource);
    1537             :     // !!! IMPORTANT NOTE !!!
    1538             :     // don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel
    1539             :     // is a base class which is called in derived classes "read" method. So if you increment the version
    1540             :     // and write new stuff, older office versions will read this in the _derived_ classes, which may result
    1541             :     // in anything from data loss to crash.
    1542             :     // (use writeCommonProperties instead, this is called in derived classes write-method)
    1543             :     // !!! EOIN !!!
    1544          15 : }
    1545             : 
    1546           0 : void OBoundControlModel::defaultCommonProperties()
    1547             : {
    1548           0 :     Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
    1549           0 :     if (xComp.is())
    1550           0 :         xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
    1551           0 :     m_xLabelControl = NULL;
    1552           0 : }
    1553             : 
    1554          13 : void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream)
    1555             : {
    1556          13 :     sal_Int32 nLen = _rxInStream->readLong();
    1557          13 :     Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY);
    1558             :     DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
    1559          13 :     sal_Int32 nMark = xMark->createMark();
    1560             :     // read the reference to the label control
    1561          26 :     Reference<stario::XPersistObject> xPersist;
    1562             :     sal_Int32 nUsedFlag;
    1563          13 :     nUsedFlag = _rxInStream->readLong();
    1564          13 :     if (nUsedFlag)
    1565           0 :         xPersist = _rxInStream->readObject();
    1566          13 :     m_xLabelControl = m_xLabelControl.query( xPersist );
    1567          26 :     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
    1568          13 :     if (xComp.is())
    1569           0 :         xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
    1570             :     // read any other new common properties here
    1571             :     // skip the remaining bytes
    1572          13 :     xMark->jumpToMark(nMark);
    1573          13 :     _rxInStream->skipBytes(nLen);
    1574          26 :     xMark->deleteMark(nMark);
    1575          13 : }
    1576             : 
    1577          13 : void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream)
    1578             : {
    1579          13 :     Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
    1580             :     DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !");
    1581          13 :     sal_Int32 nMark = xMark->createMark();
    1582             :     // a placeholder where we will write the overall length (later in this method)
    1583          13 :     sal_Int32 nLen = 0;
    1584          13 :     _rxOutStream->writeLong(nLen);
    1585             :     // write the reference to the label control
    1586          26 :     Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY);
    1587          13 :     sal_Int32 nUsedFlag = 0;
    1588          13 :     if (xPersist.is())
    1589           0 :         nUsedFlag = 1;
    1590          13 :     _rxOutStream->writeLong(nUsedFlag);
    1591          13 :     if (xPersist.is())
    1592           0 :         _rxOutStream->writeObject(xPersist);
    1593             :     // write any other new common properties here
    1594             :     // write the correct length at the beginning of the block
    1595          13 :     nLen = xMark->offsetToMark(nMark) - sizeof(nLen);
    1596          13 :     xMark->jumpToMark(nMark);
    1597          13 :     _rxOutStream->writeLong(nLen);
    1598          13 :     xMark->jumpToFurthest();
    1599          26 :     xMark->deleteMark(nMark);
    1600          13 : }
    1601             : 
    1602          15 : void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream ) throw(stario::IOException, RuntimeException, std::exception)
    1603             : {
    1604          15 :     OControlModel::read(_rxInStream);
    1605          15 :     osl::MutexGuard aGuard(m_aMutex);
    1606          15 :     sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion;
    1607          15 :     ::comphelper::operator>>( _rxInStream, m_aControlSource);
    1608          15 : }
    1609             : 
    1610       53471 : void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
    1611             : {
    1612       53471 :     switch (nHandle)
    1613             :     {
    1614             :         case PROPERTY_ID_INPUT_REQUIRED:
    1615         955 :             rValue <<= m_bInputRequired;
    1616         955 :             break;
    1617             :         case PROPERTY_ID_CONTROLSOURCEPROPERTY:
    1618        1858 :             rValue <<= m_sValuePropertyName;
    1619        1858 :             break;
    1620             :         case PROPERTY_ID_CONTROLSOURCE:
    1621        1128 :             rValue <<= m_aControlSource;
    1622        1128 :             break;
    1623             :         case PROPERTY_ID_BOUNDFIELD:
    1624         398 :             rValue <<= getField();
    1625         398 :             break;
    1626             :         case PROPERTY_ID_CONTROLLABEL:
    1627         321 :             if (!m_xLabelControl.is())
    1628         321 :                 rValue.clear();
    1629             :             else
    1630           0 :                 rValue <<= m_xLabelControl;
    1631         321 :             break;
    1632             :         default:
    1633       48811 :             OControlModel::getFastPropertyValue(rValue, nHandle);
    1634             :     }
    1635       53471 : }
    1636             : 
    1637        5379 : sal_Bool OBoundControlModel::convertFastPropertyValue(
    1638             :                                 Any& _rConvertedValue, Any& _rOldValue,
    1639             :                 sal_Int32 _nHandle,
    1640             :                                 const Any& _rValue)
    1641             :                 throw (com::sun::star::lang::IllegalArgumentException)
    1642             : {
    1643        5379 :     sal_Bool bModified(sal_False);
    1644        5379 :     switch (_nHandle)
    1645             :     {
    1646             :         case PROPERTY_ID_INPUT_REQUIRED:
    1647         568 :             bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired );
    1648         568 :             break;
    1649             :         case PROPERTY_ID_CONTROLSOURCE:
    1650         660 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource);
    1651         660 :             break;
    1652             :         case PROPERTY_ID_BOUNDFIELD:
    1653             :             SAL_WARN("forms.component",  "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" );
    1654           0 :             throw com::sun::star::lang::IllegalArgumentException();
    1655             :         case PROPERTY_ID_CONTROLLABEL:
    1656           0 :             if (!_rValue.hasValue())
    1657             :             {   // property set to void
    1658           0 :                 _rConvertedValue = Any();
    1659           0 :                 getFastPropertyValue(_rOldValue, _nHandle);
    1660           0 :                 bModified = m_xLabelControl.is();
    1661             :             }
    1662             : 
    1663             :             else
    1664             :             {
    1665           0 :                 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl);
    1666           0 :                 if (!m_xLabelControl.is())
    1667             :                     // an empty interface is interpreted as VOID
    1668           0 :                     _rOldValue.clear();
    1669             :             }
    1670             : 
    1671           0 :             break;
    1672             :         default:
    1673        4151 :             bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
    1674             :     }
    1675        5379 :     return bModified;
    1676             : }
    1677             : 
    1678           2 : Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
    1679             : {
    1680           2 :     Any aDefault;
    1681           2 :     switch ( _nHandle )
    1682             :     {
    1683             :         case PROPERTY_ID_INPUT_REQUIRED:
    1684           0 :             aDefault <<= sal_Bool( sal_True );
    1685           0 :             break;
    1686             :         case PROPERTY_ID_CONTROLSOURCE:
    1687           0 :             aDefault <<= OUString();
    1688           0 :             break;
    1689             :         case PROPERTY_ID_CONTROLLABEL:
    1690           0 :             aDefault <<= Reference< XPropertySet >();
    1691           0 :             break;
    1692             :     }
    1693           2 :     return aDefault;
    1694             : }
    1695             : 
    1696        1332 : void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception, std::exception)
    1697             : {
    1698        1332 :     switch (nHandle)
    1699             :     {
    1700             :         case PROPERTY_ID_INPUT_REQUIRED:
    1701          98 :             OSL_VERIFY( rValue >>= m_bInputRequired );
    1702          98 :             break;
    1703             :         case PROPERTY_ID_CONTROLSOURCE:
    1704         189 :             OSL_VERIFY( rValue >>= m_aControlSource );
    1705         189 :             break;
    1706             :         case PROPERTY_ID_BOUNDFIELD:
    1707             :             SAL_WARN("forms.component", "OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !");
    1708           0 :             throw com::sun::star::lang::IllegalArgumentException();
    1709             :         case PROPERTY_ID_CONTROLLABEL:
    1710             :         {
    1711           0 :             if ( rValue.hasValue() && ( rValue.getValueTypeClass() != TypeClass_INTERFACE ) )
    1712           0 :                 throw com::sun::star::lang::IllegalArgumentException();
    1713           0 :             Reference< XInterface > xNewValue( rValue, UNO_QUERY );
    1714           0 :             if ( !xNewValue.is() )
    1715             :             {   // set property to "void"
    1716           0 :                 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
    1717           0 :                 if ( xComp.is() )
    1718           0 :                     xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
    1719           0 :                 m_xLabelControl = NULL;
    1720           0 :                 break;
    1721             :             }
    1722             : 
    1723           0 :             Reference< XControlModel >  xAsModel        ( xNewValue,        UNO_QUERY );
    1724           0 :             Reference< XServiceInfo >   xAsServiceInfo  ( xAsModel,         UNO_QUERY );
    1725           0 :             Reference< XPropertySet >   xAsPropSet      ( xAsServiceInfo,   UNO_QUERY );
    1726           0 :             Reference< XChild >         xAsChild        ( xAsPropSet,       UNO_QUERY );
    1727           0 :             if ( !xAsChild.is() || !xAsServiceInfo->supportsService( m_aLabelServiceName ) )
    1728             :             {
    1729           0 :                 throw com::sun::star::lang::IllegalArgumentException();
    1730             :             }
    1731             : 
    1732             :             // check if weself and the given model have a common anchestor (up to the forms collection)
    1733           0 :             Reference<XChild> xCont;
    1734           0 :             query_interface(static_cast<XWeak*>(this), xCont);
    1735           0 :             Reference< XInterface > xMyTopLevel = xCont->getParent();
    1736           0 :             while (xMyTopLevel.is())
    1737             :             {
    1738           0 :                 Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY);
    1739           0 :                 if (!xAsForm.is())
    1740             :                     // found my root
    1741           0 :                     break;
    1742           0 :                 Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY);
    1743           0 :                 xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
    1744           0 :             }
    1745             : 
    1746           0 :             Reference< XInterface > xNewTopLevel = xAsChild->getParent();
    1747           0 :             while (xNewTopLevel.is())
    1748             :             {
    1749           0 :                 Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY);
    1750           0 :                 if (!xAsForm.is())
    1751           0 :                     break;
    1752           0 :                 Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY);
    1753           0 :                 xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
    1754           0 :             }
    1755             : 
    1756           0 :             if (xNewTopLevel != xMyTopLevel)
    1757             :             {
    1758             :                 // the both objects don't belong to the same forms collection -> not acceptable
    1759           0 :                 throw com::sun::star::lang::IllegalArgumentException();
    1760             :             }
    1761             : 
    1762           0 :             m_xLabelControl = xAsPropSet;
    1763           0 :             Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
    1764           0 :             if (xComp.is())
    1765           0 :                 xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
    1766             :         }
    1767             : 
    1768           0 :         break;
    1769             :         default:
    1770        1045 :             OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue );
    1771             :     }
    1772        1332 : }
    1773             : 
    1774             : // XPropertyChangeListener
    1775          22 : void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException, std::exception)
    1776             : {
    1777             :     // if the DBColumn value changed, transfer it to the control
    1778          22 :     if ( evt.PropertyName.equals( PROPERTY_VALUE ) )
    1779             :     {
    1780             :         OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database column?" );
    1781          22 :         osl::MutexGuard aGuard(m_aMutex);
    1782          22 :         if ( m_bForwardValueChanges && m_xColumn.is() )
    1783          22 :             transferDbValueToControl();
    1784             :     }
    1785             : 
    1786             :     else
    1787             :     {
    1788             :         OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" );
    1789             :         // our binding has properties which can control properties of ourself
    1790           0 :         OUString sBindingControlledProperty;
    1791           0 :         bool bForwardToLabelControl = false;
    1792           0 :         if ( evt.PropertyName.equals( PROPERTY_READONLY ) )
    1793             :         {
    1794           0 :             sBindingControlledProperty = PROPERTY_READONLY;
    1795             :         }
    1796             : 
    1797           0 :         else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) )
    1798             :         {
    1799           0 :             sBindingControlledProperty = PROPERTY_ENABLED;
    1800           0 :             bForwardToLabelControl = true;
    1801             :         }
    1802             : 
    1803             :         else
    1804          22 :             return;
    1805             :         try
    1806             :         {
    1807           0 :             setPropertyValue( sBindingControlledProperty, evt.NewValue );
    1808           0 :             if ( bForwardToLabelControl && m_xLabelControl.is() )
    1809           0 :                 m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue );
    1810             :         }
    1811             : 
    1812           0 :         catch( const Exception& )
    1813             :         {
    1814             :             SAL_WARN("forms.component",  "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!");
    1815             :             DBG_UNHANDLED_EXCEPTION();
    1816           0 :         }
    1817             : 
    1818             :     }
    1819             : }
    1820             : 
    1821          10 : void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException, std::exception)
    1822             : {
    1823          10 :     ControlModelLock aLock( *this );
    1824          20 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    1825             :     // disconnect from database column (which is controlled by parent, directly or indirectly)
    1826          10 :     if ( hasField() )
    1827           0 :         impl_disconnectDatabaseColumn_noNotify();
    1828             :     // log off old listeners
    1829          10 :     if ( isFormListening() )
    1830          10 :         doFormListening( false );
    1831             :     // determine the new ambient form
    1832          10 :     impl_determineAmbientForm_nothrow();
    1833             :     // log on new listeners
    1834          10 :     doFormListening( true );
    1835             :     // re-connect to database column if needed and possible
    1836          10 :     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
    1837          10 :         impl_connectDatabaseColumn_noNotify( false );
    1838          10 : }
    1839             : 
    1840             : // XBoundComponent
    1841           0 : void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException, std::exception)
    1842             : {
    1843           0 :     m_aUpdateListeners.addInterface(_rxListener);
    1844           0 : }
    1845             : 
    1846           0 : void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException, std::exception)
    1847             : {
    1848           0 :     m_aUpdateListeners.removeInterface(_rxListener);
    1849           0 : }
    1850             : 
    1851           8 : sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException, std::exception)
    1852             : {
    1853           8 :     ControlModelLock aLock( *this );
    1854             :     OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " );
    1855           8 :     if ( hasExternalValueBinding() )
    1856             :     {
    1857             :         // in most cases, no action is required: For most derivees, we know the value property of
    1858             :         // our control (see initValueProperty), and when an external binding is active, we
    1859             :         // instantly forward all changes in this property to the external binding.
    1860           0 :         if ( m_sValuePropertyName.isEmpty() )
    1861             :             // but for those derivees which did not use this feature, we need an
    1862             :             // explicit transfer
    1863           0 :             transferControlValueToExternal( aLock );
    1864           0 :         return sal_True;
    1865             :     }
    1866             : 
    1867             :     OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" );
    1868             :         // we reach this only if we're not working with an external binding
    1869           8 :     if ( !hasField() )
    1870           8 :         return sal_True;
    1871           0 :     ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners );
    1872           0 :     EventObject aEvent;
    1873           0 :     aEvent.Source = static_cast< XWeak* >( this );
    1874           0 :     sal_Bool bSuccess = sal_True;
    1875           0 :     aLock.release();
    1876             :     // UNSAFE >
    1877           0 :     while (aIter.hasMoreElements() && bSuccess)
    1878           0 :         bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent );
    1879             :     // < UNSAFE
    1880           0 :     aLock.acquire();
    1881           0 :     if ( bSuccess )
    1882             :     {
    1883             :         try
    1884             :         {
    1885           0 :             if ( m_xColumnUpdate.is() )
    1886           0 :                 bSuccess = commitControlValueToDbColumn( false );
    1887             :         }
    1888             : 
    1889           0 :         catch(const Exception&)
    1890             :         {
    1891           0 :             bSuccess = sal_False;
    1892             :         }
    1893             : 
    1894             :     }
    1895             : 
    1896           0 :     if ( bSuccess )
    1897             :     {
    1898           0 :         aLock.release();
    1899           0 :         m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent );
    1900             :     }
    1901           8 :     return bSuccess;
    1902             : }
    1903             : 
    1904          31 : void OBoundControlModel::resetField()
    1905             : {
    1906          31 :     m_xColumnUpdate.clear();
    1907          31 :     m_xColumn.clear();
    1908          31 :     m_xField.clear();
    1909          31 :     m_nFieldType = DataType::OTHER;
    1910          31 : }
    1911             : 
    1912          31 : sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm)
    1913             : {
    1914             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" );
    1915             :     // if there's a connection to the database
    1916          31 :     if (rForm.is() && getConnection(rForm).is())
    1917             :     {
    1918             :         // determine field and PropertyChangeListener
    1919          31 :         m_xCursor = rForm;
    1920          31 :         Reference<XPropertySet> xFieldCandidate;
    1921          31 :         if (m_xCursor.is())
    1922             :         {
    1923          31 :             Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY);
    1924             :             DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !");
    1925          31 :             if (xColumnsSupplier.is())
    1926             :             {
    1927          31 :                 Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY);
    1928          31 :                 if (xColumns.is() && xColumns->hasByName(m_aControlSource))
    1929             :                 {
    1930          31 :                     OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate );
    1931          31 :                 }
    1932             : 
    1933          31 :             }
    1934             : 
    1935             :         }
    1936             : 
    1937             :         try
    1938             :         {
    1939          31 :             sal_Int32 nFieldType = DataType::OTHER;
    1940          31 :             if ( xFieldCandidate.is() )
    1941             :             {
    1942          31 :                 xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
    1943          31 :                 if ( approveDbColumnType( nFieldType ) )
    1944          31 :                     impl_setField_noNotify( xFieldCandidate );
    1945             :             }
    1946             : 
    1947             :             else
    1948           0 :                 impl_setField_noNotify( NULL );
    1949          31 :             if ( m_xField.is() )
    1950             :             {
    1951          31 :                 if ( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) )
    1952             :                 {
    1953          31 :                     m_nFieldType = nFieldType;
    1954             :                     // listen to changing values
    1955          31 :                     m_xField->addPropertyChangeListener( PROPERTY_VALUE, this );
    1956          31 :                     m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY );
    1957          31 :                     m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY );
    1958          31 :                     sal_Int32 nNullableFlag = ColumnValue::NO_NULLS;
    1959          31 :                     m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag;
    1960          31 :                     m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag);
    1961             :                         // we're optimistic: in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability...
    1962             :                 }
    1963             : 
    1964             :                 else
    1965             :                 {
    1966             :                     SAL_WARN("forms.component", "OBoundControlModel::connectToField: property " << PROPERTY_VALUE << " not supported!");
    1967           0 :                     impl_setField_noNotify( NULL );
    1968             :                 }
    1969             : 
    1970             :             }
    1971             : 
    1972             :         }
    1973             : 
    1974           0 :         catch( const Exception& )
    1975             :         {
    1976             :             DBG_UNHANDLED_EXCEPTION();
    1977           0 :             resetField();
    1978          31 :         }
    1979             : 
    1980             :     }
    1981          31 :     return hasField();
    1982             : }
    1983             : 
    1984          31 : void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet )
    1985             : {
    1986             :     // but only if the rowset if posisitioned on a valid record
    1987          31 :     if ( hasField() && _rxRowSet.is() )
    1988             :     {
    1989          31 :         if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() )
    1990          31 :             transferDbValueToControl();
    1991             :         else
    1992             :             // reset the field if the row set is empty
    1993             :             // #i30661#
    1994           0 :             resetNoBroadcast();
    1995             :     }
    1996          31 : }
    1997             : 
    1998          31 : sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType)
    1999             : {
    2000             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" );
    2001          31 :     if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY)
    2002          31 :         || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER)
    2003          31 :         || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT)
    2004          31 :         || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY)
    2005          31 :         || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/
    2006          31 :         || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL))
    2007           0 :         return sal_False;
    2008          31 :     return sal_True;
    2009             : }
    2010             : 
    2011         339 : void OBoundControlModel::impl_determineAmbientForm_nothrow()
    2012             : {
    2013         339 :     Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() );
    2014         339 :     m_xAmbientForm.set( xParent, UNO_QUERY );
    2015         339 :     if ( !m_xAmbientForm.is() )
    2016             :     {
    2017         194 :         Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY );
    2018         194 :         if ( xSupRowSet.is() )
    2019          63 :             m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY );
    2020         339 :     }
    2021         339 : }
    2022             : 
    2023          31 : void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload )
    2024             : {
    2025             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" );
    2026             :     // consistency checks
    2027             :     DBG_ASSERT( !( hasField() && !_bFromReload ),
    2028             :         "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" );
    2029             :     (void)_bFromReload;
    2030          31 :     Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY );
    2031             :     OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" );
    2032          31 :     if ( !xRowSet.is() )
    2033          31 :         return;
    2034          31 :     if ( !hasField() )
    2035             :     {
    2036             :         // connect to the column
    2037          31 :         connectToField( xRowSet );
    2038             :     }
    2039             : 
    2040             :     // now that we're connected (more or less, even if we did not find a column),
    2041             :     // we definitely want to forward any potentially occuring value changes
    2042          31 :     m_bForwardValueChanges = sal_True;
    2043             :     // let derived classes react on this new connection
    2044          31 :     m_bLoaded = sal_True;
    2045          31 :     onConnectedDbColumn( xRowSet );
    2046             :     // initially transfer the db column value to the control, if we successfully connected to a database column
    2047          31 :     if ( hasField() )
    2048          31 :         initFromField( xRowSet );
    2049             : }
    2050             : 
    2051          31 : void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify()
    2052             : {
    2053             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" );
    2054             :     // let derived classes react on this
    2055          31 :     onDisconnectedDbColumn();
    2056          31 :     if ( hasField() )
    2057             :     {
    2058           0 :         getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
    2059           0 :         resetField();
    2060             :     }
    2061             : 
    2062          31 :     m_xCursor = NULL;
    2063          31 :     m_bLoaded = sal_False;
    2064          31 : }
    2065             : 
    2066             : // XLoadListener
    2067           0 : void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException, std::exception)
    2068             : {
    2069           0 :     ControlModelLock aLock( *this );
    2070           0 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2071             :     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" );
    2072             :     (void)_rEvent;
    2073             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" );
    2074           0 :     if ( hasExternalValueBinding() )
    2075           0 :         return;
    2076           0 :     impl_connectDatabaseColumn_noNotify( false );
    2077             : }
    2078             : 
    2079          31 : void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException, std::exception)
    2080             : {
    2081             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" );
    2082          31 : }
    2083             : 
    2084           0 : void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException, std::exception)
    2085             : {
    2086             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" );
    2087           0 :     if ( hasExternalValueBinding() )
    2088           0 :         return;
    2089           0 :     osl::MutexGuard aGuard(m_aMutex);
    2090           0 :     m_bForwardValueChanges = sal_False;
    2091             : }
    2092             : 
    2093          31 : void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException, std::exception)
    2094             : {
    2095          31 :     ControlModelLock aLock( *this );
    2096          62 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2097             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" );
    2098          31 :     if ( hasExternalValueBinding() )
    2099          31 :         return;
    2100          62 :     impl_disconnectDatabaseColumn_noNotify();
    2101             : }
    2102             : 
    2103           0 : void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException, std::exception)
    2104             : {
    2105           0 :     ControlModelLock aLock( *this );
    2106           0 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2107             :     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" );
    2108             :     (void)_rEvent;
    2109             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" );
    2110           0 :     if ( hasExternalValueBinding() )
    2111           0 :         return;
    2112           0 :     impl_connectDatabaseColumn_noNotify( true );
    2113             : }
    2114             : 
    2115         241 : void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator )
    2116             : {
    2117         241 :     m_eControlValueChangeInstigator = _eInstigator;
    2118         241 :     doSetControlValue( _rValue );
    2119         241 :     m_eControlValueChangeInstigator = eOther;
    2120         241 : }
    2121             : 
    2122         235 : void OBoundControlModel::doSetControlValue( const Any& _rValue )
    2123             : {
    2124             :     OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
    2125             :         "OBoundControlModel::doSetControlValue: invalid aggregate !" );
    2126             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty() || ( m_nValuePropertyAggregateHandle != -1 ),
    2127             :         "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" );
    2128             :     try
    2129             :     {
    2130             :         // release our mutex once (it's acquired in one of the calling methods), as setting aggregate properties
    2131             :         // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with
    2132             :         // our own mutex locked
    2133         235 :         MutexRelease aRelease( m_aMutex );
    2134         235 :         if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
    2135             :         {
    2136         235 :             m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue );
    2137             :         }
    2138             : 
    2139           0 :         else if ( !m_sValuePropertyName.isEmpty() && m_xAggregateSet.is() )
    2140             :         {
    2141           0 :             m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue );
    2142         235 :         }
    2143             : 
    2144             :     }
    2145             : 
    2146           6 :     catch( const Exception& )
    2147             :     {
    2148             :         SAL_WARN("forms.component",  "OBoundControlModel::doSetControlValue: caught an exception!");
    2149             :         DBG_UNHANDLED_EXCEPTION();
    2150             :     }
    2151         235 : }
    2152             : 
    2153          18 : void OBoundControlModel::onConnectedValidator( )
    2154             : {
    2155             :     try
    2156             :     {
    2157             :         // if we have an external validator, we do not want the control to force invalid
    2158             :         // inputs to the default value. Instead, invalid inputs should be translated
    2159             :         // to NaN (not a number)
    2160          18 :         Reference< XPropertySetInfo > xAggregatePropertyInfo;
    2161          18 :         if ( m_xAggregateSet.is() )
    2162          18 :             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
    2163          18 :         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
    2164           8 :             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) );
    2165             :     }
    2166             : 
    2167           0 :     catch( const Exception& )
    2168             :     {
    2169             :         SAL_WARN("forms.component",  "OBoundControlModel::onConnectedValidator: caught an exception!");
    2170             :         DBG_UNHANDLED_EXCEPTION();
    2171             :     }
    2172             : 
    2173          18 :     recheckValidity( false );
    2174          18 : }
    2175             : 
    2176          18 : void OBoundControlModel::onDisconnectedValidator( )
    2177             : {
    2178             :     try
    2179             :     {
    2180          18 :         Reference< XPropertySetInfo > xAggregatePropertyInfo;
    2181          18 :         if ( m_xAggregateSet.is() )
    2182          18 :             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
    2183          18 :         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
    2184           8 :             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) );
    2185             :     }
    2186             : 
    2187           0 :     catch( const Exception& )
    2188             :     {
    2189             :         SAL_WARN("forms.component",  "OBoundControlModel::onDisconnectedValidator: caught an exception!");
    2190             :         DBG_UNHANDLED_EXCEPTION();
    2191             :     }
    2192             : 
    2193          18 :     recheckValidity( false );
    2194          18 : }
    2195             : 
    2196          17 : void OBoundControlModel::onConnectedExternalValue( )
    2197             : {
    2198          17 :     calculateExternalValueType();
    2199          17 : }
    2200             : 
    2201          17 : void OBoundControlModel::onDisconnectedExternalValue( )
    2202             : {
    2203          17 : }
    2204             : 
    2205          14 : void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
    2206             : {
    2207             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" );
    2208          14 : }
    2209             : 
    2210          31 : void OBoundControlModel::onDisconnectedDbColumn()
    2211             : {
    2212             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" );
    2213          31 : }
    2214             : 
    2215             : // XReset
    2216           0 : Any OBoundControlModel::getDefaultForReset() const
    2217             : {
    2218           0 :     return Any();
    2219             : }
    2220             : 
    2221         133 : void OBoundControlModel::resetNoBroadcast()
    2222             : {
    2223         133 :     setControlValue( getDefaultForReset(), eOther );
    2224         133 : }
    2225             : 
    2226          35 : void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException, std::exception)
    2227             : {
    2228          35 :     m_aResetHelper.addResetListener( l );
    2229          35 : }
    2230             : 
    2231          22 : void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException, std::exception)
    2232             : {
    2233          22 :     m_aResetHelper.removeResetListener( l );
    2234          22 : }
    2235             : 
    2236          43 : void OBoundControlModel::reset() throw (RuntimeException, std::exception)
    2237             : {
    2238          43 :     if ( !m_aResetHelper.approveReset() )
    2239          56 :        return;
    2240          30 :     ControlModelLock aLock( *this );
    2241             :     // on a new record?
    2242          30 :     sal_Bool bIsNewRecord = sal_False;
    2243          60 :     Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY );
    2244          30 :     if ( xSet.is() )
    2245             :     {
    2246             :         try
    2247             :         {
    2248           0 :             xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord;
    2249             :         }
    2250             : 
    2251           0 :         catch( const Exception& )
    2252             :         {
    2253             :             DBG_UNHANDLED_EXCEPTION();
    2254             :         }
    2255             : 
    2256             :     }
    2257             : 
    2258             :     // cursor on an invalid row?
    2259          30 :     sal_Bool bInvalidCursorPosition = sal_True;
    2260             :     try
    2261             :     {
    2262          30 :         bInvalidCursorPosition =    m_xCursor.is()
    2263           0 :                                 &&  (  m_xCursor->isAfterLast()
    2264           0 :                                     || m_xCursor->isBeforeFirst()
    2265             :                                     )
    2266          30 :                                 &&  !bIsNewRecord;
    2267             :     }
    2268             : 
    2269           0 :     catch( const SQLException& )
    2270             :     {
    2271             :         SAL_WARN("forms.component",  "OBoundControlModel::reset: caught an SQL exception!" );
    2272             :         DBG_UNHANDLED_EXCEPTION();
    2273             :     }
    2274             : 
    2275             :     // #i24495# - don't count the insert row as "invalid"
    2276             :     sal_Bool bSimpleReset =
    2277          30 :                         (   !m_xColumn.is()                     // no connection to a database column
    2278           0 :                         ||  (   m_xCursor.is()                  // OR   we have an improperly positioned cursor
    2279           0 :                             &&  bInvalidCursorPosition
    2280             :                             )
    2281          30 :                         ||  hasExternalValueBinding()           // OR we have an external value binding
    2282          30 :                         );
    2283          30 :     if ( !bSimpleReset )
    2284             :     {
    2285             :         // The default values will be set if and only if the current value of the field which we're bound
    2286             :         // to is NULL.
    2287             :         // Else, the current field value should be refreshed
    2288             :         // This behaviour is not completely ... "matured": What should happen if the field as well as the
    2289             :         // control have a default value?
    2290           0 :         sal_Bool bIsNull = sal_True;
    2291             :         // we have to access the field content at least once to get a reliable result by XColumn::wasNull
    2292             :         try
    2293             :         {
    2294             :             // normally, we'd do a getString here. However, this is extremely expensive in the case
    2295             :             // of binary fields. Unfortunately, getString is the only method which is guaranteed
    2296             :             // to *always* succeed, all other getXXX methods may fail if the column is asked for a
    2297             :             // non-convertible type
    2298           0 :             sal_Int32 nFieldType = DataType::OBJECT;
    2299           0 :             getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
    2300           0 :             if  (  ( nFieldType == DataType::BINARY        )
    2301           0 :                 || ( nFieldType == DataType::VARBINARY     )
    2302           0 :                 || ( nFieldType == DataType::LONGVARBINARY )
    2303           0 :                 || ( nFieldType == DataType::OBJECT        )
    2304             :                 /*|| ( nFieldType == DataType::CLOB          )*/
    2305             :                 )
    2306           0 :                 m_xColumn->getBinaryStream();
    2307           0 :             else if ( nFieldType == DataType::BLOB          )
    2308           0 :                 m_xColumn->getBlob();
    2309             :             else
    2310           0 :                 m_xColumn->getString();
    2311           0 :             bIsNull = m_xColumn->wasNull();
    2312             :         }
    2313             : 
    2314           0 :         catch(const Exception&)
    2315             :         {
    2316             :             SAL_WARN("forms.component", "OBoundControlModel::reset: this should have succeeded in all cases!");
    2317             :             DBG_UNHANDLED_EXCEPTION();
    2318             :         }
    2319             : 
    2320           0 :         sal_Bool bNeedValueTransfer = sal_True;
    2321           0 :         if ( bIsNull )
    2322             :         {
    2323           0 :             if ( bIsNewRecord )
    2324             :             {
    2325             :                 // reset the control to it's default
    2326           0 :                 resetNoBroadcast();
    2327             :                 // and immediately commit the changes to the DB column, to keep consistency
    2328           0 :                 commitControlValueToDbColumn( true );
    2329           0 :                 bNeedValueTransfer = sal_False;
    2330             :             }
    2331             : 
    2332             :         }
    2333             : 
    2334           0 :         if ( bNeedValueTransfer )
    2335           0 :             transferDbValueToControl();
    2336             :     }
    2337             : 
    2338             :     else
    2339             :     {
    2340          30 :         resetNoBroadcast();
    2341             :         // transfer to the external binding, if necessary
    2342          30 :         if ( hasExternalValueBinding() )
    2343           0 :             transferControlValueToExternal( aLock );
    2344             :     }
    2345             : 
    2346             :     // revalidate, if necessary
    2347          30 :     if ( hasValidator() )
    2348          18 :         recheckValidity( true );
    2349          30 :     aLock.release();
    2350          60 :     m_aResetHelper.notifyResetted();
    2351             : }
    2352             : 
    2353          31 : void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField )
    2354             : {
    2355             :     DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" );
    2356          31 :     m_xField = _rxField;
    2357          31 : }
    2358             : 
    2359          17 : sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding )
    2360             : {
    2361          17 :     if ( !_rxBinding.is() )
    2362           0 :         return sal_False;
    2363          17 :     Sequence< Type > aTypeCandidates;
    2364             :     {
    2365             :         // SYNCHRONIZED >
    2366          17 :         ::osl::MutexGuard aGuard( m_aMutex );
    2367          17 :         aTypeCandidates = getSupportedBindingTypes();
    2368             :         // < SYNCHRONIZED
    2369             :     }
    2370             : 
    2371          34 :     for (   const Type* pType = aTypeCandidates.getConstArray();
    2372          17 :             pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
    2373             :             ++pType
    2374             :         )
    2375             :     {
    2376          17 :         if ( _rxBinding->supportsType( *pType ) )
    2377          17 :             return sal_True;
    2378             :     }
    2379           0 :     return sal_False;
    2380             : }
    2381             : 
    2382          17 : void OBoundControlModel::connectExternalValueBinding(
    2383             :         const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock )
    2384             : {
    2385             :     OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" );
    2386             :     OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" );
    2387             :     // if we're connected to a database column, suspend this
    2388          17 :     if ( hasField() )
    2389           0 :         impl_disconnectDatabaseColumn_noNotify();
    2390             :     // suspend listening for load-related events at out ambient form.
    2391             :     // This is because an external value binding overrules a possible database binding.
    2392          17 :     if ( isFormListening() )
    2393          17 :         doFormListening( false );
    2394             :     // remember this new binding
    2395          17 :     m_xExternalBinding = _rxBinding;
    2396             :     // tell the derivee
    2397          17 :     onConnectedExternalValue();
    2398             :     try
    2399             :     {
    2400             :         // add as value listener so we get notified when the value changes
    2401          17 :         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
    2402          17 :         if ( xModifiable.is() )
    2403           1 :             xModifiable->addModifyListener( this );
    2404             :         // add as property change listener for some (possibly present) properties we're
    2405             :         // interested in
    2406          34 :         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
    2407          34 :         Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() );
    2408          17 :         if ( xBindingPropsInfo.is() )
    2409             :         {
    2410           1 :             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) )
    2411             :             {
    2412           0 :                 xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this );
    2413           0 :                 m_bBindingControlsRO = sal_True;
    2414             :             }
    2415             : 
    2416           1 :             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) )
    2417             :             {
    2418           0 :                 xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this );
    2419           0 :                 m_bBindingControlsEnable = sal_True;
    2420             :             }
    2421             : 
    2422          17 :         }
    2423             : 
    2424             :     }
    2425             : 
    2426           0 :     catch( const Exception& )
    2427             :     {
    2428             :         DBG_UNHANDLED_EXCEPTION();
    2429             :     }
    2430             : 
    2431             :     // propagate our new value
    2432          17 :     transferExternalValueToControl( _rInstanceLock );
    2433             :     // if the binding is also a validator, use it, too. This is a constraint of the
    2434             :     // com.sun.star.form.binding.ValidatableBindableFormComponent service
    2435          17 :     if ( m_bSupportsValidation )
    2436             :     {
    2437             :         try
    2438             :         {
    2439          17 :             Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
    2440          17 :             if ( xAsValidator.is() )
    2441           0 :                 setValidator( xAsValidator );
    2442             :         }
    2443             : 
    2444           0 :         catch( const Exception& )
    2445             :         {
    2446             :             DBG_UNHANDLED_EXCEPTION();
    2447             :         }
    2448             : 
    2449             :     }
    2450          17 : }
    2451             : 
    2452          17 : void OBoundControlModel::disconnectExternalValueBinding( )
    2453             : {
    2454             :     try
    2455             :     {
    2456             :         // not listening at the binding anymore
    2457          17 :         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
    2458          17 :         if ( xModifiable.is() )
    2459           1 :             xModifiable->removeModifyListener( this );
    2460             :         // remove as property change listener
    2461          34 :         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
    2462          17 :         if ( m_bBindingControlsRO )
    2463           0 :             xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this );
    2464          17 :         if ( m_bBindingControlsEnable )
    2465          17 :             xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this );
    2466             :     }
    2467             : 
    2468           0 :     catch( const Exception& )
    2469             :     {
    2470             :         SAL_WARN("forms.component",  "OBoundControlModel::disconnectExternalValueBinding: caught an exception!");
    2471             :         DBG_UNHANDLED_EXCEPTION();
    2472             :     }
    2473             : 
    2474             :     // if the binding also acts as our validator, disconnect the validator, too
    2475          17 :     if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
    2476           0 :         disconnectValidator( );
    2477             :     // no binding anymore
    2478          17 :     m_xExternalBinding.clear();
    2479             :     // be a load listener at our form, again. This was suspended while we had
    2480             :     // an external value binding in place.
    2481          17 :     doFormListening( true );
    2482             :     // re-connect to database column of the new parent
    2483          17 :     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
    2484           0 :         impl_connectDatabaseColumn_noNotify( false );
    2485             :     // tell the derivee
    2486          17 :     onDisconnectedExternalValue();
    2487          17 : }
    2488             : 
    2489          17 : void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException, std::exception)
    2490             : {
    2491             :     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" );
    2492             :         // the interface for this method should not have been exposed if we do not
    2493             :         // support binding to external data
    2494             :     // allow reset
    2495          17 :     if ( _rxBinding.is() && !impl_approveValueBinding_nolock( _rxBinding ) )
    2496             :     {
    2497             :         throw IncompatibleTypesException(
    2498             :             FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ),
    2499             :             *this
    2500           0 :         );
    2501             :     }
    2502             : 
    2503          17 :     ControlModelLock aLock( *this );
    2504             :     // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding
    2505             :     // might trigger a change in our BoundField.
    2506          34 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2507             :     // disconnect from the old binding
    2508          17 :     if ( hasExternalValueBinding() )
    2509           8 :         disconnectExternalValueBinding( );
    2510             :     // connect to the new binding
    2511          17 :     if ( _rxBinding.is() )
    2512          34 :         connectExternalValueBinding( _rxBinding, aLock );
    2513          17 : }
    2514             : 
    2515         158 : Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding(  ) throw (RuntimeException, std::exception)
    2516             : {
    2517         158 :     ::osl::MutexGuard aGuard( m_aMutex );
    2518             :     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" );
    2519             :         // the interface for this method should not have been exposed if we do not
    2520             :         // support binding to external data
    2521         158 :     return m_xExternalBinding;
    2522             : }
    2523             : 
    2524           0 : void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException, std::exception )
    2525             : {
    2526           0 :     ControlModelLock aLock( *this );
    2527             :     OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" );
    2528           0 :     if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() )
    2529             :     {
    2530           0 :         transferExternalValueToControl( aLock );
    2531           0 :     }
    2532           0 : }
    2533             : 
    2534          53 : void OBoundControlModel::transferDbValueToControl( )
    2535             : {
    2536             :     try
    2537             :     {
    2538          53 :         setControlValue( translateDbColumnToControlValue(), eDbColumnBinding );
    2539             :     }
    2540             : 
    2541           0 :     catch( const Exception& )
    2542             :     {
    2543             :         DBG_UNHANDLED_EXCEPTION();
    2544             :     }
    2545          53 : }
    2546             : 
    2547          17 : void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock )
    2548             : {
    2549          17 :         Reference< XValueBinding > xExternalBinding( m_xExternalBinding );
    2550          34 :         Type aValueExchangeType( getExternalValueType() );
    2551          17 :         _rInstanceLock.release();
    2552             :         // UNSAFE >
    2553          34 :         Any aExternalValue;
    2554             :         try
    2555             :         {
    2556          17 :             aExternalValue = xExternalBinding->getValue( aValueExchangeType );
    2557             :         }
    2558             : 
    2559           0 :         catch( const Exception& )
    2560             :         {
    2561             :             DBG_UNHANDLED_EXCEPTION();
    2562             :         }
    2563             :         // < UNSAFE
    2564          17 :         _rInstanceLock.acquire();
    2565          34 :         setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding );
    2566          17 : }
    2567             : 
    2568           0 : void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock )
    2569             : {
    2570             :     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
    2571             :         "OBoundControlModel::transferControlValueToExternal: precondition not met!" );
    2572           0 :     if ( m_xExternalBinding.is() )
    2573             :     {
    2574           0 :         Any aExternalValue( translateControlValueToExternalValue() );
    2575           0 :         m_bTransferingValue = sal_True;
    2576           0 :         _rInstanceLock.release();
    2577             :          // UNSAFE >
    2578             :         try
    2579             :         {
    2580           0 :             m_xExternalBinding->setValue( aExternalValue );
    2581             :         }
    2582             : 
    2583           0 :         catch( const Exception& )
    2584             :         {
    2585             :             DBG_UNHANDLED_EXCEPTION();
    2586             :         }
    2587             : 
    2588             :         // < UNSAFE
    2589           0 :         _rInstanceLock.acquire();
    2590           0 :         m_bTransferingValue = sal_False;
    2591             :     }
    2592           0 : }
    2593             : 
    2594          12 : Sequence< Type > OBoundControlModel::getSupportedBindingTypes()
    2595             : {
    2596          12 :     return Sequence< Type >( &m_aValuePropertyType, 1 );
    2597             : }
    2598             : 
    2599          44 : void OBoundControlModel::calculateExternalValueType()
    2600             : {
    2601          44 :     m_aExternalValueType = Type();
    2602          44 :     if ( !m_xExternalBinding.is() )
    2603          71 :         return;
    2604          17 :     Sequence< Type > aTypeCandidates( getSupportedBindingTypes() );
    2605          34 :     for (   const Type* pTypeCandidate = aTypeCandidates.getConstArray();
    2606          17 :             pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
    2607             :             ++pTypeCandidate
    2608             :         )
    2609             :     {
    2610          17 :         if ( m_xExternalBinding->supportsType( *pTypeCandidate ) )
    2611             :         {
    2612          17 :             m_aExternalValueType = *pTypeCandidate;
    2613          17 :             break;
    2614             :         }
    2615          17 :     }
    2616             : }
    2617             : 
    2618           6 : Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
    2619             : {
    2620             :     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
    2621             :         "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" );
    2622           6 :     Any aControlValue( _rExternalValue );
    2623             :     // if the external value is VOID, and our value property is not allowed to be VOID,
    2624             :     // then default-construct a value
    2625           6 :     if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid )
    2626           0 :         aControlValue.setValue( NULL, m_aValuePropertyType );
    2627             :     // out of here
    2628           6 :     return aControlValue;
    2629             : }
    2630             : 
    2631           0 : Any OBoundControlModel::translateControlValueToExternalValue( ) const
    2632             : {
    2633           0 :     return getControlValue( );
    2634             : }
    2635             : 
    2636          45 : Any OBoundControlModel::translateControlValueToValidatableValue( ) const
    2637             : {
    2638             :     OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" );
    2639          45 :     if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() )
    2640           0 :         return translateControlValueToExternalValue();
    2641          45 :     return getControlValue();
    2642             : }
    2643             : 
    2644         262 : Any OBoundControlModel::getControlValue( ) const
    2645             : {
    2646             :     OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
    2647             :         "OBoundControlModel::getControlValue: invalid aggregate !" );
    2648             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty() || ( m_nValuePropertyAggregateHandle != -1 ),
    2649             :         "OBoundControlModel::getControlValue: please override if you have own value property handling!" );
    2650             :     // determine the current control value
    2651         262 :     Any aControlValue;
    2652         262 :     if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
    2653             :     {
    2654         262 :         aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle );
    2655             :     }
    2656             : 
    2657           0 :     else if ( !m_sValuePropertyName.isEmpty() && m_xAggregateSet.is() )
    2658             :     {
    2659           0 :         aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName );
    2660             :     }
    2661         262 :     return aControlValue;
    2662             : }
    2663             : 
    2664          18 : void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
    2665             : {
    2666             :     OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
    2667             :     OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
    2668          18 :     m_xValidator = _rxValidator;
    2669             : 
    2670             :     // add as value listener so we get notified when the value changes
    2671          18 :     if ( m_xValidator.is() )
    2672             :     {
    2673             :         try
    2674             :         {
    2675          18 :             m_xValidator->addValidityConstraintListener( this );
    2676             :         }
    2677             : 
    2678           0 :         catch( const RuntimeException& )
    2679             :         {
    2680             :         }
    2681             :     }
    2682          18 :     onConnectedValidator( );
    2683          18 : }
    2684             : 
    2685          18 : void OBoundControlModel::disconnectValidator( )
    2686             : {
    2687             :     OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
    2688             : 
    2689             :     // add as value listener so we get notified when the value changes
    2690          18 :     if ( m_xValidator.is() )
    2691             :     {
    2692             :         try
    2693             :         {
    2694          18 :             m_xValidator->removeValidityConstraintListener( this );
    2695             :         }
    2696             : 
    2697           0 :         catch( const RuntimeException& )
    2698             :         {
    2699             :         }
    2700             :     }
    2701             : 
    2702          18 :     m_xValidator.clear();
    2703             : 
    2704          18 :     onDisconnectedValidator( );
    2705          18 : }
    2706             : 
    2707          18 : void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException, std::exception)
    2708             : {
    2709          18 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    2710             :     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
    2711             :     // the interface for this method should not have been exposed if we do not
    2712             :     // support validation
    2713             : 
    2714             :     // early out if the validator does not change
    2715          18 :     if ( _rxValidator == m_xValidator )
    2716          18 :         return;
    2717             : 
    2718          18 :     if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
    2719             :         throw VetoException(
    2720             :             FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ),
    2721             :             *this
    2722           0 :         );
    2723             : 
    2724             :     // disconnect from the old validator
    2725          18 :     if ( hasValidator() )
    2726           0 :         disconnectValidator( );
    2727             : 
    2728             :     // connect to the new validator
    2729          18 :     if ( _rxValidator.is() )
    2730          18 :         connectValidator( _rxValidator );
    2731             : }
    2732             : 
    2733          40 : Reference< XValidator > SAL_CALL OBoundControlModel::getValidator(  ) throw (RuntimeException, std::exception)
    2734             : {
    2735          40 :     ::osl::MutexGuard aGuard( m_aMutex );
    2736             :     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
    2737             :         // the interface for this method should not have been exposed if we do not
    2738             :         // support validation
    2739             : 
    2740          40 :     return m_xValidator;
    2741             : }
    2742             : 
    2743           9 : void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
    2744             : {
    2745           9 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    2746             :     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
    2747             :         // the interface for this method should not have been exposed if we do not
    2748             :         // support validation
    2749             : 
    2750           9 :     recheckValidity( false );
    2751           9 : }
    2752             : 
    2753          36 : sal_Bool SAL_CALL OBoundControlModel::isValid(  ) throw (RuntimeException, std::exception)
    2754             : {
    2755          36 :     return m_bIsCurrentValueValid;
    2756             : }
    2757             : 
    2758           8 : ::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const
    2759             : {
    2760           8 :     if ( hasValidator() )
    2761           0 :         return translateControlValueToValidatableValue();
    2762           8 :     return getControlValue();
    2763             : }
    2764             : 
    2765           9 : Any SAL_CALL OBoundControlModel::getCurrentValue(  ) throw (RuntimeException, std::exception)
    2766             : {
    2767           9 :     ::osl::MutexGuard aGuard( m_aMutex );
    2768           9 :     return getCurrentFormComponentValue();
    2769             : }
    2770             : 
    2771          17 : void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException, std::exception)
    2772             : {
    2773          17 :     if ( Listener.is() )
    2774          17 :         m_aFormComponentListeners.addInterface( Listener );
    2775          17 : }
    2776             : 
    2777          17 : void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException, std::exception)
    2778             : {
    2779          17 :     if ( Listener.is() )
    2780          17 :         m_aFormComponentListeners.removeInterface( Listener );
    2781          17 : }
    2782             : 
    2783         344 : void OBoundControlModel::recheckValidity( bool _bForceNotification )
    2784             : {
    2785             :     try
    2786             :     {
    2787         344 :         sal_Bool bIsCurrentlyValid = sal_True;
    2788         344 :         if ( hasValidator() )
    2789         100 :             bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
    2790             : 
    2791         344 :         if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
    2792             :         {
    2793         317 :             m_bIsCurrentValueValid = bIsCurrentlyValid;
    2794             : 
    2795             :             // release our mutex for the notifications
    2796         317 :             MutexRelease aRelease( m_aMutex );
    2797         317 :             m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) );
    2798             :         }
    2799             : 
    2800             :     }
    2801             : 
    2802           0 :     catch( const Exception& )
    2803             :     {
    2804             :         SAL_WARN("forms.component",  "OBoundControlModel::recheckValidity: caught an exception!");
    2805             :         DBG_UNHANDLED_EXCEPTION();
    2806             :     }
    2807         344 : }
    2808             : 
    2809         282 : void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
    2810             : {
    2811         282 :     BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel )
    2812         282 :         DECL_PROP1      ( CONTROLSOURCE,           OUString,     BOUND );
    2813         282 :         DECL_IFACE_PROP3( BOUNDFIELD,               XPropertySet,       BOUND, READONLY, TRANSIENT );
    2814         282 :         DECL_IFACE_PROP2( CONTROLLABEL,             XPropertySet,       BOUND, MAYBEVOID );
    2815         282 :         DECL_PROP2      ( CONTROLSOURCEPROPERTY,    OUString,    READONLY, TRANSIENT );
    2816         282 :         DECL_BOOL_PROP1 ( INPUT_REQUIRED,                               BOUND );
    2817             :     END_DESCRIBE_PROPERTIES()
    2818         282 : }
    2819             : }
    2820             : 
    2821             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10