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