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