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

Generated by: LCOV version 1.10