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